--- kind: task slug: disconnect-linked-email title: Disconnect a linked email from a user's profile plan_slug: multitenant-saas-hardening epic_slug: tenant-lifecycle status: draft priority: P2 tenant_id: global owner: unassigned cursor_todo_id: null updated_at: "2026-06-02" --- # Task summary Let a user remove a linked email from their profile. Sounds simple; isn't. Removing the wrong row can either lock the user out (no verified email = can't be matched on next sign-in) or strand an invite that was bound to that email. ## Why deferred from the invites convoy `Task-multi-email-identity` ships the "Linked emails" list as **read-only**. Adding a remove action requires: - Server-side guard: cannot remove the user's last verified identity. Cannot remove the `source='primary'` identity unless another verified identity is promoted to primary in the same transaction. - UX for the "this email has 2 pending workspace invites — accept or revoke them first" case. - Audit-log entry (overlaps with `Task-workspace-soft-delete-and-audit`). - Confirmation modal with clear "this will affect: pending invites X, Y" copy. ## Scope (sketch — refine when scheduled) - `identity.disconnectEmail({ identityId })` procedure with the guards above. - Profile UI: confirmation modal that lists pending-invite impact before the destructive action. - If the disconnected identity was `source='primary'`, prompt to choose a new primary from the remaining verified set. ## Acceptance criteria (draft) - [ ] Cannot disconnect the only verified identity on an account. - [ ] Disconnecting an email that has pending invites surfaces those invites in the confirmation flow. - [ ] Audit-log row written for every disconnect. ## Links - Epic: `./Epic-tenant-lifecycle.md` - Depends on: `./Task-multi-email-identity.md`, `./Task-workspace-soft-delete-and-audit.md` (for audit log).