store

package
v1.7.0 Latest Latest
Warning

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

Go to latest
Published: Sep 18, 2026 License: AGPL-3.0 Imports: 43 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrTargetNotEmpty refuses to write into a database that already holds
	// something (FR-027). Merging would need conflict rules nothing can settle.
	ErrTargetNotEmpty = errors.New("target database is not empty")
	// ErrSourceBehind refuses a source whose schema is not at the head: the
	// copy would carry a shape the target's schema does not have.
	ErrSourceBehind = errors.New("source database is behind the embedded schema")
	// ErrCountMismatch means a table did not arrive whole. The transaction is
	// rolled back, so the target stays empty.
	ErrCountMismatch = errors.New("row counts differ between source and target")
	// ErrCopyRefused is returned when the operator declines at the prompt.
	ErrCopyRefused = errors.New("copy refused")
)

Sentinels the command turns into exit codes.

View Source
var (
	// ErrInvalidDSN: the connection string cannot be parsed or uses an
	// unsupported scheme.
	ErrInvalidDSN = errors.New("invalid database connection string")
	// ErrUnreachable: the database host does not answer.
	ErrUnreachable = errors.New("database unreachable")
	// ErrAuthRefused: the database answered and refused the credentials.
	ErrAuthRefused = errors.New("database credentials refused")
	// ErrUnsupportedVersion: the server runs a version older than the minimum.
	ErrUnsupportedVersion = errors.New("database version unsupported (PostgreSQL 14 or newer required)")
	// ErrSchemaNewer: the schema was written by a newer release of this binary.
	ErrSchemaNewer = errors.New("database schema is newer than this binary")
)

Startup sentinels. Each maps to one of the distinct operator-facing failure families (FR-018): the message the operator reads names the cause, never the connection string.

Functions

func ApplyDefaultSSLMode

func ApplyDefaultSSLMode(raw string) string

ApplyDefaultSSLMode enforces the product's one TLS default (FR-022): when the connection string carries no explicit sslmode and the host is not local, sslmode=require is added. An explicit value, disable included, always wins. An unparseable string is returned unchanged; opening it fails with ErrInvalidDSN anyway.

func DSNDatabase

func DSNDatabase(raw string) string

DSNDatabase returns the database name for the startup log line.

func DSNHost

func DSNHost(raw string) string

DSNHost returns the host (with port when present) for the startup log line.

func EmbeddedHeadVersion

func EmbeddedHeadVersion(d Dialect) (uint, error)

EmbeddedHeadVersion returns the highest migration number embedded for the dialect. It is what FR-017 compares the database's version against.

func IsBusy

func IsBusy(err error) bool

IsBusy reports whether err is a transient contention failure worth retrying: SQLITE_BUSY/SQLITE_LOCKED, a PostgreSQL lock timeout (55P03) or a serialization failure (40001).

func IsForeignKeyViolation

func IsForeignKeyViolation(err error) bool

IsForeignKeyViolation reports whether err is a foreign-key constraint violation, on either engine.

func IsUnavailable

func IsUnavailable(err error) bool

IsUnavailable reports whether err means the storage cannot serve requests right now but may recover on its own: the connection could not be made or was dropped mid-flight, a PostgreSQL resource-exhaustion error (class 53: disk full, too many connections), a shutdown in progress (57P01..57P03, seen during managed-provider failovers), or SQLITE_FULL on the local file.

It is what separates an outage the operator should wait out from a mistake the caller made: the API answers 503 on the former and 500 on the latter.

func IsUniqueViolation

func IsUniqueViolation(err error) bool

IsUniqueViolation reports whether err is a unique or primary-key constraint violation, on either engine.

func Migrate

func Migrate(ctx context.Context, db *DB, logger *slog.Logger) error

Migrate brings db's schema to the embedded head using golang-migrate v4. On SQLite it also runs the historical one-time conversions; PostgreSQL has no such past. A schema written by a newer release is refused (FR-017), on both engines, rather than written into.

func NullableString

func NullableString(s string) interface{}

NullableString returns nil if s is empty, otherwise returns s. Used for nullable TEXT columns in SQLite.

func ParseDSN

func ParseDSN(raw string) (*url.URL, error)

ParseDSN validates a PostgreSQL connection URL. Only the postgres:// and postgresql:// schemes are accepted; anything else wraps ErrInvalidDSN.

func RedactDSN

func RedactDSN(raw string) string

RedactDSN renders a connection string safe for logs and errors: scheme://user@host:port/database, no password, no parameters. Principle VI and FR-021: credentials never reach logs, responses or telemetry.

func StartRetentionCleanupWithOpts

func StartRetentionCleanupWithOpts(ctx context.Context, store *ContainerStore, db *DB, logger *slog.Logger, opts RetentionOpts) <-chan struct{}

StartRetentionCleanupWithOpts starts retention cleanup with all store types. The first pass runs immediately: an instance that restarts every few hours would otherwise never reach its first cleanup. The returned channel is closed once the cleanup has stopped writing, so a caller that needs the database settled can wait for it: cancelling the context only asks the goroutine to stop, it does not mean the pass in flight has landed. Shutdown waits on it before closing the database, and a test waits on it before its temporary directory is removed.

Types

type AcknowledgmentStoreImpl

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

AcknowledgmentStoreImpl implements security.AcknowledgmentStore using SQLite.

func NewAcknowledgmentStore

func NewAcknowledgmentStore(d *DB) *AcknowledgmentStoreImpl

NewAcknowledgmentStore creates a new SQLite-backed acknowledgment store.

func (*AcknowledgmentStoreImpl) DeleteAcknowledgment

func (s *AcknowledgmentStoreImpl) DeleteAcknowledgment(ctx context.Context, id string) error

func (*AcknowledgmentStoreImpl) GetAcknowledgment

func (*AcknowledgmentStoreImpl) InsertAcknowledgment

func (s *AcknowledgmentStoreImpl) InsertAcknowledgment(ctx context.Context, ack *security.RiskAcknowledgment) (string, error)

func (*AcknowledgmentStoreImpl) IsAcknowledged

func (s *AcknowledgmentStoreImpl) IsAcknowledged(ctx context.Context, containerExternalID, findingType, findingKey string) (bool, error)

func (*AcknowledgmentStoreImpl) ListAcknowledgments

func (s *AcknowledgmentStoreImpl) ListAcknowledgments(ctx context.Context, containerExternalID string) ([]*security.RiskAcknowledgment, error)

type AgentStore

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

AgentStore handles persistence for agents and enrollment tokens. The agents table primary key is `id` (the agent-generated UUID); timestamps are stored as epoch-second BIGINTs.

func NewAgentStore

func NewAgentStore(d *DB) *AgentStore

NewAgentStore creates a new AgentStore.

func (*AgentStore) CountByRuntime

func (s *AgentStore) CountByRuntime(ctx context.Context) (docker, swarm, kubernetes int, err error)

CountByRuntime returns active agent counts grouped by detected_runtime.

func (*AgentStore) CountByStatus

func (s *AgentStore) CountByStatus(ctx context.Context) (active, revoked int, err error)

CountByStatus returns agent counts grouped by status.

func (*AgentStore) Delete

func (s *AgentStore) Delete(ctx context.Context, agentID string) error

Delete hard-deletes an agent and all its events via FK ON DELETE CASCADE.

func (*AgentStore) DeleteToken

func (s *AgentStore) DeleteToken(ctx context.Context, tokenID string) error

DeleteToken removes an unconsumed token.

func (*AgentStore) EnrollAtomic

func (s *AgentStore) EnrollAtomic(ctx context.Context, limit int, tokenCleartext string, a *agent.Agent) error

EnrollAtomic enforces the per-edition host cap, consumes the one-time token, and inserts the agent as a single serialized transaction. Because the count, the token consume, and the insert run in one writer-goroutine transaction, no two concurrent enrollments can both pass the cap check and over-fill it. A limit < 0 means unlimited; the local sentinel is never counted. Returns ErrHostLimitReached, ErrTokenNotFound, ErrTokenAlreadyConsumed, or ErrTokenExpired.

func (*AgentStore) GcExpiredTokens

func (s *AgentStore) GcExpiredTokens(ctx context.Context) error

GcExpiredTokens removes unconsumed tokens that expired more than 7 days ago.

func (*AgentStore) Get

func (s *AgentStore) Get(ctx context.Context, agentID string) (*agent.Agent, error)

Get retrieves an agent by ID.

func (*AgentStore) GetByToken

func (s *AgentStore) GetByToken(ctx context.Context, tokenCleartext string) (*agent.EnrollmentToken, error)

GetByToken retrieves a token from its cleartext value, which it hashes to find the row. Nothing it returns can reconstruct the cleartext.

func (*AgentStore) GetTokenByID

func (s *AgentStore) GetTokenByID(ctx context.Context, tokenID string) (*agent.EnrollmentToken, error)

GetTokenByID retrieves a token by its opaque id.

func (*AgentStore) Insert

func (s *AgentStore) Insert(ctx context.Context, a *agent.Agent) error

Insert persists a new agent record.

func (*AgentStore) InsertToken

func (s *AgentStore) InsertToken(ctx context.Context, t *agent.EnrollmentToken) error

InsertToken persists a new enrollment token. Only the hash and the display prefix are written — the caller holds the cleartext and must not pass it here.

func (*AgentStore) List

func (s *AgentStore) List(ctx context.Context, statusFilter string) ([]*agent.Agent, error)

List retrieves agents with an optional status filter ("" or "all" = all). The local sentinel agent is an internal FK anchor, not an enrolled agent, so it is never surfaced in listings.

func (*AgentStore) ListAgentsForEOL added in v1.7.0

func (s *AgentStore) ListAgentsForEOL(ctx context.Context) ([]agent.Agent, error)

ListAgentsForEOL returns every active agent, the local sentinel included: the server's own host has an operating system to follow like any other.

func (*AgentStore) ListTokens

func (s *AgentStore) ListTokens(ctx context.Context, includeExpired, includeConsumed bool) ([]*agent.EnrollmentToken, error)

ListTokens returns all tokens with optional filters.

func (*AgentStore) Revoke

func (s *AgentStore) Revoke(ctx context.Context, agentID, revokedBy string) error

Revoke marks an agent as revoked.

func (*AgentStore) StaleAgents

func (s *AgentStore) StaleAgents(ctx context.Context, threshold time.Duration) ([]string, error)

StaleAgents returns IDs of active agents whose last_seen_at is older than threshold.

func (*AgentStore) UpdateAgentOS added in v1.7.0

func (s *AgentStore) UpdateAgentOS(ctx context.Context, agentID string, os agent.OSIdentity, reportedAt time.Time) (bool, error)

UpdateAgentOS records the operating system identity of an agent's host and reports whether it differs from the one already stored.

