@phosra/link

@phosra/link 0.7.35 is the provider-side SDK candidate for Phosra Link. The recommended integration is a server-only v3 credential, one same-origin catch-all route, one durable worker, and the mandatory-branded React component.

Private evaluation candidate. Public npm currently serves 0.6.1; @phosra/[email protected] is not a generally available production integration. Hosted routing, production credentials, and a production receipt rail remain roadmap.

bash
npm install @phosra/[email protected]

@phosra/link is ESM-only. The Golden server is Node-only and must be imported from @phosra/link/server. Never import credentials or server APIs into a client component.

Your application owns only its existing parent authentication, child lookup, and policy facts. Link owns environment discovery, trust verification, signed Intent V2 creation, public consent copy, OAuth handoff, durable delivery, retries, and evidence-based status.

ts
// lib/phosra-link-server.ts — server-only shared singleton
// Node-only module; never import from client components.
import { Pool } from "pg"
import { createGoldenLinkServer } from "@phosra/link/server"
 
export const phosraLinkServer = await createGoldenLinkServer({
  credential: process.env.PHOSRA_CREDENTIAL!,
  database: new Pool({ connectionString: process.env.DATABASE_URL }),
 
  authenticate: async (request) => {
    const session = await authenticatedParent(request)
    return session === null ? null : {
      sessionID: session.id,
      parentID: session.parentId,
    }
  },
 
  children: {
    resolve: async ({ principal, childRef }) => {
      const child = await childForParent(principal.parentID, childRef)
      return child === null ? null : {
        id: child.id,
        displayName: child.displayName,
        ageBand: child.ageBand,
        householdRef: child.familyId,
      }
    },
  },
 
  policy: {
    resolve: ({ child, platformDid }) =>
      policyRulesFor(child.id, platformDid),
  },
})

Import that singleton from the catch-all route. The route contains no credential or environment configuration of its own:

ts
// app/api/phosra/link/[...phosra]/route.ts
import { phosraLinkServer } from "@/lib/phosra-link-server"
 
export const GET = phosraLinkServer.handler
export const POST = phosraLinkServer.handler
export const DELETE = phosraLinkServer.handler

