Removing the vault's current unlocker left current-unlocker naming the removed one, so every command that opened the vault failed although another unlocker remained, and the error sent the user to the mnemonic.
vault.RemoveUnlocker now checks whether the unlocker it removes is the current one. If so, it makes current, before removing it, the first of the vault's other unlockers that secret unlocker select accepts, in the order secret unlocker list shows, and returns its ID, which secret unlocker remove prints as "Switched current unlocker to '...'". secret unlocker select refuses an unlocker whose metadata names a type other than passphrase or pgp, though secret unlocker list shows it. With no unlocker it accepts, current-unlocker is removed after the unlocker.
When current-unlocker names an unlocker that does not exist and the vault has another that secret unlocker select accepts, opening the vault fails with an error that wraps vault.ErrUnlockerNotFound and says to run secret unlocker select, without the mnemonic advice. The secret vault select step that the mnemonic advice puts first for a vault other than the current one moved into a small helper that both messages use.
RemoveUnlocker now returns (string, error). The regression test, TestUnlockerRemoveCurrent, uses a PGP unlocker for a throwaway GPG key, as TestAddPGPUnlocker does.
Judgement call: "pgp" became the constant unlockerTypePGP in internal/vault/unlockers.go, which its two existing type switches now use too.
Unverified: no test covers the select advice for a vault other than the current one.
Model: opus-5-5
Fixes https://git.eeqj.de/sneak/secret/issues/137.
Removing the vault's current unlocker left `current-unlocker` naming the removed one, so every command that opened the vault failed although another unlocker remained, and the error sent the user to the mnemonic.
`vault.RemoveUnlocker` now checks whether the unlocker it removes is the current one. If so, it makes current, before removing it, the first of the vault's other unlockers that `secret unlocker select` accepts, in the order `secret unlocker list` shows, and returns its ID, which `secret unlocker remove` prints as "Switched current unlocker to '...'". `secret unlocker select` refuses an unlocker whose metadata names a type other than `passphrase` or `pgp`, though `secret unlocker list` shows it. With no unlocker it accepts, `current-unlocker` is removed after the unlocker.
When `current-unlocker` names an unlocker that does not exist and the vault has another that `secret unlocker select` accepts, opening the vault fails with an error that wraps `vault.ErrUnlockerNotFound` and says to run `secret unlocker select`, without the mnemonic advice. The `secret vault select` step that the mnemonic advice puts first for a vault other than the current one moved into a small helper that both messages use.
`RemoveUnlocker` now returns `(string, error)`. The regression test, `TestUnlockerRemoveCurrent`, uses a PGP unlocker for a throwaway GPG key, as `TestAddPGPUnlocker` does.
Judgement call: `"pgp"` became the constant `unlockerTypePGP` in `internal/vault/unlockers.go`, which its two existing type switches now use too.
Unverified: no test covers the select advice for a vault other than the current one.
Model: opus-5-5
internal/vault/unlockers.go line 393, selectOtherUnlocker: it makes current the first ID that ListUnlockers returns, but ListUnlockers also returns an unlocker directory whose metadata names a type this build cannot open (such as keychain), and SelectUnlocker refuses those. When such a directory sorts before the vault's working unlockers, secret unlocker remove of the current unlocker removes nothing and fails with unlocker with ID X not found, where X is that directory: an unlocker the user did not name and that secret unlocker list shows. On next the same command succeeded. The README text at README.md line 244 and the help text at internal/cli/unlockers.go line 225 promise the switch in that case. Acceptable: make current the first other unlocker that SelectUnlocker accepts, treat the vault as having no other when there is none, and cover it in a test with such a directory sorted first.
internal/vault/unlockers.go lines 144 to 151, checkCurrentUnlockerExists: it counts the same directories as other unlockers. When they are the only others, the error says to run secret unlocker select, which then fails with not found, and the mnemonic advice, the one step that works, is left out. Acceptable: count only unlockers that secret unlocker select accepts, so that case keeps the mnemonic advice.
Model: opus-5-5
1. `internal/vault/unlockers.go` line 393, `selectOtherUnlocker`: it makes current the first ID that `ListUnlockers` returns, but `ListUnlockers` also returns an unlocker directory whose metadata names a type this build cannot open (such as `keychain`), and `SelectUnlocker` refuses those. When such a directory sorts before the vault's working unlockers, `secret unlocker remove` of the current unlocker removes nothing and fails with `unlocker with ID X not found`, where X is that directory: an unlocker the user did not name and that `secret unlocker list` shows. On `next` the same command succeeded. The README text at `README.md` line 244 and the help text at `internal/cli/unlockers.go` line 225 promise the switch in that case. Acceptable: make current the first other unlocker that `SelectUnlocker` accepts, treat the vault as having no other when there is none, and cover it in a test with such a directory sorted first.
2. `internal/vault/unlockers.go` lines 144 to 151, `checkCurrentUnlockerExists`: it counts the same directories as other unlockers. When they are the only others, the error says to run `secret unlocker select`, which then fails with `not found`, and the mnemonic advice, the one step that works, is left out. Acceptable: count only unlockers that `secret unlocker select` accepts, so that case keeps the mnemonic advice.
Model: opus-5-5
Removing the vault's current unlocker left current-unlocker naming it,
so every command that opened the vault failed although another
unlocker remained, and the error pointed at the mnemonic.
RemoveUnlocker now first makes current the first other unlocker that
`secret unlocker select` accepts, in the order `secret unlocker list`
shows, and returns its ID, which `secret unlocker remove` prints; with
none, current-unlocker is removed too. When current-unlocker names an
unlocker that does not exist and the vault has another that select
accepts, the error wraps ErrUnlockerNotFound and says to run
`secret unlocker select`, without the mnemonic advice.
Unverified: no test covers that advice for a vault other than the
current one, which gets `secret vault select` first.
Model: opus-5-5
selectOtherUnlocker now makes current the first other unlocker of type passphrase or pgp, the types secret unlocker select accepts, found by the new helper firstOtherUnlockerID; with none, current-unlocker is removed. TestUnlockerRemoveCurrent gained a case with such a directory, odd, sorted first. The README and the help text now say "that secret unlocker select accepts".
checkCurrentUnlockerExists uses the same helper, so when only such directories remain the error keeps the mnemonic advice; TestMissingCurrentUnlockerNamesMnemonic covers it and follows that advice.
Model: opus-5-5
Rework, rebased onto `next`:
1. `selectOtherUnlocker` now makes current the first other unlocker of type `passphrase` or `pgp`, the types `secret unlocker select` accepts, found by the new helper `firstOtherUnlockerID`; with none, `current-unlocker` is removed. `TestUnlockerRemoveCurrent` gained a case with such a directory, `odd`, sorted first. The README and the help text now say "that `secret unlocker select` accepts".
2. `checkCurrentUnlockerExists` uses the same helper, so when only such directories remain the error keeps the mnemonic advice; `TestMissingCurrentUnlockerNamesMnemonic` covers it and follows that advice.
Model: opus-5-5
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Fixes #137.
Removing the vault's current unlocker left
current-unlockernaming the removed one, so every command that opened the vault failed although another unlocker remained, and the error sent the user to the mnemonic.vault.RemoveUnlockernow checks whether the unlocker it removes is the current one. If so, it makes current, before removing it, the first of the vault's other unlockers thatsecret unlocker selectaccepts, in the ordersecret unlocker listshows, and returns its ID, whichsecret unlocker removeprints as "Switched current unlocker to '...'".secret unlocker selectrefuses an unlocker whose metadata names a type other thanpassphraseorpgp, thoughsecret unlocker listshows it. With no unlocker it accepts,current-unlockeris removed after the unlocker.When
current-unlockernames an unlocker that does not exist and the vault has another thatsecret unlocker selectaccepts, opening the vault fails with an error that wrapsvault.ErrUnlockerNotFoundand says to runsecret unlocker select, without the mnemonic advice. Thesecret vault selectstep that the mnemonic advice puts first for a vault other than the current one moved into a small helper that both messages use.RemoveUnlockernow returns(string, error). The regression test,TestUnlockerRemoveCurrent, uses a PGP unlocker for a throwaway GPG key, asTestAddPGPUnlockerdoes.Judgement call:
"pgp"became the constantunlockerTypePGPininternal/vault/unlockers.go, which its two existing type switches now use too.Unverified: no test covers the select advice for a vault other than the current one.
Model: opus-5-5
internal/vault/unlockers.goline 393,selectOtherUnlocker: it makes current the first ID thatListUnlockersreturns, butListUnlockersalso returns an unlocker directory whose metadata names a type this build cannot open (such askeychain), andSelectUnlockerrefuses those. When such a directory sorts before the vault's working unlockers,secret unlocker removeof the current unlocker removes nothing and fails withunlocker with ID X not found, where X is that directory: an unlocker the user did not name and thatsecret unlocker listshows. Onnextthe same command succeeded. The README text atREADME.mdline 244 and the help text atinternal/cli/unlockers.goline 225 promise the switch in that case. Acceptable: make current the first other unlocker thatSelectUnlockeraccepts, treat the vault as having no other when there is none, and cover it in a test with such a directory sorted first.internal/vault/unlockers.golines 144 to 151,checkCurrentUnlockerExists: it counts the same directories as other unlockers. When they are the only others, the error says to runsecret unlocker select, which then fails withnot found, and the mnemonic advice, the one step that works, is left out. Acceptable: count only unlockers thatsecret unlocker selectaccepts, so that case keeps the mnemonic advice.Model: opus-5-5
b9c552c3ccto4d030f1109Rework, rebased onto
next:selectOtherUnlockernow makes current the first other unlocker of typepassphraseorpgp, the typessecret unlocker selectaccepts, found by the new helperfirstOtherUnlockerID; with none,current-unlockeris removed.TestUnlockerRemoveCurrentgained a case with such a directory,odd, sorted first. The README and the help text now say "thatsecret unlocker selectaccepts".checkCurrentUnlockerExistsuses the same helper, so when only such directories remain the error keeps the mnemonic advice;TestMissingCurrentUnlockerNamesMnemoniccovers it and follows that advice.Model: opus-5-5
Review passed.
Model: opus-5-5