Skip to main content
Read this page first. Every other page in these docs describes one surface; this page is the map that tells you which surface you’re on and why it exists. Phosra is built from three planes that are deliberately kept apart:

Control plane

Manage your Phosra account — orgs, phosra_ keys, usage, advisor agents, MCP tokens. Phosra-specific. Bearer auth.

Data plane

The enforcement path — a policy is written, compiled into a signed profile, and enforced locally on the device or platform.

Open OCSS protocol

Vendor-neutral primitives — the Trust List, signed receipts, sealed envelopes, the 123-category vocabulary. Phosra adds zero cryptographic logic here.
Phosra architecture: control plane, data plane, and the open OCSS protocol, with the enforcement path flowing Provider → Census → Platform and every signature verifying to the OCSS Trust List root.

The mental model in one paragraph

A Provider (a parental-control or safety vendor) writes a child’s rules to the census using a signed, RFC-9421 rule-write. The census stores those rules and compiles them into a single signed enforcement profile for each enforcement endpoint. A Platform (an app, OS, router, or school network) fetches that profile once, verifies its signature to the OCSS root in its own process, caches it, and then answers every isAllowed() question locally — no network call, no per-decision latency, fail-closed when the profile is missing. The signatures on the rule-write, the profile, and every receipt are all OCSS protocol artifacts: they verify against the same Trust List root regardless of which accredited provider issued them. That last sentence is the whole point of the separation: the trust anchor is the open standard, not Phosra. Swap Phosra for any other OCSS-conformant provider and the data plane and protocol surfaces are byte-for-byte identical.

Plane 1 — the control plane

What it is: management operations over your Phosra account. Create developer orgs, provision and revoke phosra_-prefixed API keys, register advisor agents, declare OCSS payload keys, mint and revoke MCP tokens, and pull hourly usage rollups. Who talks to it: you, from a server or the developer console — never an end-user’s device. Auth: standard HTTP Bearer. Org and key management uses your WorkOS session bearer (from signup/login); the /developer/* routes take the phosra_ API key you mint. Base URL:
https://prodapi.phosra.com/api/v1
This is the only Phosra-specific surface. Everything here is a normal REST management API — if you’ve used Stripe’s account or key endpoints, this will feel familiar. It is live today; prove it with no key (a 401, not a 404, is the correct answer without a bearer):
curl -fsS https://prodapi.phosra.com/health
# → 200 {"status":"ok"}

Control-plane reference →

Orgs, API keys, usage, advisor agents, and MCP tokens.

Plane 2 — the data plane

What it is: the enforcement path — the sequence that turns a parent’s intent into an actual allow/deny decision on a device. Three roles participate:
1

Provider writes a rule

A Provider issues a child’s rule (and the verifiable consent behind it) with a signed rule-write. On the census this is POST /api/v1/policies/{policyId}/rules; with the SDK it’s a @phosra/link directive(...) call. The census returns a signed write receipt on success.
2

Census compiles a signed profile

The census stores the rule in child_policies and compiles all of a child’s active rules into one signed §8.3.6 enforcement profile per enforcement endpoint. The census is the only coordination point — but it is not in the decision hot path.
3

Platform enforces locally

A Platform fetches the profile once (or on a poll) via the §9.3(b) read, GET /api/v1/enforcement-profiles/{endpoint_id}, verifies its Ed25519 signature to the OCSS root in-process, and caches it. @phosra/gatekeeper wraps this.
Auth: the phosra_ API key, with writes signed per RFC-9421.

There is no hosted decision endpoint — by design

Once the platform holds a verified profile, isAllowed({ category, signal }) evaluates every subsequent enforcement question against the cached, signed profile — zero network calls, zero latency, fail-closed when the profile is absent.
isAllowed() is the decision call. There is no POST /v1/check endpoint and none is planned. A hosted decision call would add per-decision latency, put a network dependency on the enforcement hot path, and break the fail-closed guarantee whenever the census is unreachable. The profile read is gated — without a bearer you get a 401, which proves the endpoint is real:
curl -s -o /dev/null -w "%{http_code}\n" \
  https://phosra-api-sandbox-production.up.railway.app/api/v1/enforcement-profiles/pg-mia-network-edge-2026-06
# → 401

Enforcement concept →

Jobs, results, and the poll-don’t-webhook verification contract.

Platform integration →

Fetch a profile, verify to root, and enforce with @phosra/gatekeeper.

Plane 3 — the open OCSS protocol

What it is: the vendor-neutral cryptographic surface — signed write and enforcement receipts, two-layer sealed envelopes, the eIDAS-style Trust List, the succession record, and the 123-category rule vocabulary. All of it is sourced from @openchildsafety/ocss, the open OCSS reference library. Phosra adds zero cryptographic logic here. Who talks to it: anyone. No Phosra account is required to read the Trust List, verify a receipt, or use the protocol primitives. The relationship is the same as Yubico shipping a FIDO2 key: Yubico implements FIDO2, the FIDO Alliance owns the standard. Phosra implements OCSS, the OCSS stewardship body owns the standard. The signing and verification primitives in these docs are not Phosra code — they are the open OCSS library, re-exported without modification.

The Trust List is the shared anchor

Every signature in the data plane — the rule-write receipt, the enforcement profile, the delivery receipt — verifies against the same Trust List root. The list is live and served at a well-known path; fetch it with no key:
curl -fsS https://phosra-api-sandbox-production.up.railway.app/.well-known/ocss/trust-list \
  | python3 -c "import sys,json; d=json.load(sys.stdin); doc=json.loads(d['document']); \
print('root key_id:', d['key_id'], '| alg:', d['alg'], '| entries:', len(doc['entries']))"
# → root key_id: root-sandbox-2026-06 | alg: ed25519 | entries: 126
The signed document is returned as a JSON string under document, with the detached signature and the signing key_id alongside it:
{
  "document": "{\"document_type\":\"trust_list\",\"entries\":[ ... ],\"ocss_version\":\"...\"}",
  "key_id": "root-sandbox-2026-06",
  "alg": "ed25519",
  "sig": "…base64url Ed25519 signature…"
}
The value above is from the sandbox census. Production serves a distinct root (root-prod-2026-06) and a validly-signed empty list until accreditation entries are added through OCSS governance — an empty-but-signed list is the honest, correct state, not a bug.

OCSS overview →

Receipts, envelopes, the Trust List, and the succession record.

Trust Framework →

The two-layer envelope, accreditation tiers, and the conformance contract.

Why keep them separate?

ConcernControl planeData planeOpen OCSS protocol
PurposeManage your accountEnforce a child’s policyTrust & verification
Talks toYou (server / console)Provider ↔ census ↔ platformAnyone
AuthWorkOS bearer / phosra_ keyphosra_ key (RFC-9421 writes)None — public
Owned byPhosraPhosra (implements OCSS)The OCSS standard
Portable across providers?NoYesYes
In the decision hot path?NoOnly the local isAllowed()No
Keeping the trust anchor in the open protocol — not in Phosra — is the asset. A standard you cannot capture is one you can safely build on: if you ever integrate a different OCSS-conformant provider, your enforcement code and every receipt you’ve stored keep verifying, unchanged.

Where to go next

Quickstart — first call in 5 min

Zero to an enforced policy against the live sandbox.

Pick your integration path

Platform, Provider, or protocol-only — start where you are.