Repository navigation
fix(dogfood): the audit-capability fixture's grant writes carry their holder's organization - #24805
Conversation
… holder's organization Both `sys_user_permission_set` grant inserts in `audit-log-audit-capability.dogfood.test.ts` ran in system context with no organization. Under the walled posture a system insert on a tenant-scoped object must carry one (ADR-0131 D9), so the `isolated`-posture case was refused with SYSTEM_WRITE_ORGANIZATION_REQUIRED before any assertion ran. Each grant now carries its holder's organization on the execution context, the first form the refusal prescribes: the organization the walled case created for its holder, and on the `single` boot the one organization the holder is a member of. No assertion changes; the engine rule stays. Claude-Session: https://claude.ai/code/session_01LmjU2x1faLZ39DVTFyVca6 Co-authored-by: Claude <noreply@anthropic.com>
…ssue-24780-audit-capability-grant-organization
📓 Docs Drift CheckNothing in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 0 changed package(s)), so this run has no opinion about the docs. What this run could not see
Coarse fallback — 0 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): |
席位核对 · ACCEPT
Accepted deviations:
Out-of-scope dispositions: none. Landing: this is the lane's main-red fix, so it is the first PR this lane arms. It goes through the merge queue by this seat once every check on this head reads Generated by Claude Code |
Refs #24780
Clause-②: no
This PR repairs row 1 of the card (
Dogfood Regression Gate (1/3)). Row 2 (Console Pin Gate) belongs to #24749 and is not touched. The card stays open for the PM to settle after this lands.What changed
One file:
packages/qa/dogfood/test/audit-log-audit-capability.dogfood.test.ts. Its twosys_user_permission_setgrant inserts ran in system context with no organization. Each now carries its holder's organization on the execution context ({ isSystem: true, tenantId: ORG }):[#21260] the ledger audit capability is bounded by its holder's organization (scope: org),multiTenant: 'posture-only', so theisolatedposture): the grant to the first owner carriesorg.a, the organization that owner created earlier in the samebeforeAll.singleboot): thegranthelper reads the holder's one membership insys_memberand carries that organization (the Default Organization on that boot). The helper asserts exactly one non-empty membership. Without that check, an empty id would fall back to derivation and pass without testing anything.No assertion of any case changed.
resolveSystemInsertOrganizationand the walled lift stay as they are.Why
tenantIdon the context rather thanorganization_idon the row: the refusal names the context form first ("pass it on the execution context ({ context: { isSystem: true, tenantId: ORGANIZATION_ID } }), or set organization_id on the record itself"). It is also the form #24667 used for its own two walled fixtures (builtin-positions.boot.test.ts,grant-holder-membership-refusal.test.ts).The file's other system write, the bulk
sys_audit_loginsert in the first describe, is not this shape and is unchanged. The ledger declaressystemFields: { tenant: false }(ADR-0131 D7: no organization column), soresolveTenantFieldNameanswers null and the rule does not apply to that object. Itssingleboot would derive an organization anyway. The file makes no otherql.insert/ update / delete calls.Evidence
All runs used
pnpm --filter @objectstack/dogfood exec vitest run --maxWorkers=2 test/audit-log-audit-capability.dogfood.test.ts, after building the@objectstack/dogfood^...closure at the same commit.f7005cbd8(the parent of #24667'sfc34d000fc)Test Files 1 passed (1)·Tests 13 passed (13)fc34d000fc(#24667, the walled lift)Test Files 1 failed (1)·Tests 10 passed | 3 skipped (13),SystemWriteOrganizationRequiredError: Insert on 'sys_user_permission_set' was REFUSED … this install runs the 'isolated' tenancy posture74f78159a(this branch's base,mainbefore the fix)1 failed,10 passed | 3 skipped, the same refusal, at_ObjectQL.resolveSystemInsertOrganizationviaplugin-sharing/plugin-securitymiddleware187a247d0(this head: the fix plusmainat46bb5e3e5)Test Files 1 passed (1)·Tests 13 passed (13)The bisect pair confirms #24667 as the cause. The case's own subject is unchanged: the holder case still reads
2rows about its own organization's deleted record and0about the other's. That reading needs the grant (now stampedorg.a) to be honoured for the holder.The file runs in exactly one vitest project,
isolated(it is not inSHARED_SHOWCASE). The gate runspnpm turbo run test --filter=@objectstack/dogfoodwithOS_TEST_SHARD=k/3. The boot log shows the file's two boots at posturesingleand postureisolated. No boot in this file usesgroup.Gates
187a247d0: the 55 commands ofnode scripts/pm/dispatch-gates.mjs --commands(narrowed to this diff) all exit 0.--ranreconciles them as55 derived, 55 run, 0 NOT-MEASURED, 0 UNRUN.pnpm lint(eslint . --no-inline-config): exit 0, no findings.pnpm --filter @objectstack/dogfood run typecheck: exit 0. The tsc program lists this file (--listFilesOnly, 1 hit).Dogfood Regression Gatedoes not run onpull_requestormerge_group, so its first CI reading of this change ismain's push battery after the merge. The local red-then-green above is the pre-merge reading.Changeset
skip-changeset: the diff is one test file in@objectstack/dogfood, aprivate: truepackage that publishes nothing. No published package'sfiles[]changes.Acceptance notes
groupandsingleruns of the same lines. Measured: the vitest projects areshared-showcaseandisolated, and the file's boots aresingle(first describe) andisolated(second). There is nogroupboot here. Both grant lines answer under the boot they run in:10 passedbefore the lift and13 passedafter this fix.Generated by Claude Code