Repository navigation
hooks: fix OpenCode guard-path baking and Windows fallback, add plugin tests - #300
Merged
codeyevsky merged 1 commit intoNov 3, 2026
Merged
Conversation
…n tests bakeGuardBinPath only doubled backslashes before splicing the guard path into a single-quoted JS literal, so an install path with an apostrophe (or a line break) produced an opencode-plugin.mjs that OpenCode could not parse, which silently turned enforcement off. It now escapes quotes and line breaks too (solongate#207). The plugin's fallback guard path had no .exe suffix, so on Windows the fallback spawn always hit ENOENT and the plugin failed open (solongate#191). opencode-plugin.mjs had no tests (solongate#192). Add a node:test suite that runs the plugin against a fake guard script, covering path resolution, deny, rewrite, redaction merge, token reporting and the fail-open paths, and run it from sg-unit-check.sh and CI. Fixes solongate#207, fixes solongate#191, fixes solongate#192. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Jai Dhingra <297267163+j-ai-cmd@users.noreply.github.com>
codeyevsky
approved these changes
Nov 3, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #207, fixes #191, fixes #192.
All three issues sit in the path from install to
opencode-plugin.mjsspawning the guard, so they go in one PR. Happy to split them if you'd rather review them separately.Cause
bakeGuardBinPath(packages/core/install/source.go) splices the guard path intoconst GUARD_BAKED = '...'and only doubled backslashes. An install path with an apostrophe (/Users/o'brien/...) ended the string literal early. OpenCode then could not parse the plugin, and enforcement for OpenCode stopped with no error. A line break in the path broke it the same way.~/.solongate/bin/solongate-guard) had no.exe. On Windows the installed binary issolongate-guard.exe(goBinaryNames), so the fallback spawn always hit ENOENT and the plugin failed open on every call.Fix
bakeGuardBinPathnow uses onestrings.NewReplacerthat escapes\,',\nand\r. A single pass means a quote after a backslash still comes out right..exewhenprocess.platform === 'win32', which matchesgoBinaryNames().packages/hooks/opencode-plugin.test.mjs(node:test, no dependencies). It doesn't mockchild_process. Each test points the plugin at a small shell script that stands in for the guard: the script records its argv and stdin, then replies with a canned JSON body and exit code. So the tests run the real spawn/stdin/stdout path. 19 cases cover:.exefallback (simulated by settingprocess.platformbefore the module loads)tool.execute.before: payload and argv sent, exit 2 blocks with the guard's reason or the default reason,updatedInputrewrite applies only onallow, non-JSON output fails open, missing binary fails opentool.execute.after: audit payload, and each redaction merge branch (string,stdout,content, metadata merge, nothing redacted)event: token report for a completed assistant message, and no report for user messages, unfinished messages or part updatestest/folder, because.gitignoreignores**/test/.scripts/sg-unit-check.shruns the suite, andci.yamlgets a smallhooksjob that runs it with the runner's preinstalled Node. Nosetup-nodeaction and no new dependencies. CONTRIBUTING mentions the suite.How I tested
node --test packages/hooks/opencode-plugin.test.mjs: 19/19 pass on Node 24, macOS. The Windows-fallback test fails if the.mjsfix is reverted.go test ./install/inpackages/core, including 3 newbakeGuardBinPathcases: single quote, quote after a backslash, line breaks.go vetis clean, and the changed files pass the CI-style gofmt check.opencode-plugin.mjswithC:\Users\o'brien\nx\solongate-guard.exe, then rannode --checkandimport()on the output. Both succeed. Before the fix the output was a syntax error.go test.guard,policy,shared,tui,appandcryptopass. On macOS,sandbox,coreandclishow the same file-lock/protect failures on an untouchedorigin/maincheckout, so they come from the environment and not this change.🤖 Generated with Claude Code