Skip to content

[epic] ADR-0131 — total organization ownership: no NULL organization_id (v18 line) #15194

Description

@hotlong

Epic PM seated 2026-10-10T08:14Z: session_01Rerax7QTjKMPCUZxQUtPFR (GitHub marchtian, writing as objectstack-fleet[bot] through the relay). The maintainer summoned it as /pm-dispatch epic:#15194, per the director's ruling pointer 6094203467 (batch #310 item 3). This card is the parent of the ADR-0131 tree and carries pm:epic for the cutover batch below.

History: until this edit the body opened with the #15193 gate ("BLOCKED — the v18 development line is not open", with a backticked blocker line). #15193 was closed on the maintainer's word (6037915987), and the v18 line is open. The rest of the record below is unchanged except for one sentence in "Sub-issues", which pointed every card at that gate. Live card states are in this session's status comment, not in the body.

Delegation record

Delegated to this session: the ADR-0131 cutover batch ruled in #22601 → B (record 6094045326) under the three rules of batch #310 (6094179271): one PM runs it; only delete, never fix the retired modules; PRs under 3,000 changed lines where a clean cut exists. The batch is:

The stage plan is on #15204 (6094501866). #22621 → A amends it (6094985249, pointer 6095027530): the metadata door's write authority over the catalog does not change.

Reserved with pm:epic: #15204 and objectstack-ai/objectui#7611. Other seats do not claim, dispatch or re-route them while this record stands.

Not delegated. These stay with their lanes, and the batch orders around them:

Declared file territory. Read on objectstack origin/main 86da194 and objectui origin/main 023f00d; the stage that owns each region is named.

  • packages/spec/src/identity/position.zod.ts: the permissionSets field replaces the closed-shape refusal. Its generated baselines come with it (stage 1).
  • packages/core/src/security/: resolve-authz-context.ts, security-catalog.ts, the batch-equivalence golden trace (stage 1), and admin-standing-surface (stage 8).
  • packages/plugins/plugin-security/src/: the seven seeders, permission-set-projection.ts, position-write-through.ts, per-organization-catalog.ts, the catalog-bound modules stage 0 classifies, delegated-admin-gate.ts, explain-engine, the four object files, manifest.ts, and the boot and registration regions of security-plugin.ts that call them (stages 2, 3, 6a–6c, 7, 8).
  • packages/plugins/plugin-sharing/src/: sharing-rule-service.ts's position read (stage 2), and bootstrap-declared-sharing-rules.ts, which stage 0 decides.
  • packages/plugins/plugin-auth/src/: the catalog reads only, in auth-manager, ensure-default-organization, last-admin-guard and auto-org-admin-grant (stage 2).
  • packages/verify/src/rls.ts (stage 4, after S5c).
  • The four objects' reference sites (stage 8): spec platform-object names and system names, objectql's platform-object tenancy entry, the platform-objects pages for sys_position and sys_user, and the translations.
  • examples/app-crm/src/security/bind-position-sets.ts and examples/app-showcase/src/security/bind-position-sets.ts: the bindings move onto the position definitions.
  • The test files that name a retired module or object (about 301, measured in 6094501866). They are deleted or moved in their own PRs after the code they follow.
  • objectui: the C9 reader list (objectui#7611, 6094171670 and 6094395552). objectstack: .objectui-sha.

Why the territory is this wide: the batch retires four objects that hundreds of test files and at least ten objectui source files name, so the territory is the measured reader and writer surface. A card from another lane whose fix lands in one of these regions while the batch runs: comment here, and this session names the stage it serializes behind. The territory is declared, not a lock; the merge queue backstops any collision.

Close-out: when #15204 and objectui#7611 are closed, this session posts a summary here, removes pm:epic, and marks the territory done.


Execution tree for ADR-0131 — Total organization ownership: no NULL organization_id (docs/adr/0131-total-organization-ownership-no-null-organization-id.md, merged via #14976, approved by the maintainer 2026-09-04). §8 of the record is the table these cards are cut from.

The three sentences every card in this tree assumes

  1. A managed package's metadata is not in the database. It is cross-tenant, it upgrades with the code, and its definitions are sealed. A customer's customization is environment-level state: overlay for presentational types, disable-and-clone for behavioural ones, extend for structural ones (ADR-0126's three regimes, now at environment scope only). Environment metadata written by Studio, by the cloud build agent, or by a template-mode install lives in the database, is editable in the UI, and its ledger has no organization column. A template package cannot be installed on a shared-database multi-tenant deployment.
  2. A row with an organization column was written by that organization — created, cloned, or assigned. The column is NOT NULL. References to declared items are by machine name, resolved registry-first.
  3. A table with no organization column is deployment-level or code-level. It is protected by permissions, not by the tenant wall.

Dependency order

#15193 (gate: v18 line opens)
  └─ this epic
       ├─ C1  Default Organization load-bearing; unstamped write refused in every posture
       ├─ C2  catalog read from the registry; assignments reference by name
       │        └─ C3  retire the catalog seeders, the per-org catalog machinery, the four objects
       │        └─ C9  (objectui) Setup reads the registry; assignment pages stay data pages
       ├─ C4  email/notification templates resolve the registry; org-level editing closed
       ├─ C5  `sys_metadata` family tenant-less; per-org overlay axis retired; managed content sealed
       │        └─ C12 the template install mode
       ├─ C6  deployment-level state has no organization column
       │        └─ C10 (cloud) control plane adopts D7, backfill to fates
       ├─ C7  inventory + migration: four fates, manual operator ceremony  (needs C2–C6)
       │        └─ C8  `organization_id` NOT NULL; one predicate; both arms retired  (protocol 18)
       └─ C11 docs and family close-out  (needs C8 + C10)

Staging (D14)

Maintainer, 2026-09-04: 「我发 17.3,然后后续这么大的改动应该放到 v18」 and 「我建议18.0 的主要考虑是客户数据变化比较大,而且需要手工执行升级脚本」.

Two cards landed before the 17.3 tag and are not part of this tree: #15024 (sys_metadata_activation ships tenant-less, PR #15155) and #15030 (the NULL-inclusive business-unit screen of #14949 reverted, PR #15078). ⛔ Everything else is one major with one migration. No 17.x card narrows or removes a driver arm, adds a name column beside an id column, or ships half of this record.

Open questions the record leaves to the maintainer

ADR-0131 §6 Q1 — what becomes of email-template rows an organization has already customized (customized: true): kept readable as the Default Organization's overrides, or dropped with a release note. To be ruled when C4 is cut, not before.

Sub-issues

The order is the dependency order; Blocked-by: lines encode it card by card. (Until the epic PM sat, this sentence also said every card carried pm:blocked behind #15193. That gate is closed; the epic PM's status comment carries each card's state.)

card issue lands in blocked by (besides the gate)
C1 #15195 objectql, plugin-auth —
C2 #15196 core, objectql, plugin-security, plugin-sharing —
C3 #15204 plugin-security, platform-objects, spec C1, C2
C4 #15205 plugin-email — (⚠️ §6 Q1 must be ruled first)
C5 #15206 metadata-core, metadata-protocol, objectql, plugin-security C1
C6 #15207 spec, services —
C7 #15211 objectql, cli C2, C3, C4, C5, C6
C8 #15212 spec, drivers, objectql, plugin-security C7 · protocol 18 · clause-② yes
C9 objectstack-ai/objectui#7611 objectui C2
C10 objectstack-ai/cloud#1979 cloud C6, then C8
C11 #15214 docs C8, C10
C12 #15213 spec, objectql, cli C5

Landed before the 17.3 tag, deliberately outside this tree: #15024 (PR #15155) and #15030 (PR #15078).

Existing cards this tree re-aims

Surveyed 2026-09-04 across the three repositories' open queues at the maintainer's request. Each card named here carries a pointer comment of its own:

card why this tree touches it
#11753 a new ActionParam carry-over key for a Clone dialog C3 deletes and C9 rebuilds — folded into C9
#14491 its whole subject is which copy the catalog seeders read; C3 retires the seeders
#14772 · #13753 both describe or forward the metadata organization partition C5 retires
objectui#7205 persists an org-wide view overlay — the ADR-0005 axis C5 retires
#13419 asked whether name-based permission-set resolution is intended; D4 answers yes
#11973 · #11978 · #11979 the platform-admin re-anchor family, decided by D5 and implemented in C1/C3
#14570 · #15086 organization-less row populations C7's inventory must give a fate
#14096 ruled and closed 2026-09-04 — D9 removes the question rather than choosing an option
#14508 · #15072 · #13433 · #8241 · #15007 pointer only;排期不变

⛔ Not touched, and shipping on their own clock: #14970 / #14971 / #13566 (the p0 cross-tenant webhook family — D7 keeps sys_http_delivery and sys_email tenant data), #14754, #14936, #14937. C1 makes the last three more load-bearing, not less.

Activity

  1. objectstack-fleet commented on Oct 8, 2026

    @objectstack-fleet
    Contributor

    Record: the v18 line's opening commits on main (#22009's execution line, as this card's body asked triage to record)

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-08T08:09Z. A record only. ⛔ Not a claim, ⛔ not a dispatch.

    Read on origin/main with git log, parent links checked:

    what commit note
    The last 17.x release 4e4e881427 · chore: version packages (#21352) Tag @objectstack/*@17.7.0; npm latest is still 17.7.0. Under ruling B (6037890422) there is no further 17.x.
    The last commit before pre mode 498ea50889 (#22207) The single parent of the opening commit.
    v18 pre mode opens a87d8be299 · PR #22084 (Fixes #22080) Changesets pre mode next with one major marker, so the next version pass publishes 18.0.0-next.0.
    • Read this carefully: 498ea50889 is not a 17.x-compatible tree. Since ruling B, v18 cards have landed on main, breaking changes (!) included. The 17.x line's last shipped state is the 17.7.0 tag above.
    • Still open on the release list: chore: version packages #21988 (the version PR) is not merged. The first 18.0.0-next.0 publish goes out through it.
  2. objectstack-fleet commented on Oct 10, 2026

    @objectstack-fleet
    Contributor

    Ruling pointer: batch #310 item 3 · letter A · maintainer 「cloud 冻结在 v17 没问题,其他同意你的建议。」 2026-10-10T05:26Z

    Director seat, summon #36, session_019fWAt2renophxLVg5aJXMH (GitHub hotlong; written as objectstack-fleet[bot] via the relay). The record is 6094179271 on #15204. Thread-read: 6055619844.


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 10, 2026

    @objectstack-fleet
    Contributor

    Epic status · round 1 · 2026-10-10T08:22Z

    Epic PM session_01Rerax7QTjKMPCUZxQUtPFR (marchtian). The delegation record is in this card's body, rewritten this round; that edit is the audit record. This comment is the batch checklist, and it is refreshed at round boundaries.

    The maintainer's instruction for this batch, in this session's chat: 「这个之前是分给各车道开发的,很多已经处理了,你不要重复开发。」 So every stage below is checked against origin/main and against in-flight branches and PRs before it is claimed. A dev's first step is to falsify its premises, and a part found done is reported, not rebuilt.

    Already landed (not part of this batch, not redone)

    Cutover batch (#15204 plan 6094501866)

    stage what state
    0 catalog-bound module classification; assignment-table names; measured cut in progress (this seat, read-only census). Done here: sys_user_position.position and sys_user_permission_set.permission_set are name columns on 86da194
    1 PositionSchema.permissionSets + the resolver reads the registry dispatched: claim 6095611212, cloud dev session_01AGgRrdom7nizSbHc5Gws2U, branch claude/issue-15204-s1-position-permission-sets
    2 services readers (S8b), Q (a) same-name refusal waits on 1
    3 S9 boot report waits on 2
    4 verify/src/rls.ts waits on S5c (#15196, domain:cli, not this lane)
    5 C9 objectui#7611 + .objectui-sha bump reserved (pm:epic, 6095619495); dispatched after 1 lands; lands after 2, before 7 and 8
    6a–6c delete the seeders wait on 3
    7 retire the projector and both write-throughs waits on 5 and 6
    8 retire the four object declarations last
    T1–Tn test-file deletions each after the code PR it follows

    Outside the batch, read this round

  4. objectstack-fleet commented on Oct 10, 2026

    @objectstack-fleet
    Contributor

    Epic status · round 2 · 2026-10-10T13:10Z

    Epic PM session_01Rerax7QTjKMPCUZxQUtPFR (marchtian). This refreshes 6095636190. The usage wall stopped work between about 10:30Z and 12:50Z; every in-flight item was re-read on resume, and none was lost.

    stage what state
    0 census, classification, measured cut done: 6095755866, the cut re-measured and the order corrected
    1 PositionSchema.permissionSets + the resolver reads the registry building: cloud dev session_01AGgRrdom7nizSbHc5Gws2U, branch at 7564191e2a, about 2.9k changed lines against main; no PR yet
    2 services readers; the activation door for permission/position; position-catalog-refusal waits on stage 1's PR
    3 S9 boot report ACCEPT (6096484607); draft PR #22671, parked until stage 1 merges (one pending test is enabled then)
    4 verify/src/rls.ts waits on S5c (#15196, domain:cli)
    5 C9, part 1 ACCEPT (objectui 6097840521) after a contract review PASS (6097834214); draft objectui#12089, lands after stage 1; part 2 follows
    6b-1a platform capabilities as registry declarations ACCEPT (6096401008); PR #22669 in the merge queue since 12:56Z
    6a–6c, 6b-1b, 6c-prep seeder deletions after 2 and 5, per 6095755866
    7-pre, 7a, 7b projector and write-through deletions after 5 and 6
    new: clone door a server clone for permission, per C9's Q1 → A (objectui 6097763840) before 8. Not dispatched: inside the maintainer's veto window
    8-pre, 8 row-write gates; retire the four objects last. Stage 8 also waits on #22682

    Filed this round: #22682 (domain:spec, pm:queue): the spec half of C9's Q2 and Q3, catalog references by name in authoring surfaces.

    Blocked-by: #22682

    This Blocked-by: line is stage 8's, recorded here so the reverse index sees it. The epic itself is not blocked.

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions