Repository navigation
Commit e9bc60b
Part of #23050
Clause-②: no
Sub-slice **13c** of the `rest-server.ts` split: the fifth `/meta`
group. Group G5 of `RestServer#registerMetadataEndpointsInner` is two
statements, the per-item writes, of 405 lines (base
`rest-server.ts:5284`–`:5688` at `9975c26ae`): `registerPerItemRoute({
method: 'PUT', … })` at `:5288` (the item save, `PUT
{metaPath}/:type/:name`) and `registerPerItemRoute({ method: 'DELETE', …
})` at `:5528` (the reset to the artifact default, `DELETE
{metaPath}/:type/:name`). They move, re-indented one level, to a new
module, `packages/rest/src/meta-item-write-routes.ts`, as
`registerMetaItemWriteRoutes`. It is the first `registerPerItemRoute`
pass-through: the module registers nothing on the route manager itself.
This follows the slicing plan (`os-dev-report` `6239704287`, sub-slice
13c), seat 1's ruling on it `6239783526` (quoted below), static-receiver
ruling A `6205442867`, 13b's `handover_13c` list (report `6244193505`)
and the claim `6244810707`. PR #24240 (13b, `646303eae`) is the shape
copied.
Nothing else moves:
- the route table, the ordered server registrations, every
server-visible handler and every INNER registration (method, path,
metadata, arity, handler digest) are identical, base vs head, in 20
configurations;
- the published `dist/index.d.ts` / `index.d.cts` are byte-identical,
and so are both bundles' 39-name export lists;
- one token of the moved body changed, the ruled receiver (below).
`rest-server.ts` goes from 7,746 to 7,363 lines. G4 and G6–G8, the
umbrella `registerMetadataEndpoints` and its guarded swap, the inner
head's bindings and `registerPerItemRoute` itself, every handler body,
the class head, `meta-item-read-gate.ts`, `docs/adr/**` and
`packages/spec/src/**` are untouched. #23050 stays open for 13d–13e.
## The ruling this follows (seat 1, `6239783526`, verbatim)
> - **Q1, A.** The four head bindings (`metadata`, `metaPath`,
`isScoped`, `registerPerItemRoute`) reach each module as ONE `scope:
MetaRouteScope` parameter, built once in the inner head. Each module
destructures only what it uses, and body tokens are unchanged. The host
stays class members only.
> - `registerPerItemRoute` stays one closure that reads RestServer's
guarded `routeManager` at call time. ⛔ No module-local copy: that would
be a second copy of a helper (rule 2).
> - **Q2, A.** 13a's `meta-collection-routes.ts` hosts `MetaRouteScope`
and takes `TransportScopedMetaRequest` from `ui-routes.ts`, re-pointing
its readers in that PR. ⛔ Not `meta-item-read-gate.ts` while #24208 is
open.
> - **Q3, A.** `rest-server-registrar-files.ts` exports a named subset,
the `/meta` modules. The dogfood census's reachable count becomes "the
umbrella's sites plus every site in that subset", and a control pins the
subset against the number of module calls inside the inner method. This
is declared at 13a with the anonymous-`401` ablation as the runtime
proof.
> - From 13c on, a module with no direct register site is controlled on
`registerPerItemRoute(` instead.
> - ⛔ No naming convention, and ⛔ never "let blindSpot rise".
> - **Q4, A.** `STORED_VERSION_DOOR_POLICY`, a `private static readonly`
field set once at class evaluation, is handed over by value. 13b and 13d
name it in their claims, together with each sub-slice's static-receiver
tokens (13 in all, ruling A `6205442867`).
> - **Q5, A.** G4 (891 lines, one `if`) moves whole in 13b, with its
switch. Slice 1 moved 1,181 lines. The fallback, if the review budget
binds, is B: a move-only split called inside the remaining brace. ⛔ C
(re-shaping the registrations) is not a move and not this card's.
> - **Q6.** A for the two body-only 13b helpers
(`notImplementedRefusalAnswer`, `anonymousFormIntakeFingerprint`): they
move with the body. B for `refuseNonAuthoringCaller` (13d): it stays and
is exported, because its callee `mayReadAuthoringTrail` is a docs anchor
(`system-context.mdx:108`). Two-home helpers (`sendMetaItemAbsent`,
`stampAnonymousFormIntakeWarnings`) stay and gain `export`, as in slices
1 and 2.
>
> **Binding on every sub-slice (from the plan's measurements):**
> - **Hosts are built inside `registerMetadataEndpointsInner`**, at the
position of the statements they replace, with `routeManager` passed by
value. ⛔ Never in `registerRoutes`, the constructor, an instance cache
or the umbrella above the swap: those capture the real manager, and the
moved routes would mount outside the anonymous-deny gate (#3963) and the
type-level admissions (#21087, #21124).
> - Each sub-slice proves this with the guard ablation in the plan: an
anonymous request at every moved route gets `401` on head, and the
ablation does not.
> - **The proof gains an inner-registration leg.** Slice 12's handler
digest is blind to `/meta`, because every route's server-visible handler
is the same guard wrapper. So each sub-slice digests the inner handlers
through a recording `routeManager` and a direct
`registerMetadataEndpointsInner(basePath)` call per base, with the ruled
receiver tokens mapped back. A one-character positive control must move
exactly that route's inner digest.
> - The full-boot legs stay: `getRoutes()`, ordered registrations,
`.d.ts`/`.d.cts`, and the 39-name export list.
> - The config matrix is slice 12's 13 configs plus the `/meta` switches
the plan names.
> - **Readers move in the same PR**, loud and silent alike, as the plan
lists per sub-slice. Cross-lane edits are declared on #6017 (spec:
liveness and gate tables) and #6023 (devx: checklist) before the PR. The
`system-context.mdx` rows change with the sub-slice that moves their
code.
## The shape
**Moved, at its position.** In the inner method, right after 13b's
`registerMetaItemReadRoutes.call(itemReadHost, scope);`, the head now
builds the host literal `itemWriteHost` and calls
`registerMetaItemWriteRoutes.call(itemWriteHost, scope)` with the ONE
existing `scope` (no second one is built). Registration order is
unchanged: after the per-item reads, above the history family.
**The host, `MetaItemWriteRouteHost`: 5 members in first-read order** (a
symbol-resolved walk of G5 with the TypeScript 6.0.3 compiler API, 13b's
method; H1 of the dispatch holds: `PUT` at `:5288`–`:5523`, `DELETE` at
`:5528`–`:5688`, the history family's first statement at `:5696`, the
one static receiver at `:5340`):
| member | reads | handed over as |
|---|---:|---|
| `resolveExecCtx` | 2 | closure `(...a) => this.resolveExecCtx(...a)`,
spelled exactly as the execctx census's forwarder |
| `metaSaveVerdict` (private static) | 1 | closure `(...a) =>
RestServer.metaSaveVerdict(...a)`, typed `(typeof
RestServer)['metaSaveVerdict']` |
| `walledCatalogRefusal` | 2 | closure |
| `resolveProtocol` | 2 | closure |
| `resolveMetaWriteActor` | 2 | closure |
**No `routeManager` member (the plan's 5, H1).** The body reads the
route manager nowhere: both statements register through
`registerPerItemRoute`, which reaches the module in `scope` as the inner
head's ONE closure (Q1 A, ⛔ no module-local copy). That closure reads
the server's `this.routeManager` at call time; every call runs during
the inner call, inside the umbrella's swap, so both routes still mount
behind the wrapping registrar and still answer to
`metadata.endpoints.item`, which the same closure reads. The module
header and the comment above the literal say why. The walk found no bare
`this`, no `this[...]`, no `function` keyword and no assignment to a
`this` member, and the body reads no instance FIELD at request time, so
no member is a getter.
**Host placement (binding).** The literal is built inside
`registerMetadataEndpointsInner`, at G5's old position. It is not built
in `registerRoutes`, the constructor, an instance cache or the umbrella
above the swap. For a pass-through module the swap is read through
`registerPerItemRoute`'s call-time `this.routeManager`, so the guard
ablation below plants the wrong shape this module could take: a
module-local registrar reading a manager captured above the swap.
**The scope (Q1 A).** The module opens with `const { metaPath, isScoped,
registerPerItemRoute } = scope;`, the three bindings it reads. It does
not read `metadata`: the per-item switch is read inside
`registerPerItemRoute`, where it always was.
**The one changed token (ruling A, named in the claim).** At base
`rest-server.ts:5340` the save door calls
`RestServer.metaSaveVerdict(ctx)`. It is now `this.metaSaveVerdict(ctx)`
through the host (module `:187`). The static reads nothing but its
argument, so the receiver is the whole difference.
**Module-level names** (the same walk, base vs head):
- **Imported from `./rest-server.js`:** `META_ITEM_RESET_PARAMS` (stays:
`rest-server-meta-member-selector.test.ts` imports it from there) and
`metaItemPackageBinding` (on the package entry). Both are read only at
request time, so the two modules importing each other cannot see one
uninitialised.
- **Imports that left `rest-server.ts`** (read only by the moved code,
so `noUnusedLocals` would refuse them; a pointer comment is left at
each): the local `META_ITEM_SAVE_PARAMS` import
(`./meta-item-read-gate.js`; the re-export that names it stays),
`metaSaveRequestOptions` (`./meta-save-request.js`), and
`SaveMetaItemRequest` and `DeleteMetaItemRequest`
(`@objectstack/spec/api`). Exactly the plan's four.
`META_ITEM_RESET_PARAMS` stays, as the plan says.
- **Unchanged provenance:** every other name
(`rethrowAuthzStoreUnavailable`, `metaWriteCapabilityVerdict`,
`handleRouteError`, `META_ITEM_MEMBER_PARAM`, `metaMemberSelector`,
`refuseUnknownQueryParams`, `refuseRepeatedQueryParams`) is imported
from the module `rest-server.ts` imports it from, and is still read
there too. `MetaRouteScope` and `TransportScopedMetaRequest` come from
`./meta-collection-routes.js`.
## Proof
All runs went through `os-verify-lock`, with every exit captured before
any pipe, unless noted. The base is `9975c26ae`, measured in a read-only
comparison worktree. The head is `3750ddecc`; the merge head `39912f9e1`
adds one merge of `origin/main` `cbfa5e433` (#24244), which touches
`packages/runtime` only, outside `@objectstack/rest`'s dependency
closure (`core`, `metadata`, `metadata-core`, `observability`,
`platform-objects`, `service-package`, `spec`, `types`), so main vs
merge head reads as base vs head; the final commit `892a86538` is a
comment in a gate script.
**1. The moved text.** `git show
9975c26:packages/rest/src/rest-server.ts | sed -n 5284,5688p`, with
one 4-space indent removed, was compared with
`meta-item-write-routes.ts` `:131`–`:535`, the body after the
destructuring line.
- The raw `diff` exits 1 on exactly one line: the receiver token
(`RestServer.metaSaveVerdict(ctx)` → `this.metaSaveVerdict(ctx)`).
- With `this.metaSaveVerdict` mapped back to
`RestServer.metaSaveVerdict`, `diff` exits 0 over all 405 lines. Both
sides are sha256
`a8935ad228caf0c790c7c1314782c6eb4405ca639cd95d8f5b453982f8069bb6`.
- Every non-empty line of the range carried the 8-space indent, and no
line has trailing whitespace.
**2. `.d.ts` and exports.** `index.d.ts` and `index.d.cts` are sha256
`02f1c167ccbea3298a15ea77ac634b50500346fc489efec21828eb5a7ab5928a` at
base, at head and at the merge head.
- The head-only marker `registerMetaItemWriteRoutes` hits 2 in each of
`index.js` / `index.cjs` at head and at the merge head, and 0 at base.
- Both bundles load with 39 exports and one sorted name list, sha256
`b3246be6a1718700…`, ESM == CJS, base and head.
**3. Full-boot legs (slice 12's method), 20 configurations:** slice 12's
thirteen, then the `/meta` switches under scoped-optional:
`metadata.endpoints.types`, `.items`, `.item` and `.maintenance` each
false; all four false; `metadata.prefix: '/metadata'`;
`api.enableMetadata: false`.
- **Source leg** (a `tsx` boot of `src/rest-server.ts`): `routes.json`,
`calls.json` and `handlers.json` are byte-identical in all 20 configs:
60 of 60 files, concatenation sha256 `bd4f6685175a61ec…` on both trees.
- **Bundle leg** (the same dump against the built `dist/index.js`): 60
of 60 identical, concatenation `20103136b32ff534…`, under one declared
normalization: esbuild's numeric alias suffix on an import name two
bundled modules share. Measured by an identifier-set diff of the two
bundles, the ESM head gains exactly `itemWriteHost`,
`registerMetaItemWriteRoutes` and two renumbered aliases
(`rethrowAuthzStoreUnavailable5`, `metaWriteCapabilityVerdict2`), and
loses none; those two names are the ones normalized. (The CJS bundle
gains `itemWriteHost`, `registerMetaItemWriteRoutes`, `import_core38`
and `import_metadata_core17`.)
- Both concatenation hashes equal 13b's own readings: the full boot is
unchanged across both moves.
**4. The inner-registration leg (the plan's `proof_method`).** Each
config builds a `RestServer` with a recording `routeManager` and calls
`registerMetadataEndpointsInner(basePath)` directly for `/api/v1` and
`/api/v1/environments/:environmentId`: 688 recorded registrations over
the 20 configs, digested whitespace-free with the ruled receiver tokens
mapped back (13b's three plus `metaSaveVerdict`), together with method,
path, metadata and arity.
- **Source leg:** 688 of 688 identical, same order; the digest-list
sha256 is
`4f306a2a19ffdd181b36b43e4d8b49d0844dc396c50a3144e8221aeab48b4511` on
both trees (13b's reading too). Unnormalized, exactly 36 digests differ:
`PUT …/:type/:name` on both bases in the 18 configs that mount it, the
receiver token. The `DELETE` digests are identical raw.
- **Bundle leg:** 688 of 688 identical under the two alias names;
digest-list sha256
`535abfd10375066c385a596bf97dd8039252b8fe3f38ebb7fc78e073cf8f98c6` on
both trees.
- **Positive controls** (one character each, through
`scripts/ablation-replace.mjs`, anchor 1 → 0): the `PUT` door's 501
message gained a `!` (blob `395d5e6ec2c9` → `82dd302865c5`), then,
separately, the `DELETE` door's (→ `7b4819a6f8d5`). Each moved the inner
digests of exactly its own route, on both bases, in the 18 configs that
mount it: 36 of 688 each, and nowhere else. All 20 configs' full-boot
`routes` / `calls` / `handlers` stayed byte-identical (60 of 60): the
blind spot the inner leg covers. Restored each time: the blob equals
`HEAD` and `git diff HEAD` is empty.
**5. H2: the handed-over closure is the inner method's own.** An
anonymous request at each moved route on both bases (one-off `tsx`
probe, scoped-optional), base and head identical:
- `endpoints.item` on: `PUT` and `DELETE` answer `401 UNAUTHENTICATED`
with zero protocol calls (4 of 4), and all four server-visible handlers
are the umbrella's wrapper.
- `endpoints.item: false`: both routes are gone on both bases (150 → 126
routes, 0 `PUT` / `DELETE` item mounts), on both trees.
**6. The guard ablation** (the plan's shape for 13c, 13d and
13e-published). Two literal anchors, nested: the umbrella stashes its
`realRouteManager` (captured above the swap) and `itemWriteHost` carries
it as a `routeManager` member (`rest-server.ts` blob `2816281785c6` →
`1528afc7f2dd`, a 281-line anchor from the umbrella's `const
realRouteManager = this.routeManager;` through `itemWriteHost`'s opening
line), and the module replaces the scope's `registerPerItemRoute` with a
module-local registrar that honours the same switch but registers on
that host member (`meta-item-write-routes.ts` blob `395d5e6ec2c9` →
`6fdf0913c66a`).
- **Ablation:** an anonymous `PUT` and `DELETE` on both bases answer
`403 FORBIDDEN` from the door's own capability gate, not `401`, and none
of the four handlers is the wrapper. Under `endpoints.item: false` the
routes are still gone, so the switch alone cannot tell the two shapes
apart; the gate can.
- **Standing pins under the ablation:** `Test Files 1 failed | 4 passed
(5)`, `Tests 9 failed | 121 passed (130)`:
`meta-type-write-capability.test.ts` is red 9 times (#21124: the
datasource and datasources write shapes for member, other-grant and
author, the existing-vs-absent byte identity, and the admin-door parity
for the author bearer). `rest-meta-auth.test.ts`,
`meta-type-read-capability.test.ts`,
`rest-config-mount-table.pin.test.ts` and
`meta-route-registration-order.test.ts` stay green.
- Restored, both files: the blob equals `HEAD` and `git diff HEAD` is
empty. No permanent test was added.
**7. The late-binding ablation** (one-off script). The 4 instance
methods are planted on the server and the static on the class before
`registerRoutes()`, as recorders that delegate to the originals. Six
request shapes are driven over the two moved routes (a plain save,
`?mode=draft`, `?force=true` with `If-Match`, a plain reset,
`?state=draft`, `?dropStorage=true` with `If-Match`), each answering 200
after the expected protocol call. Then everything is planted again and
the shapes are driven again.
- **Head** (byte-identical `MEASURE` lines to base): all 5 closure
members are reached before and after the re-plant, with `early calls
after re-plant: 0`.
- **Ablation:** `walledCatalogRefusal:
this.walledCatalogRefusal.bind(this)` (blob `2816281785c6` →
`fde53002af3c`) gives `early calls after re-plant: 6
["early:walledCatalogRefusal"]` and 4 late members, exit 1. Restored:
the blob equals `HEAD` and `git diff HEAD` is empty.
## Readers re-pointed (sums unchanged, no gate loosened)
`rest-server-registrar-files.ts` gains `meta-item-write-routes.ts` in
`REST_SERVER_REGISTRAR_FILES` (length 15 → 16) and in the named `/meta`
subset `REST_SERVER_META_ROUTE_FILES` (2 → 3). The dogfood control
counts `.call(` inside the inner method, now 3, so the subset and the
call moved together.
| reader | sum over the list | change |
|---|---|---|
| `execctx-consumer-census.test.ts` | 62 sites = 10 + 9 + 5 + 7 + 8 + 1
+ 5 + 2 + 1 + 1 + 1 + 0 + 6 + 3 + 1 + 2; mentions 137 → 141 | The two
sites are locally caught on their invocation lines, as before, so the
split stays 16 / 46 (12 on the invocation line). `rest-server.ts` stays
at 55 mentions (two sites out, one forwarder's two in); the module
carries 4. Sixteen forwarders: (16 − 1) + 3 − 2 |
| `meta-draft-read-door-census.test.ts` | 8 = 0 + 0 + 0 + 0 + 0 + 2 + 0
×7 + 3 + 2 + 1 | The reset's `?state=draft` (a `write` row) moved; keys
name routes, so no ledger row changed |
| `rest-server-query-number-census.test.ts` | 9 = 8 + 1 + 0 ×14 | — |
| `rest-server-canonical-query-ast.test.ts` (`repo`) | 4 = 0 + 3 + 0 ×10
+ 1 + 0 + 0 + 0 | Floor `meta-item-write-routes.ts: 0` (the save
mapping's one `query` key sits mid-line) |
| `rest-server-docblock-position.test.ts` | floors sum 59 → 62 | The
module carries 3: the header, the host interface and the function.
`rest-server.ts` keeps its 161 blocks |
| `ui-view-route-identity` / `-tenancy` measurement tests |
`this.enforceAuth(` 60, `this.resolveExecCtx(` 77 → 78 | +1 for the
forwarder. The ownership guard is still 1 call site and 1 forwarder |
| dogfood `authz-conformance.test.ts` | 0 tripwire hits over sixteen
files | Length 15 → 16 |
| dogfood `authz-probe-blind-spot.census.ts` | 70 / 19 / 51 unchanged |
Reachable holds by 13a's Q3 rule, with no rule change. Two controls
re-keyed, as ruled (Q3: "From 13c on, a module with no direct register
site is controlled on `registerPerItemRoute(` instead"): the module's
own control is `meta-item-write-routes.ts: registerPerItemRoute(` 2 (its
`this.routeManager.register(` count is 0, which this census reads as
instrument failure); the derivation now emits one control per spelling a
module spells, so a module that stops spelling its recorded one makes
that control vanish, loudly. The whole-population
`registerPerItemRoute(` control is re-anchored over the population
rule's own haystack (this file plus every module on the list), where it
stays 8 = 6 + 2; over `rest-server.ts` alone it would read 6. `/meta
subset ↔ .call(` 3; `this.routeManager.register(` 63, `private
register*Endpoints(` 16, `const registerPerItemRoute =` 1 and
`enforceAuth` 112 unchanged |
Readers outside the list:
- **`scripts/check-route-envelope.mjs`** (`MODULES` only; declared on
#6017, `6244817361`). `meta-item-write-routes.ts` is declared
`dialectOnly` with ratchet #9559 at `stringError 0` / `siblingCode 0`:
both doors' 403, 400 and 501 bodies are the nested `{ error: { code,
message } }`. `rest-server.ts` keeps `7` / `3`. Output: 26 → 27 modules
audited, 16 → 17 ratcheted; `--self-test` exit 0.
- **`content/docs/permissions/system-context.mdx` row 50** (declared on
#20163, `6244820755`; H4 holds). The reset's `isSystem` read
(`metaWriteCapabilityVerdict({ isSystem: ctx?.isSystem === true, … })`)
moved with it, so at the move commit `check-system-context-census`
exited 1: `[file-without-a-row]
packages/rest/src/meta-item-write-routes.ts holds 1 elevation read
site(s) in 1 symbol(s) (registerMetaItemWriteRoutes)`. Row 50 gains
`packages/rest/src/meta-item-write-routes.ts#registerMetaItemWriteRoutes`
beside the inner anchor, which keeps resolving (publish and rollback
still read there). Made green by the anchor, ⛔ not by a
`NON_READ_ANCHORS` row: `142 elevation read sites … across 65 files,
living in 123 symbol(s); the page cites 136 symbol(s) against 136
required, over 159 anchors` (base: 64 files, 122 symbols, 135 / 135, 158
anchors).
-
**`scripts/adr-anchors/packages__rest__src__meta-item-write-routes.ts.json`**
(NEW; declared as possible on #6017). `check-adr-anchors` checks
`ADR-NNNN Dk` letters only in anchored files. The move took G5's eight
letter citations (ADR-0066 D1 ×2, ADR-0131 D3 ×2, ADR-0131 D6 ×4) out of
the anchored `rest-server.ts`, and the gate read 1783 → 1775 while
green: a reader that narrowed silently. This anchors ADR-0066, ADR-0131
and ADR-0106; its invariant adds no letter citation; the reading is back
to 1783 (`73 anchored file(s)`).
- **Examined, unaffected:**
- `packages/runtime/src/domains/meta-list-projection-parity.test.ts`
derives `GET` handlers only (the item, tree, layers and list reads); G5
holds none, and the test was green at the move commit (`Tests 739 passed
(739)`).
- `packages/spec/liveness/metadata_endpoints.json` (the plan: "No
liveness edit"): the `endpoints.item` row's second citation,
`rest-server.ts#registerMetadataEndpointsInner` (`registerPerItemRoute`
gates the per-item `PUT` / `DELETE` and the history family), stays true,
because the switch is read in that closure, which stays in the inner
head. `check:liveness` was green at the move commit and at head.
- `docs/qa/platform-checklist/areas/api-backend.json`' inner anchor
("metaPath and registerPerItemRoute") stays true;
`check:platform-checklist` was green at the move commit. No other
checklist or docs anchor names a G5 symbol.
**Red before the re-points**, each measured with the readers at their
base text:
- **At the move commit `344cb18d8`:**
- Six list readers read `Test Files 2 failed | 4 passed (6)`, `Tests 5
failed | 121 passed (126)`. The execctx census failed three times
(`expected 60 to be 62`, the caught split `expected 10 to be 12`, and
§7's control `expected 10 to be greater than or equal to 12`); the draft
census twice (`expected [ …(7) ] to deeply equal [ …(8) ]`, `to have a
length of 8 but got 7`).
- The dogfood pair read `Tests 2 failed | 106 passed (108)`: population
`expected 68 to be 70`, and `/meta subset ↔ .call(` `expected 3 to be
2`.
- `check:route-envelope` exited 1: `meta-item-write-routes.ts` NOT
DECLARED. `check-system-context-census` exited 1 (above).
- `check-adr-anchors` stayed green at 1775 (base 1783);
`check:liveness`, `check:platform-checklist`, the runtime parity test
and `repo` (`Tests 266 passed | 15 skipped (281)`) stayed green. Nine
standing behaviour pins of the moved doors read `Tests 205 passed
(205)`.
- **At `9ce268e26`** (the list grown, the readers not yet re-pointed):
seven list readers read `Test Files 6 failed | 1 passed (7)`, `Tests 7
failed | 127 passed (134)` (the length pins and the unfloored module);
`repo` read `Tests 2 failed | 268 passed | 16 skipped (286)`; the
dogfood pair read `Tests 2 failed | 106 passed (108)` (`registrar list
length` and the tripwire length).
- **Green after the re-points** (`cbd7d7a4c`, then the merge head).
## Changeset
`.changeset/23050-s13c-meta-item-write-routes-move.md` is a
`@objectstack/rest` patch (`Clause-②: no`, move-only). The shipped
`index.js` / `index.cjs` bytes change (the marker above); the
declarations and exports do not. `skip-changeset` does not apply.
## Acceptance notes
- The plan's 13c list held: the host's 5 members, the one receiver, the
four leaving imports, the 16 / 3 list lengths, the census's two control
changes, `MODULES` at 0 / 0 and the row-50 anchor. Beyond it, the ADR
anchor (the handover's conditional item) was owed: the letter count
dropped by 8. No reader outside the plan's list and 13b's handover read
anything G5 held.
- The moved comments keep their deixis: "the `PUT` twins", "next door"
and "a few hundred lines up" describe the inner method's order as it
was, in which `POST {metaPath}/_migrate-stored` (now in
`meta-collection-routes.ts`) sat above these doors. The module header
says so rather than editing moved text.
- The inner method's `registerPerItemRoute` docblock still says the
first four members of the per-item face "are inside the `if` block
further down" (13b moved that block to `meta-item-read-routes.ts`). It
is the inner head's text, a hold-off for this slice, and is left for the
slice that re-reads that head.
- Carried from earlier slices, untouched: `FOLLOW-UPS.md:613` (E1)
prose, `ui-routes.ts`' "52 sites" comment and `email-routes.ts`'
double-mount header.
## Gates and tests
The final head is `892a86538`: one merge of `origin/main` `cbfa5e433`
(#24244, `packages/runtime` only), then a comment-only fix to the new
`MODULES` note in `scripts/check-route-envelope.mjs`. The tests below
ran at the merge head `39912f9e1`; that last commit changes no file any
test reads. The gate union ran at `892a86538`.
- **Build.** At base, `pnpm turbo run build
--filter=@objectstack/rest... --concurrency=2` exited 0 (`Tasks: 25
successful, 25 total`). At the move commit, `pnpm turbo run build
--filter=@objectstack/rest... --filter=@objectstack/dogfood...
--filter=@objectstack/runtime... --concurrency=2` exited 0 (`Tasks: 66
successful, 66 total`). At the merge head, a whole-workspace `pnpm turbo
run build --concurrency=2` exited 0 (`Tasks: 77 successful, 77 total`),
for the dist readers. No package source was edited while turbo built it;
the base dist reads 0 head-only markers.
- **Typecheck.** `pnpm --filter @objectstack/rest typecheck` exits 0
(`check:test-typecheck: OK … 0 file(s) / 0 error(s)`). `pnpm --filter
@objectstack/dogfood typecheck` exits 0.
- **`@objectstack/rest`.** `local`: `Test Files 294 passed (294)`,
`Tests 6032 passed | 326 skipped (6358)`, including
`meta-route-registration-order.test.ts`,
`rest-config-mount-table.pin.test.ts` and the moved doors' pins
(`meta-type-write-capability`, `rest-server-meta-member-selector`,
`rest-server-meta-door-closed-sets`, `meta-501-envelope`,
`meta-write-actor-identity`, `meta-write-door-capability-enumeration`).
`repo` (its `test:repo`, run locally because this diff edits
`rest-server-canonical-query-ast.test.ts`): `Test Files 5 passed (5)`,
`Tests 270 passed | 16 skipped (286)`.
- **Dogfood pair** (`authz-probe-blind-spot.test.ts`,
`authz-conformance.test.ts`): `Test Files 2 passed (2)`, `Tests 108
passed (108)`. The dogfood shards skip on PRs and in the queue, so this
local run is the evidence.
- **`test:repo`.** `@objectstack/runtime`: `Test Files 3 passed (3)`,
`Tests 808 passed (808)`, `meta-list-projection-parity.test.ts` among
them. `@objectstack/core`: `Test Files 6 passed (6)`, `Tests 86 passed
(86)` (its security tests read `rest-server.ts` from disk).
- **Lint.** `pnpm exec eslint --no-inline-config` over the 13 changed
`.ts` / `.mjs` files exits 0, with no output. The repo-wide `pnpm lint`
belongs to CI.
- **Gate union.** `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` (no paths) at `892a86538` derives 117
commands; its stderr names the commit, and the `--repo` assertion holds.
The change set is 16 paths vs merge base `cbfa5e433`, 1,152 changed
lines (+722 / −430), under 3,000.
- All 117 exit 0, each captured before any pipe.
- `--ran`: `Run reconciliation — 117 derived, 117 run, 0 NOT-MEASURED, 0
UNRUN.`, exit 0. It also printed a STALE TREE note: `origin/main` moved
to `f5ef054a7` (#24248) after the merge, and changed
`scripts/check-single-authz-resolver.mjs`, whose new `DELEGATORS` row
keys `rest-server.ts` on `resolveAuthzContext` (the class head,
untouched here). No path of that commit is one of this diff's 16, so it
was not merged again; PR CI runs the merge ref.
- Selected readings: `check:route-envelope` (`27 route module(s)
audited: 9 conformant, 17 ratcheted, 1 exempt`); `check:adr-anchors`
(`73 anchored file(s)`, `1783 decision-letter citation(s)`); `node
scripts/check-system-context-census.mjs` (`… across 65 files, living in
123 symbol(s); the page cites 136 symbol(s) against 136 required, over
159 anchors`); `check:liveness` (`947 pointer(s) … 947 naming a symbol`,
`737 … asked, 736 anchored, 1 exempt`, as at base);
`check:undeclared-dep-imports`; `check:cross-package-test-inputs`;
`check:authz-resolver`; `check:durability-log-level`;
`check:dispatcher-error-vocabulary`; `check:error-status-conformance`;
`check:dual-build-cjs-loads` (`111 published require entry point(s)
across 69 package(s) load`); `check:pm-dispatch-gates` (`1884 cases
pass`); `check:type-check-coverage`; `check:type-check-debt`;
`check:nul-bytes`. `node scripts/check-platform-checklist.mjs
--changed-from origin/main`: `10 anchor(s) judged, 0 lost`.
- **Not run locally:** `check:dev-prereqs` and
`check:skill-frame-freshness` (local-only families). This diff touches
no `packages/spec` build input and no four-axis frame file.
- **Not governed.** `check-governed-merges --branch HEAD`: `0 of 16
path(s) hit the register`, and the size is under the human-merge
threshold.
Commits:
- `344cb18d8`, the move;
- `9ce268e26`, the list and the `/meta` subset;
- `cbd7d7a4c`, the re-points, with the module's ADR anchor and the
row-50 anchor;
- `3750ddecc`, the changeset;
- `39912f9e1`, the merge;
- `892a86538`, a comment-only fix to the new `MODULES` note (which door
builds the 400).
---
_Generated by [Claude
Code](https://claude.ai/code/session_01QyoWKK9RwUNxBxmevy9Neb)_
---------
Co-authored-by: Claude <noreply@anthropic.com>
1 parent 8eccf51 commit e9bc60b
16 files changed
Lines changed: 722 additions & 430 deletions
File tree
- .changeset
- content/docs/permissions
- packages
- qa/dogfood/test
- rest/src
- scripts
- adr-anchors
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
181 | 181 | | |
182 | 182 | | |
183 | 183 | | |
184 | | - | |
| 184 | + | |
185 | 185 | | |
186 | 186 | | |
187 | 187 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1636 | 1636 | | |
1637 | 1637 | | |
1638 | 1638 | | |
1639 | | - | |
| 1639 | + | |
| 1640 | + | |
1640 | 1641 | | |
1641 | 1642 | | |
1642 | 1643 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
540 | 540 | | |
541 | 541 | | |
542 | 542 | | |
543 | | - | |
544 | | - | |
| 543 | + | |
| 544 | + | |
545 | 545 | | |
546 | 546 | | |
547 | 547 | | |
548 | 548 | | |
549 | 549 | | |
550 | | - | |
| 550 | + | |
551 | 551 | | |
552 | 552 | | |
553 | | - | |
| 553 | + | |
| 554 | + | |
554 | 555 | | |
555 | 556 | | |
556 | 557 | | |
| |||
866 | 867 | | |
867 | 868 | | |
868 | 869 | | |
| 870 | + | |
| 871 | + | |
| 872 | + | |
| 873 | + | |
| 874 | + | |
| 875 | + | |
| 876 | + | |
| 877 | + | |
| 878 | + | |
| 879 | + | |
| 880 | + | |
| 881 | + | |
| 882 | + | |
| 883 | + | |
| 884 | + | |
| 885 | + | |
| 886 | + | |
| 887 | + | |
| 888 | + | |
| 889 | + | |
| 890 | + | |
| 891 | + | |
| 892 | + | |
| 893 | + | |
869 | 894 | | |
870 | 895 | | |
871 | 896 | | |
872 | | - | |
| 897 | + | |
873 | 898 | | |
874 | 899 | | |
875 | 900 | | |
| |||
884 | 909 | | |
885 | 910 | | |
886 | 911 | | |
| 912 | + | |
| 913 | + | |
| 914 | + | |
887 | 915 | | |
888 | 916 | | |
889 | 917 | | |
| |||
1405 | 1433 | | |
1406 | 1434 | | |
1407 | 1435 | | |
1408 | | - | |
1409 | | - | |
1410 | | - | |
| 1436 | + | |
| 1437 | + | |
| 1438 | + | |
| 1439 | + | |
| 1440 | + | |
| 1441 | + | |
| 1442 | + | |
| 1443 | + | |
| 1444 | + | |
| 1445 | + | |
| 1446 | + | |
| 1447 | + | |
| 1448 | + | |
| 1449 | + | |
| 1450 | + | |
1411 | 1451 | | |
1412 | 1452 | | |
1413 | 1453 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
129 | 129 | | |
130 | 130 | | |
131 | 131 | | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
132 | 136 | | |
133 | 137 | | |
134 | 138 | | |
| |||
146 | 150 | | |
147 | 151 | | |
148 | 152 | | |
149 | | - | |
| 153 | + | |
150 | 154 | | |
151 | 155 | | |
152 | 156 | | |
| |||
766 | 770 | | |
767 | 771 | | |
768 | 772 | | |
769 | | - | |
| 773 | + | |
| 774 | + | |
| 775 | + | |
| 776 | + | |
| 777 | + | |
| 778 | + | |
| 779 | + | |
| 780 | + | |
| 781 | + | |
| 782 | + | |
| 783 | + | |
| 784 | + | |
| 785 | + | |
770 | 786 | | |
771 | | - | |
| 787 | + | |
772 | 788 | | |
773 | 789 | | |
774 | 790 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
272 | 272 | | |
273 | 273 | | |
274 | 274 | | |
275 | | - | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
276 | 280 | | |
277 | 281 | | |
278 | 282 | | |
| |||
0 commit comments