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
This commit is contained in:
2026-10-04 21:39:24 +00:00
parent 176095e3d1
commit a83743383e
19 changed files with 159 additions and 97 deletions
+6 -9
View File
@@ -35,10 +35,6 @@ var (
errSecretTooLarge = errors.New("secret too large: exceeds 100MB limit")
errSecretFileTooLarge = errors.New(
"secret file too large: exceeds 100MB limit")
errSecretNotFound = errors.New("not found")
errSecretExistsNoForce = errors.New(
"already exists (use --force to overwrite)")
errVaultDoesNotExist = errors.New("does not exist")
errCrossVaultSourceUnqualified = errors.New(
"source must specify vault (e.g., vault:secret) for cross-vault move")
errMoveOntoItself = errors.New("cannot be moved onto itself")
@@ -776,7 +772,7 @@ func (cli *Instance) findSecretToRemove(
if !exists {
return secretToRemove{},
fmt.Errorf("secret '%s' %w", secretName, errSecretNotFound)
fmt.Errorf("secret '%s' %w", secretName, vault.ErrSecretNotFound)
}
// A secret without a versions directory has no versions, and can
@@ -907,7 +903,7 @@ func (cli *Instance) existingVault(name string) (*vault.Vault, error) {
}
if !slices.Contains(vaults, name) {
return nil, fmt.Errorf("vault '%s' %w", name, errVaultDoesNotExist)
return nil, fmt.Errorf("vault '%s' %w", name, vault.ErrVaultNotFound)
}
return vault.NewVault(cli.fs, cli.stateDir, name), nil
@@ -938,7 +934,7 @@ func (cli *Instance) moveSecretWithinVault(
}
if !exists {
return fmt.Errorf("secret '%s' %w", source, errSecretNotFound)
return fmt.Errorf("secret '%s' %w", source, vault.ErrSecretNotFound)
}
destEncoded := strings.ReplaceAll(dest, "/", "%")
@@ -963,7 +959,8 @@ func (cli *Instance) moveSecretWithinVault(
if exists {
if !force {
return fmt.Errorf("secret '%s' %w", dest, errSecretExistsNoForce)
return fmt.Errorf("secret '%s' %w (use --force to overwrite)",
dest, vault.ErrSecretExists)
}
err = secret.RemoveDirAtomic(cli.fs, destDir)
@@ -1028,7 +1025,7 @@ func (cli *Instance) moveSecretCrossVault(
exists, err := afero.DirExists(cli.fs, srcSecretDir)
if err != nil || !exists {
return fmt.Errorf("secret '%s' %w in vault '%s'",
srcSecretName, errSecretNotFound, srcVault.Name)
srcSecretName, vault.ErrSecretNotFound, srcVault.Name)
}
// The source is removed after the copy, so a destination that is the