store

package
v0.19.4 Latest Latest
Warning

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

Go to latest
Published: Apr 18, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrEmailTaken = errors.New("email already taken")

ErrEmailTaken is returned when a user attempts to register with an email already in use.

View Source
var ErrLastAdmin = errors.New("cannot remove the last admin")

ErrLastAdmin is returned when attempting to demote or delete the last admin user.

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

ErrNotFound is returned when a requested resource does not exist.

Functions

func BuildConditionsSnapshot

func BuildConditionsSnapshot(metric string, actualValue, threshold float64) string

BuildConditionsSnapshot creates a JSON snapshot for an alert.

func ConditionsSummary

func ConditionsSummary(raw json.RawMessage) string

ConditionsSummary returns a short human-readable description of a watch's conditions_json. For simple single-condition watches it extracts the metric; for compound conditions it returns a generic summary.

func ConditionsThreshold

func ConditionsThreshold(raw json.RawMessage) float64

ConditionsThreshold extracts the threshold value from a simple threshold condition. Returns 0 for compound or non-threshold conditions.

Types

type AffectedUser

type AffectedUser struct {
	UserID          string         `json:"user_id"`
	OccurrenceCount int            `json:"occurrence_count"`
	FirstSeenAt     time.Time      `json:"first_seen_at"`
	LastSeenAt      time.Time      `json:"last_seen_at"`
	LastContext     map[string]any `json:"last_context,omitempty"`
}

AffectedUser represents a user affected by an error.

type AgentNote

type AgentNote struct {
	bun.BaseModel `bun:"table:agent_notes" json:"-"`
	ID            int64     `bun:"id,pk,autoincrement" json:"id"`
	EntityType    string    `bun:"entity_type" json:"entity_type"` // "query", "endpoint", "service", "healthcheck", "error"
	EntityID      string    `bun:"entity_id" json:"entity_id"`     // fingerprint, URL, query hash, etc.
	Note          string    `bun:"note" json:"note"`
	CreatedAt     time.Time `bun:"created_at" json:"created_at"`
	UpdatedAt     time.Time `bun:"updated_at" json:"updated_at"`
}

AgentNote represents a persistent note attached to an entity by the AI agent.

type AgentNoteStore

type AgentNoteStore interface {
	Upsert(ctx context.Context, entityType, entityID, note string) (*AgentNote, error)
	Get(ctx context.Context, entityType, entityID string) (*AgentNote, error)
	List(ctx context.Context, entityType string) ([]AgentNote, error)
	Delete(ctx context.Context, entityType, entityID string) error
	Prune(ctx context.Context, olderThan time.Duration) (int64, error)
}

AgentNoteStore manages persistent notes for the AI agent.

type AnalyticsParams

type AnalyticsParams struct {
	Service string    `json:"service,omitempty"`
	Since   time.Time `json:"since"`
	Until   time.Time `json:"until"`
}

AnalyticsParams defines common filters for analytics queries.

type AnalyticsStore

type AnalyticsStore interface {
	// Aggregation (background job)
	AggregateEndpointStats(ctx context.Context, period string, since time.Time) error
	UpdateTrafficHeatmap(ctx context.Context, since time.Time) error

	// Query
	TopEndpoints(ctx context.Context, params TopEndpointParams) ([]EndpointStat, error)
	TrafficSummary(ctx context.Context, params AnalyticsParams) (*TrafficSummary, error)
	TrafficHeatmap(ctx context.Context, service string) ([]HeatmapCell, error)

	// Maintenance
	Prune(ctx context.Context, olderThan time.Duration) (int64, error)
}

AnalyticsStore manages web analytics data: endpoint stats, traffic heatmaps.

type AuditEntry

type AuditEntry struct {
	bun.BaseModel `bun:"table:audit_log" json:"-"`
	ID            int64     `bun:"id,pk,autoincrement" json:"id"`
	UserID        string    `bun:"user_id" json:"user_id"`
	UserEmail     string    `bun:"user_email" json:"user_email"`
	Action        string    `bun:"action" json:"action"`
	TargetType    string    `bun:"target_type" json:"target_type,omitempty"`
	TargetID      string    `bun:"target_id" json:"target_id,omitempty"`
	Details       string    `bun:"details" json:"details,omitempty"`
	IPAddress     string    `bun:"ip_address" json:"ip_address,omitempty"`
	Environment   string    `bun:"environment" json:"environment,omitempty"`
	CreatedAt     time.Time `bun:"created_at" json:"created_at"`
}

AuditEntry represents a single audit log entry.

type AuditStore

type AuditStore interface {
	Log(ctx context.Context, params LogAuditParams) error
	Recent(ctx context.Context, limit int) ([]AuditEntry, error)
	Prune(ctx context.Context, olderThan time.Duration) (int64, error)
}

AuditStore tracks admin actions for security audit trail.

type BatchRecord

type BatchRecord struct {
	BatchID    string
	LogCount   int
	ReceivedAt time.Time
}

BatchRecord tracks a processed batch for deduplication.

type CodeEntity

type CodeEntity struct {
	bun.BaseModel       `bun:"table:code_entities" json:"-"`
	ID                  int64          `bun:"id,pk,autoincrement" json:"id"`
	EntityType          CodeEntityType `bun:"entity_type" json:"entity_type"`
	EntityName          string         `bun:"entity_name" json:"entity_name"`
	Service             string         `bun:"service" json:"service"`
	RiskScore           float64        `bun:"risk_score" json:"risk_score"`
	ErrorCount          int            `bun:"error_count" json:"error_count"`
	InvestigationCount  int            `bun:"investigation_count" json:"investigation_count"`
	AvgDurationMs       *float64       `bun:"avg_duration_ms" json:"avg_duration_ms,omitempty"`
	LastErrorAt         *time.Time     `bun:"last_error_at" json:"last_error_at,omitempty"`
	LastInvestigationAt *time.Time     `bun:"last_investigation_at" json:"last_investigation_at,omitempty"`
	Metadata            map[string]any `bun:"metadata_json" json:"metadata,omitempty"`
	CreatedAt           time.Time      `bun:"created_at" json:"created_at"`
	UpdatedAt           time.Time      `bun:"updated_at" json:"updated_at"`
}

CodeEntity represents a tracked source code path with risk scoring.

type CodeEntityStore

type CodeEntityStore interface {
	Upsert(ctx context.Context, params UpsertCodeEntityParams) (*CodeEntity, error)
	GetByName(ctx context.Context, entityType CodeEntityType, entityName, service string) (*CodeEntity, error)
	TopByRisk(ctx context.Context, service string, limit int) ([]CodeEntity, error)
	BatchGetRisk(ctx context.Context, entityType CodeEntityType, names []string, service string) ([]CodeEntity, error)
	IncrementError(ctx context.Context, entityType CodeEntityType, entityName, service string) error
	IncrementInvestigation(ctx context.Context, entityType CodeEntityType, entityName, service string) error
	BatchRecomputeRisk(ctx context.Context) error
	Prune(ctx context.Context, olderThan time.Duration) (int64, error)
}

CodeEntityStore manages code entity risk tracking (Stage 5).

type CodeEntityType

type CodeEntityType string

CodeEntityType identifies the kind of source code entity.

const (
	CodeEntityFile       CodeEntityType = "file"
	CodeEntityController CodeEntityType = "controller"
	CodeEntityEndpoint   CodeEntityType = "endpoint"
)

type ConnectorStatus

type ConnectorStatus string
const (
	StatusConnected    ConnectorStatus = "connected"
	StatusDisconnected ConnectorStatus = "disconnected"
	StatusError        ConnectorStatus = "error"
)

type ConnectorType

type ConnectorType string
const (
	ConnectorLogs          ConnectorType = "logs"
	ConnectorDatabase      ConnectorType = "database"
	ConnectorMySQL         ConnectorType = "mysql"
	ConnectorRedis         ConnectorType = "redis"
	ConnectorTurso         ConnectorType = "turso"
	ConnectorMonitoring    ConnectorType = "monitoring"
	ConnectorServerMetrics ConnectorType = "server_metrics"
)

type CreateDataSourceParams

type CreateDataSourceParams struct {
	Type        ConnectorType  `json:"type"`
	Name        string         `json:"name"`
	Config      map[string]any `json:"config"`
	Environment string         `json:"environment,omitempty"`
}

type CreateHealthCheckParams

type CreateHealthCheckParams struct {
	Name           string `json:"name"`
	URL            string `json:"url"`
	Method         string `json:"method,omitempty"`
	IntervalSecs   int    `json:"interval_secs,omitempty"`
	TimeoutSecs    int    `json:"timeout_secs,omitempty"`
	ExpectedStatus int    `json:"expected_status,omitempty"`
	ExpectedBody   string `json:"expected_body,omitempty"`
	Retries        int    `json:"retries,omitempty"`
	Environment    string `json:"environment,omitempty"`
}

CreateHealthCheckParams defines the input for creating a health check.

type CreateUserParams

type CreateUserParams struct {
	Email               string   `json:"email"`
	PasswordHash        string   `json:"-"`
	DisplayName         string   `json:"display_name"`
	Role                UserRole `json:"role"`
	MCPToken            *string  `json:"-"`
	AllowedEnvironments []string `json:"allowed_environments,omitempty"`
}

CreateUserParams defines the input for creating a user.

type CreateWatchAlertParams

type CreateWatchAlertParams struct {
	WatchID            string               `json:"watch_id"`
	RunID              string               `json:"run_id,omitempty"`
	Urgency            WatchUrgency         `json:"urgency"`
	Summary            string               `json:"summary"`
	ConditionsSnapshot string               `json:"conditions_snapshot"`
	Environment        string               `json:"environment,omitempty"`
	Evidence           *WatchEvidenceBundle `json:"evidence,omitempty"`
}

CreateWatchAlertParams defines the input for creating a watch alert.

type CreateWatchParams

type CreateWatchParams struct {
	ConditionsJSON json.RawMessage `json:"conditions"`
	Service        string          `json:"service,omitempty"`
	Endpoint       string          `json:"endpoint,omitempty"`
	Environment    string          `json:"environment,omitempty"`
	CommitHash     string          `json:"commit_hash,omitempty"`
	Duration       string          `json:"duration,omitempty"`
	Urgency        WatchUrgency    `json:"urgency,omitempty"`
	CheckInterval  string          `json:"check_interval,omitempty"`
	BaselineWindow string          `json:"baseline_window,omitempty"`
	MinConsecutive int             `json:"min_consecutive,omitempty"`
	CreatedBy      string          `json:"created_by,omitempty"`
	SessionID      string          `json:"session_id,omitempty"`
}

CreateWatchParams defines the input for creating a watch. ConditionsJSON is required and contains the full condition tree.

type DataSource

type DataSource struct {
	bun.BaseModel `bun:"table:data_sources" json:"-"`
	ID            uuid.UUID       `bun:"id,pk" json:"id"`
	Type          ConnectorType   `bun:"type" json:"type"`
	Name          string          `bun:"name" json:"name"`
	Config        map[string]any  `bun:"config" json:"config"`
	Status        ConnectorStatus `bun:"status" json:"status"`
	StatusMessage *string         `bun:"status_message" json:"status_message,omitempty"`
	LastTestedAt  *time.Time      `bun:"last_tested_at" json:"last_tested_at,omitempty"`
	// Environment pins this connector to a single env ("staging", "production",
	// etc.) or the wildcard "*" for shared infrastructure (e.g. an analytics
	// warehouse queried from every env). See decision #7 in
	// docs/multi-env-support.md for the bidirectional enforcement rules.
	Environment string    `bun:"environment" json:"environment,omitempty"`
	CreatedAt   time.Time `bun:"created_at" json:"created_at"`
	UpdatedAt   time.Time `bun:"updated_at" json:"updated_at"`
}

type DataSourceStore

type DataSourceStore interface {
	Create(ctx context.Context, params CreateDataSourceParams) (*DataSource, error)
	GetByID(ctx context.Context, id uuid.UUID) (*DataSource, error)
	List(ctx context.Context, params ListDataSourceParams) ([]DataSource, error)
	Update(ctx context.Context, id uuid.UUID, params UpdateDataSourceParams) (*DataSource, error)
	Delete(ctx context.Context, id uuid.UUID) error
}

DataSourceStore defines CRUD operations for data sources.

type DeployMarker

type DeployMarker struct {
	bun.BaseModel `bun:"table:deploy_markers" json:"-"`
	ID            int64     `bun:"id,pk,autoincrement" json:"id"`
	Service       string    `bun:"service" json:"service"`
	Environment   string    `bun:"environment" json:"environment,omitempty"`
	CommitHash    string    `bun:"commit_hash" json:"commit_hash"`
	FirstSeenAt   time.Time `bun:"first_seen_at" json:"first_seen_at"`
	RequestCount  int       `bun:"request_count" json:"request_count"`
}

DeployMarker records when a new commit was first seen.

type EndpointStat

type EndpointStat struct {
	bun.BaseModel    `bun:"table:endpoint_stats" json:"-"`
	ID               int64     `bun:"id,pk,autoincrement" json:"id"`
	Period           string    `bun:"period" json:"period"`
	PeriodStart      time.Time `bun:"period_start" json:"period_start"`
	Service          string    `bun:"service" json:"service,omitempty"`
	Method           string    `bun:"method" json:"method,omitempty"`
	Controller       string    `bun:"controller" json:"controller,omitempty"`
	Action           string    `bun:"action" json:"action,omitempty"`
	PathPattern      string    `bun:"path_pattern" json:"path_pattern,omitempty"`
	RequestCount     int       `bun:"request_count" json:"request_count"`
	ErrorCount       int       `bun:"error_count" json:"error_count"`
	ClientErrorCount int       `bun:"client_error_count" json:"client_error_count"`
	AvgDurationMs    float64   `bun:"avg_duration_ms" json:"avg_duration_ms"`
	P95DurationMs    float64   `bun:"p95_duration_ms" json:"p95_duration_ms"`
	MaxDurationMs    float64   `bun:"max_duration_ms" json:"max_duration_ms"`
	AvgSQLCount      float64   `bun:"avg_sql_count" json:"avg_sql_count"`
	Status2xx        int       `bun:"status_2xx" json:"status_2xx"`
	Status3xx        int       `bun:"status_3xx" json:"status_3xx"`
	Status4xx        int       `bun:"status_4xx" json:"status_4xx"`
	Status5xx        int       `bun:"status_5xx" json:"status_5xx"`
	CreatedAt        time.Time `bun:"created_at" json:"created_at"`
}

EndpointStat holds aggregated stats for a single endpoint in a time period.

type ErrorGroup

type ErrorGroup struct {
	bun.BaseModel   `bun:"table:error_groups" json:"-"`
	Fingerprint     string           `bun:"fingerprint,pk" json:"fingerprint"`
	Environment     string           `bun:"environment,pk" json:"environment"`
	Service         string           `bun:"service" json:"service"`
	ExceptionClass  string           `bun:"exception_class" json:"exception_class"`
	Message         string           `bun:"message" json:"message"`
	SourceFile      string           `bun:"source_file" json:"source_file"`
	SourceLine      int              `bun:"source_line" json:"source_line"`
	Status          ErrorGroupStatus `bun:"status" json:"status"`
	FirstSeenAt     time.Time        `bun:"first_seen_at" json:"first_seen_at"`
	LastSeenAt      time.Time        `bun:"last_seen_at" json:"last_seen_at"`
	OccurrenceCount int              `bun:"occurrence_count" json:"occurrence_count"`
	LastLogID       *int64           `bun:"last_log_id" json:"last_log_id,omitempty"`
	ReopenedCount   int              `bun:"reopened_count" json:"reopened_count"`
	ResolvedAt      *time.Time       `bun:"resolved_at" json:"resolved_at,omitempty"`
	IgnoredAt       *time.Time       `bun:"ignored_at" json:"ignored_at,omitempty"`
	// SeenInEnvs is stored as a JSON array of env names in the seen_in_envs
	// TEXT column; the sqlite store encodes/decodes on read/write.
	SeenInEnvs []string          `bun:"-" json:"seen_in_envs,omitempty"`
	Events     []ErrorGroupEvent `bun:"rel:has-many,join:fingerprint=fingerprint" json:"events,omitempty"`

	// Phase 3: Impact tracking
	UniqueUsers   int            `bun:"unique_users" json:"unique_users"`
	ImpactScore   float64        `bun:"impact_score" json:"impact_score"`
	CommonContext map[string]any `bun:"common_context" json:"common_context,omitempty"`
}

ErrorGroup aggregates errors by (fingerprint, environment). The same crash appearing in staging and production produces two distinct rows; SeenInEnvs carries the full set of envs a given fingerprint has been observed in so the agent can cross-reference without scanning every row.

type ErrorGroupEvent

type ErrorGroupEvent struct {
	bun.BaseModel `bun:"table:error_group_events" json:"-"`
	ID            int64     `bun:"id,pk,autoincrement" json:"id"`
	Fingerprint   string    `bun:"fingerprint" json:"fingerprint"`
	Environment   string    `bun:"environment" json:"environment,omitempty"`
	Action        string    `bun:"action" json:"action"` // "resolved", "ignored", "reopened"
	Reason        string    `bun:"reason" json:"reason,omitempty"`
	CreatedAt     time.Time `bun:"created_at" json:"created_at"`
}

ErrorGroupEvent records a lifecycle action on an error group. Environment matches the parent error_groups row; both are required to disambiguate.

type ErrorGroupStatus

type ErrorGroupStatus string

ErrorGroupStatus represents the lifecycle state of an error group.

const (
	ErrorGroupUnresolved ErrorGroupStatus = "unresolved"
	ErrorGroupResolved   ErrorGroupStatus = "resolved"
	ErrorGroupIgnored    ErrorGroupStatus = "ignored"
)

type ErrorGroupStore

