Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions packages/spec/src/data/injected-system-columns.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -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({
Expand Down
5 changes: 4 additions & 1 deletion packages/spec/src/data/object.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -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' }),
Expand Down
32 changes: 32 additions & 0 deletions packages/spec/src/data/object.zod.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -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
Expand Down
Loading