Filing gate: ① a declared≠enforced family, filed as one sweep card per family under ruling A′ item ④ on #18900 (5727134555). This is triage's standing request 5857165909 on the seat post. Family rest-api-documentation, seat verdict ENFORCE.
reach: the declared authoring door. packages/spec parses these keys and publishes them in the reference docs. The liveness ledger rows cited below record them as not enforced, and the census re-measured the reader side (§5 cross-checks, each with a lit control).
- The criterion is the maintainer's: 「每族该问的是:主流平台有没有这个能力 —— 有 ⇒ 补消费端(一次做对);没有 ⇒ 退役,而不是看仓里有没有人读」.
- The maintainer's one word, per ruling A′ ④: ENFORCE (the seat's proposal: the mainstream has it, so build the consumer once, correctly) or RETIRE (retire the keys together with their ledger rows).
Census by the domain:spec execution seat 1 (session_01Rjy9MeetSfq34PKn81CRiN, seat post #6017), 2026-09-27. Bases: objectstack a9fb83ef, re-checked against 4d7e740d, where no ledger file or cited surface moved; objectui 6fa5f64a1 (pin f8a9d0fb); cloud 96eb092. Ledger instrument: check-liveness.mts --json, whose byStatus equals the committed state-counts.md row for row. ⛔ Filed bare: routing and grading belong to triage. ⛔ Not a claim. The ranking is by value, user-visible risk × keys. This family's rank is 8 of 16. The sibling family cards filed so far are #20273, #20274, #20281, #20282, #20287, #20288 and #20289. Ranks 8 and 9 are the two halves of rest_api: one ENFORCE, one RETIRE.
Capability: API documentation metadata (title, description, version, terms, contact, license) in the served API description
| key |
ledger status |
ledger row |
what the ledger cites |
rest_api.documentation.title |
dead (verified 2026-09-21) |
packages/spec/liveness/rest_api.json:115 |
note: Normalized by RestServer and read by NOTHING — the ADR-0049 fourth state (parsed, unmarked, unenforced). normalizeConfig lists documentation: api.documentation straight into this.config.api and no site ever reads it back. `api.documentation.title: '… |
rest_api.documentation.description |
dead (verified 2026-09-21) |
packages/spec/liveness/rest_api.json:121 |
note: Normalized by RestServer and read by NOTHING — the ADR-0049 fourth state (parsed, unmarked, unenforced). normalizeConfig lists documentation: api.documentation straight into this.config.api and no site ever reads it back. no consumer; the served `in… |
rest_api.documentation.version |
dead (verified 2026-09-21) |
packages/spec/liveness/rest_api.json:127 |
note: Normalized by RestServer and read by NOTHING — the ADR-0049 fourth state (parsed, unmarked, unenforced). normalizeConfig lists documentation: api.documentation straight into this.config.api and no site ever reads it back. no consumer; the served `in… |
rest_api.documentation.termsOfService |
dead (verified 2026-09-21) |
packages/spec/liveness/rest_api.json:133 |
note: Normalized by RestServer and read by NOTHING — the ADR-0049 fourth state (parsed, unmarked, unenforced). normalizeConfig lists documentation: api.documentation straight into this.config.api and no site ever reads it back. no consumer, and the served… |
rest_api.documentation.contact.name |
dead (verified 2026-09-21) |
packages/spec/liveness/rest_api.json:145 |
note: The contact name an OpenAPI info.contact would carry. No consumer: the served document's info.contact is the literal { name: 'ObjectStack', url: 'https://objectstack.io' } written by packages/spec/scripts/build-openapi.ts, and rest-server.ts#registerO… |
rest_api.documentation.contact.url |
dead (verified 2026-09-21) |
packages/spec/liveness/rest_api.json:151 |
note: The contact URL an OpenAPI info.contact would carry. No consumer; the served value is the build-openapi.ts literal. Drilled rather than left riding on its container's blanket verdict, and NOT by fanning the parent's status out over its children — the call… |
rest_api.documentation.contact.email |
dead (verified 2026-09-21) |
packages/spec/liveness/rest_api.json:157 |
note: The contact email an OpenAPI info.contact would carry. No consumer, and the served document carries no info.contact.email at all — build-openapi.ts writes only name and url. Drilled rather than left riding on its container's blanket verdict, and NOT… |
rest_api.documentation.license.name |
dead (verified 2026-09-21) |
packages/spec/liveness/rest_api.json:171 |
note: The license identifier an OpenAPI info.license would carry. ⚠️ The one member of either container that is REQUIRED by its own schema (z.string(), no .optional()), so authoring a license object at all forces a value the runtime then ignores. No consu… |
rest_api.documentation.license.url |
dead (verified 2026-09-21) |
packages/spec/liveness/rest_api.json:177 |
note: The license URL an OpenAPI info.license would carry. No consumer; the served value is the Apache-2.0 literal URL from build-openapi.ts. Drilled rather than left riding on its container's blanket verdict, and NOT by fanning the parent's status out over its… |
Mainstream evidence:
- The OpenAPI
info object is the standard carrier. Azure API Management and Apigee let the API owner set it.
- ServiceNow Scripted REST APIs have a name, description and documentation per API, shown in the REST API Explorer.
- Power Platform custom connectors have a "General information" tab (description, icon, host).
- Salesforce and Dataverse publish fixed platform API docs with no admin-set info. The capability exists where the platform lets owners publish an API, which is this surface.
Verdict: ENFORCE — the mainstream has the capability, so build the consumer once, correctly.
Reader that must exist / disposition: objectstack packages/rest/src/rest-server.ts#registerOpenApiEndpoints (:4869) builds enriched from the bundled spec and overrides servers, paths and tags. It must also overlay enriched.info from this.config.api.documentation. Today normalizeConfig writes the key (:4252) and nothing reads it back.
User-visible risk (1): Developer-facing documentation text; the silent no-op is cosmetic.
Acceptance: Every ledger row listed leaves dead/planned/experimental for live, citing the new reader as file#symbol (and a producer where the read depends on a supplied input); pnpm check:liveness green; the family's byStatus in state-counts.md regenerated.
Lane: domain:spec parent + packages/rest sub-issue (objectstack)
File surface: packages/spec/src/api/rest-server.zod.ts:206-225 · packages/rest/src/rest-server.ts (normalizeConfig, registerOpenApiEndpoints) · packages/spec/liveness/rest_api.json
Dedupe: rest_api\b \| RestApiConfig \| responseFormat \| termsOfService \| documentation\.(enabled\|title\|contact\|license) \| includePagination → 1 open hit. None carries a key of this family:
四轴:
- 实际业务需求: 对外发布 API 的团队需要在文档里写上标题、版本、联系人和许可。这是 OpenAPI 的标准字段。
- 项目长远合理性: 消费端只需在已有的 OpenAPI 组装函数里加一步覆盖,把声明与产物接起来。
- 防 AI 写错: 写进去却不出现在文档里,会让 AI 以为配置位置错了而反复改写。接上之后结果可见、可测。
- 创业阶段不扩散: 一个函数里十几行,零新机制。
Unblocked by ruling 5862477514 on #20359 (B, batch #231 item 1; note 5862495365) — was blocked by #20359 from 2026-09-28T02:45Z. Execution: eight keys ENFORCE + documentation.version RETIRE, per the ruling.
Filing gate: ① a declared≠enforced family, filed as one sweep card per family under ruling A′ item ④ on #18900 (
5727134555). This is triage's standing request5857165909on the seat post. Familyrest-api-documentation, seat verdict ENFORCE.reach:the declared authoring door.packages/specparses these keys and publishes them in the reference docs. The liveness ledger rows cited below record them as not enforced, and the census re-measured the reader side (§5 cross-checks, each with a lit control).Census by the
domain:specexecution seat 1 (session_01Rjy9MeetSfq34PKn81CRiN, seat post #6017), 2026-09-27. Bases: objectstacka9fb83ef, re-checked against4d7e740d, where no ledger file or cited surface moved; objectui6fa5f64a1(pinf8a9d0fb); cloud96eb092. Ledger instrument:check-liveness.mts --json, whosebyStatusequals the committedstate-counts.mdrow for row. ⛔ Filed bare: routing and grading belong to triage. ⛔ Not a claim. The ranking is by value, user-visible risk × keys. This family's rank is8of 16. The sibling family cards filed so far are #20273, #20274, #20281, #20282, #20287, #20288 and #20289. Ranks 8 and 9 are the two halves ofrest_api: one ENFORCE, one RETIRE.Capability: API documentation metadata (title, description, version, terms, contact, license) in the served API description
rest_api.documentation.titlepackages/spec/liveness/rest_api.json:115RestServerand read by NOTHING — the ADR-0049 fourth state (parsed, unmarked, unenforced).normalizeConfiglistsdocumentation: api.documentationstraight intothis.config.apiand no site ever reads it back. `api.documentation.title: '…rest_api.documentation.descriptionpackages/spec/liveness/rest_api.json:121RestServerand read by NOTHING — the ADR-0049 fourth state (parsed, unmarked, unenforced).normalizeConfiglistsdocumentation: api.documentationstraight intothis.config.apiand no site ever reads it back. no consumer; the served `in…rest_api.documentation.versionpackages/spec/liveness/rest_api.json:127RestServerand read by NOTHING — the ADR-0049 fourth state (parsed, unmarked, unenforced).normalizeConfiglistsdocumentation: api.documentationstraight intothis.config.apiand no site ever reads it back. no consumer; the served `in…rest_api.documentation.termsOfServicepackages/spec/liveness/rest_api.json:133RestServerand read by NOTHING — the ADR-0049 fourth state (parsed, unmarked, unenforced).normalizeConfiglistsdocumentation: api.documentationstraight intothis.config.apiand no site ever reads it back. no consumer, and the served…rest_api.documentation.contact.namepackages/spec/liveness/rest_api.json:145info.contactwould carry. No consumer: the served document'sinfo.contactis the literal{ name: 'ObjectStack', url: 'https://objectstack.io' }written by packages/spec/scripts/build-openapi.ts, and rest-server.ts#registerO…rest_api.documentation.contact.urlpackages/spec/liveness/rest_api.json:151info.contactwould carry. No consumer; the served value is the build-openapi.ts literal. Drilled rather than left riding on its container's blanket verdict, and NOT by fanning the parent's status out over its children — the call…rest_api.documentation.contact.emailpackages/spec/liveness/rest_api.json:157info.contactwould carry. No consumer, and the served document carries noinfo.contact.emailat all — build-openapi.ts writes onlynameandurl. Drilled rather than left riding on its container's blanket verdict, and NOT…rest_api.documentation.license.namepackages/spec/liveness/rest_api.json:171info.licensewould carry.z.string(), no.optional()), so authoring alicenseobject at all forces a value the runtime then ignores. No consu…rest_api.documentation.license.urlpackages/spec/liveness/rest_api.json:177info.licensewould carry. No consumer; the served value is the Apache-2.0 literal URL from build-openapi.ts. Drilled rather than left riding on its container's blanket verdict, and NOT by fanning the parent's status out over its…Mainstream evidence:
infoobject is the standard carrier. Azure API Management and Apigee let the API owner set it.Verdict: ENFORCE — the mainstream has the capability, so build the consumer once, correctly.
Reader that must exist / disposition: objectstack packages/rest/src/rest-server.ts#registerOpenApiEndpoints (:4869) builds
enrichedfrom the bundled spec and overrides servers, paths and tags. It must also overlayenriched.infofromthis.config.api.documentation. Today normalizeConfig writes the key (:4252) and nothing reads it back.User-visible risk (1): Developer-facing documentation text; the silent no-op is cosmetic.
Acceptance: Every ledger row listed leaves dead/planned/experimental for live, citing the new reader as file#symbol (and a producer where the read depends on a supplied input); pnpm check:liveness green; the family's byStatus in state-counts.md regenerated.
Lane: domain:spec parent + packages/rest sub-issue (objectstack)
File surface: packages/spec/src/api/rest-server.zod.ts:206-225 · packages/rest/src/rest-server.ts (normalizeConfig, registerOpenApiEndpoints) · packages/spec/liveness/rest_api.json
Dedupe:
rest_api\b \| RestApiConfig \| responseFormat \| termsOfService \| documentation\.(enabled\|title\|contact\|license) \| includePagination→ 1 open hit. None carries a key of this family:RestApiConfigSchemain the liveness ledger asrest_api#19594rest_apiledger enrolment; carries no key四轴:
Unblocked by ruling 5862477514 on #20359 (B, batch #231 item 1; note 5862495365) — was blocked by #20359 from 2026-09-28T02:45Z. Execution: eight keys ENFORCE +
documentation.versionRETIRE, per the ruling.