Skip to content

finding: no gate sees rest-server.ts's response envelopes — check:route-envelope does not scan the file, and neither gate has a rule for envelope POSITION #7295

Description

@os-help

Measured while implementing #7035 (PR #7293), whose triage ruling asked to extend the error-code-casing / route-envelope gate family to cover the two non-conforming /meta 501 sites if it does not already. It does not, and extending it is not the one-rule change the dispatch hoped for — so this is filed rather than built there.

Filed unassigned, finding-class: nothing a user hits today. It is a gate gap, not a defect.

1. check:route-envelope never looks at rest-server.ts

scripts/check-route-envelope.mjs's discover() collects only files whose name ends in -routes.ts, plus the single hard-coded i18n-service-plugin.ts. packages/rest/src/rest-server.ts matches neither, so it has never been audited — while being, by a wide margin, the largest response-emitting file in the repo (#5949).

Running the gate's own exported scanSource against it by hand:

packages/rest/src/rest-server.ts {"responses":208,"ok":2,"err":0,"privateOk":0,"stringError":44}

For comparison, every module the gate does audit declares 0 / 0 / 0 — they route every body through the shared sendOk / sendError in packages/types/src/response-envelope.ts.

The gate's header states its own thesis on exactly this point: "A module discovered by the scan but absent from the table is an ERROR, not a default", and "a module nobody thought to convert still gets audited." Both were written about the discovery surface. The file with 208 hand-built write sites sits outside it.

2. Even if it were scanned, the sibling-code dialect is invisible

scanSource counts responses, ok, err, privateOk and stringError. There is no counter for a top-level code sitting as a sibling of error — which is one of the two dialects #7035 was about:

// what the gate can see:            { error: 'some message' }        → stringError
// what it cannot:                   { error: 'some message', code }  → nothing

So adding the file to the table would catch the bare-string half of #7035 and silently pass the sibling-key half.

3. check:error-code-casing scans the file, but only for casing

scripts/check-error-code-casing.mjs does walk packages/**, rest-server.ts included — but its patterns match lowercase literals in code positions (code: 'x', .code = 'x', code === 'x', union types). Position is outside its thesis, and it is textual by design; the header explains that check-route-envelope went AST precisely because textual counting of response shapes was wrong twice over. Teaching position to the textual gate would re-make that mistake.

Why this is not a small fix

Bringing rest-server.ts into check:route-envelope means entering it as a ratchet at responses: 208. That number moves whenever any of the file's ~208 write sites is added or removed, in a file that changes several times a day — so the gate would go red constantly for reasons unrelated to envelopes, and the pressure would be to raise the ratchet rather than fix anything. The gate's model — "declare zero, route everything through the shared pair" — is #7035's option 3 (a shared envelope constructor for the file), which that card's triage explicitly ruled out of scope.

So the honest options are a decision, not a patch:

  1. Convert rest-server.ts onto the shared sendOk / sendError, then declare 0 / 0 / 0 like every other module. Largest, and the only one that ends the problem. Effectively finding: rest-server.ts 里三个相邻 /meta handler 的错误信封是三种不同形状,其中两种不符合 ADR-0112 #7035 option 3 + the gate for free.
  2. Ratchet the file in as-is (responses: 208, stringError: 44) and add a siblingCode counter plus self-test cases. Cheap to write, but pins a hot number and creates recurring unrelated red.
  3. Extend discovery, but count only the error-shape facts (stringError, a new siblingCode), not responses. Stable under ordinary edits because it counts dialects rather than write sites, and it would have caught both halves of finding: rest-server.ts 里三个相邻 /meta handler 的错误信封是三种不同形状,其中两种不符合 ADR-0112 #7035. Middle-sized; needs a ratchet at 44 that only ever ticks down.

My read, from having just measured it: option 3 is the one worth costing, because it is the only one whose number does not move under unrelated edits and it covers both dialects. But this is a gate-architecture decision, not a dev call.

Not measured (do not cite as fact)

  • Whether other unscanned files have the same exposure. discover()'s -routes.ts convention was only checked against rest-server.ts here; a repo-wide census of response-emitting files outside the convention was not run.
  • The 44 stringError sites in rest-server.ts were counted, not read. How many are /meta, how many are reachable in a default deployment, and whether any consumer reads them — unmeasured.

Related

#7035 (the card this came out of; PR #7293 converged three /meta 501 sites and deliberately left the other ~44) · #5949 (rest-server.ts size) · #3877 (response bodies never checked against their declaring schemas — adjacent, but about schema validation rather than gate discovery) · ADR-0112 · ADR-0049


Generated by Claude Code

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions