npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@phosra/link

v0.6.1

Published

Writer-plane SDK for the OCSS (Open Child Safety Specification). Performs the consent attestation ceremony, rule-write directives, and platform binding — all signed locally over RFC 9421, posted to the Phosra hosted census.

Readme

@phosra/link

Writer-plane SDK for the OCSS (Open Child Safety Specification). Performs the consent attestation ceremony, rule-write directives, and platform binding — all signed locally over RFC 9421, posted to the Phosra hosted census.

Install

npm install @phosra/link

pg (node-postgres) is a runtime dependency — the grant store is Postgres-backed.

Quickstart with createLink (recommended, 0.5.0+)

createLink collapses the 8-field LinkConfig to three and returns a signed-by-default, self-migrating client. One key (the writer key you already hold), one census URL, one database — no shared connect secret.

import { createLink } from "@phosra/link"
import pg from "pg"

const link = createLink({
  census:     "https://census.phosra.com",   // pinned Trust-List root ships with the SDK
  writerSeed:  process.env.OCSS_WRITER_SEED!, // your Ed25519 accreditation seed (base64url)
  writerKeyId: "did:ocss:your-org#2026-07",   // the DID+kid published on your Trust-List entry
  db:          new pg.Pool({ connectionString: process.env.LINK_DB_URL }),
})

// Provision the product tables + run the accreditation self-check (once, at boot).
await link.ready()

// Connect a child (Plaid-style 3-leg ceremony) — signed delivery by default:
const { authorizeUrl, state, sessionId } =
  await link.connect.start({ platformDid: "did:ocss:notflix", redirectUri, parentSessionRef })
// …redirect the parent, then on the OAuth callback:
const { childProfiles } = await link.connect.resume({ code, state, parentSessionRef })
const result = await link.connect.finish({
  sessionId, platformChildProfileId: childProfiles[0].id, childId: "child:<uuid>",
  granted_scope: ["addictive_pattern_block"], state,
})

// Write an enforcement rule under the granted scope:
await link.enforce(result.grant_id, "addictive_pattern_block", "child:<uuid>", { decision: "block" })

// Batch-provision N age-banded profiles in one action (signed by default):
await link.provision("did:ocss:notflix", { state: "acct", children: [ /* … */ ] })

// Withdraw consent:
await link.revoke(result.grant_id)

What is derived (so nothing downstream changes): writerDid from writerKeyId; the router DID (constant did:ocss:phosra-router); the router payload key (pulled from the Trust List at use time); the family-hash householdSecret = HKDF(writerSeed, "phosra-link/household-hash/v1"); and the household/parent persona = HKDF(writerSeed, "phosra-link/parent-persona/v1") → a deterministic did:ocss:household-<hash>.

  • Pinned roots, no TOFU. For a canonical census host the Trust-List root ships with the SDK. For any other host you MUST pass trustRoot (the base64url root X) — the SDK never trusts a root it just met.
  • Signed by default. connect.finish and provision deliver the sender-DID-signed writer envelope (verified to the pinned root); there is no connect secret to mint or rotate. An undocumented __legacyConnectSecret escape hatch remains for receivers that have not migrated off HMAC.
  • Ships its own schema. link.migrate() (or migrateLinkSchema(pool) / printLinkSchema()) provisions the tables; the stores also self-heal a missing table on first use, so the silent "relation does not exist" crash is gone.
  • Accreditation self-check. link.verifyAccreditation() (run by link.ready() and before every write) root-verifies the Trust List, matches your writer public key, and requires an active enforcement-agent entry — else NotAccreditedError. Pass verifyAccreditation: false to disable.
  • Census registration of the derived household DID. The derived did:ocss:household-<hash> persona signs the consent attestation; for the census to verify that signature the persona must be admitted on the census (or pass your own already-registered parentKey). This is an operator step, not a code change.

Typed errors

