store

package
v0.19.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 4, 2026 License: MIT Imports: 20 Imported by: 0

Documentation

Overview

Package store provides key-value storage implementations.

Index

Constants

This section is empty.

Variables

View Source
var (
	DBTypeSQLite   = enum.DbTypeSQLite
	DBTypePostgres = enum.DbTypePostgres
)

Database type constants for convenience.

View Source
var ErrConflict = errors.New("version conflict")

ErrConflict is returned when optimistic locking fails due to concurrent modification.

View Source
var ErrDecryptionFailed = errors.New("decryption failed")

ErrDecryptionFailed is returned when decryption fails (wrong key or corrupted data).

View Source
var ErrInvalidZKPayload = errors.New("invalid ZK payload: must be $ZK$ followed by valid base64 of encrypted data")

ErrInvalidZKPayload is returned when a ZK-prefixed value has invalid format.

View Source
var ErrNotFound = errors.New("key not found")

ErrNotFound is returned when a key is not found in the store.

View Source
var ErrSecretsNotConfigured = errors.New("secrets key not configured")

ErrSecretsNotConfigured is returned when trying to access secrets without a key configured.

Functions

func IsSecret added in v0.15.0

func IsSecret(key string) bool

IsSecret checks if a key should be treated as a secret based on its path. A key is a secret if it contains "secrets" as a path segment:

  • secrets/db/password → true (starts with secrets/)
  • app/secrets/db → true (contains /secrets/)
  • app/secrets → true (ends with /secrets)
  • secrets → true (exactly "secrets")
  • my-secrets/foo → false (not a path segment)
  • secretsabc/foo → false (not a path segment)

func NormalizeKey added in v0.9.1

func NormalizeKey(key string) string

NormalizeKey normalizes a key by trimming spaces, leading/trailing slashes, and replacing spaces with underscores.

Types

type AuditEntry added in v0.18.0

type AuditEntry struct {
	ID        int64            `json:"id" db:"id"`
	Timestamp time.Time        `json:"timestamp" db:"timestamp"`
	Action    enum.AuditAction `json:"action" db:"action"`
	Key       string           `json:"key" db:"key"`
	Actor     string           `json:"actor" db:"actor"`
	ActorType enum.ActorType   `json:"actor_type" db:"actor_type"`
	Result    enum.AuditResult `json:"result" db:"result"`
	IP        string           `json:"ip,omitempty" db:"ip"`
	UserAgent string           `json:"user_agent,omitempty" db:"user_agent"`
	ValueSize *int             `json:"value_size,omitempty" db:"value_size"`
	RequestID string           `json:"request_id,omitempty" db:"request_id"`
}

AuditEntry represents a single audit log entry.

type AuditQuery added in v0.18.0

type AuditQuery struct {
	Key       string           // prefix match with * suffix, e.g., "app/*"
	Actor     string           // exact match
	ActorType enum.ActorType   // exact match (zero value = any)
	Action    enum.AuditAction // exact match (zero value = any)
	Result    enum.AuditResult // exact match (zero value = any)
	From      time.Time        // inclusive
	To        time.Time        // inclusive
	Limit     int              // max entries to return
	Offset    int              // skip entries for pagination
}

AuditQuery defines filters for querying audit logs.

type Cached added in v0.8.0

type Cached struct {
	// contains filtered or unexported fields
}

Cached wraps a store Interface with a loading cache and satisfies the Interface itself. Cache is populated on reads via loader function, invalidated on writes.

func NewCached added in v0.8.0

func NewCached(store Interface, maxKeys int) (*Cached, error)

NewCached creates a new cached store wrapper. maxKeys sets the maximum number of entries in the cache.

func (*Cached) Close added in v0.8.0

func (c *Cached) Close() error

Close closes the cache and underlying store.

func (*Cached) Delete added in v0.8.0

func (c *Cached) Delete(ctx context.Context, key string) error

Delete removes a key and invalidates the cache entry.

func (*Cached) Get added in v0.8.0

func (c *Cached) Get(ctx context.Context, key string) ([]byte, error)

Get retrieves the value for a key, using cache with load-through. Secrets are never cached to avoid storing decrypted values in memory.

func (*Cached) GetInfo added in v0.8.2

func (c *Cached) GetInfo(ctx context.Context, key string) (KeyInfo, error)

GetInfo retrieves metadata for a key from the underlying store (not cached).

func (*Cached) GetWithFormat added in v0.8.0

func (c *Cached) GetWithFormat(ctx context.Context, key string) ([]byte, string, error)

GetWithFormat retrieves the value and format for a key, using cache with load-through. Secrets are never cached to avoid storing decrypted values in memory.

func (*Cached) List added in v0.8.0

