feat: run TreatVault as a service image
All checks were successful
Build and Push Image / docker-build-and-push (push) Successful in 6m2s

This commit is contained in:
2026-09-17 10:29:36 -04:00
parent 63ee4a99e6
commit 4256b7a50e
7 changed files with 147 additions and 260 deletions

View File

@@ -24,7 +24,10 @@ const (
maxDocumentBytes = 16 * 1024 * 1024
)
var ErrSecretNotFound = errors.New("secret not found")
var (
ErrSecretNotFound = errors.New("secret not found")
ErrAlreadyInitialized = errors.New("encrypted file already exists")
)
type Record struct {
Revision string `json:"revision"`
@@ -49,12 +52,26 @@ type Store struct {
mu sync.Mutex
}
func Open(path, identityPath string) (*Store, error) {
// OpenOrInitialize opens an encrypted file, creating an empty vault when it
// does not exist. A TreatVault service owns this bootstrap path; operators
// never need a separate vault-management executable.
func OpenOrInitialize(path, identityPath string) (*Store, error) {
identity, err := ReadIdentity(identityPath)
if err != nil {
return nil, err
}
store := &Store{path: path, identity: identity, recipient: identity.Recipient()}
store := New(path, identity)
if _, err := os.Stat(path); err == nil {
if _, err := store.Load(); err != nil {
return nil, err
}
return store, nil
} else if !errors.Is(err, os.ErrNotExist) {
return nil, fmt.Errorf("stat encrypted file: %w", err)
}
if err := Initialize(path, identity); err != nil && !errors.Is(err, ErrAlreadyInitialized) {
return nil, err
}
if _, err := store.Load(); err != nil {
return nil, err
}
@@ -77,25 +94,9 @@ func ReadIdentity(path string) (*age.X25519Identity, error) {
return identity, nil
}
func GenerateIdentity(path string) (string, error) {
identity, err := age.GenerateX25519Identity()
if err != nil {
return "", fmt.Errorf("generate age identity: %w", err)
}
if _, err := os.Stat(path); err == nil {
return "", fmt.Errorf("identity file %q already exists", path)
} else if !errors.Is(err, os.ErrNotExist) {
return "", err
}
if err := writeFileAtomic(path, []byte(identity.String()+"\n"), 0o600); err != nil {
return "", fmt.Errorf("write age identity: %w", err)
}
return identity.Recipient().String(), nil
}
func Initialize(path string, identity *age.X25519Identity) error {
if _, err := os.Stat(path); err == nil {
return fmt.Errorf("encrypted file %q already exists", path)
return fmt.Errorf("%w: %q", ErrAlreadyInitialized, path)
} else if !errors.Is(err, os.ErrNotExist) {
return err
}