Every failure is a LinkError subclass with a stable code: NotAccreditedError, PlatformNotConnectableError, LaneInactiveError, StateExpiredError, ParentSessionMismatchError, DeliveryFailedError (with .status + a .hint — a 401 delivery says "add your DID to the platform allowlist"), SchemaNotReadyError, BandMismatchError. Branch on .code or instanceof; the human-readable messages are unchanged from prior versions.

Quickstart (low-level API)

import { makeLinkStore, createLinkSession, completeLink, directive } from "@phosra/link"
import type { LinkConfig, LinkSession } from "@phosra/link"
import pg from "pg"

// 1. Construct your config (real keys, live census URL).
//    Obtain a key from the Phosra developer console or via
//    POST /api/v1/developers/orgs/{orgID}/keys (see docs.phosra.com).
const config: LinkConfig = {
  censusBaseUrl:    "https://phosra-api-sandbox-production.up.railway.app", // the ONE canonical partner sandbox host
  trustRootXB64Url: process.env.OCSS_TRUST_ROOT_X!,                         // sandbox root X (public): CMHWy3vUAiEcYDdE_bDvkRuEqwxkklS0tV-TYHJTlWU
  parentKey:        { seed: new Uint8Array(32) /* supply real Ed25519 seed */, keyID: "did:ocss:household-acme#parent-key-2026" },
  writerKey:        { seed: new Uint8Array(32) /* supply real Ed25519 seed */, keyID: "did:ocss:your-org#writer-key-2026" },
  writerDid:        "did:ocss:your-org",
  routerDid:        "did:ocss:phosra-router",
  householdSecret:  process.env.HOUSEHOLD_SECRET!,  // high-entropy per-family shared secret
  pool: new pg.Pool({ connectionString: process.env.LINK_DB_URL }),
}

// 2. Obtain the Postgres-backed grant store (synchronous — takes cfg.pool directly).
//    completeLink/directive also use the store internally; use this reference for
//    direct grant queries (listGrants, getGrant, etc.).
const store = makeLinkStore(config.pool)

// 3. Open a link session for a parent authorizing access for a platform.
const session: LinkSession = createLinkSession(
  "did:ocss:your-platform",    // audience_did — the platform being granted write access
  ["addictive_pattern_block"], // granted_scope
  "child:a11ce0fa-0000-4000-8000-0000000000a1", // target_ref — the child's full census UUID (normalizeChildRef rejects a truncated id)
  { ageHint: "13_15" },
)

// 4. Complete the link: posts a consent_attestation to the census.
const { grant_id } = await completeLink(config, session)

// 5. Write a rule directive under the granted scope.
const res = await directive(config, grant_id, "addictive_pattern_block", session.target_ref, {
  decision: "block",
})

Create-and-link (no existing profile, no prior grant)

completeLink binds an EXISTING platform profile via the connect ceremony. When the child has no profile on the platform yet (one parent action → create the profile AND bind it — EXT-01 batch provisioning), the chain is three public calls, per child:

import { ingestConsentAttestation, mintEnforcementEndpoint, provisionProfiles } from "@phosra/link"

// 1. Consent FIRST (the census enforcement-endpoint mint is consent-gated):
//    signed as the AUTHORITY HOLDER (config.parentKey — the household persona).
const consent = await ingestConsentAttestation(config, {
  platformDid: "did:ocss:notflix",
  childRef: "child:<census-child-uuid>",   // a census subject (POST /api/v1/subjects)
  band: "13_15",                            // §8.3.2 AGE band, never a capability band
})

// 2. Mint the §9.3(b) resolver-bound endpoint (signed as config.writerKey),
//    naming the consent standing on the binding:
const { endpointIdLabel } = await mintEnforcementEndpoint(config, {
  platformDid: "did:ocss:notflix",
  childRef: "child:<census-child-uuid>",
  standingRef: consent.standingRef,        // "consent:attestation:<key>"
})

// 3. Deliver the batch to the platform's connect receiver, sender-DID-signed
//    (EXT-01 §3.6 — zero shared secret; `state` is the platform-minted principal
//    ref, e.g. its OAuth access token from the parent's authorize-approve):
await provisionProfiles(config, "did:ocss:notflix", {
  state: platformAccessToken,
  children: [{ endpoint_id_label: endpointIdLabel, age_band: "13_15", display_hint: "Nia" }],
  auth: { mode: "signed" },
})