type ErrorGroupStore interface {
	Upsert(ctx context.Context, entry LogEntry) error
	Get(ctx context.Context, fingerprint string) (*ErrorGroup, error)
	List(ctx context.Context, params ListErrorGroupParams) ([]ErrorGroup, error)
	Count(ctx context.Context, status ErrorGroupStatus) (int, error)
	Resolve(ctx context.Context, fingerprint string, reason string) error
	Ignore(ctx context.Context, fingerprint string, reason string) error
	Reopen(ctx context.Context, fingerprint string, reason string) error
	ListEvents(ctx context.Context, fingerprint string, limit int) ([]ErrorGroupEvent, error)
	Prune(ctx context.Context, olderThan time.Duration) (int64, error)
}

ErrorGroupStore manages error groups aggregated by fingerprint.

type ErrorGroupWithImpact

type ErrorGroupWithImpact struct {
	ErrorGroup
	TopAffectedUsers []AffectedUser `json:"top_affected_users,omitempty"`
}

ErrorGroupWithImpact extends ErrorGroup with impact details.

type ErrorImpact

type ErrorImpact struct {
	bun.BaseModel    `bun:"table:error_impacts" json:"-"`
	Fingerprint      string         `bun:"error_fingerprint,pk" json:"fingerprint"`
	Environment      string         `bun:"environment" json:"environment,omitempty"`
	UniqueUsers      int            `bun:"-" json:"unique_users"`
	TotalOccurrences int            `bun:"-" json:"total_occurrences"`
	ImpactScore      float64        `bun:"-" json:"impact_score"`
	CommonTraits     map[string]any `bun:"-" json:"common_traits,omitempty"`
}

ErrorImpact summarizes the user impact of an error group. Environment matches the parent error_groups row (composite FK + unique constraint).

type ErrorImpactStore

type ErrorImpactStore interface {
	// Called on each error occurrence (upsert). environment must match the
	// env of the error_groups row the impact belongs to.
	TrackImpact(ctx context.Context, fingerprint, environment, userID string, contextData map[string]any, logID int64, service string) error

	// Query. GetImpact aggregates across every env the fingerprint has been
	// observed in; callers that want env-specific numbers should filter
	// GetAffectedUsers results.
	GetImpact(ctx context.Context, fingerprint string) (*ErrorImpact, error)
	GetAffectedUsers(ctx context.Context, fingerprint string, limit int) ([]AffectedUser, error)
	GetUserErrors(ctx context.Context, userID string, since time.Time) ([]ErrorSummary, error)

	// Scoring
	ComputeImpactScores(ctx context.Context) error
	TopByImpact(ctx context.Context, params ImpactQueryParams) ([]ErrorGroupWithImpact, error)

	// Pattern detection
	FindCommonTraits(ctx context.Context, fingerprint string) (map[string]any, error)
}

ErrorImpactStore tracks which users are affected by each error and computes impact scores.

type ErrorSummary

type ErrorSummary struct {
	Fingerprint     string           `json:"fingerprint"`
	ExceptionClass  string           `json:"exception_class"`
	Message         string           `json:"message"`
	OccurrenceCount int              `json:"occurrence_count"`
	FirstSeenAt     time.Time        `json:"first_seen_at"`
	LastSeenAt      time.Time        `json:"last_seen_at"`
	Status          ErrorGroupStatus `json:"status"`
}

ErrorSummary is a lightweight error record for user-scoped queries.

type HealthCheck

type HealthCheck struct {
	bun.BaseModel  `bun:"table:healthchecks" json:"-"`
	ID             string    `bun:"id,pk" json:"id"`
	Name           string    `bun:"name" json:"name"`
	URL            string    `bun:"url" json:"url"`
	Method         string    `bun:"method" json:"method"`
	IntervalSecs   int       `bun:"interval_secs" json:"interval_secs"`
	TimeoutSecs    int       `bun:"timeout_secs" json:"timeout_secs"`
	ExpectedStatus int       `bun:"expected_status" json:"expected_status"`
	ExpectedBody   string    `bun:"expected_body" json:"expected_body,omitempty"`
	Retries        int       `bun:"retries" json:"retries,omitempty"`
	Enabled        bool      `bun:"enabled" json:"enabled"`
	Environment    string    `bun:"environment" json:"environment,omitempty"`
	CreatedAt      time.Time `bun:"created_at" json:"created_at"`
}

HealthCheck represents a configured HTTP endpoint monitor.

type HealthCheckResult

type HealthCheckResult struct {
	bun.BaseModel `bun:"table:healthcheck_results" json:"-"`
	ID            int64             `bun:"id,pk,autoincrement" json:"id"`
	HealthCheckID string            `bun:"healthcheck_id" json:"healthcheck_id"`
	Status        HealthCheckStatus `bun:"status" json:"status"`
	StatusCode    *int              `bun:"status_code" json:"status_code,omitempty"`
	ResponseMs    *int              `bun:"response_ms" json:"response_ms,omitempty"`
	Error         string            `bun:"error" json:"error,omitempty"`
	CheckedAt     time.Time         `bun:"checked_at" json:"checked_at"`
}

HealthCheckResult records a single probe result.

type HealthCheckStatus

type HealthCheckStatus string

HealthCheckStatus represents the current state of a health check target.

const (
	HealthCheckUp       HealthCheckStatus = "up"
	HealthCheckDown     HealthCheckStatus = "down"
	HealthCheckDegraded HealthCheckStatus = "degraded"
)

type HealthCheckStore

type HealthCheckStore interface {
	Create(ctx context.Context, params CreateHealthCheckParams) (*HealthCheck, error)
	Get(ctx context.Context, id string) (*HealthCheck, error)
	List(ctx context.Context, params ListHealthCheckParams) ([]HealthCheck, error)
	Delete(ctx context.Context, id string) error
	SetEnabled(ctx context.Context, id string, enabled bool) error
	RecordResult(ctx context.Context, result HealthCheckResult) error
	LatestResults(ctx context.Context, healthcheckID string, limit int) ([]HealthCheckResult, error)
	UptimeSummaries(ctx context.Context, since time.Time) ([]UptimeSummary, error)
	PruneResults(ctx context.Context, olderThan time.Duration) (int64, error)
}

HealthCheckStore manages HTTP endpoint health checks (uptime monitoring).

type HeatmapCell

type HeatmapCell struct {
	bun.BaseModel `bun:"table:traffic_heatmap" json:"-"`
	Service       string  `bun:"service" json:"service,omitempty"`
	DayOfWeek     int     `bun:"day_of_week" json:"day_of_week"` // 0=Sunday
	HourOfDay     int     `bun:"hour_of_day" json:"hour_of_day"` // 0-23
	RequestCount  int     `bun:"request_count" json:"request_count"`
	ErrorCount    int     `bun:"error_count" json:"error_count"`
	AvgDurationMs float64 `bun:"avg_duration_ms" json:"avg_duration_ms"`
}

HeatmapCell holds one cell of the 24x7 traffic heatmap.

type ImpactQueryParams

type ImpactQueryParams struct {
	Status      ErrorGroupStatus `json:"status,omitempty"`
	Service     string           `json:"service,omitempty"`
	Environment string           `json:"environment,omitempty"`
	Since       time.Time        `json:"since"`
	SortBy      string           `json:"sort_by,omitempty"` // impact_score, unique_users, occurrence_count, last_seen
	Limit       int              `json:"limit,omitempty"`
}

ImpactQueryParams defines filters for querying errors by impact.

type ListDataSourceParams

type ListDataSourceParams struct {
	Type        ConnectorType `json:"type,omitempty"`
	Environment string        `json:"environment,omitempty"`
}

ListDataSourceParams defines filters for listing data sources.

type ListErrorGroupParams

type ListErrorGroupParams struct {
	Status      ErrorGroupStatus `json:"status,omitempty"`
	Service     string           `json:"service,omitempty"`
	Environment string           `json:"environment,omitempty"`
	Since       *time.Time       `json:"since,omitempty"`   // only groups first seen after this time
	SortBy      string           `json:"sort_by,omitempty"` // "occurrence_count", "last_seen_at", "first_seen_at"
	Limit       int              `json:"limit,omitempty"`
	Offset      int              `json:"offset,omitempty"`
}

ListErrorGroupParams defines filters for listing error groups.

type ListHealthCheckParams

type ListHealthCheckParams struct {
	Limit       int    `json:"limit,omitempty"`
	Offset      int    `json:"offset,omitempty"`
	Environment string `json:"environment,omitempty"`
}

ListHealthCheckParams controls pagination for health check listing.

type ListServerParams

type ListServerParams struct {
	Limit       int    `json:"limit,omitempty"`
	Offset      int    `json:"offset,omitempty"`
	Environment string `json:"environment,omitempty"`
}

ListServerParams controls pagination for server listing.

type ListWatchParams

type ListWatchParams struct {
	Status      WatchStatus `json:"status,omitempty"`
	Service     string      `json:"service,omitempty"`
	Environment string      `json:"environment,omitempty"`
	SessionID   string      `json:"session_id,omitempty"`
	Limit       int         `json:"limit,omitempty"`
	Offset      int         `json:"offset,omitempty"`
}

