Correct v0.8 §9.7.3: the binding correspondence as first cut could never pass
secrets-engine found, and access-engine and approval-engine reported independently within hours, that GH-DEC-2026-008 as written was unimplementable. Where a claim travels inside the hashed request — the dual-control pattern it was written for — embedding the claim changes the digest of the request carrying it, so a digest recorded at issue can never equal the final one. It is a hash cycle. A fail-closed consumer obeying the rule would have denied destroy permanently. The comparison is now against the digest the PDP publishes for the request with the approval evidence excluded (flex-auth's binding.approval_binding_digest, verified present in its schema and tests). The exclusion rule is the PDP's to publish and a consumer MUST NOT guess it: a digest computed under an assumed rule fails open toward accepting a claim bound to a different request — the same failure direction as an invented vocabulary mapping, by another road. §6.4 obligation 5 gains the general property access-engine flagged as a near miss rather than a request: an evidence-bearing input may be excluded from a correspondence digest but never from the replay identity. Two requests differing only in which approval was presented decide differently, so collapsing them lets an allow obtained with a valid claim be replayed against a request carrying none — a fail-open hole reached by a refactor that looks like simplification. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WtJBr77gMFLrN93iEevqQJ Assistant: claude-code Assistant-Model: opus Assistant-Process: 425128@bnt-lap001 Assistant-Session: f5944d8b-dac4-4e1a-87eb-8b3d8f314a63
This commit is contained in:
parent
66eeabad38
commit
31a49a43eb
1 changed files with 61 additions and 15 deletions
|
|
@ -548,6 +548,21 @@ Four obligations, and they are normative:
|
||||||
way that still produces a confident answer, it fails open, and it would be a
|
way that still produces a confident answer, it fails open, and it would be a
|
||||||
third authority on what a request *is*.
|
third authority on what a request *is*.
|
||||||
|
|
||||||
|
**An evidence-bearing input may be excluded from a correspondence digest, but
|
||||||
|
never from the replay identity.** These are two digests over one request and
|
||||||
|
they are deliberately different. A correspondence digest answers *"is this the
|
||||||
|
action the approval was granted for"* and must exclude the evidence, or it
|
||||||
|
cannot be computed before the evidence exists. A replay identity answers *"is
|
||||||
|
this the same request"* and MUST cover every input the decision depends on,
|
||||||
|
evidence included — two requests differing only in which approval was
|
||||||
|
presented decide differently, one allowing and one denying, so collapsing them
|
||||||
|
would let an allow obtained with a valid claim be replayed against a request
|
||||||
|
carrying none. That is a fail-open hole reached by a refactor that looks like
|
||||||
|
simplification, which is why the property is stated rather than left to be
|
||||||
|
rediscovered. The shape recurs wherever evidence travels inside a hashed
|
||||||
|
request. Raised by `access-engine`, which nearly took the unsafe simplification
|
||||||
|
and reported the near miss.
|
||||||
|
|
||||||
**A consumer of a summary predicate trusts the issuer's evaluation of
|
**A consumer of a summary predicate trusts the issuer's evaluation of
|
||||||
everything folded into it.** Where the split reduces what a PEP verifies
|
everything folded into it.** Where the split reduces what a PEP verifies
|
||||||
independently — as `valid_now` does for an approver threshold the claim
|
independently — as `valid_now` does for an approver threshold the claim
|
||||||
|
|
@ -956,15 +971,36 @@ deciding wrongly. The model has had no temporal law, and the approval race in
|
||||||
action is spent. Reversibility would reopen replay, which is the failure the
|
action is spent. Reversibility would reopen replay, which is the failure the
|
||||||
mutation exists to close.
|
mutation exists to close.
|
||||||
|
|
||||||
**The correspondence is the PDP digest.** A consumer on this path MUST verify
|
**The correspondence is a digest, and it is the PDP's to define.** A consumer
|
||||||
that `claim.binding.pdp_digest` equals the decision's
|
on this path MUST verify that the approval's recorded PDP digest equals the
|
||||||
`NewDecisionBinding.request_digest`, and MUST NOT use a claim carrying none.
|
digest the PDP publishes **for the request with the approval evidence
|
||||||
Recomputing the approval engine's native binding from a `CheckRequest` is not
|
excluded** — `binding.approval_binding_digest` in `access-engine` — and MUST
|
||||||
a permitted fallback: it requires translating between two vocabularies, no
|
NOT use a claim that carries no such digest. Recomputing the approval engine's
|
||||||
mapping is published, and a wrong translation fails open by silently
|
native binding from a `CheckRequest` is not a permitted fallback: it requires
|
||||||
accepting a claim approved for something else. Without this, `valid_now: true`
|
translating between two vocabularies, no mapping is published, and a wrong
|
||||||
plus an ALLOW establishes *approved* and *permitted* but never *approved for
|
translation fails open by silently accepting a claim approved for something
|
||||||
this request*. Settled in `GH-DEC-2026-008`.
|
else. Without this, `valid_now: true` plus an ALLOW establishes *approved* and
|
||||||
|
*permitted* but never *approved for this request*.
|
||||||
|
|
||||||
|
**The comparison cannot be against the full request digest.** Where a claim
|
||||||
|
travels inside the hashed request — the dual-control pattern — embedding it
|
||||||
|
changes the digest of the request carrying it, so a digest recorded at issue
|
||||||
|
can never equal the final one. That is a hash cycle and the resolution is
|
||||||
|
forced, not chosen: the recorded digest is necessarily of the underlying
|
||||||
|
action before any claim was embedded. A standard that mandates the naive
|
||||||
|
comparison mandates a check that can never pass, and a fail-closed consumer
|
||||||
|
then denies the action permanently.
|
||||||
|
|
||||||
|
**The exclusion rule is the PDP's to publish, and until it does the path is
|
||||||
|
incomplete rather than complete.** A consumer MUST NOT guess which fields are
|
||||||
|
excluded: a digest computed under an assumed rule produces a confident wrong
|
||||||
|
answer, and comparing two digests derived under different rules fails open
|
||||||
|
toward accepting a claim bound to a different request — the same failure
|
||||||
|
direction as an invented vocabulary mapping, reached by another road.
|
||||||
|
|
||||||
|
Settled in `GH-DEC-2026-008`, amended on an implementability defect found by
|
||||||
|
`secrets-engine` and reported independently by `access-engine` and
|
||||||
|
`approval-engine` within hours of the ruling.
|
||||||
|
|
||||||
Settled in `GH-DEC-2026-003`; the protocol is
|
Settled in `GH-DEC-2026-003`; the protocol is
|
||||||
`gate-house/docs/contracts/approval-consumption.md`.
|
`gate-house/docs/contracts/approval-consumption.md`.
|
||||||
|
|
@ -1300,12 +1336,22 @@ v0.7 → v0.8:
|
||||||
v0.7's stated order left the CAS able to prevent only the second record, never
|
v0.7's stated order left the CAS able to prevent only the second record, never
|
||||||
the second side effect. Protocol correction, not a retraction of the forensic
|
the second side effect. Protocol correction, not a retraction of the forensic
|
||||||
claim (`GH-DEC-2026-003`).
|
claim (`GH-DEC-2026-003`).
|
||||||
2. **§9.7.3 gains the binding correspondence** — `claim.binding.pdp_digest` MUST
|
2. **§9.7.3 gains the binding correspondence** — the approval's recorded PDP
|
||||||
equal the decision's request digest, and a claim without one is unusable on
|
digest MUST equal the digest the PDP publishes for the request with the
|
||||||
that path. No cross-engine vocabulary mapping is published: a translation can
|
approval evidence excluded, and a claim without one is unusable on that path.
|
||||||
be confidently wrong and fails open, where a digest is identity
|
No cross-engine vocabulary mapping is published: a translation can be
|
||||||
(`GH-DEC-2026-008`, raised by `access-engine`, which declined to close it
|
confidently wrong and fails open, where a digest is identity. The comparison
|
||||||
locally).
|
is against an exclusion-scoped digest because a claim travelling inside a
|
||||||
|
hashed request cannot name the digest of the request containing it — a hash
|
||||||
|
cycle, found by `secrets-engine` and reported independently by two engines
|
||||||
|
within hours of the ruling, which as first written mandated a check that could
|
||||||
|
never pass (`GH-DEC-2026-008`, raised by `access-engine`, which declined to
|
||||||
|
close it locally).
|
||||||
|
2b. **§6.4 obligation 5 gains the replay-identity property** — an evidence-bearing
|
||||||
|
input may be excluded from a correspondence digest but never from the replay
|
||||||
|
identity, because two requests differing only in which approval was presented
|
||||||
|
decide differently. Flagged by `access-engine` as a near miss rather than a
|
||||||
|
request.
|
||||||
3. **§6.4 obligation 5 added** — validation by owning layer, and correspondence
|
3. **§6.4 obligation 5 added** — validation by owning layer, and correspondence
|
||||||
by identity rather than translation. A PIP MUST NOT republish the PDP's
|
by identity rather than translation. A PIP MUST NOT republish the PDP's
|
||||||
decision. Carries the consequence that a consumer of a summary predicate
|
decision. Carries the consequence that a consumer of a summary predicate
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue