mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-27 04:56:20 +02:00
PR #1868 conflated "has workspace" with "completed onboarding" — restore `onboarded_at` as the single signal, and route invited users through a dedicated /invitations page before they ever see onboarding. - Backend: CreateWorkspace + AcceptInvitation atomically set onboarded_at alongside the member insert, establishing the invariant "member row exists ↔ onboarded_at != null" at the DB layer. - Migration 065: one-shot backfill closes the dirty rows produced by PR #1868 (users with a workspace but onboarded_at == null). - Entry points (web callback, login, desktop App): if onboarded_at is null, look up pending invitations by email and route to the new batch /invitations page; otherwise the resolver picks workspace / new-workspace as before. - OnboardingPage: stops bouncing on hasWorkspaces; only hasOnboarded bounces. Unblocks the user from completing Step 3 (workspace creation) → Steps 4 / 5. - StarterContentPrompt: only shows when the user is the solo member of the workspace, so invited users never get prompted to import starter content into someone else's workspace. Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
14 lines
747 B
SQL
14 lines
747 B
SQL
-- Backfill onboarded_at for users who already belong to a workspace.
|
|
-- PR #1868 (since reverted) routed users by hasWorkspace instead of onboarded_at,
|
|
-- producing a population of users with workspace memberships but
|
|
-- onboarded_at == NULL. After the new design enforces
|
|
-- "member row exists ↔ onboarded_at != null" via backend transactions,
|
|
-- this one-shot backfill cleans existing dirty rows.
|
|
--
|
|
-- Uses created_at as the timestamp because these users were de facto onboarded
|
|
-- when their account was first created — backfilling with now() would distort
|
|
-- onboarding-funnel analytics. COALESCE keeps it idempotent.
|
|
UPDATE "user"
|
|
SET onboarded_at = COALESCE(onboarded_at, created_at)
|
|
WHERE id IN (SELECT DISTINCT user_id FROM member);
|