Skip to content

Commit d0e954f

Browse files
committed
Merge remote-tracking branch 'origin/main' into claude/issue-24355-search-empty-set-docs-family
2 parents 093a016 + d1f082d commit d0e954f

19 files changed

Lines changed: 942 additions & 502 deletions
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'@objectstack/rest': patch
3+
---
4+
5+
The `/meta` object state-machine read and the published read live in their own modules, with no route, handler or answer changed
6+
7+
Clause-②: no (a move: the two routes per base, their place in the `/meta` registration order, every handler, every response and the anonymous-deny gate in front of them are unchanged, and the published declarations are byte-identical)
8+
9+
- `RestServer#registerMetadataEndpointsInner` keeps its name, docblock, place and head, its per-item registrar included. The statement that registers `GET {metaPath}/object/:name/state/:field` (the legal next states of an object field's state machine) moved, re-indented, to `packages/rest/src/meta-object-state-routes.ts`, and the block that registers `GET {metaPath}/:type/:name/published` (an item's published version) moved to `packages/rest/src/meta-item-history-routes.ts`, beside the history family. The method calls each at its old position, inside the umbrella's guarded registration. The state read still answers to `api.enableMetadata` alone, and the published read still registers through the per-item registrar, so the `metadata.endpoints.item` switch gates the same mounts.
10+
- Nothing to do for a consumer: no export of the package entry, no route, no configuration key and no response moved.

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1638,7 +1638,8 @@ describe('#9084 — the rest-server.ts transport tripwire keys off mechanics', (
16381638
// [#23050 slice 13b] Length 14 → 15 (`meta-item-read-routes.ts`), still 0 over it.
16391639
// [#23050 slice 13c] Length 15 → 16 (`meta-item-write-routes.ts`), still 0 over it.
16401640
// [#23050 slice 13d] Length 16 → 17 (`meta-item-history-routes.ts`), still 0 over it.
1641-
expect(REST_SERVER_REGISTRAR_FILES).toHaveLength(17);
1641+
// [#23050 slice 13e] Length 17 → 18 (`meta-object-state-routes.ts`), still 0 over it.
1642+
expect(REST_SERVER_REGISTRAR_FILES).toHaveLength(18);
16421643
expect(REST_SERVER_REGISTRAR_PATHS[0]).toBe(REST_SERVER);
16431644
const listed = REST_SERVER_REGISTRAR_PATHS.map((file) => readFileSync(join(REPO_ROOT, file), 'utf8'));
16441645
for (const probe of [MECHANICS, ROUTES]) {

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

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -541,17 +541,17 @@ export const PROBE_FILE_CENSUS: readonly ProbeFileReading[] = [
541541
'`data-action-routes.ts`, `batch-routes.ts`, `approvals-routes.ts`, `sharing-routes.ts`, ' +
542542
'`analytics-routes.ts`, `security-routes.ts`, `discovery-routes.ts`, `email-routes.ts`, ' +
543543
'`search-routes.ts`, `ui-routes.ts`, `form-routes.ts`, `crud-routes.ts`, `meta-collection-routes.ts`, ' +
544-
'`meta-item-read-routes.ts`, `meta-item-write-routes.ts` and `meta-item-history-routes.ts`, ' +
545-
'the modules the bodies of ' +
544+
'`meta-item-read-routes.ts`, `meta-item-write-routes.ts`, `meta-item-history-routes.ts` and ' +
545+
'`meta-object-state-routes.ts`, the modules the bodies of ' +
546546
'`registerDataActionEndpoints`, `registerBatchEndpoints`, `registerApprovalsEndpoints`, ' +
547547
'`registerSharingEndpoints`, `registerSharingRuleEndpoints`, `registerAnalyticsEndpoints`, ' +
548548
'`registerSecurityExplainEndpoints`, `registerSecurityEndpoints`, `registerDiscoveryEndpoints`, ' +
549549
'`registerOpenApiEndpoints`, `registerEmailEndpoints`, `registerSearchEndpoints`, ' +
550-
'`registerUiEndpoints`, `registerFormEndpoints` and `registerCrudEndpoints`, and the first six `/meta` ' +
550+
'`registerUiEndpoints`, `registerFormEndpoints` and `registerCrudEndpoints`, and all eight `/meta` ' +
551551
'groups of `registerMetadataEndpointsInner`, moved to; ' +
552552
'reachable = those inside registerMetadataEndpoints, PLUS every site in the registrar list\'s named `/meta` ' +
553553
'subset (`REST_SERVER_META_ROUTE_FILES`: `meta-collection-routes.ts`, `meta-item-read-routes.ts`, ' +
554-
'`meta-item-write-routes.ts` and `meta-item-history-routes.ts`), whose ' +
554+
'`meta-item-write-routes.ts`, `meta-item-history-routes.ts` and `meta-object-state-routes.ts`), whose ' +
555555
'registrations the inner method ' +
556556
'runs inside the umbrella\'s swap',
557557
// [#15542 / #15854] ⭐ THE POPULATION RULE LEARNED A SECOND SPELLING, and
@@ -910,10 +910,31 @@ export const PROBE_FILE_CENSUS: readonly ProbeFileReading[] = [
910910
// `const registerPerItemRoute =` stays 1, `forwarder slice:` stays 1 and
911911
// `enforceAuth` stays 112: the moved group spells none of them, and neither
912912
// does the seam.
913+
// [#23050 slice 13e] 70 / 19 / 51 UNCHANGED, `reachable` held by 13a's rule
914+
// with no rule change, and ONE control re-keyed. The seventh `/meta` group,
915+
// the object state-machine read (one DIRECT registration site, in no
916+
// per-family switch), moved to `meta-object-state-routes.ts`, which joins the
917+
// list (length 17 -> 18) and the named `/meta` subset (4 -> 5) with its own
918+
// control on `this.routeManager.register(` (1). The eighth and last, the
919+
// published read (one helper-routed site), joined `meta-item-history-routes.ts`,
920+
// whose own control goes 5 -> 6, and the whole-population
921+
// `registerPerItemRoute(` control stays 8 over this file plus every module on
922+
// the list (0 here + 2 + 6). Measured at the move commit, before the list
923+
// learned the new module: population 69, the state read's site out of reach.
924+
// RE-KEYED, not relaxed: the inner method now calls the history module TWICE
925+
// (the history family, and the published read at its own position after the
926+
// state read), so `.call(` inside the inner method reads 6 against a subset of
927+
// 5 files, and is recorded as the subset's length PLUS that one second call;
928+
// a `/meta` module called without joining the subset, or a subset entry no
929+
// longer called, still moves it. `this.routeManager.register(` stays 63 over
930+
// the eighteen files (one site moved from here to the new module),
931+
// `private register*Endpoints(` stays 16, `const registerPerItemRoute =`
932+
// stays 1, `forwarder slice:` stays 1 and `enforceAuth` stays 112: the moved
933+
// groups spell none of the last four, and neither does the seam.
913934
controls: {
914935
'private register*Endpoints(': 16,
915936
'this.routeManager.register(': 63,
916-
'registrar list length': 17,
937+
'registrar list length': 18,
917938
'data-action-routes.ts: this.routeManager.register(': 9,
918939
'batch-routes.ts: this.routeManager.register(': 5,
919940
'approvals-routes.ts: this.routeManager.register(': 7,
@@ -932,11 +953,16 @@ export const PROBE_FILE_CENSUS: readonly ProbeFileReading[] = [
932953
// has no direct site (see above).
933954
'meta-item-write-routes.ts: registerPerItemRoute(': 2,
934955
// [#23050 slice 13d] The same: the history family's module has no direct site.
935-
'meta-item-history-routes.ts: registerPerItemRoute(': 5,
956+
// [#23050 slice 13e] 5 -> 6: the published read joined it, helper-routed too.
957+
'meta-item-history-routes.ts: registerPerItemRoute(': 6,
958+
// [#23050 slice 13e] The object state-machine read registers directly.
959+
'meta-object-state-routes.ts: this.routeManager.register(': 1,
936960
// [#23050 slice 13a] Recorded AS the subset's length, not as a literal: the
937961
// measured side is the module calls inside the inner method, so the two
938962
// can only move together.
939-
'/meta subset ↔ .call( inside registerMetadataEndpointsInner': REST_SERVER_META_ROUTE_FILES.length,
963+
// [#23050 slice 13e] …PLUS ONE: `meta-item-history-routes.ts` is the one
964+
// module the inner method calls at two positions (see above).
965+
'/meta subset ↔ .call( inside registerMetadataEndpointsInner': REST_SERVER_META_ROUTE_FILES.length + 1,
940966
// Both halves of the new rule carry their own control, so neither can go
941967
// silently to zero: a helper deleted and its routes inlined back would
942968
// still read population 80, and only these two controls would notice the
@@ -1478,6 +1504,7 @@ export function deriveProbeFileCensus(): {
14781504
'forwarder slice: this.routeManager.register(': occurrences(forwarderSlice(src), mountRe),
14791505
// [#23050 slice 13a] The module calls inside the inner method — one per
14801506
// moved `/meta` group's module — recorded against the subset's length.
1507+
// [#23050 slice 13e] Two for `meta-item-history-routes.ts`, recorded as such.
14811508
'/meta subset ↔ .call( inside registerMetadataEndpointsInner': occurrences(inner, /\.call\(/g),
14821509
enforceAuth: occurrences(all, /enforceAuth/g),
14831510
},

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

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,11 @@ const SOURCE = readFileSync(resolve(HERE, 'rest-server.ts'), 'utf8');
140140
* lines, the change log's and the comparison's on their continuation lines —
141141
* two of §7's and §8's four continuation sites, which those sections find there
142142
* because they read every file here.
143+
*
144+
* [#23050 slice 13e] …and the seventh and eighth, the object state-machine read
145+
* to `meta-object-state-routes.ts` and the published read to
146+
* `meta-item-history-routes.ts`, with none: neither door resolves a caller
147+
* itself (the umbrella's wrapper does, before either handler runs).
143148
*/
144149
const SITE_FILES = REST_SERVER_REGISTRAR_FILES;
145150
const SOURCES = new Map<string, string>(SITE_FILES.map((file) => [
@@ -157,7 +162,7 @@ const siteKey = (file: string, line: number) => `${file}:${line}`;
157162
* `registerSearchEndpoints`, `registerUiEndpoints`,
158163
* `registerCrudEndpoints`) hands its moved body — and each one
159164
* `registerMetadataEndpointsInner` builds for a moved `/meta` group's module
160-
* (#23050 slices 13a, 13b, 13c and 13d), counted as that module's registrar —
165+
* (#23050 slices 13a to 13e), counted as that module's registrar —
161166
* forwards each member to the server with `(...a) => this.<member>(...a)`, so
162167
* a moved site's stack shows
163168
* that forwarder above the site itself. The site is the first censused frame
@@ -182,11 +187,17 @@ const FORWARDERS = new Set(FORWARDER_LINES.map((line) => siteKey('rest-server.ts
182187
* bodies), each handed over by its own host literal — but see
183188
* {@link MOVED_REGISTRARS_READING_NO_EXECCTX}: only one of its two literals
184189
* carries the forwarder.
190+
*
191+
* [#23050 slice 13e] So does `meta-item-history-routes.ts` (the history family
192+
* and the published read), each handed over by its own host literal the inner
193+
* method builds at its own position — and, as for the discovery module, only
194+
* the first of the two carries the forwarder.
185195
*/
186196
const EXTRA_MOVED_REGISTRARS: Readonly<Partial<Record<(typeof SITE_FILES)[number], number>>> = {
187197
'sharing-routes.ts': 1,
188198
'security-routes.ts': 1,
189199
'discovery-routes.ts': 1,
200+
'meta-item-history-routes.ts': 1,
190201
};
191202
/**
192203
* [#23050 slice 7] The moved registrars whose bodies read no `resolveExecCtx`,
@@ -201,10 +212,18 @@ const EXTRA_MOVED_REGISTRARS: Readonly<Partial<Record<(typeof SITE_FILES)[number
201212
* either (the AST walk of the body finds no read): the public form doors run
202213
* as the form grant and resolve no caller, so their host literal names no
203214
* `resolveExecCtx` member.
215+
*
216+
* [#23050 slice 13e] Neither the object state-machine read's body
217+
* (`meta-object-state-routes.ts`) nor the published read's
218+
* (`meta-item-history-routes.ts`' second registrar) reads it either (the AST
219+
* walk of each body finds no read): both doors leave the caller to the
220+
* umbrella's wrapper, so neither host literal names a `resolveExecCtx` member.
204221
*/
205222
const MOVED_REGISTRARS_READING_NO_EXECCTX: Readonly<Partial<Record<(typeof SITE_FILES)[number], number>>> = {
206223
'discovery-routes.ts': 1,
207224
'form-routes.ts': 1,
225+
'meta-item-history-routes.ts': 1,
226+
'meta-object-state-routes.ts': 1,
208227
};
209228

210229
/** A stack frame in any censused file, as `<file>:<line>:<column>`. */
@@ -802,13 +821,24 @@ describe('[#13160] §2 the consumer surface, counted from the tree', () => {
802821
// out, one forwarder's two mentions in). Seventeen forwarders now:
803822
// (17 - 1) + 3 - 2, the module carrying one host literal that reads the seam,
804823
// so neither map gains an entry.
805-
expect(SITE_FILES).toHaveLength(17);
824+
//
825+
// [#23050 slice 13e] 62 sites / 145 mentions UNCHANGED — the same MOVE. The
826+
// seventh and eighth `/meta` groups, the object state-machine read and the
827+
// published read, left for `meta-object-state-routes.ts` (a new module on the
828+
// list) and `meta-item-history-routes.ts` (already on it) with NO site, and
829+
// neither host literal the inner method builds for them names a
830+
// `resolveExecCtx` member, so no mention moved either:
831+
// 5 + 9 + 5 + 7 + 8 + 1 + 5 + 2 + 1 + 1 + 1 + 0 + 6 + 3 + 1 + 2 + 5 + 0 = 62
832+
// sites. Still seventeen forwarders: (18 - 1) + 4 - 4, the published read
833+
// counted as the history module's second registrar in BOTH maps and the new
834+
// module in `MOVED_REGISTRARS_READING_NO_EXECCTX`.
835+
expect(SITE_FILES).toHaveLength(18);
806836
expect(SITES.length).toBe(62);
807837
expect([...SOURCES.values()].reduce((n, text) => n + text.split('resolveExecCtx').length - 1, 0)).toBe(145);
808838
const extraMovedRegistrars = Object.values(EXTRA_MOVED_REGISTRARS).reduce((n, k) => n + (k ?? 0), 0);
809-
expect(extraMovedRegistrars).toBe(3);
839+
expect(extraMovedRegistrars).toBe(4);
810840
const registrarsReadingNoExecCtx = Object.values(MOVED_REGISTRARS_READING_NO_EXECCTX).reduce((n, k) => n + (k ?? 0), 0);
811-
expect(registrarsReadingNoExecCtx).toBe(2);
841+
expect(registrarsReadingNoExecCtx).toBe(4);
812842
expect(FORWARDER_LINES, 'one host-literal resolveExecCtx forwarder per moved registrar whose body reads it: one was respelt or removed, or a module moved without joining SITE_FILES')
813843
.toHaveLength(SITE_FILES.length - 1 + extraMovedRegistrars - registrarsReadingNoExecCtx);
814844
});

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,12 @@ describe('[#20338] census: every draft switch in rest-server.ts is ledgered', ()
280280
// carrying no draft switch: none of its five doors reads one, so no ledger row
281281
// changed:
282282
// 8 = 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 3 + 2 + 1 + 0, length 16 → 17.
283-
expect(REST_SERVER_REGISTRAR_FILES).toHaveLength(17);
283+
// [#23050 slice 13e] The object state-machine read moved to
284+
// `meta-object-state-routes.ts`, and the published read to
285+
// `meta-item-history-routes.ts`, carrying no draft switch: neither door reads
286+
// one, so no ledger row changed:
287+
// 8 = 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 3 + 2 + 1 + 0 + 0, length 17 → 18.
288+
expect(REST_SERVER_REGISTRAR_FILES).toHaveLength(18);
284289
expect(SOURCE_FILES.map((file) => file.fileName)).toEqual([...REST_SERVER_REGISTRAR_FILES]);
285290
expect(SITES).toHaveLength(8);
286291
});

0 commit comments

Comments
 (0)