Skip to main content
Provider applications use @phosra/link to connect an authenticated parent and child to an accredited platform. The Golden path replaces manual OAuth, trust, signing, endpoint minting, and retry wiring with one credential and three application adapters. This page is the recommended provider quickstart — the one new integrations start from.
A legacy writer-plane lane (createLink({ census, writerSeed, writerKeyId, db })) also exists and remains supported for existing integrations and for product-side grant reads around the Golden server — see Provider · createLink (writer-plane compatibility).
Hosted/private release candidate. The Railway qualification fleet vendors the Golden @phosra/link surface, now published on public npm. Production manifest, trust, and client-directory discovery are live. Environment-bound credentials are issued through the approved operator workflow and are not public self-service yet.

What you build

  1. A server-only Link singleton imported by one same-origin catch-all route and one worker entry point.
  2. Adapters for your existing parent auth, child ownership, and policy facts.
  3. One durable worker process.
  4. The SDK-owned PhosraLink component in your parent UI.
Link owns the rest: environment and Trust List verification, platform discovery, signed Intent V2, public consent copy, OAuth handoff, durable delivery, retry, and evidence-based status.

1. Create the Golden server

Then mount that same singleton in one catch-all route:
Use a v3 PHOSRA_CREDENTIAL. It carries the pinned environment authority; do not copy service URLs, trust roots, signing keys, or platform endpoints into browser code.
authenticate and children.resolve are authorization boundaries. A child reference from the request is only a lookup key. Return a child only after proving it belongs to the authenticated parent.
children.resolve must return the child’s census identity, not your row id. The id you return must be a census child UUID (a UUID the Phosra census issued for this child; the SDK canonicalises it to child:<uuid>). It becomes the grant’s target_ref and the consent attestation’s target on the census.
  • A non-UUID app id (nanoid, cuid, serial) makes the Link route answer an opaque 502 LINK_OPERATION_FAILED — the SDK rejects it with “child_ref must be a census child UUID … pass the Phosra child id, not the platform profile id” before anything reaches the census.
  • A UUID that is merely your local primary key passes that check but names a child the census has never heard of, and fails later at endpoint minting.
Store the census child id in its own column next to your child record (e.g. census_child_id) when the child is provisioned on the census, and return that value here. The Link ceremony cannot create a census child for you.

Household authority and Intent V2

Return a stable provider-local family identifier as householdRef. Link commits that value into a receiver-specific digest in the signed Intent V2. This enables safe one-to-many linking—for example, two children in one parental-controls household can share one Notflix Kids profile—without exposing the raw family ID to the browser or platform. The platform still receives a separate, parent-authorized member for each child. Gatekeeper combines those members on the shared target and computes the effective policy. Your provider does not send a platform account ID or choose the merge algorithm.

No provider-owned sharing modal

If the parent selects an occupied profile from the same verified family, Gatekeeper’s authorize handler owns the recommendation and explicit consent. It recommends a separate profile, explains strictest-rule aggregation and shared activity attribution, and offers Choose another profile, Confirm sharing, and Cancel and return in that order. Keep the existing PhosraLink createSession, onEvent, and onExit contract. Do not pass family, child, platform-profile, target, or policy authority through browser props, and do not recreate the decision in your application. The initial screen identifies the authenticated platform catalog label recovered from the platform’s server-side sealed catalog and the same-family member count. The signed selected-profile presentation follows token exchange; it is not the source of the confirmation label. Member names and numeric ages remain deferred until a future provider-signed member-display resolver is available.

2. Run the worker

Run one loop. It serializes durable delivery and signed retry processing. Do not also schedule runWorkerOnce() in the same process while the loop is active.
Forward the AbortSignal exactly. The component owns the branded review, handoff, bounded polling, cancellation, retry, and restart-safe recovery.

Exit reasons and events

onExit receives one of six PhosraLinkExitReason values: onEvent receives a PhosraLinkEvent union: opened, handoff_started, cancelled, status_changed, linked, completed (the latter three carry stage and evidence_level), expired, and { type: "error", code } where code is one of START_FAILED, STATUS_FAILED, STATUS_TIMEOUT, CANCEL_UNCONFIRMED, RETRY_UNCONFIRMED. Treating onEvent purely as an analytics sink is fine; treating onExit as a bare close handler is not — a host that ignores the reason renders a stale “Connect” button after every successful link.

4. Read status honestly

The session snapshot is the authority for parent-facing status: Never translate an HTTP 2xx, delivery acknowledgement, or adapter return into “controls active.”

5. Grant operations and disconnect

Every grant operation on the Golden server — getSnapshotForGrant, enforceRuleForGrant, retryGrant, retryPlatformForGrant, restartIncompleteGrant, abandonFailedGrant, disconnectGrant — takes the same exact authority tuple:
Where each value comes from: The Golden server does not expose a grant-listing method, but the grants live in the same Postgres the server owns, and the package-root store reads them:
To disconnect, authorize the exact grant in your own tenant boundary, then call:
Reuse the exact targetRef persisted with the issued grant. Never synthesize it from a raw child ID or householdRef: householdRef establishes authenticated provider-local family authority during issuance, while the saved targetRef binds this exact grant operation. enforceRuleForGrant(authority, rule) takes the same tuple plus a rule { category, decision?, params?, revision? }revision must be unique per edit and reused verbatim when retrying the same edit. The returned snapshot proves provider-side revocation. Platform removal is complete only when releaseStatus becomes complete through the signed release lifecycle. See Disconnect & reconnect.

Production checklist

  • Keep PHOSRA_CREDENTIAL and Postgres server-only.
  • Mount GET, POST, and DELETE on the complete catch-all path.
  • Derive parent and child authority from your authenticated server session.
  • Use a stable, non-display householdRef.
  • Run one worker with graceful abort.
  • Render PhosraLink; do not replace its evidence language with optimistic copy.
  • Let the platform SDK own shared-profile confirmation; add no host modal or browser authority.
  • Log only your correlation IDs—never credentials, authorization URLs, or raw household identifiers.
For the complete API surface, see @phosra/link. Platform teams should use the Platform quickstart.