func (*AgentStore) UpdateAgentVersion

func (s *AgentStore) UpdateAgentVersion(ctx context.Context, agentID, version string) error

UpdateAgentVersion records the build the agent is currently running. Enrollment only happens once, so this is the only way the stored version stays truthful across agent upgrades.

func (*AgentStore) UpdateLabel

func (s *AgentStore) UpdateLabel(ctx context.Context, agentID, label string) error

UpdateLabel updates the display label for an agent.

func (*AgentStore) UpdateLastSeen

func (s *AgentStore) UpdateLastSeen(ctx context.Context, agentID string, t time.Time) error

UpdateLastSeen updates the last_seen_at timestamp.

type AlertStoreImpl

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

AlertStoreImpl implements alert.AlertStore using SQLite.

func NewAlertStore

func NewAlertStore(d *DB) *AlertStoreImpl

NewAlertStore creates a new SQLite-backed alert store.

func (*AlertStoreImpl) AcknowledgeAlert

func (s *AlertStoreImpl) AcknowledgeAlert(ctx context.Context, id string, by string, at time.Time) error

func (*AlertStoreImpl) DeleteAlertsOlderThan

func (s *AlertStoreImpl) DeleteAlertsOlderThan(ctx context.Context, before time.Time) (int64, error)

func (*AlertStoreImpl) GetActiveAlert

func (s *AlertStoreImpl) GetActiveAlert(ctx context.Context, source, alertType, entityType string, entityID string) (*alert.Alert, error)

func (*AlertStoreImpl) GetAlert

func (s *AlertStoreImpl) GetAlert(ctx context.Context, id string) (*alert.Alert, error)

func (*AlertStoreImpl) InsertAlert

func (s *AlertStoreImpl) InsertAlert(ctx context.Context, a *alert.Alert) (string, error)

func (*AlertStoreImpl) ListActiveAlerts

func (s *AlertStoreImpl) ListActiveAlerts(ctx context.Context) ([]*alert.Alert, error)

func (*AlertStoreImpl) ListAlerts

func (s *AlertStoreImpl) ListAlerts(ctx context.Context, opts alert.ListAlertsOpts) ([]*alert.Alert, error)

func (*AlertStoreImpl) ListUnacknowledgedActiveAlerts

func (s *AlertStoreImpl) ListUnacknowledgedActiveAlerts(ctx context.Context) ([]*alert.Alert, error)

func (*AlertStoreImpl) SetEscalatedAt

func (s *AlertStoreImpl) SetEscalatedAt(ctx context.Context, id string, at time.Time) error

func (*AlertStoreImpl) UpdateAlertOnEscalation

func (s *AlertStoreImpl) UpdateAlertOnEscalation(ctx context.Context, id, severity, message, entityName, details string) error

func (*AlertStoreImpl) UpdateAlertStatus

func (s *AlertStoreImpl) UpdateAlertStatus(ctx context.Context, id string, status string, resolvedAt *time.Time, resolvedByID *string) error

type CertificateStore

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

CertificateStore implements certificate.CertificateStore using SQLite.

func NewCertificateStore

func NewCertificateStore(d *DB) *CertificateStore

NewCertificateStore creates a new SQLite-backed certificate store.

func (*CertificateStore) CountConfigured

func (s *CertificateStore) CountConfigured(ctx context.Context) (int, error)

CountConfigured returns the number of certificate monitors. Operator-created and auto-detected entries are both counted; the table uses hard-delete only, so no soft-delete filter is needed. Used by the telemetry subsystem; see specs/015-shm-telemetry.

func (*CertificateStore) CountStandaloneMonitors

func (s *CertificateStore) CountStandaloneMonitors(ctx context.Context) (int, error)

func (*CertificateStore) CreateMonitor

func (s *CertificateStore) CreateMonitor(ctx context.Context, m *certificate.CertMonitor) (string, error)

CreateMonitor upserts a cert monitor. Its id is derived deterministically from (agent_id, hostname, port, server_name) so the agent and server mint the same id; a repeat report for the same host updates the existing row's mutable settings.

func (*CertificateStore) DeleteCheckResultsBefore

func (s *CertificateStore) DeleteCheckResultsBefore(ctx context.Context, before time.Time, batchSize int) (int64, error)

func (*CertificateStore) DeleteMonitor

func (s *CertificateStore) DeleteMonitor(ctx context.Context, id string) error

DeleteMonitor hard-deletes a certificate monitor. Associated check results and chain entries are removed via ON DELETE CASCADE.

func (*CertificateStore) GetChainEntries

func (s *CertificateStore) GetChainEntries(ctx context.Context, checkResultID string) ([]*certificate.CertChainEntry, error)

func (*CertificateStore) GetLatestCheckResult

func (s *CertificateStore) GetLatestCheckResult(ctx context.Context, monitorID string) (*certificate.CertCheckResult, error)

func (*CertificateStore) GetMonitorByEndpointID

func (s *CertificateStore) GetMonitorByEndpointID(ctx context.Context, endpointID string) (*certificate.CertMonitor, error)

func (*CertificateStore) GetMonitorByHostPort

func (s *CertificateStore) GetMonitorByHostPort(ctx context.Context, hostname string, port int, serverName string) (*certificate.CertMonitor, error)

func (*CertificateStore) GetMonitorByHostPortAgent

func (s *CertificateStore) GetMonitorByHostPortAgent(ctx context.Context, agentID *string, hostname string, port int, serverName string) (*certificate.CertMonitor, error)

GetMonitorByHostPortAgent resolves a monitor scoped to a given agent (or the local server when agentID is nil/empty). Matches the agent-aware identity (agent_id, hostname, port, server_name) so a remote agent's localhost:443 does not collide with the server's own or another agent's.

func (*CertificateStore) GetMonitorByID

func (s *CertificateStore) GetMonitorByID(ctx context.Context, id string) (*certificate.CertMonitor, error)

func (*CertificateStore) InsertChainEntries

func (s *CertificateStore) InsertChainEntries(ctx context.Context, entries []*certificate.CertChainEntry) error

func (*CertificateStore) InsertCheckResult

func (s *CertificateStore) InsertCheckResult(ctx context.Context, result *certificate.CertCheckResult) (string, error)

func (*CertificateStore) ListCheckResults

func (s *CertificateStore) ListCheckResults(ctx context.Context, monitorID string, opts certificate.ListChecksOpts) ([]*certificate.CertCheckResult, int, error)

func (*CertificateStore) ListDueScheduledMonitors

func (s *CertificateStore) ListDueScheduledMonitors(ctx context.Context, now time.Time) ([]*certificate.CertMonitor, error)

func (*CertificateStore) ListMonitors

func (*CertificateStore) ListMonitorsByExternalID

func (s *CertificateStore) ListMonitorsByExternalID(ctx context.Context, agentID, externalID string) ([]*certificate.CertMonitor, error)

func (*CertificateStore) UpdateMonitor

func (s *CertificateStore) UpdateMonitor(ctx context.Context, m *certificate.CertMonitor) error

type ChannelStoreImpl

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

ChannelStoreImpl implements alert.ChannelStore using SQLite.

func NewChannelStore

func NewChannelStore(d *DB) *ChannelStoreImpl

NewChannelStore creates a new SQLite-backed channel store.

func (*ChannelStoreImpl) DeleteChannel

func (s *ChannelStoreImpl) DeleteChannel(ctx context.Context, id string) error

func (*ChannelStoreImpl) GetChannel

func (*ChannelStoreImpl) GetChannelHealth

func (s *ChannelStoreImpl) GetChannelHealth(ctx context.Context, channelID string) (string, error)

func (*ChannelStoreImpl) InsertChannel

func (s *ChannelStoreImpl) InsertChannel(ctx context.Context, ch *alert.NotificationChannel) (string, error)

func (*ChannelStoreImpl) InsertDelivery

func (s *ChannelStoreImpl) InsertDelivery(ctx context.Context, d *alert.NotificationDelivery) (string, error)

func (*ChannelStoreImpl) ListChannels

func (s *ChannelStoreImpl) ListChannels(ctx context.Context) ([]*alert.NotificationChannel, error)

func (*ChannelStoreImpl) ListDeliveriesByAlert

func (s *ChannelStoreImpl) ListDeliveriesByAlert(ctx context.Context, alertID string) ([]*alert.NotificationDelivery, error)

func (*ChannelStoreImpl) UpdateChannel

func (s *ChannelStoreImpl) UpdateChannel(ctx context.Context, ch *alert.NotificationChannel) error

func (*ChannelStoreImpl) UpdateDelivery

func (s *ChannelStoreImpl) UpdateDelivery(ctx context.Context, d *alert.NotificationDelivery) error

type ContainerStore

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

ContainerStore implements container.ContainerStore using SQLite.

func NewContainerStore

func NewContainerStore(d *DB) *ContainerStore

NewContainerStore creates a new SQLite-backed container store.

func (*ContainerStore) ArchiveContainer

func (s *ContainerStore) ArchiveContainer(ctx context.Context, id string, archivedAt time.Time) error

func (*ContainerStore) CountConfigured

func (s *ContainerStore) CountConfigured(ctx context.Context) (int, error)

CountConfigured returns the number of non-archived auto-discovered containers. Used by the telemetry subsystem; see specs/015-shm-telemetry.

func (*ContainerStore) CountRestartsSince

func (s *ContainerStore) CountRestartsSince(ctx context.Context, containerID string, since time.Time) (int, error)

func (*ContainerStore) DeleteArchivedContainersBefore

func (s *ContainerStore) DeleteArchivedContainersBefore(ctx context.Context, before time.Time) (int64, error)

func (*ContainerStore) DeleteContainerByID

func (s *ContainerStore) DeleteContainerByID(ctx context.Context, id string) error

func (*ContainerStore) DeleteTransitionsBefore

func (s *ContainerStore) DeleteTransitionsBefore(ctx context.Context, before time.Time, batchSize int) (int64, error)

func (*ContainerStore) GetContainerByExternalID

func (s *ContainerStore) GetContainerByExternalID(ctx context.Context, agentID, externalID string) (*container.Container, error)

func (*ContainerStore) GetContainerByID

func (s *ContainerStore) GetContainerByID(ctx context.Context, id string) (*container.Container, error)

func (*ContainerStore) GetTransitionsInWindow

func (s *ContainerStore) GetTransitionsInWindow(ctx context.Context, containerID string, from, to time.Time) ([]*container.StateTransition, error)

func (*ContainerStore) InsertContainer

func (s *ContainerStore) InsertContainer(ctx context.Context, c *container.Container) (string, error)

InsertContainer upserts a container. Its id is derived deterministically from (agent_id, external_id) so the agent and server mint the same id; a repeat report updates the existing row.

func (*ContainerStore) InsertTransition

