feat: enforce the operation gate with allowed-tools, a PreToolUse hook, and a gated wrapper - #4
Merged
Merged
Conversation
Every SKILL.md frontmatter and module manifest now declares an explicit allowed-tools set: control-plane modules are limited to reads and their own validators, provider packs to reads plus their provider CLI, and executors receive the full toolset that the PreToolUse gate constrains. Missing, duplicated, malformed, or mismatched declarations fail validation instead of warning. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nding tools/devops_exec.py executes exactly one approved command: it computes the canonical digest of the actual argv, requires equality with the approved change.plan_digest, re-runs the registered operation gate immediately before launch, executes without a shell, and appends a secret-redacted record to a local execution ledger. Digest drift, gate refusal, malformed requests, and internal errors block with a non-zero exit code. The portfolio demo now executes its simulated rollout through the wrapper and proves the drift path is blocked. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
tools/hooks/pretooluse_gate.py denies every shell command that is not provably read-only, a resolved-path-verified platform script, or a devops_exec wrapper call whose operation request binds the approved plan digest to the canonical digest of the exact wrapped command, has an open execution window, and receives a fresh operation-gate PASS. Obfuscation via shell wrappers, eval, base64, substitution, variable expansion, redirection, multi-line input, and unknown executables is denied fail-closed. docs/hooks-setup.md documents installation and the decision rules. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The README safety-properties section now states per property whether it is enforced by a blocking mechanism (gate, wrapper digest binding, PreToolUse hook, allowed-tools validation, release verification) or advisory discipline that depends on the agent. CHANGELOG records the enforcement layer added for the next release. Co-Authored-By: Claude Fable 5 <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
Phase 1 of the hardening roadmap: turn the fail-closed policy layer from a convention into a mechanism.
allowed-toolsdeclaration in every module (SKILL.mdfrontmatter +module.yaml), enforced by the manifest schema andvalidate_platform.py; control-plane and provider modules receive no unrestricted shell.tools/devops_exec.py: executes exactly one approved command, requires the canonical argv digest to equal the approvedchange.plan_digest, re-runs the operation gate immediately before launch, and appends a secret-redacted record to a local execution ledger. Drift blocks with a non-zero exit.tools/hooks/pretooluse_gate.py(+docs/hooks-setup.md): a fail-closed PreToolUse hook that denies mutating, obfuscated, or unclassifiable shell commands without a fresh gate PASS bound to the exact command digest.Testing
python devops-platform-contracts/scripts/validate_platform.py→ OK, 21/21 compatible installed skillspython -m unittest discover -s tests→ 50 tests OK (was 33)python examples/portfolio-demo/run_demo.py→ verified, wrapper drift blockedpython -m unittest discover -s examples/portfolio-demo/tests -p "test_*.py"→ OK🤖 Generated with Claude Code