feat(backend): track first organization onboarding in Bento
Merged
WC
3mo ago+3441+3441+0123456789012345678901234567890123456789-59-59-01234567890123456789
Summary
- mark future direct registrations that still have no active organization access with
onboarding:awaiting_first_organd emituser:registered_without_org - atomically clear awaiting state and add permanent recovery suppression when active direct organization access appears, then emit
user:joined_org - permanently suppress recovery for normalized email changes so a queued message cannot be sent to the wrong address
- permanently suppress and unsubscribe deletion-scheduled users with abortable, ordered Bento requests while allowing Stripe, organization, and image cleanup to proceed independently
- route organization-access changes through the existing pgmq trigger/consumer system and document the Bento workflow guard
Safety and rollout
- Capgo's database remains the source of truth: registration and role-binding handlers reconcile deletion state after every terminal Bento tag/event, including ambiguous delivery failures, before propagating any retryable error.
- Bento subscriber imports are asynchronous, so every terminal organization-access transition adds monotonic suppression in the same update that removes awaiting state; malformed or short provider acknowledgements fail closed and retry.
- Default API-key provisioning is serialized with account deletion and rejects deletion-scheduled users inside the same database transaction.
- Invited registrations and users who already have active direct organization access are not enrolled.
- This is prospective only: there is no backfill and no existing subscriber is enrolled by this PR.
- The database migration may deploy before the Cloudflare route. That ordering is safe for this prospective cohort because tag creation and the join handler activate together in the same worker deployment; role-binding messages from before that activation cannot strand a newly tagged subscriber.
- This PR does not enable or edit a Bento workflow. Before enabling the non-transactional recovery email, its final pre-send branch must require
onboarding:awaiting_first_organd reject bothonboarding:first_org_recovery_suppressedandonboarding_disabled.
Verification
TZ=UTC bun test:unit— 1,323 passedbun lintbun lint:backendbun typecheck:backendbash scripts/check-supabase-migration-order.sh- clean
bun run supabase:db:reset bun scripts/supabase-worktree.ts test db— 816 passed- SQLFluff on the new migration and pgTAP test
bun scripts/supabase-worktree.ts db lint -s public --fail-on warning- production Cloudflare worker
wrangler deploy --dry-run --env=prod