Skip to content

Commit 96504da

Browse files
committed
refactor(rest): re-point every reader of the moved security bodies (#23050 slice 6)
Each reader whose reading included a moved line now reads it in security-routes.ts, with its sum unchanged: - the nine registrar-list readers re-read their numbers at length 7 (query-number 9, canonical query slots 4, meta-draft switches 8, docblock floors 29, execctx 62 sites / 109 mentions with eight forwarders = (7 - 1) + 2, ui-view pair 55 / 70, the dogfood tripwire 0, the blind-spot row 70 / 19 / 51 with register 63 and enforceAuth 92); - check-route-envelope declares security-routes.ts dialectOnly at stringError 0 / siblingCode 0 (rest-server.ts unchanged at 17 / 17); - a new ADR anchor for security-routes.ts (ADR-0090, ADR-0105, ADR-0112) restores check-adr-anchors' decision-letter reading 1751 -> 1761; - error-response.ts' nestedRefusalEnvelope docblock names the three families' current homes. Claude-Session: https://claude.ai/code/session_01Q9PZ5Pzqcus4woVvTZwWNU Co-authored-by: Claude <noreply@anthropic.com>
1 parent d6fc91a commit 96504da

12 files changed

Lines changed: 122 additions & 20 deletions

‎packages/qa/dogfood/test/authz-conformance.test.ts‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1627,7 +1627,8 @@ describe('#9084 — the rest-server.ts transport tripwire keys off mechanics', (
16271627
// text is every file on it, in order — so the zero is not a list ignored.
16281628
// [#23050 slice 4] Length 4 → 5 (`sharing-routes.ts`), still 0 over it.
16291629
// [#23050 slice 5] Length 5 → 6 (`analytics-routes.ts`), still 0 over it.
1630-
expect(REST_SERVER_REGISTRAR_FILES).toHaveLength(6);
1630+
// [#23050 slice 6] Length 6 → 7 (`security-routes.ts`), still 0 over it.
1631+
expect(REST_SERVER_REGISTRAR_FILES).toHaveLength(7);
16311632
expect(REST_SERVER_REGISTRAR_PATHS[0]).toBe(REST_SERVER);
16321633
const listed = REST_SERVER_REGISTRAR_PATHS.map((file) => readFileSync(join(REPO_ROOT, file), 'utf8'));
16331634
for (const probe of [MECHANICS, ROUTES]) {

‎packages/qa/dogfood/test/authz-probe-blind-spot.census.ts‎

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -519,10 +519,11 @@ export const PROBE_FILE_CENSUS: readonly ProbeFileReading[] = [
519519
'indentation and the subtrahend is pinned at 1 by the `forwarder slice:` control, never inferred from a ' +
520520
'terminator spelling), PLUS `registerPerItemRoute(` call sites; counted over this file AND every ' +
521521
'module on the registrar list (`packages/rest/src/rest-server-registrar-files.ts`) — ' +
522-
'`data-action-routes.ts`, `batch-routes.ts`, `approvals-routes.ts`, `sharing-routes.ts` and ' +
523-
'`analytics-routes.ts`, the modules the bodies of `registerDataActionEndpoints`, `registerBatchEndpoints`, ' +
524-
'`registerApprovalsEndpoints`, `registerSharingEndpoints`, `registerSharingRuleEndpoints` and ' +
525-
'`registerAnalyticsEndpoints` moved to; ' +
522+
'`data-action-routes.ts`, `batch-routes.ts`, `approvals-routes.ts`, `sharing-routes.ts`, ' +
523+
'`analytics-routes.ts` and `security-routes.ts`, the modules the bodies of `registerDataActionEndpoints`, ' +
524+
'`registerBatchEndpoints`, `registerApprovalsEndpoints`, `registerSharingEndpoints`, ' +
525+
'`registerSharingRuleEndpoints`, `registerAnalyticsEndpoints`, `registerSecurityExplainEndpoints` and ' +
526+
'`registerSecurityEndpoints` moved to; ' +
526527
'reachable = those inside registerMetadataEndpoints',
527528
// [#15542 / #15854] ⭐ THE POPULATION RULE LEARNED A SECOND SPELLING, and
528529
// the numbers it produces did NOT move: 80 / 19 / 61, exactly as before.
@@ -703,23 +704,37 @@ export const PROBE_FILE_CENSUS: readonly ProbeFileReading[] = [
703704
// counted in both readings; the four new occurrences are this slice's
704705
// seam, the same two spellings once (the host literal's forwarder, two;
705706
// the host interface's member, two). No call site was added.
707+
// [#23050 slice 6] 70 / 19 / 51 UNCHANGED, the same measurement again:
708+
// `registerSecurityExplainEndpoints`' and `registerSecurityEndpoints`'
709+
// bodies (six registration sites, three and three, all outside
710+
// `registerMetadataEndpoints`, so all six in the blind spot) moved to
711+
// `security-routes.ts`, which joins the list (length 6 -> 7) with its own
712+
// control. `this.routeManager.register(` stays 63 over the seven files
713+
// (27 here + 9 + 5 + 7 + 8 + 1 + 6), `private register*Endpoints(` stays
714+
// 16 (both registrars are still declared here), and `enforceAuth` 84 -> 92
715+
// is RE-ANCHORED, not relaxed: the five call sites moved with their routes
716+
// and are counted in both readings; the eight new occurrences are this
717+
// slice's seam, the same two spellings TWICE, because the module carries
718+
// two registrars (two host literals' forwarders, four; two host
719+
// interfaces' members, four). No call site was added.
706720
controls: {
707721
'private register*Endpoints(': 16,
708722
'this.routeManager.register(': 63,
709-
'registrar list length': 6,
723+
'registrar list length': 7,
710724
'data-action-routes.ts: this.routeManager.register(': 9,
711725
'batch-routes.ts: this.routeManager.register(': 5,
712726
'approvals-routes.ts: this.routeManager.register(': 7,
713727
'sharing-routes.ts: this.routeManager.register(': 8,
714728
'analytics-routes.ts: this.routeManager.register(': 1,
729+
'security-routes.ts: this.routeManager.register(': 6,
715730
// Both halves of the new rule carry their own control, so neither can go
716731
// silently to zero: a helper deleted and its routes inlined back would
717732
// still read population 80, and only these two controls would notice the
718733
// shape moved and force this provenance to be re-read.
719734
'registerPerItemRoute(': 8,
720735
'const registerPerItemRoute =': 1,
721736
'forwarder slice: this.routeManager.register(': 1,
722-
enforceAuth: 84,
737+
enforceAuth: 92,
723738
},
724739
note:
725740
'The single non-tripwire probe names ONE registrar of 16. The other 15 can never mint a key: ' +

‎packages/rest/src/error-response.ts‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -760,7 +760,9 @@ export function sandboxFaultAnswer(
760760
* ## Why it exists
761761
*
762762
* Three hand-built route families in `rest-server.ts` — the sharing-rule, the
763-
* suggested-binding (and the since-retired overlay-discard) and the approval arms — answered a
763+
* suggested-binding (and the since-retired overlay-discard) and the approval arms, which
764+
* have since moved to `sharing-routes.ts`, `security-routes.ts` and `approvals-routes.ts`
765+
* (#23050 slices 4, 6 and 3) — answered a
764766
* refusal their own arms could not read as a server fault, relaying
765767
* `.message`. For a sandboxed hook's refusal `.message` is the QuickJS debug
766768
* wrapper, so each answered `500` with `hook '<name>' threw: Error: …` where

‎packages/rest/src/execctx-consumer-census.test.ts‎

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ const SOURCE = readFileSync(resolve(HERE, 'rest-server.ts'), 'utf8');
9393
*
9494
* [#23050 slice 5] …and `registerAnalyticsEndpoints`' body to
9595
* `analytics-routes.ts`, with its one.
96+
*
97+
* [#23050 slice 6] …and `registerSecurityExplainEndpoints`' and
98+
* `registerSecurityEndpoints`' bodies to `security-routes.ts`, with their five
99+
* (two and three) — the second module on the list to carry TWO registrars.
96100
*/
97101
const SITE_FILES = REST_SERVER_REGISTRAR_FILES;
98102
const SOURCES = new Map<string, string>(SITE_FILES.map((file) => [
@@ -104,7 +108,8 @@ const siteKey = (file: string, line: number) => `${file}:${line}`;
104108
* The frames in `rest-server.ts` that are NOT consumers: the host literal each
105109
* moved registrar (`registerDataActionEndpoints`, `registerBatchEndpoints`,
106110
* `registerApprovalsEndpoints`, `registerSharingEndpoints`,
107-
* `registerSharingRuleEndpoints`, `registerAnalyticsEndpoints`) hands
111+
* `registerSharingRuleEndpoints`, `registerAnalyticsEndpoints`,
112+
* `registerSecurityExplainEndpoints`, `registerSecurityEndpoints`) hands
108113
* its moved body forwards each member to the server with
109114
* `(...a) => this.<member>(...a)`, so a moved site's stack shows that forwarder
110115
* above the site itself. The site is the first censused frame that is not one.
@@ -120,9 +125,12 @@ const FORWARDERS = new Set(FORWARDER_LINES.map((line) => siteKey('rest-server.ts
120125
* [#23050 slice 4] The moved registrars beyond one per moved module:
121126
* `sharing-routes.ts` carries two registrars' bodies, each handed over by its
122127
* own host literal and so through its own forwarder.
128+
*
129+
* [#23050 slice 6] `security-routes.ts` carries two as well, on the same terms.
123130
*/
124131
const EXTRA_MOVED_REGISTRARS: Readonly<Partial<Record<(typeof SITE_FILES)[number], number>>> = {
125132
'sharing-routes.ts': 1,
133+
'security-routes.ts': 1,
126134
};
127135

128136
/** A stack frame in any censused file, as `<file>:<line>:<column>`. */
@@ -598,11 +606,21 @@ describe('[#13160] §2 the consumer surface, counted from the tree', () => {
598606
// mentions are this slice's seam, the same two spellings once (its host
599607
// literal's forwarder, two; its host interface's member, two). Six
600608
// forwarders now, one per moved registrar: (6 - 1) + 1.
601-
expect(SITE_FILES).toHaveLength(6);
609+
//
610+
// [#23050 slice 6] 62 sites UNCHANGED / 101 → 109 mentions — the same MOVE.
611+
// `registerSecurityExplainEndpoints`' and `registerSecurityEndpoints`'
612+
// bodies left for `security-routes.ts` with their five BARE sites (two
613+
// and three): 27 + 9 + 5 + 7 + 8 + 1 + 5 = 62 sites. The eight new
614+
// mentions are this slice's seam, the same two spellings TWICE, as slice
615+
// 4's (two host literals' forwarders, four; two host interfaces'
616+
// members, four). Eight forwarders now, one per moved registrar:
617+
// (7 - 1) + 2, the second module carrying two registrars counted in
618+
// `EXTRA_MOVED_REGISTRARS`.
619+
expect(SITE_FILES).toHaveLength(7);
602620
expect(SITES.length).toBe(62);
603-
expect([...SOURCES.values()].reduce((n, text) => n + text.split('resolveExecCtx').length - 1, 0)).toBe(101);
621+
expect([...SOURCES.values()].reduce((n, text) => n + text.split('resolveExecCtx').length - 1, 0)).toBe(109);
604622
const extraMovedRegistrars = Object.values(EXTRA_MOVED_REGISTRARS).reduce((n, k) => n + (k ?? 0), 0);
605-
expect(extraMovedRegistrars).toBe(1);
623+
expect(extraMovedRegistrars).toBe(2);
606624
expect(FORWARDER_LINES, 'one host-literal resolveExecCtx forwarder per moved registrar: one was respelt or removed, or a module moved without joining SITE_FILES')
607625
.toHaveLength(SITE_FILES.length - 1 + extraMovedRegistrars);
608626
});

‎packages/rest/src/meta-draft-read-door-census.test.ts‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,10 @@ describe('[#20338] census: every draft switch in rest-server.ts is ledgered', ()
246246
// and `req.query?.preview === 'draft'`, admitted in one declaration)
247247
// moved with its body to `analytics-routes.ts`. A key names its route,
248248
// never its file, so no ledger row changed: 8 = 6 + 0 + 0 + 0 + 0 + 2,
249-
// length 5 → 6.
250-
expect(REST_SERVER_REGISTRAR_FILES).toHaveLength(6);
249+
// length 5 → 6. [#23050 slice 6] The two security bodies
250+
// (`security-routes.ts`) read no draft: 8 = 6 + 0 + 0 + 0 + 0 + 2 + 0,
251+
// length 6 → 7.
252+
expect(REST_SERVER_REGISTRAR_FILES).toHaveLength(7);
251253
expect(SOURCE_FILES.map((file) => file.fileName)).toEqual([...REST_SERVER_REGISTRAR_FILES]);
252254
expect(SITES).toHaveLength(8);
253255
});

‎packages/rest/src/rest-server-canonical-query-ast.test.ts‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,11 @@ interface CensusEntry {
135135
* [#23050 slice 5] 4 = 1 + 3 + 0 + 0 + 0 + 0: the analytics dataset body
136136
* (`analytics-routes.ts`) builds no `query:` literal either — it hands
137137
* `queryDataset` the caller's own `selection`, never a `query:` slot.
138+
*
139+
* [#23050 slice 6] 4 = 1 + 3 + 0 + 0 + 0 + 0 + 0: the two security bodies
140+
* (`security-routes.ts`) build no `query:` literal either — the explain doors
141+
* hand the security service a parsed explain request, and the suggestion list
142+
* a `status` / `packageId` pair read off `req.query`, never a `query:` slot.
138143
*/
139144
const REGISTRAR_QUERY_SLOT_FLOORS: Readonly<Record<RestServerRegistrarFile, number>> = {
140145
'rest-server.ts': 1,
@@ -143,6 +148,7 @@ const REGISTRAR_QUERY_SLOT_FLOORS: Readonly<Record<RestServerRegistrarFile, numb
143148
'approvals-routes.ts': 0,
144149
'sharing-routes.ts': 0,
145150
'analytics-routes.ts': 0,
151+
'security-routes.ts': 0,
146152
};
147153

148154
const CENSUS: CensusEntry[] = [
@@ -332,7 +338,8 @@ describe('[#16638] §1 CONTROLS on the census instrument itself', () => {
332338
// A module added to the list makes this re-read its number rather than
333339
// widening unnoticed. [#23050 slice 4] Length 4 → 5, the sum unchanged.
334340
// [#23050 slice 5] Length 5 → 6, the sum unchanged.
335-
expect(REST_SERVER_REGISTRAR_FILES).toHaveLength(6);
341+
// [#23050 slice 6] Length 6 → 7, the sum unchanged.
342+
expect(REST_SERVER_REGISTRAR_FILES).toHaveLength(7);
336343
expect(Object.keys(REGISTRAR_QUERY_SLOT_FLOORS).sort()).toEqual([...REST_SERVER_REGISTRAR_FILES].sort());
337344
expect(CENSUS.filter(({ file }) => REGISTRAR_SOURCES.has(file)).map(({ file }) => file))
338345
.toEqual([...REST_SERVER_REGISTRAR_FILES]);

‎packages/rest/src/rest-server-docblock-position.test.ts‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,13 +153,21 @@ describe('rest-server.ts docblock position', () => {
153153
* approval modules do: the module header, the host interface's block and the
154154
* function's. The analytics body held no TSDoc block of its own, so
155155
* `rest-server.ts` keeps every block it had.
156+
*
157+
* [#23050 slice 6] `security-routes.ts` carries eight: the module header, two
158+
* host interfaces' blocks and two functions' (it holds two registrars' bodies),
159+
* plus the three blocks that moved with those bodies (the explain family's
160+
* `respondError` and `delegableHandler` blocks, and the suggested-binding
161+
* family's `respondError` block), which `rest-server.ts` therefore no longer
162+
* holds (167 → 164 there, still far above its floor).
156163
*/
157164
const MOVED_FILE_FLOORS: Readonly<Record<Exclude<RestServerRegistrarFile, typeof FILE>, number>> = {
158165
'data-action-routes.ts': 4,
159166
'batch-routes.ts': 3,
160167
'approvals-routes.ts': 3,
161168
'sharing-routes.ts': 8,
162169
'analytics-routes.ts': 3,
170+
'security-routes.ts': 8,
163171
};
164172
const MOVED_FILES: ReadonlyArray<{ file: string; minBlocks: number }> = REST_SERVER_REGISTRAR_FILES
165173
.filter((file): file is Exclude<RestServerRegistrarFile, typeof FILE> => file !== FILE)
@@ -189,9 +197,10 @@ describe('[#23050 slice 3] the registrar list this pin reads', () => {
189197
// widening unnoticed: 4 + 3 + 3 = 10 blocks over the three modules.
190198
// [#23050 slice 4] 4 + 3 + 3 + 8 = 18 over four, length 4 → 5.
191199
// [#23050 slice 5] 4 + 3 + 3 + 8 + 3 = 21 over five, length 5 → 6.
192-
expect(REST_SERVER_REGISTRAR_FILES).toHaveLength(6);
200+
// [#23050 slice 6] 4 + 3 + 3 + 8 + 3 + 8 = 29 over six, length 6 → 7.
201+
expect(REST_SERVER_REGISTRAR_FILES).toHaveLength(7);
193202
expect(Object.keys(MOVED_FILE_FLOORS).sort())
194203
.toEqual(REST_SERVER_REGISTRAR_FILES.filter((file) => file !== FILE).sort());
195-
expect(MOVED_FILES.reduce((n, { minBlocks }) => n + minBlocks, 0)).toBe(21);
204+
expect(MOVED_FILES.reduce((n, { minBlocks }) => n + minBlocks, 0)).toBe(29);
196205
});
197206
});

‎packages/rest/src/rest-server-query-number-census.test.ts‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,9 @@ describe('#20139 census — every numeric coercion in rest-server.ts is classifi
321321
// record-sharing bodies (`sharing-routes.ts`): 9 = 8 + 1 + 0 + 0 + 0,
322322
// length 4 → 5. [#23050 slice 5] Nor does the analytics dataset body
323323
// (`analytics-routes.ts`): 9 = 8 + 1 + 0 + 0 + 0 + 0, length 5 → 6.
324-
expect(REST_SERVER_REGISTRAR_FILES).toHaveLength(6);
324+
// [#23050 slice 6] Nor do the two security bodies (`security-routes.ts`):
325+
// 9 = 8 + 1 + 0 + 0 + 0 + 0 + 0, length 6 → 7.
326+
expect(REST_SERVER_REGISTRAR_FILES).toHaveLength(7);
325327
expect(SOURCES.map(([file]) => file)).toEqual([...REST_SERVER_REGISTRAR_FILES]);
326328
expect(sites).toHaveLength(9);
327329
});

‎packages/rest/src/ui-view-route-identity.measurement.test.ts‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,9 @@ describe('[#13214] §1 the REST seam — absent context vs entitled context', ()
346346
// (50 and 65 before, +1 each per new host-literal forwarder).
347347
// [#23050 slice 5] 5 → 6 (`analytics-routes.ts`): 53 and 68, +1 each
348348
// for that slice's forwarder.
349-
expect(REST_SERVER_REGISTRAR_FILES).toHaveLength(6);
349+
// [#23050 slice 6] 6 → 7 (`security-routes.ts`): 55 and 70, +1 each
350+
// per new host-literal forwarder (two registrars, two forwarders).
351+
expect(REST_SERVER_REGISTRAR_FILES).toHaveLength(7);
350352
expect(REGISTRAR_SOURCES.split('this.enforceAuth(').length - 1).toBeGreaterThan(40);
351353
expect(REGISTRAR_SOURCES.split('this.resolveExecCtx(').length - 1).toBeGreaterThan(40);
352354
});

‎packages/rest/src/ui-view-route-tenancy.measurement.test.ts‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1113,7 +1113,10 @@ describe('[#13214] §4 preconditions', () => {
11131113
// new host-literal forwarder) and the ownership guard stays at 1.
11141114
// [#23050 slice 5] 5 → 6 (`analytics-routes.ts`): 53 and 68, +1 each
11151115
// for that slice's forwarder; the ownership guard still 1.
1116-
expect(REST_SERVER_REGISTRAR_FILES).toHaveLength(6);
1116+
// [#23050 slice 6] 6 → 7 (`security-routes.ts`): 55 and 70, +1 each
1117+
// per new host-literal forwarder (two registrars, two forwarders); the
1118+
// ownership guard still 1.
1119+
expect(REST_SERVER_REGISTRAR_FILES).toHaveLength(7);
11171120
expect(REGISTRAR_SOURCES.split('this.enforceAuth(').length - 1).toBeGreaterThan(40);
11181121
expect(REGISTRAR_SOURCES.split('this.resolveExecCtx(').length - 1).toBeGreaterThan(40);
11191122
// ...and the ownership guard is NOT sprayed across the file — it is a

0 commit comments

Comments
 (0)