ListWatchParams defines filters for listing watches.

type LogAuditParams

type LogAuditParams struct {
	UserID      string
	UserEmail   string
	Action      string // e.g. "user.create", "connector.delete", "settings.update"
	TargetType  string // e.g. "user", "connector", "watcher"
	TargetID    string
	Details     string // JSON or free-text details
	IPAddress   string
	Environment string // env the write targeted; empty for admin / global actions
}

LogAuditParams are the parameters for creating an audit log entry.

type LogCountParams

type LogCountParams struct {
	Since       time.Time
	Until       time.Time
	Service     string // optional filter
	Level       string // optional filter
	Environment string // optional filter — empty matches every env
}

LogCountParams defines filters for log aggregation queries.

type LogEntry

type LogEntry struct {
	bun.BaseModel    `bun:"table:logs" json:"-"`
	ID               int64           `bun:"id,pk,autoincrement" json:"id"`
	Timestamp        time.Time       `bun:"timestamp" json:"timestamp"`
	Level            string          `bun:"level" json:"level"`
	Service          string          `bun:"service" json:"service,omitempty"`
	Environment      string          `bun:"environment" json:"environment,omitempty"`
	CommitHash       string          `bun:"commit_hash" json:"commit_hash,omitempty"`
	TraceID          string          `bun:"trace_id" json:"trace_id,omitempty"`
	SpanID           string          `bun:"span_id" json:"span_id,omitempty"`
	ParentSpanID     string          `bun:"parent_span_id" json:"parent_span_id,omitempty"`
	RequestID        string          `bun:"request_id" json:"request_id,omitempty"`
	UserID           string          `bun:"user_id" json:"user_id,omitempty"`
	Message          string          `bun:"message" json:"message"`
	EventType        string          `bun:"event_type" json:"event_type,omitempty"`
	ExceptionClass   string          `bun:"exception_class" json:"exception_class,omitempty"`
	ErrorFingerprint string          `bun:"error_fingerprint" json:"error_fingerprint,omitempty"`
	SourceFile       string          `bun:"source_file" json:"source_file,omitempty"`
	SourceLine       int             `bun:"source_line" json:"source_line,omitempty"`
	Metadata         map[string]any  `bun:"metadata" json:"metadata,omitempty"`
	MetadataJSON     string          `bun:"-" json:"-"` // pre-marshaled metadata; avoids double marshal on hot path
	DeepCapture      json.RawMessage `bun:"-" json:"-"` // carrier field: raw deep capture document for in-tx processing
	RequestSummary   *RequestSummary `bun:"rel:has-one,join:id=log_id" json:"request_summary,omitempty"`
	CreatedAt        time.Time       `bun:"created_at" json:"created_at"`
}

LogEntry represents an ingested log line.

type LogHistogramBucket

type LogHistogramBucket struct {
	Timestamp  time.Time `json:"timestamp"`
	Total      int       `json:"total"`
	ErrorCount int       `json:"error_count"`
}

LogHistogramBucket holds aggregated log counts for a single time bucket.

type LogHistogramParams

type LogHistogramParams struct {
	Since       time.Time
	Until       time.Time
	Interval    time.Duration
	Service     string
	Level       string
	Environment string
}

LogHistogramParams defines parameters for log volume histogram queries.

type LogMCPActivityParams

type LogMCPActivityParams struct {
	SessionID              string
	UserID                 string
	ToolName               string
	Arguments              string
	ResultPreview          string
	IsError                bool
	DurationMs             *int64
	EventType              string // "tool_call", "connect", "disconnect"
	Environment            string // env the call targeted; empty for scope-less or global tools
	InvestigationSessionID string // links to investigation_sessions.id
	StepIndex              int    // step number within the investigation session
	WasSuggested           bool   // whether this tool was in the previous suggested_tools
	SuggestionRank         int    // rank in the suggestion list (0 if not suggested)
	FollowedBy             string // tool name that followed this one (unused in INSERT, kept for compat)
	PreviousStepIndex      int    // step index of the previous tool (for updating followed_by)
}

LogMCPActivityParams defines input for logging an MCP activity event.

type LogSearchParams

type LogSearchParams struct {
	Query            string            `json:"query,omitempty"`
	Service          string            `json:"service,omitempty"`
	Level            string            `json:"level,omitempty"`
	Environment      string            `json:"environment,omitempty"`
	CommitHash       string            `json:"commit_hash,omitempty"`
	TraceID          string            `json:"trace_id,omitempty"`
	RequestID        string            `json:"request_id,omitempty"`
	EventType        string            `json:"event_type,omitempty"`
	ExceptionClass   string            `json:"exception_class,omitempty"`
	ErrorFingerprint string            `json:"error_fingerprint,omitempty"`
	SourceFile       string            `json:"source_file,omitempty"`
	Start            *time.Time        `json:"start,omitempty"`
	End              *time.Time        `json:"end,omitempty"`
	Limit            int               `json:"limit,omitempty"`
	Offset           int               `json:"offset,omitempty"`
	SinceID          int64             `json:"since_id,omitempty"`
	MetadataFilter   map[string]string `json:"metadata_filter,omitempty"` // key-value filters on metadata JSON
	Exclude          map[string]string `json:"exclude,omitempty"`         // field -> comma-separated values to exclude (NOT IN)
	SortAsc          bool              `json:"sort_asc,omitempty"`        // true for oldest-first (default: newest-first)
}

LogSearchParams defines filters for log search.

type LogStore

type LogStore interface {
	BatchInsert(ctx context.Context, entries []LogEntry) (int, error)
	Search(ctx context.Context, params LogSearchParams) ([]LogEntry, error)
	Prune(ctx context.Context, olderThan time.Duration) (int64, error)
	CountByLevel(ctx context.Context, params LogCountParams) (map[string]int, error)
	CountByService(ctx context.Context, params LogCountParams) ([]ServiceLogCount, error)
	Histogram(ctx context.Context, params LogHistogramParams) ([]LogHistogramBucket, error)
	DistinctValues(ctx context.Context, field string, params LogCountParams) ([]string, error)
	MetadataKeys(ctx context.Context, params LogCountParams) ([]string, error)
	GetByID(ctx context.Context, id int64) (*LogEntry, error)
	// Request performance
	SearchRequestSummaries(ctx context.Context, params RequestSummarySearchParams) ([]RequestSummaryResult, error)
	AggregateRequestSummaries(ctx context.Context, params RequestSummaryAggregateParams) (*RequestSummaryAggregates, error)
	// Batch deduplication
	RecordBatch(ctx context.Context, batchID string, logCount int) error
	GetBatch(ctx context.Context, batchID string) (*BatchRecord, error)
	PruneBatches(ctx context.Context, olderThan time.Duration) (int64, error)
}

LogStore defines operations for log ingestion and search.

type MCPActivityEvent

type MCPActivityEvent struct {
	bun.BaseModel `bun:"table:mcp_activity" json:"-"`
	ID            int64     `bun:"id,pk,autoincrement" json:"id"`
	SessionID     string    `bun:"session_id" json:"session_id"`
	UserID        string    `bun:"user_id" json:"user_id,omitempty"`
	ToolName      string    `bun:"tool_name" json:"tool_name"`
	Arguments     string    `bun:"arguments" json:"arguments,omitempty"`
	ResultPreview string    `bun:"result_preview" json:"result_preview,omitempty"`
	IsError       bool      `bun:"is_error" json:"is_error"`
	DurationMs    *int64    `bun:"duration_ms" json:"duration_ms,omitempty"`
	EventType     string    `bun:"event_type" json:"event_type"`
	Environment   string    `bun:"environment" json:"environment,omitempty"`
	CreatedAt     time.Time `bun:"created_at" json:"created_at"`
}

MCPActivityEvent represents a single MCP tool call or connection event.

type MCPActivityStats

type MCPActivityStats struct {
	ActiveSessions int        `json:"active_sessions"`
	CallsLastHour  int        `json:"calls_last_hour"`
	ErrorsLastHour int        `json:"errors_last_hour"`
	LastActivity   *time.Time `json:"last_activity,omitempty"`
}

MCPActivityStats holds aggregated MCP activity statistics.

type MCPActivityStore

type MCPActivityStore interface {
	Log(ctx context.Context, params LogMCPActivityParams) error
	Stats(ctx context.Context) (*MCPActivityStats, error)
	Recent(ctx context.Context, limit int) ([]MCPActivityEvent, error)
	ListByInvestigationSession(ctx context.Context, sessionID string) ([]MCPActivityEvent, error)
	Prune(ctx context.Context, olderThan time.Duration) (int64, error)
	SetSuggestionTracking(ctx context.Context, invSessionID string, stepIndex int, wasSuggested bool, rank int) error
	UpdateFollowedBy(ctx context.Context, invSessionID string, stepIndex int, followedBy string) error
}

MCPActivityStore tracks MCP tool calls and connection events.

type MetricBucket

