| 1 | -- Deleting an account is soft first. The row stays, with when, by whom and |
| 2 | -- until when g1t's staff can restore it, and every read that resolves a |
| 3 | -- person leaves it out: it cannot sign in, its profile is not found, and |
| 4 | -- nobody can add it to anything. Its sessions, tokens, keys and |
| 5 | -- memberships are removed at once (src/account_deletion.rs). The row keeps |
| 6 | -- the username from anyone else meanwhile. Once purge_after passes, the |
| 7 | -- scheduled purge removes it with its personal data. |
| 8 | -- |
| 9 | -- `deleted_by`: the account itself when the person deleted it; null when |
| 10 | -- staff did (who, and why, are in `deleted_went`). |
| 11 | -- `deleted_went`: JSON, what went with it, counted when it was deleted, |
| 12 | -- and the memberships, teams and repository roles it left, so a restore |
| 13 | -- can put them back. |
| 14 | ALTER TABLE users ADD COLUMN deleted_at TEXT; |
| 15 | ALTER TABLE users ADD COLUMN deleted_by TEXT; |
| 16 | ALTER TABLE users ADD COLUMN purge_after TEXT; |
| 17 | ALTER TABLE users ADD COLUMN deleted_went TEXT; |
| 18 | |
| 19 | CREATE INDEX IF NOT EXISTS users_purge_after ON users (purge_after) WHERE deleted_at IS NOT NULL; |
| 20 | |
| 21 | -- A purged account's username, kept so it is never given to another |
| 22 | -- account or workspace: links, mentions and commits that name it keep |
| 23 | -- meaning what they meant. Nothing personal: the id is random. |
| 24 | CREATE TABLE IF NOT EXISTS deleted_users ( |
| 25 | username TEXT PRIMARY KEY, |
| 26 | user_id TEXT NOT NULL, |
| 27 | deleted_at TEXT NOT NULL, |
| 28 | purged_at TEXT NOT NULL |
| 29 | ); |
| 30 | |
| 31 | -- `ghost`: who wrote what a purged account wrote. A row of its own, so a |
| 32 | -- workspace whose creator is purged still names an account. It has no |
| 33 | -- password and no address, and is marked deleted with no purge time, so it |
| 34 | -- can never sign in, is never listed, and is never purged. `ghost` is a |
| 35 | -- reserved name, so nobody can register it. |
| 36 | INSERT OR IGNORE INTO users (id, username, password_hash, created_at, deleted_at) |
| 37 | VALUES ('usr_ghost', 'ghost', '', '2026-10-08T00:00:00.000Z', '2026-10-08T00:00:00.000Z'); |