func (s *ContainerStore) InsertTransition(ctx context.Context, t *container.StateTransition) (string, error)

InsertTransition records a state transition.

func (*ContainerStore) ListContainers

func (*ContainerStore) ListTransitionsByContainer

func (s *ContainerStore) ListTransitionsByContainer(ctx context.Context, containerID string, opts container.ListTransitionsOpts) ([]*container.StateTransition, int, error)

func (*ContainerStore) UpdateContainer

func (s *ContainerStore) UpdateContainer(ctx context.Context, c *container.Container) error

type DB

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

DB wraps a SQLite database connection with maintenant configuration.

func Open

func Open(dbPath string, logger *slog.Logger) (*DB, error)

Open creates and configures a SQLite database connection with WAL mode. It is the default and the only storage an agent ever uses; OpenPostgres is its counterpart for an operator-supplied server database.

The PRAGMAs below are the SQLite-specific part. Everything else — the schema (uuid_schema.sql) and the queries — stays in the portable common subset (TEXT/BIGINT/INTEGER ids and timestamps, ON CONFLICT upserts, `?` placeholders, no AUTOINCREMENT), and the few genuine differences go through Dialect.

func OpenPostgres

func OpenPostgres(ctx context.Context, dsn string, logger *slog.Logger) (*DB, error)

OpenPostgres opens the operator-supplied PostgreSQL database. Failures are classified into the distinct startup families (FR-018) and never echo the connection string (FR-021). There is no fallback: a configured but unusable database refuses to start (FR-004).

func (*DB) Close

func (d *DB) Close() error

Close closes the database connection.

func (*DB) Database

func (d *DB) Database() string

Database returns the database name for the startup log line; empty on SQLite.

func (*DB) Dialect

func (d *DB) Dialect() Dialect

Dialect returns the engine this DB was opened with.

func (*DB) Engine

func (d *DB) Engine() string

Engine returns the engine name for logs, health and telemetry.

func (*DB) Host

func (d *DB) Host() string

Host returns the database host for the startup log line; empty on SQLite.

func (*DB) PingContext

func (d *DB) PingContext(ctx context.Context) error

PingContext reports whether the database answers right now.

func (*DB) ReadDB

func (d *DB) ReadDB() *sql.DB

ReadDB returns the underlying sql.DB for read operations.

func (*DB) Reader

func (d *DB) Reader() *Reader

func (*DB) RedactedDSN

func (d *DB) RedactedDSN() string

RedactedDSN exposes the connection target without its credentials, for the startup log line and error messages.

func (*DB) SchemaVersion

func (d *DB) SchemaVersion(ctx context.Context) (uint, error)

SchemaVersion reads the applied schema version, for the startup log line and the health diagnostic. golang-migrate keeps exactly one row.

func (*DB) StartWriter

func (d *DB) StartWriter(ctx context.Context)

StartWriter starts the single-writer goroutine.

func (*DB) Writer

func (d *DB) Writer() *Writer

Writer returns the serialized to write channel.

type DailyUptime

type DailyUptime struct {
	Date          string   `json:"date"`
	UptimePercent *float64 `json:"uptime_percent"`
	IncidentCount int      `json:"incident_count"`
}

DailyUptime represents a single day's uptime aggregation.

type Dialect

type Dialect int

Dialect selects the engine-specific form at the few places where SQLite and PostgreSQL genuinely differ. Every engine variation in this package MUST go through a Dialect method — never an inline engine check in a query file.

The six variation points, and nothing else:

  • placeholder syntax (Rebind)
  • batched deletes (BatchDeleteSQL)
  • opening PRAGMAs (db.go, SQLite path only)
  • error classification (errors.go)
  • write serialization (writer.go: single goroutine on SQLite, pool on PG)
  • UUID generation in SQL for set-based rollups (UUIDExpr)

Dialect-specific findings from running the shared suite on both engines:

  • PostgreSQL requires every non-aggregated SELECT column in GROUP BY.
  • Booleans bound as Go bool map to INTEGER 0/1 columns; bind ints.
  • BLOB columns read back as BYTEA; []byte scans work on both.
const (
	DialectSQLite Dialect = iota
	DialectPostgres
)

func (Dialect) BatchDeleteSQL

func (d Dialect) BatchDeleteSQL(table, pk, where string) string

BatchDeleteSQL returns the engine's form of "delete at most ? rows of table matching where". The where fragment uses `?` placeholders; the batch size is always the statement's last parameter. SQLite deletes by rowid so the subquery is served by the index on the filtered column alone; PostgreSQL has no rowid nor DELETE ... LIMIT, so it goes through the primary key.

func (Dialect) Rebind

func (d Dialect) Rebind(query string) string

Rebind converts `?` placeholders to the engine's native form. On SQLite it is the identity and performs no allocation.

func (Dialect) String

func (d Dialect) String() string

func (Dialect) UUIDExpr

func (d Dialect) UUIDExpr() string

UUIDExpr is a SQL expression minting a well-formed UUID string per row, for set-based INSERT ... SELECT statements that cannot mint ids in Go.

type EndpointStore

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

EndpointStore implements endpoint.EndpointStore using SQLite.

func NewEndpointStore

func NewEndpointStore(d *DB) *EndpointStore

NewEndpointStore creates a new SQLite-backed endpoint store.

func (*EndpointStore) CountConfigured

func (s *EndpointStore) CountConfigured(ctx context.Context) (int, error)

CountConfigured returns the number of operator-configured active endpoints. Soft-deleted (active=0) entries pending retention cleanup are excluded. Used by the telemetry subsystem; see specs/015-shm-telemetry.

func (*EndpointStore) CountStandaloneEndpoints added in v1.5.0

func (s *EndpointStore) CountStandaloneEndpoints(ctx context.Context) (int, error)

func (*EndpointStore) DeactivateEndpoint

func (s *EndpointStore) DeactivateEndpoint(ctx context.Context, id string) error

func (*EndpointStore) DeleteCheckResultsBefore

func (s *EndpointStore) DeleteCheckResultsBefore(ctx context.Context, before time.Time, batchSize int) (int64, error)

func (*EndpointStore) DeleteEndpoint

func (s *EndpointStore) DeleteEndpoint(ctx context.Context, id string) error

DeleteEndpoint permanently removes an endpoint and its check results, whatever its source. The caller decides what may be deleted; see endpoint.Service.Delete.

func (*EndpointStore) DeleteInactiveEndpointsBefore

func (s *EndpointStore) DeleteInactiveEndpointsBefore(ctx context.Context, before time.Time) (int64, error)

func (*EndpointStore) DeleteStandaloneEndpoint

func (s *EndpointStore) DeleteStandaloneEndpoint(ctx context.Context, id string) error

DeleteStandaloneEndpoint permanently removes a standalone endpoint and its check results.

func (*EndpointStore) GetActiveAgentEndpointByTarget

func (s *EndpointStore) GetActiveAgentEndpointByTarget(ctx context.Context, agentID, target string) (*endpoint.Endpoint, error)

GetActiveAgentEndpointByTarget resolves an active endpoint pushed by a remote agent, keyed by (agent_id, target). Used to attach a pushed probe result to the endpoint the server provisioned from that agent's container labels.

func (*EndpointStore) GetCheckResultsInWindow

func (s *EndpointStore) GetCheckResultsInWindow(ctx context.Context, endpointID string, from, to time.Time) (int, int, error)

func (*EndpointStore) GetEndpointByID

func (s *EndpointStore) GetEndpointByID(ctx context.Context, id string) (*endpoint.Endpoint, error)

func (*EndpointStore) GetEndpointByIdentity

func (s *EndpointStore) GetEndpointByIdentity(ctx context.Context, containerName, labelKey string) (*endpoint.Endpoint, error)

func (*EndpointStore) GetSparklineData

func (s *EndpointStore) GetSparklineData(ctx context.Context, limit int) (map[string][]float64, error)

GetSparklineData returns the last N response_time_ms values per active endpoint.

func (*EndpointStore) InsertCheckResult

func (s *EndpointStore) InsertCheckResult(ctx context.Context, result *endpoint.CheckResult) (string, error)

func (*EndpointStore) InsertStandaloneEndpoint

func (s *EndpointStore) InsertStandaloneEndpoint(ctx context.Context, e *endpoint.Endpoint) (string, error)

InsertStandaloneEndpoint creates a manually-defined endpoint (not from container labels). Its identity is (agent_id, empty container_name, label_key=external_id) where the external_id is a freshly minted unique key, so the derived id is stable.

func (*EndpointStore) ListCheckResults

func (s *EndpointStore) ListCheckResults(ctx context.Context, endpointID string, opts endpoint.ListChecksOpts) ([]*endpoint.CheckResult, int, error)

func (*EndpointStore) ListEndpoints

func (s *EndpointStore) ListEndpoints(ctx context.Context, opts endpoint.ListEndpointsOpts) ([]*endpoint.Endpoint, error)

func (*EndpointStore) ListEndpointsByExternalID

func (s *EndpointStore) ListEndpointsByExternalID(ctx context.Context, agentID, externalID string) ([]*endpoint.Endpoint, error)

func (*EndpointStore) UpdateCheckResult

func (s *EndpointStore) UpdateCheckResult(ctx context.Context, id string, status endpoint.EndpointStatus,
	alertState endpoint.AlertState, consecutiveFailures, consecutiveSuccesses int,
	responseTimeMs int64, httpStatus *int, lastError string) error

func (*EndpointStore) UpdateStandaloneEndpoint

func (s *EndpointStore) UpdateStandaloneEndpoint(ctx context.Context, id string, name, target string, endpointType endpoint.EndpointType, configJSON string) error

UpdateStandaloneEndpoint updates a standalone endpoint's mutable fields.

func (*EndpointStore) UpsertEndpoint

func (s *EndpointStore) UpsertEndpoint(ctx context.Context, e *endpoint.Endpoint) (string, error)

UpsertEndpoint upserts a label-discovered endpoint. Its id is derived deterministically from (agent_id, container_name, label_key) so the agent and server mint the same id; a repeat report updates the existing row.

type EscalationStore

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

EscalationStore implements escalation.Store using SQLite.

func NewEscalationStore

func NewEscalationStore(d *DB) *EscalationStore

NewEscalationStore creates a new SQLite-backed escalation store.

func (*EscalationStore) BulkDeactivateAllPolicies

func (s *EscalationStore) BulkDeactivateAllPolicies(ctx context.Context) error

func (*EscalationStore) BulkRestorePoliciesFromDowngrade

func (s *EscalationStore) BulkRestorePoliciesFromDowngrade(ctx context.Context) error

func (*EscalationStore) BulkStopActiveRuns

func (s *EscalationStore) BulkStopActiveRuns(ctx context.Context, stopStatus string, endedAt time.Time) error