func (c *Cached) List(ctx context.Context, filter enum.SecretsFilter) ([]KeyInfo, error)

List returns all keys from the underlying store (not cached).

func (*Cached) SecretsEnabled added in v0.15.0

func (c *Cached) SecretsEnabled() bool

SecretsEnabled returns whether secrets encryption is enabled in the underlying store.

func (*Cached) Set added in v0.8.0

func (c *Cached) Set(ctx context.Context, key string, value []byte, format string) (created bool, err error)

Set stores a value and invalidates the cache entry. Returns (true, nil) if a new key was created, (false, nil) if an existing key was updated.

func (*Cached) SetWithVersion added in v0.10.1

func (c *Cached) SetWithVersion(ctx context.Context, key string, value []byte, format string, expectedVersion time.Time) error

SetWithVersion stores a value with version check and invalidates the cache entry on success.

func (*Cached) Stats added in v0.8.0

func (c *Cached) Stats() lcw.CacheStat

Stats returns cache statistics.

type ConflictError added in v0.10.1

type ConflictError struct {
	Info ConflictInfo
}

ConflictError wraps ErrConflict with conflict details for UI display.

func (*ConflictError) Error added in v0.10.1

func (e *ConflictError) Error() string

Error returns a string representation of the conflict.

func (*ConflictError) Unwrap added in v0.10.1

func (e *ConflictError) Unwrap() error

Unwrap returns the underlying ErrConflict sentinel.

type ConflictInfo added in v0.10.1

type ConflictInfo struct {
	CurrentValue     []byte
	CurrentFormat    string
	CurrentVersion   time.Time
	AttemptedVersion time.Time
}

ConflictInfo holds details about a detected version conflict.

type Crypto added in v0.15.0

type Crypto struct {
	// contains filtered or unexported fields
}

Crypto handles encryption and decryption of secret values using NaCl secretbox with Argon2id key derivation.

func NewCrypto added in v0.15.0

func NewCrypto(masterKey []byte) (*Crypto, error)

NewCrypto creates a new Crypto instance with the given master key. Key must be at least 16 bytes.

func (*Crypto) Decrypt added in v0.15.0

func (c *Crypto) Decrypt(encrypted []byte) ([]byte, error)

Decrypt decrypts the value that was encrypted with Encrypt.

func (*Crypto) Encrypt added in v0.15.0

func (c *Crypto) Encrypt(value []byte) ([]byte, error)

Encrypt encrypts the value using NaCl secretbox with Argon2id key derivation. Format: base64(salt || nonce || ciphertext)

type DBType

type DBType = enum.DbType

DBType is an alias for enum.DbType for compatibility.

type Encryptor added in v0.15.0

type Encryptor interface {
	Encrypt(value []byte) ([]byte, error)
	Decrypt(encrypted []byte) ([]byte, error)
}

Encryptor defines the interface for encrypting and decrypting secret values.

type Interface added in v0.8.0

type Interface interface {
	Get(ctx context.Context, key string) ([]byte, error)
	GetWithFormat(ctx context.Context, key string) ([]byte, string, error)
	GetInfo(ctx context.Context, key string) (KeyInfo, error)
	Set(ctx context.Context, key string, value []byte, format string) (created bool, err error)
	SetWithVersion(ctx context.Context, key string, value []byte, format string, expectedVersion time.Time) error
	Delete(ctx context.Context, key string) error
	List(ctx context.Context, filter enum.SecretsFilter) ([]KeyInfo, error)
	SecretsEnabled() bool
	Close() error
}

Interface defines the contract for key-value storage operations. Both Store (concrete DB) and Cached (wrapper) implement this interface.

type KeyInfo

type KeyInfo struct {
	Key         string    `json:"key" db:"key"`
	Size        int       `json:"size" db:"size"`
	Format      string    `json:"format" db:"format"`
	Secret      bool      `json:"secret" db:"-"`
	ZKEncrypted bool      `json:"zk_encrypted" db:"-"`
	CreatedAt   time.Time `json:"created_at" db:"created_at"`
	UpdatedAt   time.Time `json:"updated_at" db:"updated_at"`
}

KeyInfo holds metadata about a stored key.

type Option added in v0.15.0

type Option func(*Store)

Option configures Store behavior.

func WithEncryptor added in v0.15.0

func WithEncryptor(enc Encryptor) Option

WithEncryptor enables secrets encryption with the given encryptor.

type RWLocker

type RWLocker interface {
	RLock()
	RUnlock()
	Lock()
	Unlock()
}

RWLocker is an interface for read-write locking.

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store implements key-value storage using SQLite or PostgreSQL.

func New

func New(dbURL string, opts ...Option) (*Store, error)

