import { createGatekeeper } from "@phosra/gatekeeper"
const gk = createGatekeeper({
platformDid: "did:ocss:loopline",
platformKeyId: "did:ocss:loopline#2026-06",
gatekeeperSigningKey: { seed: new Uint8Array(32) /* real Ed25519 seed */, keyID: "did:ocss:loopline#2026-06" },
censusBaseUrl: "https://phosra-api-sandbox-production.up.railway.app",
trustRootXB64Url: process.env.PHOSRA_TRUST_ROOT_X,
endpointId: "iGrFqzp43O0S9YTNN2oAT6zMzcugEX_EwZbraWrE1AA",
})
const verdict = gk.check("infinite_scroll_block")
// ...apply the decision at the edge, then attest the outcome:
await verdict.confirm("applied") // signs the §8.3.8 receipt + POSTs it{
"id": "rcpt_01KWVD0ABX041061050R3GG28A",
"type": "enforcement_result",
"spec": "OCSS-v1.0-pre",
"body": {
"applied_at": "2026-07-06T09:43:59.612Z",
"enforcement_state": "applied",
"envelope_ref": "env_9f2c1a7e",
"method_class": "platform_gate",
"rule_ref": "rr_loopline_infinite_scroll_block"
},
"key_id": "did:ocss:loopline#2026-06",
"sig": "ed25519:mGm30Y7TKrhTnTXH8fq2H8BaaVwFGOJCmJpI_F1hqefhCf9u9I5TRZawk2t12KSiq0pyuCbgzxjeQF11djnUAA"
}{
"id": "rcpt_01KWVD0ABX041061050R3GG28A",
"type": "enforcement_result",
"spec": "OCSS-v1.0-pre",
"body": {
"applied_at": "2026-07-06T09:43:59.612Z",
"enforcement_state": "applied",
"envelope_ref": "env_9f2c1a7e",
"method_class": "platform_gate",
"rule_ref": "rr_loopline_infinite_scroll_block"
},
"key_id": "did:ocss:loopline#2026-06",
"sig": "ed25519:mGm30Y7TKrhTnTXH8fq2H8BaaVwFGOJCmJpI_F1hqefhCf9u9I5TRZawk2t12KSiq0pyuCbgzxjeQF11djnUAA"
}{
"error": "Bad Request",
"message": "payload is not an enforcement_result receipt (§8.3.8)",
"code": 400,
"class": "malformed"
}{
"error": "Unauthorized",
"message": "enforcement_result signed by an app DID not resolvable on the Trust List (§8.3.8 cl.4)",
"code": 401,
"class": "signature_invalid"
}{
"error": "Forbidden",
"message": "the enforcement_result must be signed by the calling app; failed binding: writer_binding",
"code": 403,
"class": "scope_failure"
}{
"error": "Conflict",
"message": "(rule_ref, app_did) replayed with a different enforcement_result (D-13)",
"code": 409,
"class": "replay"
}{
"error": "Too Many Requests",
"message": "rate limit exceeded",
"code": 429
}{
"error": "Internal Server Error",
"message": "internal error",
"code": 500
}{
"error": "Bad Gateway",
"message": "downstream provider error",
"code": 502
}{
"error": "Service Unavailable",
"message": "census operation not yet available",
"code": 503
}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.
import { createGatekeeper } from "@phosra/gatekeeper"
const gk = createGatekeeper({
platformDid: "did:ocss:loopline",
platformKeyId: "did:ocss:loopline#2026-06",
gatekeeperSigningKey: { seed: new Uint8Array(32) /* real Ed25519 seed */, keyID: "did:ocss:loopline#2026-06" },
censusBaseUrl: "https://phosra-api-sandbox-production.up.railway.app",
trustRootXB64Url: process.env.PHOSRA_TRUST_ROOT_X,
endpointId: "iGrFqzp43O0S9YTNN2oAT6zMzcugEX_EwZbraWrE1AA",
})
const verdict = gk.check("infinite_scroll_block")
// ...apply the decision at the edge, then attest the outcome:
await verdict.confirm("applied") // signs the §8.3.8 receipt + POSTs it{
"id": "rcpt_01KWVD0ABX041061050R3GG28A",
"type": "enforcement_result",
"spec": "OCSS-v1.0-pre",
"body": {
"applied_at": "2026-07-06T09:43:59.612Z",
"enforcement_state": "applied",
"envelope_ref": "env_9f2c1a7e",
"method_class": "platform_gate",
"rule_ref": "rr_loopline_infinite_scroll_block"
},
"key_id": "did:ocss:loopline#2026-06",
"sig": "ed25519:mGm30Y7TKrhTnTXH8fq2H8BaaVwFGOJCmJpI_F1hqefhCf9u9I5TRZawk2t12KSiq0pyuCbgzxjeQF11djnUAA"
}{
"id": "rcpt_01KWVD0ABX041061050R3GG28A",
"type": "enforcement_result",
"spec": "OCSS-v1.0-pre",
"body": {
"applied_at": "2026-07-06T09:43:59.612Z",
"enforcement_state": "applied",
"envelope_ref": "env_9f2c1a7e",
"method_class": "platform_gate",
"rule_ref": "rr_loopline_infinite_scroll_block"
},
"key_id": "did:ocss:loopline#2026-06",
"sig": "ed25519:mGm30Y7TKrhTnTXH8fq2H8BaaVwFGOJCmJpI_F1hqefhCf9u9I5TRZawk2t12KSiq0pyuCbgzxjeQF11djnUAA"
}{
"error": "Bad Request",
"message": "payload is not an enforcement_result receipt (§8.3.8)",
"code": 400,
"class": "malformed"
}{
"error": "Unauthorized",
"message": "enforcement_result signed by an app DID not resolvable on the Trust List (§8.3.8 cl.4)",
"code": 401,
"class": "signature_invalid"
}{
"error": "Forbidden",
"message": "the enforcement_result must be signed by the calling app; failed binding: writer_binding",
"code": 403,
"class": "scope_failure"
}{
"error": "Conflict",
"message": "(rule_ref, app_did) replayed with a different enforcement_result (D-13)",
"code": 409,
"class": "replay"
}{
"error": "Too Many Requests",
"message": "rate limit exceeded",
"code": 429
}{
"error": "Internal Server Error",
"message": "internal error",
"code": 500
}{
"error": "Bad Gateway",
"message": "downstream provider error",
"code": 502
}{
"error": "Service Unavailable",
"message": "census operation not yet available",
"code": 503
}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:
@openchildsafety/ocss@0.1.5 and wrap the receipt
with receiptToWire() before POSTing. The helper was introduced in 0.1.4 and
remains present in public 0.1.5; the qualified 0.1.6 Railway candidate is not
a public npm release. signReceipt returns body as a Uint8Array of canonical bytes;
JSON.stringify on the raw receipt numeric-keys it ({"0":123,…}), which the census rejects as a
non-canonical body — 401 {"class":"signature_invalid","message":"enforcement_result sender_signature failed verification … (§8.3.8 cl.4)"}. receiptToWire(receipt) decodes body to
nested JSON so it rides as the verbatim canonical blob the census verifies (this is exactly what
gk.confirm() does internally). The signed bytes are unchanged. verdict.confirm() remains the
easiest path; the raw Node tab below uses receiptToWire. On @openchildsafety/ocss@0.1.3 and
earlier the standalone raw path fails — upgrade to public 0.1.5.import { createGatekeeper } from "@phosra/gatekeeper"
const gk = createGatekeeper({
platformDid: "did:ocss:loopline",
platformKeyId: "did:ocss:loopline#2026-06",
gatekeeperSigningKey: { seed: /* 32-byte Ed25519 seed */ new Uint8Array(32), keyID: "did:ocss:loopline#2026-06" },
censusBaseUrl: "https://phosra-api-sandbox-production.up.railway.app",
trustRootXB64Url: process.env.PHOSRA_TRUST_ROOT_X!,
endpointId: "iGrFqzp43O0S9YTNN2oAT6zMzcugEX_EwZbraWrE1AA",
})
const verdict = gk.isAllowed({ category: "infinite_scroll_block" })
// ...apply the decision at the edge, then attest the outcome:
await verdict.confirm("applied") // signs the §8.3.8 receipt + POSTs /enforcement-confirmations
import { signRequest, signReceipt, receiptToWire, ed25519Sign } from "@openchildsafety/ocss"
import { randomBytes } from "node:crypto"
const BASE = "https://phosra-api-sandbox-production.up.railway.app/api/v1"
const seed = new Uint8Array(Buffer.from("bG9vcGxpbmUBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE", "base64url"))
const keyID = "did:ocss:loopline#2026-06"
const key = { keyId: keyID, sign: (m) => ed25519Sign(seed, m) }
// rule_ref comes from the enforcement profile's categories[] row you enforced.
const body = {
envelope_ref: "env_abc123",
rule_ref: "rr_mia_infinite_scroll",
enforcement_state: "applied", // applied | degraded | refused
applied_at: new Date().toISOString(),
method_class: "platform_gate", // non-empty when enforcement_state === "applied"
}
const receipt = signReceipt("enforcement_result", body, key, new Date(), new Uint8Array(randomBytes(10)))
const targetURI = BASE + "/enforcement-confirmations", bodyText = JSON.stringify(receiptToWire(receipt))
const headers = signRequest({ method: "POST", targetURI, body: new TextEncoder().encode(bodyText), keyID, seed, created: Math.floor(Date.now() / 1000) })
headers["Content-Type"] = "application/json"
const res = await fetch(targetURI, { method: "POST", headers, body: bodyText })
console.log(res.status) // 201 recorded, 200 idempotent re-submit
# sign_request(...) is the RFC 9421 transport signer from /concepts/signing-requests.
# sign_receipt(...) below signs the INNER §8.3.8 receipt (JCS over {body, spec, type}).
import base64, json, os, time, requests
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
BASE, SPEC = "https://phosra-api-sandbox-production.up.railway.app/api/v1", "OCSS-v1.0-pre"
SEED = "bG9vcGxpbmUBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE"
KEYID = "did:ocss:loopline#2026-06"
_CROCKFORD = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"
def _b64u(s): return base64.urlsafe_b64decode(s + "=" * (-len(s) % 4))
def _jcs(v): return json.dumps(v, sort_keys=True, separators=(",", ":"), ensure_ascii=False)
def _ulid() -> str: # rcpt_ + a Crockford ULID (SDK-compatible shape)
n = (int(time.time() * 1000) << 80) | int.from_bytes(os.urandom(10), "big")
return "".join(_CROCKFORD[(n >> (5 * (25 - i))) & 31] for i in range(26))
def sign_receipt(rtype: str, body: dict) -> dict:
sk = Ed25519PrivateKey.from_private_bytes(_b64u(SEED))
sig = sk.sign(_jcs({"body": body, "spec": SPEC, "type": rtype}).encode())
return {"id": "rcpt_" + _ulid(), "type": rtype, "spec": SPEC, "body": body,
"key_id": KEYID, "sig": "ed25519:" + base64.urlsafe_b64encode(sig).decode().rstrip("=")}
# rule_ref MUST be a live per-child ref from a profile you actually enforced (§8.3.8 cl.1).
receipt = sign_receipt("enforcement_result", {
"envelope_ref": "env_abc123", "rule_ref": "rr_mia_infinite_scroll",
"enforcement_state": "applied", "applied_at": "2026-07-06T09:43:59.612Z",
"method_class": "platform_gate", # non-empty when state == "applied"
})
url = BASE + "/enforcement-confirmations"
body = json.dumps(receipt).encode()
h = sign_request("POST", url, KEYID, SEED, body); h["Content-Type"] = "application/json"
print(requests.post(url, data=body, headers=h).status_code) # 201 recorded, 200 idempotent
// SignRequest(...) is the RFC 9421 transport signer from /concepts/signing-requests.
// signReceipt below signs the INNER §8.3.8 receipt (JCS over {body, spec, type}).
package main
import (
"bytes"; "crypto/ed25519"; "crypto/rand"; "encoding/base64"; "encoding/json"
"fmt"; "io"; "net/http"; "sort"; "strings"; "time"
)
const (
base = "https://phosra-api-sandbox-production.up.railway.app/api/v1"
spec = "OCSS-v1.0-pre"
seed = "bG9vcGxpbmUBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE"
keyID = "did:ocss:loopline#2026-06"
)
// jcs renders RFC 8785 canonical JSON for the receipt's flat, ASCII value domain.
func jcs(v any) []byte {
switch t := v.(type) {
case map[string]any:
keys := make([]string, 0, len(t))
for k := range t {
keys = append(keys, k)
}
sort.Strings(keys)
var b strings.Builder
b.WriteByte('{')
for i, k := range keys {
if i > 0 {
b.WriteByte(',')
}
kb, _ := json.Marshal(k)
b.Write(kb)
b.WriteByte(':')
b.Write(jcs(t[k]))
}
b.WriteByte('}')
return []byte(b.String())
default:
out, _ := json.Marshal(v)
return out
}
}
func signReceipt(rtype string, body map[string]any) map[string]any {
sk := ed25519.NewKeyFromSeed(mustSeed())
sig := ed25519.Sign(sk, jcs(map[string]any{"body": body, "spec": spec, "type": rtype}))
var ent [10]byte
rand.Read(ent[:])
id := fmt.Sprintf("rcpt_%d%X", time.Now().UnixMilli(), ent)
return map[string]any{"id": id, "type": rtype, "spec": spec, "body": body,
"key_id": keyID, "sig": "ed25519:" + base64.RawURLEncoding.EncodeToString(sig)}
}
func mustSeed() []byte { s, _ := base64.RawURLEncoding.DecodeString(seed); return s }
func main() {
// rule_ref MUST be a live per-child ref from a profile you enforced (§8.3.8 cl.1).
receipt := signReceipt("enforcement_result", map[string]any{
"envelope_ref": "env_abc123", "rule_ref": "rr_mia_infinite_scroll",
"enforcement_state": "applied", "applied_at": "2026-07-06T09:43:59.612Z",
"method_class": "platform_gate",
})
url := base + "/enforcement-confirmations"
body, _ := json.Marshal(receipt)
h, _ := SignRequest("POST", url, keyID, seed, body)
req, _ := http.NewRequest("POST", url, bytes.NewReader(body))
for k, v := range h {
req.Header.Set(k, v)
}
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
b, _ := io.ReadAll(resp.Body)
fmt.Println(resp.StatusCode, string(b)) // 201 recorded, 200 idempotent
}
sign_receipt here is a faithful port of @openchildsafety/ocss’s signReceipt (JCS over
{body, spec, type}, §8.3.8 D-9 boundary) and reproduces that SDK function’s bytes exactly — but
those bytes are not what the live census currently accepts (see the warning above). The 201
capture below was produced by verdict.confirm(), the reliable path. §8.3.8 is a first-person
attestation: the census verifies your RFC 9421 signature, the first-person binding (the signer
must equal the receipt’s signer), a non-empty rule_ref, and dedup — it does not currently
verify that the rule_ref corresponds to a profile you actually enforced, so a well-formed but
fabricated rule_ref with a valid signature is recorded (201), not rejected. Attesting only to
rules you truly applied is the enforcing app’s own integrity obligation (§8.3.8 cl.1), not a
guarantee the census checks for you.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.{
"id": "rcpt_01KWVD0ABX041061050R3GG28A",
"type": "enforcement_result",
"spec": "OCSS-v1.0-pre",
"body": {
"applied_at": "2026-07-06T09:43:59.612Z",
"enforcement_state": "applied",
"envelope_ref": "env_9f2c1a7e",
"method_class": "platform_gate",
"rule_ref": "rr_loopline_infinite_scroll_block"
},
"key_id": "did:ocss:loopline#2026-06",
"sig": "ed25519:mGm30Y7TKrhTnTXH8fq2H8BaaVwFGOJCmJpI_F1hqefhCf9u9I5TRZawk2t12KSiq0pyuCbgzxjeQF11djnUAA"
}
HTTP/2 200
content-type: application/json
ocss-replay: original
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:
{
"error": "Conflict",
"message": "(rule_ref, app_did) replayed with a different enforcement_result (D-13)",
"code": 409,
"class": "replay"
}
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.
Show child attributes
Show child attributes
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:loopline#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.
Show child attributes
Show child attributes
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:loopline#2026-06"
"ed25519:" + base64url-raw signature over canon.Marshal({body,spec,type}).