func (*EscalationStore) CountActivePolicies

func (s *EscalationStore) CountActivePolicies(ctx context.Context) (int, error)

func (*EscalationStore) DeletePolicy

func (s *EscalationStore) DeletePolicy(ctx context.Context, id string) error

func (*EscalationStore) InsertDelivery

func (s *EscalationStore) InsertDelivery(ctx context.Context, d *escalation.Delivery) (string, error)

InsertDelivery reserves a delivery slot. Returns escalation.ErrDeliveryDuplicate when (run_id, level_index, channel_id) already exists — the caller treats this as "already attempted" (R4 reserve-then-deliver idempotence).

func (*EscalationStore) InsertPolicy

func (s *EscalationStore) InsertPolicy(ctx context.Context, p *escalation.Policy) (string, error)

func (*EscalationStore) InsertRun

func (s *EscalationStore) InsertRun(ctx context.Context, r *escalation.Run) (string, error)

InsertRun persists a new escalation run.

func (*EscalationStore) PauseRunForMaintenance

func (s *EscalationStore) PauseRunForMaintenance(ctx context.Context, runID string, recheckAt time.Time) error

PauseRunForMaintenance moves an active run to paused_by_maintenance and schedules a recheck. Returning to active happens via ResumeRunFromMaintenance.

func (*EscalationStore) PurgeRunsAndDeliveriesOlderThan

func (s *EscalationStore) PurgeRunsAndDeliveriesOlderThan(ctx context.Context, before time.Time) error

PurgeRunsAndDeliveriesOlderThan deletes terminated runs (ended_at < before) in batches of 1000. Cascade delete handles escalation_deliveries automatically.

func (*EscalationStore) ResumeRunFromMaintenance

func (s *EscalationStore) ResumeRunFromMaintenance(ctx context.Context, runID string, nextActionAt time.Time) error

ResumeRunFromMaintenance flips a paused run back to active with an updated due time.

func (*EscalationStore) SelectActiveRunsByAlert

func (s *EscalationStore) SelectActiveRunsByAlert(ctx context.Context, alertID string) ([]*escalation.Run, error)

SelectActiveRunsByAlert returns runs in non-terminal state for a given alert. Used by ack/resolve hooks and OnAlertCreated dedup.

func (*EscalationStore) SelectDueRuns

func (s *EscalationStore) SelectDueRuns(ctx context.Context, now time.Time) ([]*escalation.Run, error)

SelectDueRuns returns runs in status 'active' or 'paused_by_maintenance' whose next_action_at is at or before now. The partial index covers the active case; paused runs fall back to a small-table scan (acceptable: <200 paused runs per spec hypothesis v1).

func (*EscalationStore) SelectOrphanPendingDeliveries

func (s *EscalationStore) SelectOrphanPendingDeliveries(ctx context.Context, before time.Time) ([]*escalation.Delivery, error)

SelectOrphanPendingDeliveries returns deliveries stuck in 'pending' for longer than the runner's orphan timeout. The runner decides whether to retry or abandon.

func (*EscalationStore) SelectPolicies

func (s *EscalationStore) SelectPolicies(ctx context.Context, activeOnly bool) ([]*escalation.Policy, error)

func (*EscalationStore) SelectPolicy

func (s *EscalationStore) SelectPolicy(ctx context.Context, id string) (*escalation.Policy, error)

func (*EscalationStore) SelectRun

func (s *EscalationStore) SelectRun(ctx context.Context, id string) (*escalation.Run, error)

func (*EscalationStore) SelectRunDeliveries

func (s *EscalationStore) SelectRunDeliveries(ctx context.Context, runID string) ([]*escalation.Delivery, error)

func (*EscalationStore) SelectRunsByAlert

func (s *EscalationStore) SelectRunsByAlert(ctx context.Context, alertID string) ([]*escalation.Run, error)

func (*EscalationStore) SelectRunsByPolicy

func (s *EscalationStore) SelectRunsByPolicy(ctx context.Context, policyID string, limit int, cursor string) ([]*escalation.Run, error)

func (*EscalationStore) TerminateRun

func (s *EscalationStore) TerminateRun(ctx context.Context, runID string, status string, endedAt time.Time) error

TerminateRun moves a run to a terminal status (stopped_by_*, exhausted) and stamps ended_at.

func (*EscalationStore) UpdateDelivery

func (s *EscalationStore) UpdateDelivery(ctx context.Context, d *escalation.Delivery) error

UpdateDelivery persists status/error/sent_at after a send attempt completes.

func (*EscalationStore) UpdatePolicy

func (s *EscalationStore) UpdatePolicy(ctx context.Context, p *escalation.Policy) error

func (*EscalationStore) UpdateRunProgress

func (s *EscalationStore) UpdateRunProgress(ctx context.Context, runID string, lastExecutedLevelIndex int, nextActionAt *time.Time, status string) error

UpdateRunProgress advances a run's level cursor and reschedules its next action. Used by the runner after executing a level (R4 reserve-then-deliver).

type HeartbeatStore

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

HeartbeatStore implements heartbeat.HeartbeatStore using SQLite.

func NewHeartbeatStore

func NewHeartbeatStore(d *DB) *HeartbeatStore

NewHeartbeatStore creates a new SQLite-backed heartbeat store.

func (*HeartbeatStore) CountActiveHeartbeats

func (s *HeartbeatStore) CountActiveHeartbeats(ctx context.Context) (int, error)

func (*HeartbeatStore) CountConfigured

func (s *HeartbeatStore) CountConfigured(ctx context.Context) (int, error)

CountConfigured satisfies the telemetry counter interface uniformly across stores. Paused heartbeats keep active=1; active=0 is delete-pending. See specs/015-shm-telemetry.

func (*HeartbeatStore) CreateHeartbeat

func (s *HeartbeatStore) CreateHeartbeat(ctx context.Context, h *heartbeat.Heartbeat) (string, error)

CreateHeartbeat upserts a heartbeat. Its id is the public ping token: the caller supplies it via h.ID, falling back to a fresh UUID when empty.

func (*HeartbeatStore) DeleteExecutionsBefore

func (s *HeartbeatStore) DeleteExecutionsBefore(ctx context.Context, before time.Time, batchSize int) (int64, error)

func (*HeartbeatStore) DeleteHeartbeat

func (s *HeartbeatStore) DeleteHeartbeat(ctx context.Context, id string) error

func (*HeartbeatStore) DeletePingsBefore

func (s *HeartbeatStore) DeletePingsBefore(ctx context.Context, before time.Time, batchSize int) (int64, error)

func (*HeartbeatStore) GetCurrentExecution

func (s *HeartbeatStore) GetCurrentExecution(ctx context.Context, heartbeatID string) (*heartbeat.HeartbeatExecution, error)

GetCurrentExecution returns the latest in-progress execution. Execution ids are time-ordered UUIDv7, so ORDER BY id DESC yields the most recent.

func (*HeartbeatStore) GetHeartbeatByID

func (s *HeartbeatStore) GetHeartbeatByID(ctx context.Context, id string) (*heartbeat.Heartbeat, error)

func (*HeartbeatStore) GetHeartbeatByUUID

func (s *HeartbeatStore) GetHeartbeatByUUID(ctx context.Context, token string) (*heartbeat.Heartbeat, error)

GetHeartbeatByUUID looks up an active heartbeat by its ping token (the id).

func (*HeartbeatStore) InsertExecution

func (s *HeartbeatStore) InsertExecution(ctx context.Context, e *heartbeat.HeartbeatExecution) (string, error)

func (*HeartbeatStore) InsertPing

func (s *HeartbeatStore) InsertPing(ctx context.Context, p *heartbeat.HeartbeatPing) (string, error)

func (*HeartbeatStore) ListExecutions

func (s *HeartbeatStore) ListExecutions(ctx context.Context, heartbeatID string, opts heartbeat.ListExecutionsOpts) ([]*heartbeat.HeartbeatExecution, int, error)

func (*HeartbeatStore) ListHeartbeats

func (*HeartbeatStore) ListOverdueHeartbeats

func (s *HeartbeatStore) ListOverdueHeartbeats(ctx context.Context, now time.Time) ([]*heartbeat.Heartbeat, error)

func (*HeartbeatStore) ListPings

func (s *HeartbeatStore) ListPings(ctx context.Context, heartbeatID string, opts heartbeat.ListPingsOpts) ([]*heartbeat.HeartbeatPing, int, error)

func (*HeartbeatStore) PauseHeartbeat

func (s *HeartbeatStore) PauseHeartbeat(ctx context.Context, id string) error

func (*HeartbeatStore) ResumeHeartbeat

func (s *HeartbeatStore) ResumeHeartbeat(ctx context.Context, id string, nextDeadlineAt time.Time) error

func (*HeartbeatStore) UpdateExecution

func (s *HeartbeatStore) UpdateExecution(ctx context.Context, id string, completedAt *time.Time, durationMs *int64, exitCode *int, outcome heartbeat.ExecutionOutcome, payload *string) error

func (*HeartbeatStore) UpdateHeartbeat

func (s *HeartbeatStore) UpdateHeartbeat(ctx context.Context, id string, input heartbeat.UpdateHeartbeatInput) error

func (*HeartbeatStore) UpdateHeartbeatState

func (s *HeartbeatStore) UpdateHeartbeatState(ctx context.Context, id string,
	status heartbeat.HeartbeatStatus, alertState heartbeat.AlertState,
	lastPingAt *time.Time, nextDeadlineAt *time.Time, currentRunStartedAt *time.Time,
	lastExitCode *int, lastDurationMs *int64,
	consecutiveFailures, consecutiveSuccesses int) error

type IncidentStoreImpl

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

IncidentStoreImpl implements status.IncidentStore using SQLite.

func NewIncidentStore

func NewIncidentStore(d *DB) *IncidentStoreImpl

NewIncidentStore creates a new SQLite-backed incident store.

func (*IncidentStoreImpl) CreateIncident

func (s *IncidentStoreImpl) CreateIncident(ctx context.Context, inc *status.Incident, componentIDs []string, initialMessage string) (string, error)

func (*IncidentStoreImpl) CreateUpdate

func (s *IncidentStoreImpl) CreateUpdate(ctx context.Context, u *status.IncidentUpdate) (string, error)

func (*IncidentStoreImpl) DeleteIncident

func (s *IncidentStoreImpl) DeleteIncident(ctx context.Context, id string) error

func (*IncidentStoreImpl) DeleteIncidentsOlderThan

func (s *IncidentStoreImpl) DeleteIncidentsOlderThan(ctx context.Context, days int) (int64, error)

func (*IncidentStoreImpl) GetActiveIncidentByComponent

func (s *IncidentStoreImpl) GetActiveIncidentByComponent(ctx context.Context, componentID string) (*status.Incident, error)

