bb5a81a396
* refactor(secrets): detect absent secret via ErrNotFound sentinel
Replace the "secret not found:" string-prefix matching with an exported
secrets.ErrNotFound sentinel, matched via errors.Is. The store(s) now
return fmt.Errorf("%w: %s", ErrNotFound, id); the rendered message is
byte-identical so logs are unchanged.
Consumers migrated off the prefix:
- internal/plugins/config.go isSecretNotFound (behind host GetSecret/
DeleteSecret and service.go vault rollback)
- internal/integrations/secretadapter Exists (jira/linear/sentry inherit
the change through the shared adapter)
Adds a non-Postgres-gated secrets test asserting errors.Is(err,
ErrNotFound) plus message-unchanged coverage; updates the affected test
fakes to wrap the sentinel.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* test(secrets): address review — eager t.Cleanup, faithful fake Delete
- sqlite_store_test: register sqlxDB close via t.Cleanup immediately
after creation, before the NewMasterKeyProvider/Provide fatal paths
(per the t.Cleanup-immediately convention).
- secretadapter_test: fakeStore.Delete now returns wrapped
secrets.ErrNotFound for an absent id, mirroring the real store and
the fakeSecretRevealer.Delete fake.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Kandev Agent <agent@kandev.dev>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
38 lines
1.2 KiB
Go
38 lines
1.2 KiB
Go
package secrets
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
)
|
|
|
|
// ErrNotFound is the sentinel returned (wrapped) by store implementations when
|
|
// a secret id is absent. Consumers that must tell "absent entry" apart from a
|
|
// genuine backend fault should match with errors.Is(err, secrets.ErrNotFound)
|
|
// rather than string-matching the error text.
|
|
var ErrNotFound = errors.New("secret not found")
|
|
|
|
// SecretStore abstracts secret storage. Implementations handle
|
|
// encryption/decryption internally.
|
|
type SecretStore interface {
|
|
// Create stores a new secret (encrypts the value).
|
|
Create(ctx context.Context, secret *SecretWithValue) error
|
|
|
|
// Get retrieves secret metadata (without value).
|
|
Get(ctx context.Context, id string) (*Secret, error)
|
|
|
|
// Reveal retrieves the decrypted value of a secret.
|
|
Reveal(ctx context.Context, id string) (string, error)
|
|
|
|
// Update updates a secret's name and/or value.
|
|
Update(ctx context.Context, id string, req *UpdateSecretRequest) error
|
|
|
|
// Delete permanently removes a secret.
|
|
Delete(ctx context.Context, id string) error
|
|
|
|
// List returns all secrets without values.
|
|
List(ctx context.Context) ([]*SecretListItem, error)
|
|
|
|
// Close releases resources.
|
|
Close() error
|
|
}
|