Skip to content

Commit 2fc96ab

Browse files
os-litantclaude
andauthored
docs(rest-test): three production seams plus one test-only injection, not four (#12537) (#12646)
The `/api/v1/packages` direct-mount door's suite described its `SITES` table as the door's "four seams". Three of the four are production producers; the fourth, `resolveExecutionContext`, is a test-only injection point. A production resolver cannot throw synchronously — `resolvePackageRouteExecutionContext` is a non-`async` wrapper whose only call is to a `private async` method — and its rejections are swallowed twice, at `rest-server.ts:1483` and again at `package-routes.ts:81`, landing on the 401 anonymous-deny floor instead of `sendThrownError`. Corrects six sites, states the reason once in a `Seam census` block and cites it from the others, and retires the falsifier limb that named a synchronously throwing `resolveExecutionContext`: unreachable by construction, so not a falsifier. The `resolveExecutionContext` test case itself is KEPT and relabelled, never deleted — it still pins how the door answers an injected resolver that throws. Comment/prose only: both blobs transpile to a byte-identical program under `removeComments`, with the instrument reverse-checked in both directions (a code token moves the hash, a comment token does not). Claude-Session: https://claude.ai/code/session_01UjujZN219uFzBhSYfMykCd Co-authored-by: Claude <noreply@anthropic.com>
1 parent fb5a669 commit 2fc96ab

1 file changed

Lines changed: 91 additions & 14 deletions

File tree

packages/rest/src/package-door-declared-code.test.ts

Lines changed: 91 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -52,19 +52,73 @@
5252
* into `PackageRoutesOptions`, and `resolveExecutionContext` is handed in by
5353
* the composition step. The door forwards whatever they throw, so the
5454
* demote fires on any spelling outside `@objectstack/spec`'s ledger.
55-
* Section 1 drives all four seams through the real registrar.
55+
* Section 1 drives all four seams through the real registrar — but
56+
* ⚠️ only THREE of the four are production producers; the
57+
* `resolveExecutionContext` seam is a TEST-ONLY injection point. See
58+
* **Seam census** below, which is the one place that reason is stated.
5659
*
5760
* - **The framework's OWN producers do not populate it, by GATE.**
5861
* `pnpm check:dispatcher-error-vocabulary` (`dispatcher-error-vocabulary.ts`)
5962
* fails on an unswept platform producer precisely so a platform semantic
6063
* code cannot silently demote off the wire. Measured on this checkout: every
61-
* status-declaring coded throw reachable at these four seams spells a
62-
* REGISTERED code. That is the point of the gate, not an argument that the
64+
* status-declaring coded throw reachable at the three PRODUCTION seams
65+
* (**Seam census** below) spells a REGISTERED code. That is the point of the gate, not an argument that the
6366
* channel is dead — it leaves `declaredCode`'s live population as the limb
6467
* no ledger can enumerate: a metadata app's own thrown `.code` across the
6568
* QuickJS boundary (#7867) and a downstream repo's codes, which the ledger's
6669
* federation ruling (2026-08-03/09) keeps out of this ledger BY DESIGN.
6770
*
71+
* ## ⭐ Seam census: THREE production seams, plus ONE test-only injection
72+
*
73+
* `SITES` below drives FOUR seams. Three are producers a deployment can
74+
* actually reach; the fourth is an injection point that exists only in a test.
75+
* Stated ONCE here and cited from the sites that depend on it, rather than
76+
* restated at each.
77+
*
78+
* Measured on `origin/main` @ `aa5994e17` by reading the composition rather
79+
* than inferring it:
80+
*
81+
* - `rest-api-plugin.ts:471` is the ONLY production supplier of this option,
82+
* repo-wide: `resolveExecutionContext: (req) =>
83+
* restServer.resolvePackageRouteExecutionContext(req)`.
84+
* - `rest-server.ts:1481` — `resolvePackageRouteExecutionContext` is NOT
85+
* `async`. Its whole body is an optional-chained
86+
* `req?.params?.environmentId` read, then `return
87+
* this.resolveExecCtx(environmentId, req).catch(() => undefined)`.
88+
* - `rest-server.ts:1453` — `private async resolveExecCtx(...)`. Being
89+
* `async`, calling it cannot throw SYNCHRONOUSLY; it always returns a
90+
* promise.
91+
* - `package-routes.ts:81` — the consumer then `await`s
92+
* `options.resolveExecutionContext(req).catch(() => undefined)`, swallowing
93+
* a rejection a SECOND time.
94+
*
95+
* ⇒ A production resolver delivers exactly two things: a context, or
96+
* `undefined`. Its rejections are swallowed twice and land on the
97+
* anonymous-deny floor as a 401 — they never reach `sendThrownError`. The
98+
* ONLY route from this seam to `sendThrownError` is a SYNCHRONOUS throw (it
99+
* happens before `.catch` is attached, so it rejects `refusePackageRequest`
100+
* itself and the handler's `try` catches it) — and the production wrapper
101+
* above has no statement that can make one.
102+
*
103+
* ⚠️ Nor can an embedder reach it: `registerPackageRoutes` and
104+
* `PackageRoutesOptions` are NOT exported from `packages/rest/src/index.ts`
105+
* (the package publishes a single `.` entry, and `direct-mount-composition.ts`
106+
* is their only importer), so no downstream composition can supply a resolver
107+
* of its own here either.
108+
*
109+
* ⛔ The `resolveExecutionContext` case is KEPT anyway, deliberately. It
110+
* pins something real — how this door answers when an injected resolver
111+
* throws synchronously — and `reached()` keeps it from going vacuous. It
112+
* simply is not evidence about a PRODUCTION path, so nothing in this file may
113+
* cite it as one. Deleting a test to make a census true would be the census
114+
* lying in the other direction.
115+
*
116+
* ⛔ Whether that double swallow SHOULD exist at all is a different
117+
* question — it would change what a public door emits — and it is open
118+
* at #12537, deliberately not answered here. Note for whoever takes it: the
119+
* swallow is documented at NEITHER site, so "deliberate" is not established by
120+
* the code as it stands.
121+
*
68122
* Section 5 is the second fact stated as a test: a REAL `ObjectQL`, a REAL
69123
* `ObjectStackProtocolImplementation` and a failing driver, driven through the
70124
* route a client calls, answer a REGISTERED `SERVICE_UNAVAILABLE` and therefore
@@ -198,6 +252,10 @@ const MANIFEST = { id: 'com.acme.crm', version: '1.0.0' };
198252
* `package-routes-coded-error-mapping.test.ts`, for the same reason: a case
199253
* that silently never reached the seam would otherwise "pass" on a body it got
200254
* for a completely different reason.
255+
*
256+
* ⚠️ Four seams, THREE of them production. The
257+
* `resolveExecutionContext` entry is the test-only one — see **Seam census**
258+
* in the module docblock, the single place that reason is stated.
201259
*/
202260
interface Site {
203261
name: string;
@@ -219,6 +277,14 @@ const SITES: Site[] = [
219277
},
220278
},
221279
{
280+
// ⚠️ TEST-ONLY INJECTION POINT — NOT a production seam, and ⛔ not to
281+
// be counted as one. A production resolver cannot throw synchronously and
282+
// its rejections are swallowed twice before this door sees them; the
283+
// measurement is in **Seam census** in the module docblock. Kept because
284+
// it pins real door behaviour (and `reached()` keeps it honest).
285+
// ⚠️ The `vi.fn` below is deliberately NOT `async`: an `async` one
286+
// would REJECT, and `package-routes.ts:81` would swallow that into the
287+
// 401 anonymous-deny floor instead of reaching `sendThrownError`.
222288
name: 'GET /packages — the capability gate resolver throws',
223289
run: async (error: unknown) => {
224290
const resolveExecutionContext = vi.fn(() => { throw error; });
@@ -259,7 +325,8 @@ const SITES: Site[] = [
259325
];
260326

261327
// ---------------------------------------------------------------------------
262-
// 1. The demote reaches the wire, at every seam this door has
328+
// 1. The demote reaches the wire, at every seam this suite drives
329+
// (three production producers + one test-only injection — Seam census)
263330
// ---------------------------------------------------------------------------
264331

265332
describe('[#12405] an UNREGISTERED producer spelling rides `declaredCode`', () => {
@@ -478,9 +545,10 @@ describe('[#12405] the demote is not withheld by the 5xx message sanitiser', ()
478545
* merely consistent, because of a fact about the producers, and that fact is
479546
* recorded here because it can rot and is written down nowhere else:
480547
*
481-
* **No producer reaching these four seams can put a driver errno in
482-
* `declaredCode` today, because `PackageService` discriminates on the
483-
* STATUS channel and never on `.code`.**
548+
* **No producer reaching the three PRODUCTION seams can put a driver
549+
* errno in `declaredCode` today, because `PackageService` discriminates on
550+
* the STATUS channel and never on `.code`.** (Three, not four — **Seam
551+
* census** in the module docblock.)
484552
*
485553
* `packages/services/service-package/src/index.ts` is explicit about why:
486554
* `publish` and `delete` re-throw only what `declaresHttpAnswer(error)`
@@ -502,13 +570,22 @@ describe('[#12405] the demote is not withheld by the 5xx message sanitiser', ()
502570
* here measures that shape, because nothing produces it.
503571
*
504572
* ⛔ **The falsifier, stated so the next reader inherits a measurement
505-
* instead of an argument:** a producer that reaches any of these four seams
506-
* carrying a driver errno as its `.code` — a `PackageService` implementation
507-
* that re-throws on `.code` rather than on status, a `protocol` slice that
508-
* lets a raw driver error out of `deletePackage`, or a
509-
* `resolveExecutionContext` that throws one synchronously. On that day the
510-
* disclosure becomes live, this block's premise is false, and the fork has to
511-
* be RE-OPENED rather than re-derived from the consistency half above.
573+
* instead of an argument:** a producer that reaches any of the three
574+
* PRODUCTION seams carrying a driver errno as its `.code` — a
575+
* `PackageService` implementation that re-throws on `.code` rather than on
576+
* status, or a `protocol` slice that lets a raw driver error out of
577+
* `deletePackage`. On that day the disclosure becomes live, this block's
578+
* premise is false, and the fork has to be RE-OPENED rather than re-derived
579+
* from the consistency half above.
580+
*
581+
* ⚠️ This list carried a THIRD limb — "or a `resolveExecutionContext`
582+
* that throws one synchronously" — retired here rather than reworded,
583+
* because it is unreachable BY CONSTRUCTION and not merely unobserved
584+
* (**Seam census** in the module docblock). A falsifier that cannot be
585+
* reached is not a falsifier: it reads as a live way to test this block,
586+
* and costs the reader who tries it the time to discover it cannot happen.
587+
* If the swallow at `rest-server.ts:1483` is ever un-done — the half of
588+
* #12537 still open — this limb becomes real again and belongs back here.
512589
*
513590
* Ruled A by the `domain:cli` PM seat on 2026-08-26 on exactly this ground —
514591
* ⛔ not option B (suppress the demote when the message was withheld), which

0 commit comments

Comments
 (0)