Repository navigation
refactor(rest): move the /meta object state-machine read and the published read out of rest-server.ts (#23050 slice 13e) - #24330
Conversation
…ad out of rest-server.ts (#23050 slice 13e, move only) G7 (`GET {metaPath}/object/:name/state/:field`) moves to the new `meta-object-state-routes.ts` as `registerMetaObjectStateRoute`; G8 (`GET {metaPath}/:type/:name/published`) joins `meta-item-history-routes.ts` as `registerMetaItemPublishedRoute`. Each is called at its old position in `registerMetadataEndpointsInner` with a host literal built there and the one existing scope. The registrar list and its readers are re-pointed in the next commits. Claude-Session: https://claude.ai/code/session_01SYEJqDL3NXxrJRBVqaMu9T Co-authored-by: Claude <noreply@anthropic.com>
…3050 slice 13e) The list and its named /meta subset gain the object state-machine read's module; its readers are re-pointed in the next commit. Claude-Session: https://claude.ai/code/session_01SYEJqDL3NXxrJRBVqaMu9T Co-authored-by: Claude <noreply@anthropic.com>
…ed reads (#23050 slice 13e) The registrar-list readers learn the new module (length 17 -> 18, sums unchanged), the objectQLProvider slot census reads its two moved consumers where they now live, the dogfood blind-spot census keeps 70 / 19 / 51 with the state module's direct control and the history module's per-item control 5 -> 6, the route-envelope table declares the new module 0 / 0, the undeclared-dep ledger row follows the dynamic objectql import, and an ADR-0020 anchor restores the decision-letter count the move dropped. Claude-Session: https://claude.ai/code/session_01SYEJqDL3NXxrJRBVqaMu9T Co-authored-by: Claude <noreply@anthropic.com>
…lished read move (#23050 slice 13e) Claude-Session: https://claude.ai/code/session_01SYEJqDL3NXxrJRBVqaMu9T Co-authored-by: Claude <noreply@anthropic.com>
…state-published No path in common with this branch. Claude-Session: https://claude.ai/code/session_01SYEJqDL3NXxrJRBVqaMu9T Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 1 package(s): 13 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
⛔ 8 release-owned page(s) also name something this change touched. These are read-only:
What this run could not see
Coarse fallback — 18 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 013d5a9c46dc69d1cb9cd1d87bb62effd9fd2e28 && git checkout 013d5a9c46dc69d1cb9cd1d87bb62effd9fd2e28
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 33f700b87bd1e0c9a610418b0e573c3bf3958abf 30a3bccfdc6792d37ec3c493c4096e1f3b335d5e && git checkout -B drift-repro 33f700b87bd1e0c9a610418b0e573c3bf3958abf && git merge --no-ff 30a3bccfdc6792d37ec3c493c4096e1f3b335d5e
node scripts/docs-audit/affected-docs.mjs --json 33f700b87bd1e0c9a610418b0e573c3bf3958abf
|
席位核对 — REWORK (patch round 1: a split-off Tier H anchor PR)
The move is accepted as it stands. It was measured here independently with git's moved-line detection (
One item blocks it, and this PR cannot fix it.
The route:
Out-of-scope notes: the three Generated by Claude Code |
席位核对ACCEPT ·
Generated by Claude Code |
Part of #23050
Clause-②: no
Sub-slice 13e of the
rest-server.tssplit, the last/metasub-slice. The seventh and eighth groups ofRestServer#registerMetadataEndpointsInnermove out, each called at its old position:52ff308b8, leading comments included)GET {metaPath}/object/:name/state/:field(one direct register statement, in no per-family switch)rest-server.ts:5287–:5439(statement:5315–:5439), 153 linespackages/rest/src/meta-object-state-routes.ts,registerMetaObjectStateRouteGET {metaPath}/:type/:name/published(one bare block holding one per-item registration)rest-server.ts:5441–:5722(block:5466–:5722), 282 linespackages/rest/src/meta-item-history-routes.ts, a second exportregisterMetaItemPublishedRouteThis follows the slicing plan (
os-dev-report6239704287, entry 13e), seat 1's ruling on it6239783526, static-receiver ruling A6205442867, the provider-getter ruling6215084478, 13d'shandover_13e(report6248737371, binding where it measured) and the claim6249541908. PR #24304 (13d) is the shape copied.Nothing else moves:
dist/index.d.ts/index.d.ctsare byte-identical, and so are both bundles' 39-name export lists;rest-server.tsgoes from 6,575 to 6,196 lines (+70 / −449). The umbrellaregisterMetadataEndpointsand its guarded swap, the inner head's bindings andregisterPerItemRouteitself (only its docblock's stale text is re-worded, below), every handler body, the class head and its members,meta-item-read-gate.ts,docs/adr/**andpackages/spec/src/**are untouched.The basis for the
Clause-②: noline above: this is a move. The route table, the inner registrations, every wire answer, the.d.tsand the export list stay identical (measured below), no declaration gained or lost anexport, and the reader edits change evidence paths only.The rulings this follows
The maintainer's rule on this card, verbatim: 「每片只搬代码、路由表前后一致、门禁和文档锚点同 PR 迁完。」
Seat 1's ruling
6239783526, verbatim in the parts that bind this slice:The provider-getter ruling
6215084478: "A provider field keeps the getter shape, unbound, as slices 2–8 did."The shape
Moved, at its positions. Right after 13d's history call, the inner method now declares one arrow,
const readObjectQLProvider = () => this.objectQLProvider;(what both getters below read), then buildsobjectStateHostand callsregisterMetaObjectStateRoutewith it, then buildsitemPublishedHostand callsregisterMetaItemPublishedRoutewith it, each with the ONE existingscope(no second scope literal). Registration order is unchanged: history family, object state read, published read, then the tail comment on the retired compound twins.MetaObjectStateRouteHost, 3 members in first-read order (a symbol-resolved walk with the TypeScript compiler API, slice 12's method; no barethis, nothis[...], nofunctionkeyword, no assignment to athismember):routeManagerobjectQLProviderwiredEngineOrLoud)resolveProtocolMetaItemPublishedRouteHost, 7 members in first-read order, norouteManager(13d's hand-off corrected the plan's 6):metaTypeSingular(private static)(...a) => RestServer.metaTypeSingular(...a)resolveObjectMaskerresolveProtocolmetaItemReadGatemaskObjectDocumentobjectQLProviderresolveMetadataServiceThe published read registers through
registerPerItemRoute, which reaches the module inscopeas the inner head's ONE closure (Q1 A, no module-local copy); it still reads the server's route manager at call time, inside the umbrella's swap, and still readsmetadata.endpoints.item.The one ruled receiver token (ruling A
6205442867):RestServer.metaTypeSingular(type)becamethis.metaTypeSingular(type)in the published read. The static reads nothing but its argument.Module-level names.
wiredEngineOrLoudand theRestProtocoltype stay inrest-server.tsand are imported from it (both read only at request time).rest-server.tswith the bodies (five, measured bytsc --noEmit'snoUnusedLocals):META_ITEM_PUBLISHED_PARAMS(its re-export there stays),canonicalMetaUrlType,relateObjectSchemaMaskPosture,refuseUnknownQueryParamsandhandleRouteError. The plan named two;refuseUnknownQueryParamshad the published read as its last reader in that file, andhandleRouteErrorhad exactly these two doors. A one-line pointer comment stands at each old position.ObjectSchemaMaskEvaluationErrorstays: the class head'sresolveObjectMaskerdocblock links it, and bothtscand eslint count that use.import('@objectstack/objectql')moved with the state read.Inner-head docblock. The
registerPerItemRoutedocblock's two stale sentences (13d's out-of-scope note) now say where the per-item members live: the first four in theifblock that moved tometa-item-read-routes.ts, the later ones registered by three calls in two modules, with the state read registered between the last two. The.d.tsdoes not carry it (it is inside the method body).Proof
Builds, suites, dumps, controls and ablations ran through
os-verify-lock, every exit captured before any pipe; the shorttsxprobes ran unlocked (Deviations). Base is52ff308b8(the claim's). The move is1ed1f29bc; the registrar list grows at7684c634e; the readers are re-pointed at7c625ffe7; the changeset isea3f421d8;f2c84cc6fmergesorigin/main2b7fc52c3(eight commits, no path in common with this diff, andpackages/restbyte-identical across52ff308b8..2b7fc52c3).1. The moved text. G7, base
:5287–:5439against the module's body with one 4-space indent removed: identical over all 153 lines (sha256fbdd10f74c51…both sides). G8, base:5441–:5722againstregisterMetaItemPublishedRoute's body: the raw comparison differs on exactly one line (the receiver); withthis.metaTypeSingular(mapped back it is identical over all 282 lines (sha25679f1e7c77c4f…both sides). Every non-empty line carried the 8-space indent; no tab, no trailing whitespace.2.
.d.tsand exports.index.d.tsandindex.d.ctsare sha256e027d7941ba1908e…at base, at7c625ffe7and at the merge head (byte-identical,cmpexit 0). Both bundles load with 39 exports and one sorted name list, sha256b3246be6a1718700…, ESM == CJS, base and head. The head-only markersregisterMetaObjectStateRouteandregisterMetaItemPublishedRoutehit 2 each inindex.jsandindex.cjsat head, 0 at base.3. Full-boot legs, 20 configurations (slice 12's thirteen, plus the
/metaswitches under scoped-optional:metadata.endpoints.types,.items,.item,.maintenanceeach false, all four false,metadata.prefix: '/metadata',api.enableMetadata: false):tsxboot ofsrc/rest-server.ts):routes.json,calls.jsonandhandlers.jsonbyte-identical in all 20 configs, 60 of 60, concatenation sha256e73a487e4cfc05ab…, at the move commit and at the merge head.dist/index.js, the base bundle loaded from a gitignored copy): 60 of 60 identical, concatenationcd64ab2234f144bd…, with no normalization.4. The inner-registration leg. A recording
routeManagerand a directregisterMetadataEndpointsInner(basePath)call per base and per config: 688 recorded registrations, digested whitespace-free with the ruled receiver tokens of 13a–13e mapped back, together with method, path, metadata and arity.GET …/publishedon both bases in the 18 configs that mount it, the receiver.ObjectSchemaMaskEvaluationError(4 → 3) andcanonicalMetaUrlType(3 → 2). The token diff shows exactly three changes in that handler, the receiver and those two aliases.scripts/ablation-replace.mjs, anchor 1 → 0): the state read's 501 message gained a!(module blob58cd7759387a→0a91d9fe3459): exactly 40 of 688 inner digests moved, that route on both bases in all 20 configs, and nowhere else. Then, separately, the published read's 501 message (module blob5e850bcc6a62→6efca2bac7d6): exactly 36 of 688 moved, that route only. All 20 configs' full-boot files stayed byte-identical (60 of 60) under both. Restored each time: the blob equalsHEADandgit diff HEADis empty.5. H2: both routes still mount behind the umbrella's gate. An anonymous request at each moved route on both bases (one-off
tsxprobe, scoped-optional), base and head output byte-identical (diffexit 0):endpoints.itemon: all four mounts answer401 UNAUTHENTICATEDwith zero protocol calls and zero provider calls, and all four server-visible handlers are the umbrella's wrapper.endpoints.item: false: 150 → 126 routes; the two published mounts are gone and the two state mounts remain (the state read is in no per-family switch), still401.6. The guard ablation (the plan's shapes for 13e-state and 13e-published, four nested
ablation-replaceanchors, none occurring inside its own replacement): the umbrella stashes itsrealRouteManagercaptured above the swap;objectStateHostcarries THAT as itsrouteManager(13e-state);itemPublishedHostcarries it too, andregisterMetaItemPublishedRoutereplaces the scope's registrar with a module-local one that honours the same switch but registers on that host member (13e-published).200, the provider called once) and the anonymous published request reaches the protocol (501 NOT_IMPLEMENTED, one protocol call); none of the four handlers is the wrapper. Underendpoints.item: falsethe published mounts are still gone.Test Files 2 failed | 5 passed (7),Tests 17 failed | 135 passed (152):meta-type-read-capability.test.tsred 16 times ([security] A datasource read path serves connection topology to signed-in members below the capability the datasource admin door requires — detail withheld pending maintainer #21087, the/publishedread shape for the four datasource-family type spellings, for member, other-grant and author, plus each spelling's existing-vs-absent byte identity), andmeta-state-route-engine-outage.test.tsred once ("the route is behind the anonymous-deny gate"), so the state read does have a standing anonymous pin (the plan read none).rest-meta-auth.test.ts,meta-type-write-capability.test.ts,rest-config-mount-table.pin.test.ts,meta-route-registration-order.test.tsandmeta-disabled-package-doors.test.tsstay green.HEADandgit diff HEADis empty. No permanent test was added.7. The late-binding ablation (one-off script). The five instance methods and the provider field are planted on the server, and the static on the class, before
registerRoutes(), as recorders; four request shapes are driven over the two moved routes, then everything is planted again and the shapes are driven again.MEASURElines byte-identical to base): all 7 members, the provider field included, are reached late after the re-plant,early calls after re-plant: 0.objectStateHost's getter turned into a value copied at host-build time givesearly calls after re-plant: 2 ["early:objectQLProvider"], exit 1.resolveMetadataService: this.resolveMetadataService.bind(this)givesearly calls after re-plant: 2 ["early:resolveMetadataService"], exit 1.HEADandgit diff HEADis empty.Readers re-pointed (sums unchanged, no gate loosened)
rest-server-registrar-files.tsgainsmeta-object-state-routes.tsinREST_SERVER_REGISTRAR_FILES(length 17 → 18) and inREST_SERVER_META_ROUTE_FILES(4 → 5);meta-item-history-routes.tswas already on both, and its comments now name the published read.execctx-consumer-census.test.tsresolveExecCtxmember. Still seventeen forwarders: (18 − 1) + 4 − 4, the published read counted as the history module's second registrar inEXTRA_MOVED_REGISTRARSand inMOVED_REGISTRARS_READING_NO_EXECCTX(the discovery module's precedent), the new module in the lattermeta-draft-read-door-census.test.tsrest-server-query-number-census.test.tsrest-server-canonical-query-ast.test.ts(repo project)rest-server-docblock-position.test.tsrest-server.tskeeps its 161ui-view-route-identity/-tenancymeasurement teststhis.enforceAuth(60,this.resolveExecCtx(79, unchangedobjectql-slot-consumer-census.test.tsSLOT_FILESgains both modules; the getter pin (SLOT_FILES.length - 1) reads 3 (batch, state, published);HOST_MEMBER_TYPEis 1 in each module; the comment-dropping CONTROL reads the retired-spelling comment where it now lives,meta-object-state-routes.ts, with a positive read of that same file beside itmeta-state-route-engine-outage.test.tsimport()now namemeta-object-state-routes.tsauthz-conformance.test.tsauthz-probe-blind-spot.census.tsthis.routeManager.register(= 1; the history module'sregisterPerItemRoute(5 → 6; whole-populationregisterPerItemRoute(stays 8 (0 + 2 + 6);this.routeManager.register(stays 63. One control re-keyed, not relaxed: the inner method now calls the history module twice, so.call(inside it reads 6 against a subset of 5 files; it is recorded asREST_SERVER_META_ROUTE_FILES.length + 1, so a/metamodule called without joining the subset, or a subset entry no longer called, still moves itscripts/check-route-envelope.mjs(MODULESonly)rest-server.tsstays 2 / 2scripts/check-undeclared-dep-imports.mjs(LEDGER)@objectstack/objectqloptional-runtime-probe row'sfilefollows the dynamic import tometa-object-state-routes.ts; itswhynow says "query-multiplicity.tsandrest-server.tsduck-type the same seam" (was "the rest ofrest-server.ts")scripts/adr-anchors/packages__rest__src__meta-object-state-routes.ts.json(new)ADR-0020 D3.3left the anchored surface silently; the anchor puts the module on it (its header, its moved body and the anchor's invariant each cite D3.3)content/docs/permissions/system-context.mdxcheck-system-context-censusreads OK before and after (142 sites, 136/136 symbols, 159 anchors): neither moved door holds anisSystemreadRed before re-point, measured. At the move commit
1ed1f29bc(list not grown): the slot censusTests 4 failed | 156 passed (160)over its eight-file set; dogfoodTests 2 failed | 45 passed (47)(population 69 against 70, the state read's site out of reach; a control off);check:route-envelopeexit 1 (meta-object-state-routes.tsNOT DECLARED);check:undeclared-dep-importsexit 1 (the row stale, the import unledgered);check-adr-anchorsexit 0 at 1782 (the silent drop the anchor repairs);check-system-context-censusexit 0, unchanged. At7684c634e(list grown, readers at base text): rest localTests 11 failed | 151 passed (162), rest repoTests 2 failed | 105 passed | 18 skipped (125), dogfoodTests 1 failed | 46 passed (47). At7c625ffe7:Tests 162 passed (162),Tests 107 passed | 18 skipped (125),Tests 108 passed (108). (Dogfoodauthz-conformance.test.tscould not load@objectstack/verifybefore the whole-workspace build at the first two commits: NOT MEASURED there, measured green at7c625ffe7.)Tests and gates at the final head
At the final head
f2c84cc6f(the merge), underos-verify-lock, every exit captured before any pipe:pnpm --filter @objectstack/rest typecheck: exit 0 (check:test-typecheck: OK — … 0 file(s) / 0 error(s)).local(whole project): exit 0,Test Files 295 passed (295),Tests 6051 passed | 326 skipped (6377)(436.87 s on a shared box).repo(this diff edits one of its tests): exit 0,Test Files 5 passed (5),Tests 278 passed | 18 skipped (296).pnpm --filter @objectstack/dogfood typecheck: exit 0. Dogfoodauthz-probe-blind-spot.test.ts+authz-conformance.test.ts: exit 0,Tests 108 passed (108).repo, narrowed tosrc/domains/meta-list-projection-parity.test.ts(the one runtime test that readsrest-server.tsfrom disk): exit 0,Tests 739 passed (739). The rest of runtime's and core'srepoprojects are CI's (Test Core).Gates:
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack(no paths) atf2c84cc6fderives 92 commands over this branch's 19 paths against merge base2b7fc52c3(1,444 changed lines, +942 / −502). All 92 ran sequentially: 92 exit 0.--ran:Run reconciliation — 92 derived, 92 run, 0 NOT-MEASURED, 0 UNRUN.Readings:check:route-envelope29 route modules (9 conformant, 19 ratcheted, 1 exempt);check:adr-anchors75 anchored files, 1785 decision letters;check-system-context-censusOK (142 sites, 136/136 symbols, 159 anchors);check:undeclared-dep-imports1 ledger row, evidence intact;check-issue-citations49 judged across 4 files, 48 resolve and 1 resolves as a pull request;check:cross-package-test-inputsOK;check:nul-bytesOK;check:dual-build-cjs-loads111 entry points across 69 packages. Beside the union:node scripts/check-platform-checklist.mjs --changed-from origin/mainexit 0 (10 anchors judged, 0 lost);pnpm exec eslint --no-inline-configover the 17 changed.ts/.mjsfiles, exit 0 with no output;node scripts/pm/check-governed-merges.mjs --branch HEADexit 0, 0 of 19 paths governed. The repo-widepnpm lintis CI's.origin/mainhas since moved to117301705(#24319, #24317:packages/adapters/hono,packages/platform-objects), no path in common with this diff; not merged again.Acceptance notes
rest-server-audit-org-scope.test.ts:23says "the/publishedroute's comment inrest-server.tsrecords that inventing org plumbing … would be a smuggled seam". The published read's comment has not said that since its[ADR-0131 D6]paragraph replaced it, so the pointer was already dead before this move; not edited here,carrier:none.packages/spec/liveness/metadata_endpoints.json'sendpoints.itemevidence says the inner method'sregisterPerItemRoutegates "the per-item PUT/DELETE and the history family"; still true of the gate (the closure stays in the inner head), and the published read now joins those call sites inmeta-item-history-routes.ts. The spec seat's file, still resolving, not edited (13d's note,carrier:none).registerMetadataEndpointsInneris its head (the three bindings,registerPerItemRouteand the scope), six host literals with their six calls, and the tail comment on the retired compound twins. ADR-0076's D11 status line and its section 4 size note are the maintainer's Tier H carry, due now; nothing underdocs/adr/is touched here.Generated by Claude Code