Account
Delete my account, forgot password, change email, change password, and sign out on other devices. It's part of the core: always on, with no kit to add. Code: convex/account/, convex/lib/account/, src/kits/account/, tests in tests/account.test.ts.
Blocks #
| Block | What it does |
|---|---|
account.email | Change email: the password, then a code sent to the new address; the old address gets a notice |
account.password | Change password; signs out the person's other devices |
account.sessions | Sign out on other devices |
account.delete | Delete my account. It names each space the person owns and how many people are in it, because those spaces go too |
They act on the viewer's own account, work on any page for anyone, and take every word as a prop. The Spaces screen shows all four in an "Account" section, reachable from "Spaces" on every space's bar, so deleting is always easy to find (App Store rule 5.1.1(v)). "Forgot password?" is on the sign-in screen.
Codes #
8 digits, stored hashed, good for 15 minutes, 5 tries, 45 seconds between sends. Password checks use Convex Auth's own rate limit.
What deleting does #
- Spaces the person owns are removed whole, with everything in them.
- Their posts in other people's spaces stay in place but empty, like a deleted post. Ledger movements say "gone".
- Everything else that points at the person is removed or cleared. Sign-ins, sessions and the user row go first, so the email is free at once.
- It can't be undone. A goodbye email is sent.
The erase plan (convex/lib/account/plan.ts) reads the schema at run time, so new tables are covered on their own, and a test fails if a table holds a person the plan misses.
AI and MCP #
New scope account:
| Tool | What it does |
|---|---|
account_overview | The account and the spaces it owns |
account_request_deletion | Emails the person a code |
account_confirm_deletion({ code }) | Deletes the account; the emailed code is the person's approval |
Changing email or password is only in the app, because those need the password and an AI is never handed one.