Repository navigation
fix(dogfood): the criteria-less legacy sharing-rule row carries the organization the admin acts in - #24913
Conversation
…rganization the admin acts in The case "a criteria-less rule already IN the table shares nothing and loses its grants" wrote its legacy row at the driver seam with no organization_id. Since the organization-less readers of sharing rules retired (ADR-0131 D1/D8, 7cacad5), no admin read resolves such a row, so POST /sharing/rules/srule_3896_legacy/evaluate answered 404 before the criteria guard the case pins was reached. The row now carries the admin's active organization, read off the admin's own session: the shape a pre-gate row has once the organization-ownership ceremony attributes it (ADR-0131 D10). Every assertion is unchanged: evaluate answers below 300, matches 0 records, and materialises no grant. Claude-Session: https://claude.ai/code/session_01LmjU2x1faLZ39DVTFyVca6 Co-authored-by: Claude <noreply@anthropic.com>
…aring-rule-legacy-row-org
📓 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:
Landing: this is this lane's main-red card. It goes through the merge queue by this seat once every check on this head reads Generated by Claude Code |
… into 7b-0 Conflicts in seven fixture files take #24893's resolution (4dadd7e): where 7a-2 now writes the grant with an organization the pre-18 relax goes; where main still lands an organization-less row the relax stays. sharing-rule-criteria-required takes main's version verbatim (both sides had added the organization key). plugin-webhooks' new real-SqlDriver case gets the lean engine's Default Organization. Claude-Session: https://claude.ai/code/session_018EszgtA3V2KXBX5tf59Hi4 Co-authored-by: Claude <noreply@anthropic.com>
Fixes #24879
Clause-②: no
The hourly full run's
Dogfood Regression Gate (1/3)red (run 39419131283): one dogfood fixture went stale against the ruled retirement of the organization-less sharing-rule readers. This PR repairs the fixture. No product code changes, and no assertion changes.What changed
One file, one case:
packages/qa/dogfood/test/sharing-rule-criteria-required.dogfood.test.ts, "a criteria-less rule already IN the table shares nothing and loses its grants".sys_sharing_rulerow at the driver seam, and that row had noorganization_id.7cacad5348(PR feat(plugin-sharing,plugin-approvals,metadata-protocol)!: 18.x step 7 part 7a-3 — the organization-less readers of sharing rules, approval units and the seed loader retire #24828, 18.x step 7 part 7a-3), no admin read resolves a rule with no organization.findRuleRowandfindRuleRowByNameread the caller's own organization only (ADR-0131 D1/D8). SoPOST /sharing/rules/srule_3896_legacy/evaluateanswered404 RULE_NOT_FOUNDbefore the criteria guard this case pins was reached.organization_id: the organization the admin acts in. It is read off the admin's own session (GET /auth/get-session,session.activeOrganizationId), which is the field theevaluaterequest's context is resolved from. No id is hard-coded.get-sessionanswers 200 and that the organization id is a non-empty string, so a missing id fails loudly instead of writing an organization-less row again.evaluateanswers below 300, matches 0 records, and materialises nosys_record_sharegrant.The file's other writes do not share the cause. The direct-insert case (
ql.insert('sys_sharing_rule', …, { context: SYS })) is refused for its missing criteria. It was green onmainbefore this change (4 of 5 passed), and it is unchanged. Every other system-context call in the file is a read.There is no skip and no retry, and a 404 is not accepted anywhere. The retirement in PR #24828 stays as it is, and nothing under
packages/plugins/plugin-sharing/**orpackages/spec/**is touched.Evidence
Each row ran
pnpm --filter @objectstack/dogfood exec vitest run --maxWorkers=2 test/sharing-rule-criteria-required.dogfood.test.ts, after building the dogfood closure (turbo run build --filter=@objectstack/dogfood) at the same commit. The test file,test/showcase-boot.tsandvitest.config.tsare byte-identical on the first three trees.abd5acdaf7(7cacad5348^, the commit of the last green hourly run, 39412016980)Tests 5 passed (5). The boot logsrule has no usable criteria — matching NO records instead of every recordforlegacy_match_all_3896.7cacad5348(PR #24828)Tests 1 failed | 4 passed (5):AssertionError: expected 404 to be less than 300at:153c2d4072281(main, this branch's base):15330629ffe1f(this change)Tests 5 passed (5)2ecc76b48e(head: this change merged withmainatfcb40ad673)Tests 5 passed (5), with the samematching NO recordsline forlegacy_match_all_3896organization_id: organizationId,line turns the case red again, withexpected 404 to be less than 300.scripts/ablation-replace.mjs: anchor count 1 to 0, blobc22aa9f438f5toc129bbc072f1.c22aa9f438f5), andgit diff HEADis empty.OS_TEST_SHARD=1/3 pnpm turbo run test --filter=@objectstack/dogfoodran on2ecc76b48e. The result wasTest Files 96 passed (96),Tests 772 passed (772),Tasks: 67 successful, 67 total.VITEST_MAX_WORKERSwas 2 here, where the runner's computed cap is 3. That is a concurrency difference only.isolatedandshared-showcase, and this file runs only inisolated(it is not inSHARED_SHOWCASE). The two variants run are the file alone and its gate shard, shown above. The file's one boot is posturesingle, with the Default Organization.Gates (head
2ecc76b48e)node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstackderived 56 commands. All 56 ran, each with its exit code captured before any pipe.pnpm check:dual-build-cjs-loadsfirst answeredPREREQUISITE NOT MET(exit 3), because this worktree had nodist/for 8 packages outside the dogfood closure. After building those packages, it exited 0 ("112 published require entry point(s) across 69 package(s) load").check:init-service-contract,check:live-db-isolation,check:meta-type-normalized,check:optional-error-sink,check:resume-authority-declared,check:route-envelope,check:runner-env-posture,check:settings-bind-window,check:startup-registry-verdict,check:verify-stand-in,check:wildcard-fallthrough) all exited 0.--ranwith the exit codes recorded:Run reconciliation — 56 derived, 56 run, 0 NOT-MEASURED, 0 UNRUN.It derives the zero from the 56 recorded exit codes.pnpm --filter @objectstack/dogfood run typecheck: exit 0. The tsc program lists this file (--listFilesOnly, 1 hit).pnpm lint(eslint . --no-inline-config) over the whole tree: exit 0, with no findings.Dogfood Regression Gatedoes not run onpull_requestormerge_group. Its first CI reading of this change ismain's push and hourly battery after the merge, so 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
isolatedandshared-showcase, and the file's boot is posturesingle. Nogroupposture boot is in this file. The gate's grouping is its shard, and both the file alone and its shard ran green.GET /auth/get-session), not throughsys_member.resolveAuthzContextreadssession.activeOrganizationIdinto the request context'stenantId(packages/core/src/security/resolve-authz-context.ts), andSharingRuleService.callerOrgIdreads that value back. So the row lands in the organization that theevaluaterequest is scoped to.Generated by Claude Code