docs: api-artifacts contract revision 2 (luna review F1-F5)
ci/woodpecker/pr/ci Pipeline was canceled

F1: declared route-metadata layer as complete generator input; generator
fails closed on any route lacking extractable metadata; migration of
local-DTO/inline-typed/raw-handler routes named as implementing-PR scope.
F2: coverage closed over raw framework mounts, delegated surfaces,
tier-conditional controllers, SSE, and both-direction Socket.IO events;
explicit exclusion and delegation lists.
F3: ENDPOINTS.md structured entry format with operationId links; the
no-duplication rule reattributed as new disclosed policy with a
mechanical boundary witness.
F4: witnesses added for OpenAPI 3.1 validity, family coverage in
ENDPOINTS.md, per-entry required content, fail-closed generator control,
and a defined retirement equivalence algorithm.
F5: section 8 disclosure completed (10 items); Authority paragraph
restated in the sitemap's own terms.
This commit is contained in:
fred
2026-08-26 20:02:49 -05:00
parent f891f78e7b
commit 6043b9ebff
+170 -70
View File
@@ -7,12 +7,30 @@ HTTP/WebSocket contract and `docs/API/ENDPOINTS.md` as the
human-readable endpoint, authentication, permission, and error index — human-readable endpoint, authentication, permission, and error index —
both declared, neither present (the webui-audit REPORT's prerequisite both declared, neither present (the webui-audit REPORT's prerequisite
9). `docs/SITEMAP.md` records that canonical scope requires maintainer 9). `docs/SITEMAP.md` records that canonical scope requires maintainer
approval; this contract's ratification is that approval path. Contract approval; ratification of this contract by the repository maintainer
5 (`tool-gateway-mapping.md`) §4 binds the per-operation supplies that approval for these two artifacts. Contract 5
(`tool-gateway-mapping.md`) §4 binds the per-operation
request/result/error/audit envelope; this contract binds only how the request/result/error/audit envelope; this contract binds only how the
two artifacts are produced, what they must cover, and how they are two artifacts are produced, what they must cover, and how they are
kept true. kept true.
Revision 2 (luna review F1F5): the generation model now defines its
complete input — a declared route-metadata layer every production
route must carry, with the generator failing closed on any route
lacking extractable metadata, and the migration of today's local-DTO,
inline-typed, and raw-handler routes named as implementing-PR scope
(F1). The §7.2 inventory is closed over the real surface: raw
framework mounts, delegated surfaces, conditional/tier-gated
controllers, SSE, and Socket.IO events in both directions, with an
explicit delegation/exclusion list (F2). The `ENDPOINTS.md`
no-duplication rule is reattributed as a new disclosed policy with a
structured entry format and a mechanical checker (F3). Witnesses are
added or made executable for 3.1 validity, family coverage in
`ENDPOINTS.md`, per-entry required content, and the retirement
equivalence algorithm (F4). §8 discloses every untraced binding rule,
and the SITEMAP approval claim is restated in the sitemap's own terms
(F5).
This contract binds the artifact definitions (§2), the production This contract binds the artifact definitions (§2), the production
model (§3), coverage obligations (§4), legacy migration (§5), phase model (§3), coverage obligations (§4), legacy migration (§5), phase
timing (§6), witnesses (§7), and disclosed drafting additions (§8). timing (§6), witnesses (§7), and disclosed drafting additions (§8).
@@ -24,39 +42,63 @@ documentation placement rules stay with the docs atlas
1. **The artifacts**: `docs/API/OPENAPI.yaml` and 1. **The artifacts**: `docs/API/OPENAPI.yaml` and
`docs/API/ENDPOINTS.md`, exactly as declared by `docs/API/README.md`. `docs/API/ENDPOINTS.md`, exactly as declared by `docs/API/README.md`.
2. **Coverage**: the set of Gateway HTTP routes and Socket.IO events 2. **Coverage**: the set of Gateway HTTP routes (however registered),
the artifacts describe. SSE routes, and Socket.IO events (both directions) the artifacts
describe.
3. **Drift**: any difference between an artifact and the production 3. **Drift**: any difference between an artifact and the production
surface it documents — an undocumented live route, a documented surface it documents — an undocumented live route or event, a
phantom route, or a divergent schema/auth/error description. documented phantom, or a divergent schema/auth/error description.
4. **Delegated surface**: a mounted path prefix whose request handling
is delegated wholesale to an embedded third-party engine (for
example an auth engine's own route tree): the Gateway registers the
mount; the engine defines the routes.
## 2. Artifact contract ## 2. Artifact contract
1. **`OPENAPI.yaml`** is one file, valid OpenAPI 3.1, and the canonical 1. **`OPENAPI.yaml`** is one file, valid OpenAPI 3.1 (witness §7.6),
machine-readable contract for the Gateway's HTTP surface. Socket.IO and the canonical machine-readable contract for the Gateway's HTTP
events, which OpenAPI cannot express natively, are documented in surface. Socket.IO events, which OpenAPI cannot express natively,
`ENDPOINTS.md` and referenced from the OpenAPI description block; are documented in `ENDPOINTS.md` and referenced from the OpenAPI
inventing a pseudo-path encoding for them inside `OPENAPI.yaml` is description block; inventing a pseudo-path encoding for them inside
non-conformant. `OPENAPI.yaml` is non-conformant.
2. **`ENDPOINTS.md`** is the human index: per endpoint family, the 2. **`ENDPOINTS.md`** is the human index, in a structured entry
behavior, authentication requirement, permission/authorization rule format: one entry per endpoint family, carrying (a) the family's
(naming the owning contract — contract 2 for chain authorization, behavior summary, (b) its operations referenced by `operationId`
the SOT for workspace membership), and error semantics including link into `OPENAPI.yaml` — never by restated definition, (c) the
the contract 5 §4.2 taxonomy. It links to owning contracts and to authentication requirement, (d) the permission/authorization rule
`OPENAPI.yaml`; it does not duplicate endpoint definitions (the naming the owning contract (contract 2 for chain authorization, the
`docs/API/README.md` authoring boundary). SOT for workspace membership), (e) error semantics including the
contract 5 §4.2 taxonomy, and (f) Socket.IO event entries (both
directions) for event families. `ENDPOINTS.md` MUST NOT contain
request/response schema definitions for any operation that exists
in `OPENAPI.yaml` (mechanical rule: no `requestBody`/`responses`/
schema-fragment blocks for such operations — witness §7.5). This
no-duplication rule and the entry format are new policy disclosed
in §8 (the `docs/API/README.md` boundary as written binds guide
books, not `ENDPOINTS.md` itself).
3. Both artifacts are committed repository files, reviewed in PRs like 3. Both artifacts are committed repository files, reviewed in PRs like
any contract text; neither is a build output that exists only in CI. any contract text; neither is a build output that exists only in CI.
## 3. Production model ## 3. Production model
1. **Generation (per the ruling).** `OPENAPI.yaml` is GENERATED from 1. **Generation (per the ruling).** `OPENAPI.yaml` is GENERATED from
the Gateway source (route decorators plus the shared request/result the Gateway source by a deterministic repository script whose input
DTOs of contract 5 §4.1) by a deterministic repository script; the is a **declared route-metadata layer**: every production HTTP/SSE
generated output is committed, and CI regenerates and byte-compares route carries machine-extractable metadata — route decorators plus
it (§7.1). Hand edits to `OPENAPI.yaml` are non-conformant — a typed request/response schemas (the contract 5 §4.1 shared DTOs
description that cannot be expressed from source annotations goes where the operation is a mapped tool family; declared per-route
into the annotations, or into `ENDPOINTS.md`. schemas elsewhere) and its error-code set. **The generator fails
closed:** a production route lacking complete extractable metadata
is a generation error, never a silently omitted or partially
emitted operation. Today's local-DTO, inline-typed, and
raw-handler routes therefore migrate to declared metadata in the
implementing PR — that migration is in the implementing PR's
scope, and §7.2's independent inventory is the cross-check that no
route escaped it. The generated output is committed, and CI
regenerates and byte-compares it (§7.1). Hand edits to
`OPENAPI.yaml` are non-conformant — a description that cannot be
expressed from source annotations goes into the annotations, or
into `ENDPOINTS.md`.
2. **Normative direction.** Generation documents the code; it does not 2. **Normative direction.** Generation documents the code; it does not
ratify it. The S2 contracts and their witnesses remain the ratify it. The S2 contracts and their witnesses remain the
normative gates on what the surface may be; the artifacts make the normative gates on what the surface may be; the artifacts make the
@@ -65,14 +107,25 @@ documentation placement rules stay with the docs atlas
that route's owning contract, not authority for it. that route's owning contract, not authority for it.
3. `ENDPOINTS.md` is hand-authored (its content — permission 3. `ENDPOINTS.md` is hand-authored (its content — permission
rationale, cross-contract links, event semantics — is judgment, not rationale, cross-contract links, event semantics — is judgment, not
extraction), against the §7.2 coverage witness. extraction), against the §7.2 coverage and §7.3 content witnesses.
## 4. Coverage obligations ## 4. Coverage obligations
1. Every production Gateway HTTP route appears in `OPENAPI.yaml`; every 1. **Closure over the real surface.** Coverage extends to every
route family appears in `ENDPOINTS.md`. Test-only and production route however registered: framework-decorated
development-only surfaces are excluded and the exclusion list is controllers and gateways AND raw framework mounts registered
explicit in the generation script, not implicit. outside them (the bootstrap's own route/hook registrations), SSE
routes, and conditionally registered (deployment-tier-gated)
controllers — documented in the union, each conditional route
marked with its condition. **Delegated surfaces** (§1.4) are
documented as delegated-surface entries naming the mount, the
delegating engine, and that engine's own contract — not
re-documented route-by-route. **Socket.IO events are covered in
both directions:** subscribed (inbound handler) events and
server-emitted events. Test-only and development-only surfaces are
excluded via an exclusion list that is explicit in the generation
script and enumerated in `ENDPOINTS.md`, never implicit. The
exclusion and delegation lists are new policy disclosed in §8.
2. Every documented operation carries: its authentication requirement; 2. Every documented operation carries: its authentication requirement;
its authorization rule by reference to the owning contract; its its authorization rule by reference to the owning contract; its
error responses drawn from the contract 5 §4.2 closed taxonomy. error responses drawn from the contract 5 §4.2 closed taxonomy.
@@ -83,7 +136,7 @@ documentation placement rules stay with the docs atlas
choice. choice.
3. New surface ships documented: a PR that adds or changes a Gateway 3. New surface ships documented: a PR that adds or changes a Gateway
route or event lands with the regenerated `OPENAPI.yaml` and any route or event lands with the regenerated `OPENAPI.yaml` and any
needed `ENDPOINTS.md` row in the same PR, enforced by the §7.1 needed `ENDPOINTS.md` entry in the same PR, enforced by the §7.1
drift gate — there is no "docs to follow" state. drift gate — there is no "docs to follow" state.
## 5. Legacy migration ## 5. Legacy migration
@@ -93,23 +146,28 @@ documentation placement rules stay with the docs atlas
demonstrably covers it: the `docs/API/README.md` retirement rule demonstrably covers it: the `docs/API/README.md` retirement rule
(verify paths, schemas, authentication, permissions, error (verify paths, schemas, authentication, permissions, error
behavior, and generated/client references) is binding, witnessed by behavior, and generated/client references) is binding, witnessed by
§7.4. §7.4's equivalence algorithm.
2. Retirement is deletion in a reviewed PR after the §7.4 witness 2. Retirement is deletion in a reviewed PR after the §7.4 witness
passes; until then no consumer may treat the legacy artifact as passes; until then no consumer may treat the legacy artifact as
canonical for anything beyond its own 17 paths. canonical for anything beyond its own 17 paths. (The
deletion-in-reviewed-PR form and the interim-consumer restriction
are disclosed in §8.)
## 6. Phase timing ## 6. Phase timing
1. The artifacts and the generation script are produced by an 1. The artifacts, the metadata migration (§3.1), and the generation
implementing PR after this contract is ratified; they are S4-phase script are produced by an implementing PR after this contract is
platform work, not part of any S2 ruling PR. ratified; they are S4-phase platform work, not part of any S2
ruling PR.
2. From the first commit of `OPENAPI.yaml` onward, the §7.1 drift gate 2. From the first commit of `OPENAPI.yaml` onward, the §7.1 drift gate
is a required CI check on the integration trunk; the §4.3 is a required CI check on the integration trunk; the §4.3
same-PR rule binds every subsequent surface-changing PR. same-PR rule binds every subsequent surface-changing PR.
3. The build-first tool families (A5 ranks, contracts 13, 5, 8) are 3. The build-first tool families (A5 ranks, contracts 13, 5, 8) are
documented as they land, under the same rule — the roll-up query, documented as they land, under the same rule — the roll-up query,
for example, ships with its OpenAPI operation and its for example, ships with its OpenAPI operation and its
`ENDPOINTS.md` row in its implementing PR. `ENDPOINTS.md` entry in its implementing PR.
4. The phase placement and rollout sequencing in this section are
disclosed in §8.
## 7. Verification requirements ## 7. Verification requirements
@@ -119,51 +177,93 @@ scanned source roots, and compared files.
1. **Drift witness:** CI regenerates `OPENAPI.yaml` with the 1. **Drift witness:** CI regenerates `OPENAPI.yaml` with the
repository script and fails on any byte difference from the repository script and fails on any byte difference from the
committed file; the witness proves it can fail by a control run committed file; the witness proves it can fail by a control run
against a mutated copy. against a mutated copy. A second control proves the generator's
2. **Coverage witness:** an independent route inventory (static fail-closed rule (§3.1): a fixture route stripped of its metadata
enumeration of Gateway controllers and gateways over `apps/`, makes generation fail, not emit a partial document.
production code, tests excluded — the A5 §1.2 inventory style) 2. **Coverage witness:** an independent surface inventory — static
equals the documented path set in both directions: no undocumented enumeration over `apps/` production code, tests excluded (the A5
live route, no documented phantom. Socket.IO events are inventoried §1.2 inventory style), covering framework-decorated controllers
the same way against `ENDPOINTS.md`. and gateways, raw mount/hook registrations in the bootstrap
3. **Taxonomy witness:** every error response documented in path, SSE routes, conditional registrations (evaluated per
`OPENAPI.yaml` uses a code from the contract 5 §4.2 closed enums, deployment profile and unioned), and delegated-surface mounts —
and each family's documented codes exactly match the enum in the equals the documented set in both directions: no undocumented live
shared types package; where the no-oracle rule applies, the route, no documented phantom, each conditional route carrying its
documented refusal and not-found responses are identical in code, condition, each delegated surface present as a delegated-surface
status, and shape. entry. Socket.IO events are inventoried in both directions —
inbound subscription handlers by handler scan, server-emitted
events by emit-call scan over production code — and compared to
`ENDPOINTS.md`'s event entries in both directions. Additionally,
every HTTP route family in `OPENAPI.yaml` has an `ENDPOINTS.md`
entry, and every `ENDPOINTS.md` operation reference resolves to an
existing `operationId` — both directions, mechanical.
3. **Content and taxonomy witness:** every `ENDPOINTS.md` entry
carries the §2.2 required fields — behavior, operation links,
authentication requirement, owning-contract link, error semantics
— presence-checked mechanically against the structured entry
format; every error response documented in `OPENAPI.yaml` uses a
code from the contract 5 §4.2 closed enums, and each family's
documented codes exactly match the enum in the shared types
package; where the no-oracle rule applies, the documented refusal
and not-found responses are identical in code, status, and shape.
4. **Retirement witness:** before `docs/openapi-tess.yaml` is deleted, 4. **Retirement witness:** before `docs/openapi-tess.yaml` is deleted,
an automated comparison proves each of its 17 paths is covered by an automated comparison proves each of its 17 paths is covered by
`OPENAPI.yaml` with equivalent schemas, auth, permissions, and `OPENAPI.yaml` under a defined equivalence algorithm: both
error behavior, and a repository-wide reference scan shows no documents canonicalized (references dereferenced, keys sorted),
then per path — structural schema equality, security/authentication
requirement equality, and documented error-code set equality —
with permissions compared against the covering `ENDPOINTS.md`
entries, and the comparison emitting the exact per-path
differences on failure. A repository-wide reference scan shows no
remaining consumer (including generated clients) resolves the remaining consumer (including generated clients) resolves the
legacy file. legacy file.
5. **Boundary witness:** `ENDPOINTS.md` contains no endpoint 5. **Boundary witness:** `ENDPOINTS.md` contains no schema definition
definition duplicated from `OPENAPI.yaml` (machine-checkable: for any operation that exists in `OPENAPI.yaml` — mechanically: no
no path+verb table row whose content restates the generated `requestBody`/`responses`/schema-fragment block attached to a
operation instead of linking it), per the `docs/API/README.md` linked operation, and every operation mention is an `operationId`
authoring boundary. link (§2.2's structured format makes this checkable); the witness
proves it can fail by a control run against a mutated copy
containing an inline schema block.
6. **Validity witness:** `OPENAPI.yaml` parses and validates as
OpenAPI 3.1 under a named validator run in CI; the witness proves
it can fail by a control run against an invalidated copy.
## 8. Drafting additions (PRD §12.1 disclosure) ## 8. Drafting additions (PRD §12.1 disclosure)
The two artifacts, their roles, the single-boundary rule, and the The two artifacts, their roles, and the retirement verification
legacy retirement conditions are traced to `docs/API/README.md` and dimensions are traced to `docs/API/README.md` and `docs/SITEMAP.md`.
`docs/SITEMAP.md`. Proposed drafting additions, visible here for Proposed drafting additions, visible here for ratification, each
ratification, each severable: severable:
1. The generated-with-committed-output production model and CI drift 1. The generated-with-committed-output production model, the declared
gate (§3.1, §7.1) — the ruling below. route-metadata layer with its fail-closed generator, the metadata
migration scope, and the CI drift gate (§3.1, §7.1) — the ruling
below.
2. The same-PR documentation rule for surface changes (§4.3). 2. The same-PR documentation rule for surface changes (§4.3).
3. The explicit exclusion list for test/development surfaces (§4.1). 3. The explicit exclusion list and the delegated-surface
documentation form (§4.1).
4. The Socket.IO placement rule (events in `ENDPOINTS.md`, no 4. The Socket.IO placement rule (events in `ENDPOINTS.md`, no
pseudo-paths) (§2.1). pseudo-paths) and the both-direction event coverage (§2.1, §4.1).
5. The no-oracle documentation requirement (§4.2). 5. The no-oracle documentation requirement (§4.2).
6. The `ENDPOINTS.md` structured entry format and its no-duplication
rule with the mechanical boundary witness (§2.2, §7.5).
7. The committed-repository-file rule — neither artifact exists only
in CI (§2.3).
8. The normative-direction rule — generation documents, never
ratifies (§3.2).
9. The retirement deletion-in-reviewed-PR form and the
interim-consumer restriction (§5.2), and the §7.4 equivalence
algorithm.
10. The §6 phase placement: implementing-PR-after-ratification, the
drift gate as a required trunk check from first commit, and the
build-first documentation sequencing.
## Ruling request ## Ruling request
Ruling requested (one decision): shall `OPENAPI.yaml` be generated Ruling requested (one decision): shall `OPENAPI.yaml` be generated
from Gateway source with a committed output and a CI drift gate from Gateway source through a declared, fail-closed route-metadata
(recommended — the 45-controller surface already exists, so layer with a committed output and a CI drift gate (recommended — the
generation is the only route that starts true and stays true) — or 45-controller surface already exists, so generation is the only route
hand-authored contract-first, with code conformance to the that starts true and stays true, and fail-closed metadata makes
hand-written contract enforced by witnesses instead? incompleteness a build error) — or hand-authored contract-first, with
code conformance to the hand-written contract enforced by witnesses
instead?