From dc7bf8ab040bc6dceb3b26696912bf265d7e2bbc Mon Sep 17 00:00:00 2001 From: ZDDC Date: Thu, 7 May 2026 11:10:31 -0500 Subject: [PATCH] docs(zddc): tighten inherit/strict-mode docstrings + AllowedAtLevel deprecation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Address two follow-ups from the security review of feat/zddc-inherit-directive: 1. file.go's Inherit docstring previously claimed "the internal decider treats it as inherit:true and emits a warning at evaluation time" — the decider does the first part but the warning was never wired up. Strike the over-promise; point operators at the cascade tracer (`/.profile/effective-policy`) which surfaces both `cascade_mode` and `chain.visible_start` so a fenced configuration that's being ignored under strict mode is visible. 2. AllowedAtLevel hardcodes ModeDelegated. Safe today (1-level synthetic chain, no ancestors) but a footgun if anyone migrates the shim to a real PolicyChain later. Add a `// Deprecated:` marker pointing at GrantedVerbsAtLevel for fence-aware paths. Co-Authored-By: Claude Opus 4.7 (1M context) --- zddc/internal/zddc/acl.go | 12 ++++++++++-- zddc/internal/zddc/file.go | 9 ++++++--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/zddc/internal/zddc/acl.go b/zddc/internal/zddc/acl.go index 2b73156..7341dad 100644 --- a/zddc/internal/zddc/acl.go +++ b/zddc/internal/zddc/acl.go @@ -3,8 +3,16 @@ package zddc import "strings" // AllowedAtLevel is a thin shim over GrantedVerbsAtLevel preserved for -// callers that only need the legacy boolean read decision. New code -// should call GrantedVerbsAtLevel directly. +// callers that only need the legacy boolean read decision on a single +// ZddcFile (no cascade chain). +// +// Hardcodes ModeDelegated — safe because the synthetic chain has only +// one level and no ancestors to fence — but callers that operate on a +// real PolicyChain must call GrantedVerbsAtLevel directly with the +// active mode. +// +// Deprecated: prefer GrantedVerbsAtLevel for any code path that may +// later need fence-aware or strict-mode evaluation. func AllowedAtLevel(level ZddcFile, email string) (decision bool, matched bool) { chain := PolicyChain{Levels: []ZddcFile{level}, HasAnyFile: true} v, m := GrantedVerbsAtLevel(chain, 0, email, ModeDelegated) diff --git a/zddc/internal/zddc/file.go b/zddc/internal/zddc/file.go index 1b9380a..bb9cf2b 100644 --- a/zddc/internal/zddc/file.go +++ b/zddc/internal/zddc/file.go @@ -38,9 +38,12 @@ import ( // // In strict cascade mode (federal / NIST AC-6), inherit:false is // REFUSED — a leaf-level directive cannot widen access an ancestor -// refused. The internal decider treats it as inherit:true and emits a -// warning at evaluation time. Operators running the federal Rego -// preset get the same behaviour from policy enforcement. +// refused. The internal decider silently treats it as inherit:true; +// the cascade tracer (/.profile/effective-policy) reports both +// `cascade_mode` and `chain.visible_start` so an operator can see +// that a configured fence is being ignored under the active mode. +// Operators running the federal Rego preset get the same behaviour +// from policy enforcement. // // Inherit is per-level and not itself cascading: an ancestor's // `inherit: false` does not transitively block descendants from