Who somebody is in one workspace.
Two, by the owner's decision of 2026-09-18, and the argument is the one he
made: four roles that collapse to two predicates are not four roles. OWNER
and ADMIN differed in two lines in the whole codebase; EDITOR and VIEWER in
one.
Worse, four roles plus per-connection grants meant the same fact could be
stated twice and disagree — a role saying VIEWER while a grant said writer,
with the winner decided across sixteen separate gates. One axis cannot
express the contradiction.
OWNER does everything: billing, team, connecting accounts, approving
changes, and reading and writing on every connection.
MEMBER does exactly what it was given, per connection, in
connection_grants.level. A member with no row anywhere can sign in and
see that nothing has been shared with them yet, and that is all.
Persisted as a plain string: VARCHAR(32), no CHECK constraint, no native
Postgres type, so this is a code change and not a migration.