Skip corrupt unlocker metadata in unlocker select and remove (closes #72) #91

Merged
clawbot merged 1 commits from issue-72-skip-corrupt-unlocker-lookup into next 2026-10-04 12:42:02 +02:00
Collaborator

Fixes #72: secret unlocker select ID and secret unlocker remove ID failed when an unlocker directory whose metadata could not be checked, read or parsed sorted before the one asked for.

What changed:

  • The code in ListUnlockers that reads one unlocker directory's metadata, or warns and skips it (from #61), moved into readUnlockerMetadataOrWarn, which findUnlockerByID also uses, so lookup skips the same directories with the same warning.
  • A skipped directory has no ID, so findUnlockerByID returns it, without an unlocker, when its directory name is the ID asked for. RemoveUnlocker removes it with secret.RemoveDirAtomic (from #69); SelectUnlocker reports it as not found.
  • In secret unlocker remove, removing a skipped directory whose metadata file is missing or corrupt never counts as removing the last unlocker, as in the duplicate check before adding; one whose metadata file cannot be checked for or read always does, since it may be the only working unlocker.

What the diff does not show:

  • Removing a skipped directory removes only the directory: its type is unknown, so a keychain item or Secure Enclave key it used stays behind.
  • Judgement call: secret unlocker remove prints the skip warning twice, once while counting unlockers and once in the lookup.
  • An ID that matches no unlocker, in a vault with one unlocker and secrets, is now reported as not found instead of being refused as the last unlocker.
  • Lookup now warns about a directory with no metadata file, as listing does; it used to skip it silently.

Model: opus-5-5

Fixes https://git.eeqj.de/sneak/secret/issues/72: `secret unlocker select ID` and `secret unlocker remove ID` failed when an unlocker directory whose metadata could not be checked, read or parsed sorted before the one asked for. What changed: - The code in `ListUnlockers` that reads one unlocker directory's metadata, or warns and skips it (from https://git.eeqj.de/sneak/secret/pulls/61), moved into `readUnlockerMetadataOrWarn`, which `findUnlockerByID` also uses, so lookup skips the same directories with the same warning. - A skipped directory has no ID, so `findUnlockerByID` returns it, without an unlocker, when its directory name is the ID asked for. `RemoveUnlocker` removes it with `secret.RemoveDirAtomic` (from https://git.eeqj.de/sneak/secret/pulls/69); `SelectUnlocker` reports it as not found. - In `secret unlocker remove`, removing a skipped directory whose metadata file is missing or corrupt never counts as removing the last unlocker, as in the duplicate check before adding; one whose metadata file cannot be checked for or read always does, since it may be the only working unlocker. What the diff does not show: - Removing a skipped directory removes only the directory: its type is unknown, so a keychain item or Secure Enclave key it used stays behind. - Judgement call: `secret unlocker remove` prints the skip warning twice, once while counting unlockers and once in the lookup. - An ID that matches no unlocker, in a vault with one unlocker and secrets, is now reported as not found instead of being refused as the last unlocker. - Lookup now warns about a directory with no metadata file, as listing does; it used to skip it silently. Model: opus-5-5
clawbot added the needs-review label 2026-10-04 11:12:42 +02:00
clawbot self-assigned this 2026-10-04 11:12:42 +02:00
Author
Collaborator

FAIL (needs-rework)

  1. internal/cli/unlockers.go, the new last-unlocker check in removeUnlocker (with Vault.RemoveUnlocker in internal/vault/unlockers.go): removing a directory that secret unlocker list skips never counts as removing the last unlocker. That is right for a corrupt metadata file. But listing also skips a directory whose metadata file cannot be checked or read (a permission or I/O error), and that unlocker may still be the vault's only working one. In a vault with secrets whose only unlocker has an unreadable metadata file, secret unlocker remove with that directory name now deletes it without --force. Before this change the command refused, and the README still says the last unlocker of a vault with secrets is removed only with --force. This loosens the check that #64 made stop on unreadable state. Acceptable: when listing shows no unlocker, removing a skipped directory from a vault with secrets is refused without --force, as removing the last unlocker is. Letting only a missing or corrupt metadata file bypass the check, as the duplicate check before adding does, is also acceptable. Add a test with an unreadable metadata file, and make the comment above the check and the TODO.md entry ("never counts as removing the last unlocker") match the code.

Note: the branch conflicts with current next only in TODO.md. I reviewed it with both entries kept.

Judgement call: I did not count the PR body, at about 250 words, as over the limit.

Model: opus-5-5

**FAIL** (`needs-rework`) 1. `internal/cli/unlockers.go`, the new last-unlocker check in `removeUnlocker` (with `Vault.RemoveUnlocker` in `internal/vault/unlockers.go`): removing a directory that `secret unlocker list` skips never counts as removing the last unlocker. That is right for a corrupt metadata file. But listing also skips a directory whose metadata file cannot be checked or read (a permission or I/O error), and that unlocker may still be the vault's only working one. In a vault with secrets whose only unlocker has an unreadable metadata file, `secret unlocker remove` with that directory name now deletes it without `--force`. Before this change the command refused, and the README still says the last unlocker of a vault with secrets is removed only with `--force`. This loosens the check that https://git.eeqj.de/sneak/secret/pulls/64 made stop on unreadable state. Acceptable: when listing shows no unlocker, removing a skipped directory from a vault with secrets is refused without `--force`, as removing the last unlocker is. Letting only a missing or corrupt metadata file bypass the check, as the duplicate check before adding does, is also acceptable. Add a test with an unreadable metadata file, and make the comment above the check and the `TODO.md` entry ("never counts as removing the last unlocker") match the code. Note: the branch conflicts with current `next` only in `TODO.md`. I reviewed it with both entries kept. Judgement call: I did not count the PR body, at about 250 words, as over the limit. Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-10-04 11:52:12 +02:00
clawbot added 1 commit 2026-10-04 12:22:44 +02:00
findUnlockerByID failed on the first unlocker directory whose metadata
could not be checked, read or parsed, so `secret unlocker select` and
`remove` failed when one sorted before the unlocker asked for. It now
skips such a directory with the warning ListUnlockers gives, through
the code both now share. A skipped directory is removed by its
directory name, with RemoveDirAtomic, and cannot be selected. Removing
one whose metadata file is missing or corrupt never counts as removing
the last unlocker; removing one whose metadata file cannot be checked
for or read does, since it may be the only working unlocker.

Model: opus-5-5
clawbot force-pushed issue-72-skip-corrupt-unlocker-lookup from a328e2487d to b9d2797840 2026-10-04 12:22:44 +02:00 Compare
clawbot added needs-review and removed needs-rework labels 2026-10-04 12:22:49 +02:00
Author
Collaborator

Reworked for the review of 2026-10-04 11:52:

  • secret unlocker remove: removing an unlocker directory whose metadata file is missing or corrupt still never counts as removing the last unlocker, as in the duplicate check before adding. Removing one whose metadata file cannot be checked for or read now counts as removing the last unlocker, so in a vault with secrets it needs --force.
  • Added a test: removing the only unlocker, whose metadata file cannot be checked for or read, from a vault with secrets is refused without --force and done with it.
  • The comment above the check and the TODO.md entry now say this.
  • Rebased onto current next; both TODO.md entries kept.

Model: opus-5-5

Reworked for the review of 2026-10-04 11:52: - `secret unlocker remove`: removing an unlocker directory whose metadata file is missing or corrupt still never counts as removing the last unlocker, as in the duplicate check before adding. Removing one whose metadata file cannot be checked for or read now counts as removing the last unlocker, so in a vault with secrets it needs `--force`. - Added a test: removing the only unlocker, whose metadata file cannot be checked for or read, from a vault with secrets is refused without `--force` and done with it. - The comment above the check and the `TODO.md` entry now say this. - Rebased onto current `next`; both `TODO.md` entries kept. Model: opus-5-5
Author
Collaborator

PASS: removing an unlocker whose metadata file cannot be checked for or read now needs --force in a vault with secrets, only a missing or corrupt metadata file bypasses that check, and lookup by ID skips unreadable or corrupt directories with the listing's warning, as #72 asks.

Model: opus-5-5

**PASS**: removing an unlocker whose metadata file cannot be checked for or read now needs `--force` in a vault with secrets, only a missing or corrupt metadata file bypasses that check, and lookup by ID skips unreadable or corrupt directories with the listing's warning, as https://git.eeqj.de/sneak/secret/issues/72 asks. Model: opus-5-5
clawbot merged commit 24d99819a3 into next 2026-10-04 12:42:02 +02:00
clawbot deleted branch issue-72-skip-corrupt-unlocker-lookup 2026-10-04 12:42:02 +02:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/secret#91