Repository navigation
test(plugin-security,plugin-auth,plugin-approvals): narrow the blanket pre-18 tenant-column relax rigs to the tables they write organization-less - #25327
Conversation
…t pre-18 tenant-column relax rigs to the tables they write organization-less Each blanket `relaxEveryRegisteredTenantColumn` / `relaxEveryTenantColumn` call now names the tables its rig writes organization-less, measured per call site with a NULL-write trigger probe, through `relaxTenantColumns`. Two sites wrote no organization-less row at all, so their relax is gone. The blanket exports leave the three packages' testkits. Test files only. No behavior change. Claude-Session: https://claude.ai/code/session_014aRYTwvuSQoDgWzLdw1nc9 Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift Check2 anchor(s) derived from 3 changed package(s); no hand-written page names any of them, so this run has nothing to list — not a clean bill of health. This check sees only pages that NAME a derived anchor: one that documents this change in prose, or enumerates it in an authoring dialect, names none and stays invisible to it on every run. What this run could not see
Coarse fallback — 27 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 0da16954e9199450ac7756cf7107b9a4634509d9 && git checkout 0da16954e9199450ac7756cf7107b9a4634509d9
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 97967a9a06f3b85a2f9fe2f1bf615e1eb186b7f0 c4a6f34beb2dfe1322d44ca532cc8e3fce7a2b47 && git checkout -B drift-repro 97967a9a06f3b85a2f9fe2f1bf615e1eb186b7f0 && git merge --no-ff c4a6f34beb2dfe1322d44ca532cc8e3fce7a2b47
node scripts/docs-audit/affected-docs.mjs --json 97967a9a06f3b85a2f9fe2f1bf615e1eb186b7f0 |
席位核对 · ACCEPT · 2026-10-23T01:56Z
Generated by Claude Code |
Requested by Sales · project thread
Fixes #25132
Clause-②: no
Metadata-protocol: none
Why
Clause-②: no: test files only. No source, no export, no schema and no published file changes (the three packages shipdist,README.mdandCHANGELOG.md), so no changeset either.What changed
Every blanket
relaxEveryRegisteredTenantColumn(engine)/relaxEveryTenantColumn(engine, objects)call inplugin-security,plugin-authandplugin-approvalstests now names the tables its rig writes organization-less, through the testkit's existingrelaxTenantColumns(engine, tables). On this base there were 41 call sites in 38 files. The card counted 47 occurrences in 40 files on4e2c42f363, a count that also matched the testkits' own definitions.sys_permission_setis the common one). The widest iscatalog-reference-reportwith four.controlled-by-parent-chain-middle-master.test.tsand thebootSharingrig inexplain-enforce-parity.test.ts.The organization-less rows below (global sets, positions, grants) exist only…(and its two siblings) named row kinds most rigs do not seed. It now readsThe organization-less rows below exist only on a store built before 18.x (ADR-0131 D1 makes a fresh tenant column NOT NULL): this is that store.Rig-specific comments are kept as they were.pre-18-tenant-column.testkit.ts.relaxTenantColumns' doc gains one sentence on why a suite names only its own tables.packages/qa/dogfood/test/pre-18-tenant-column.testkit.tskeeps its own copy and callers; it is outside this card.How the lists were measured
The lists were measured, not read off the code. A temporary probe (never committed) wrapped the blanket form: after relaxing, it put an
AFTER INSERT/AFTER UPDATEtrigger on each relaxed table. The trigger fired when a row landed withorganization_idNULL and logged the table, the test and the call site. All 38 files ran with the probe in place: plugin-security 27 files / 641 tests, plugin-auth 9 / 96 (10 skipped), plugin-approvals 2 / 18. Each site's list is the union of the tables that fired under it.Every logged row was then traced to the test's own writes. Each row's id is either a literal in the test file, or comes from a write the test itself makes through the engine as a case's subject. Examples are "a writer with no active organization stores an organization-less row" and "the
singleposture … an emptied organization is admitted". No table on any list is there only because of an unstamped side write from production code.Verification (on
c4a6f34b)HEAD(each restore checked withgit diff --quiet HEAD). All 58 runs went red. Each one failed only onNOT NULL constraint failed: TABLE.organization_idfor the dropped table. For the per-testqa_parity_deal_*objects ofbootRls, it failed only on that family.pnpm --filter @objectstack/plugin-approvals --filter @objectstack/plugin-auth run test: 94 files / 1213 tests and 187 files / 3525 tests (10 skipped), exit 0. plugin-security: see the report.typecheckfor all three packages, includingcheck:test-typecheck, exits 0. The test-typecheck debt ledgers are unchanged.driver-fault-auth-log-carriersPostgres and MySQL cells skip here because their URLs are unset. Their seeds are the same code as the SQLite cell, which measuredsys_permission_setalone.Branch: the harness-assigned
claude/project-thread-wxw16a, not the repo-conventionclaude/issue-25132-…(Duplicate Fix Guard).Acceptance notes
last-admin-guard.anchor-paritymodels "a tenant column NOT NULL nowhere" (a pre-18 store, or a driver that enforces no NOT NULL). It now relaxes onlysys_user_permission_set, the grant table its organization-less row lives in. Its comment says "a grant tenant column".Generated by Claude Code
🤖 Generated with Claude Code
https://claude.ai/code/session_014aRYTwvuSQoDgWzLdw1nc9