Repository navigation
test(rest): execctx-consumer-census derives its structural reading from the tree instead of hand counts - #26520
Conversation
…om the tree instead of hand counts §2's literal site / mention / caught-bare-same-line / moved-registrar counts and the per-slice recount history are replaced by one derived invariant: every resolveExecCtx site is either bare with the shared anonymous floor as its next statement, or locally caught and not behind that floor. Its controls are derived too: no call in the censused files is spelt outside the census' reading, and every call the mounted table makes is attributed to a censused site. The floors that restated the counts elsewhere (§3, §7, §8) now compare against the site table, site by site. Claude-Session: https://claude.ai/code/session_01FEkQ5oi3XkDNLtE2KCnbvV Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FEkQ5oi3XkDNLtE2KCnbvV Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs. What this run could not see
Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
席位核对ACCEPT · The maintainer's standing authorisation for landing reviewed PRs, verbatim: 「按照 pm-dispatch 规则复核过的都授权」.
Generated by Claude Code |
Requested by Leehom · project thread
Fixes #26436
Part of #26431
Clause-②: no
Metadata-protocol: none
维护者速读
execctx-consumer-census.test.ts里所有手数的数字(调用点 62、提及 145、caught/bare/同行 16/46/12、迁出注册器 4/4、文件数 18)和每次拆分rest-server.ts留下的重数记录全部删掉,换成一条从源码推导的规则:每个resolveExecCtx调用点,要么是「裸调用,下一行就是共享的匿名拦截」,要么是「自带 catch,且不在那道拦截后面」。computeExecCtxswallows EVERY fault into an anonymous context for all 72resolveExecCtxcall sites — measured fail-closed at exactly one door, unmeasured at the rest #13160 要的答案(执行上下文缺失时每个消费点意味着什么)已经写在文件散文和行为测试里,数字本身什么都不证明。packages/rest/src/execctx-consumer-census.test.ts的 §2(新规则及其两个对照);同文件 §3 新增的「每次调用都归属到一个已普查调用点」对照。pnpm --filter @objectstack/rest exec vitest run src/execctx-consumer-census.test.ts,预期 27 个用例全绿。What changes
One file,
packages/rest/src/execctx-consumer-census.test.ts. Seat ruling arm (b): the invariant holds today, so the file stays and its counts go.this.resolveExecCtx(environmentId, req)site in every file onREST_SERVER_REGISTRAR_FILESis EITHER bare withif (this.enforceAuth(req, res, context)) return;as its very next statement, OR locally caught and not behind that floor. A failure names each site out of shape. Two derived controls sit in the same case: (i) completeness, no line in a censused file callsresolveExecCtxin any spelling other than a site, a host literal's forwarder or the method's declaration, so the partition cannot silently narrow; (ii) neither half of the partition is empty.SITE_FILESlength 18,SITES62, 145 mentions, 16 / 46 / 12, theEXTRA_MOVED_REGISTRARSandMOVED_REGISTRARS_READING_NO_EXECCTXhand maps (4 / 4) with the forwarder-count arithmetic, the per-slice recount docblocks and the ten-entry recount changelog inside §2.instrument()now records a call no censused frame made as(no censused frame)instead of dropping it, and a new §3 control asserts that every call the mounted table makes, under the FULL and the ISOLATED mounts, is attributed to a censused site. A registrar body moved to a module that never joined the list reds there (ablation C below). A respelt forwarder reds the §2 completeness control.rows.length >= 46becomes "the rows cover every bare site"; §7's>= 12inline />= 4continuation floors become equality with the site table's own reading of where each catch sits, per site, plus both layouts non-empty; §8's>= 4becomes non-empty. Titles and prose that stated a population count ("the 46 bare sites", "the 20 locally-caught sites", "the four continuation sites", "four of the inner sites") are reworded without the number.Per
describeblock (the triage asked for this):undefinedWhy
The card (
Part ofthe transcription-pin parent): the file pinned hand counts that everyrest-server.tssplit slice had to retype, and the question it answers (#13160, what an absent execution context means at each consumer) is a one-time reading already recorded in its prose. The derived rule is the reading the file itself recorded as its structural finding ("the bare sites are bare BECAUSE the shared anonymous floor is the next statement; the locally-caught ones carry a.catchbecause they are NOT behind that floor"), now asserted as a rule instead of as 46 and 0. It reds on #13160's defect shape: a consumer that takes the context bare and proceeds with nothing deciding the absent context beside it.Tests
pnpm --filter @objectstack/rest exec vitest run --maxWorkers=2 src/execctx-consumer-census.test.ts: 27 / 27 pass (28 before: §2's three cases became one, §3 gained one).pnpm --filter @objectstack/rest test(under the shared verify lock, VERDICT command-exit 0): Test Files 324 passed (324), Tests 6482 passed, 326 skipped.pnpm --filter @objectstack/rest typecheck(tsc --noEmit && pnpm check:test-typecheck): VERDICT command-exit 0.eslint packages/rest --no-inline-config: exit 0, no output.Ablations — three legs, each through scripts/ablation-replace.mjs, each restored to the HEAD blob with git diff HEAD empty
The suite reads
src/directly (relative import of./rest-server.js, same package), so nodistleg applies.computeExecCtxswallows EVERY fault into an anonymous context for all 72resolveExecCtxcall sites — measured fail-closed at exactly one door, unmeasured at the rest #13160's shape: deleteif (this.enforceAuth(req, res, context)) return;under the bare site inemail-routes.ts(anchor 1 → 0, blob30a8f5a0c886→8b44d5e1a6f3). 2 failed / 25 passed: §2 namesemail-routes.ts:77 — bare, and NOT followed by the shared floor; §3's driven case readsPOST /api/v1/email/send under an absent context: expected 200 to be 401, the absent context served. Restored, blob == HEAD30a8f5a0c886.this.resolveExecCtx(environmentId, req)→this.resolveExecCtx(environmentId,req)inemail-routes.ts(blob30a8f5a0c886→19282f570843). 2 failed / 25 passed: §2's completeness control listsemail-routes.ts:77: const context = await this.resolveExecCtx(environmentId,req);; §3's attribution control listsPOST /api/v1/email/send ← email-routes.ts:77. Restored, blob == HEAD.'email-routes.ts',fromREST_SERVER_REGISTRAR_FILES(blobfa939290f54d→1f4b4e2e8c74). 1 failed / 26 passed: §3's attribution control listsPOST /api/v1/email/send ← (no censused frame). Restored, blob == HEADfa939290f54d.Acceptance notes
SITE_FILES18,SITES62, 145, 16 / 46 / 12 and 4 / 4 are gone from code and prose; notoHaveLengthremains in the file./metarows with a site (measured 19). Both sit below the measurement with margin, which is the floor family test(floors): floors set at today's measured value and two-sided baselines red on every legitimate deletion — ui package counts in ~8 places, CLI command counts, catalog entries pinned 4×, slot-lookup-class baselines that fail on a decrease #26444 keeps.toHaveLength(18)in seven test files — drop the seven length pins, the list is the authority #26433 edits six otherpackages/resttest files; no open PR touches this file orrest-server-registrar-files.ts(all open PRs' file lists read at the start of the work and again before opening this one).skip-changeset: the file is not published (@objectstack/restfilesisdist,README.md,CHANGELOG.md, and tsup's entry issrc/index.ts). NoresolveExecCtxdocblock was touched (that was arm (a)).Verification
All local readings at branch head
fd29a1d26, against merge base45de8c6cb.node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackon the real diff: 49. Each run with its exit code captured before any pipe;--ranreconciliation: "49 derived famil(ies) accounted for — 48 run, 1 NOT-MEASURED".check:type-check-debt(0 raw tsc errors, none above its recorded number),check:cross-package-test-inputs,check:test-source-alias,check:nul-bytes,check:issue-citationsandcheck:doc-authoring.node scripts/check-plugin-teardown-shape.mjs --self-testexited 3 on the first pass (its pinned positive-control commit was outside the shallow clone); after fetching that commit it exits 0 ("48 cases pass").pnpm check:dual-build-cjs-loads, exit 3, PREREQUISITE NOT MET (the worktree built only the@objectstack/restdependency closure, so other packages have nodist/). CI runs it.!in the title and no(narrowing)arm.Human Minimum
packages/specholds no runtime logic. (not touched)pnpm lintpasses (scoped to the touched package; CI runs the repo-wide scan).main, one pull request.packages/spectouched: not touched.content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.Generated by Claude Code