Runnable. Every version string and status below was captured live from
https://phosra-api-sandbox-production.up.railway.app on 2026-07-06.The four layers
| Layer | Where you see it | Today’s value | Changes when |
|---|---|---|---|
| API version | URL path /api/v1/… | v1 | A breaking API change → a new path (/api/v2); v1 keeps serving |
| OCSS spec version | ocss_version in the trust list; OCSS-Spec-Version request header | OCSS-v1.0-pre | The protocol itself revs |
| Annex B edition | /api/v1/annex-b/editions/{n} | (pre-Edition-1) | The steward freezes a new numbered edition |
| SDK | your package.json | semver, e.g. @phosra/sdk@0.1.0 | Normal library releases; pin exact |
API version — it is in the path
The major version is the first path segment. Everything under/api/v1 shares one
contract, and additions inside v1 are backward-compatible. A future breaking
change gets a new path — v1 is never mutated under you.
curl
What “backward-compatible additions” means inside
v1: we may add new
endpoints, new optional request fields, and new response fields or enum
values. Write clients that ignore unknown fields and do not break on a new
enum value — that is the whole forward-compatibility contract.OCSS spec version
The protocol carried over the API has its own version,OCSS-v1.0-pre. You can read
the census’s binding of it directly from the (unmetered, unauthenticated) trust list:
curl
Output
OCSS-Spec-Version request header (covered by your RFC 9421 signature).
Send OCSS-v1.0-pre; the census pins its own side via ocss_version, so a mismatch
is detectable rather than silent.
Dated artifacts — Annex B editions
Governed content (the rule registry, statute mappings) is published as frozen, numbered Annex B editions. An edition is content-addressed and immutable: once editionN is cut, its bytes never change, and its ETag is the artifact hash. Pin
to an edition number and you have pinned to exact bytes forever.
curl
A
404 on an edition number means that edition is not yet frozen — every
number returns 404 before Edition 1 is cut. It is a clean not-found, never a
substitution to a nearby edition. Rule slugs reference their registry edition
inline as ocss-rules/<edition>#<slug>, so a stored rule always names the exact
edition it was written against.Conditional reads and caching
Discovery artifacts (the trust list, profiles, editions) return a strongETag and
Cache-Control: public, max-age=300. Send the ETag back as If-None-Match to get
an empty 304 when nothing moved — free, and it does not count against your
rate limit.
curl
issue.number means the census re-issued:
curl
SDK versioning — pin exact
The published SDKs follow semver. Pin the exact version you tested against and bump deliberately; do not float on a caret range in production.| Package | Latest | Pin |
|---|---|---|
@phosra/sdk | 0.1.0 | "@phosra/sdk": "0.1.0" |
@phosra/link | 0.1.2 | "@phosra/link": "0.1.2" |
@phosra/mcp | 0.4.0 | "@phosra/mcp": "0.4.0" |
@openchildsafety/ocss (protocol/signing) | 0.1.3 | "@openchildsafety/ocss": "0.1.3" |
npm
Staying forward-compatible
Ignore unknown fields
New response fields and enum values arrive inside
v1. Deserialize leniently;
never fail on a field you did not expect.Pin dated artifacts by number
Reference Annex B editions by number and verify the
ETag. Frozen bytes never
move under you.Pin the SDK exact
Test against a specific version, pin it, and bump on purpose after reading the
changelog.
Watch the issue serial
Poll the trust list with
If-None-Match; act only when issue.number climbs.Next steps
Deprecation & sunset policy
The lifecycle before anything can change — advance-notice windows, the
Deprecation/Sunset headers, and how to migrate.Changelog
What shipped, when — including SDK releases and platform conventions.
Forward compatibility (OCSS)
How the protocol itself stays additive across editions.