type MetricBucket struct {
	bun.BaseModel     `bun:"table:metric_buckets" json:"-"`
	ID                int64     `bun:"id,pk,autoincrement" json:"id"`
	BucketStart       time.Time `bun:"bucket_start" json:"bucket_start"`
	BucketInterval    string    `bun:"bucket_interval" json:"bucket_interval"`
	Service           string    `bun:"service" json:"service,omitempty"`
	Endpoint          string    `bun:"endpoint" json:"endpoint,omitempty"`
	Environment       string    `bun:"environment" json:"environment,omitempty"`
	RequestCount      int       `bun:"request_count" json:"request_count"`
	ErrorCount        int       `bun:"error_count" json:"error_count"`
	LogCount          int       `bun:"log_count" json:"log_count"`
	AvgDurationMs     float64   `bun:"avg_duration_ms" json:"avg_duration_ms"`
	P50DurationMs     float64   `bun:"p50_duration_ms" json:"p50_duration_ms"`
	P95DurationMs     float64   `bun:"p95_duration_ms" json:"p95_duration_ms"`
	P99DurationMs     float64   `bun:"p99_duration_ms" json:"p99_duration_ms"`
	MaxDurationMs     float64   `bun:"max_duration_ms" json:"max_duration_ms"`
	AvgSQLCount       float64   `bun:"avg_sql_count" json:"avg_sql_count"`
	AvgDBTimeMs       float64   `bun:"avg_db_time_ms" json:"avg_db_time_ms"`
	AvgCacheHitRatio  float64   `bun:"avg_cache_hit_ratio" json:"avg_cache_hit_ratio"`
	AvgHTTPExternalMs float64   `bun:"avg_http_external_ms" json:"avg_http_external_ms"`
	CreatedAt         time.Time `bun:"created_at" json:"created_at"`
}

MetricBucket holds pre-aggregated metrics for a time bucket.

type MetricPoint

type MetricPoint struct {
	bun.BaseModel `bun:"table:metrics" json:"-"`
	ID            int64             `bun:"id,pk,autoincrement" json:"id"`
	ServerID      uuid.UUID         `bun:"server_id" json:"server_id"`
	Timestamp     time.Time         `bun:"timestamp" json:"timestamp"`
	MetricName    string            `bun:"metric_name" json:"metric_name"`
	MetricValue   float64           `bun:"metric_value" json:"metric_value"`
	Unit          string            `bun:"unit" json:"unit,omitempty"`
	Labels        map[string]string `bun:"labels" json:"labels,omitempty"`
}

MetricPoint represents a single metric data point returned by queries.

type MetricQuery

type MetricQuery struct {
	ServerID   uuid.UUID  `json:"server_id"`
	MetricName string     `json:"metric_name,omitempty"`
	Start      *time.Time `json:"start,omitempty"`
	End        *time.Time `json:"end,omitempty"`
	Limit      int        `json:"limit,omitempty"`
}

MetricQuery defines filters for querying metrics.

type MetricSample

type MetricSample struct {
	Name   string            `json:"name"`
	Value  float64           `json:"value"`
	Unit   string            `json:"unit,omitempty"`
	Labels map[string]string `json:"labels,omitempty"`
}

MetricSample is a single metric in an ingestion batch (no server_id or timestamp — those come from the batch context).

type MetricStore

type MetricStore interface {
	BatchInsert(ctx context.Context, serverID uuid.UUID, ts time.Time, samples []MetricSample) (int, error)
	Query(ctx context.Context, params MetricQuery) ([]MetricPoint, error)
	LatestByServer(ctx context.Context, serverID uuid.UUID) ([]MetricPoint, error)
	Prune(ctx context.Context, olderThan time.Duration) (int64, error)
}

MetricStore manages time-series metric data for servers.

type RegisterServerParams

type RegisterServerParams struct {
	Hostname     string            `json:"hostname"`
	IPAddress    string            `json:"ip_address,omitempty"`
	OS           string            `json:"os,omitempty"`
	Arch         string            `json:"arch,omitempty"`
	AgentVersion string            `json:"agent_version,omitempty"`
	Labels       map[string]string `json:"labels,omitempty"`
	Environment  string            `json:"environment,omitempty"`
}

RegisterServerParams defines the input for registering/updating a server.

type RequestSummary

type RequestSummary struct {
	bun.BaseModel       `bun:"table:request_summaries" json:"-"`
	ID                  int64   `bun:"id,pk,autoincrement" json:"id"`
	LogID               int64   `bun:"log_id" json:"log_id"`
	Controller          string  `bun:"controller" json:"controller,omitempty"`
	Action              string  `bun:"action" json:"action,omitempty"`
	Method              string  `bun:"method" json:"method,omitempty"`
	Path                string  `bun:"path" json:"path,omitempty"`
	Status              int     `bun:"status" json:"status,omitempty"`
	DurationMs          float64 `bun:"duration_ms" json:"duration_ms,omitempty"`
	DBTimeMs            float64 `bun:"db_time_ms" json:"db_time_ms,omitempty"`
	ViewTimeMs          float64 `bun:"view_time_ms" json:"view_time_ms,omitempty"`
	SQLCount            int     `bun:"sql_count" json:"sql_count,omitempty"`
	SQLTotalMs          float64 `bun:"sql_total_ms" json:"sql_total_ms,omitempty"`
	SQLSlowestMs        float64 `bun:"sql_slowest_ms" json:"sql_slowest_ms,omitempty"`
	SQLSlowestName      string  `bun:"sql_slowest_name" json:"sql_slowest_name,omitempty"`
	NPlusOne            bool    `bun:"n_plus_one" json:"n_plus_one,omitempty"`
	ViewCount           int     `bun:"view_count" json:"view_count,omitempty"`
	ViewTotalMs         float64 `bun:"view_total_ms" json:"view_total_ms,omitempty"`
	ViewSlowestMs       float64 `bun:"view_slowest_ms" json:"view_slowest_ms,omitempty"`
	ViewSlowestTemplate string  `bun:"view_slowest_template" json:"view_slowest_template,omitempty"`
	CacheReads          int     `bun:"cache_reads" json:"cache_reads,omitempty"`
	CacheHits           int     `bun:"cache_hits" json:"cache_hits,omitempty"`
	CacheWrites         int     `bun:"cache_writes" json:"cache_writes,omitempty"`
	CacheHitRatio       float64 `bun:"cache_hit_ratio" json:"cache_hit_ratio,omitempty"`
	HTTPExternalCount   int     `bun:"http_external_count" json:"http_external_count,omitempty"`
	HTTPExternalTotalMs float64 `bun:"http_external_total_ms" json:"http_external_total_ms,omitempty"`
	HTTPSlowestMs       float64 `bun:"http_slowest_ms" json:"http_slowest_ms,omitempty"`
	HTTPSlowestHost     string  `bun:"http_slowest_host" json:"http_slowest_host,omitempty"`
	MemoryBeforeMb      float64 `bun:"memory_before_mb" json:"memory_before_mb,omitempty"`
	MemoryAfterMb       float64 `bun:"memory_after_mb" json:"memory_after_mb,omitempty"`
	MemoryDeltaMb       float64 `bun:"memory_delta_mb" json:"memory_delta_mb,omitempty"`
	Timeline            string  `bun:"timeline" json:"timeline,omitempty"`
	TimeBreakdown       string  `bun:"time_breakdown" json:"time_breakdown,omitempty"`
	DuplicateQueries    int     `bun:"duplicate_queries" json:"duplicate_queries,omitempty"`
	WorstDuplicateCount int     `bun:"worst_duplicate_count" json:"worst_duplicate_count,omitempty"`
	TopDuplicates       string  `bun:"top_duplicates" json:"top_duplicates,omitempty"`
}

RequestSummary holds structured performance metrics for an HTTP request.

type RequestSummaryAggregateParams

type RequestSummaryAggregateParams struct {
	Start       *time.Time
	End         *time.Time
	Service     string
	Endpoint    string
	Environment string
}

RequestSummaryAggregateParams defines filters for SQL-level aggregation.

type RequestSummaryAggregates

type RequestSummaryAggregates struct {
	Count        int     `json:"count"`
	AvgDuration  float64 `json:"avg_duration_ms"`
	AvgSQLCount  float64 `json:"avg_sql_count"`
	TotalReads   int     `json:"total_cache_reads"`
	TotalHits    int     `json:"total_cache_hits"`
	CacheHitRate float64 `json:"cache_hit_rate"`
}

RequestSummaryAggregates holds pre-computed aggregate metrics.

type RequestSummaryResult

type RequestSummaryResult struct {
	RequestSummary
	Timestamp time.Time `json:"timestamp"`
	Service   string    `json:"service,omitempty"`
	TraceID   string    `json:"trace_id,omitempty"`
}

RequestSummaryResult extends RequestSummary with log-level fields.

type RequestSummarySearchParams

type RequestSummarySearchParams struct {
	Start         *time.Time
	End           *time.Time
	Controller    string
	Action        string
	Path          string
	Environment   string
	NPlusOneOnly  bool
	MinDurationMs float64
	MinSQLCount   int
	SortBy        string // "duration_ms", "sql_count", "db_time_ms", "duplicate_queries"
	Limit         int
	Offset        int
}

