Compare commits

..
1 Commits
Author SHA1 Message Date
sneak a83743383e Give each failure one error value (closes #113)
check / check (push) Failing after 3s
internal/cli's copies of vault.ErrSecretNotFound, ErrVaultNotFound,
ErrVersionNotFound and ErrSecretExists are removed; the commands wrap the
vault errors. Every error of secret.ReadPassphrase wraps
ErrPassphraseNotRead, so its callers no longer add those words.
ResolveGPGKeyFingerprint returns ErrGPGKeyNotFound for a key the keyring
lacks, recognised by gpg's status line. storeInKeychain returns
errNilDataBuffer. bip85's ErrPasswordTooShort and ErrEncodedTooShort go
with their unreachable checks. Tests that matched these errors' text use
errors.Is.

Model: opus-5-5
2026-10-04 21:39:24 +00:00
3 changed files with 11 additions and 25 deletions
+1 -3
View File
@@ -23,9 +23,7 @@ https://git.eeqj.de/sneak/secret/milestone/12
keeps its own copies of `vault.ErrSecretNotFound`, `ErrVaultNotFound`,
`ErrVersionNotFound` and `ErrSecretExists`: `secret mv`, `rm`, `decrypt`,
`vault import`, `vault remove` and `version list`, `promote` and `rm` wrap
the `vault` errors. `errUnsupportedUnlockerType` is removed: `secret
unlocker add` gives `errInvalidUnlockerType` for an unknown type, whichever
check rejects it. Messages are unchanged, except that `secret decrypt`
the `vault` errors. Messages are unchanged, except that `secret decrypt`
of a missing secret says "not found", as `secret get` does, not "does not
exist". Every error of `secret.ReadPassphrase` wraps
`secret.ErrPassphraseNotRead`, which supplies the words "failed to read
+7 -20
View File
@@ -61,29 +61,16 @@ func TestRejectedMoveWithinVaultLeavesStateUnchanged(t *testing.T) {
})
}
missing := []struct {
command string
source, dest string
force bool
want error
// A missing secret, and a missing vault: only an existing vault is used.
for source, want := range map[string]error{
"work:nosuch": vault.ErrSecretNotFound,
"nosuch:x": vault.ErrVaultNotFound,
} {
{
"mv work:nosuch work:y", "work:nosuch", "work:y", false,
vault.ErrSecretNotFound,
},
// Only an existing vault is used.
{
"mv --force nosuch:x nosuch:y", "nosuch:x", "nosuch:y", true,
vault.ErrVaultNotFound,
},
}
for _, tt := range missing {
t.Run(tt.command, func(t *testing.T) {
t.Run("mv --force "+source+" work:y", func(t *testing.T) {
t.Parallel()
requireRejectedAndUnchanged(t, before, tt.want, func(c *cli.Instance) error {
return c.MoveSecret(&cobra.Command{}, tt.source, tt.dest, tt.force)
requireRejectedAndUnchanged(t, before, want, func(c *cli.Instance) error {
return c.MoveSecret(&cobra.Command{}, source, "work:y", true)
})
})
}
+2 -1
View File
@@ -47,6 +47,7 @@ var (
// composes "GPG key <id> is already added as an unlocker".
errGPGKeyAlreadyUnlocker = errors.New(
"is already added as an unlocker")
errUnsupportedUnlockerType = errors.New("unsupported unlocker type")
)
// UnlockerInfo represents unlocker information for display
@@ -438,7 +439,7 @@ func (cli *Instance) UnlockersAdd(unlockerType string, cmd *cobra.Command) error
}
return fmt.Errorf("%w: %s (supported: %s)",
errInvalidUnlockerType, unlockerType, supportedTypes)
errUnsupportedUnlockerType, unlockerType, supportedTypes)
}
}