Commit d16b9fb
fix(metadata-protocol, objectql, core): platform store reads and writes carry the explicit system opt-in (#21938)
Fixes #21911
Clause-②: no
- Each producer takes the explicit system opt-in that exists today. No
gate before the hand-off fires on any of them, so nothing accepted or
refused changes today.
This is a slice of #21908: the engine-lane producers of the
principal-less hand-off. #21908 stays open, and it builds the deny
itself once every producer has a route.
## What changed
Every engine call in the card's functions now passes `context: {
isSystem: true }`. Inside a `SysMetadataRepository` transaction it
passes `{ ...ctx, isSystem: true }`, so the transaction handle still
rides along. This is the opt-in that already exists. There is no new
API, no export change, and no change to what any door authorizes.
| Row | Package | Function (engine calls moved) |
|:--|:--|:--|
| 1 | metadata-protocol | `findServedOverlayRow` (1 `findOne`) |
| 2 | metadata-protocol | `overlayLockLayerAt` (1 `find`, in its store
reader) |
| 3 | metadata-protocol | `readActiveOverlayRows` / `queryByOrg` (2
`find`), `readFlattenedMetaItems` (2 `find`, draft preview) |
| 4 | metadata-protocol | `foldStoredCollection` (1 `find`). These are
the only reads `assertRuntimeAuthoringRules` issues. |
| 5 | metadata-protocol | `SysMetadataRepository`: `get` 1, `put` 6,
`delete` 3, `promoteDraft` 1, `restoreVersion` 2, `listDrafts` 1,
`nextItemVersion` 1, `nextEventSeq` 1 |
| 6 | metadata-protocol | `recordMetadataAudit` (insert),
`persistPackageCommitRow` (insert), `publishPackageDrafts`,
`resolveOverlayPackageBinding`, `storedFlowBindingAgrees`,
`deletePackage`, `duplicatePackage` (1 read each),
`reassignOrphanedMetadata` (`find` + `update`) |
| 9 | objectql | `ObjectQLPlugin.readAuthoredActionRows` (3 `find`),
`readAuthoredHookRows` (2 `find`) |
| 10 | core | `readAuthoredTranslationLayer` (2 `find`) |
H1 holds: every row sits where the card says on `cab63967`. Every engine
call in each named function was enumerated with the TypeScript AST, not
only the first one: 32 in metadata-protocol, 5 in objectql and 2 in
core. Each now carries the opt-in.
## The six gates: none fires on these calls (Zone 1)
A system context skips the six gates the middleware still runs before
the hand-off's `next()`. Each one, on the `sys_metadata` family
(`sys_metadata`, `_history`, `_audit`, `_commit`):
- **package-managed**: acts only on `sys_permission_set`.
- **system-row**: acts only on `sys_position` and `sys_capability`.
- **curated-capability**: acts only on `sys_capability`.
- **audience-anchor**: acts only on `sys_position_permission_set`.
- **engine-owned**: the bucket matches (the family is `engine-owned` /
`append-only`), but `isUserContextWrite` needs a `userId`. A context
with no principal passes it by construction, exactly as a system one
does.
- **delegated-administration**: acts only on the RBAC link tables and
`sys_member`.
**Measured.** A local, uncommitted instrument sat at plugin-security's
engine middleware. It wrapped each of the six gates, so a throw was
recorded per gate and per operation. It also recorded the outcome after
the hand-off. After the change it dry-ran the six gates for every moved
`isSystem` call, with the flag cleared. The run covered the dogfood
suite and a booted showcase dev composition.
- Before: 0 gate throws on any of 35,248 (dogfood) + 388 (boot)
principal-less operations, from any producer. 0 downstream failures on
the card's functions.
- After: 0 gates would fire on any moved call.
The instrument was reverted, and `security-plugin.ts` equals its HEAD
blob (`5b4ab280`). plugin-security's `dist/` was rebuilt clean, and
`ablation-dist-preflight --absent` passed.
## Before and after, per function (H2)
Principal-less, non-system operations credited to each function. A
function is credited when it is the first frame past the engine, its
closures and the repository transaction wrapper.
| Function | dogfood before → after | boot before → after |
|:--|--:|--:|
| `findServedOverlayRow` | 13,614 → 0 | 80 → 0 |
| `overlayLockLayerAt` | 13,736 → 0 | 80 → 0 |
| `queryByOrg` (`readActiveOverlayRows`) | 2,037 → 0 | 16 → 0 |
| `readFlattenedMetaItems` draft preview | 0 → 0 (no run reached it;
unit-pinned) | 0 → 0 |
| `foldStoredCollection` | 761 → 0 | 0 → 0 |
| `SysMetadataRepository.get` / `put` / `delete` | 169 / 296 / 41 → 0 |
0 |
| `promoteDraft` / `restoreVersion` / `listDrafts` | 6 / 2 / 1 → 0 | 0 |
| `nextItemVersion` / `nextEventSeq` | 105 / 105 → 0 | 0 |
| `recordMetadataAudit` / `persistPackageCommitRow` | 110 / 1 → 0 | 0 |
| `publishPackageDrafts` / `resolveOverlayPackageBinding` /
`storedFlowBindingAgrees` | 1 / 1 / 6 → 0 | 0 |
| `deletePackage` / `duplicatePackage` / `reassignOrphanedMetadata` | 1
/ 1 / 2 → 0 | 0 |
| `readAuthoredActionRows` / `readAuthoredHookRows` | 810 / 496 → 0 | 3
/ 2 → 0 |
| `readAuthoredTranslationLayer` | 496 → 0 | 2 → 0 |
| **all principal-less operations, any producer** | **35,248 → 2,476** |
**388 → 204** |
After the change, the same calls arrive as `isSystem` operations in
matching numbers. For example: `findServedOverlayRow` 13,618,
`queryByOrg` 2,037, `put` 296, `recordMetadataAudit` 110. The dogfood
suite was green on both sides with identical counts: 205 files passed +
1 skipped, 1,590 tests passed + 9 skipped. The boot answered the same
statuses on both sides: admin data reads 200, anonymous reads 401. The
2,476 / 204 operations that remain come from the other slices' producers
(settings, messaging, storage, auth, webhooks, datasource).
## Tests
- **Unit pins, one per package (H4):**
- `metadata-protocol/src/protocol.platform-store-system-opt-in.test.ts`:
the engine double records the context of every call. It drives draft
save → publish → active save → rollback → delete, the overlay and list
reads (each private reader directly, too), and reassign / duplicate /
uninstall. Each step asserts that it reached the store and that every
call carried `isSystem: true`. Inside the transaction the context is
exactly `{ transaction, isSystem: true }`.
- objectql: `plugin-authored-actions.test.ts` and
`plugin-authored-hooks.test.ts` each gain one case.
- core: `authored-translation-sync.test.ts` gains one case.
- **Ablations, each committed first and restored through
`scripts/ablation-replace.mjs` (blob equals HEAD, `git diff HEAD`
empty).** Each pin resolves its subject from `src`, so no `dist` leg was
needed. The expected direction was red, and red is what was observed:
1. `findServedOverlayRow` opt-in dropped: 2 of 3 metadata-protocol cases
red.
2. `put`'s history-insert opt-in reverted to `{ context: ctx }`: 2 of 3
red.
3. `readAuthoredHookRows`' first read set to `isSystem: false`: 1 of 11
red.
4. `readAuthoredTranslationLayer`'s first read set to `isSystem: false`:
1 of 6 red.
- The first attempt at 3 and 4 used a replacement that was a prefix of
its anchor. The tool refused it as a no-op and nothing ran. They were
re-run with the `false` spelling.
- **Package suites (H4 falsified test-side; see the acceptance notes)**,
at `89ced04af3`. The merge to `9fd7113eaa` brought only two docs pages
and one `rest` test:
- metadata-protocol: 217 files passed + 3 skipped, 27,921 tests passed.
- objectql (`local` + `repo`): 376 files, 7,476 tests passed.
- core: 80 files, 2,226 tests passed.
- `typecheck` for all three exit 0, including objectql's and core's
`check:test-typecheck`.
- **Instrumented runs:** the dogfood suite (7 chunks, 206 files) and a
booted showcase dev composition, before and after, all under
`os-verify-lock`. The numbers are in the table above.
- **Gates:** `dispatch-gates --commands` at `9fd7113eaa` derives 76
families. All 76 were run there and exited 0, and `--ran` reconciles 76
derived, 76 run, 0 NOT-MEASURED.
- `check:engine-split-ratio` first refused on the shallow clone. It was
deepened (`--shallow-since=2026-06-30`) and re-run.
- `check:dual-build-cjs-loads` first needed dists of unbuilt packages
and a `plugin-audit` declaration. These were built, and the gate re-ran
green.
- `check:objectql-double-limit` flagged the new double as limit-blind.
The double now applies the caller's bound.
- **Lint, a proven narrowing (CI runs the full `pnpm lint`):**
1. The population comes from `eslint.config.mjs`:
`**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}` plus the `packages/**` object.
2. `eslint --no-inline-config --format json` over the 13 changed `.ts`
files: 13 files, 0 errors, 0 warnings.
3. The config never enables type-aware linting (no
`parserOptions.project`, no typed rules), so this diff cannot move any
untouched file's verdict.
## Acceptance notes
- **Same family, not moved here (static, not in the card's list):**
`SysMetadataRepository.getByHash`, `list`, `history` and
`replayFromHistory` still reach the engine with no context. No measured
run reached them (0 records in either probe). They belong to #21908's
closure census.
- **One engine check besides the six gates also stands down under
`isSystem`:** the referential-integrity check on a caller-supplied
lookup. On these writes the only lookup it judged was
`sys_metadata.organization_id`, which the repository fills from the
door-derived organization. The probe recorded 0 refusals from it (0
downstream failures on the card's functions). The other `isSystem` reads
on the census page touch none of these four objects, or only change a
log line (the tenant-audit warning, the reference-cleanup actor label).
- **H4 was falsified, and the fix is test-side only:** objectql's
protocol suites held seven exact-argument expectations, the reassign
rebind and the `listDrafts` WHERE. Each now includes the opt-in. Two
revert/rollback conflict pins (`protocol-commit-history`,
`protocol-writepath-object-ownership`) found `put`'s in-transaction read
by a bare `context` key, and every repository read now carries one.
Their engine now hands its transaction callback a handle, as
`ObjectQL.transaction` does, and the pin discriminates on that handle.
metadata-protocol's and core's own suites passed unchanged.
- **`scripts/engine-double-contract.pinned.json`** gains three rows
(`--write`, a grow-only coverage ledger) for the new pin's double. That
double is copied from the pinned one in
`protocol-publish-drafts-org-scope.test.ts`.
- **Probe artifact:** after the change, the `isSystem` count for
`overlayLockLayerAt` reads 10. This is not because its reads vanished.
The function is not `async`, so it does not appear in the async stack
the probe filtered system records by. Its principal-less count (the
claim) is 0 on both runs.
- **H5:** #21864's head (`d8657b5c`, re-tested after every merge of
`main`) test-merges cleanly onto this branch at `9fd7113eaa`. Its hunks
are in `anonymousFormIntakeOrgScopeRefusal`, `saveMetaItem` and
`promoteDraftForPublish`, and none of them is a named function here. All
16 protocol calls keep the opt-in in the merged tree.
- **H6:** the cross-lane declaration is on #6367 (`6003826474`).
- **H3:** the `isSystem` census page needs no edit. Object-literal
producers are not elevation reads, and the census gate is green with its
counts unchanged.
---
_Generated by [Claude
Code](https://claude.ai/code/session_011K3zqE8Pv1Evw5hc8tZCnN)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 0728cbf commit d16b9fb
15 files changed
Lines changed: 493 additions & 36 deletions
File tree
- .changeset
- packages
- core/src/fallbacks
- metadata-protocol/src
- objectql/src
- scripts
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
Lines changed: 19 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
118 | 118 | | |
119 | 119 | | |
120 | 120 | | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
119 | 119 | | |
120 | 120 | | |
121 | 121 | | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
122 | 125 | | |
123 | 126 | | |
| 127 | + | |
124 | 128 | | |
125 | 129 | | |
126 | 130 | | |
127 | 131 | | |
128 | 132 | | |
| 133 | + | |
129 | 134 | | |
130 | 135 | | |
131 | 136 | | |
| |||
Lines changed: 296 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
0 commit comments