RequestSummarySearchParams defines filters for searching request summaries.

type RetentionSettings

type RetentionSettings struct {
	RetentionDays       int `json:"retention_days"`
	MetricRetentionDays int `json:"metric_retention_days"` // 0 = use global retention_days
}

RetentionSettings holds data retention configuration.

type SamplingRule

type SamplingRule struct {
	Service    string  `json:"service"`     // service name, or "*" for default
	Rate       float64 `json:"rate"`        // 0.0-1.0 (1.0 = keep all)
	KeepErrors bool    `json:"keep_errors"` // always keep error/warn/fatal logs
}

SamplingRule defines a per-service log sampling policy.

type Server

type Server struct {
	bun.BaseModel `bun:"table:servers" json:"-"`
	ID            uuid.UUID         `bun:"id,pk" json:"id"`
	Hostname      string            `bun:"hostname" json:"hostname"`
	DisplayName   string            `bun:"display_name" json:"display_name,omitempty"`
	IPAddress     string            `bun:"ip_address" json:"ip_address,omitempty"`
	OS            string            `bun:"os" json:"os,omitempty"`
	Arch          string            `bun:"arch" json:"arch,omitempty"`
	AgentVersion  string            `bun:"agent_version" json:"agent_version,omitempty"`
	Labels        map[string]string `bun:"labels" json:"labels,omitempty"`
	Status        ServerStatus      `bun:"status" json:"status"`
	LastSeenAt    *time.Time        `bun:"last_seen_at" json:"last_seen_at,omitempty"`
	Environment   string            `bun:"environment" json:"environment,omitempty"`
	CreatedAt     time.Time         `bun:"created_at" json:"created_at"`
	UpdatedAt     time.Time         `bun:"updated_at" json:"updated_at"`
}

Server represents a monitored VM or host.

type ServerStatus

type ServerStatus string

ServerStatus represents the health status of a monitored server.

const (
	ServerOnline  ServerStatus = "online"
	ServerOffline ServerStatus = "offline"
	ServerUnknown ServerStatus = "unknown"
)

type ServerStore

type ServerStore interface {
	Register(ctx context.Context, params RegisterServerParams) (*Server, error)
	GetByID(ctx context.Context, id uuid.UUID) (*Server, error)
	List(ctx context.Context, params ListServerParams) ([]Server, error)
	Update(ctx context.Context, id uuid.UUID, params UpdateServerParams) (*Server, error)
	UpdateHeartbeat(ctx context.Context, id uuid.UUID) error
	Delete(ctx context.Context, id uuid.UUID) error
	MarkStaleOffline(ctx context.Context, threshold time.Duration) (int, error)
}

ServerStore manages monitored server registrations.

type ServiceLogCount

type ServiceLogCount struct {
	Service    string `json:"service"`
	Total      int    `json:"total"`
	ErrorCount int    `json:"error_count"`
}

ServiceLogCount holds per-service log counts.

type Session

type Session struct {
	bun.BaseModel `bun:"table:sessions" json:"-"`
	ID            string    `bun:"id,pk" json:"id"`
	UserID        string    `bun:"user_id" json:"user_id"`
	Token         string    `bun:"token" json:"-"`
	ExpiresAt     time.Time `bun:"expires_at" json:"expires_at"`
	CreatedAt     time.Time `bun:"created_at" json:"created_at"`
}

Session represents an authenticated browser session.

type SessionStore

type SessionStore interface {
	Create(ctx context.Context, userID string, token string, expiresAt time.Time) (*Session, error)
	GetByToken(ctx context.Context, token string) (*Session, error)
	Delete(ctx context.Context, id string) error
	DeleteExpired(ctx context.Context) (int, error)
	DeleteAllForUser(ctx context.Context, userID string) error
}

SessionStore manages browser sessions.

type SettingsStore

type SettingsStore interface {
	GetRetention(ctx context.Context) (*RetentionSettings, error)
	SetRetention(ctx context.Context, settings RetentionSettings) error
	GetAPIKey(ctx context.Context) (string, error)
	SetAPIKey(ctx context.Context, key string) error
	GetCORSOrigins(ctx context.Context) (string, error)
	SetCORSOrigins(ctx context.Context, origins string) error
	GetMaxQueryRows(ctx context.Context) (int, error)
	SetMaxQueryRows(ctx context.Context, val int) error
	GetStatementTimeout(ctx context.Context) (int, error)
	SetStatementTimeout(ctx context.Context, val int) error
	GetMCPName(ctx context.Context) (string, error)
	SetMCPName(ctx context.Context, name string) error
	GetSamplingRules(ctx context.Context) ([]SamplingRule, error)
	SetSamplingRules(ctx context.Context, rules []SamplingRule) error
	GetTelegramConfig(ctx context.Context) (*TelegramConfig, error)
	SetTelegramConfig(ctx context.Context, cfg TelegramConfig) error
}

SettingsStore manages application settings stored in app_config.

type Stores

type Stores struct {
	DSStore          DataSourceStore
	LogStore         LogStore
	ServerStore      ServerStore
	MetricStore      MetricStore
	UserStore        UserStore
	SessionStore     SessionStore
	SettingsStore    SettingsStore
	MCPActivityStore MCPActivityStore
	AuditStore       AuditStore
	WatchStore       WatchStore
	ErrorGroupStore  ErrorGroupStore
	HealthCheckStore HealthCheckStore
	AgentNoteStore   AgentNoteStore
	TrendStore       TrendStore
	AnalyticsStore   AnalyticsStore
	ErrorImpactStore ErrorImpactStore
	TraceStore       TraceStore
	CodeEntityStore  CodeEntityStore
}

Stores groups all domain store implementations. Embedding this struct in dependency containers lets consumers access e.g. deps.LogStore without individual fields.

type TelegramConfig

type TelegramConfig struct {
	BotToken string `json:"bot_token"`
	ChatID   string `json:"chat_id"`
	Enabled  bool   `json:"enabled"`
}

TelegramConfig holds Telegram notification settings.

type TestCorrelationStore

type TestCorrelationStore interface {
	RefreshUncoveredPaths(ctx context.Context) error
	TopByPriority(ctx context.Context, service string, limit int) ([]UncoveredErrorPath, error)
	GetByFingerprint(ctx context.Context, fingerprint string) (*UncoveredErrorPath, error)
	Prune(ctx context.Context, olderThan time.Duration) (int64, error)
}

TestCorrelationStore manages uncovered error path analysis.

type TopEndpointParams

type TopEndpointParams struct {
	Service     string    `json:"service,omitempty"`
	Since       time.Time `json:"since"`
	Until       time.Time `json:"until"`
	SortBy      string    `json:"sort_by,omitempty"` // "request_count", "error_rate", "avg_duration", "p95_duration"
	Limit       int       `json:"limit,omitempty"`
	MinRequests int       `json:"min_requests,omitempty"`
}

TopEndpointParams defines filters for ranking endpoints.

type TraceStatus

type TraceStatus struct {
	bun.BaseModel `bun:"table:trace_status" json:"-"`
	TraceID       string    `bun:"trace_id,pk" json:"trace_id"`
	SpanCount     int       `bun:"span_count" json:"span_count"`
	RootSpanID    string    `bun:"root_span_id" json:"root_span_id,omitempty"`
	Services      []string  `bun:"services" json:"services"`
	FirstSeenAt   time.Time `bun:"first_seen_at" json:"first_seen_at"`
	LastUpdatedAt time.Time `bun:"last_updated_at" json:"last_updated_at"`
	DurationMs    float64   `bun:"duration_ms" json:"duration_ms"`
	Status        string    `bun:"status" json:"status"` // "partial", "complete", "timeout"
	HasErrors     bool      `bun:"has_errors" json:"has_errors"`
}

TraceStatus tracks the reassembly status of a distributed trace.

type TraceStore

type TraceStore interface {
	UpsertTraceStatus(ctx context.Context, traceID string, entry LogEntry) error
	GetTraceStatus(ctx context.Context, traceID string) (*TraceStatus, error)
	ListRecentTraces(ctx context.Context, limit, offset int) ([]TraceStatus, int, error)
	MarkStaleTraces(ctx context.Context, olderThan time.Duration) (int, error)
}

TraceStore manages distributed trace reassembly status.

type TrafficSummary

type TrafficSummary struct {
	TotalRequests   int            `json:"total_requests"`
	UniqueEndpoints int            `json:"unique_endpoints"`
	ErrorRate       float64        `json:"error_rate"`
	AvgDurationMs   float64        `json:"avg_duration_ms"`
	P95DurationMs   float64        `json:"p95_duration_ms"`
	StatusBreakdown map[string]int `json:"status_breakdown"`
	MethodBreakdown map[string]int `json:"method_breakdown"`
}

TrafficSummary holds high-level traffic overview.

type TrendQueryParams

