Mint a test consent attestation (sandbox)

Sandbox only. Gated on PHOSRA_ENV==sandbox — returns 404 on dev, staging, and production. Production §8.3.2 consent semantics are unchanged.

Mints a §8.3.2-shaped test consent row with app_ref = your RFC 9421 caller DID, so a cold self-registered platform can satisfy the consent-first gate on POST /enforcement-endpoints with no OCSS_CONSENT_ATTESTATION_APPS roster edit and no live counterparty.

With no child_ref, the census auto-provisions the sandbox self-serve test child and targets it. A supplied child_ref must already exist — the door never fabricates a caller-named child. The response gives you the target_ref to pass straight into the bind call.

Worked example

ts
import { signRequest } from "@openchildsafety/ocss"
 
const BASE  = "https://phosra-api-sandbox-production.up.railway.app/api/v1"
const seed  = new Uint8Array(Buffer.from(process.env.OCSS_SANDBOX_TEST_SEED_B64URL!, "base64url"))
const keyID = process.env.OCSS_SANDBOX_KEY_ID!
 
const targetURI = BASE + "/sandbox/consent-attestations"
const body = { band: "13_15", consent_scope: "collection_parental_authority" }   // both optional; these are the defaults
const bodyText = JSON.stringify(body)
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 })
const consent = await res.json()
console.log(res.status, consent.target_ref)   // pass target_ref to POST /enforcement-endpoints

Example synthetic sandbox 201 response:

json
{
  "ok": true,
  "app_ref": "did:ocss:loopline",
  "target_ref": "child:5ba0d00c-0000-4000-8000-0000000000c1",
  "standing_ref": "consent:attestation:sbx-consent:did:ocss:loopline:child:5ba0d00c-0000-4000-8000-0000000000c1",
  "idempotency_key": "sbx-consent:did:ocss:loopline:child:5ba0d00c-0000-4000-8000-0000000000c1",
  "band": "13_15",
  "consent_scope": "collection_parental_authority",
  "expiry": "2027-07-06T05:26:40Z",
  "note": "sandbox-only test consent; pass audience_did=<this DID> and child_ref=<target_ref> to POST /api/v1/enforcement-endpoints to complete the consent-first mint"
}

The call is idempotent on (app_ref, target_ref) — re-minting returns the same standing_ref. Next: bind the endpoint.

This standing_ref satisfies the consent-first precondition for POST /enforcement-endpoints (endpoint binding) — that is its only job. It does not satisfy a signed rule write (POST /policies/{id}/rules): the sandbox mint stores no signed consent envelope, so the census's writer-tier resolver fails closed and the rule write returns 403 standing_failure. For a rule write, obtain a standing via the §8.3.2 consent-ingest lane (a real signed consent_attestation), not this sandbox mint. The two consent surfaces are not interchangeable.