# Path Proof Receipt — Threat Boundary This document states, precisely, what the `path_proof` verification gate proves and does not prove. It is the contract the verifier enforces and the limit a consumer must respect. The field rationale lives in `docs/path-proof-receipt.md` (branch `timmy/3-path-proof-receipt`); this file is the executable-side boundary statement required by issue #28. ## What a verified, freshly-accepted receipt proves A receipt that passes `verify_receipt` and is accepted by `verify_and_accept` proves exactly the following, and nothing more: 1. **Binding.** The receipt commits, as a single signed unit, to: - the consequential action (`action.kind`, `action.target`), - the exact request and observed result it claims (`action.request_sha256`, `action.result_sha256`), - the model invocation identity (`path.model.id`, `path.model.invocation`), - the ordered tool path and effective policy (`path.tools.trace_sha256`, `path.policy.bundle_sha256`), - the immutable code identity (`path.code.repo`, `path.code.commit`, `path.code.entrypoint`), and - the retrievable evidence bundle (`evidence.uri`). 2. **Trust.** The attestation resolves to a signer that is present in the caller's trusted key registry, is not revoked, and is within its validity window at the time of verification. 3. **Freshness.** The receipt is inside its `[issued_at, expires_at]` window. 4. **Single-use.** The receipt's `nonce` and `action_id` have not been previously consumed, so an identical receipt cannot be accepted a second time (idempotency / replay protection). ## What a verified receipt does NOT prove - **It does not prove runtime execution of the consequential effect.** `result_sha256` is the hash of an *observed* result the recorder claims it saw. Proving the side effect actually took place requires the verifier to independently re-observe it (for example, read the Gitea label state back and compare it to `result_sha256`). Until that happens the effect is *attested*, not *confirmed*. - **It does not prove the provider ran the advertised weights.** `path.model.id` is an identity string, not a cryptographic attestation of model provenance. Only a separately trusted provider model attestation could close that gap. - **It does not survive compromise of both the recorder and its signing key.** The trust anchor is the key registry. If both are compromised, a forged receipt with a valid signature is indistinguishable from a genuine one. - **It does not prove the evidence bundle was not selectively redacted ambiguously.** The redaction manifest is part of the bundle; verifying the bundle digest proves integrity of what is present, not that nothing material was omitted. ## Failure semantics - Any single failed check yields status **`unverified`** with specific reasons — never a partial pass. - A structurally unreadable receipt yields status **`malformed`**. - A rejected receipt has **no side effects**: it does not consume a nonce or action_id. Only a verified acceptance marks identities as spent. ## Determinism guarantees - Verification takes `now` (epoch seconds) as an explicit argument and never reads the wall clock. - The key registry and spent-identity registry are in-memory objects the caller controls; the module performs no I/O, no randomness, and no network. - Therefore the gate is fully reproducible from a clean checkout and leaves no generated artifacts (test caches are gitignored).