diff --git a/docs/approval-claim.md b/docs/approval-claim.md index 7bf83bd..8cb0323 100644 --- a/docs/approval-claim.md +++ b/docs/approval-claim.md @@ -148,6 +148,27 @@ produces a confident wrong answer, and comparing two digests derived under different rules fails open in the direction of accepting a claim bound to a different request. +**`pdp_digest` does not authenticate the decision.** This is the limit most +easily mistaken for coverage, so it is stated plainly: matching +`claim.binding.pdp_digest` against the PDP's published digest proves the two +artifacts describe *one request*. It proves nothing about whether the decision +is genuine. **An approval whose `pdp_digest` matches a forged decision matches +perfectly** — every input to the comparison is either sent by the caller or +published by the PDP, so a responder that knows a package id and version can +return a well-formed allow that passes every check a consumer makes. + +Fail-closed protects against a PDP that is *absent*, not against one that +*lies*. The distinction matters because the digest chain looks like it closes +this and does not: a consumer that verified correspondence has verified +correspondence, not authenticity. + +Closing it is the PDP's to do, by signing the decision envelope — +`FLEX-WP-0024`, reported by flex-auth against its own interest after finding its +response channel served plain HTTP with no envelope signature. Until a signature +exists and a consumer verifies it, treat a matching `pdp_digest` as evidence +that the right request was approved, never as evidence that the decision came +from the PDP. + ### The comparison target at execute time The issue-time description above is unchanged: this engine records the