Public: anyone can read this; the crew can change it.

Remove on a cloud account goes through the confirm page, which names the account and says its sealed token goes with it #8014

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

Removing a cloud account on Settings › Cloud now asks first, as the terminal already does. The confirm page names the account and says its sealed token is deleted.

shipped production is serving it deploy 3b6d43c

opened this

Removing a cloud account on Settings › Cloud now asks first, as the terminal already does. The confirm page names the account and says its sealed token is deleted.

  • src/web/pages/cloud.ts: the Remove form with hidden fields is replaced by confirmAction({ action: "/settings/cloud/remove?provider=…&name=…", verb: "Remove", size: "sm" }). The confirm page posts to its to path exactly, so the account travels in the query. cloudRemove reads provider and name from the form first and falls back to ctx.url.searchParams when the form has none. The admin gate, readForm(ctx, "admin") and removeAccount are unchanged.
  • src/web/pages/search.ts: one new DESTRUCTIVE entry, directly after the settings/origins entry, for ^/settings/cloud/remove\?provider=([a-z0-9_-]+)&name=([a-z][a-z0-9_]{0,31})$. Its title is "Remove the <provider> account <name>?", followed by the detail text from the issue. Because the pattern is anchored, a to with an extra parameter matches nothing and gets a 404.
  • test/confirm-cloud-remove.test.ts (new) proves three things:

- /settings/cloud links Remove to /-/confirm?to=…, and the old form action is gone. - The confirm page answers 200 with the title and posts to the escaped target; a crafted to with &back=… gets a 404. - The empty-body POST to the confirm target removes the account.

All three tests fail without the change.

The route in src/http/server.ts is untouched, as the issue asked.

Checks run before the push: bun scripts/gate.ts, bun x tsc --noEmit and bun scripts/design-lint.ts are clean. bun test test/confirm-cloud-remove.test.ts test/cloud.test.ts passes, 14 tests. scripts/fast.ts named 992 test files (too broad to run here), so I picked the covering suites myself: the cloud settings, doors, gate and timing tests, every confirm-* test, account unlink, search, cross-origin mutations, the security floor and the design audit. All 71 pass.

To try it: as an admin, open Settings › Cloud, press Remove on an account, read the confirm page, then press Remove account.

🤖 Generated with Claude Code

Closes #7982

commented

Removing a cloud account on Settings › Cloud now asks first, as the terminal already does. The confirm page names the account and says its sealed token is deleted.

  • src/web/pages/cloud.ts: the Remove form with hidden fields is replaced by confirmAction({ action: "/settings/cloud/remove?provider=…&name=…", verb: "Remove", size: "sm" }). The confirm page posts to its to path exactly, so the account travels in the query. cloudRemove reads provider and name from the form first and falls back to ctx.url.searchParams when the form has none. The admin gate, readForm(ctx, "admin") and removeAccount are unchanged.
  • src/web/pages/search.ts: one new DESTRUCTIVE entry, directly after the settings/origins entry, for ^/settings/cloud/remove\?provider=([a-z0-9_-]+)&name=([a-z][a-z0-9_]{0,31})$. Its title is "Remove the <provider> account <name>?", followed by the detail text from the issue. Because the pattern is anchored, a to with an extra parameter matches nothing and gets a 404.
  • test/confirm-cloud-remove.test.ts (new) proves three things:

- /settings/cloud links Remove to /-/confirm?to=…, and the old form action is gone. - The confirm page answers 200 with the title and posts to the escaped target; a crafted to with &back=… gets a 404. - The empty-body POST to the confirm target removes the account.

All three tests fail without the change.

The route in src/http/server.ts is untouched, as the issue asked.

Checks run before the push: bun scripts/gate.ts, bun x tsc --noEmit and bun scripts/design-lint.ts are clean. bun test test/confirm-cloud-remove.test.ts test/cloud.test.ts passes, 14 tests. scripts/fast.ts named 992 test files (too broad to run here), so I picked the covering suites myself: the cloud settings, doors, gate and timing tests, every confirm-* test, account unlink, search, cross-origin mutations, the security floor and the design audit. All 71 pass.

To try it: as an admin, open Settings › Cloud, press Remove on an account, read the confirm page, then press Remove account.

🤖 Generated with Claude Code

Approved

Works in the preview (confirm page answers 200 for the account target), no JS needed: Remove is an <a> to /-/confirm, the mutation is a POST, the admin gate and same-origin readForm are unchanged, the anchored pattern 404s a crafted target, and the three tests exercise each step. Two things I would do next: (1) the old button carried aria-label "Remove <name>"; confirmAction takes no label, so several accounts now expose identical "Remove" links to a screen reader. Give confirmAction an optional label and pass the account name. (2) The query fallback in cloudRemove makes the form fields dead for this route; drop the hidden() form fields path once nothing else posts them.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs