Users & membership
Identity lives on platform.users; per-tenant membership and role live on platform.organization_users.
ER diagram
platform.users
One row per Firebase user. Identity-only — anything per-org lives on organization_users.
| Column | Type | Notes |
|---|---|---|
id | UUID PK | Referenced by user_invitations.invited_by and similar. |
firebase_uid | VARCHAR(128) | UNIQUE. Auth provider's stable ID. |
email | VARCHAR(320) | UNIQUE. |
display_name | VARCHAR(255) | |
is_active | BOOL | NOT NULL. Default true. |
last_login_at | TIMESTAMPTZ | Updated on each GET /user hit. |
created_at | TIMESTAMPTZ | NOT NULL. Default NOW(). |
updated_at | TIMESTAMPTZ | NOT NULL. Default NOW(). Auto-updated by trigger. |
platform.organization_users
One row per (user, org). Role lives here.
| Column | Type | Notes |
|---|---|---|
id | UUID PK | |
user_id | UUID FK | → platform.users(id) ON DELETE CASCADE. |
org_id | UUID FK | → platform.organizations(id) ON DELETE CASCADE. |
role | org_role | NOT NULL. ENUM (owner, admin, member, viewer). |
is_active | BOOL | NOT NULL. Default true. |
joined_at | TIMESTAMPTZ | NOT NULL. Default NOW(). |
last_active_at | TIMESTAMPTZ | NULL until first activity. Updated on every request scoped to this org. |
created_at | TIMESTAMPTZ | NOT NULL. Default NOW(). |
updated_at | TIMESTAMPTZ | NOT NULL. Default NOW(). Auto-updated by trigger. |
UNIQUE (user_id, org_id).