The catch-all is important. It serves the callback, session creation and status, retry/cancel, and signed platform-event receiver under /api/phosra/link/*. Mounting only the callback breaks recovery and prevents later platform evidence from reaching the provider.

The authenticated householdRef boundary

householdRef is your stable, provider-local family authority. Return it only after authenticating the parent and proving that the child belongs to that parent. The SDK derives a platform-scoped digest for signed Intent V2. The raw value is not a browser input and is not sent to the platform.

Never use a display name, email address, or client-supplied family ID as householdRef.

An occupied same-family platform profile does not add a provider API or React state for the host to implement. The Golden Gatekeeper authorize handler recommends a separate profile and presents Choose another profile, Confirm sharing, and Cancel and return in that order. It explains that the strictest combined protections apply and that shared activity cannot be reliably attributed to one child.

Before token exchange, the handler displays only the authenticated platform catalog label recovered from its server-side sealed catalog and the verified same-family member count. The signed selected-profile presentation follows token exchange. It does not expose raw platform IDs, family/child authority, target or aggregate identifiers, or policy parameters; forms carry only bounded opaque tokens. Names and numeric ages of existing members require a future provider-signed member-display resolver and are not claimed by this release.

Run the durable worker

Run exactly one worker loop in a worker process and abort it during graceful shutdown:

ts
// phosra-link-worker.ts — separate server process entry point
import { phosraLinkServer } from "@/lib/phosra-link-server"
 
const shutdown = new AbortController()
process.once("SIGTERM", () => shutdown.abort())
process.once("SIGINT", () => shutdown.abort())
 
await phosraLinkServer.runWorker({ signal: shutdown.signal })

The worker serializes delivery and retry work. A successful HTTP response means a verified receiver acknowledgement, not that every control is applied. Parent status advances only when signed platform evidence supports it.

Render the parent experience

tsx
import { PhosraLink } from "@phosra/link/react"
 
<PhosraLink
  createSession={async ({ signal }) => {
    const response = await fetch("/api/phosra/link/sessions", {
      method: "POST",
      signal,
      headers: { "content-type": "application/json" },
      body: JSON.stringify({
        platform_did: selectedPlatformDid,
        child_ref: selectedChildId,
        return_to: window.location.pathname,
      }),
    })
    if (!response.ok) throw new Error("Unable to start Phosra Link")
    return response.json()
  }}
  onEvent={recordLinkEvent}
  onExit={closeLink}
/>

Forward the supplied signal. Link cancels abandoned session creation, supports restart-safe same-tab recovery, polls bounded server-authoritative status, and never turns a delivery acknowledgement into a fake success state.

PhosraLinkDialog remains an alias for source compatibility. New code should use the shorter PhosraLink export.

Shared-profile confirmation preserves the same createSession, onEvent, and onExit behavior. Do not wrap the component in a second consent modal.

Server API

MemberPurpose
ready()Verify the environment and ensure package-owned schema is ready. The Golden factory calls this before it returns.
handlerFetch-standard handler for the GET, POST, and DELETE catch-all exports.
runWorkerOnce()Perform at most one bounded, non-idle delivery or retry action.
runWorker({ signal })Drain durable work serially until the signal aborts.
getSnapshotForGrant(authority)Read the verified public projection for an app-authorized grant.
retryPlatformForGrant(authority)Schedule one signed, durable platform refresh for the exact saved or disconnect-pending connection after re-authorizing it against your tenant.
disconnectGrant(authority)Record provider-side revocation and begin the signed platform release lifecycle.

Grant reads and disconnects require the exact app-authorized tuple { grantId, platformDid, targetRef }. Do not accept that tuple directly from an untrusted browser without re-authorizing it against your own tenant boundary.

Let a parent refresh an existing connection

When a platform reports degraded, stale, or a previously applied result that needs to be checked again, do not create another Link ceremony. The same method also resumes an exhausted profile refresh after disconnectGrant() so the platform can fetch the signed revocation tombstone and finish its release. Re-authorize the child and exact active or disconnect-pending grant in your own database, then pass only that exact tuple to the SDK:

ts
const authority = {
  grantId: savedConnection.grantId,
  platformDid: savedConnection.platformDid,
  targetRef: `child:${authorizedChild.censusRef}`,
}
 
const projection = await phosraLinkServer.retryPlatformForGrant(authority)
if (projection === null) throw new Error("Platform sync is not available")

The method records a signed retry request in the provider outbox. The existing runWorker() process delivers it, and Gatekeeper independently checks current grant authority before reopening only a failed degraded or stale profile lifecycle. A signed revocation request cannot reopen healthy or unrelated authority. A healthy shared-profile aggregate and its other child memberships remain intact. Keep the last verified state visible while the refresh runs; label the parent action with plain copy such as Sync now or Check disconnect.

If the platform is unreachable for the request's five-minute validity window, the request becomes immutable expired evidence. A later authorized parent check mints the next signed retry epoch; repeated checks while a request is still active reuse that exact request rather than creating parallel work.

Evidence states are intentionally different

  • bound means a durable connection exists.
  • rule_recorded means requested controls were recorded, not applied.
  • profile_ready means the platform has a verified profile and results are being checked.
  • applied with E4 means every requested control has current concrete platform evidence.
  • degraded, refused, and stale remain visible; the SDK does not paint them green.
  • revoked means the provider authority is revoked. Platform removal is complete only after the signed release lifecycle confirms it.

Advanced compatibility API

createLink(...) and the low-level ceremony functions remain available for older writer-plane integrations. They are not the recommended durability boundary for a new parent application. New integrations should begin with createGoldenLinkServer(...) and PhosraLink.

See the Provider quickstart, branding contract, and disconnect guide.