func (*IncidentStoreImpl) GetIncident

func (s *IncidentStoreImpl) GetIncident(ctx context.Context, id string) (*status.Incident, error)

func (*IncidentStoreImpl) ListActiveIncidents

func (s *IncidentStoreImpl) ListActiveIncidents(ctx context.Context) ([]status.Incident, error)

func (*IncidentStoreImpl) ListIncidents

func (s *IncidentStoreImpl) ListIncidents(ctx context.Context, opts status.ListIncidentsOpts) ([]status.Incident, int, error)

func (*IncidentStoreImpl) ListRecentIncidents

func (s *IncidentStoreImpl) ListRecentIncidents(ctx context.Context, days int) ([]status.Incident, error)

func (*IncidentStoreImpl) ListUpdates

func (s *IncidentStoreImpl) ListUpdates(ctx context.Context, incidentID string) ([]status.IncidentUpdate, error)

func (*IncidentStoreImpl) UpdateIncident

func (s *IncidentStoreImpl) UpdateIncident(ctx context.Context, inc *status.Incident, componentIDs []string) error

type Instance

type Instance struct {
	ID         string
	Hostname   string
	Version    string
	StartedAt  time.Time
	LastSeenAt time.Time
}

Instance is one running server process, registered for visibility only (FR-012). The table informs, it never arbitrates: no lock, no lease, no election (FR-013) — exclusion belongs to the operator's cluster manager.

type InstanceStore

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

InstanceStore records this instance's heartbeat and reports peers seen on the same database.

func NewInstanceStore

func NewInstanceStore(d *DB) *InstanceStore

func (*InstanceStore) Beat

func (s *InstanceStore) Beat(ctx context.Context, id string, now time.Time) error

Beat refreshes this instance's last_seen_at.

func (*InstanceStore) Deregister

func (s *InstanceStore) Deregister(ctx context.Context, id string) error

Deregister removes this instance's row on a clean shutdown, so a restart does not see its own previous run as a peer for the next few minutes. A process that dies without getting here is caught by PurgeStale instead.

It writes through the pool rather than the serialized writer: shutdown runs after the writer's context is cancelled, so submitting there would be dropped. Nothing else writes at that point, so SQLite's single-writer discipline is not at stake.

func (*InstanceStore) Peers

func (s *InstanceStore) Peers(ctx context.Context, selfID string, since time.Time) ([]Instance, error)

Peers returns the other instances seen since the given time, most recent first.

func (*InstanceStore) PurgeStale

func (s *InstanceStore) PurgeStale(ctx context.Context, before time.Time) (int64, error)

PurgeStale removes instances whose heartbeat stopped before the cutoff, so crashed processes do not read as peers forever.

func (*InstanceStore) Register

func (s *InstanceStore) Register(ctx context.Context, in Instance) error

Register inserts this instance's row at startup. The id is ephemeral, minted per process; a stale row with the same id cannot exist.

type KubernetesStore

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

KubernetesStore persists per-agent Kubernetes topology (namespaces, workloads, pods, nodes). Each Replace*ForAgent reconciles the snapshot it is given, upserting present rows and hard-deleting the agent's rows that are gone.

func NewKubernetesStore

func NewKubernetesStore(d *DB) *KubernetesStore

NewKubernetesStore creates a SQLite-backed Kubernetes topology store.

func (*KubernetesStore) GetPod

func (s *KubernetesStore) GetPod(ctx context.Context, agentID, namespace, name string) (*kubernetes.K8sPod, error)

GetPod returns a single pod by namespace and name, or nil if absent.

func (*KubernetesStore) GetWorkload

func (s *KubernetesStore) GetWorkload(ctx context.Context, agentID, workloadID string) (*kubernetes.K8sWorkload, error)

GetWorkload returns a single workload by its natural id, or nil if absent.

func (*KubernetesStore) ListEventsForObject

func (s *KubernetesStore) ListEventsForObject(ctx context.Context, agentID, kind, namespace, name string) ([]kubernetes.K8sEvent, error)

ListEventsForObject returns the agent's events concerning a single object (e.g. a Pod or a Deployment), newest first.

func (*KubernetesStore) ListNamespaces

func (s *KubernetesStore) ListNamespaces(ctx context.Context, agentID string) ([]string, error)

ListNamespaces returns the agent's namespaces sorted by name. agentID empty returns every agent's namespaces (deduplicated).

func (*KubernetesStore) ListNodes

func (s *KubernetesStore) ListNodes(ctx context.Context, agentID string) ([]kubernetes.K8sNode, error)

ListNodes returns the agent's nodes sorted by name.

func (*KubernetesStore) ListPods

func (s *KubernetesStore) ListPods(ctx context.Context, agentID string, namespaces []string, filters kubernetes.PodFilters) ([]kubernetes.K8sPod, error)

ListPods returns the agent's pods, optionally filtered by namespaces and the workload/node/status filters.

func (*KubernetesStore) ListWorkloads

func (s *KubernetesStore) ListWorkloads(ctx context.Context, agentID string, namespaces []string) ([]kubernetes.K8sWorkloadGroup, error)

ListWorkloads returns the agent's workloads grouped by namespace, optionally restricted to the given namespaces.

func (*KubernetesStore) ReplaceEventsForAgent

func (s *KubernetesStore) ReplaceEventsForAgent(ctx context.Context, agentID string, events []kubernetes.K8sEventRef) error

ReplaceEventsForAgent replaces the agent's events wholesale. Events are ephemeral (the agent reports its current event window each snapshot), so the snapshot fully supersedes the stored set: wipe the agent's rows, then insert.

func (*KubernetesStore) ReplaceNamespacesForAgent

func (s *KubernetesStore) ReplaceNamespacesForAgent(ctx context.Context, agentID string, namespaces []string) error

ReplaceNamespacesForAgent replaces the agent's namespace list wholesale. Namespaces carry no mutable fields beyond their key, so the snapshot fully supersedes the stored set: wipe the agent's rows, then insert the new set.

func (*KubernetesStore) ReplaceNodesForAgent

func (s *KubernetesStore) ReplaceNodesForAgent(ctx context.Context, agentID string, nodes []kubernetes.K8sNode) error

ReplaceNodesForAgent reconciles the agent's nodes.

func (*KubernetesStore) ReplacePodsForAgent

func (s *KubernetesStore) ReplacePodsForAgent(ctx context.Context, agentID string, pods []kubernetes.K8sPod) error

ReplacePodsForAgent reconciles the agent's pods.

func (*KubernetesStore) ReplaceWorkloadsForAgent

func (s *KubernetesStore) ReplaceWorkloadsForAgent(ctx context.Context, agentID string, workloads []kubernetes.K8sWorkload) error

ReplaceWorkloadsForAgent reconciles the agent's workloads.

type MCPOAuthStoreImpl

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

MCPOAuthStoreImpl implements oauth.MCPOAuthStore using SQLite.

func NewMCPOAuthStore

func NewMCPOAuthStore(d *DB) *MCPOAuthStoreImpl

NewMCPOAuthStore creates a new SQLite-backed MCP OAuth store.

func (*MCPOAuthStoreImpl) ConsumeCode

func (s *MCPOAuthStoreImpl) ConsumeCode(ctx context.Context, codeHash string) (*oauth.MCPAuthCode, error)

ConsumeCode atomically marks an authorization code used, so that only one caller among concurrent exchanges of the same code can ever succeed.

func (*MCPOAuthStoreImpl) ConsumeRefreshToken added in v1.5.0

func (s *MCPOAuthStoreImpl) ConsumeRefreshToken(ctx context.Context, tokenHash string) (*oauth.MCPOAuthToken, error)

ConsumeRefreshToken atomically revokes a refresh token, so that only one caller among concurrent refreshes of the same token can ever rotate it.

func (*MCPOAuthStoreImpl) DeleteExpired

func (s *MCPOAuthStoreImpl) DeleteExpired(ctx context.Context) (int64, error)

func (*MCPOAuthStoreImpl) GetToken

func (s *MCPOAuthStoreImpl) GetToken(ctx context.Context, tokenHash string) (*oauth.MCPOAuthToken, error)

func (*MCPOAuthStoreImpl) RevokeFamily

func (s *MCPOAuthStoreImpl) RevokeFamily(ctx context.Context, familyID string) error

func (*MCPOAuthStoreImpl) RevokeToken

func (s *MCPOAuthStoreImpl) RevokeToken(ctx context.Context, tokenHash string) error

func (*MCPOAuthStoreImpl) StoreCode

func (s *MCPOAuthStoreImpl) StoreCode(ctx context.Context, code *oauth.MCPAuthCode) error

func (*MCPOAuthStoreImpl) StoreToken

func (s *MCPOAuthStoreImpl) StoreToken(ctx context.Context, token *oauth.MCPOAuthToken) error

type MaintenanceStoreImpl

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

MaintenanceStoreImpl implements status.MaintenanceStore using SQLite.

func NewMaintenanceStore

func NewMaintenanceStore(d *DB) *MaintenanceStoreImpl

NewMaintenanceStore creates a new SQLite-backed maintenance store.

func (*MaintenanceStoreImpl) CreateMaintenance

func (s *MaintenanceStoreImpl) CreateMaintenance(ctx context.Context, mw *status.MaintenanceWindow, componentIDs []string) (string, error)

func (*MaintenanceStoreImpl) DeleteMaintenance

func (s *MaintenanceStoreImpl) DeleteMaintenance(ctx context.Context, id string) error

func (*MaintenanceStoreImpl) GetMaintenance

func (s *MaintenanceStoreImpl) GetMaintenance(ctx context.Context, id string) (*status.MaintenanceWindow, error)

func (*MaintenanceStoreImpl) GetPendingActivation

func (s *MaintenanceStoreImpl) GetPendingActivation(ctx context.Context, now int64) ([]status.MaintenanceWindow, error)

func (*MaintenanceStoreImpl) GetPendingDeactivation

func (s *MaintenanceStoreImpl) GetPendingDeactivation(ctx context.Context, now int64) ([]status.MaintenanceWindow, error)

func (*MaintenanceStoreImpl) IsEntitySuppressed

func (s *MaintenanceStoreImpl) IsEntitySuppressed(
	ctx context.Context, monitorType string, monitorID string, now time.Time,
) (matched bool, windowID string, endsAt time.Time, err error)

IsEntitySuppressed returns true (with the matching window ID and end time) if at least one active maintenance window currently covers the given monitor. Active means starts_at ≤ now < ends_at regardless of the window's `active` flag (which controls Status Page display, not suppressor logic).

func (*MaintenanceStoreImpl) ListMaintenance

func (s *MaintenanceStoreImpl) ListMaintenance(ctx context.Context, statusFilter string, limit int) ([]status.MaintenanceWindow, error)

