ADR 0001 — The support catalog is rendered, never restated
- Status: accepted
- Date: 2026-08-18
- Scope:
putnami.dev(sites/putnami.dev)
Context
A support status is a public promise: it tells a reader whether they can depend
on a package today. The workspace root holds exactly one reviewed authority for
those promises, putnami.support.json, and protocols/support is explicit that
a generated view must point back at that file instead of becoming a second
inventory.
The site was doing the opposite. src/lib/tools.ts carried a hand-written
status on each documented surface, and the docs hub rendered it as a badge.
That list had already drifted in two ways that a reader could not detect:
- the tooling surface was published as
evolving, a token the support protocol does not accept as a wire value at all, while the reviewed catalog classifies@putnami/cliasstable; - the catalog's 80 reviewed entries had no published representation anywhere, so a visitor asking "is this stable?" had no answer short of reading the repository.
Drift here is worse than a stale sentence. Publishing preview for something
the catalog calls stable understates a commitment; publishing stable for
something reviewed as experimental invents one.
Decision
The reviewed catalog is the site's only source of support statuses.
/docs/support is a generated page. src/plugins/support-catalog.plugin.ts
reads putnami.support.json at the workspace root and renders every classified
package and protocol, with the independent default and parity claims for the
subjects that carry them. The page is never committed, and it is a pure function
of the catalog bytes, so repeated builds produce identical output.
The reader is strict. Only the three reviewed statuses parse; a token like
beta or evolving, a protocolVersion other than the exact integer 1, a
repeated (kind, id), or an experimental subject that also claims to be
default-on fails the build. Publishing a page that silently omits reviewed
statuses would understate a public commitment, which is worse than not building.
src/lib/tools.ts names the catalog subject for each documented surface —
supportSubject — and never restates its value. Statuses are resolved
server-side, in src/app/docs/loader.ts, which keeps tools.ts client-safe for
the islands that import it. A surface the catalog deliberately does not classify
carries supportSubject: null and renders no badge.
The managed platform is such a surface. The support protocol classifies
packages, protocols, and features — things a user depends on — not services
Putnami operates, so neither the platform surface nor the two site projects in
sites/ gets an invented classification.
The generated page is written before static paths are enumerated, from the same callback that materializes content bundles, so a cold build and a warm build publish the same page set and the same route digest.
Rejected alternatives
- Keep the hand-written list and add a test that compares it to the catalog. The test would prevent drift, but the second inventory would remain: every new classification would need two edits, and the page would still show only the five surfaces the site happens to document rather than the reviewed catalog.
- Import
putnami.support.jsondirectly from the client-safe module. It would reach outside the project root through a bundler-resolved relative import, and it would pull the whole catalog into the browser bundle to render five badges. - Commit the generated page under
doc/. It would then be generated output under review, drifting the moment a classification changed without a rebuild — the exact failure this ADR exists to prevent. - Write the page into the source
public/docsmirror as well. The statics plugin declares routes from the sourcepublic/folder and the public-surface plugin declares the generated copies; both declaring the same path fails the route inventory withhttp_routes.duplicate_route. - Invent a
sitesupport kind so the two site projects appear in the catalog. That is a wire-contract change to a closed vocabulary, made to satisfy a checklist rather than a consumer, and it would turn a promise about dependable artifacts into a promise about hosted services. - Tolerate an unparseable catalog and publish what could be read. A partial table reads as a complete one; a missing row is indistinguishable from "not supported".
Consequences
- Adding, removing, or reclassifying an entry in
putnami.support.jsonchanges a published page with no site edit. That is the point, and it also means a careless catalog edit is immediately public. - The catalog participates in this project's generate cache key, so a classification change invalidates the site build. Without it the page would serve a stale promise from cache.
- A malformed catalog now breaks the site build, not just the support protocol's own gate. That is a deliberate second consumer of the same strictness.
- Surfaces the catalog does not classify render no badge. A future reviewer who wants a badge there must get the subject classified rather than edit the site.
- The status vocabulary on this site is closed at three values. Presenting a fourth would require a support-protocol version bump first.