Repository navigation
Commit e2c2355
fix(dogfood): the criteria-less legacy sharing-rule row carries the organization the admin acts in (#24913)
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".
- The case writes its legacy `sys_sharing_rule` row at the driver seam,
and that row had no `organization_id`.
- Since `7cacad5348` (PR #24828, 18.x step 7 part 7a-3), no admin read
resolves a rule with no organization. `findRuleRow` and
`findRuleRowByName` read the caller's own organization only (ADR-0131
D1/D8). So `POST /sharing/rules/srule_3896_legacy/evaluate` answered
`404 RULE_NOT_FOUND` before the criteria guard this case pins was
reached.
- The row now carries `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 the `evaluate`
request's context is resolved from. No id is hard-coded.
- The case asserts that `get-session` answers 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.
- That is the shape a pre-gate row has once the organization-ownership
ceremony attributes it (ADR-0131 D10), which is the triage's done-when.
- Every assertion is unchanged: `evaluate` answers below 300, matches 0
records, and materialises no `sys_record_share` grant.
**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 on `main` before 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/**` or `packages/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.ts` and `vitest.config.ts` are byte-identical on the
first three trees.
| tree | result |
|---|---|
| `abd5acdaf7` (`7cacad5348^`, the commit of the last green hourly run,
39412016980) | `Tests 5 passed (5)`. The boot logs `rule has no usable
criteria — matching NO records instead of every record` for
`legacy_match_all_3896`. |
| `7cacad5348` (PR #24828) | `Tests 1 failed \| 4 passed (5)`:
`AssertionError: expected 404 to be less than 300` at `:153` |
| `c2d4072281` (`main`, this branch's base) | the same red at `:153` |
| `30629ffe1f` (this change) | `Tests 5 passed (5)` |
| `2ecc76b48e` (head: this change merged with `main` at `fcb40ad673`) |
`Tests 5 passed (5)`, with the same `matching NO records` line for
`legacy_match_all_3896` |
- **Without the organization on the row:** on the committed change,
deleting only the `organization_id: organizationId,` line turns the case
red again, with `expected 404 to be less than 300`.
- The mutation went through `scripts/ablation-replace.mjs`: anchor count
1 to 0, blob `c22aa9f438f5` to `c129bbc072f1`.
- The restore was proven: the blob equals HEAD (`c22aa9f438f5`), and
`git diff HEAD` is empty.
- **The gate's own invocation:** `OS_TEST_SHARD=1/3 pnpm turbo run test
--filter=@objectstack/dogfood` ran on `2ecc76b48e`. The result was `Test
Files 96 passed (96)`, `Tests 772 passed (772)`, `Tasks: 67 successful,
67 total`.
- `VITEST_MAX_WORKERS` was 2 here, where the runner's computed cap is 3.
That is a concurrency difference only.
- The file falls in shard 1. Computed with vitest 4.1.11's own shard
algorithm over this tree's 287 files: shard 1 holds 96 files, including
this one. The 772 matches the red run's count.
- **Variants:** the dogfood vitest projects are `isolated` and
`shared-showcase`, and this file runs only in `isolated` (it is not in
`SHARED_SHOWCASE`). The two variants run are the file alone and its gate
shard, shown above. The file's one boot is posture `single`, with the
Default Organization.
## Gates (head `2ecc76b48e`)
- `node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack` derived 56 commands. All 56 ran, each with
its exit code captured before any pipe.
- 55 exited 0 on the first run.
- `pnpm check:dual-build-cjs-loads` first answered `PREREQUISITE NOT
MET` (exit 3), because this worktree had no `dist/` 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").
- The 11 declared-WIDE families (`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.
- Reconciliation, `--ran` with 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 Gate` does not run on `pull_request` or
`merge_group`. Its first CI reading of this change is `main`'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`, a
`private: true` package that publishes nothing. No published package's
`files[]` changes.
## Acceptance notes
- The dispatch named "isolated and group" variants. As measured, the
vitest projects are `isolated` and `shared-showcase`, and the file's
boot is posture `single`. No `group` posture boot is in this file. The
gate's grouping is its shard, and both the file alone and its shard ran
green.
- The organization is read through the session (`GET
/auth/get-session`), not through `sys_member`. `resolveAuthzContext`
reads `session.activeOrganizationId` into the request context's
`tenantId` (`packages/core/src/security/resolve-authz-context.ts`), and
`SharingRuleService.callerOrgId` reads that value back. So the row lands
in the organization that the `evaluate` request is scoped to.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01LmjU2x1faLZ39DVTFyVca6)_
Co-authored-by: Claude <noreply@anthropic.com>1 parent eee65af commit e2c2355
1 file changed
Lines changed: 16 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
134 | 134 | | |
135 | 135 | | |
136 | 136 | | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
137 | 152 | | |
138 | 153 | | |
139 | 154 | | |
| |||
147 | 162 | | |
148 | 163 | | |
149 | 164 | | |
| 165 | + | |
150 | 166 | | |
151 | 167 | | |
152 | 168 | | |
| |||
0 commit comments