Repository navigation
Commit 24360dc
fix(plugin-sharing): the declared-rule organization walk ends on the rows read; ADR-0131 small carriers retire the NULL-means-global texts (#25266)
<!-- claude-projects-attribution: {"github_login":"os-bill"} -->
_Requested by **Bill** · [project
thread](https://claude.ai/code/project/chan_016iMXWSZDzqWRWvWzdNo8wg?thread=cmsg_016iMXWSZDzqWRWvWzdNo8wg3X7qDVRkhCrq8R4os9DMy3)_
Part of #25203
Part of #15212
Clause-②: no
Metadata-protocol: none
Claim 6346494581 (`domain:engine` seat 2, card thread
`session_01M7Q2xAsaBG8KpAYgUxtSdU`). Items 1, 2, 3, 6, 7 and 8 of the
card. Item 4 landed with #25210. Item 5 is a governed `.claude/**` line
and goes to the skills lane. Items 9 and 10 (comment 6345275520) wait on
#25246 and are not in this claim. So this PR is `Part of #25203`, not
`Fixes`: the card stays open for items 5, 9 and 10 (seat correction
after the contract review).
## What changed
**Item 1, the one behaviour change: `resolveDeclaredRuleScopes`
(`packages/plugins/plugin-sharing/src/sharing-plugin.ts`).**
- Before: the keyset walk over `sys_organization` filtered each page to
string ids, then tested the FILTERED page for "short page, stop". A full
page of 500 rows holding one row with no readable `id` read as short, so
the walk ended there and answered a partial list. The boot sweep then
revoked the declared-rule grants of every organization past that page.
- Now: the walk ends on the number of rows READ. A page holding a row
whose `id` the walk cannot read answers unknown (`null`), with a warning
that names the cause, as the epic's plan amendment 6254164222 prescribes
("treat a filtered-out id as a failed read"). The caller already treats
`null` as UNKNOWN: no declared rule is served, and no declared rule's
grant is revoked.
- Hardening, not a reachable defect: `sys_organization.id` is a text
field, so no shipped install produces such a row.
- Pin: `sharing-rule.test.ts`, "a FULL page holding a row with no
readable id answers unknown (null) …". 1201 organizations, row 10 of the
first page loses its id.
**Item 2, wording.**
- `18.sharing-rule-declared-mirror-retired.ts` `reason`: the D13
paraphrase. ADR-0131 D13 asks an ADR-0087 entry of every retirement **of
an authorable shape**. The text now says this entry is registered by
choice, because the seeder is not one. (The reconciliation's suggested
text named a card number; the repo's runtime-string rule keeps tracker
numbers out of shipped text, so the sentence carries the reason
instead.)
- `18.driver-read-scope-follows-tenant-wall.ts` `surface`: names update
and delete "by id or by predicate".
- `packages/cli/src/commands/migrate/organization-ownership.ts`: the
printed warning "(but on a table whose column is not the tenancy
anchor): assign …" now reads ", except on a table whose column is not
the tenancy anchor. Assign …". The same idiom is fixed in the comment
above `unattributableHeld` and in the `heldUnattributable` docblock
(`organization-ownership-apply.ts`).
**Item 3, texts of the retired NULL-means-global reading.**
- `sys-user-position.object.ts`: the docblock and the Organization help.
An assignment applies only while its organization is the active one, and
an organization-less row applies nowhere (`grantAppliesInTenant`,
`packages/core/src/security/resolve-authz-context.ts`).
- `sys-user-permission-set.object.ts`: the Organization help ("Optional
organization scope. NULL = applies in every org context." → "The
organization this grant belongs to.").
- `plugin-security`'s `en` bundle was regenerated with `node
scripts/check-i18n-bundles.mjs --write`. The `zh-CN`, `ja-JP` and
`es-ES` values are hand-written and were updated to match, because merge
mode keeps translated values.
- "simply unstamped": the text lives in
`packages/spec/src/contracts/email-service.ts` (the `IEmailService`
`organizationId` TSDoc), not in `plugin-email`. It now says the engine
stamps the organization it can derive or refuses the insert (ADR-0131
D9), and leaves the row unstamped only in a composition with no
organization object.
- `packages/verify/src/harness.ts`, `inviteForAudienceGate`: the
dedicated organization id hides these invitations from fixtures under a
wall only. On `single` an organization owner's read returns them too.
- Forced companion:
`packages/spec/scripts/liveness/empty-state-registry.mts` loses its
`sys_user_permission_set.organization_id` row. That row classified the
"NULL = applies in every org context" statement this card removes, and
`check:empty-state` reds `STALE — registered, but the statement is gone`
without the removal (measured).
**Item 6.** `schedule-organization.zod.ts` cited the deleted
`objectql/src/tenancy/platform-object-tenancy.ts` ledger. It now cites
`service-automation/src/suspended-run-store.ts`, where the store stamps
a run's row.
`content/docs/references/automation/schedule-organization.mdx` was
regenerated (`check:generated --fix`, then re-checked green).
**Item 7.** `content/docs/permissions/tenant-audit-census.mdx`, the gate
order's second item: the engine sets `bypassTenantAudit` on an
`isSystem` write only where the object's schema puts it out of scope (no
tenant field, or federated), as `buildDriverOptions` does today.
**Item 8.** `delivery-claim-tenant-audit.integration.test.ts`: the
docblock quoted the driver's old warning tail. It now quotes the opening
and says the prescription after the dash has been reworded. The
assertions are unchanged.
## Tests
At head `0a71e50d7`:
- `plugin-sharing` `pnpm test`: 53 files, 1201 tests passed.
- `plugin-security` `pnpm test`: 208 files, 4274 passed, 45 skipped.
- `cli` unit tier, `organization-ownership` files: 8 files, 76 passed.
- `spec` `src/migrations` + `scripts/liveness`: 17 files, 579 passed.
- `typecheck`: plugin-sharing, plugin-security, cli, verify,
service-messaging, spec, all exit 0.
- Ablation of item 1 (`scripts/ablation-replace.mjs`, the old
filtered-page block put back): the new pin went red (1 failed, 5
passed), every other `resolveDeclaredRuleScopes` test stayed green.
Restore verified: blob equal to `HEAD`, `git diff HEAD` empty. The suite
imports `./sharing-plugin.js` from `src`, so no `dist` leg applies.
## Gates
`node scripts/pm/dispatch-gates.mjs --commands` at `0a71e50d7` derived
124 families. `--ran` reconciliation: 122 run, all exit 0; 2 NOT
MEASURED (exit 3, prerequisite not met on this checkout), left to CI:
`check:dual-build-cjs-loads` (needs a whole-workspace build) and
`check:i18n-coverage` (one of 14 configs could not lint here).
`check-plugin-teardown-shape --self-test` and `check:skill-examples`
first exited 3 on missing prerequisites (a pinned fixture commit, the
client builds) and exited 0 once those were fetched and built.
## Acceptance notes
Published text, per item:
- Item 1: `@objectstack/plugin-sharing` behaviour and a new warning
string. Published.
- Item 2: the two semantic entries ship in `@objectstack/spec`'s upgrade
guide and registry. Published. No check reads their wording, and
`check:upgrade-guide` / `check:spec-changes` are green. The cli warning
is a runtime string in `@objectstack/cli`. Published. The two cli
comments are not.
- Item 3: the two `description`s and the four locale bundles ship in
`@objectstack/plugin-security`. Published. The `IEmailService` TSDoc
ships in `@objectstack/spec`'s `.d.ts`. Published. The position docblock
and the `verify` comment are not published.
- Item 6: the TSDoc is in a `*.zod.ts`, which `@objectstack/spec` ships
verbatim (`files` includes `src/**/*.zod.ts`). Published. The reference
page is docs.
- Items 7 and 8: docs and a test comment. Not published.
- One `patch` changeset covers the four published packages
(`Metadata-protocol: none`).
Not changed here (no drive-by): the `sys-user-permission-set.object.ts`
docblock still calls an organization-less grant "platform-wide" when it
explains the unique index's NULL-safety; `tenant-audit-census.mdx` keeps
its historical narrative about the old mute further down. Neither is
named by the card.
Cross-lane declarations (not claims): `domain:cli` on #22648
(6346689477), `domain:devx` on #20163 (6346705267, for `content/docs`,
which the lane table assigns to devx), `domain:spec` on #18549
(6346927889), `domain:services` on #21118 (6346947858, `plugin-sharing`,
`plugin-security`, `service-messaging`).
---
_Generated by [Claude
Code](https://claude.ai/code/session_01M7Q2xAsaBG8KpAYgUxtSdU)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent cc8d886 commit 24360dc
20 files changed
Lines changed: 96 additions & 50 deletions
File tree
- .changeset
- content/docs
- permissions
- references/automation
- packages
- cli/src
- commands/migrate
- utils
- plugins
- plugin-security/src
- objects
- translations
- plugin-sharing/src
- services/service-messaging/src
- spec
- scripts/liveness
- src
- automation
- contracts
- migrations/entries/semantic
- verify/src
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
46 | 46 | | |
47 | 47 | | |
48 | 48 | | |
49 | | - | |
50 | | - | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
51 | 53 | | |
52 | 54 | | |
53 | 55 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
76 | 76 | | |
77 | 77 | | |
78 | 78 | | |
79 | | - | |
80 | | - | |
| 79 | + | |
| 80 | + | |
81 | 81 | | |
82 | 82 | | |
83 | 83 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
632 | 632 | | |
633 | 633 | | |
634 | 634 | | |
635 | | - | |
| 635 | + | |
636 | 636 | | |
637 | 637 | | |
638 | 638 | | |
| |||
1121 | 1121 | | |
1122 | 1122 | | |
1123 | 1123 | | |
1124 | | - | |
| 1124 | + | |
1125 | 1125 | | |
1126 | 1126 | | |
1127 | 1127 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3801 | 3801 | | |
3802 | 3802 | | |
3803 | 3803 | | |
3804 | | - | |
| 3804 | + | |
3805 | 3805 | | |
3806 | 3806 | | |
3807 | 3807 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
110 | 110 | | |
111 | 111 | | |
112 | 112 | | |
113 | | - | |
| 113 | + | |
114 | 114 | | |
115 | 115 | | |
116 | 116 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
19 | | - | |
20 | | - | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
21 | 22 | | |
22 | 23 | | |
23 | 24 | | |
| |||
107 | 108 | | |
108 | 109 | | |
109 | 110 | | |
110 | | - | |
| 111 | + | |
111 | 112 | | |
112 | 113 | | |
113 | 114 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
38 | 38 | | |
39 | 39 | | |
40 | 40 | | |
41 | | - | |
| 41 | + | |
42 | 42 | | |
43 | 43 | | |
44 | 44 | | |
| |||
104 | 104 | | |
105 | 105 | | |
106 | 106 | | |
107 | | - | |
| 107 | + | |
108 | 108 | | |
109 | 109 | | |
110 | 110 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
38 | 38 | | |
39 | 39 | | |
40 | 40 | | |
41 | | - | |
| 41 | + | |
42 | 42 | | |
43 | 43 | | |
44 | 44 | | |
| |||
104 | 104 | | |
105 | 105 | | |
106 | 106 | | |
107 | | - | |
| 107 | + | |
108 | 108 | | |
109 | 109 | | |
110 | 110 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
38 | 38 | | |
39 | 39 | | |
40 | 40 | | |
41 | | - | |
| 41 | + | |
42 | 42 | | |
43 | 43 | | |
44 | 44 | | |
| |||
104 | 104 | | |
105 | 105 | | |
106 | 106 | | |
107 | | - | |
| 107 | + | |
108 | 108 | | |
109 | 109 | | |
110 | 110 | | |
| |||
0 commit comments