URL: https://mkdocs.justinsforge.com/memory/general/reference_creatortrack_account_deletion/
CreatorTrack account deletion (90-day retention)¶
Built 2026-07-10 on branch feat/account-deletion (worktree ~/forge-suite-wt/feat/account-deletion, DB clone ct_feat_account_deletion). Plan: creatortrack-account-deletion-2026-07-10. Merged to main 2026-07-11 (merge commit 0c88ef6) and deployed to prod; its migration (20260711T000228) has been applied to prod.
Flow¶
- Settings, Account, danger zone: type DELETE plus password re-entry (password accounts only; Google-only accounts rely on session + the emailed link). POST
/api/account/delete. - REFUSED (409, inline guidance) while the user owns any workspace with other members. Solo-owned workspaces soft-delete with the account.
- Confirmation email (Resend, branded
accountDeletionEmail) carries a single-use 24h token to the public page/account/delete/confirm?token=...; the button POSTs/api/account/delete/confirm(never GET side effects; scanners prefetch). - Confirm: revokes Google refresh tokens at
oauth2.googleapis.com/revoke(best-effort, logged loud, never aborts), wipesapp.api_connections, stampscore.users.deleted_at, deletes allcore.auth_sessionrows, soft-deletes solo-owned non-pinned workspaces. - Sign-in gates: credentials (
loginAction) and Google (auth.ts callbacks.signIn->/login?error=account_deleted) both show "This account has been deleted. To restore it within 90 days..., email [email protected]."core.loginalso excludes deleted accounts. - Purge: daily timer curls
POST /api/account/jobs{"job":"purge"}(bearerACCOUNT_JOBS_TOKEN);core.account_delete_purge(owner-GUC gated) hard-deletes accounts past 90 days plus workspaces where the deleted user was the sole member. Pinned workspaces are excluded at every step (soft-delete AND purge), so workspace 67 can never be touched.
SQL (migration 20260711T000228)¶
core.users gains deleted_at, delete_requested_at, delete_confirm_token_hash. Functions: account_delete_blockers/request (user GUC), account_delete_pending/confirm (token-authed), account_delete_status (email gate), account_delete_restore (lifeos_admin ONLY, EXECUTE revoked from app role), account_delete_purge (core.is_owner() gated).
Ops¶
- Token:
ACCOUNT_JOBS_TOKENin~/.forge-secrets/creatortrack-auth.env(generated 2026-07-10; prod service must restart with it at merge). - Purge timer:
forge/scripts/forge_creatortrack_account_purge.sh+forge-creatortrack-account-purge.{service,timer}.unit(04:30 CT daily). Written, still NOT enabled post-merge: copy units to /etc/systemd/system/,systemctl daemon-reload && systemctl enable --now forge-creatortrack-account-purge.timer. - Restore (contact@ support path):
bash forge/scripts/forge_creatortrack_account_restore.sh <email>(prod dblifeosdefault; pass a clone name for dev). Fails loud past 90 days; replay fails loud; fires PostHogaccount_restored. - PostHog events:
account_delete_requested,account_delete_confirmed(server HTTP capture vialib/posthog-server.ts),account_purged,account_restored. - Dev-slot e2e trick: with
WORKSPACE_DEV_AUTH=1the request route logs the confirm link to the dev log; set[email protected]temporarily to exercise logged-out signup/login UI on a dev slot.
[Claude Code]