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

A test fails when a new danger button posts straight from a page instead of through the confirm page #7989

Merged opened this

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

Merged

This adds `test/danger-buttons.test.ts`. It does a plain text scan of every `.ts` file under `src/web/` and looks for `variant: "danger"` buttons that sit inside an open `<form method="post">`. When it finds one that isn't allowed, it fails with `file:line "Label" posts without asking: use confirmAction from src/web/ui.ts`.

shipped production is serving it deploy 2e641a3

opened this

This adds test/danger-buttons.test.ts. It does a plain text scan of every .ts file under src/web/ and looks for variant: "danger" buttons that sit inside an open <form method="post">. When it finds one that isn't allowed, it fails with file:line "Label" posts without asking: use confirmAction from src/web/ui.ts.

What it lets through without a confirm:

  • buttons whose btn(...) options set href, which covers confirmAction;
  • forms that contain a name="confirm" field (or name: "confirm", the formField form). That covers confirmBody in search.ts, the chain "Sever" form, and the accounts suspend/retire forms.

Today's other cases are listed in the test, one line each, keyed by file and button label so a new button in the same file is still caught:

  • board panel "Remove" (the panel index is in the body)
  • board delete
  • team member "Remove" in org.ts
  • the edit page's "Delete this file" (the page is the confirmation)
  • the detach page
  • "Land past the gate" (asks for a typed reason)
  • owner-note ban in studio/notes.ts (undone by unban)

A listed case that no longer exists only prints a hint telling you to drop it, so the sibling confirm pulls can land in any order without touching this file.

Things to look at:

  • Scan rules: these are deliberately narrow. The button must be a btn(/iconBtn( call within 400 characters of the danger option, with a <form before it that isn't closed yet and whose tag says method="post". Anything less certain is skipped, not failed.
  • App Stop: the issue names it, but no variant: "danger" button for it exists under src/web/, so it isn't listed. If it's built some other way, this scan doesn't see it.

Two tests check the scanner itself: the issue's Wipe example is caught, and links, confirm fields, GET forms, buttons after a closed form, and non-button variant objects are not. I also added the Wipe form to detach.ts temporarily: the test failed naming src/web/pages/detach.ts:89, and I reverted the file. The file runs in about 120 ms. bun scripts/gate.ts and bun x tsc --noEmit pass. No app code changed.

Try it: bun test test/danger-buttons.test.ts, then add a danger button inside a post form to any page.

🤖 Generated with Claude Code

Closes #7984

commented

This adds test/danger-buttons.test.ts. It does a plain text scan of every .ts file under src/web/ and looks for variant: "danger" buttons that sit inside an open <form method="post">. When it finds one that isn't allowed, it fails with file:line "Label" posts without asking: use confirmAction from src/web/ui.ts.

What it lets through without a confirm:

  • buttons whose btn(...) options set href, which covers confirmAction;
  • forms that contain a name="confirm" field (or name: "confirm", the formField form). That covers confirmBody in search.ts, the chain "Sever" form, and the accounts suspend/retire forms.

Today's other cases are listed in the test, one line each, keyed by file and button label so a new button in the same file is still caught:

  • board panel "Remove" (the panel index is in the body)
  • board delete
  • team member "Remove" in org.ts
  • the edit page's "Delete this file" (the page is the confirmation)
  • the detach page
  • "Land past the gate" (asks for a typed reason)
  • owner-note ban in studio/notes.ts (undone by unban)

A listed case that no longer exists only prints a hint telling you to drop it, so the sibling confirm pulls can land in any order without touching this file.

Things to look at:

  • Scan rules: these are deliberately narrow. The button must be a btn(/iconBtn( call within 400 characters of the danger option, with a <form before it that isn't closed yet and whose tag says method="post". Anything less certain is skipped, not failed.
  • App Stop: the issue names it, but no variant: "danger" button for it exists under src/web/, so it isn't listed. If it's built some other way, this scan doesn't see it.

Two tests check the scanner itself: the issue's Wipe example is caught, and links, confirm fields, GET forms, buttons after a closed form, and non-button variant objects are not. I also added the Wipe form to detach.ts temporarily: the test failed naming src/web/pages/detach.ts:89, and I reverted the file. The file runs in about 120 ms. bun scripts/gate.ts and bun x tsc --noEmit pass. No app code changed.

Try it: bun test test/danger-buttons.test.ts, then add a danger button inside a post form to any page.

🤖 Generated with Claude Code

Approved

Test-only change, no app code touched, no new dependency, no secrets or I/O beyond reading src/web. The scanner is narrow by design, the allowlist is keyed by file and label so a new button in a listed file is still caught, and stale entries only print a hint so sibling confirm pulls can land in any order. Two scanner tests cover the positive and negative cases. Note: App Stop is not covered because no danger button for it exists under src/web, as the description says. I could not run the file here (the branch checkout did not contain it), so I judged it from the diff.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs