Before a platform can run the connect ceremony it needs a provider counterparty: a DID that
is on the Trust List, active, and reachable. GET /api/v1/directory is the public browse index
for exactly that — “who is registered, in what role, with what capabilities, and does it have a
sealed-classify enclave I can connect to.”
The directory is an index, not a key gate. It serves booleans and pointers only —
has_payload_key, an enclave marker, the Trust-List path. Actual key material is resolved
from the one root-signed /.well-known/ocss/trust-list document (§11.9 / §4.2 cl.2), verified
offline against your pinned root X. The directory never returns a public key.
GET /api/v1/directory
Public, unauthenticated read. No phosra_ key, no signature.
Query parameters (all optional):
| Param | Meaning |
|---|
role=<r> | Keep entries whose Trust-List entry_role equals <r>. role=routing matches the default (empty) role. Vocabulary: classifier-accredited, verifying-agency, enforcement-agent, independent-advocate, routing. |
capability=<c> | Keep entries that declare §5.3 manifest cell <c> as enforce or alert_only on at least one OS (e.g. capability=addictive_pattern_block). |
status=all | Include non-active entries (default: active only). |
200 response:
{
"trust_list": "/.well-known/ocss/trust-list",
"issue_number": 57,
"issued_at": "2026-07-03T13:10:45Z",
"entries": [
{
"entity": "Loopline (OCSS reference emitter)",
"did": "did:ocss:loopline",
"role": "",
"tier": "verified",
"status": "active",
"jurisdiction": [],
"valid_through": "2026-12-30T13:10:45Z",
"capabilities": [],
"has_payload_key": true,
"enclave": {
"enclave_id": "01f05283-…",
"endpoint_url": "…",
"mode": "standin",
"attested": false
}
}
]
}
| Field | Meaning |
|---|
did | The counterparty DID you pass to the connect-config lookup below. |
role | Trust-List entry_role (empty = a routing entry). |
tier | provisional | verified | accredited (§3.6 ladder). |
has_payload_key | true ⇒ the DID publishes an encryption JWK on its Trust-List entry, so you can seal a payload to it once you resolve its JWKS from the signed list. |
enclave | Present when the DID has an active sealed-classify enclave registered — the “there is a connectable classify counterparty here” marker. attested reflects live attestation (a stored-but-expired attestation reads false). |
capabilities | Union of §5.3 manifest cells the entry declares enforce/alert_only. Empty until the provider declares a capability manifest (a §5.3 accreditation-time step), so a freshly self-registered sandbox provider is listed and connectable but not yet filterable by ?capability=. |
role and capabilities are accreditation-declared metadata. A provider that has not yet
declared an entry_role or a §5.3 capability manifest still appears in the unfiltered listing
and is still connectable — it just won’t match a ?role= / ?capability= filter. In sandbox,
most reference providers ship without those declarations, so enumerate unfiltered and select
on the enclave marker (and a 200 from the connect-config lookup below) rather than relying on
the facet filters.
Recipe — find a connectable provider
const CENSUS = "https://phosra-api-sandbox-production.up.railway.app"
// 1. Browse the directory (unfiltered — see the warning above).
const dir = await (await fetch(`${CENSUS}/api/v1/directory`)).json()
// 2. Candidates = active entries that advertise a sealed-classify enclave.
const candidates = dir.entries.filter((e) => e.enclave)
// 3. Resolve HOW to reach one: the connect-config lookup.
// 200 → connectable (returns authorize_url/token_url/profiles_url).
// 404 → on the Trust List but no connect config registered yet (skip it).
for (const c of candidates) {
const res = await fetch(
`${CENSUS}/api/v1/providers/${encodeURIComponent(c.did)}/connect`
)
if (res.ok) {
const cfg = await res.json() // { authorize_url, token_url, profiles_url, scopes, name }
// feed cfg into the connect ceremony (initPlatformOAuth)
break
}
}
GET /api/v1/providers/{did}/connect is the companion lookup — it returns the OAuth
authorize_url / token_url / profiles_url the ceremony needs. See
Get provider connect config for its full contract (and the
deliberate 404 for an unknown, revoked, or connect-config-less DID — no existence leak).
Next