Rules then live on the child's policy (the census compiles the served enforcement profile from the policy's rules; the binding only routes the platform's pull): write them with directive(...) under a grant, or directly via the rule-write API citing consent.standingRef as standing_ref.

Parent sessions (the ceremony's auth binding)

The parent authenticates with your app's own auth — Phosra never sees parent credentials. What @phosra/link needs is a trustworthy binding between your authenticated parent session and the OAuth ceremony:

  • Verified mode (recommended): set parentSessionSecret in LinkConfig. After your login succeeds, issue a token with issueParentSession(secret, { parentId }) (e.g. as an HttpOnly cookie) and pass it as parentSessionRef to initPlatformOAuth / completePlatformOAuth / bindProfile. The SDK verifies it (HMAC + expiry, fail closed) and binds the ceremony to the verified session id — an expired login cannot start or finish a ceremony, and one parent's state can never be completed by another parent's session.
  • BYO mode: leave parentSessionSecret unset and pass your own server-side session identifier as parentSessionRef. Contract: derive it server-side from your authenticated session; NEVER accept it from the client.

See examples/reference-bff/ for the full working wiring.

Receiving sealed harm signals (EXT-03, the F6 lane)

The parent app pulls its sealed harm excerpts from the census over the documented §8.3.9 recipient-pull (GET /api/v1/harm-context — receiver-scoped, sealed_payload served byte-verbatim) and decrypts them client-side with its own EC P-256 payload key. The census/router never holds that key (the §3A.3 router-blind invariant).

import { harmContextReadiness, receiveHarmContext } from "@phosra/link"

// payload_jwk prerequisite checklist + the harm_context_ready flag:
const { harm_context_ready, checklist } = harmContextReadiness(config) // LinkConfig w/ payloadJwk
if (!harm_context_ready) throw new Error(checklist.filter(c => !c.ok).map(c => c.item).join(", "))

const { signals, rejected } = await receiveHarmContext({ client, payloadJwk: config.payloadJwk! })
// signals[i].signal is one of two TYPED shapes (the bespoke sealed shape is retired):
//   kind: "harm_context" — the §3A.2 post-confirmation excerpt body
//   kind: "verdict"      — the EXT-03 harm-signal-verdict.v1, severity + harm_class
//                          validated against the §4.4 closed enums BY CITATION
// rejected[] rows failed a vocabulary rule (H7/H8/H9/H11) and were rejected WHOLE —
// out-of-vocabulary is never coerced to a near match (§4.4 rule 2, §7.1).

Post-decrypt conduct is the recipient's §4.6 duty: retention clock, purpose limitation, disposition receipt. Apparent CSAM never rides this lane in either direction — the census diverts it at the route step, and the parent-facing enum deliberately excludes it (report-and-preserve is the only path for that class).

Pricing & keys

This SDK is free and open (MIT). It performs all signing/verification locally and calls the hosted Phosra census over RFC 9421. Metered census usage requires a Phosra API keybilling is enforced server-side, never in this package. Provision a key via the Phosra developer console (docs.phosra.com) or the REST endpoint POST /api/v1/developers/orgs/{orgID}/keys.

The /protocol subpath

import { verifyDocument, verifyReceipt } from "@phosra/link/protocol"

@phosra/link/protocol is a verbatim re-export of @openchildsafety/ocss — identical object identities. It lets platform-side code verify signed documents and receipts without a separate @openchildsafety/ocss install when you already depend on this package.

Stability

This package is 0.x — live-proven but still co-evolving with the OCSS spec. Under 0.x semver, minor bumps (0.1 → 0.2) may include breaking changes with a one-minor deprecation window. Exports marked @experimental are excluded from that window.

The following test/sandbox utilities are intentionally not exported from the public barrel and are not part of the stable API: makeConfigFromEnv, deterministicTestSeed, scopeDigest, resolveProviderEntry, startExampleProvider.