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>
93 lines
2.5 KiB
Go
93 lines
2.5 KiB
Go
package secrets
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
|
|
"github.com/kandev/kandev/internal/testutil"
|
|
)
|
|
|
|
func TestPostgresStoreRoundTrip(t *testing.T) {
|
|
db := testutil.OpenIsolatedPostgres(t, testutil.PostgresDSNFromEnv(t))
|
|
|
|
crypto, err := NewMasterKeyProvider(t.TempDir())
|
|
if err != nil {
|
|
t.Fatalf("master key: %v", err)
|
|
}
|
|
store, cleanup, err := Provide(db, db, crypto)
|
|
if err != nil {
|
|
t.Fatalf("provide store: %v", err)
|
|
}
|
|
t.Cleanup(func() {
|
|
_ = cleanup()
|
|
})
|
|
|
|
ctx := context.Background()
|
|
secret := &SecretWithValue{Secret: Secret{Name: "token"}, Value: "s3cr3t"}
|
|
if err := store.Create(ctx, secret); err != nil {
|
|
t.Fatalf("create secret: %v", err)
|
|
}
|
|
got, err := store.Reveal(ctx, secret.ID)
|
|
if err != nil {
|
|
t.Fatalf("reveal secret: %v", err)
|
|
}
|
|
if got != "s3cr3t" {
|
|
t.Fatalf("revealed value = %q, want %q", got, "s3cr3t")
|
|
}
|
|
|
|
metadata, err := store.Get(ctx, secret.ID)
|
|
if err != nil {
|
|
t.Fatalf("get secret: %v", err)
|
|
}
|
|
if metadata.Name != "token" {
|
|
t.Fatalf("secret name = %q, want %q", metadata.Name, "token")
|
|
}
|
|
|
|
nameOnly := "renamed-token"
|
|
if err := store.Update(ctx, secret.ID, &UpdateSecretRequest{Name: &nameOnly}); err != nil {
|
|
t.Fatalf("update secret name: %v", err)
|
|
}
|
|
metadata, err = store.Get(ctx, secret.ID)
|
|
if err != nil {
|
|
t.Fatalf("get renamed secret: %v", err)
|
|
}
|
|
if metadata.Name != nameOnly {
|
|
t.Fatalf("renamed secret name = %q, want %q", metadata.Name, nameOnly)
|
|
}
|
|
got, err = store.Reveal(ctx, secret.ID)
|
|
if err != nil {
|
|
t.Fatalf("reveal renamed secret: %v", err)
|
|
}
|
|
if got != "s3cr3t" {
|
|
t.Fatalf("renamed secret value = %q, want %q", got, "s3cr3t")
|
|
}
|
|
|
|
newValue := "n3w-s3cr3t"
|
|
valueName := "renamed-token-with-value"
|
|
if err := store.Update(ctx, secret.ID, &UpdateSecretRequest{Name: &valueName, Value: &newValue}); err != nil {
|
|
t.Fatalf("update secret value: %v", err)
|
|
}
|
|
metadata, err = store.Get(ctx, secret.ID)
|
|
if err != nil {
|
|
t.Fatalf("get updated secret: %v", err)
|
|
}
|
|
if metadata.Name != valueName {
|
|
t.Fatalf("updated secret name = %q, want %q", metadata.Name, valueName)
|
|
}
|
|
got, err = store.Reveal(ctx, secret.ID)
|
|
if err != nil {
|
|
t.Fatalf("reveal updated secret: %v", err)
|
|
}
|
|
if got != newValue {
|
|
t.Fatalf("updated secret value = %q, want %q", got, newValue)
|
|
}
|
|
|
|
if err := store.Delete(ctx, secret.ID); err != nil {
|
|
t.Fatalf("delete secret: %v", err)
|
|
}
|
|
if _, err := store.Get(ctx, secret.ID); err == nil || !errors.Is(err, ErrNotFound) {
|
|
t.Fatalf("get deleted secret error = %v, want secrets.ErrNotFound", err)
|
|
}
|
|
}
|