type TrendQueryParams struct {
	Service     string    `json:"service,omitempty"`
	Endpoint    string    `json:"endpoint,omitempty"`
	Environment string    `json:"environment,omitempty"`
	Interval    string    `json:"interval,omitempty"` // "5m", "15m", "1h", "1d"
	Metric      string    `json:"metric,omitempty"`   // field to extract
	Since       time.Time `json:"since"`
	Until       time.Time `json:"until"`
}

TrendQueryParams defines filters for querying trend data.

type TrendStore

type TrendStore interface {
	// Aggregation (background job)
	AggregateBuckets(ctx context.Context, interval string, since time.Time) error

	// Query
	QueryTrends(ctx context.Context, params TrendQueryParams) ([]MetricBucket, error)
	ListDeployMarkers(ctx context.Context, service string, since time.Time) ([]DeployMarker, error)

	// Maintenance
	Prune(ctx context.Context, olderThan time.Duration) (int64, error)
}

TrendStore manages pre-aggregated metric buckets and deploy markers.

type UncoveredErrorPath

type UncoveredErrorPath struct {
	bun.BaseModel      `bun:"table:uncovered_error_paths" json:"-"`
	ID                 int64     `bun:"id,pk,autoincrement" json:"id"`
	Service            string    `bun:"service" json:"service"`
	ErrorFingerprint   string    `bun:"error_fingerprint" json:"error_fingerprint"`
	ErrorClass         string    `bun:"error_class" json:"error_class"`
	SourceFile         string    `bun:"source_file" json:"source_file"`
	Endpoint           string    `bun:"endpoint" json:"endpoint"`
	ErrorCount         int       `bun:"error_count" json:"error_count"`
	UserImpactScore    float64   `bun:"user_impact_score" json:"user_impact_score"`
	InvestigationCount int       `bun:"investigation_count" json:"investigation_count"`
	PriorityScore      float64   `bun:"priority_score" json:"priority_score"`
	LastSeenAt         time.Time `bun:"last_seen_at" json:"last_seen_at"`
	CreatedAt          time.Time `bun:"created_at" json:"created_at"`
	UpdatedAt          time.Time `bun:"updated_at" json:"updated_at"`
}

UncoveredErrorPath tracks production error paths that lack test coverage.

type UpdateDataSourceParams

type UpdateDataSourceParams struct {
	Name          *string          `json:"name,omitempty"`
	Config        map[string]any   `json:"config,omitempty"`
	Status        *ConnectorStatus `json:"status,omitempty"`
	StatusMessage *string          `json:"status_message,omitempty"`
	LastTestedAt  *time.Time       `json:"last_tested_at,omitempty"`
	Environment   *string          `json:"environment,omitempty"`
}

type UpdateServerParams

type UpdateServerParams struct {
	DisplayName *string `json:"display_name,omitempty"`
}

UpdateServerParams defines the input for updating a server's user-facing fields.

type UpdateUserParams

type UpdateUserParams struct {
	DisplayName         *string   `json:"display_name,omitempty"`
	Role                *UserRole `json:"role,omitempty"`
	MCPEnabled          *bool     `json:"mcp_enabled,omitempty"`
	IsActive            *bool     `json:"is_active,omitempty"`
	AllowedEnvironments *[]string `json:"allowed_environments,omitempty"`
}

UpdateUserParams defines the input for updating a user.

type UpsertCodeEntityParams

type UpsertCodeEntityParams struct {
	EntityType CodeEntityType
	EntityName string
	Service    string
}

UpsertCodeEntityParams defines input for creating or updating a code entity.

type UptimeSummary

type UptimeSummary struct {
	HealthCheckID string  `json:"healthcheck_id"`
	Name          string  `json:"name"`
	URL           string  `json:"url"`
	CurrentStatus string  `json:"current_status"`
	UptimePct     float64 `json:"uptime_pct"`
	AvgResponseMs float64 `json:"avg_response_ms"`
	TotalChecks   int     `json:"total_checks"`
	DownChecks    int     `json:"down_checks"`
	Reliability   float64 `json:"reliability,omitempty"`
}

UptimeSummary aggregates uptime stats for a single health check.

type User

type User struct {
	bun.BaseModel       `bun:"table:users" json:"-"`
	ID                  string    `bun:"id,pk" json:"id"`
	Email               string    `bun:"email" json:"email"`
	PasswordHash        string    `bun:"password_hash" json:"-"`
	DisplayName         string    `bun:"display_name" json:"display_name"`
	Role                UserRole  `bun:"role" json:"role"`
	MCPEnabled          bool      `bun:"mcp_enabled" json:"mcp_enabled"`
	MCPToken            *string   `bun:"mcp_token" json:"mcp_token,omitempty"`
	IsActive            bool      `bun:"is_active" json:"is_active"`
	AllowedEnvironments []string  `bun:"-" json:"allowed_environments"`
	CreatedAt           time.Time `bun:"created_at" json:"created_at"`
	UpdatedAt           time.Time `bun:"updated_at" json:"updated_at"`
}

User represents an authenticated user.

AllowedEnvironments controls which envs this user's MCP token may read/write. Values:

  • []string{} — no scope granted; all env-scoped tool calls deny.
  • []string{"production"} — single-env scope; ResolveEnv auto-fills.
  • []string{"staging", "production"} — multi-env; explicit env arg required.
  • []string{"*"} — legacy wildcard; all envs, with deprecation fallback on writes (see internal/mcp/envscope.go).

type UserRole

type UserRole string

UserRole represents the access level of a user.

const (
	RoleAdmin  UserRole = "admin"
	RoleMember UserRole = "member"
)

type UserStore

type UserStore interface {
	Create(ctx context.Context, params CreateUserParams) (*User, error)
	GetByID(ctx context.Context, id string) (*User, error)
	GetByEmail(ctx context.Context, email string) (*User, error)
	GetByMCPToken(ctx context.Context, token string) (*User, error)
	List(ctx context.Context) ([]User, error)
	Update(ctx context.Context, id string, params UpdateUserParams) (*User, error)
	UpdatePassword(ctx context.Context, id string, passwordHash string) error
	UpdateMCPToken(ctx context.Context, id string, token string) error
	Delete(ctx context.Context, id string) error
	Count(ctx context.Context) (int, error)
}

UserStore manages user accounts.

type Watch

type Watch struct {
	bun.BaseModel       `bun:"table:watches" json:"-"`
	ID                  string          `bun:"id,pk" json:"id"`
	ConditionsJSON      json.RawMessage `bun:"conditions_json" json:"conditions"`
	Service             string          `bun:"service" json:"service,omitempty"`
	Endpoint            string          `bun:"endpoint" json:"endpoint,omitempty"`
	Environment         string          `bun:"environment" json:"environment,omitempty"`
	CommitHash          string          `bun:"commit_hash" json:"commit_hash,omitempty"`
	Duration            string          `bun:"duration" json:"duration"`
	Urgency             WatchUrgency    `bun:"urgency" json:"urgency"`
	CheckInterval       string          `bun:"check_interval" json:"check_interval"`
	BaselineWindow      string          `bun:"baseline_window" json:"baseline_window"`
	MinConsecutive      int             `bun:"min_consecutive" json:"min_consecutive"`
	Status              WatchStatus     `bun:"status" json:"status"`
	BaselineJSON        *WatchBaseline  `bun:"baseline_json" json:"baseline,omitempty"`
	ConsecutiveBreaches int             `bun:"consecutive_breaches" json:"consecutive_breaches"`
	CurrentValue        *float64        `bun:"current_value" json:"current_value,omitempty"`
	ExpiresAt           *time.Time      `bun:"expires_at" json:"expires_at,omitempty"`
	CreatedBy           string          `bun:"created_by" json:"created_by,omitempty"`
	SessionID           string          `bun:"session_id" json:"session_id,omitempty"`
	LastCheckedAt       *time.Time      `bun:"last_checked_at" json:"last_checked_at,omitempty"`
	NextCheckAt         *time.Time      `bun:"next_check_at" json:"next_check_at,omitempty"`
	CreatedAt           time.Time       `bun:"created_at" json:"created_at"`
	UpdatedAt           time.Time       `bun:"updated_at" json:"updated_at"`
}

Watch represents a metric threshold monitor using a JSON condition tree.

The ConditionsJSON field stores the full rule definition as a JSON condition tree which supports AND/OR/NOT combinators and multiple condition types (threshold, relative, delta, count). The Service, Endpoint, Environment, and CommitHash fields are kept for filtering/display and stream matching.

type WatchAlert

type WatchAlert struct {
	bun.BaseModel      `bun:"table:watch_alerts" json:"-"`
	ID                 string               `bun:"id,pk" json:"id"`
	WatchID            string               `bun:"watch_id" json:"watch_id"`
	RunID              string               `bun:"run_id" json:"run_id,omitempty"`
	Urgency            WatchUrgency         `bun:"urgency" json:"urgency"`
	Summary            string               `bun:"summary" json:"summary"`
	ConditionsSnapshot string               `bun:"conditions_snapshot" json:"conditions_snapshot"`
	EvidenceJSON       *WatchEvidenceBundle `bun:"evidence_json" json:"evidence,omitempty"`
	Status             string               `bun:"status" json:"status"`
	DismissReason      string               `bun:"dismiss_reason" json:"dismiss_reason,omitempty"`
	Environment        string               `bun:"environment" json:"environment,omitempty"`
	CreatedAt          time.Time            `bun:"created_at" json:"created_at"`
}