func (*MaintenanceStoreImpl) SetActive

func (s *MaintenanceStoreImpl) SetActive(ctx context.Context, id string, active bool, incidentID *string) error

func (*MaintenanceStoreImpl) UpdateMaintenance

func (s *MaintenanceStoreImpl) UpdateMaintenance(ctx context.Context, mw *status.MaintenanceWindow, componentIDs []string) error

type PersonalizationStoreImpl

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

func NewPersonalizationStore

func NewPersonalizationStore(d *DB) *PersonalizationStoreImpl

func (*PersonalizationStoreImpl) BumpVersion

func (s *PersonalizationStoreImpl) BumpVersion(ctx context.Context) error

func (*PersonalizationStoreImpl) CreateFAQItem

func (s *PersonalizationStoreImpl) CreateFAQItem(ctx context.Context, question, answerMD, answerHTML string) (status.FAQItem, error)
func (s *PersonalizationStoreImpl) CreateFooterLink(ctx context.Context, label, url string) (status.FooterLink, error)

func (*PersonalizationStoreImpl) DeleteAsset

func (s *PersonalizationStoreImpl) DeleteAsset(ctx context.Context, role status.AssetRole) error

func (*PersonalizationStoreImpl) DeleteFAQItem

func (s *PersonalizationStoreImpl) DeleteFAQItem(ctx context.Context, id string) error
func (s *PersonalizationStoreImpl) DeleteFooterLink(ctx context.Context, id string) error

func (*PersonalizationStoreImpl) GetAsset

func (*PersonalizationStoreImpl) GetSettings

func (*PersonalizationStoreImpl) ListFAQItems

func (s *PersonalizationStoreImpl) ListFAQItems(ctx context.Context) ([]status.FAQItem, error)
func (s *PersonalizationStoreImpl) ListFooterLinks(ctx context.Context) ([]status.FooterLink, error)

func (*PersonalizationStoreImpl) PutAsset

func (*PersonalizationStoreImpl) ReorderFAQItems

func (s *PersonalizationStoreImpl) ReorderFAQItems(ctx context.Context, ids []string) ([]status.FAQItem, error)
func (s *PersonalizationStoreImpl) ReorderFooterLinks(ctx context.Context, ids []string) ([]status.FooterLink, error)

func (*PersonalizationStoreImpl) UpdateFAQItem

func (s *PersonalizationStoreImpl) UpdateFAQItem(ctx context.Context, id string, question, answerMD, answerHTML string) (status.FAQItem, error)
func (s *PersonalizationStoreImpl) UpdateFooterLink(ctx context.Context, id string, label, url string) (status.FooterLink, error)

func (*PersonalizationStoreImpl) UpdateSettings

type Plan

type Plan struct {
	// Carried lists each travelling table with its row count in the source.
	Carried []TableCount
	// LeftBehind lists what stays, grouped, with the reason.
	LeftBehind []leftBehindGroup
	// Consequences are the visible effects of what stays behind.
	Consequences []string
}

Plan is what the copy announces before writing anything.

func (Plan) Total

func (p Plan) Total() int64

Total returns how many rows the copy will move.

type Reader

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

Reader is the read handle stores keep: the same QueryContext / QueryRowContext / ExecContext surface as *sql.DB, with `?` placeholders rebound for the active engine.

func (*Reader) Dialect

func (r *Reader) Dialect() Dialect

Dialect returns the engine this reader rebinds for.

func (*Reader) ExecContext

func (r *Reader) ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)

func (*Reader) QueryContext

func (r *Reader) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)

func (*Reader) QueryRowContext

func (r *Reader) QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row

type Report

type Report struct {
	Plan     Plan
	Copied   []TableCount
	Verified bool
}

Report is what the copy returns once it is done: the same tables, with the counts read back from the target.

func Copy

func Copy(ctx context.Context, src, dst *sql.DB, out io.Writer, confirm func(Plan) bool) (Report, error)

Copy carries an existing SQLite install into an empty PostgreSQL database, in a single transaction. It installs the schema itself rather than letting the migrator do it first: PostgreSQL DDL is transactional, so a failure half-way rolls the schema back with the data and leaves the target actually empty, which is what FR-028 asks for and what makes a retry work.

confirm is called with the plan before anything is written; returning false aborts with ErrCopyRefused. out receives the human-readable announcement.

type ResourceStore

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

ResourceStore implements resource.ResourceStore using SQLite.

func NewResourceStore

func NewResourceStore(d *DB) *ResourceStore

NewResourceStore creates a new SQLite-backed resource store.

func (*ResourceStore) AggregateDailyRollup

func (s *ResourceStore) AggregateDailyRollup(ctx context.Context, bucketStart, bucketEnd time.Time) error

func (*ResourceStore) AggregateHourlyRollup

func (s *ResourceStore) AggregateHourlyRollup(ctx context.Context, bucketStart, bucketEnd time.Time) error

func (*ResourceStore) DeleteDailyBefore

func (s *ResourceStore) DeleteDailyBefore(ctx context.Context, before time.Time, batchSize int) (int64, error)

func (*ResourceStore) DeleteHourlyBefore

func (s *ResourceStore) DeleteHourlyBefore(ctx context.Context, before time.Time, batchSize int) (int64, error)

func (*ResourceStore) DeleteSnapshotsBefore

func (s *ResourceStore) DeleteSnapshotsBefore(ctx context.Context, before time.Time, batchSize int) (int64, error)

func (*ResourceStore) GetAlertConfig

func (s *ResourceStore) GetAlertConfig(ctx context.Context, containerID string) (*resource.ResourceAlertConfig, error)

func (*ResourceStore) GetLatestSnapshot

func (s *ResourceStore) GetLatestSnapshot(ctx context.Context, containerID string) (*resource.ResourceSnapshot, error)

func (*ResourceStore) GetTopConsumersByPeriod

func (s *ResourceStore) GetTopConsumersByPeriod(ctx context.Context, metric string, period string, limit int, agentID *string) ([]resource.TopConsumerRow, error)

GetTopConsumersByPeriod ranks containers by average resource usage over a period. agentID filters by host: nil = all hosts, a pointer to "" = the local server (containers owned by the LocalAgent sentinel), a pointer to an id = that agent.

func (*ResourceStore) InsertDailyRollup

func (s *ResourceStore) InsertDailyRollup(ctx context.Context, r *resource.RollupRow) error

func (*ResourceStore) InsertHourlyRollup

func (s *ResourceStore) InsertHourlyRollup(ctx context.Context, r *resource.RollupRow) error

func (*ResourceStore) InsertSnapshot

func (s *ResourceStore) InsertSnapshot(ctx context.Context, snap *resource.ResourceSnapshot) (string, error)

func (*ResourceStore) ListDailyInRange

func (s *ResourceStore) ListDailyInRange(ctx context.Context, containerID string, from, to time.Time) ([]*resource.ResourceSnapshot, error)

ListDailyInRange returns the daily rollup for a container as snapshots. The 90-day window reads it rather than the hourly rollup, which is kept exactly 90 days: served from there, its oldest buckets would fall away mid-read and two consecutive calls would not cover the same period.

The daily schema carries no block I/O columns, so those two counters are 0 on this window. Adding them would need a migration.

func (*ResourceStore) ListHourlyInRange

func (s *ResourceStore) ListHourlyInRange(ctx context.Context, containerID string, from, to time.Time) ([]*resource.ResourceSnapshot, error)

ListHourlyInRange returns the hourly rollup for a container as snapshots, so the long ranges read pre-aggregated buckets instead of grouping a week of raw rows. Block I/O is 0 for buckets aggregated before it was rolled up.

func (*ResourceStore) ListSnapshots

func (s *ResourceStore) ListSnapshots(ctx context.Context, containerID string, from, to time.Time) ([]*resource.ResourceSnapshot, error)

func (*ResourceStore) ListSnapshotsAggregated

func (s *ResourceStore) ListSnapshotsAggregated(ctx context.Context, containerID string, from, to time.Time, granularity resource.Granularity) ([]*resource.ResourceSnapshot, error)

func (*ResourceStore) UpsertAlertConfig

func (s *ResourceStore) UpsertAlertConfig(ctx context.Context, cfg *resource.ResourceAlertConfig) error

type RetentionConfig

type RetentionConfig struct {
	// Scheduling
	Interval        time.Duration // between two full passes
	CatchUpInterval time.Duration // used instead of Interval while a backlog remains
	BudgetPerTable  time.Duration // caps how long one table may hold the writer
	BatchSize       int           // rows deleted per transaction

	// Windows
	Snapshots         time.Duration
	Hourly            time.Duration
	Daily             time.Duration
	Transitions       time.Duration
	Archived          time.Duration
	CheckResults      time.Duration
	InactiveEndpoints time.Duration
	HeartbeatPings    time.Duration
	HeartbeatExecs    time.Duration
	CertCheckResults  time.Duration
}

RetentionConfig tunes the retention cleanup. A zero value means "use the defaults", so an empty struct reproduces the historical behaviour.

type RetentionOpts

type RetentionOpts struct {
	EndpointStore    *EndpointStore
	HeartbeatStore   *HeartbeatStore
	CertificateStore *CertificateStore
	ResourceStore    *ResourceStore
	Config           RetentionConfig
}

RetentionOpts holds optional stores for retention cleanup.

type SilenceStoreImpl

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

SilenceStoreImpl implements alert.SilenceStore using SQLite.

func NewSilenceStore

func NewSilenceStore(d *DB) *SilenceStoreImpl

NewSilenceStore creates a new SQLite-backed silence store.

func (*SilenceStoreImpl) CancelSilenceRule

func (s *SilenceStoreImpl) CancelSilenceRule(ctx context.Context, id string) error

func (*SilenceStoreImpl) GetActiveSilenceRules

func (s *SilenceStoreImpl) GetActiveSilenceRules(ctx context.Context) ([]*alert.SilenceRule, error)

func (*SilenceStoreImpl) InsertSilenceRule

func (s *SilenceStoreImpl) InsertSilenceRule(ctx context.Context, rule *alert.SilenceRule) (string, error)

func (*SilenceStoreImpl) ListSilenceRules

func (s *SilenceStoreImpl) ListSilenceRules(ctx context.Context, activeOnly bool) ([]*alert.SilenceRule, error)

type StatusComponentStoreImpl

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

StatusComponentStoreImpl implements status.ComponentStore using SQLite.

func NewStatusComponentStore

func NewStatusComponentStore(d *DB) *StatusComponentStoreImpl

NewStatusComponentStore creates a new SQLite-backed component store.

func (*StatusComponentStoreImpl) CountConfigured

func (s *StatusComponentStoreImpl) CountConfigured(ctx context.Context) (int, error)

