Submit a signed §8.3.8 enforcement-result receipt
The enforcing app (gatekeeper) POSTs its OWN signed enforcement_result receipt attesting that it applied a rule. The census VERIFIES the app’s RFC 9421 signature (caller must equal the receipt’s signer — first-person binding, §8.3.8 cl.1) and RECORDS the receipt verbatim. It does NOT re-sign or append to the Receipt rail. Three invariants (spec-pinned, non-optional): - §6.2 NOT-A-WRITE: this is the app’s attestation, not a policy write. - §10.6 NEVER-GATES-THE-RULE: a missing/rejected confirmation never blocks or revives the §8.3.1 rule’s enforcement.
- HONEST CEILING (§8.3.8): “reported applied, never proven applied.” The body is the full outer receipt (id, type, spec, body, key_id, sig), not just the inner EnforcementResultBody.
enforcement_result receipt attesting that it
applied a rule. The census verifies the caller’s RFC 9421 signature
(the caller must equal the receipt’s signer — first-person binding, §8.3.8 cl.1) and
records the receipt verbatim. It does not re-sign or append to the Receipt rail.
The request body is the full outer receipt (id, type, spec, body, key_id,
sig), not just the inner EnforcementResultBody. Three spec-pinned invariants:
- §6.2 NOT-A-WRITE — this is the app’s attestation, not a policy write.
- §10.6 NEVER-GATES-THE-RULE — a missing or rejected confirmation never blocks or revives the rule’s enforcement.
- HONEST CEILING (§8.3.8) — “reported applied, never proven applied.”
Worked example
The@phosra/gatekeeper SDK is the supported path — verdict.confirm()
constructs and signs the receipt, then POSTs it for you:
sign_receipt here is byte-verified: signing the receipt body shown in the
201 capture below reproduces its exact sig
(ed25519:mGm30Y7T…). It is a faithful port of the SDK’s signReceipt (JCS over
{body, spec, type}, §8.3.8 D-9 boundary). A live rule_ref from a profile you actually
enforced is required — a fabricated one is rejected 401/403, which is why
verdict.confirm() (recommended tab) is the reliable path.What comes back
The census records your receipt and echoes it back byte-for-byte — it never re-signs or wraps it (§8.3.8 cl.3: the app’s own receipt IS the artifact). So the201 body is the exact
receipt you POSTed. A byte-identical re-submit returns 200 with an OCSS-Replay: original
header (the census deduplicates on rule_ref + caller DID); the same rule_ref with different
content is a 409 replay.
did:ocss:loopline-signed
POST /enforcement-confirmations against the sandbox census
(https://phosra-api-sandbox-production.up.railway.app), then the byte-identical re-POST. Not
hand-written.409 Conflict is returned only when the same rule_ref is re-submitted with different
content (a D-13 replay), never for a faithful re-submit:
rule_ref must be a live per-child reference from a profile the caller actually enforced
(§8.3.8 cl.1 first-person binding); the receipt signer must equal the RFC 9421 caller. A
fabricated rule_ref or a signer/caller mismatch is rejected 401/403 — which is why the
SDK’s verdict.confirm() (it carries the exact rule_ref from the verdict) is the reliable
path.Body
Full §8.3.8 signed receipt (the app's first-person apply attestation). The confirmation POST body IS this outer receipt — not the inner body alone. Sig covers canon.Marshal({body, spec, type}); id and key_id ride outside the signed bytes (D-9 exposure rule). Source: receipt.Receipt in internal/ocss/receipt/types.go with body = EnforcementResultBody.
rcpt_ — rides outside signed bytes (D-9).
"rcpt_01JTEST00000000000000000"
Always "enforcement_result" for §8.3.8 confirmations.
enforcement_result OCSS spec version — §11.4 domain separation.
"OCSS-v1.0-pre"
JSON-encoded EnforcementResultBody. Kept as raw bytes: re-marshaling would alter the canonical signed bytes and break verification.
DID key id of the submitting enforcing app (rides outside signed bytes). Verified indirectly: the signature only verifies if the resolved key matches.
"did:ocss:snaptr#snaptr-2026-06"
"ed25519:" + base64url-raw signature over canon.Marshal({body,spec,type}).
Response
Idempotent re-submit of the same receipt (same (rule_ref, app_did), byte-identical content). The body is the original receipt echoed verbatim — identical to the 201 body — and the response carries an OCSS-Replay: original header so a client can tell the write already landed.
Full §8.3.8 signed receipt (the app's first-person apply attestation). The confirmation POST body IS this outer receipt — not the inner body alone. Sig covers canon.Marshal({body, spec, type}); id and key_id ride outside the signed bytes (D-9 exposure rule). Source: receipt.Receipt in internal/ocss/receipt/types.go with body = EnforcementResultBody.
rcpt_ — rides outside signed bytes (D-9).
"rcpt_01JTEST00000000000000000"
Always "enforcement_result" for §8.3.8 confirmations.
enforcement_result OCSS spec version — §11.4 domain separation.
"OCSS-v1.0-pre"
JSON-encoded EnforcementResultBody. Kept as raw bytes: re-marshaling would alter the canonical signed bytes and break verification.
DID key id of the submitting enforcing app (rides outside signed bytes). Verified indirectly: the signature only verifies if the resolved key matches.
"did:ocss:snaptr#snaptr-2026-06"
"ed25519:" + base64url-raw signature over canon.Marshal({body,spec,type}).