Documentation
¶
Overview ¶
Package monitor finds what needs an admin – expiring certificates, CA certificates and CRLs, a sealed server, silent agents, failed deployments – keeps it as alerts in system.db and (step 23) tells someone about it (docs/PHASE3.md §9). Everything here works while the server is sealed: it reads pki.db and the keyring state and decrypts nothing.
Index ¶
- Constants
- type Agents
- type Alert
- type Changes
- type DigestOptions
- type Engine
- type Evaluator
- type Finding
- type Rules
- type Store
- func (s *Store) Digest(ctx context.Context, now time.Time, opt DigestOptions) (notify.Digest, error)
- func (s *Store) List(ctx context.Context, who keys.Who, now time.Time) (open, resolved []Alert, err error)
- func (s *Store) Open(ctx context.Context) ([]Alert, error)
- func (s *Store) Prune(ctx context.Context, cutoff time.Time) (int64, error)
- func (s *Store) Since(ctx context.Context, since time.Time) ([]Alert, error)
- func (s *Store) Sync(ctx context.Context, now time.Time, findings []Finding) (Changes, error)
Constants ¶
const ( Warning = "warning" Critical = "critical" )
Severities of an alert.
const ( KindCertExpiry = "cert_expiry" KindCAExpiry = "ca_expiry" KindCRL = "crl" KindSealed = "sealed" KindAgentSilent = "agent_silent" KindAgentCertificate = "agent_certificate" KindDeployFailed = "deploy_failed" )
Kinds of alerts (docs/PHASE3.md §9.2).
const ResolvedWindow = 7 * 24 * time.Hour
ResolvedWindow is how long a resolved alert stays on the Alerts page and in the API (it is kept 30 days, see internal/server/monitor.go).
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Agents ¶
type Agents interface {
ListAgents(ctx context.Context, who keys.Who) ([]agents.Agent, error)
GetAgent(ctx context.Context, who keys.Who, id string) (*agents.Agent, error)
}
Agents is what the evaluation reads about agents; nil when the agent listener is off.
type Alert ¶
type Alert struct {
ID, Key, Kind, Subject, Severity, Detail, Href string
FirstSeen, LastSeen time.Time
Resolved time.Time // zero while open
NotifiedSeverity string // "" = not reported yet
Notified time.Time
}
Alert is one row of the alerts table.
type Changes ¶
type Changes struct {
Opened, Raised, Lowered, Resolved []Alert
}
Changes is what one Sync changed – for the log; notifications read the notified_* columns, so a lost Changes value loses no message.
type DigestOptions ¶
type DigestOptions struct {
Server string // host name in the subject
RepeatEvery time.Duration // reminder for an alert still open
Link func(string) string // UI path → absolute link; nil = none
Channels []string // queue one message per channel
}
DigestOptions shape the digest of one evaluation.
type Engine ¶
type Engine interface {
Certificates(ctx context.Context, who keys.Who, f ca.CertificateFilter) (*ca.CertificatePage, error)
Certificate(ctx context.Context, who keys.Who, id string) (*ca.CertificateInfo, error)
CAs(ctx context.Context, who keys.Who) ([]ca.CAInfo, error)
}
Engine is what the evaluation reads from the CA engine.
type Evaluator ¶
type Evaluator struct {
Engine Engine
Agents Agents // nil = no agent rules
Seal func() keys.Status
Rules Rules
Who keys.Who // a system principal that may read the whole tenant
}
Evaluator finds the conditions of docs/PHASE3.md §9.2.
type Finding ¶
type Finding struct {
Key, Kind, Subject, Severity, Detail, Href string
}
Finding is one condition the evaluation found. Key is stable across runs (kind and the ID of what it is about), so the store can tell new, changed and gone conditions apart.
type Rules ¶
type Rules struct {
// End-entity certificates: warning and critical before they expire.
ExpiryWarn, ExpiryCrit time.Duration
// CA certificates.
CAWarn, CACrit time.Duration
// A sealed server: warning after SealedAfter; critical once a CRL's
// next update is closer than CRLHorizon (a sealed server can't sign).
SealedAfter, CRLHorizon time.Duration
// Agents: warning and critical after this long without a report.
AgentSilentWarn, AgentSilentCrit time.Duration
// An active agent's own certificate: critical below this.
AgentCertificate time.Duration
// ExpiredFor: an expired, not superseded certificate stays an alert this
// long after its end, then the alert is closed.
ExpiredFor time.Duration
// RepeatEvery: a reminder for an open alert (step 23).
RepeatEvery time.Duration
}
Rules are the thresholds of the evaluation (configuration `monitor:`).
func DefaultRules ¶
func DefaultRules() Rules
DefaultRules are the owner-approved defaults (Q7, 2026-10-29).
type Store ¶
type Store struct {
DB *sql.DB // system.db, the write connection
Tenant string
Rand io.Reader // nil = crypto/rand (IDs)
}
Store keeps the alerts of one tenant in system.db.
func (*Store) Digest ¶
func (s *Store) Digest(ctx context.Context, now time.Time, opt DigestOptions) (notify.Digest, error)
Digest collects what to report since the last digest – new alerts, alerts that became critical, reminders, resolved alerts whose opening was reported – marks them and queues one message per channel, all in one transaction. It returns the digest (no events = nothing queued). Without channels nothing is marked: once a channel is configured, the first message lists every open alert.
func (*Store) List ¶
func (s *Store) List(ctx context.Context, who keys.Who, now time.Time) (open, resolved []Alert, err error)
List is what the Alerts page and GET /alerts show to who: the open alerts (critical first, then the oldest) and those resolved within ResolvedWindow (newest first). Alerts name certificates, CAs and hosts of the whole tenant, so it needs the tenant-wide read role (viewer); a role limited to one CA does not see them.