Files
pad/internal/store
xarmian d212eb6503 fix(members): keep a workspace's owner and at least one owner member (#1737)
* fix(members): a workspace keeps its owner and at least one owner member (BUG-3355)

Role changes and member removals checked nothing about ownership: an owner
could demote themselves or remove the last owner, leaving zero owners, and
demoting the canonical owner split authority from workspaces.owner_id, which
sets the URL, restore rights and plan limits. The store now refuses, in the
write's own transaction, demoting or removing the canonical owner (409
canonical_owner) and leaving no owner member (409 last_owner), locking the
owner membership rows FOR UPDATE on Postgres. An unknown role is a 400
instead of the CHECK constraint's misleading 404.

* fix(members): anchor the owner invariant on the canonical owner, without row locks (BUG-3355)

Codex r1: locking the other owners' rows FOR UPDATE neither serialized a
concurrent promote-then-demote under READ COMMITTED nor kept a lock order
account deletion agreed with (40P01). The canonical owner is an owner member
in every live workspace and owner_id cannot change, so refusing that one row
keeps an owner whatever runs concurrently; the last-owner count stays as a
best-effort guard for legacy rows. Store test covers all three doors,
including removal without revoking grants.
2026-10-02 17:01:54 -04:00
..