Skip to content
103 linesCodeBlameRaw

Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.

Merge account deletion: soft delete for 30 days, staff restore and purge, ghost for what remains (identity 0037)1import assert from "node:assert/strict";
2import { test } from "node:test";
3
Staff delete an account with the workspaces it alone owns4import {
5 accountWentSummary,
6 confirmsUsername,
7 deletedWithAccount,
8 soleOwnerNote,
9 soleWorkspacesRefusal,
10 staffDeleteProblem,
11 staffDeletionRefusal,
12} from "./deleted-accounts.ts";
Merge account deletion: soft delete for 30 days, staff restore and purge, ghost for what remains (identity 0037)13
14const deletion = {
15 username: "ada",
16 workspaces: 2,
17 tokens: 1,
18 ssh_keys: 0,
19 applications: 0,
20 repositories: 0,
21 sole_owner_of: [],
22 protected: false,
23};
24
Staff delete an account with the workspaces it alone owns25const sole = (slug: string) => ({ slug, name: slug, members: 1, billing: null, protected: false });
26
27const went = { workspaces: 2, teams: 1, repositories: 3, tokens: 1, sshKeys: 2, staff: null, reason: null, deletedWorkspaces: [] };
28
Merge account deletion: soft delete for 30 days, staff restore and purge, ghost for what remains (identity 0037)29test("what went reads as one line", () => {
Staff delete an account with the workspaces it alone owns30 assert.equal(accountWentSummary(went), "2 workspaces, 1 team, 3 repositories, 1 token, 2 SSH keys");
Merge account deletion: soft delete for 30 days, staff restore and purge, ghost for what remains (identity 0037)31});
32
Staff delete an account with the workspaces it alone owns33test("only a protected account is refused outright", () => {
Merge account deletion: soft delete for 30 days, staff restore and purge, ghost for what remains (identity 0037)34 assert.equal(staffDeletionRefusal(deletion), null);
Staff delete an account with the workspaces it alone owns35 const owner = { ...deletion, sole_owner_of: [sole("acme")] };
36 assert.equal(staffDeletionRefusal(owner), null);
Merge account deletion: soft delete for 30 days, staff restore and purge, ghost for what remains (identity 0037)37 assert.equal(
Staff delete an account with the workspaces it alone owns38 staffDeletionRefusal({ ...owner, username: "g1t", protected: true }),
39 "g1t is protected and can never be deleted.",
Merge account deletion: soft delete for 30 days, staff restore and purge, ghost for what remains (identity 0037)40 );
Staff delete an account with the workspaces it alone owns41});
42
43test("workspaces it owns alone go with it, said up front", () => {
44 assert.equal(soleOwnerNote(deletion), null);
45 assert.match(soleOwnerNote({ ...deletion, sole_owner_of: [sole("ada")] })!, /^ada is the only owner of 1 workspace\. Deleting the account deletes it first/);
46 assert.match(soleOwnerNote({ ...deletion, sole_owner_of: [sole("a"), sole("b")] })!, /of 2 workspaces\. Deleting the account deletes them first/);
47 assert.equal(soleWorkspacesRefusal({ ...deletion, sole_owner_of: [sole("ada")] }), null);
48});
49
50test("a protected workspace or billing that cannot settle stops it, naming which", () => {
51 const owner = {
52 ...deletion,
53 sole_owner_of: [
54 sole("ada"),
55 { ...sole("flagon-io"), protected: true },
56 { ...sole("ada-labs"), billing: "ada-labs has an unpaid invoice. Pay it from the workspace's Billing page first." },
57 ],
58 };
Merge account deletion: soft delete for 30 days, staff restore and purge, ghost for what remains (identity 0037)59 assert.equal(
Staff delete an account with the workspaces it alone owns60 soleWorkspacesRefusal(owner),
61 "ada cannot be deleted with its workspaces yet. flagon-io is protected and can never be deleted. ada-labs has an unpaid invoice. Pay it from the workspace's Billing page first.",
Merge account deletion: soft delete for 30 days, staff restore and purge, ghost for what remains (identity 0037)62 );
63});
64
65test("staff confirm with the username", () => {
66 assert.ok(confirmsUsername("ada", " ADA "));
67 assert.ok(!confirmsUsername("ada", ""));
68 assert.ok(!confirmsUsername("ada", "grace"));
69});
Staff delete an account with the workspaces it alone owns70
71test("the form needs a reason, the username, and the box ticked when workspaces go too", () => {
72 const form = { username: "ada", reason: "Retired test account", confirm: "ada", withWorkspaces: false, acknowledged: false };
73 assert.equal(staffDeleteProblem(form), null);
74 assert.equal(staffDeleteProblem({ ...form, reason: "" }), "Say why the account is being deleted.");
75 assert.equal(staffDeleteProblem({ ...form, confirm: "grace" }), "Type ada to confirm.");
76 assert.equal(
77 staffDeleteProblem({ ...form, withWorkspaces: true }),
78 "Tick the box to say the workspaces it alone owns are deleted too.",
79 );
80 assert.equal(staffDeleteProblem({ ...form, withWorkspaces: true, acknowledged: true }), null);
81});
82
83test("workspaces deleted with the account are matched to their deletions", () => {
84 const waiting = {
85 workspaceId: "wsp_1",
86 slug: "ada",
87 name: "Ada",
88 deletedAt: "2026-10-08T00:00:00.000Z",
89 deletedBy: "staff@g1t.sh",
90 purgeAfter: "2026-11-07T00:00:00.000Z",
91 went: { repositories: 1, projects: 0, members: 1, billing: null, protected: false },
92 restorable: true,
93 };
94 const gone = deletedWithAccount(
95 { ...went, deletedWorkspaces: [{ workspaceId: "wsp_1", slug: "ada" }, { workspaceId: "wsp_2", slug: "ada-labs" }] },
96 [waiting],
97 );
98 assert.deepEqual(gone, [
99 { workspaceId: "wsp_1", slug: "ada", deleted: waiting },
100 { workspaceId: "wsp_2", slug: "ada-labs", deleted: null },
101 ]);
102 assert.deepEqual(deletedWithAccount(went, [waiting]), []);
103});

This file's history is long; its oldest lines are credited to the oldest commit read.