Skip to content

feat(cli)!: default secrets unset to no and require --all to unset every secret - #7172

Merged
Coly010 merged 3 commits into
nextfrom
columferry/cli-2346-require-safeguards-before-bulk-deleting-edge-function
Oct 15, 2026
Merged

Coly010 merged 3 commits into
nextfrom
columferry/cli-2346-require-safeguards-before-bulk-deleting-edge-function

Conversation

@Coly010

@Coly010 Coly010 commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Summary

supabase secrets unset defaulted to yes. On a non-TTY it confirmed itself, and with no names it lists every secret and deletes all the non-SUPABASE_ ones. A stray run in a script or CI could wipe every Edge Function secret, and there's no undo. This flips those defaults:

  • The prompt defaults to No and names the project it's about to change.
  • Without --yes (or SUPABASE_YES), a run that can't prompt (non-TTY stdin, piped stdout, or --output-format json/stream-json) fails before any request. Piped answers aren't read any more, so echo y | supabase secrets unset FOO no longer counts as consent.
  • With no names, the command now fails instead of unsetting everything. --all does that explicitly. Names and --all together are rejected. Both usage errors fail before any API call.
  • New --dry-run prints the secrets that would be unset and exits 0 without prompting or deleting, so --all can be previewed in CI without --yes.
  • JSON results gain names and dry_run, and --all with nothing to unset now returns an empty result instead of only a stderr line.

This applies the consent rule proposed in CLI-2695 (hosted destructive operations default to No and need --yes when non-interactive) to secrets unset only.

Linked issue

Closes CLI-2346

Checklist

  • The PR title follows Conventional Commits.
  • Tests added or updated for the change.
  • From the repository root, pnpm check:all passes.

BREAKING CHANGE: supabase secrets unset no longer defaults to yes. The prompt defaults to No, and a run that can't prompt (non-TTY stdin, non-interactive stdout, or JSON output) now fails unless --yes or SUPABASE_YES=1 is set, for named secrets and --all alike. Piped stdin answers are no longer read. Running it with no secret names now fails instead of unsetting every secret; pass --all to do that. Add --yes to unattended secrets unset invocations.

`secrets unset` with no names now fails unless `--all` is passed, and names
with `--all` is rejected; both fail before any API call. The prompt names the
project and defaults to No. Without `--yes` or `SUPABASE_YES`, a run that can't
prompt (non-TTY stdin, non-interactive stdout, or JSON output) fails before any
request, and piped answers are no longer read. `--dry-run` prints the secrets
that would be unset without prompting or deleting. JSON results gain `names`
and `dry_run`.
@Coly010
Coly010 requested a review from a team as a code owner October 15, 2026 09:01

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🤖 AI Review

Verified both review sets against the checked-out code. Confirmed Claude's single non-blocking output-consistency nit: an empty secret list produces no machine-readable result, including in the new dry-run workflow. This behavior predates the PR. Codex reported no findings. Tests were not run.

Findings

Severity Location Category Sources Claim
⚪ NIT apps/cli/src/commands/secrets/unset/unset.handler.ts:88 output-contract claude When --all finds no non-SUPABASE_ secrets, --all --dry-run and --all --yes return successfully with empty stdout even in json or stream-json mode, omitting the structured result and its count, names, and dry_run fields.

Findings outside the diff

  • ⚪ NIT apps/cli/src/commands/secrets/unset/unset.handler.ts:88 — When --all finds no non-SUPABASE_ secrets, --all --dry-run and --all --yes return successfully with empty stdout even in json or stream-json mode, omitting the structured result and its count, names, and dry_run fields.

Stats

Claude findings: 1 · Codex findings: 0 · Confirmed: 1 · Refuted: 0 · Uncertain: 0


Models: claude-opus-5-5 + gpt-6.1-sol · Trigger: auto · Workflow run

This review runs once per PR. A maintainer can request another with a /ai-review comment.

Machine output formats now get {project_ref, count: 0, names: [], dry_run}
instead of only the stderr no-op, so --all and --all --dry-run always return
a structured result.
@Coly010 Coly010 self-assigned this Oct 15, 2026
@Coly010 Coly010 changed the title feat(cli)!: require --all and confirmation before secrets unset deletes feat(cli)!: default secrets unset to no and require --all to unset every secret Oct 15, 2026
Comment thread apps/cli/src/commands/secrets/unset/unset.handler.ts
The confirmation-required refusal makes no secrets request, but the
linked-project cache in Effect.ensuring can still GET /v1/projects/{ref}.
Also correct the cache path to <workdir>/supabase/.temp/linked-project.json.
@Coly010
Coly010 added this pull request to the merge queue Oct 15, 2026
Merged via the queue into next with commit 59d4627 Oct 15, 2026
43 checks passed
@Coly010
Coly010 deleted the columferry/cli-2346-require-safeguards-before-bulk-deleting-edge-function branch October 15, 2026 10:56
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