Repository navigation
Commit 60b42cd
fix(spec,plugin-sharing,scripts): retire the organization-less text step 7 left behind; check-tenant-chokepoint accepts where(tenant, 'is not', null) (#25140)
Fixes #24902
Clause-②: no (description and help text, plus a CI gate's rule: no
response, status, outcome, boot verdict or export moves)
Metadata-protocol: none (a schema description and a field's help text;
nothing a metadata author writes changes)
## What changed
**1. Text that contradicted behaviour after 18.x step 7**
- `packages/spec/src/api/events.zod.ts`: the `DataEvent.organizationId`
TSDoc and `.describe()`. They said every event on a `single` deployment
carries no organization because "nothing stamps the column". Under
ADR-0131 D9, every tenant row on a single-organization deployment is
stamped with the Default Organization the engine derives
(`resolveSystemInsertOrganization`, `packages/objectql/src/engine.ts`),
so its events carry it. The text now matches
`content/docs/protocol/objectql/schema.mdx`. Absence is described as two
cases: a row of an object outside the wall, and every row of a
composition that registers no organization object. The schema itself is
unchanged. `content/docs/references/api/events.mdx` was regenerated
(`check:generated --fix`, then a re-check: 14/14 up to date).
-
`packages/plugins/plugin-sharing/src/objects/sys-sharing-rule.object.ts`:
the Organization help said "null = global". It now reads "The
organization this rule belongs to.", which follows this object's
admin-facing rule (no tables, columns or ADRs in a `description`). A
code comment above it points to the typed `deploymentWide` projection
(`sharing-rule-service.ts`). The `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 and they would otherwise still say "null =
global".
- The three "stays NULL on single-tenant" comments in #25128 (C1) are
not in these files, so they stay with #25128.
**2. The gate nit:** `scripts/check-tenant-chokepoint.mjs`
- The header says `IS NOT NULL` is never refused. The rule refused every
three-argument `where(tenant, …, null)`, including `where(tenant, 'is
not', null)`. Knex compiles that call to `IS NOT NULL`:
`knex/lib/query/querybuilder.js:456-457`, operator lower-cased and
trimmed.
- The rule now exempts exactly a literal `'is not'` operator, matched
the way Knex matches it. An operator the gate cannot read is still
refused. The header names all three `IS NOT NULL` spellings.
- Self-test: there is one new silent case (`'is not'` and `' IS NOT '`)
and one new refused case (a non-literal operator). The `D8 null-arm
rule` battery floor goes from 22 to 24.
- Reverse check: I replaced the new condition with `true`, and the
self-test went red (exit 1) on the new silent case. The file was
restored with `git checkout HEAD --`, and `git diff HEAD` was empty
afterwards.
**3. The dormant paths: both are KEPT, with reasons. Neither is
retired.**
`organizationOutOfWriteReach`
(`packages/services/service-storage/src/metadata-store.ts:800`) is
**alive**:
- Callers: `storage-routes.ts:780`, inside
`requireStartingOrganization`. Three upload doors use it: the presigned
commit door, chunked completion, and the progress door when its expiry
stamp is due. It is the guard behind the `409` an uploader gets after
switching organization. It has a door-level pin in
`error-envelope.conformance.test.ts:226-245` (the commit door after an
organization switch) and unit pins in `metadata-store.test.ts:368-405`.
Probe: `vitest run src/error-envelope.conformance.test.ts
src/metadata-store.test.ts -t 'switching active
organization|organizationOutOfWriteReach'` gives 2 files, 7 passed.
service-storage is not in this diff, so CI does not run it.
- Only its organization-less-row branch (`metadata-store.ts:809`) was
written against the retired NULL arm. That branch can still run. The v18
boot guard is composed by `os serve` alone
(`packages/runtime/src/organization-ownership-boot-guard.ts`, "Where it
runs"). An embedding host that does not compose it can boot a database
that has not been through the ceremony and still holds a v17
organization-less `sys_file` / `sys_upload_session` row.
- So nothing is removed. One finding is left for the seat (see
Acceptance notes).
The `sys_record_share` backfill apply pass
(`packages/plugins/plugin-sharing/src/backfill-sys-record-share-organizations.ts`)
is **dead in every shipped build, but has a published reach**:
- No production caller. The only callers are tests:
`backfill-sys-record-share-organizations.test.ts` and
`record-share-organization-stamp.test.ts:315`.
- It does not ship: the tsup entry is `src/index.ts` alone, `files` is
`dist`, and the index does not export it.
- Probe (a throwaway vitest that was not committed): on a
`sys_record_share` table created by the 18.x driver with no relax,
storing an organization-less grant is refused (`NOT NULL`).
`planSysRecordShareOrganizationBackfill` answers `{scanned: 0, planned:
0}`, and the apply pass writes 0. The existing real-driver pin can only
build its legacy rows because it first relaxes the column
(`record-share-organization-stamp.test.ts:180`).
- **External reach, so it is kept:** the published 17.3 release notes
(`content/docs/releases/v17/17-3.mdx:44-48, 284-289`) tell operators to
run `planSysRecordShareOrganizationBackfill` /
`runSysRecordShareOrganizationBackfill(engine, { dryRun: false })`. The
CLI ceremony inventory cites the file as its derivation
(`packages/cli/src/utils/organization-ownership-inventory.ts:538`).
Retiring it also moves two ledgers outside this claim's file surface:
`scripts/engine-double-contract.pinned.json:3670` and the tenant-audit
census counts. Per the dispatch, this is the seat's call.
## Acceptance notes
- **For the seat, the open question:** the organization-less branch of
`organizationOutOfWriteReach` answers "in reach". Since D8, the driver's
scoped write cannot reach such a row, so on a host without the boot
guard the door writes, misses, and answers the `500` outage text. Option
A: keep it as it is; that state only exists on a database that has not
been through the ceremony. Option B: make the door refuse such a row
with its own answer. That needs a new refusal text, and it touches
`storage-routes.ts`, which is outside this claim. I recommend A, and
noting it for #24897's ADR text.
- **For the seat, the open question:** retire the `sys_record_share`
backfill or keep it. Option A: keep it until the 17.x upgrade window is
formally closed. Option B: retire the module, its two tests and the two
ledger rows now, and add an erratum PR for the 17.3 notes. I recommend
A.
- The claim names
`packages/platform-objects/src/**/sys-sharing-rule.object.ts`. The file
is actually at `packages/plugins/plugin-sharing/src/objects/`. I edited
it there.
- The storage-routes comment (`storage-routes.ts:761`) "a row stamped
with no organization stays in reach" has the same staleness as the
branch above. It is outside the file surface, so I left it.
## Verification
- `pnpm --filter @objectstack/spec test`: 706 files, 21465 tests passed.
- `pnpm --filter @objectstack/plugin-sharing test`: 53 files, 1200
passed.
- `pnpm --filter @objectstack/plugin-sharing typecheck`: exit 0.
- `pnpm --filter @objectstack/spec check:generated`: exit 0.
- `node scripts/check-tenant-chokepoint.mjs --self-test`: exit 0, 12
refused and 7 silent. The scan itself exits 0.
- `node scripts/pm/dispatch-gates.mjs --commands`: 130 commands. 130
commands on head `02067f8c`, each exit code captured before any pipe:
127 exit 0 on the first pass. Three exited 3 (PREREQUISITE NOT MET,
nothing measured). `check-plugin-teardown-shape --self-test` needed a
pinned commit the shallow clone lacked; after fetching it, exit 0. `spec
check:skill-examples` needed `client-react` built; after building it,
exit 0. `check:dual-build-cjs-loads` needs ten packages this diff does
not touch (studio, client-react, connector-slack and others) built, so
it is **NOT MEASURED locally** and declared to CI. `--ran`
reconciliation: 130 derived, 130 run, 0 unrun.
- `node scripts/pm/check-governed-merges.mjs --branch
origin/claude/issue-24902-tenant-text-dormant-paths`: NOT governed, 95
changed lines.
- Size **S**. Not a governed surface, so it lands through the ordinary
queue.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_01Pjh5f11tyUbYMQmSZaJZFS
---
_Generated by [Claude
Code](https://claude.ai/code/session_01Pjh5f11tyUbYMQmSZaJZFS)_
---------
Co-authored-by: Claude <noreply@anthropic.com>1 parent 863c580 commit 60b42cd
9 files changed
Lines changed: 71 additions & 24 deletions
File tree
- .changeset
- content/docs/references/api
- packages
- plugins/plugin-sharing/src
- objects
- translations
- spec/src/api
- scripts
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
59 | 59 | | |
60 | 60 | | |
61 | 61 | | |
62 | | - | |
| 62 | + | |
63 | 63 | | |
64 | 64 | | |
65 | 65 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
92 | 92 | | |
93 | 93 | | |
94 | 94 | | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
95 | 98 | | |
96 | 99 | | |
97 | 100 | | |
98 | 101 | | |
99 | | - | |
| 102 | + | |
100 | 103 | | |
101 | 104 | | |
102 | 105 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
113 | 113 | | |
114 | 114 | | |
115 | 115 | | |
116 | | - | |
| 116 | + | |
117 | 117 | | |
118 | 118 | | |
119 | 119 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
113 | 113 | | |
114 | 114 | | |
115 | 115 | | |
116 | | - | |
| 116 | + | |
117 | 117 | | |
118 | 118 | | |
119 | 119 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
113 | 113 | | |
114 | 114 | | |
115 | 115 | | |
116 | | - | |
| 116 | + | |
117 | 117 | | |
118 | 118 | | |
119 | 119 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
113 | 113 | | |
114 | 114 | | |
115 | 115 | | |
116 | | - | |
| 116 | + | |
117 | 117 | | |
118 | 118 | | |
119 | 119 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
257 | 257 | | |
258 | 258 | | |
259 | 259 | | |
260 | | - | |
261 | | - | |
262 | | - | |
263 | | - | |
264 | | - | |
265 | | - | |
| 260 | + | |
266 | 261 | | |
267 | 262 | | |
268 | | - | |
269 | | - | |
270 | | - | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
271 | 272 | | |
272 | 273 | | |
273 | 274 | | |
| |||
282 | 283 | | |
283 | 284 | | |
284 | 285 | | |
285 | | - | |
286 | | - | |
| 286 | + | |
| 287 | + | |
287 | 288 | | |
288 | 289 | | |
289 | 290 | | |
| |||
295 | 296 | | |
296 | 297 | | |
297 | 298 | | |
298 | | - | |
299 | | - | |
300 | | - | |
301 | | - | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
302 | 303 | | |
303 | 304 | | |
304 | 305 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
133 | 133 | | |
134 | 134 | | |
135 | 135 | | |
136 | | - | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
137 | 140 | | |
138 | 141 | | |
139 | 142 | | |
| |||
311 | 314 | | |
312 | 315 | | |
313 | 316 | | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
314 | 326 | | |
315 | 327 | | |
316 | 328 | | |
| |||
394 | 406 | | |
395 | 407 | | |
396 | 408 | | |
397 | | - | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
398 | 415 | | |
399 | 416 | | |
400 | 417 | | |
| |||
629 | 646 | | |
630 | 647 | | |
631 | 648 | | |
632 | | - | |
| 649 | + | |
633 | 650 | | |
634 | 651 | | |
635 | 652 | | |
| |||
865 | 882 | | |
866 | 883 | | |
867 | 884 | | |
| 885 | + | |
| 886 | + | |
| 887 | + | |
| 888 | + | |
| 889 | + | |
| 890 | + | |
| 891 | + | |
868 | 892 | | |
869 | 893 | | |
870 | 894 | | |
| |||
910 | 934 | | |
911 | 935 | | |
912 | 936 | | |
| 937 | + | |
| 938 | + | |
| 939 | + | |
| 940 | + | |
| 941 | + | |
| 942 | + | |
| 943 | + | |
913 | 944 | | |
914 | 945 | | |
915 | 946 | | |
| |||
0 commit comments