| 1 | # Personal-data erasure |
| 2 | |
| 3 | Owner: Flagon support (`support@g1t.sh`). Check **sudo → Customers → Privacy** and the support inbox each business day. The sidebar counts open requests. Check failed cleanup jobs even when there are no open requests. An empty queue is not proof that an erasure request has been fulfilled. |
| 4 | |
| 5 | ## Receive and assess |
| 6 | |
| 7 | Settings → Account accepts a request independently of account closure, sole workspace ownership and outstanding billing. Intake does not delete anything. Repeated submissions keep the original deadline. Staff can record requests received elsewhere with their original receipt time; recording one for a person who already has an open case adds the notes to that case's trail and can only move its deadline earlier. Each case shows its full trail (intake, reviews, refusal or completion) in sudo. A request about a person without an account belongs in the restricted support case system; it must not be rejected because no username exists. |
| 8 | |
| 9 | Respond without undue delay, ordinarily within one calendar month of receipt. The application clamps the corresponding day to the last day of the next month. It does not automatically grant extensions or reset the deadline during verification. If an extension is legally justified, explain it to the requester within the original period and record the reason and revised date in the review. Ask only for proportionate identity evidence; use the existing authenticated session or verified address where sufficient. Never request passwords, recovery codes, or unnecessary identity documents. |
| 10 | |
| 11 | Record the requested scope, identity verification, affected account/workspace/repository IDs, and whether Flagon is controller or processing workspace content for a customer. Contact the responsible workspace controller where needed. Ownership and unpaid bills are operational matters to resolve, not blanket grounds to reject a personal-data request. Transfer an organization's ownership appropriately; assess which records are necessary for tax/accounting or legal claims, with a reason, restricted access and review/deletion date for each retained category. Do not delete another person's workspace or shared work simply because the requester authored it. |
| 12 | |
| 13 | ## Execute and verify |
| 14 | |
| 15 | For approved account erasure, use the existing staff account-deletion controls after the workspace disposition has been resolved, then **Deleted accounts → Purge** promptly. Do not impose the ordinary 30-day recovery delay on an approved erasure request. Workspace purge is separate. If closure is blocked by billing, resolve the retained billing records and workspace disposition with the operator; do not close the privacy case or insist that payment is a condition of considering erasure. |
| 16 | |
| 17 | Identity commits five jobs atomically with a purge: avatar cleanup, Chat, Notify, Artifacts, and event publication. A restore that won the transaction prevents both deletion and scheduling. Jobs run every 15 minutes, in batches, and remain pending on error. Error retries back off to at most 16 hours; large successful batches continue at the next sweep. Repair the failing service/binding and verify the next retry. Do not manually mark failed jobs completed. Successful jobs remove their payload and retain a minimal receipt. |
| 18 | |
| 19 | Automatic cleanup covers: |
| 20 | |
| 21 | - Identity's account record, emails, credentials and personal settings; the avatar is removed when no account/workspace still references it. |
| 22 | - Chat memberships, reactions and join state; the person's private conversation with g1t, including AI answers and pending jobs, is removed. Authorship in shared conversations becomes `ghost`; the shared conversation itself, and other members' pending answers, are untouched. A workspace purge removes its channels, messages (in chunks, over several retries for a large workspace), settings and unreferenced emoji files, and tombstones reject late channels, members, messages, reactions, settings, emoji and meter rows. |
| 23 | - The person's notification feed, browser push subscription credentials, Expo device tokens, visit state and known presence/topic registrations. A permanent tombstone makes later deliveries to the erased feed no-ops (dropped, not refused). Presence rooms recorded before this implementation may include historical memberships no longer discoverable from a feed: check those rooms from the case's membership inventory as well. |
| 24 | - For a workspace purge, Notify clears the workspace from the feeds of the members identity held at purge time and of everyone its presence rooms know, under its current slug and any former slug no live workspace holds. The person whose username it is may make the slug again, so these marks are times, not bans: notifications from before the purge are dropped, and counts, seeds and visits (which carry no time) are refused for 24 hours. **Not reached:** former members and non-members (watchers, people mentioned on public repositories) who were notified under the workspace's name. Review these where the case requires it. |
| 25 | - Unshared private folios (in any workspace), their live room, files, versions, proposals, text search and vector records. Personal visits, favorites, access requests, memberships, mention lists and authorship fields (including cleared-by and repository-space added-by) are removed or replaced in shared artifacts. Workspace purge also removes pages, spaces, repository-doc copies, uploads and embedding state, a page at a time. Failures preserve the SQL references needed for retry. An index run that races an erasure writes no search rows and takes back the vectors it wrote. |
| 26 | - **Not covered automatically in Artifacts:** comment threads and their authors inside a shared document's live state and its saved version snapshots; pages in a private space (kept and ghosted, unlike private folios); live documents of pages deleted before this change (ordinary page deletion now destroys them); rooms beyond the first 200 of an emptied folio trash; large folio version blobs (`docs/versions/<folio>/…`) and upload blobs of folios deleted earlier; vectors whose deletion failed during an earlier ordinary deletion. Treat these as manual review items. |
| 27 | - Publication of `user.deleted` / `workspace.deleted` to existing lifecycle consumers. **Publication is not a consumer acknowledgement.** Check the bus and subscriber dead-letter queues and verify the resulting records in Work, Repos, Projects, Integrations, Webhooks, Actions, Deployments, Billing, Security, Search, Packages and the inbox. Retry failed lifecycle work and verify its effect before recording completion. |
| 28 | |
| 29 | The automatic path does **not** discover every occurrence of a person's information inside free text, git commits, collaborative document state/history, attachments, AI output or another user's notifications. Review these explicitly. Replacing a username with `ghost` is not proof of anonymisation. Use a scoped, reviewed data correction/removal for content that must be erased, covering current content, revision/Yjs state, exported blobs, FTS, vectors and caches. For git history, assess authorship, legal basis and downstream clones before a coordinated history rewrite. Record any permitted retention and explain it to the requester. |
| 30 | |
| 31 | Review copies held by Cloudflare logging/storage, HeyCatch, analytics, Google Workspace mail, Expo and any workspace-configured AI/integration providers as applicable. Removing a push token prevents future deliveries; it does not recall messages already delivered. Contact recipients where required, obtain deletion confirmations or document their bounded retention/exception, and record reference IDs rather than sensitive response bodies. No provider request is sent automatically by this code. |
| 32 | |
| 33 | ## Backups, restores and closure |
| 34 | |
| 35 | Before completion, export a minimal restricted deletion ledger outside the databases that might be restored: subject IDs, affected resources, deletion date, required re-erasure actions and evidence references. Include deletions that predate the new job table. Do not put credentials or copies of erased content in that ledger. |
| 36 | |
| 37 | For each backup/versioned store, record its actual configured retention and expiry, who can access it, and how it is kept beyond ordinary use. Inspect D1 Time Travel, Durable Object backups, object-store versions, exports, developer copies and provider logs; do not assume they all have D1's schedule. Explain residual backup retention in the response. |
| 38 | |
| 39 | Restore procedure: keep the restored service isolated from public traffic and outbound notifications/jobs; replay the deletion ledger against restored identity data, all service databases, live-object state, files, indexes and cached copies; verify the subjects cannot authenticate and deleted content is inaccessible; then enable traffic. Restoring an older identity database also restores older outbox state, so that outbox cannot be the sole source of the replay ledger. Test this procedure on disposable fixtures before using it for recovery. |
| 40 | |
| 41 | Send the requester a clear outcome: what was erased, what remains and why, the retention/review dates, backup treatment, and relevant complaint/remedy information if any part is refused. Record the response reference. The staff completion form requires evidence for identity, downstream services, shared content, processors, backups, response and retention; it also refuses completion while the account or pending cleanup jobs remain. These records support an operator's assessment; the application does not certify legal compliance. Keep case notes minimal and review their necessity with the retention schedule. |
| 42 | |
| 43 | ## Deployment and validation |
| 44 | |
| 45 | Apply the identity `0049_privacy`, Chat `0006_erasure`, and Artifacts `0010_erasure` migrations before deploying code that uses them. Deploy Chat, Notify and Artifacts before Identity, then the web and sudo apps. Identity needs the new CHAT, NOTIFY and ARTIFACTS service bindings. A transient mismatch leaves jobs pending and retryable. These changes have no production effect until deployed. |
| 46 | |
| 47 | Validate on disposable staging accounts: one with shared work, a private g1t DM, a private folio with an upload, browser/mobile subscriptions and presence; keep another account's comparable data as a control. Submit a request, verify its original deadline survives a duplicate, exercise a storage/service failure, purge, and inspect all receipts and stores. Exercise a delayed message/job after erasure and a restore followed by ledger replay. Check legacy deletion tombstones separately: these changes do not automatically reconstruct cleanup references lost by previous purges. |
| 48 | |
| 49 | Local fixture tests: `cargo test -p g1t-identity --lib` and `node --test --test-isolation=none conformance/erasure.test.mjs`. These verify code behavior, not production provider configuration or completion of a real person's request. |
| 50 | |
| 51 | Legal references: [GDPR Articles 12, 17 and 19](https://eur-lex.europa.eu/eli/reg/2016/679/oj/eng) and [ICO erasure guidance](https://ico.org.uk/for-organisations/uk-gdpr-guidance-and-resources/individual-rights/individual-rights/right-to-erasure/). Check applicable law and current guidance when assessing a case. |