1package secrets
2
3import (
4 "errors"
5 "regexp"
6 "time"
7
8 "github.com/bluesky-social/indigo/atproto/syntax"
9)
10
11type DidSlashRepo string
12
13type 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
22type LockedSecret = Secret[struct{}]
23
24// the secret is present in plaintext, never expose this publicly,
25// only use in the workflow engine
26type UnlockedSecret = Secret[string]
27
28type 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
35var ErrKeyAlreadyPresent = errors.New("key already present")
36var ErrInvalidKeyIdent = errors.New("key is not a valid identifier")
37var ErrKeyNotFound = errors.New("key not found")
38
39// ensure that we are satisfying the interface
40var (
41 _ = []Manager{
42 &SqliteManager{},
43 }
44)
45
46var (
47 // bash identifier syntax
48 keyIdent = regexp.MustCompile(`^[a-zA-Z_][a-zA-Z0-9_]*$`)
49)
50
51func isValidKey(key string) bool {
52 if key == "" {
53 return false
54 }
55 return keyIdent.MatchString(key)
56}
57
58func ValidateKey(key string) error {
59 if !isValidKey(key) {
60 return ErrInvalidKeyIdent
61 }
62 return nil
63}