|
| 1 | +--- |
| 2 | +"@objectstack/spec": minor |
| 3 | +--- |
| 4 | + |
| 5 | +feat(spec): retire `RestApiEndpoint.handlerStatus` and the Route Coverage Report shapes — declared, never read; the 501 they described comes from the endpoint executor (#13823, ADR-0049) |
| 6 | + |
| 7 | +<!-- adr-0087: registered rest-api-endpoint-handler-status-retired --> |
| 8 | + |
| 9 | +**BREAKING** accept-set narrowing and export removal, landing after the |
| 10 | +v17.0.0 cut (the lockstep launch-window convention ships it as `minor`; the |
| 11 | +prescription is registered under protocol major 18 — |
| 12 | +`RETIRED_KEYS_BY_MAJOR[18]` for the key, `RETIRED_DEFS_BY_MAJOR[18]` for the |
| 13 | +three defs, plus the D3 semantic entry |
| 14 | +`rest-api-endpoint-handler-status-retired` — where `os migrate meta` users |
| 15 | +will look). Maintainer ruling 2026-09-01 on #13823 (director decision batch |
| 16 | +#27, verbatim 「同意」): remove; enforce excluded. |
| 17 | + |
| 18 | +`handlerStatus` (`implemented` / `stub` / `planned`) was an authorable key on |
| 19 | +`RestApiEndpointSchema` whose docstring promised that a `stub` handler |
| 20 | +"returns 501 Not Implemented", and **nothing read it**. Measured at the |
| 21 | +retirement base (`origin/main` a9b2be0b0, 2026-09-02, `skills/**` and tests |
| 22 | +excluded): the only identifier hits were the declaration, its re-declaration |
| 23 | +on `RouteCoverageEntrySchema` and a docblock saying adapters SHOULD warn on |
| 24 | +it. The 501 it described has a different cause — every |
| 25 | +`DispatcherErrorCode.enum.NOT_IMPLEMENTED` site (`runtime/src/endpoint-executor.ts` |
| 26 | +×3, `runtime/src/api-mapping.ts`, `runtime/src/api-endpoint-step.ts`) is the |
| 27 | +declarative-endpoint executor refusing a target or mapping it cannot serve, |
| 28 | +and none consults the key. So an author who wrote `handlerStatus: 'stub'` |
| 29 | +expecting a 501 got an ordinarily served route, and the declaration reported |
| 30 | +progress to nobody: `RouteCoverageReportSchema`, the only shape that would |
| 31 | +have carried it outward, had zero constructors in objectstack, objectui |
| 32 | +(pinned sha) and cloud. |
| 33 | + |
| 34 | +FROM → TO: |
| 35 | + |
| 36 | +- `handlerStatus: 'implemented' | 'stub' | 'planned'` on a `RestApiEndpoint` |
| 37 | + → *(removed key)* — tombstoned with `retiredKey()` (the schema is not |
| 38 | + `.strict()`, so a bare deletion would be a silent strip): authoring it is |
| 39 | + now a `tsc` error and a parse error carrying the prescription at path |
| 40 | + `handlerStatus`, for every former value including the documented default |
| 41 | + `'implemented'` (prose only — the key never carried a Zod `.default()`, so |
| 42 | + no built artifact materialised it and there is no residue window). |
| 43 | +- `HandlerStatusSchema` / `HandlerStatus` → *(removed — no replacement)*. The |
| 44 | + enum's only two carriers leave in this same change; an exported value |
| 45 | + schema with no consumer reads as a capability (#3950). |
| 46 | +- `RouteCoverageEntrySchema` / `RouteCoverageEntry` and |
| 47 | + `RouteCoverageReportSchema` / `RouteCoverageReport` → *(removed — no |
| 48 | + replacement)*. No adapter, dispatcher or registrar ever constructed the |
| 49 | + report; it was a shape with no producer. |
| 50 | + |
| 51 | +One-line fix: delete the key — nothing served changes, because nothing ever |
| 52 | +read it. An endpoint that has no handler yet is simply not registered. Route |
| 53 | +readiness that IS measured is untouched: the discovery payload's per-service |
| 54 | +`status` / `handlerReady` (`api/discovery.zod.ts`) and the CI-asserted route |
| 55 | +ledger (`packages/runtime/src/route-ledger.ts`). A declared-but-unbuilt route |
| 56 | +answering 501 instead of 404 is a new capability the ruling explicitly |
| 57 | +excluded (zero pull); if it is ever wanted it re-declares fresh under its own |
| 58 | +ruling, executor first. |
| 59 | + |
| 60 | +The retirement kit: |
| 61 | + |
| 62 | +- key tombstone at the declaration (`api/RestApiEndpoint:handlerStatus` in |
| 63 | + `RETIRED_KEYS_BY_MAJOR[18]`; the surface baseline line carries `[RETIRED]`) |
| 64 | +- whole-def deletions `api/HandlerStatus`, `api/RouteCoverageEntry`, |
| 65 | + `api/RouteCoverageReport` in `RETIRED_DEFS_BY_MAJOR[18]` (manifest keys |
| 66 | + deliberately removed; the #4725 gate adjudicated them) |
| 67 | +- deliberately NO D2 conversion: nothing in the tree parses |
| 68 | + `RestApiEndpointSchema` outside its own unit tests — a REST API plugin route |
| 69 | + registration is not a stack collection member and never a `sys_metadata` |
| 70 | + row — so the conversion chain has no seam that would ever see one (the |
| 71 | + `kernel/Manifest:loading` disposition); the D3 semantic entry carries the |
| 72 | + prescription, and for the same reason the tombstone carries no |
| 73 | + `os migrate meta` sentence |
| 74 | +- pin tests (`api/plugin-rest-api.handler-status-retirement.test.ts`): all |
| 75 | + three former values refused at path `handlerStatus` with the prescription, |
| 76 | + through the route-registration embed too; a well-formed endpoint without the |
| 77 | + key still parses and grows no `handlerStatus` property; the shipped default |
| 78 | + route registrations still parse; zero holders for all 6 retired export names |
| 79 | + on every public entry; the carrier schemas survive; the registrations under |
| 80 | + major 18 are present |
| 81 | +- no liveness-ledger row moves: `RestApiEndpointSchema` is outside the walked |
| 82 | + population (not a registered metadata type and not in `SPEC_ONLY_SCHEMAS`), |
| 83 | + so the verdict is recorded here, in the schema and in the D3 entry |
| 84 | +- teaching sweep: `content/docs/**`, `examples/**`, `packages/*/README.md` and |
| 85 | + `packages/create-objectstack/**` carry no hand-written mention; the generated |
| 86 | + reference page regenerates. The published skill `skills/objectstack-api` |
| 87 | + taught the key at this PR's base (a9b2be0b0); `main` already dropped that |
| 88 | + teaching in the #14448 optimization flight (bae4088f3 — zero `handlerStatus` |
| 89 | + / Handler Status / RouteCoverage hits under `skills/` at 99b8faf8f, with |
| 90 | + `RestApiEndpoint` still hitting the skill as the live control), so no |
| 91 | + skills-lane follow-up is needed |
0 commit comments