feat(cli): add doberman enforcement <enforce|monitor|off> command (UX-A)#97
Open
fu351 wants to merge 1 commit into
Open
feat(cli): add doberman enforcement <enforce|monitor|off> command (UX-A)#97fu351 wants to merge 1 commit into
doberman enforcement <enforce|monitor|off> command (UX-A)#97fu351 wants to merge 1 commit into
Conversation
…UX-A) Wire the gated setter apply_enforcement_change() to a CLI verb so a user finally has an in-product way to turn Doberman's enforcement dial down. Before this, #88 wired only the decision-path *consumption* of the dial — no setter existed, so a frustrated user had no in-band knob to reach for. Turning the dial DOWN is a weaken: it is confirmed — plus a TOTP code when 2FA is enrolled, and confirm-only otherwise so the safety valve is never out of reach — and recorded in the append-only policy-change ledger. Re-arming (-> enforce) is a strengthen and applies automatically, ungated. The command persists the exact fields the ledger just recorded, so the read-side effective_enforcement clamp confirms a soften; a hand-edited `enforcement: off` with no approved ledger row is still clamped back to enforce (fail closed). Mirrors the existing `mode`/`prefs` command shape. With no argument, prints the current on-disk state. Adds tests/unit/test_cli_enforcement.py covering show, the confirm-gated soften round trip, denial-leaves-state-unchanged (fail closed), unknown-state rejection, re-arm-is-never-gated, and the hand-edit tamper clamp. Unenrolled 2FA takes the confirm-only path.
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.
Slice
doberman enforcement <enforce|monitor|off>CLI commanddoberman_core_plan.md); vault TODO docs: sync operating manual to three-plan structure; add core plan #2 (2026-07-09 softlock audit, gap A)What this PR does
Adds the setter for the enforcement dial that #88 wired the consumption of. Before this there was no in-product way to turn Doberman's enforcement down — the single "turn it down" knob a frustrated user reaches for simply didn't exist as a command.
It routes through the existing gated chokepoint
apply_enforcement_change()(policy/drift.py) — semantics unchanged:enforce→monitor/off) is confirmed — plus a TOTP code when 2FA is enrolled, and confirm-only otherwise so the safety valve is never out of reach — and recorded in the append-only policy-change ledger.→ enforce) is a strengthen and applies automatically, ungated.effective_enforcementclamp confirms a soften; a hand-editedenforcement: offwith no approved ledger row is still clamped back toenforce(fail closed).mode/prefscommand shape.Also fixes two import bugs in the pre-existing in-progress work:
load_enforcementwas used but not imported (wouldNameErrorat runtime);resolve_enforcement_syncwas imported intomain.pybut unused (ruffF401).Tests added (run in CI)
tests/unit/test_cli_enforcement.py(8 tests): show defaults toenforce; confirm-gated soften round-trips and becomes effective (resolve_enforcement_sync);monitorround-trips; a denied soften leaves state unchanged (fail closed); an unknown state is rejected before it reaches the gate or the policy file; no-op is a friendly no-op; re-arm is never gated (a prompter that raises on any prompt proves it); and a hand-editedoffwith no ledger row is clamped back toenforce(the tamper contrast that is the whole reason the command exists). Unenrolled 2FA exercises the confirm-only safety-valve path.Local:
ruff check✓,ruff format --check✓,lint-imports✓ (2/2 contracts kept), the 8 enforcement tests ✓ (full suite running for coverage).Security checklist
enforce; an unknown argument exits2before the gate.Public-release safety (doberman-core only)
Edge cases covered / Deviations from plan / Risks introduced