CountConfigured returns the number of operator-configured status-page components. The table uses hard-delete only, so no soft-delete filter is needed. Used by the telemetry subsystem; see specs/015-shm-telemetry.

func (*StatusComponentStoreImpl) CreateComponent

func (s *StatusComponentStoreImpl) CreateComponent(ctx context.Context, c *status.Component) (string, error)

func (*StatusComponentStoreImpl) DeleteComponent

func (s *StatusComponentStoreImpl) DeleteComponent(ctx context.Context, id string) error

func (*StatusComponentStoreImpl) GetComponent

func (s *StatusComponentStoreImpl) GetComponent(ctx context.Context, id string) (*status.Component, error)

func (*StatusComponentStoreImpl) ListComponents

func (s *StatusComponentStoreImpl) ListComponents(ctx context.Context) ([]status.Component, error)

func (*StatusComponentStoreImpl) ListComponentsByMonitor

func (s *StatusComponentStoreImpl) ListComponentsByMonitor(ctx context.Context, monitorType string, monitorID string) ([]status.Component, error)

func (*StatusComponentStoreImpl) ListVisibleComponents

func (s *StatusComponentStoreImpl) ListVisibleComponents(ctx context.Context) ([]status.Component, error)

func (*StatusComponentStoreImpl) RemoveDanglingMonitorRefs

func (s *StatusComponentStoreImpl) RemoveDanglingMonitorRefs(ctx context.Context, monitorType string, monitorID string) error

func (*StatusComponentStoreImpl) UpdateComponent

func (s *StatusComponentStoreImpl) UpdateComponent(ctx context.Context, c *status.Component) error

type SubscriberStoreImpl

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

SubscriberStoreImpl implements status.SubscriberStore using SQLite.

func NewSubscriberStore

func NewSubscriberStore(d *DB) *SubscriberStoreImpl

NewSubscriberStore creates a new SQLite-backed subscriber store.

func (*SubscriberStoreImpl) CleanExpiredUnconfirmed

func (s *SubscriberStoreImpl) CleanExpiredUnconfirmed(ctx context.Context) (int64, error)

func (*SubscriberStoreImpl) ConfirmSubscriber

func (s *SubscriberStoreImpl) ConfirmSubscriber(ctx context.Context, id string) error

func (*SubscriberStoreImpl) CreateSubscriber

func (s *SubscriberStoreImpl) CreateSubscriber(ctx context.Context, sub *status.StatusSubscriber) (string, error)

func (*SubscriberStoreImpl) DeleteSubscriber

func (s *SubscriberStoreImpl) DeleteSubscriber(ctx context.Context, id string) error

func (*SubscriberStoreImpl) GetSubscriberByToken

func (s *SubscriberStoreImpl) GetSubscriberByToken(ctx context.Context, confirmToken string) (*status.StatusSubscriber, error)

func (*SubscriberStoreImpl) GetSubscriberByUnsubToken

func (s *SubscriberStoreImpl) GetSubscriberByUnsubToken(ctx context.Context, unsubToken string) (*status.StatusSubscriber, error)

func (*SubscriberStoreImpl) GetSubscriberStats

func (s *SubscriberStoreImpl) GetSubscriberStats(ctx context.Context) (*status.SubscriberStats, error)

func (*SubscriberStoreImpl) ListConfirmedSubscribers

func (s *SubscriberStoreImpl) ListConfirmedSubscribers(ctx context.Context) ([]status.StatusSubscriber, error)

func (*SubscriberStoreImpl) ListSubscribers

func (s *SubscriberStoreImpl) ListSubscribers(ctx context.Context) ([]status.StatusSubscriber, error)

type SwarmNodeStore

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

SwarmNodeStore implements swarm node persistence using SQLite.

func NewSwarmNodeStore

func NewSwarmNodeStore(d *DB) *SwarmNodeStore

NewSwarmNodeStore creates a new SQLite-backed swarm node store.

func (*SwarmNodeStore) GetNodeByNodeID

func (s *SwarmNodeStore) GetNodeByNodeID(ctx context.Context, nodeID string) (*swarm.SwarmNode, error)

GetNodeByNodeID returns a single swarm node by its Docker node ID.

func (*SwarmNodeStore) ListNodes

func (s *SwarmNodeStore) ListNodes(ctx context.Context, agentID string) ([]*swarm.SwarmNode, error)

ListNodes returns swarm nodes. When agentID is non-empty only that agent's nodes are returned; otherwise every agent's nodes are returned.

func (*SwarmNodeStore) ReplaceNodesForAgent

func (s *SwarmNodeStore) ReplaceNodesForAgent(ctx context.Context, agentID string, nodes []*swarm.SwarmNode) error

ReplaceNodesForAgent upserts every node in the snapshot and hard-deletes any node previously held for this agent that is no longer present. first_seen_at is preserved across upserts by UpsertNode.

func (*SwarmNodeStore) UpdateNodeStatus

func (s *SwarmNodeStore) UpdateNodeStatus(ctx context.Context, nodeID, status, availability string) error

UpdateNodeStatus updates the status and availability of a swarm node.

func (*SwarmNodeStore) UpdateNodeTaskCount

func (s *SwarmNodeStore) UpdateNodeTaskCount(ctx context.Context, nodeID string, count int) error

UpdateNodeTaskCount updates the task count for a swarm node.

func (*SwarmNodeStore) UpsertNode

func (s *SwarmNodeStore) UpsertNode(ctx context.Context, node *swarm.SwarmNode) error

UpsertNode inserts or updates a swarm node. Its id is derived deterministically from (agent_id, node_id) so the agent and server mint the same id.

type SwarmTopologyStore

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

SwarmTopologyStore persists per-agent swarm services and tasks. Nodes live in SwarmNodeStore. All three are reconciled together by the ingest service: each snapshot upserts the rows it carries and hard-deletes the agent's rows that are absent from it.

func NewSwarmTopologyStore

func NewSwarmTopologyStore(d *DB) *SwarmTopologyStore

NewSwarmTopologyStore creates a SQLite-backed swarm topology store.

func (*SwarmTopologyStore) ListServices

func (s *SwarmTopologyStore) ListServices(ctx context.Context, agentID string) ([]*swarm.SwarmService, error)

ListServices returns swarm services. When agentID is non-empty only that agent's services are returned; otherwise every agent's services are returned.

func (*SwarmTopologyStore) ListTasks

func (s *SwarmTopologyStore) ListTasks(ctx context.Context, agentID, serviceID string) ([]*swarm.SwarmTask, error)

ListTasks returns swarm tasks. agentID and serviceID are optional filters (empty = no filter on that dimension).

func (*SwarmTopologyStore) ReplaceServicesForAgent

func (s *SwarmTopologyStore) ReplaceServicesForAgent(ctx context.Context, agentID string, services []swarm.SwarmService) error

ReplaceServicesForAgent upserts every service in the snapshot and hard-deletes any service previously held for this agent that is no longer present.

func (*SwarmTopologyStore) ReplaceTasksForAgent

func (s *SwarmTopologyStore) ReplaceTasksForAgent(ctx context.Context, agentID string, tasks []swarm.SwarmTask) error

ReplaceTasksForAgent upserts every task in the snapshot and hard-deletes any task previously held for this agent that is no longer present.

type TableCount

type TableCount struct {
	Table  string
	Reason string
	Rows   int64
}

TableCount is one table and how many rows it holds.

type TriggerStoreImpl

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

TriggerStoreImpl implements alert.TriggerStore using SQLite.

func NewTriggerStore

func NewTriggerStore(d *DB) *TriggerStoreImpl

NewTriggerStore creates a new SQLite-backed trigger store.

func (*TriggerStoreImpl) DeleteTrigger

func (s *TriggerStoreImpl) DeleteTrigger(ctx context.Context, id string) error

func (*TriggerStoreImpl) GetTrigger

func (s *TriggerStoreImpl) GetTrigger(ctx context.Context, id string) (*alert.AlertTrigger, error)

func (*TriggerStoreImpl) InsertTrigger

func (s *TriggerStoreImpl) InsertTrigger(ctx context.Context, t *alert.AlertTrigger) (string, error)

func (*TriggerStoreImpl) ListChannelsForTrigger

func (s *TriggerStoreImpl) ListChannelsForTrigger(ctx context.Context, triggerID string) ([]string, error)

func (*TriggerStoreImpl) ListEnabledTriggers

func (s *TriggerStoreImpl) ListEnabledTriggers(ctx context.Context) ([]*alert.AlertTrigger, error)

func (*TriggerStoreImpl) ListTriggers

func (s *TriggerStoreImpl) ListTriggers(ctx context.Context) ([]*alert.AlertTrigger, error)

func (*TriggerStoreImpl) ListTriggersForChannel

func (s *TriggerStoreImpl) ListTriggersForChannel(ctx context.Context, channelID string) ([]*alert.AlertTrigger, error)

func (*TriggerStoreImpl) SetChannels

func (s *TriggerStoreImpl) SetChannels(ctx context.Context, triggerID string, channelIDs []string) error