New creates a new Store with the given database URL. Automatically detects database type from URL: - postgres:// or postgresql:// -> PostgreSQL - everything else -> SQLite

func (*Store) Close

func (s *Store) Close() error

Close closes the database connection.

func (*Store) CreateSession added in v0.11.0

func (s *Store) CreateSession(ctx context.Context, token, username string, expiresAt time.Time) error

CreateSession stores a new session in the database.

func (*Store) Delete

func (s *Store) Delete(ctx context.Context, key string) error

Delete removes the key from the store. Returns ErrNotFound if the key does not exist.

func (*Store) DeleteAllSessions added in v0.11.0

func (s *Store) DeleteAllSessions(ctx context.Context) error

DeleteAllSessions removes all sessions from the database.

func (*Store) DeleteAuditOlderThan added in v0.18.0

func (s *Store) DeleteAuditOlderThan(ctx context.Context, olderThan time.Time) (int64, error)

DeleteAuditOlderThan removes audit entries older than the given time. Returns the number of deleted entries.

func (*Store) DeleteExpiredSessions added in v0.11.0

func (s *Store) DeleteExpiredSessions(ctx context.Context) (int64, error)

DeleteExpiredSessions removes all expired sessions. Returns the number of sessions deleted.

func (*Store) DeleteSession added in v0.11.0

func (s *Store) DeleteSession(ctx context.Context, token string) error

DeleteSession removes a session by token. Returns nil even if the session doesn't exist (idempotent).

func (*Store) DeleteSessionsByUsername added in v0.12.0

func (s *Store) DeleteSessionsByUsername(ctx context.Context, username string) error

DeleteSessionsByUsername removes all sessions for a specific user. Returns nil even if the user has no sessions (idempotent).

func (*Store) Get

func (s *Store) Get(ctx context.Context, key string) ([]byte, error)

Get retrieves the value for the given key. Returns ErrNotFound if the key does not exist. Returns ErrSecretsNotConfigured if key is a secret path but secrets are not enabled.

func (*Store) GetInfo added in v0.8.2

func (s *Store) GetInfo(ctx context.Context, key string) (KeyInfo, error)

GetInfo retrieves metadata for the given key without loading the value. Returns ErrNotFound if the key does not exist. Returns ErrSecretsNotConfigured if key is a secret path but secrets are not enabled.

func (*Store) GetSession added in v0.11.0

func (s *Store) GetSession(ctx context.Context, token string) (username string, expiresAt time.Time, err error)

GetSession retrieves session data by token. Returns ErrNotFound if the session doesn't exist or is expired.

func (*Store) GetWithFormat added in v0.4.0

func (s *Store) GetWithFormat(ctx context.Context, key string) ([]byte, string, error)

GetWithFormat retrieves the value and format for the given key. Returns ErrNotFound if the key does not exist. Returns ErrSecretsNotConfigured if key is a secret path but secrets are not enabled.

func (*Store) List

func (s *Store) List(ctx context.Context, filter enum.SecretsFilter) ([]KeyInfo, error)

List returns metadata for all keys, with optional filtering by secret flag. SecretsFilterAll returns all keys, SecretsFilterSecretsOnly returns only secrets, SecretsFilterKeysOnly returns only non-secrets.

func (*Store) LogAudit added in v0.18.0

func (s *Store) LogAudit(ctx context.Context, entry AuditEntry) error

LogAudit inserts an audit entry into the audit_log table.

func (*Store) QueryAudit added in v0.18.0

func (s *Store) QueryAudit(ctx context.Context, q AuditQuery) ([]AuditEntry, int, error)

QueryAudit retrieves audit entries matching the given filters. Returns entries ordered by timestamp descending (newest first).

func (*Store) SecretsEnabled added in v0.15.0

func (s *Store) SecretsEnabled() bool

SecretsEnabled returns true if the store is configured for secrets encryption.

func (*Store) Set

func (s *Store) Set(ctx context.Context, key string, value []byte, format string) (created bool, err error)

Set stores the value for the given key with the specified format. Creates a new key or updates an existing one. If format is empty, defaults to "text". Returns ErrSecretsNotConfigured if key is a secret path but secrets are not enabled. Returns (true, nil) if a new key was created, (false, nil) if an existing key was updated.

func (*Store) SetWithVersion added in v0.10.1

func (s *Store) SetWithVersion(ctx context.Context, key string, value []byte, format string, expectedVersion time.Time) error

SetWithVersion stores the value only if the key's updated_at matches expectedVersion. Returns *ConflictError with current state if the key was modified since expectedVersion. If expectedVersion is zero, behaves like regular Set (no version check). Returns ErrSecretsNotConfigured if key is a secret path but secrets are not enabled.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL