Skip to content

feat(policy): ledger-verified effective_enforcement clamp against on-disk tampering#86

Merged
fu351 merged 1 commit into
mainfrom
feat/policy/enforcement-tamper-check
Jul 6, 2026
Merged

feat(policy): ledger-verified effective_enforcement clamp against on-disk tampering#86
fu351 merged 1 commit into
mainfrom
feat/policy/enforcement-tamper-check

Conversation

@fu351

@fu351 fu351 commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Slice

What this PR does

Adds drift.effective_enforcement() — the single sanctioned way to turn the on-disk enforcement fields into the state to act on, closing the gap named in #81: once the engine honors PolicyDoc.enforcement, hand-editing .doberman/policies.yaml to enforcement: off would silently bypass the whole apply_enforcement_change gate.

  • A soften (monitor/off) is honored only when the append-only ledger holds a matching APPROVED change: state, expiry (both directions — a hand-deleted expires_at that would make a temporary soften permanent is also caught), and any non-default revert target.
  • Anything else — mismatch, missing ledger, garbage value, DB error — fails closed to enforce with a redacted observer anomaly + log warning (no ledger write: the ledger records gate-approved changes only).
  • Raise-only: never returns weaker than the on-disk claim; an expired soften reverts, with a weaker-than-monitor revert clamped up to enforce.
  • The common enforce path returns with zero I/O (runs on every mediated action).
  • PolicyDoc.enforcement docstring now directs consumers to this helper; README roadmap line updated.

Closes #81

Tests added (run in CI)

  • tests/unit/test_enforcement_tamper_check.py (13 tests): approved soften honored · hand-edit without ledger row clamped · denied-attempt rows don't legitimize · state mismatch clamped · garbage value clamped+anomaly · enforce resolves with zero I/O (nonexistent repo root) · expired soften reverts to verified target · off revert clamped up on expiry · future expiry keeps the soften · hand-deleted expiry after a temporary soften clamped · gate-approved expiry clear honored · DB explosion fails closed · exploding observer can't break the clamp

Security checklist

  • Fails closed on error / uncertainty
  • No secret, full file, or unredacted prompt logged or committed
  • Any guardrail/learning change is raise-only (no silent loosening)
  • Every BLOCK/AUTH carries reason codes + a human explanation (N/A — no decision-path change; the anomaly event carries a human-readable reason)

Edge cases covered / Deviations from plan / Risks introduced

…disk tampering

Once the engine honors PolicyDoc.enforcement, hand-editing
.doberman/policies.yaml to 'enforcement: off' would silently bypass the
apply_enforcement_change gate. effective_enforcement() is the read-side
clamp: a soften (monitor/off) is honored only when the append-only ledger
holds a matching APPROVED change (state, expiry both ways, non-default
revert); anything else — including a hand-deleted expiry that would make a
temporary soften permanent — fails closed to 'enforce' with a redacted
anomaly. Raise-only; zero I/O on the common 'enforce' path.

Closes #81
@fu351 fu351 merged commit 4dc8ff6 into main Jul 6, 2026
6 checks passed
@fu351 fu351 deleted the feat/policy/enforcement-tamper-check branch July 6, 2026 22:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Blocking prerequisite for runtime enforcement consumption: policies.yaml tamper detection for the enforcement fields

1 participant