WatchAlert represents an alert generated by a watch breach. Environment is denormalized from the parent Watch at write time — notifiers carry it in their payload, and querying alerts by env doesn't need a join.

func (WatchAlert) ThresholdValue

func (a WatchAlert) ThresholdValue() float64

func (WatchAlert) TriggerMetric

func (a WatchAlert) TriggerMetric() string

Convenience accessors for backward-compatible reads from conditions_snapshot.

func (WatchAlert) TriggerValue

func (a WatchAlert) TriggerValue() float64

type WatchBaseline

type WatchBaseline struct {
	ErrorRate        float64                 `json:"error_rate"`
	AvgResponseMs    float64                 `json:"avg_response_ms"`
	P95ResponseMs    float64                 `json:"p95_response_ms"`
	LogCount         int                     `json:"log_count"`
	ErrorCount       int                     `json:"error_count"`
	SQLCount         float64                 `json:"sql_count"`
	CacheHitRate     float64                 `json:"cache_hit_rate"`
	ExceptionClasses []string                `json:"exception_classes,omitempty"`
	Endpoints        []WatchEndpointBaseline `json:"endpoints,omitempty"`
	CapturedAt       time.Time               `json:"captured_at"`
	WindowDuration   string                  `json:"window_duration"`
}

WatchBaseline holds a snapshot of baseline metrics at watch creation time.

type WatchBaselineDiff

type WatchBaselineDiff struct {
	MetricName    string  `json:"metric_name"`
	BaselineValue float64 `json:"baseline_value"`
	CurrentValue  float64 `json:"current_value"`
	DeltaPct      float64 `json:"delta_pct"`
}

WatchBaselineDiff shows overall metric drift from baseline.

type WatchEndpointBaseline

type WatchEndpointBaseline struct {
	Path          string  `json:"path"`
	AvgDurationMs float64 `json:"avg_duration_ms"`
	AvgSQLCount   float64 `json:"avg_sql_count"`
	RequestCount  int     `json:"request_count"`
}

WatchEndpointBaseline holds per-endpoint baseline stats.

type WatchEndpointDelta

type WatchEndpointDelta struct {
	Path               string  `json:"path"`
	CurrentDurationMs  float64 `json:"current_duration_ms"`
	BaselineDurationMs float64 `json:"baseline_duration_ms"`
	DeltaPct           float64 `json:"delta_pct"`
}

WatchEndpointDelta shows how an endpoint changed vs baseline.

type WatchEvidenceBundle

type WatchEvidenceBundle struct {
	RecentErrors      []WatchEvidenceError `json:"recent_errors,omitempty"`
	NewErrors         []WatchEvidenceError `json:"new_errors,omitempty"`
	AffectedEndpoints []WatchEndpointDelta `json:"affected_endpoints,omitempty"`
	RelevantLogs      []WatchEvidenceLog   `json:"relevant_logs,omitempty"`
	Timeline          []WatchTimelineEvent `json:"timeline,omitempty"`
	BaselineDiff      *WatchBaselineDiff   `json:"baseline_diff,omitempty"`
	SourceFiles       []string             `json:"source_files,omitempty"`
	TraceIDs          []string             `json:"trace_ids,omitempty"`
}

WatchEvidenceBundle contains all evidence collected when an alert fires.

type WatchEvidenceError

type WatchEvidenceError struct {
	ExceptionClass string `json:"exception_class"`
	Message        string `json:"message"`
	Count          int    `json:"count"`
	IsNew          bool   `json:"is_new"`
}

WatchEvidenceError represents an error found during investigation.

type WatchEvidenceLog

type WatchEvidenceLog struct {
	Timestamp time.Time `json:"timestamp"`
	Level     string    `json:"level"`
	Message   string    `json:"message"`
	Service   string    `json:"service,omitempty"`
	TraceID   string    `json:"trace_id,omitempty"`
}

WatchEvidenceLog represents a relevant log entry in evidence.

type WatchMetric

type WatchMetric string

WatchMetric identifies what the watch measures.

const (
	WatchMetricErrorRate    WatchMetric = "error_rate"
	WatchMetricResponseTime WatchMetric = "response_time"
	WatchMetricP95Response  WatchMetric = "p95_response"
	WatchMetricLogCount     WatchMetric = "log_count"
	WatchMetricErrorCount   WatchMetric = "error_count"
	WatchMetricHeartbeat    WatchMetric = "heartbeat"
	WatchMetricSQLCount     WatchMetric = "sql_count"
	WatchMetricCacheHitRate WatchMetric = "cache_hit_rate"
)

func ConditionsMetric

func ConditionsMetric(raw json.RawMessage) WatchMetric

ConditionsMetric extracts the primary metric from a simple single-condition watch. Returns an empty WatchMetric for compound conditions.

type WatchOperator

type WatchOperator string

WatchOperator defines comparison operators for watches.

const (
	WatchOpGreaterThan      WatchOperator = "gt"
	WatchOpGreaterThanEqual WatchOperator = "gte"
	WatchOpLessThan         WatchOperator = "lt"
	WatchOpLessThanEqual    WatchOperator = "lte"
	WatchOpEqual            WatchOperator = "eq"
	WatchOpNotEqual         WatchOperator = "neq"
)

type WatchRun

type WatchRun struct {
	bun.BaseModel `bun:"table:watch_runs" json:"-"`
	ID            string     `bun:"id,pk" json:"id"`
	WatchID       string     `bun:"watch_id" json:"watch_id"`
	Status        string     `bun:"status" json:"status"`
	MetricValue   *float64   `bun:"metric_value" json:"metric_value,omitempty"`
	Breached      bool       `bun:"breached" json:"breached"`
	Summary       string     `bun:"summary" json:"summary,omitempty"`
	ErrorMessage  string     `bun:"error_message" json:"error_message,omitempty"`
	Environment   string     `bun:"environment" json:"environment,omitempty"`
	StartedAt     time.Time  `bun:"started_at" json:"started_at"`
	FinishedAt    *time.Time `bun:"finished_at" json:"finished_at,omitempty"`
}

WatchRun represents a single evaluation of a watch. Environment is denormalized from the parent Watch at write time so listing runs by env avoids a join.

type WatchStatus

type WatchStatus string

WatchStatus represents the lifecycle state of a watch.

const (
	WatchStatusActive    WatchStatus = "active"
	WatchStatusTriggered WatchStatus = "triggered"
	WatchStatusResolved  WatchStatus = "resolved"
	WatchStatusExpired   WatchStatus = "expired"
)

type WatchStore

type WatchStore interface {
	Create(ctx context.Context, params CreateWatchParams) (*Watch, error)
	GetByID(ctx context.Context, id string) (*Watch, error)
	List(ctx context.Context, params ListWatchParams) ([]Watch, error)
	UpdateStatus(ctx context.Context, id string, status WatchStatus) error
	UpdateAfterCheck(ctx context.Context, id string, value float64, breaches int, nextCheck time.Time) error
	UpdateBaseline(ctx context.Context, id string, baseline *WatchBaseline) error
	Delete(ctx context.Context, id string) error
	GetDueWatches(ctx context.Context) ([]Watch, error)
	ExpireWatches(ctx context.Context) (int, error)
	CreateRun(ctx context.Context, watchID string) (*WatchRun, error)
	CompleteRun(ctx context.Context, id string, value float64, breached bool, summary string) error
	FailRun(ctx context.Context, id string, errMsg string) error
	ListRuns(ctx context.Context, watchID string, limit int) ([]WatchRun, error)
	CreateAlert(ctx context.Context, params CreateWatchAlertParams) (*WatchAlert, error)
	GetAlert(ctx context.Context, id string) (*WatchAlert, error)
	ListAlerts(ctx context.Context, watchID string, status string, limit int) ([]WatchAlert, error)
	DismissAlert(ctx context.Context, id string, reason string) error
	AcknowledgeAlert(ctx context.Context, id string) error
	CountPendingAlerts(ctx context.Context) (int, error)
}

WatchStore manages agent-first watches (Phase 1).

type WatchTimelineEvent

type WatchTimelineEvent struct {
	Timestamp time.Time `json:"timestamp"`
	Event     string    `json:"event"`
	Value     *float64  `json:"value,omitempty"`
}

WatchTimelineEvent marks a point in the alert timeline.

type WatchUrgency

type WatchUrgency string

WatchUrgency represents alert urgency for a watch.

const (
	WatchUrgencyLow      WatchUrgency = "low"
	WatchUrgencyNormal   WatchUrgency = "normal"
	WatchUrgencyHigh     WatchUrgency = "high"
	WatchUrgencyCritical WatchUrgency = "critical"
)

Jump to

Keyboard shortcuts

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