spindle: introduce secret manager interface #371

merged
opened by oppi.li targeting master from push-vynsusnqpmus
Changed files
+63
spindle
secrets
+63
spindle/secrets/manager.go
··· 1 + package secrets 2 + 3 + import ( 4 + "errors" 5 + "regexp" 6 + "time" 7 + 8 + "github.com/bluesky-social/indigo/atproto/syntax" 9 + ) 10 + 11 + type DidSlashRepo string 12 + 13 + type Secret[T any] struct { 14 + Key string 15 + Value T 16 + Repo DidSlashRepo 17 + CreatedAt time.Time 18 + CreatedBy syntax.DID 19 + } 20 + 21 + // the secret is not present 22 + type LockedSecret = Secret[struct{}] 23 + 24 + // the secret is present in plaintext, never expose this publicly, 25 + // only use in the workflow engine 26 + type UnlockedSecret = Secret[string] 27 + 28 + type Manager interface { 29 + AddSecret(secret UnlockedSecret) error 30 + RemoveSecret(secret Secret[any]) error 31 + GetSecretsLocked(repo DidSlashRepo) ([]LockedSecret, error) 32 + GetSecretsUnlocked(repo DidSlashRepo) ([]UnlockedSecret, error) 33 + } 34 + 35 + var ErrKeyAlreadyPresent = errors.New("key already present") 36 + var ErrInvalidKeyIdent = errors.New("key is not a valid identifier") 37 + var ErrKeyNotFound = errors.New("key not found") 38 + 39 + // ensure that we are satisfying the interface 40 + var ( 41 + _ = []Manager{ 42 + &SqliteManager{}, 43 + } 44 + ) 45 + 46 + var ( 47 + // bash identifier syntax 48 + keyIdent = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_]*$`) 49 + ) 50 + 51 + func isValidKey(key string) bool { 52 + if key == "" { 53 + return false 54 + } 55 + return keyIdent.MatchString(key) 56 + } 57 + 58 + func ValidateKey(key string) error { 59 + if !isValidKey(key) { 60 + return ErrInvalidKeyIdent 61 + } 62 + return nil 63 + }