feat(trust): gate untrusted-directory exec config + deepcode trust#120
Merged
Conversation
Implements the Trust gating half of §3.15.10. In a directory the user hasn't trusted, the project/local settings layers can't run arbitrary code on launch. core (config/trust-gate.ts): - gateUntrustedSettings(loaded, status) — for untrusted/plan-only dirs, resets the exec-bearing fields (hooks, mcpServers, apiKeyHelper, statusLine) to the user-global layer's value (always trusted), stripping anything the project /local layers tried to set. Returns the effective settings + the gated list. Pure + 7 tests. cli: - repl.ts + headless.ts gate settings right after loadSettings (before apiKeyHelper resolution / MCP connect / hook wiring), warning which fields were ignored. Headless is the key case: `deepcode -p` on an untrusted PR checkout no longer runs that repo's hooks/MCP. - `deepcode trust [--plan-only | --remove | --list]` to manage trust; wired into cli.ts dispatch + --help. (+5 tests) Also fixes a latent bug this surfaced: TrustStore.load() returned a shallow copy of a module-level EMPTY whose `dirs` was shared, so trust() mutated it and later load()s of a not-yet-created store leaked entries. Now returns a fresh empty state. (+1 regression test) CLI suite 78 green; core trust-gate 7 green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.
Summary
Implements the gating half of the Trust dialog (
docs/DEVELOPMENT_PLAN.md§3.15.10). In a directory the user hasn't trusted, a project's.deepcode/settings.jsoncan no longer execute arbitrary code on launch.Behavior
hooks,mcpServers,apiKeyHelper,statusLine— are reset to the user-global layer's value (~/.deepcode/settings.json, always trusted). Anything the project/local layers tried to set for those is ignored, with a one-line warning listing what was gated. Non-exec fields (model, effort, …) still merge normally.deepcode trustmarks the current directory trusted (full);--plan-only,--remove,--listmanage it. Once trusted, full behavior returns.deepcode -p "…"run against an untrusted checkout (e.g. a PR branch) no longer runs that repo's hooks/MCP servers. Warning goes to stderr; stdout stays clean.Changes
config/trust-gate.ts:gateUntrustedSettings(loaded, status)(pure, uses the existingLoadedSettings.layersprovenance). +TRUST_GATED_FIELDS.repl.ts+headless.tsgate right afterloadSettings, beforeapiKeyHelperresolution / MCP connect / hook wiring. Newtrust-cmd.ts(deepcode trust …) wired intocli.ts+--help.Latent bug fixed (surfaced by the new cross-home tests)
TrustStore.load()returned{ ...EMPTY }— a shallow copy of a module-levelEMPTYwhosedirsobject was shared.trust()then mutatedstate.dirs, permanently pollutingEMPTY.dirs, so every laterload()of a not-yet-created store file leaked those entries. Now returns a fresh{ dirs: {} }via a factory. Added a regression test.Tests
trust-gate.test.ts(+7): trusted passthrough, untrusted strips each field + lists them, user-layer value kept, local-layer gating, nothing-to-gate, plan-only parity, no input mutation.trust-cmd.test.ts(+5) +trust.test.tsregression (+1). CLI suite 78 green.hooks+mcpServersprints the gate warning and drops them.🤖 Generated with Claude Code