SetChannels replaces all channel links for a trigger atomically (within the writer's serialization guarantee).

func (*TriggerStoreImpl) UpdateTrigger

func (s *TriggerStoreImpl) UpdateTrigger(ctx context.Context, t *alert.AlertTrigger) error

type Tx

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

Tx wraps *sql.Tx so statements written with `?` placeholders run on either engine. It is what Writer.Tx callbacks receive.

func (*Tx) ExecContext

func (t *Tx) ExecContext(ctx context.Context, query string, args ...interface{}) (sql.Result, error)

func (*Tx) QueryContext

func (t *Tx) QueryContext(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)

func (*Tx) QueryRowContext

func (t *Tx) QueryRowContext(ctx context.Context, query string, args ...interface{}) *sql.Row

func (*Tx) Serialize

func (t *Tx) Serialize(ctx context.Context, table string) error

Serialize makes check-then-write sections of this transaction mutually exclusive across writers of table. On SQLite the single writer goroutine already guarantees it, so this is free; on PostgreSQL concurrent transactions would otherwise all pass the check before any of them writes. SHARE ROW EXCLUSIVE conflicts with itself without blocking readers.

type UpdateStore

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

UpdateStore implements update.UpdateStore using SQLite.

func NewUpdateStore

func NewUpdateStore(d *DB) *UpdateStore

NewUpdateStore creates a new SQLite-backed update store.

func (*UpdateStore) CleanupExpired

func (s *UpdateStore) CleanupExpired(ctx context.Context, olderThan time.Time) (int64, error)

func (*UpdateStore) DeleteCVEEvaluation added in v1.5.0

func (s *UpdateStore) DeleteCVEEvaluation(ctx context.Context, containerID string) error

func (*UpdateStore) DeleteContainerCVEs

func (s *UpdateStore) DeleteContainerCVEs(ctx context.Context, containerID string) error

func (*UpdateStore) DeleteExclusion

func (s *UpdateStore) DeleteExclusion(ctx context.Context, id string) error

func (*UpdateStore) DeleteImageUpdatesByContainer

func (s *UpdateStore) DeleteImageUpdatesByContainer(ctx context.Context, containerID string) error

func (*UpdateStore) DeleteOrphanImageUpdates

func (s *UpdateStore) DeleteOrphanImageUpdates(ctx context.Context) (int64, error)

DeleteOrphanImageUpdates removes the findings listed by ListOrphanImageUpdates.

func (*UpdateStore) DeleteStaleImageUpdates

func (s *UpdateStore) DeleteStaleImageUpdates(ctx context.Context, scanID string, scannedContainerNames []string) (int64, error)

func (*UpdateStore) DeleteVersionPin

func (s *UpdateStore) DeleteVersionPin(ctx context.Context, containerID string) error

func (*UpdateStore) GetCVECacheEntries

func (s *UpdateStore) GetCVECacheEntries(ctx context.Context, ecosystem, packageName, packageVersion string) ([]*update.CVECacheEntry, error)

func (*UpdateStore) GetCVEEvaluation added in v1.5.0

func (s *UpdateStore) GetCVEEvaluation(ctx context.Context, containerID string) (*update.CVEEvaluation, error)

func (*UpdateStore) GetCVESummaryCounts

func (s *UpdateStore) GetCVESummaryCounts(ctx context.Context) (map[string]int, error)

func (*UpdateStore) GetDigestBaseline

func (s *UpdateStore) GetDigestBaseline(ctx context.Context, containerID string) (*update.DigestBaseline, error)

GetDigestBaseline returns the stored digest baseline for a container.

func (*UpdateStore) GetImageUpdate

func (s *UpdateStore) GetImageUpdate(ctx context.Context, id string) (*update.ImageUpdate, error)

func (*UpdateStore) GetImageUpdateByContainer

func (s *UpdateStore) GetImageUpdateByContainer(ctx context.Context, containerID string) (*update.ImageUpdate, error)

func (*UpdateStore) GetLatestScanRecord

func (s *UpdateStore) GetLatestScanRecord(ctx context.Context) (*update.ScanRecord, error)

func (*UpdateStore) GetScanRecord

func (s *UpdateStore) GetScanRecord(ctx context.Context, id string) (*update.ScanRecord, error)

func (*UpdateStore) GetUpdateSummary

func (s *UpdateStore) GetUpdateSummary(ctx context.Context) (*update.UpdateSummary, error)

func (*UpdateStore) GetVersionPin

func (s *UpdateStore) GetVersionPin(ctx context.Context, containerID string) (*update.VersionPin, error)

func (*UpdateStore) InsertCVECacheEntry

func (s *UpdateStore) InsertCVECacheEntry(ctx context.Context, e *update.CVECacheEntry) (string, error)

func (*UpdateStore) InsertExclusion

func (s *UpdateStore) InsertExclusion(ctx context.Context, e *update.UpdateExclusion) (string, error)

func (*UpdateStore) InsertImageUpdate

func (s *UpdateStore) InsertImageUpdate(ctx context.Context, u *update.ImageUpdate) (string, error)

func (*UpdateStore) InsertRiskScoreRecord

func (s *UpdateStore) InsertRiskScoreRecord(ctx context.Context, r *update.RiskScoreRecord) (string, error)

func (*UpdateStore) InsertScanRecord

func (s *UpdateStore) InsertScanRecord(ctx context.Context, r *update.ScanRecord) (string, error)

func (*UpdateStore) InsertVersionPin

func (s *UpdateStore) InsertVersionPin(ctx context.Context, p *update.VersionPin) (string, error)

func (*UpdateStore) IsCVECacheFresh

func (s *UpdateStore) IsCVECacheFresh(ctx context.Context, ecosystem, packageName, packageVersion string) (bool, error)

func (*UpdateStore) ListAllActiveCVEs

func (s *UpdateStore) ListAllActiveCVEs(ctx context.Context, opts update.ListCVEsOpts) ([]*update.ContainerCVE, error)

func (*UpdateStore) ListContainerCVEs

func (s *UpdateStore) ListContainerCVEs(ctx context.Context, containerID string) ([]*update.ContainerCVE, error)

func (*UpdateStore) ListExclusions

func (s *UpdateStore) ListExclusions(ctx context.Context) ([]*update.UpdateExclusion, error)

func (*UpdateStore) ListImageUpdates

func (s *UpdateStore) ListImageUpdates(ctx context.Context, opts update.ListImageUpdatesOpts) ([]*update.ImageUpdate, error)

func (*UpdateStore) ListOrphanImageUpdates

func (s *UpdateStore) ListOrphanImageUpdates(ctx context.Context) ([]update.StaleImageUpdate, error)

ListOrphanImageUpdates returns the findings whose container no runtime reports anymore — archived or deleted. Name-based staleness can never catch those on Swarm, where `docker stack deploy` replaces the task with one under a new id and a new name. The container uid comes along when the archived row is still there, so the recovery event resolves the alert by its real entity id.

func (*UpdateStore) ListRiskScoreHistory

func (s *UpdateStore) ListRiskScoreHistory(ctx context.Context, containerID string, from, to time.Time) ([]*update.RiskScoreRecord, error)

func (*UpdateStore) ListStaleImageUpdates

func (s *UpdateStore) ListStaleImageUpdates(ctx context.Context, scanID string, scannedContainerNames []string) ([]update.StaleImageUpdate, error)

ListStaleImageUpdates returns the containers that had a pending update before this scan but are no longer in the latest results — i.e. containers that were upgraded between scans. The container id is returned alongside the name so the recovery event can resolve the alert by its real entity id.

func (*UpdateStore) ResolveContainerCVE

func (s *UpdateStore) ResolveContainerCVE(ctx context.Context, containerID, cveID string) error

func (*UpdateStore) UpdateImageUpdate

func (s *UpdateStore) UpdateImageUpdate(ctx context.Context, u *update.ImageUpdate) error

func (*UpdateStore) UpdateScanRecord

func (s *UpdateStore) UpdateScanRecord(ctx context.Context, r *update.ScanRecord) error

func (*UpdateStore) UpsertCVEEvaluation added in v1.5.0

func (s *UpdateStore) UpsertCVEEvaluation(ctx context.Context, e *update.CVEEvaluation) error

func (*UpdateStore) UpsertContainerCVE

func (s *UpdateStore) UpsertContainerCVE(ctx context.Context, c *update.ContainerCVE) error

func (*UpdateStore) UpsertDigestBaseline

func (s *UpdateStore) UpsertDigestBaseline(ctx context.Context, b *update.DigestBaseline) error

UpsertDigestBaseline inserts or updates the digest baseline for a container.

type UptimeDailyStore

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

UptimeDailyStore provides daily uptime aggregation queries.

func NewUptimeDailyStore

func NewUptimeDailyStore(d *DB) *UptimeDailyStore

NewUptimeDailyStore creates a new daily uptime store.

func (*UptimeDailyStore) GetContainerDailyUptime

func (s *UptimeDailyStore) GetContainerDailyUptime(ctx context.Context, containerID string, days int) ([]DailyUptime, error)

GetContainerDailyUptime computes a per-day, time-weighted uptime series for a container from its state transitions. Unlike endpoints/heartbeats (discrete checks), container uptime is the running+healthy fraction of each day. Days before the first recorded transition return nil (no data), most recent first.

func (*UptimeDailyStore) GetEndpointDailyUptime

func (s *UptimeDailyStore) GetEndpointDailyUptime(ctx context.Context, endpointID string, days int) ([]DailyUptime, error)

GetEndpointDailyUptime aggregates endpoint check results by UTC day. Returns up to `days` days of data, most recent first. Days with no checks have UptimePercent = nil.

func (*UptimeDailyStore) GetHeartbeatDailyUptime

func (s *UptimeDailyStore) GetHeartbeatDailyUptime(ctx context.Context, heartbeatID string, days int) ([]DailyUptime, error)

GetHeartbeatDailyUptime aggregates heartbeat pings by UTC day. Returns up to `days` days of data, most recent first. Days with no pings have UptimePercent = nil.

type WebhookStoreImpl

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

WebhookStoreImpl implements webhook.WebhookSubscriptionStore using SQLite.

func NewWebhookStore

func NewWebhookStore(d *DB) *WebhookStoreImpl

NewWebhookStore creates a new SQLite-backed webhook subscription store.

func (*WebhookStoreImpl) CountConfigured

func (s *WebhookStoreImpl) CountConfigured(ctx context.Context) (int, error)

CountConfigured returns the number of operator-configured webhook subscriptions. is_active=0 means operator-paused (still counted per spec). Used by the telemetry subsystem; see specs/015-shm-telemetry.

func (*WebhookStoreImpl) Create

func (*WebhookStoreImpl) Delete

func (s *WebhookStoreImpl) Delete(ctx context.Context, id string) error

func (*WebhookStoreImpl) GetByID

func (*WebhookStoreImpl) List

func (*WebhookStoreImpl) ListActive

func (*WebhookStoreImpl) UpdateDeliveryStatus

func (s *WebhookStoreImpl) UpdateDeliveryStatus(ctx context.Context, id string, status string, failureCount int) error

type WriteOp

type WriteOp struct {
	Query string
	Args  []interface{}
	Fn    func(context.Context, *Tx) error
	Done  chan WriteResult
}

type WriteResult

type WriteResult struct {
	RowsAffected int64
	Err          error
}

type Writer

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

Writer serializes writes through a single goroutine on SQLite, working around its single-writer discipline. On PostgreSQL the engine governs concurrency itself, so writes go straight to the pool: funneling them through one goroutine would cap the engine at a single writer for nothing.

func NewWriter

func NewWriter(db *sql.DB, dialect Dialect, logger *slog.Logger) *Writer

func (*Writer) Exec

func (w *Writer) Exec(ctx context.Context, query string, args ...interface{}) (WriteResult, error)

func (*Writer) Start

func (w *Writer) Start(ctx context.Context)

func (*Writer) Tx

func (w *Writer) Tx(ctx context.Context, fn func(context.Context, *Tx) error) error

Directories

Path Synopsis
Package storetest opens migrated test databases for the packages whose suites exercise the store: SQLite by default, PostgreSQL when MAINTENANT_TEST_DATABASE_URL points at an admin role, so the same business assertions run on both engines (SC-002).
Package storetest opens migrated test databases for the packages whose suites exercise the store: SQLite by default, PostgreSQL when MAINTENANT_TEST_DATABASE_URL points at an admin role, so the same business assertions run on both engines (SC-002).

Jump to

Keyboard shortcuts

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