From f9885133007d7b0223839ecf89f2cb878fd2752b Mon Sep 17 00:00:00 2001 From: fred Date: Wed, 26 Aug 2026 22:22:34 -0500 Subject: [PATCH] docs: api-artifacts contract revision 8 (luna r7 residuals F1/F2/NF1/NF2 + NF7) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - §7.7(d)(2): execution-pipeline attribution — framework interception components attach to framework-routed routes only; adapter hook-chain components attributed by dispatch predicate; raw-mounted routes never carry framework-component statuses (phantom rejection + raw-hook control) (F1) - §7.2: method-partition exhaustiveness — acceptance/refusal path classification; forwarding complement or unguarded branch fails; declared external method contract for non-production forwarding edges (F2, NF2) - §7.7(d)(5): exhaustive default inventory — total classification over pinned options-type keys plus configured composition-root options; unclassified key fails; bodyLimit migration example (NF1) - §2.2/§7.5: three entry kinds; Delegated:/Excluded: exact sub-item syntax mirroring §4.4 allowlist and §4.1 exclusion list; revised (k) kind-partition rule; new (l) exclusion mirror; twelve reject rules (NF7) --- docs/requirements/api-artifacts.md | 246 +++++++++++++++++++++++++---- 1 file changed, 212 insertions(+), 34 deletions(-) diff --git a/docs/requirements/api-artifacts.md b/docs/requirements/api-artifacts.md index 1286553f..24d2a156 100644 --- a/docs/requirements/api-artifacts.md +++ b/docs/requirements/api-artifacts.md @@ -159,6 +159,34 @@ pinned-version citation plus a runtime probe (NF1). §2.2 requires every family to have a non-empty surface, rejected by a new §7.5 rule (NF6). +Revision 8 (luna r7 residuals F1/F2/NF1/NF2 + NF7): §7.7(d)(2) +attributes interception components to their actual execution +pipeline — framework components (all four binding scopes) attach to +framework-routed routes ONLY, adapter-level hooks attach to exactly +the routes their dispatch predicate accepts, and a raw-mounted route +(dispatched by a hook before the framework router) never carries a +framework component's status — with a raw-hook phantom control (F1). +The §7.2 raw-mount rule gains method-partition exhaustiveness: every +control-flow path is an acceptance path (pinned to one method +constant, one record), a refusal path (constant-status refusal, no +forwarding — the only place a complement or unguarded test is +admissible), or a scan failure; a forwarding edge into a +non-production package escapes failure only through a declared +external method contract, which then defines the branch's record set +(F2, NF2). The §7.7(d)(5) default rule becomes an exhaustive +inventory: total emitting/non-emitting classification over every +option key of the pinned framework and adapter options types plus +every configured composition-root option, an unclassified key a +witness failure (the adapter body-size limit is the migration +example), citation-plus-probe per emitting entry (NF1). §2.2 defines +three entry kinds — surface, delegated-surface (`Delegated:` with +exact four-sub-item syntax mirroring the §4.4 allowlist), and +exclusion (`Excluded:` with exact per-route sub-item syntax +mirroring the §4.1 script list) — so non-surface entries are +grammatical without phantom operations; §7.5(k) becomes the +kind-partition rule and new rule (l) checks the exclusion mirror +(NF7). + This contract binds the artifact definitions (§2), the production model (§3), coverage obligations (§4), legacy migration (§5), phase timing (§6), witnesses (§7), and disclosed drafting additions (§8). @@ -295,17 +323,30 @@ documentation placement rules stay with the docs atlas heading whose text is the endpoint family name (unique in the file), followed by a bullet list whose items begin with exactly one of the literal field labels `Summary:`, `Operations:`, - `Auth:`, `Permissions:`, `Errors:`, `Events:` — each label at most - once per entry; `Summary:`, `Auth:`, `Permissions:`, and - `Errors:` REQUIRED in every entry; `Operations:` REQUIRED for a + `Auth:`, `Permissions:`, `Errors:`, `Events:`, `Delegated:`, + `Excluded:` — each label at most once per entry. **Entry + kinds**: every entry is exactly one of three kinds, decided by + its labels. A **surface entry** carries `Summary:`, `Auth:`, + `Permissions:`, and `Errors:` (REQUIRED) and neither + `Delegated:` nor `Excluded:`; within a surface entry, + `Operations:` is REQUIRED for a family with at least one `OPENAPI.yaml` operation and ABSENT for an **event-only family** (a family whose entire surface is Socket.IO events — such a family MUST carry `Events:`, which is - how it satisfies the grammar with no operations to link); - `Events:` REQUIRED for a family with Socket.IO events and absent - otherwise. **Non-empty surface**: every entry carries at least + how it satisfies the grammar with no operations to link), and + `Events:` is REQUIRED for a family with Socket.IO events and + absent otherwise. A **delegated-surface entry** carries exactly + `Summary:` and `Delegated:` and no other label. An **exclusion + entry** carries exactly `Summary:` and `Excluded:` and no + other label, and the file contains at most one exclusion entry + (absent when the §4.1 exclusion list is empty). **Non-empty + surface**: every surface entry carries at least one of `Operations:` or `Events:` — a family with neither - documents nothing and is not grammatical (reject rule §7.5(k)), + documents nothing; a delegated-surface or exclusion entry + documents its surface through `Delegated:`/`Excluded:` + instead, needing no phantom operation. An entry matching no + kind, or more than one, is not grammatical (reject rule + §7.5(k)), so a stale zero-surface family cannot survive the grammar. Field contents: `Summary:` — the family's behavior summary, free prose; `Operations:` — one or more Markdown links, each with link @@ -325,7 +366,19 @@ documentation placement rules stay with the docs atlas where `{event-name}` is a member of the §4.6 event registry, the item appears in exactly the entry of the family the §4.6 ownership map assigns to that event, and each (direction, name) - pair appears at most once in the whole file. + pair appears at most once in the whole file; `Delegated:` — + exactly four bullet sub-items, each exactly one of + `prefix {mount-prefix}`, `engine {package-name} +{version-constraint}`, `contract {engine-contract-reference}`, + and `module {registering-module}` (each sub-item label exactly + once), whose values mirror one §4.4 allowlist entry + field-by-field (string equality after whitespace trimming — + the §4.4 mirror rule, reject rule §7.5(g)); `Excluded:` — one + bullet sub-item per excluded route, each exactly + `{HTTP-method} {path-template} {reason-class} {guard}` where + `{reason-class}` is `test-only` or `dev-only`, mirroring the + §4.1 generation-script exclusion list field-by-field under the + same string equality (reject rule §7.5(l)). `ENDPOINTS.md` MUST NOT contain request/response schema definitions for any operation that exists in `OPENAPI.yaml` (mechanical rule: the reserved tokens @@ -390,13 +443,15 @@ documentation placement rules stay with the docs atlas 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 + documented as delegated-surface entries (the §2.2 entry kind, + `Delegated:` field) 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 + script and enumerated in `ENDPOINTS.md` (the §2.2 exclusion + entry, one `Excluded:` sub-item per route), never implicit. The list has a **closed, machine-checked eligibility rule**: each entry names the route, its reason class (`test-only` or `dev-only`), and the exact guard — the deployment-profile branch @@ -592,7 +647,38 @@ scanned source roots, and compared files. accepts a longer non-boundary URL (a bare prefix test accepting `/mcpfoo` under the prefix `/mcp`) is a scan failure naming the site: the code is corrected to a boundary test; the widened - match is never absorbed by documentation. For path-bearing sites, the effective + match is never absorbed by documentation. + **Method-partition exhaustiveness**: enumerating constant + method comparisons is necessary but not sufficient — the + checker proves the callback's dispatch partitions its control + flow. Every path from callback entry to a request-terminating + action (a response emission or a forwarding of the request) is + classified as exactly one of: (i) an **acceptance path** — + dominated by positive equality tests of the request method + against string constants that pin the path to exactly one + method; that (prefix, method) pair carries a record; (ii) a + **refusal path** — the ONLY classification where a complement + test (`method !== X`) or an unguarded path is admissible: the + path terminates in a constant-status refusal emission (by the + §7.7(d)(4) emission-site rules) and forwards the request + nowhere; or (iii) a **scan failure** — a complement-guarded or + unguarded path that forwards the request (into a handler, + another dispatcher, or any package) accepts an unbounded + method set and fails naming the site. One carve-out mirrors + the §7.7(d)(4) delegated-emission rule: a forwarding edge into + a non-production package may instead carry a **declared + external method contract** — the accepted-method set the + external package's pinned version documents for that entry + point, declared alongside the edge's external status + contract; the branch then contributes exactly one + (prefix × method) record per documented method, the branch's + record set equal to the declared set in both directions, and a + forwarding edge with neither dominating single-method tests + nor a declared method contract is a scan failure naming the + edge (the live MCP existing-session path, which forwards + requests of any method into the external transport, is the + migration example; its sibling non-`POST` complement branch + must classify as a refusal path). For path-bearing sites, the effective path is computed by the framework's composition rules before comparison: the class-level prefix (a string or an array — an array expands to one route per element) concatenated with the @@ -614,7 +700,13 @@ handler)`, a computed decorator value) is a scan FAILURE naming raw-mount method branch with no matching record fails; a raw-mount record no branch accepts fails; a non-constant method comparison fails; a non-boundary prefix predicate — accepting - `/mcpfoo` under `/mcp` — fails). The inventory equals the documented set in both + `/mcpfoo` under `/mcp` — fails; a complement method branch that + forwards the request fails; a complement branch terminating in + a constant-status refusal is admitted as a refusal path; a + forwarding edge with a declared external method contract + yields exactly the contract's records; a forwarding edge with + neither single-method domination nor a declared method + contract fails). The inventory equals the documented set in both directions: no undocumented live route, no documented phantom, each conditional operation carrying its §4.5 condition field, each delegated surface present exactly once. Socket.IO events are @@ -746,7 +838,7 @@ handler)`, a computed decorator value) is a scan FAILURE naming `ENDPOINTS.md` into the §2.2 entry grammar via a Markdown AST and rejects, exactly: (a) an entry violating the grammar — a non-`##` entry heading, a duplicate family name, a missing - required field label under the §2.2 conditional rule (including + required field label under the §2.2 per-kind rules (including `Operations:` absent from a family with operations, or present on an event-only family), a duplicated field label, or an `Events:` field on a non-event family; (b) an operation mention that is not @@ -763,9 +855,13 @@ handler)`, a computed decorator value) is a scan FAILURE naming item not matching the §2.2 `inbound {name}` / `outbound {name}` syntax or whose event name is not in the §4.6 registry's matching direction; (f) an `operationId` linked from more than one entry; - (g) a delegated-surface entry whose fields are not field-by-field + (g) a delegated-surface entry whose `Delegated:` sub-item + values are not field-by-field equal to the §4.4 allowlist entry (string comparison after - whitespace trimming); (h) a (direction, event-name) item appearing + whitespace trimming), a §4.4 allowlist entry with no + delegated-surface entry, a `Delegated:` prefix naming no + allowlist entry, or a malformed `Delegated:` sub-item (not the + exact §2.2 four-sub-item syntax); (h) a (direction, event-name) item appearing more than once in the file, whether within one entry or across entries; (i) an event item in an entry other than the one the §4.6 ownership map assigns to that event; (j) a §4.6 registry @@ -774,9 +870,20 @@ handler)`, a computed decorator value) is a scan FAILURE naming equal the registry union), a family name in the map with no entry in the file, or an event name present in both the inbound and outbound registries (the §4.6 disjointness rule); (k) an - entry carrying neither `Operations:` nor `Events:` (the §2.2 + entry that is not exactly one §2.2 kind — a surface entry + carrying neither `Operations:` nor `Events:` (the non-empty-surface rule — a zero-surface family documents - nothing). The witness + nothing), an entry mixing kind-defining labels (`Delegated:` + or `Excluded:` together with `Operations:`/`Events:`, or with + each other), a delegated-surface or exclusion entry carrying + any label beyond its exact §2.2 set, or a second exclusion + entry in the file; (l) an exclusion mismatch — an `Excluded:` + sub-item not field-by-field equal to a §4.1 generation-script + exclusion entry (string comparison after whitespace trimming), + a script exclusion entry with no sub-item, a sub-item with no + script entry (both directions), or a malformed sub-item (not + the exact §2.2 `{HTTP-method} {path-template} {reason-class} +{guard}` syntax). The witness proves it can fail with one control per reject rule. (Prose duplication a scanner cannot see is handled by review, but every structural duplication channel above is mechanical.) @@ -830,11 +937,39 @@ handler)`, a computed decorator value) is a scan FAILURE naming filter's mapped status — the live interaction controller's runtime-approval-denied filter emitting 403 is the migration example), attributed to exactly the routes its binding scope - covers: global to every route, controller-scoped to the - declaring class's routes, route-scoped to that route alone. A - binding site in any of the four scopes the scan does not - enumerate, and a bound component with no source-asserted - status set, are each a witness failure naming the site; (3) + covers WITHIN the component's execution pipeline. + **Execution-pipeline attribution**: the production surface + partitions into **framework-routed routes** — registered + through the framework's routing primitives (decorated + controllers/gateways and framework route registrations) and + dispatched by the framework router — and **raw-mounted + routes** — the §7.2 raw-mount records, dispatched by a hook + callback before or outside the framework router. Framework + interception components in all four binding scopes execute + only in the framework dispatch pipeline, so they attribute to + framework-routed routes ONLY: global (by call or by DI token) + to every framework-routed route, controller-scoped to the + declaring class's routes, route-scoped to that route alone; a + framework component's status attributed to a raw-mounted + route is a phantom — the component never runs for it — and + the bidirectional comparison rejects it exactly as it rejects + any other phantom map status. A raw-mounted route's + interception statuses come instead from the **adapter hook + chain**: every non-path-bearing hook registration (§7.2) + whose callback can emit a response (per the class-(4) rules + over the callback closure) is an interception component + attributed to exactly the routes whose URLs its dispatch + predicate accepts — a hook with no URL dispatch attributes to + every route, framework-routed and raw alike; a raw mount's + own dispatch attributes to its (prefix × method) records + alone (the live raw MCP hook, which answers before the + framework router runs and is therefore untouched by the + framework's global pipes and guards, is the motivating + example). A binding site in any of the four scopes the scan + does not enumerate, a bound component with no source-asserted + status set, and an emitting hook registration with no + dispatch-derived route attribution, are each a witness + failure naming the site; (3) decorator status metadata — the framework's route-level status metadata (explicit status-code decorators, each method decorator's default status, and the implicit @@ -866,16 +1001,35 @@ handler)`, a computed decorator value) is a scan FAILURE naming send-with-status calls, status-carrying error constructors) AND against Node's `http.ServerResponse` declarations (`writeHead`, `statusCode` assignment), so raw handlers are covered; (5) - framework error defaults — the framework's own route-level - default error statuses (the default unhandled-error status, the - default validation/parse-failure statuses, the default - not-found on a matched mount): each default the implementing PR - declares route-attributable carries BOTH a citation into the - pinned framework version's source or documentation for that - default AND a runtime probe that triggers the default and - asserts the observed status; a declared default missing its - citation or its probe is a witness failure — declaration alone - attributes nothing. Every site's status argument must resolve + framework and adapter defaults — an EXHAUSTIVE default + inventory, not a declared-only list: the implementing PR + classifies, as response-emitting (with the emitted status and + triggering condition) or non-emitting, every member of a + closed domain with two mechanically enumerated parts — (i) + every property key of the pinned framework + application-options type AND the pinned adapter + construction-options type, resolved from the packages' type + declarations, and (ii) every key of every options object the + composition root actually passes to the framework/adapter + construction and server-setup calls (call sites identified by + symbol identity). The classification is TOTAL: a domain key + absent from the inventory is a witness failure naming the + key, so an applicable default cannot be omitted by silence + (the adapter-level body-size limit set at the composition + root — an adapter rejection path the revision-7 declared-only + rule could silently omit — is the migration example). The + framework's documented route-level default statuses (the + default unhandled-error status, the default + validation/parse-failure statuses, the default not-found on a + matched mount) are fixed members of the inventory regardless + of configuration. Each response-emitting entry carries BOTH a + citation into the pinned version's source or documentation + for that behavior AND a runtime probe that triggers the + default and asserts the observed status; a response-emitting + entry missing its citation or its probe is a witness failure, + and each entry's status attributes to the routes the option's + scope covers (a server-wide option to every route on that + server). Every site's status argument must resolve to a literal or compile-time constant; an unresolvable status is a FAILURE naming the site. Both directions: every resolved status is a member of the route's record response map, AND @@ -888,11 +1042,21 @@ handler)`, a computed decorator value) is a scan FAILURE naming global-pipe status absent from the map fails; a route-scoped filter status absent from the map fails; a component bound through a DI binding token is detected and attributed; a + framework global component's status attributed to (or + required of) a raw-mounted fixture route fails as a phantom — + the raw-hook control; a fixture adapter hook emitting a + constant status with no URL dispatch is attributed to every + route, raw mounts included; a fixture handler passing the reply object into a stub external package with no declared external status contract fails; a decorator status absent from the map fails; a raw `writeHead` status - absent from the map fails; a phantom map status fails; the + absent from the map fails; a phantom map status fails; an + option key present in the pinned adapter options type but + absent from the default inventory fails; a configured + composition-root option key absent from the inventory fails; + the body-size-limit probe triggers the adapter rejection and + asserts its observed status; the implicit default success status is attributed to the route and must appear in its response map; (e) **guard-equivalence** — for each `ApiAuthClass`, the witness asserts the derived @@ -980,7 +1144,7 @@ severable: with its registration-primitive list, symbol-identity detection with its failure-not-skip rule, and bidirectional family/operation checks, the §7.3 content and taxonomy witness, - the §7.5 checker script with its eleven reject rules, the §7.6 + the §7.5 checker script with its twelve reject rules, the §7.6 pinned validator (Redocly CLI), the §7.7 source-consistency witness, the per-field fail-closed controls in §7.1, and the §7.4 canonicalization/derivation/ @@ -1035,6 +1199,20 @@ severable: status contract and the §7.7(d)(5) citation-plus-probe rule for framework defaults; and the §2.2 non-empty-surface rule with §7.5 reject rule (k). +19. The revision-8 closure rules: the §7.7(d)(2) + execution-pipeline attribution — framework interception + components to framework-routed routes only, adapter + hook-chain components attributed by dispatch predicate, + phantom rejection for raw-mounted routes, with the raw-hook + control; the §7.2 method-partition exhaustiveness rule with + its acceptance/refusal path classification, forwarding + complement-branch failure, and declared external method + contract; the §7.7(d)(5) exhaustive default inventory (total + classification over the pinned options-type keys and the + configured composition-root options, citation-plus-probe per + emitting entry); and the §2.2 entry kinds with the + `Delegated:`/`Excluded:` field syntax, the revised §7.5(k) + kind-partition rule, and the §7.5(l) exclusion mirror. ## Ruling request