`is_account_member` is a `LANGUAGE sql` function, so Postgres parses
and validates its body at CREATE time — references to `profiles.account_id`
and `profiles.account_role` must already exist in the schema. The
original ordering created the helper before the ALTER TABLE that
added those columns, causing Supabase to abort with
ERROR: column p.account_id does not exist (SQLSTATE 42703)
on every fresh apply. Reordering: the profile column-add now runs
immediately after the `accounts` / `account_invitations` tables and
before the helper. No semantic change elsewhere.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Turns every wacrm install multi-tenant on the database side. A single
user's signup now creates an `accounts` row, links the profile to it
as `owner`, and every domain row is scoped via a new `account_id`
column instead of `user_id`.
Why now: the next handful of PRs add the invite/members user surface
(gated by the `account_sharing` beta flag); that surface needs RLS to
already speak "membership" rather than "ownership". Doing the schema
flip in isolation keeps the diff reviewable and lets the follow-up
PRs stay focused on TS/UI.
What the migration does:
- Introduces `account_role_enum` + `accounts` + `account_invitations`.
- Adds `account_id` to every parent tenant table (16 tables incl.
profiles) and `account_role` to profiles.
- Backfills one account per existing user, then sets NOT NULL.
- Replaces every `auth.uid() = user_id` RLS policy with a membership
check via a SECURITY DEFINER `is_account_member(account_id, min)`
helper. Three tiers: viewers read, agents write operational data,
admins write settings-class tables (whatsapp_config, templates,
pipelines, tags, custom_fields).
- Swaps `whatsapp_config.UNIQUE(user_id)` → `UNIQUE(account_id)` and
`flow_runs` active-run idempotency key to `(account_id, contact_id)`.
- Replaces `handle_new_user` so new signups bootstrap their own
account atomically.
Backwards compatibility: every existing user is the sole `owner` of
their freshly-created account, every existing row is linked to it,
and the legacy `user_id` columns stay (still used for assignment /
audit, no longer for isolation). Net behavioural change on its own:
zero.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>