TheSkillz

Destructive Action Gate

A checklist and a hook that run before anything irreversible

TheSkillz Team TheSkillz Team No reviews yet0 installsv1.0.0
Scan passed · 100/100Human reviewedOfficial · TheSkillz
☆ Star 0

Classifies operations as reversible, recoverable or irreversible and gates only the last, because a gate that fires on everything gets switched off in a week. Requires a counted blast radius, a verified restore point and a written rollback command before it runs, and ships deny rules plus a PreToolUse hook for remote DB execution, force pushes, bulk deletes and terraform apply.

SKILL.md

Destructive Action Gate

Every team that has lost data has the same story afterwards: the command was familiar, the flag was one character different from usual, and nothing asked. The instinct is then to confirm everything — which produces a prompt on ls, teaches everyone to hit yes without reading, and leaves you worse off than before.

A gate that fires on everything gets switched off within a week. The discipline is to fire rarely, and to make it count when it does.

Classify first

Sort every operation into three buckets. Only the third is gated.

  • Reversible — undo is trivial and local. Editing a file, a local commit, adding a column, a feature branch. Never gate these.
  • Recoverable — undo exists but costs something: a backup restore, a revert deploy, a reflog rescue. Worth logging and worth naming out loud. Not worth blocking.
  • Irreversible — no undo, or an undo with a deadline you might miss. Dropping a table, deleting storage objects, force-pushing over someone else's work, deleting a secret, sending real messages, charging real money.

The line moves with configuration, and you have to check rather than assume. DELETE FROM is recoverable with point-in-time restore and irreversible without it. Object deletion is recoverable on a versioned bucket and permanent on an unversioned one. Verify which you have before you decide which bucket you are in.

The three things required before an irreversible action

Not a yes/no prompt — a yes/no prompt is answered reflexively. Three statements, in writing:

  1. Blast radius. What exactly is affected, and how much. Not "some rows" — run the SELECT COUNT(*) with the same WHERE clause first and state the number. A count that surprises you is the single most common way this gets caught in time.
  2. A verified restore point. Verified, not assumed. Name the backup, its timestamp, and the fact that you checked it exists. "Backups run nightly" is not a restore point; a bookmark id is.
  3. The rollback command, written out, ready to paste. If you cannot write it, you do not have one, and that is the finding.

If any of the three cannot be produced, the action does not run. That is the whole gate.

Wire it mechanically

Human discipline decays; make the harness carry it. Generate:

  • Deny and ask rules in .claude/settings.json for the patterns that matter: --remote database execution, DROP/TRUNCATE, rm -rf, git push --force (allow --force-with-lease), terraform apply and destroy, bulk object deletion, secret deletion, DELETE/UPDATE without a WHERE clause.
  • A PreToolUse hook that inspects the command and blocks with a message naming which of the three statements is missing, so the block teaches rather than merely obstructs.
  • A separate credential path for production. The strongest control here is not a prompt — it is that the everyday credential cannot perform the destructive operation at all.

Match on the shape of the command, not an exact string. wrangler d1 execute --remote and wrangler d1 execute db --remote --file x.sql must both match.

Recovery, for the minute after it happens anyway

Write this down before you need it, because you will be reading it in a hurry:

  • Postgres — point-in-time recovery to just before the statement, if WAL retention covers it. Check the retention window now, not then.
  • Cloudflare D1 — Time Travel restores to a bookmark or timestamp, typically within 30 days.
  • S3 and R2 — a versioned bucket keeps the previous version and a delete marker you can remove. An unversioned bucket keeps nothing.
  • gitgit reflog recovers a clobbered local branch for around 90 days. A force-pushed remote branch is recoverable only from someone's local clone, so ask the team before rewriting history.
  • Secrets — usually unrecoverable. Rotation is the plan, not restoration.

The retention window is the deadline. Find the number for each system and record it.

Judgement calls

  • Staging and production are different. Gate production. Gating a scratch database trains people to ignore the gate, which costs you the one that matters.
  • Bulk operations deserve extra scrutiny even when reversible. Restoring ten million rows is technically possible and practically a very long day.
  • Never widen a gate to get unblocked. If a rule fires and the action is legitimate, satisfy the three statements; do not edit the rule. The edit outlives the moment.

Verification gate

  • Deny rules are in place and tested against a deliberately dangerous command — an untested gate is not a gate.
  • The hook blocks and explains which statement is missing, rather than failing silently.
  • Retention windows for every backing store are written down with real numbers.
  • A restore has been rehearsed at least once against a non-production copy.
  • Reversible operations are demonstrably not gated — confirm the everyday workflow is unaffected.

Reviews

Sign in to leave a review.

  • Be the first to review this skill.

More in security