mirror of
https://github.com/Luchexx/wacrm.git
synced 2026-11-02 17:29:45 +00:00
Scaffolding for the upcoming WhatsApp Flows feature. The whole Flows
stack (interactive button/list send + parse, server-side runner, no-
code builder, templates) will land across the next ~4 PRs *behind*
this gate so the owner can dogfood the feature on their own account
before exposing it to teammates or downstream pullers of the OSS.
What this lands:
1. `profiles.beta_features TEXT[] NOT NULL DEFAULT ARRAY[]::TEXT[]`
— generic opt-in column, lives on the existing profiles table.
Empty by default for every existing row.
2. `src/lib/flows/feature-flag.ts` — `isFlowsEnabled(profile)`
predicate + `BETA_FEATURE_FLOWS` constant. Single source of
truth for the gate; later PRs import this in every guarded
surface (sidebar nav, /flows page, /api/flows routes, webhook
dispatcher).
3. `Profile.beta_features` added to the shared TS type and the
auth hook's local copy. Auth hook loads the column and
defaults it to `[]` defensively if the DB read returns null.
4. 11 unit tests covering null/undefined/empty/mismatched cases,
including case sensitivity (only lowercase `'flows'` opts in)
and defensive guards against malformed input.
How the owner enables it for their own account, once merged:
UPDATE profiles
SET beta_features = array_append(beta_features, 'flows')
WHERE user_id = '<their-auth-uid>';
How we ship it to everyone, when ready: grep-and-delete the
`isFlowsEnabled()` callsites in one cleanup PR.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
41 lines
1.9 KiB
SQL
41 lines
1.9 KiB
SQL
-- ============================================================
|
|
-- Per-account beta feature flag column on `profiles`.
|
|
--
|
|
-- Adds an array of opted-in beta feature keys to each profile row.
|
|
-- Currently used to gate the Flows feature (`'flows'`); shape is
|
|
-- generic so subsequent betas (e.g. `'ai_replies'`, `'voice_notes'`)
|
|
-- can land in this column without another migration.
|
|
--
|
|
-- Why a per-account flag rather than a global env var:
|
|
-- - Self-hosted wacrm instances are multi-user (small teams, shared
|
|
-- workspaces). A global flag would force every account on the
|
|
-- instance to opt into a not-yet-stable feature simultaneously.
|
|
-- - The owner wanted to dogfood the feature on their own account
|
|
-- before exposing it to teammates. Flipping a column via
|
|
-- Supabase Studio (`UPDATE profiles SET beta_features = ...
|
|
-- WHERE user_id = '<theirs>'`) is the lowest-friction toggle.
|
|
-- - DB-managed flags survive env rotation, deploy-restart timing,
|
|
-- and (since beta_features is a TEXT[]) extend naturally to
|
|
-- additional features without further schema work.
|
|
--
|
|
-- Default is the empty array, so every existing profile row opts
|
|
-- out of every beta feature on apply. NOT NULL keeps callers from
|
|
-- having to defend against `beta_features == null` at every site.
|
|
--
|
|
-- Idempotent — safe to run multiple times.
|
|
-- ============================================================
|
|
|
|
ALTER TABLE profiles
|
|
ADD COLUMN IF NOT EXISTS beta_features TEXT[]
|
|
NOT NULL
|
|
DEFAULT ARRAY[]::TEXT[];
|
|
|
|
-- No new RLS policy needed: the existing `Users can view own profile` /
|
|
-- `Users can update own profile` policies (migration 001) already gate
|
|
-- access to this column. Server-side reads via service_role bypass RLS
|
|
-- as they do for every other column.
|
|
--
|
|
-- No index needed: the column is read on the login codepath (one row
|
|
-- lookup by primary key / user_id, both already indexed) and very
|
|
-- rarely written.
|