Ask before removing a secret, version, vault or unlocker (closes #39)
check / check (push) Failing after 3s

secret rm, secret version rm, secret vault remove and secret unlocker
remove ask [y/N] on a terminal, naming what they remove, and go ahead
only on y or yes. Without --force, a command whose stdin is not a
terminal fails at once. --force, now also on rm and version rm,
removes without asking; it replaces the old refusals to remove a vault
with secrets or the last unlocker without --force. The checks run and
the question is asked before the state directory lock is taken; under
the lock the checks run again, and nothing is removed if they would
ask a different question.

Model: opus-5-5
This commit is contained in:
2026-10-04 15:18:17 +00:00
parent 7e4e0f7806
commit b4a03c595e
17 changed files with 1146 additions and 256 deletions
+47 -21
View File
@@ -70,6 +70,24 @@ make build
## Commands Reference
### Confirmation Before Removal
`secret rm`, `secret version rm`, `secret vault remove` and
`secret unlocker remove` destroy data that exists nowhere else. On a terminal
each one first asks `[y/N]`, naming exactly what it is about to remove, and
goes ahead only on `y` or `yes`; any other answer, a bare Enter included,
cancels and removes nothing. The question is asked only after the command's
checks have passed, and before it changes anything.
Whether to ask is decided by stdin, where the answer is read from, so
`secret rm foo | tee log` still asks. When stdin is not a terminal, as in a
script or a CI job, nobody is there to answer: the command fails at once,
removes nothing, and says to pass `--force`.
`--force` (`-f`) removes without asking, whatever the command removes: a vault
that holds secrets and the last unlocker of a vault included. Scripts that
remove things pass `--force`.
### Initialization
#### `secret init`
@@ -100,13 +118,13 @@ Switches to the specified vault for subsequent operations.
#### `secret vault remove <name> [--force]` / `secret vault rm` ⚠️ 🛑
**DANGER**: Permanently removes a vault and all its secrets. Like Unix `rm`,
this command does not ask for confirmation.
**DANGER**: Permanently removes a vault and all its secrets. It first asks
for confirmation, naming the vault and how many secrets it holds (see
[Confirmation Before Removal](#confirmation-before-removal)). The last vault
cannot be removed. Removing the current vault makes another vault the current
one.
Requires --force if the vault contains secrets. With --force, will
automatically switch to another vault if removing the current one.
- `--force, -f`: Force removal even if vault contains secrets
- `--force, -f`: Remove without asking, also a vault that contains secrets
- **NO RECOVERY**: All secrets in the vault will be permanently deleted
### Secret Management
@@ -132,9 +150,12 @@ Retrieves and outputs a secret value to stdout.
Lists all secrets in the current vault. Optional filter for substring
matching.
#### `secret remove <secret-name>` / `secret rm` ⚠️ 🛑
#### `secret remove <secret-name> [--force]` / `secret rm` ⚠️ 🛑
**DANGER**: Permanently removes a secret and ALL its versions. Like Unix `rm`, this command does not ask for confirmation.
**DANGER**: Permanently removes a secret and ALL its versions. It first asks
for confirmation, naming the secret, its vault and how many versions it has
(see [Confirmation Before Removal](#confirmation-before-removal)).
- `--force, -f`: Remove without asking
- **NO RECOVERY**: Once removed, the secret cannot be recovered
- **ALL VERSIONS DELETED**: Every version of the secret will be permanently deleted
@@ -158,10 +179,12 @@ Lists all versions of a secret showing creation time, status, and validity perio
Promotes a specific version to current by updating the symlink. Does not
modify any timestamps, allowing for rollback scenarios.
#### `secret version remove <secret-name> <version>` / `secret version rm` ⚠️ 🛑
#### `secret version remove <secret-name> <version> [--force]` / `secret version rm` ⚠️ 🛑
**DANGER**: Permanently removes a specific version of a secret. Like Unix
`rm`, this command does not ask for confirmation.
**DANGER**: Permanently removes a specific version of a secret. It first asks
for confirmation, naming the version, the secret and its vault (see
[Confirmation Before Removal](#confirmation-before-removal)).
- `--force, -f`: Remove without asking
- **NO RECOVERY**: Once removed, this version cannot be recovered
- Cannot remove the current version (must promote another version first)
@@ -202,12 +225,15 @@ has, which is removed only once the new one is the current unlocker.
#### `secret unlocker remove <unlocker-id> [--force]` / `secret unlocker rm` ⚠️ 🛑
**DANGER**: Permanently removes an unlocker. Like Unix `rm`, this command
does not ask for confirmation. Cannot remove the last unlocker if the vault
has secrets unless --force is used. An unlocker directory that
`secret unlocker list` skips with a warning, because its metadata cannot be
read or parsed, is removed by the directory name the warning gives.
- `--force, -f`: Force removal of last unlocker even if vault has secrets
**DANGER**: Permanently removes an unlocker. It first asks for confirmation,
naming the unlocker and its vault and saying whether it is the vault's last
unlocker; for the last one it says how many secrets the vault holds and warns
that the vault then opens only with its mnemonic (see
[Confirmation Before Removal](#confirmation-before-removal)). An unlocker
directory that `secret unlocker list` skips with a warning, because its
metadata cannot be read or parsed, is removed by the directory name the
warning gives.
- `--force, -f`: Remove without asking, even the last unlocker
- **CRITICAL WARNING**: Without unlockers and without your mnemonic phrase,
vault data will be PERMANENTLY INACCESSIBLE
- **NO RECOVERY**: Removing all unlockers without having your mnemonic means
@@ -377,7 +403,7 @@ secret list
secret get database/prod/password
secret get services/api/key
# Remove a secret ⚠️ 🛑 (NO CONFIRMATION - PERMANENT!)
# Remove a secret ⚠️ 🛑 (asks first - PERMANENT!)
secret remove ssh/servers/web01
```
@@ -400,7 +426,7 @@ echo "personal-email-pass" | secret add email/password
# List all vaults
secret vault list
# Remove a vault ⚠️ 🛑 (NO CONFIRMATION - PERMANENT!)
# Remove a vault ⚠️ 🛑 (--force: NO CONFIRMATION - PERMANENT!)
secret vault remove personal --force
```
@@ -418,7 +444,7 @@ secret unlocker list
# Select a specific unlocker
secret unlocker select <unlocker-id>
# Remove an unlocker ⚠️ 🛑 (NO CONFIRMATION!)
# Remove an unlocker ⚠️ 🛑 (asks first!)
secret unlocker remove <unlocker-id>
```
@@ -431,7 +457,7 @@ secret version list database/prod/password
# Promote an older version to current
secret version promote database/prod/password 20231215.001
# Remove an old version ⚠️ 🛑 (NO CONFIRMATION - PERMANENT!)
# Remove an old version ⚠️ 🛑 (asks first - PERMANENT!)
secret version remove database/prod/password 20231214.001
```