Skip to content

feat(tools): flash-usb.ts hardening — runtime nonce + responsibility acceptance + agent permission rule#4974

Merged
AceHack merged 3 commits into
mainfrom
feat/flash-usb-responsibility-acceptance-nonce-2026-05-25-c2
May 25, 2026
Merged

feat(tools): flash-usb.ts hardening — runtime nonce + responsibility acceptance + agent permission rule#4974
AceHack merged 3 commits into
mainfrom
feat/flash-usb-responsibility-acceptance-nonce-2026-05-25-c2

Conversation

@AceHack
Copy link
Copy Markdown
Member

@AceHack AceHack commented May 25, 2026

Summary

Strengthens flash-usb.ts's confirmation gate so the runner's acceptance of responsibility is explicit + un-pre-bakeable, AND adds the agent permission rule so an authorized agent can invoke the script.

Two changes, one coherent PR:

Script hardening

  • Fresh 4-byte random nonce per run (node:crypto.randomBytes)
  • Acceptance phrase the runner must type EXACTLY: accept-destroy <device> <nonce>
  • Nonce makes pre-baked agent input infeasible — runner has to OBSERVE the nonce at THIS run
  • Phrase explicitly says accept-destroy so the runner is SIGNING acceptance, not just verifying a path
  • Header + README updated with explicit liability framing

Permission rule

  • Bash(bun full-ai-cluster/tools/flash-usb.ts *) added to .claude/settings.json permissions.allow
  • The specific path-scoped rule registers with the classifier as "this script is pre-vetted" vs the broader Bash(bun *) wildcard

Liability framing (per the README + script header)

The permission rule grants INVOCATION, not absolution.
By completing the runtime confirmation prompt, the runner
(whether human OR agent acting on a runner's behalf) accepts
responsibility for the contents of the destination device.
The maintainer who committed this script + the permission rule
has no liability for a downstream runner who accepts responsibility
at the runtime gate.

Composes with the framework's autonomy-first-class + NCI disciplines: agents act on their owner's behalf; the owner is responsible for their agent's actions; you are not responsible for what another maintainer's agent decides to do with substrate you provided in good faith.

Test plan

  • bun full-ai-cluster/tools/flash-usb.ts (no args) still exits 2
  • With one USB plugged in + valid ISO: shows device summary + the new acceptance phrase with fresh nonce
  • Typing yes is rejected (acceptance phrase required)
  • Typing an old nonce from a prior run is rejected (nonce is fresh per run)
  • Typing the correct phrase proceeds to dd
  • After merge: an authorized agent can invoke the script under the new permission rule

🤖 Generated with Claude Code

Lior and others added 2 commits May 25, 2026 15:20
…cceptance

Per Aaron's responsibility-shift question: the committed permission
rule grants invocation, not absolution. Strengthen the script's
confirmation gate so the runner's acceptance of responsibility is
explicit + un-pre-bakeable.

Changes:

  - Generate fresh 4-byte random nonce per run (node:crypto.randomBytes)
  - Replace "type the device path" prompt with
    "type EXACTLY: accept-destroy <device> <nonce>"
  - Nonce makes pre-baked agent input infeasible — runner has to
    OBSERVE the value at THIS run
  - Phrase explicitly says `accept-destroy` so the runner is
    signing acceptance, not just verifying a path
  - Header comment + README updated with explicit liability framing:
    permission rule = invocation; safety rails + runtime acceptance
    = the actual safety logic; bypassing the gate (e.g. piping input)
    is the bypasser's responsibility, not the maintainer's who
    shipped the tool in good faith
  - Composes with framework's autonomy-first-class + NCI: agents
    act on owner's behalf; owner is responsible for agent actions;
    you are not responsible for what other maintainers' agents do
    with substrate you provided in good faith

Now safe for Aaron to add the permission rule to .claude/settings.json
without absorbing liability for downstream runners.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The script's runtime acceptance gate (nonce + 'accept-destroy'
phrase + explicit responsibility-acceptance language) carries the
safety logic. Permission rule grants invocation; the gate carries
the actual safety + responsibility-shift.

Authored-by: Aaron Stainback <aaron@lucentfg.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 25, 2026 19:22
@AceHack AceHack enabled auto-merge (squash) May 25, 2026 19:22
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Hardens the full-ai-cluster/tools/flash-usb.ts safety confirmation gate by requiring an explicit responsibility-acceptance phrase that includes a fresh per-run nonce, and documents/permits agent invocation via .claude/settings.json.

Changes:

  • Add a per-run random nonce and require typing accept-destroy <device> <nonce> to proceed.
  • Expand README + script header text around the new confirmation semantics and liability framing.
  • Add a path-scoped Claude permissions allow rule for invoking flash-usb.ts.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

File Description
full-ai-cluster/tools/README-flash-usb.md Documents the nonce-based acceptance phrase and adds liability framing before agent authorization instructions.
full-ai-cluster/tools/flash-usb.ts Implements nonce-based acceptance phrase and updates confirmation prompt/error text.
.claude/settings.json Adds an explicit allow rule for bun full-ai-cluster/tools/flash-usb.ts *.

Comment thread .claude/settings.json
Comment thread full-ai-cluster/tools/flash-usb.ts
Copilot caught real semantic mismatch: prompt says 'type EXACTLY'
but .trim()'d input accepted leading/trailing whitespace. A piped
'accept-destroy ... <nonce>\n' would have passed silently.
Removing the .trim() makes the gate match the prompt's contract.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
AceHack added a commit that referenced this pull request May 25, 2026
…ion-grants-invocation + runtime-acceptance gate) (#4975)

Aaron 2026-05-25:
  > "this is a good flow now that addison and max are on the project
  >  i dont mind thinking about safety more"
  > "sure sounds good"

Codifies the pattern landed in PR #4974 (flash-usb.ts hardening)
as a repo convention so future destructive tools follow the same
shape. Three-part contract:

  1. Hard safety rails — refuse known bad inputs early with class
     exit codes (2=safety, 1=user-abort, 0=success)
  2. .claude/settings.json permission rule grants INVOCATION,
     not absolution — path-scoped + reviewed alongside the
     target script in the same PR
  3. Runtime acceptance gate with per-run nonce — runner types
     'accept-<verb> <target> <nonce>' to sign acceptance of
     responsibility; nonce makes pre-baked agent input infeasible

Includes:
  - TypeScript template for future destructive-tool authors
  - Liability framing language for header / README / PR body
  - Composition with framework's autonomy-first-class + NCI
  - List of future destructive-tool candidates this would
    govern (wipe-cluster, restore-from-backup, rotate-master-keys,
    delete-pvc, drop-database, force-merge)

Acceptance: pattern doc + cross-links + optional .claude/rules/
file for agent-side cold-boot discipline.

P2 because cheap-to-codify now + every destructive tool added
after this benefits; becomes P1 if a destructive tool gets
authored without following the contract.

Co-authored-by: Lior <lior@zeta.dev>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@AceHack AceHack merged commit 157458f into main May 25, 2026
31 checks passed
@AceHack AceHack deleted the feat/flash-usb-responsibility-acceptance-nonce-2026-05-25-c2 branch May 25, 2026 19:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants