Repository navigation
feat(plugin-security)!: under single, Setup positions are written through to the environment ledger, and row-only positions are backfilled once (ADR-0131 D3, C2 stage S7) - #22388
Conversation
…ckfill under single (ADR-0131 D3, C2 stage S7) Claude-Session: https://claude.ai/code/session_01WkL6Eijt432S1Y7ekb6ovQ Co-authored-by: Claude <noreply@anthropic.com>
…w-only position backfill (ADR-0131 D3, C2 stage S7) Claude-Session: https://claude.ai/code/session_01WkL6Eijt432S1Y7ekb6ovQ Co-authored-by: Claude <noreply@anthropic.com>
… the durability gate's critical list Claude-Session: https://claude.ai/code/session_01WkL6Eijt432S1Y7ekb6ovQ Co-authored-by: Claude <noreply@anthropic.com>
…gle, and row-only positions are backfilled once (ADR-0131 D3, C2 stage S7) Claude-Session: https://claude.ai/code/session_01WkL6Eijt432S1Y7ekb6ovQ Co-authored-by: Claude <noreply@anthropic.com>
…(ADR-0131 D3, C2 stage S7) Claude-Session: https://claude.ai/code/session_01WkL6Eijt432S1Y7ekb6ovQ Co-authored-by: Claude <noreply@anthropic.com>
…-position-write-through
…ugh and backfill write sites Claude-Session: https://claude.ai/code/session_01WkL6Eijt432S1Y7ekb6ovQ Co-authored-by: Claude <noreply@anthropic.com>
…e row-only position backfill registered beside it Claude-Session: https://claude.ai/code/session_01WkL6Eijt432S1Y7ekb6ovQ Co-authored-by: Claude <noreply@anthropic.com>
…ough's own level, not at the data door's answer; cite the write-through's isSystem read on the system-context page Claude-Session: https://claude.ai/code/session_01WkL6Eijt432S1Y7ekb6ovQ Co-authored-by: Claude <noreply@anthropic.com>
…-position-write-through
… so the test layer compiles Claude-Session: https://claude.ai/code/session_01WkL6Eijt432S1Y7ekb6ovQ Co-authored-by: Claude <noreply@anthropic.com>
…-position-write-through
📓 Docs Drift CheckThis PR changes 1 package(s): 43 hand-written doc(s) name something this change touched — list omitted above 15 rows. Re-derive on the tree named below: ⛔ 15 release-owned page(s) also affected — read-only, see AGENTS.md Documentation Guardrails. What this run could not see
Coarse fallback — 16 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 d816fa96e929897bb63ba87c5e94b6693c62e9d5 && git checkout d816fa96e929897bb63ba87c5e94b6693c62e9d5
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 3ca71b6e05efbfc6ec5908c8c263fee6cceba389 df77cc154e5e6b101dbb32ee0495c1e19b0f23ec && git checkout -B drift-repro 3ca71b6e05efbfc6ec5908c8c263fee6cceba389 && git merge --no-ff df77cc154e5e6b101dbb32ee0495c1e19b0f23ec
node scripts/docs-audit/affected-docs.mjs --json 3ca71b6e05efbfc6ec5908c8c263fee6cceba389
|
|
Out of the merge queue: a red on
|
…-position-write-through # Conflicts: # content/docs/permissions/system-context.mdx
…-position-write-through
…-position-write-through
…ged tree (121 reads) Claude-Session: https://claude.ai/code/session_01WkL6Eijt432S1Y7ekb6ovQ Co-authored-by: Claude <noreply@anthropic.com>
…-position-write-through # Conflicts: # content/docs/permissions/system-context.mdx
|
|
|
Measured: the Follows
|
…-position-write-through
|
Correction to
|
Part of #15196
Clause-②: no (narrowing)
ADR-0131 D3, C2 stage S7. Built on the seat's re-rule of the card (comment 6070208925: Q1 = A, Q2 = A, Q3 = A) after the measurement round (os-dev-report 6070148106), and on the seat note that keeps the Q2 stand-down while #22360 changes the declared-position seeder.
Not touched: every position reader (the read switch is S8),
packages/core,packages/spec, the rowactiveflag, S2's built-in declarations, the permission-set write-through, andbootstrap-declared-positions.ts. Walled postures behave exactly as before; the walled gap is #22361.What changes, under
singlesys_position{ name, label, description, delegatable }saved through the metadata door at environment scope; the catalog read resolves it at onceactive/is_defaultonlyerrorwith its remedy201/200400 INVALID_REQUESTat the item-name grammar,422 INVALID_METADATAatPositionSchema.name); the row write is undone, nothing is kept (Q1 = A)200A metadata refusal of a legal name also undoes the row write (create) or restores the patched columns (edit), and the refusal is the answer. No reader changes, so a user holding a position is granted exactly what they were granted before (pinned below against a kernel with no metadata door).
The package door (Q3 = A, within Q4 = A). Once a Setup position is defined in the environment ledger, a package registering a position of the same name is refused
422 NAMESPACE_CONFLICT, naming both holders. Before this change the same registration was accepted. The changeset says so.The one-time backfill.
runOneTimePositionEnvironmentBackfill, atkernel:bootstrappedbeside the S4b grant-name backfill, undersingleonly. Every position name the security catalog read does not resolve gets a definition from its row through the metadata door, verified through the catalog read afterwards. A name the environment ledger, a package or a built-in declares is left alone. A name the door refuses is a final class, reported atwarnand never written. Rows of one name that disagree are reported aterrorand not written. The verdict row (sys_migration, idadr-0131-position-environment-backfill) is written only when every name is decided; a failure leaves it unrecorded and the next boot retries. Its writerpersistPositionBackfillRecordjoins the durability gate's critical list. The hook iskernel:bootstrappedbecause an environment definition minted ahead of a package's declaration of the same name would refuse that package (measured at the registry item seam).Measured before the build (objectstack
1cb0edb82d, showcase,single)201and wrote a row and nothing else: nosys_metadatarow, and the catalog read did not resolve it. Edit, rename, deactivate and delete likewise touched only the row. The data door accepted names in seven classes (uppercase, a space, a hyphen, a leading digit, a leading underscore, one character, a dot) that the metadata door refuses.Pins and ablations
packages/plugins/plugin-security/src/position-write-through.test.ts, 30 tests. They use a real ObjectQL engine over the SQL driver, the realSecurityPlugin, and the realObjectStackProtocolImplementation(aliased to source) writing realsys_metadatarows.security-plugin.tsrestored to the base (3f80f17167), so nothing is registered: 18 red, 12 green. The 12 green are the controls (walled posture, system write, no door, a built-in refused at the admin door, the permission-set write-through unchanged, the Q1 edit control, the door's ownNOT_OVERRIDABLE) and the backfill's module-level cases. The restore was proven: blob equals HEAD, andgit diff HEADis empty.scripts/ablation-replace.mjs, with the anchor hit once, the blob changed and the restore proven. Each turned exactly its own pins red:packages/qa/dogfood/test/position-environment-write-through.dogfood.test.ts, 6 tests on the real showcase. It covers a create that resolves, rename and delete, the Q1 door refusals (400 INVALID_REQUEST,422 INVALID_METADATA), the Q3NAMESPACE_CONFLICT, and the backfill across three boots of one database.plugin-securityrebuilt, the marker proven present indist/byablation-dist-preflight. The backfill pin goes red. The restore was rebuilt, and the marker was proven absent with the tree clean.security-plugin.tsat base, rebuilt, write-through proven absent fromdist/): every behaviour pin is red. The precondition stays green, as does a Q2 data-door case that has since been removed.grant-readers-by-name.golden.test.tsis green inplugin-security(also at42f9c68085) and inplugin-auth.Verification at HEAD
dbef39ca41This head merges
origin/mainafter #22364 landed. It runspnpm install --frozen-lockfile, then rebuilds the dogfood closure (63 tasks).pnpm --filter @objectstack/plugin-security run typecheck: exit 0 (check:test-typecheck: OK).plugin-security, full suite: 188 files, 3925 passed, 45 skipped. This includes the pin file, the S4b backfill file and S5b'sgrant-readers-by-name.golden.test.ts.plugin-auth, full suite: 132 files, 2672 passed, 10 skipped. This includes itsgrant-readers-by-name.golden.test.ts.pnpm check:durability-log-level: 44 critical seams, all loud. With the verdict writer'serrordowngraded, it goes red, namingpersistPositionBackfillRecord.node scripts/check-adr-0087-registration.mjs --base origin/main: one declared-breaking changeset,not-required (no-migration-prescription).check-changeset-no-major, with this body as the event:✓ LEVEL AXIS: this PR declares clause-② no (narrowing), and no package whose packages/**/src/** it moves is graded patch.check-tenant-audit-censusandcheck-system-context-census: OK at this head.eslint --no-inline-configover the 8 changed TS/MJS files gives 0 errors and 0 warnings.eslint.config.mjsenables no type-aware linting, so this diff cannot move a verdict on an untouched file.dispatch-gates --commands). All 117 exited 0 at42f9c68085, and--ranreconciled to 117 run, 0 unrun. They are re-running at this head; the card report carries the verdict lines.Acceptance notes
content/docs/permissions/system-context.mdxgains row 11b for the write-through'sisSystemread, and its counts were regenerated (pnpm gen:system-context-census).node scripts/tenant-audit-census.mjs --write). The page's hand-written prose figures were updated to the census, as the census gate demands.measure-durability-swallow-family.mjscarries the vocabulary copy for the new critical seam.kernel:bootstrappedhandlers: the grant-name backfill, then this one.singlewith several organizations, two Setup rows of one name share one environment definition. The backfill refuses to guess when they disagree. The write-through saves the definition from the row being written.Generated by Claude Code