Skip to content

[finding] RestApiConfig.documentation and responseFormat are normalized by RestServer and read by nothing — two more ADR-0049 candidates on the one RestServerConfig sub-object the liveness ledger does not cover #14640

Description

@claude

Blocked-by: #14366 — the api block's consumption seam is still validate-only and is about to move. #14369 left RestApiConfigSchema out of the ledger for exactly that reason: a census taken now would record a half that is changing. ⛔ Do not enrol these keys before that seam settles.

Observation from the liveness-ledger work on #14369, which enrolled four of the five RestServerConfig sub-objects and deliberately left RestApiConfigSchema (api) out. While measuring the four it enrolled, the same census was run across the api block, and two of its keys came out the same way as the ten on that card.

What was measured

On origin/main @ 2514d49f3, packages/rest/src non-test sources, every read site outside NormalizedRestServerConfig's type declaration (rest-server.ts lines 723-786) and normalizeConfig itself (3518-3616), comments excluded:

Read by the runtimeapi.version, api.basePath, api.apiPath (getApiBasePath), api.enableCrud, api.enableMetadata, api.enableUi, api.enableBatch, api.enableDiscovery, api.enableOpenApi, api.enableSearch, api.enableProjectScoping, api.projectResolution.

Normalized and never read (0 sites each) — two declared containers:

key declared as
api.documentation object: enabled / title / description / version / termsOfService / contact{name,url,email} / license{name,url}
api.responseFormat object: envelope / includeMetadata / includePagination

normalizeConfig copies both straight through into this.config.api, and nothing reads either back. Re-confirmed by triage at origin/main 4d0d944: responseFormat occurs at exactly two sites in packages/rest/src — the type declaration (rest-server.ts:738) and the copy-through (:3555) — and includeMetadata / includePagination return 0 files each.

So api.responseFormat.envelope: false does not unwrap a single response, and api.documentation.title: 'Acme API' does not retitle the served OpenAPI document — that document is the pre-generated @objectstack/spec contract enriched at request time with the live server URL and the registered objects, and it never consults this config.

⚠️ Ledger placement — the name is already taken

packages/spec/liveness/api.json exists, and it is a different api: its own header says ApiEndpointSchema (packages/spec/src/api/endpoint.zod.ts), the registered api metadata type, with consumers in the matcher, executor, policy chain and mapping layer. It has nothing to do with RestApiConfigSchema.

⛔ So "put the verdicts in the api ledger" resolves to the wrong file. A new rest_api ledger is needed, as this card says — and whoever creates it should note in its _note why it is not api.json, or the next reader repeats the mistake.

⭐ This is the same shape as #14676's userMessage collision, graded this round: one spelling, two unrelated meanings, inside packages/spec.

Not prejudged

Declared-but-unenforced is the ADR-0049 class. ⭐ The two keys differ in a way that should survive into the verdicts: documentation is customer-facing metadata an OpenAPI document plausibly should carry, so enforce is a genuine candidate and is real work in the document builder; responseFormat describes an envelope the REST layer already produces unconditionally, so its enforce route would mean making the envelope configurable — a larger claim. ⛔ Do not give them one shared verdict by default.

Related: #14369 (the ten sibling keys, ledger landed) · #14691 (the enforce-or-remove door for those, pm:queue) · #14366 (the api block's consumption seam — the blocker) · #11637 (the api block's validate-only parse).

Generated by Claude Code

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions