From 4b3b6dbb960cbf5b26d433c9c399101d931b92cf Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 20 Aug 2026 11:43:01 +0000 Subject: [PATCH] docs(spec): widen the #8778 organizationField scope pin to name the cloud#1395 ruling The #8778 scope pin on `tenancy.organizationField` admitted exactly one consumer (audit stamping). The maintainer ruling recorded on cloud#1395 (2026-08-17T03:18Z) widens it BY NAME to three sanctioned platform-row writers, and requires the widening be declared rather than discovered. Annotation/prose only: no schema shape change, no accept/reject behaviour change. The behaviour change is #10101's. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_016gcKVsiywU9CcS96S5t9qD --- .../src/data/injected-system-columns.test.ts | 12 +++++-- packages/spec/src/data/object.test.ts | 5 ++- packages/spec/src/data/object.zod.ts | 32 +++++++++++++++++++ 3 files changed, 45 insertions(+), 4 deletions(-) diff --git a/packages/spec/src/data/injected-system-columns.test.ts b/packages/spec/src/data/injected-system-columns.test.ts index 16dbfd0de7..0166389827 100644 --- a/packages/spec/src/data/injected-system-columns.test.ts +++ b/packages/spec/src/data/injected-system-columns.test.ts @@ -81,9 +81,15 @@ describe('resolveInjectedSystemColumns (#5378)', () => { }); it('is blind to the stamp-only `tenancy.organizationField` (#8778 read-neutrality)', () => { - // The #8778 ruling's scope pin: `organizationField` is consulted by audit - // stamping ONLY. The injection plan must reach the same verdicts with and - // without it — on a plain tenant object, and on the shipped sys_api_key + // The #8778 scope pin, as widened by the cloud#1395 ruling (2026-08-17): + // `organizationField` is consulted by the sanctioned platform-row WRITERS + // only — audit stamping today, `plugin-approvals` and the automation-run + // recorder once #10101 lands. No READ path reads it, and that is what this + // test pins; the widening does not touch it, because all three sanctioned + // consumers stamp rows rather than read them. + // + // The injection plan must reach the same verdicts with and without it — + // on a plain tenant object, and on the shipped sys_api_key // shape (better-auth managed + `enabled: false`), where the plan's // better-auth bail must keep running BEFORE tenancy is read at all. const withKey = resolveInjectedSystemColumns({ diff --git a/packages/spec/src/data/object.test.ts b/packages/spec/src/data/object.test.ts index cf1b37a572..d89bb191ab 100644 --- a/packages/spec/src/data/object.test.ts +++ b/packages/spec/src/data/object.test.ts @@ -1685,7 +1685,10 @@ describe('TenancyConfigSchema — #2763 strategy/crossTenantAccess removal', () it('accepts the stamp-only `organizationField`, with no default materialized (#8778)', () => { // The shipped shape: sys_api_key stays unwalled (`enabled: false`) while // audit rows stamp the organization of the key they describe. The key is - // read by audit stamping ONLY — read-neutrality is pinned beside each + // consulted by the sanctioned platform-row writers only — audit stamping + // today, plus `plugin-approvals` and the automation-run recorder once + // #10101 lands under the cloud#1395 widening of the #8778 scope pin. No + // read path reads it either way: read-neutrality is pinned beside each // read path (driver tenant scope, Layer 0, injection plan), not here. expect( TenancyConfigSchema.parse({ enabled: false, organizationField: 'active_organization_id' }), diff --git a/packages/spec/src/data/object.zod.ts b/packages/spec/src/data/object.zod.ts index 512b065c2e..2955f97a41 100644 --- a/packages/spec/src/data/object.zod.ts +++ b/packages/spec/src/data/object.zod.ts @@ -538,6 +538,38 @@ const TENANCY_MODES_EXPLAINER = * move of a general field-roles mechanism — a consumer other than audit * stamping needs its own ruling before reading it. * + * That pin is WIDENED **by name** by the maintainer ruling recorded on + * cloud#1395, 2026-08-17T03:18Z, accepting the decision-inbox recommendations + * in full — verbatim: 「新进卡六张 同意你的建议」. It is transcribed here so the + * widening is declared, not discovered (#10110): + * + * > Ruled: Option A — extend the #8778 ruling: `resolveRecordOrganizationField` + * > is promoted to a shared resolver used by all three platform-row writers + * > (approvals, automation runs, audit). A platform row's organization is the + * > SUBJECT record's organization; actor context is the fallback, never the + * > primary. + * + * The ruling sanctions exactly THREE consumers of this key, and no others: + * + * 1. **audit stamping** — plugin-audit's `resolveRecordOrganizationField`; + * the original #8778 consumer and, as of this annotation, still the only + * one wired up; + * 2. **`plugin-approvals`** — the approval-row writer; + * 3. **the automation-run recorder** — reached when + * `resolveRecordOrganizationField` is promoted to the shared platform-row + * resolver. + * + * Consumers 2 and 3 are sanctioned but not yet implemented: #10101 carries that + * behaviour change (this card is annotation-only and changes no accept/reject + * behaviour). Which is why the `.describe()` below still speaks of audit rows — + * it states what reads the key TODAY, and #10101 updates it as the readers + * actually land. + * + * ⛔ The refusal posture is UNCHANGED for a FOURTH consumer. Three named + * platform-row writers are still not a general field-roles mechanism: anything + * outside the list above needs its own maintainer ruling before reading this + * key, exactly as #8778 required. + * * @example Shared database, platform-default tenant column (organization_id) * { * enabled: true