Documentation
¶
Index ¶
- Variables
- func AdvisoryXactLock(ctx context.Context, tx pgx.Tx, key string) error
- func NewWorkingRiverClient(pool *pgxpool.Pool, queues map[string]river.QueueConfig, ...) (*river.Client[pgx.Tx], error)
- func OpenDB(dsn string, opts ...Option) (*pgxpool.Pool, error)
- type AuthStore
- func (s *AuthStore) AssignAgent(ctx context.Context, userID string, agentID string) error
- func (s *AuthStore) CreatePolicy(ctx context.Context, p auth.Policy) (auth.Policy, error)
- func (s *AuthStore) CreateUserToken(ctx context.Context, token auth.UserToken) (auth.UserToken, error)
- func (s *AuthStore) DeletePolicy(ctx context.Context, id string) error
- func (s *AuthStore) GetActiveAutoUserToken(ctx context.Context, userID string) (auth.UserToken, error)
- func (s *AuthStore) GetActiveUserTokenByHash(ctx context.Context, tokenHash string) (auth.UserToken, error)
- func (s *AuthStore) GetPolicy(ctx context.Context, id string) (auth.Policy, error)
- func (s *AuthStore) GetUserTokenByHash(ctx context.Context, tokenHash string) (auth.UserToken, error)
- func (s *AuthStore) ListAgentUserIDs(ctx context.Context, agentID string) ([]string, error)
- func (s *AuthStore) ListEnabledPolicies(ctx context.Context) ([]auth.Policy, error)
- func (s *AuthStore) ListPolicies(ctx context.Context) ([]auth.Policy, error)
- func (s *AuthStore) ListUserAgentIDs(ctx context.Context, userID string) ([]string, error)
- func (s *AuthStore) RemoveAgent(ctx context.Context, userID string, agentID string) error
- func (s *AuthStore) RevokeUserToken(ctx context.Context, id string) (int64, error)
- func (s *AuthStore) RotateUserToken(ctx context.Context, id string) (int64, error)
- func (s *AuthStore) UpdatePolicy(ctx context.Context, p auth.Policy) error
- func (s *AuthStore) UpdateUserTokenLastUsed(ctx context.Context, id string) (int64, error)
- type Embedded
- type ExtensionRequirement
- type MigrateReport
- type OIDCStore
- func (s *OIDCStore) AssignAgent(ctx context.Context, userID, agentID string) error
- func (s *OIDCStore) BeginAuthTx(ctx context.Context) (auth.AuthStores, func() error, func(), error)
- func (s *OIDCStore) CountUsers(ctx context.Context) (int64, error)
- func (s *OIDCStore) CreateChannelIdentity(ctx context.Context, i auth.ChannelIdentity) (auth.ChannelIdentity, error)
- func (s *OIDCStore) CreateCredential(ctx context.Context, c auth.Credential) (auth.Credential, error)
- func (s *OIDCStore) CreateLoginIdentity(ctx context.Context, i auth.LoginIdentity) (auth.LoginIdentity, error)
- func (s *OIDCStore) CreateSession(ctx context.Context, sess auth.Session) (auth.Session, error)
- func (s *OIDCStore) CreateUser(ctx context.Context, u auth.User) (auth.User, error)
- func (s *OIDCStore) DeleteChannelIdentity(ctx context.Context, id string) error
- func (s *OIDCStore) DeleteCredential(ctx context.Context, userID string) error
- func (s *OIDCStore) DeleteExpiredSessions(ctx context.Context) error
- func (s *OIDCStore) DeleteSession(ctx context.Context, id string) error
- func (s *OIDCStore) DeleteUser(ctx context.Context, id string) error
- func (s *OIDCStore) DeleteUserSessions(ctx context.Context, userID string) error
- func (s *OIDCStore) GetChannelIdentity(ctx context.Context, id string) (auth.ChannelIdentity, error)
- func (s *OIDCStore) GetChannelIdentityByPlatform(ctx context.Context, platform, externalID string) (auth.ChannelIdentity, error)
- func (s *OIDCStore) GetCredentialByUserID(ctx context.Context, userID string) (auth.Credential, error)
- func (s *OIDCStore) GetLoginIdentityByProvider(ctx context.Context, provider, providerSubject string) (auth.LoginIdentity, error)
- func (s *OIDCStore) GetSession(ctx context.Context, id string) (auth.Session, error)
- func (s *OIDCStore) GetSessionByTokenHash(ctx context.Context, tokenHash string) (auth.Session, error)
- func (s *OIDCStore) GetUser(ctx context.Context, id string) (auth.User, error)
- func (s *OIDCStore) GetUserByEmail(ctx context.Context, email string) (auth.User, error)
- func (s *OIDCStore) GetVaultUser(ctx context.Context, id string) (sqlc.VaultUser, error)
- func (s *OIDCStore) ListActiveUserIDs(ctx context.Context) ([]string, error)
- func (s *OIDCStore) ListAgentUserIDs(ctx context.Context, agentID string) ([]string, error)
- func (s *OIDCStore) ListChannelIdentitiesByUser(ctx context.Context, userID string) ([]auth.ChannelIdentity, error)
- func (s *OIDCStore) ListLoginIdentitiesByUser(ctx context.Context, userID string) ([]auth.LoginIdentity, error)
- func (s *OIDCStore) ListSessionsByUser(ctx context.Context, userID string) ([]auth.Session, error)
- func (s *OIDCStore) ListUserAgentIDs(ctx context.Context, userID string) ([]string, error)
- func (s *OIDCStore) ListUsers(ctx context.Context) ([]auth.User, error)
- func (s *OIDCStore) ListUsersPaged(ctx context.Context, limit, offset int64) ([]auth.User, error)
- func (s *OIDCStore) RemoveAgent(ctx context.Context, userID, agentID string) error
- func (s *OIDCStore) UpdateChannelIdentityExternalID(ctx context.Context, id, externalID string) error
- func (s *OIDCStore) UpdateCredentialHash(ctx context.Context, userID, passwordHash string) error
- func (s *OIDCStore) UpdateLoginIdentity(ctx context.Context, i auth.LoginIdentity) error
- func (s *OIDCStore) UpdateSessionExpiry(ctx context.Context, id string, expiresAt time.Time) error
- func (s *OIDCStore) UpdateUser(ctx context.Context, u auth.User) error
- func (s *OIDCStore) UpdateUserActive(ctx context.Context, userID string, isActive bool) error
- func (s *OIDCStore) UpdateUserAgeKeys(ctx context.Context, userID, publicKey, privateKey string) error
- func (s *OIDCStore) UpdateUserDefaultAgent(ctx context.Context, userID, agentID string) error
- func (s *OIDCStore) UpdateUserNotifyIdentity(ctx context.Context, userID string, identityID *string) error
- func (s *OIDCStore) UpdateUserRole(ctx context.Context, userID string, role string) error
- type Option
Constants ¶
This section is empty.
Variables ¶
var MigrationsFS embed.FS
MigrationsFS holds the goose migration files. Embed the entire directory so it works even when no migrations exist yet.
Functions ¶
func AdvisoryXactLock ¶ added in v0.50.0
AdvisoryXactLock acquires a PostgreSQL transaction-scoped advisory lock keyed by an arbitrary string. Concurrent transactions that request the same key run serially; transactions with different keys are unaffected. Under SQLite this serialization was implicit (single writer); under PostgreSQL writers run in parallel, so call this to guard a read-modify-write that must not interleave for a given entity. The lock releases automatically when tx commits or rolls back — there is no unlock to forget. Prefix keys by domain (e.g. "mem:", "group:") so unrelated entities don't share a slot in the 64-bit lock space.
func NewWorkingRiverClient ¶ added in v0.50.0
func NewWorkingRiverClient(pool *pgxpool.Pool, queues map[string]river.QueueConfig, workers *river.Workers, logger *slog.Logger) (*river.Client[pgx.Tx], error)
NewWorkingRiverClient builds a WORKING (electable) River client that works the given queues with the given workers. River elects a single leader per database to run leader-only maintenance — including the periodic-job enqueuer, which only enqueues the periodic jobs registered on the LEADER client. A second electable client could win leadership and silently starve another client's periodic jobs (e.g. the scheduler's cron).
INVARIANT: exactly ONE electable client per database. That is a process+database scoped property and cannot be enforced here — the test suite legitimately builds many across separate databases in one process. The composition root (cmd/stellad buildSharedRiverClient) is the single production enforcement point: it assembles one client from every subsystem's queues + workers and injects it back via SetRiverClient, so no subsystem constructs its own electable client. A new electable construction site is a bug; route subsystems through the composition root instead. An insert-only client (no queues, never Started) must use river.NewClient directly, not this constructor — which is what the guard below enforces: a working client must actually have queues and workers to work.
func OpenDB ¶
OpenDB opens the PostgreSQL database at dsn, sizes the connection pool, ensures required PostgreSQL extensions and the schema are present, and returns a pool safe for concurrent use. dsn is a libpq/pgx connection string (e.g. "postgres://user:pass@host:5432/db?sslmode=disable").
The server must be PostgreSQL 18 or newer: the schema baseline defaults ids with the uuidv7() built-in, so migrate() fails with "function uuidv7() does not exist" against an older server.
Types ¶
type AuthStore ¶
type AuthStore struct {
*OIDCStore
// contains filtered or unexported fields
}
AuthStore implements auth.AuthStore using sqlc queries backed by PostgreSQL. It embeds OIDCStore to satisfy all new auth store interfaces so that gateway.go can pass a single *AuthStore to all wiring points without knowing about the split between sqlc-backed and raw-SQL-backed stores.
func NewAuthStore ¶
NewAuthStore creates a new AuthStore wrapping the given database connection.
func (*AuthStore) AssignAgent ¶
func (*AuthStore) CreatePolicy ¶
func (*AuthStore) CreateUserToken ¶
func (*AuthStore) DeletePolicy ¶
func (*AuthStore) GetActiveAutoUserToken ¶
func (*AuthStore) GetActiveUserTokenByHash ¶
func (*AuthStore) GetUserTokenByHash ¶
func (*AuthStore) ListAgentUserIDs ¶
func (*AuthStore) ListEnabledPolicies ¶
func (*AuthStore) ListPolicies ¶
func (*AuthStore) ListUserAgentIDs ¶
func (*AuthStore) RemoveAgent ¶
func (*AuthStore) RevokeUserToken ¶
func (*AuthStore) RotateUserToken ¶
func (*AuthStore) UpdatePolicy ¶
type Embedded ¶ added in v0.50.0
type Embedded struct {
// contains filtered or unexported fields
}
Embedded is a managed PostgreSQL server that stellad runs as a child process. It lets the server and its tests run against real PostgreSQL with nothing to install or operate: the server binary is downloaded once and cached under the user home, then started on demand. Start it, open the DSN with OpenDB, and Stop it on shutdown.
func StartEmbedded ¶ added in v0.50.0
StartEmbedded boots a PostgreSQL server on the given TCP port and returns a ready-to-use handle. A port of 0 picks a free ephemeral port — use it for tests so parallel test binaries never collide. dataDir is where the cluster's files live: a stable path persists data across restarts (the server runtime), while an empty string uses a throwaway temp dir that is removed on Stop (tests).
func (*Embedded) DSN ¶ added in v0.50.0
DSN returns the libpq connection string for the server's default "stella" database.
type ExtensionRequirement ¶ added in v0.50.0
type MigrateReport ¶ added in v0.50.0
type MigrateReport struct {
Tables map[string]int // target table → rows copied
Total int // total rows across all tables
Sanitized int // values whose invalid UTF-8 was replaced
Converted int // uuid values salvaged from a legacy-prefixed string
Dropped int // rows skipped: a uuid column held an unsalvageable value
Skipped []string // target tables with no SQLite source (left empty)
}
MigrateReport summarizes a SQLite→PostgreSQL data copy.
func MigrateSQLite ¶ added in v0.50.0
func MigrateSQLite(ctx context.Context, sqlitePath string, pg *pgxpool.Pool, dryRun bool) (*MigrateReport, error)
MigrateSQLite copies every row from the legacy SQLite database at sqlitePath into the already-migrated PostgreSQL schema behind pg. The destination schema is the source of truth for what to copy: each PostgreSQL base table pulls from the same-named SQLite table, so SQLite's FTS5 shadow tables (absent in PostgreSQL) are skipped automatically, as are generated columns (tsvector). A target table with no SQLite source is left empty and listed in Skipped.
dryRun previews the work — each target table's source row count, plus the no-source tables — without touching the destination. A real run does everything in one transaction, so a failure leaves the destination unchanged, and a re-run truncates and reloads to the same state (idempotent), then verifies every copied count actually persisted.
Foreign-key triggers are disabled for the transaction with SET LOCAL session_replication_role (auto-reset at commit/rollback, so nothing leaks back to the pool), which lets tables load in any order without a topological sort. This is a deliberate faithful copy: SQLite does not enforce foreign keys, so any pre-existing orphan row is carried over as-is rather than failing the migration. Disabling the role requires a superuser DSN (the managed embedded cluster runs as one).
type OIDCStore ¶ added in v0.38.0
type OIDCStore struct {
// contains filtered or unexported fields
}
OIDCStore implements auth store interfaces using raw SQL against the OIDC tables (auth_user, auth_identity, auth_session, channel_identity, auth_credential).
func NewOIDCStore ¶ added in v0.38.0
NewOIDCStore creates an OIDCStore backed by the given database connection.
func (*OIDCStore) AssignAgent ¶ added in v0.38.0
func (*OIDCStore) BeginAuthTx ¶ added in v0.38.0
BeginAuthTx starts a database transaction and returns tx-scoped copies of all auth stores. Implements auth.Transactioner so AuthService.ProcessOIDCLogin can run the entire login flow atomically.
func (*OIDCStore) CountUsers ¶ added in v0.38.0
func (*OIDCStore) CreateChannelIdentity ¶ added in v0.38.0
func (s *OIDCStore) CreateChannelIdentity(ctx context.Context, i auth.ChannelIdentity) (auth.ChannelIdentity, error)
func (*OIDCStore) CreateCredential ¶ added in v0.38.0
func (s *OIDCStore) CreateCredential(ctx context.Context, c auth.Credential) (auth.Credential, error)
func (*OIDCStore) CreateLoginIdentity ¶ added in v0.38.0
func (s *OIDCStore) CreateLoginIdentity(ctx context.Context, i auth.LoginIdentity) (auth.LoginIdentity, error)
func (*OIDCStore) CreateSession ¶ added in v0.38.0
func (*OIDCStore) CreateUser ¶ added in v0.38.0
func (*OIDCStore) DeleteChannelIdentity ¶ added in v0.38.0
func (*OIDCStore) DeleteCredential ¶ added in v0.38.0
func (*OIDCStore) DeleteExpiredSessions ¶ added in v0.38.0
func (*OIDCStore) DeleteSession ¶ added in v0.38.0
func (*OIDCStore) DeleteUser ¶ added in v0.38.0
func (*OIDCStore) DeleteUserSessions ¶ added in v0.38.0
func (*OIDCStore) GetChannelIdentity ¶ added in v0.38.0
func (*OIDCStore) GetChannelIdentityByPlatform ¶ added in v0.38.0
func (*OIDCStore) GetCredentialByUserID ¶ added in v0.38.0
func (*OIDCStore) GetLoginIdentityByProvider ¶ added in v0.38.0
func (*OIDCStore) GetSession ¶ added in v0.38.0
func (*OIDCStore) GetSessionByTokenHash ¶ added in v0.38.0
func (*OIDCStore) GetUserByEmail ¶ added in v0.38.0
func (*OIDCStore) GetVaultUser ¶ added in v0.38.0
GetVaultUser returns the age key fields for a user. Satisfies vault.DB.
func (*OIDCStore) ListActiveUserIDs ¶ added in v0.38.0
func (*OIDCStore) ListAgentUserIDs ¶ added in v0.38.0
func (*OIDCStore) ListChannelIdentitiesByUser ¶ added in v0.38.0
func (*OIDCStore) ListLoginIdentitiesByUser ¶ added in v0.38.0
func (*OIDCStore) ListSessionsByUser ¶ added in v0.38.0
func (*OIDCStore) ListUserAgentIDs ¶ added in v0.38.0
func (*OIDCStore) ListUsersPaged ¶ added in v0.38.0
func (*OIDCStore) RemoveAgent ¶ added in v0.38.0
func (*OIDCStore) UpdateChannelIdentityExternalID ¶ added in v0.38.0
func (*OIDCStore) UpdateCredentialHash ¶ added in v0.38.0
func (*OIDCStore) UpdateLoginIdentity ¶ added in v0.38.0
func (*OIDCStore) UpdateSessionExpiry ¶ added in v0.38.0
func (*OIDCStore) UpdateUser ¶ added in v0.38.0
func (*OIDCStore) UpdateUserActive ¶ added in v0.38.0
func (*OIDCStore) UpdateUserAgeKeys ¶ added in v0.38.0
func (*OIDCStore) UpdateUserDefaultAgent ¶ added in v0.38.0
func (*OIDCStore) UpdateUserNotifyIdentity ¶ added in v0.38.0
type Option ¶ added in v0.50.0
Option overrides pool configuration after OpenDB has applied its defaults.
func WithMaxConns ¶ added in v0.50.0
WithMaxConns caps the pool size. Production uses the built-in default; tests pass a small value so many parallel test databases stay well under the embedded server's max_connections.