Skip to content

feat(objectql,plugin-auth): the Default Organization is load-bearing under single; an unstamped write is derived there and refused everywhere else (ADR-0131 D3/D9/D11) #15195

Description

@hotlong

⛔ BLOCKED — the v18 development line is not open.

Blocked-by: #15193

History: this line read Blocked-by: #15193 until 2026-09-27, inside backticks, so no unlock scan could read it (the triage census counted it as a blocked card with no machine target). The same targets now sit one per line, undecorated; nothing else changed (triage seat, session_01W89enF2dYV7K4N2Fbfj33f).

Part of #15194 (ADR-0131 execution tree). ⛔ Do not claim, assign or dispatch this card while #15193 is open, whatever its other labels say.


In one sentence. In a single-tenant deployment the one organization must exist before anyone writes anything, because from now on every row has an owner; a write that arrives without an organization is refused in every posture, and only single-tenant can derive the owner.

Scope. (1) ensureDefaultOrganization (packages/plugins/plugin-auth/src/ensure-default-organization.ts) becomes a boot invariant under single: failure is a boot error, not a best-effort warning; it runs before application seed datasets load (SeedLoaderService.load, packages/metadata-protocol/src/seed-loader.ts) and before the first authenticated request — today seeds land during start() and the organization is created by a later sign-up, so a first boot's business seeds (and every sys_business_unit seed, #14547) land NULL. (1b) The seed loader's exemption of sys_ / cloud_ / ai_ seeds from organization stamping (fallbackOrgId never applied to platform seeds) is withdrawn: there are no platform-global seeds left; every seed row is stamped with the resolved organization or the load refuses (D9). seed-tenancy-backfill.ts becomes the attribution path for existing first-boot residue (C7). (2) resolveSystemInsertOrganization (packages/objectql/src/tenancy/system-write-organization.ts): derived only when exactly one organization exists (single), refused otherwise, in every posture; the unclassified branch and the isPlatformObjectOutOfTenantAuditScope gate are bypassed for objects carrying the column (C8 removes them outright). Message per ADR-0123 D4. (3) ⛔ No default to any other owner — the "platform organization" was considered and rejected in ADR-0131 §5.

Collision to read before starting: #11973 (platform-admin re-anchor L3) re-points the same ensure-default-organization function and moves the same trigger. Its re-pointing half is absorbed here; its last-admin-guard re-pricing half is not and stays on that card. Read it first and say in the PR body which half you found already done.

Acceptance. Fresh single boot: the Default Organization is present before the HTTP listener accepts, and an isSystem insert on a tenant-column object with no organization lands stamped with it. Fresh isolated / group boot: the same insert is refused with a message naming the missing organization — positive control: the identical insert carrying tenantId succeeds.

⛔ Stop and report rather than proceeding: touching applyTenantScope (C8 owns it); editing any seeder (C3 owns them).

Refs: ADR-0131 D3, D9, D11 · ADR-0093 · ADR-0123 D2–D4 · #8844 · #14547.

No activity

Activity on this issue will appear here.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions