--- id: resolve-org-dual-ownership name: Resolve dual ownership model for organizations status: completed depends_on: [resolve-sessions-accountid-cascade] scope: narrow risk: high impact: component level: implementation --- ## Description Two competing ownership concepts with no documented relationship: 1. `organizations.ownerId` — a single FK to one account (`identity.md:44`) 2. `organization_members.membershipLevel: "owner"` — can exist on multiple rows (`identity.md:58`) Can `ownerId` point to an account with `membershipLevel: "member"` (not "owner")? Can an org have zero members with `membershipLevel: "owner"` but a non-null `ownerId`? An implementer cannot determine which field is authoritative for ownership queries. The resolution of `sessions.accountId` cascade (C01) affects this because if account deletion is enabled (nullable FKs), the org ownership transfer workflow depends on knowing which field is authoritative. ## Acceptance Criteria - [ ] `identity.md` documents the invariant relating `organizations.ownerId` and `organization_members.membershipLevel` - [ ] One of the following invariants is chosen and documented: - "`ownerId` is always a member with `membershipLevel: 'owner'` (enforced by app logic). If all owner-level members are removed, `ownerId` must be transferred first." - "`ownerId` is the creator; `membershipLevel: 'owner'` is a separate authorization concept." - [ ] The account deletion workflow interacts correctly with the chosen invariant (e.g., RESTRICT on ownerId means account deletion blocked if account owns an org) - [ ] `table-reference.md` cascade rationale for `organizations.ownerId → accounts.id` (RESTRICT) is updated with the invariant reference ## References - docs/reviews/storage-architecture-review-2026-04-21.md#C13 - docs/architecture/storage/identity.md:44 - docs/architecture/storage/identity.md:58 ## Notes > To be filled by implementation agent ## Summary > To be filled on completion