config

package
v0.6.1 Latest Latest
Warning

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

Go to latest
Published: Jul 3, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Overview

Package config defines RunLore's configuration, including provider wiring and the trigger policy that decides which incidents start an investigation.

The trigger policy is what keeps RunLore from firing on every alert: it filters incidents by environment, severity, namespace/team/label, and dedups still-firing alerts — controlling noise, relevance, and LLM cost.

Index

Constants

View Source
const (
	NetworkHubble          = "hubble"            // Cilium Hubble Relay (requires the Cilium CNI)
	NetworkAWSVPCFlowLogs  = "aws-vpc-flow-logs" // AWS VPC Flow Logs via CloudWatch Logs (any AWS VPC; CNI-agnostic)
	NetworkGCPFirewallLogs = "gcp-firewall-logs" // GCP Firewall Rules Logging via Cloud Logging (any GCP VPC; CNI-agnostic)
)

Network provider identifiers for config.network.provider. The network signal is PLUGGABLE and assumes no particular CNI — pick the one matching your environment.

Variables

This section is empty.

Functions

func ValidateEffort added in v0.3.0

func ValidateEffort(field, provider, effort string) error

ValidateEffort checks an effective (provider, effort) pair against the per-provider effort vocabulary, so callers that build a ModelProvider outside config.Load (e.g. the eval model-comparison runner) share one source of truth. field names the setting in the returned error. Empty effort is always valid.

Types

type AWSFlowCfg

type AWSFlowCfg struct {
	Region   string `yaml:"region"`    // AWS region (default: AWS_REGION / IMDS)
	LogGroup string `yaml:"log_group"` // CloudWatch Logs group that receives the VPC Flow Logs (required)
}

AWSFlowCfg configures the AWS VPC Flow Logs network provider. Auth is in-cluster identity (EKS Pod Identity / IRSA) via the AWS default credential chain.

type ActionAllow

type ActionAllow struct {
	ReversibleOnly      bool     `yaml:"reversible_only"`      // never auto-apply irreversible actions
	Namespaces          []string `yaml:"namespaces"`           // allowlist of target namespaces; empty = no executable target permitted
	ProtectedNamespaces []string `yaml:"protected_namespaces"` // never an action target (added to the built-ins flux-system, kube-system)
	MaxBlastRadius      int      `yaml:"max_blast_radius"`     // cap on affected workloads
	Kinds               []string `yaml:"kinds"`                // resource kinds that may be acted on
}

ActionAllow bounds what may be acted on, even in approve/auto modes. Irreversibility is the trip-wire for mandatory human approval.

type ActionMode

type ActionMode string

ActionMode controls how far RunLore may go when acting on the cluster. Default (zero value) is read-only.

const (
	ActionOff     ActionMode = "off"     // read-only (default): no action tools registered
	ActionSuggest ActionMode = "suggest" // propose a command/PR; never execute
	ActionApprove ActionMode = "approve" // execute only after explicit human approval
	ActionAuto    ActionMode = "auto"    // EXPERIMENTAL/frozen (FEAT-1): execute in-envelope, no click — not for prod
)

Action modes, from read-only to autonomous.

type ActionPolicy

type ActionPolicy struct {
	Mode             ActionMode  `yaml:"mode"`               // off | suggest | approve | auto (experimental, frozen)
	Allow            ActionAllow `yaml:"allow"`              // envelope, enforced even in approve/auto
	RequireApproval  bool        `yaml:"require_approval"`   // force a human click for gated actions
	ApprovalTokenEnv string      `yaml:"approval_token_env"` // env var with a shared secret for the approval endpoints
	AuditLogPath     string      `yaml:"audit_log_path"`     // append-only, hash-chained action audit log (required for auto)
	Auto             AutoPolicy  `yaml:"auto"`               // rung-3 unattended-execution safety controls
}

ActionPolicy gates cluster-mutating actions — the upper rungs of the autonomy ladder. v1 ships ActionOff; the type exists so active tools can be added later behind a gate without re-architecting (see docs/design.md §9, "Act").

func (ActionPolicy) Enabled

func (a ActionPolicy) Enabled() bool

Enabled reports whether any cluster-mutating action is permitted.

type AutoPolicy

type AutoPolicy struct {
	DryRun        bool     `yaml:"dry_run"`        // log "would execute" without executing
	MinConfidence float64  `yaml:"min_confidence"` // only auto-execute when the investigation is at least this confident
	MaxPerWindow  int      `yaml:"max_per_window"` // rate limit; 0 = unlimited (not recommended)
	Window        Duration `yaml:"window"`         // rate-limit window (default 1h)
}

AutoPolicy bounds unattended execution (mode "auto"). Even within these, auto only ever runs REVERSIBLE actions, and every decision is audited + delivered.

type Catalog

type Catalog struct {
	Dir           string        `yaml:"dir"` // OKF bundle path (mounted ConfigMap, or the git-sync mirror)
	Git           CatalogGit    `yaml:"git"`
	InstantRecall InstantRecall `yaml:"instant_recall"`
}

Catalog configures the OKF knowledge catalog read by the agent. Provide either a mounted Dir (e.g. a ConfigMap) or a Git repo to sync (which closes the read/write loop — the curator's merged PRs flow back into what the agent reads).

type CatalogGit

type CatalogGit struct {
	URL      string   `yaml:"url"`       // repo to clone/pull; empty disables git-sync
	Branch   string   `yaml:"branch"`    // default "main"
	Interval Duration `yaml:"interval"`  // re-sync period (default 5m)
	TokenEnv string   `yaml:"token_env"` // env var with a read token (empty = anonymous/public)
}

CatalogGit configures periodic Git sync of the catalog into Dir.

type Cloud

type Cloud struct {
	Provider    string `yaml:"provider"`     // "" (disabled) | "aws"
	Region      string `yaml:"region"`       // e.g. eu-west-3 (default: AWS_REGION / IMDS)
	ClusterName string `yaml:"cluster_name"` // EKS cluster name, scopes nodegroup/ASG queries
}

Cloud configures the cloud context provider. Auth is in-cluster identity (EKS Pod Identity / IRSA) via the AWS SDK's default credential chain — no static keys. Empty Provider disables the cloud tools (default — cloud is opt-in).

type Coalesce

type Coalesce struct {
	Enabled           bool     `yaml:"enabled"`
	Debounce          Duration `yaml:"debounce"`
	MaxWait           Duration `yaml:"max_wait"`
	MaxBatch          int      `yaml:"max_batch"`
	Cooldown          Duration `yaml:"cooldown"`
	CorrelationLabels []string `yaml:"correlation_labels"` // empty ⇒ AM groupKey, else namespace+label values
}

Coalesce folds correlated incidents into one investigation.

type Config

type Config struct {
	GitOps   GitOps        `yaml:"gitops"` // engine selection (flux default | argocd)
	Triggers TriggerPolicy `yaml:"triggers"`

	// Sources is the per-source enablement map: a key under `sources.<name>`
	// enables that source adapter, and its value is the adapter's own raw config
	// (decoded lazily by each adapter's Build). Presence is enablement — e.g.
	// `sources.alertmanager: {}` turns on the Alertmanager webhook source. This
	// keeps adding a source from requiring a central-struct edit. The webhook
	// auth token stays server-level (server.webhook_token_env).
	Sources map[string]yaml.Node `yaml:"sources"`

	Actions ActionPolicy `yaml:"actions"` // read-only by default; the upper rungs of the autonomy ladder
	Forge   Forge        `yaml:"forge"`   // git-forge auth (GitHub App) for diff access + curation
	Curate  Curate       `yaml:"curate"`  // Phase-2 backlog groomer settings
	Model   Model        `yaml:"model"`   // optional; when BaseURL is set, serve uses the LLM investigator
	Notify  Notify       `yaml:"notify"`  // chat delivery for findings
	Catalog Catalog      `yaml:"catalog"` // OKF knowledge catalog
	Outcome Outcome      `yaml:"outcome"` // learning-loop outcome ledger

	LeaderElection LeaderElection `yaml:"leader_election"` // HA: only the leader investigates

	Metrics Endpoint `yaml:"metrics"` // PromQL backend (VictoriaMetrics/Prometheus) for query_metrics
	Logs    Endpoint `yaml:"logs"`    // LogsQL backend (VictoriaLogs) for query_logs
	Network Network  `yaml:"network"` // network-flow data source (pluggable, CNI-agnostic); empty Provider disables it
	Cloud   Cloud    `yaml:"cloud"`   // cloud-side context (AWS); empty Provider disables it
	MCP     MCP      `yaml:"mcp"`     // external MCP servers whose tools the agent may call (opt-in)

	Server ServerConfig `yaml:"server"` // HTTP ingress (webhook authentication)

	Investigation Investigation `yaml:"investigation"` // coalescing + rate-limit + per-investigation token controls
	Telemetry     Telemetry     `yaml:"telemetry"`     // OpenTelemetry metrics
	Logging       Logging       `yaml:"logging"`       // structured-logging format + verbosity
}

Config is the top-level RunLore configuration (loaded from YAML).

func Load

func Load(path string) (*Config, error)

Load reads, strictly parses, and validates a RunLore config file. Unknown keys are rejected (KnownFields) so a typo in a safety-critical field — e.g. an autonomy gate — fails loudly instead of being silently ignored.

func (*Config) Validate

func (c *Config) Validate() error

Validate enforces cross-field invariants after loading — fail-closed defaults for the autonomy ladder: enabling execution requires the controls that bound it. Returns an error that should abort startup.

type Curate

type Curate struct {
	StaleAfter          Duration `yaml:"stale_after"`          // close unprotected KB PRs idle longer than this; 0 disables (default 720h)
	RecurrenceThreshold int      `yaml:"recurrence_threshold"` // open a knowledge-gap issue after this many unresolved occurrences of a pattern; 0 ⇒ default 3
}

Curate configures the Phase-2 backlog groomer (lore curate).

type Dedup

type Dedup struct {
	Window Duration `yaml:"window"`
}

Dedup suppresses re-investigation of a still-firing alert within Window.

type Duration

type Duration time.Duration

Duration is a time.Duration that unmarshals from a Go duration string ("30m").

func (Duration) Std

func (d Duration) Std() time.Duration

Std returns the standard library duration.

func (*Duration) UnmarshalYAML

func (d *Duration) UnmarshalYAML(value *yaml.Node) error

UnmarshalYAML parses a duration string such as "30m" or "1h30m".

type Embeddings

type Embeddings struct {
	BaseURL   string `yaml:"base_url"`
	Model     string `yaml:"model"`
	APIKeyEnv string `yaml:"api_key_env"`
}

Embeddings configures an OpenAI-compatible /embeddings endpoint (vLLM/Ollama/ OpenAI) for hybrid catalog recall — served by the same kind of endpoint as the model; keyless when APIKeyEnv is empty.

type Endpoint

type Endpoint struct {
	URL string `yaml:"url"`

	// TokenEnv names an env var holding a bearer token for the backend. When set
	// and the var is non-empty, requests carry "Authorization: Bearer <token>".
	// Empty (default) ⇒ no Authorization header (unchanged, keyless behaviour).
	TokenEnv string `yaml:"token_env"`

	// Headers are static request headers added to every backend request — e.g. a
	// tenant header for a multi-tenant VictoriaMetrics/VictoriaLogs instance
	// ("X-Scope-OrgID: <tenant>"). Empty (default) ⇒ no extra headers.
	Headers map[string]string `yaml:"headers"`
}

Endpoint is a backend base URL with optional auth; empty URL disables the corresponding tool. Auth follows the secrets-by-indirection convention used elsewhere (model.api_key_env, forge.*_env): the config stores the NAME of an env var, never the secret itself, and the value is read at runtime.

type Forge

type Forge struct {
	GitHubApp     GitHubApp `yaml:"github_app"`
	KBRepo        string    `yaml:"kb_repo"`        // "owner/name" — the catalog repo for curation
	BaseBranch    string    `yaml:"base_branch"`    // PR target branch (default "main")
	GitHubAPIURL  string    `yaml:"github_api_url"` // override for GHES/tests (default https://api.github.com)
	DupScore      float64   `yaml:"dup_score"`      // file-time catalog BM25 dedup threshold (default 5.0)
	MinConfidence float64   `yaml:"min_confidence"` // file-time quality gate: min overall confidence (default 0.75)
}

Forge holds git-forge authentication and the curation target repo.

type GCPFlowCfg

type GCPFlowCfg struct {
	Project string `yaml:"project"` // GCP project ID (default: ADC / metadata server)
}

GCPFlowCfg configures the GCP Firewall Rules Logging network provider. Auth is Workload Identity / Application Default Credentials.

type GitHubApp

type GitHubApp struct {
	AppID          int64  `yaml:"app_id"`
	InstallationID int64  `yaml:"installation_id"`
	PrivateKeyRef  string `yaml:"private_key_ref"` // Secret name/key (e.g. via External Secrets)
	PrivateKeyEnv  string `yaml:"private_key_env"` // v1: env var holding the PEM private key
}

GitHubApp holds GitHub App credentials. The private key mints 1-hour installation tokens (no long-lived PAT); it is referenced from a Secret, never inlined. Required permissions: contents:read (diff), and on the KB repo issues:write + pull_requests:write + contents:write (curation).

type GitOps

type GitOps struct {
	Engine string `yaml:"engine"` // "flux" (default) | "argocd"
}

GitOps selects the GitOps engine RunLore reads (what-changed + failure watch).

type GitOpsFailureTrigger

type GitOpsFailureTrigger struct {
	// Debounce is a pointer so an unset key (nil ⇒ 60s default, applied in
	// applyDefaults) is distinguishable from an explicit `debounce: 0` (fire
	// immediately). A plain Duration can't tell the two apart — both are the zero
	// value — which is why `debounce: 0` used to be silently clobbered to 60s.
	Debounce *Duration `yaml:"debounce"`
}

GitOpsFailureTrigger holds the GitOps-failure-driven investigation POLICY. Enablement now lives under `sources.gitops.enabled`; this struct keeps only the debounce window. Debounce delays an investigation until the failure has persisted for that window (re-checked still Ready=False), filtering reconcile-churn transients that would otherwise produce confident-but-wrong root causes. A zero Debounce fires immediately on every Ready=False (the original behavior).

func (GitOpsFailureTrigger) DebounceWindow

func (g GitOpsFailureTrigger) DebounceWindow() time.Duration

DebounceWindow is the GitOps-failure debounce window. nil (unset) reads as 0 here, but applyDefaults fills an unset trigger with 60s; an explicit 0 means fire immediately on every Ready=False.

type HubbleCfg

type HubbleCfg struct {
	URL string `yaml:"url"` // Hubble Relay gRPC address (host:port), e.g. hubble-relay.kube-system:80
}

HubbleCfg configures the Cilium Hubble Relay network provider.

type IncidentMatch

type IncidentMatch struct {
	Severity    []string          `yaml:"severity"`    // e.g. [critical]
	Environment []string          `yaml:"environment"` // e.g. [prod]
	Namespaces  []string          `yaml:"namespaces"`  // glob patterns
	AlertNames  []string          `yaml:"alertnames"`  // glob patterns
	Labels      map[string]string `yaml:"labels"`      // arbitrary label matchers
}

IncidentMatch is a set of matchers ANDed together; empty fields match anything.

type IncidentTrigger

type IncidentTrigger struct {
	Match  IncidentMatch `yaml:"match"`  // must match to investigate
	Ignore IncidentMatch `yaml:"ignore"` // excludes even if Match passes
	Dedup  Dedup         `yaml:"dedup"`
	// Debounce is the pre-investigation hold for a firing alert: after admission
	// (match + dedup) RunLore waits this long and investigates only if the alert
	// is still active — i.e. no matching Alertmanager `resolved` webhook arrived
	// within the window. It filters self-resolving alerts (e.g. a
	// KubeDaemonSetRolloutStuck during a Karpenter node-churn cycle) that would
	// otherwise burn a full investigation on noise. A zero window (the default)
	// disables the hold and investigates immediately, preserving today's behavior;
	// it is opt-in per deployment. It composes with `coalesce` (which batches the
	// survivors afterwards) and `dedup` (which still suppresses re-fires before the
	// hold begins).
	Debounce Duration `yaml:"debounce"`
}

IncidentTrigger holds the incident/alert MATCH policy. Enablement of the alertmanager source now lives under `sources.alertmanager`; this struct is purely the match/ignore/dedup criteria applied to admitted alerts.

func (IncidentTrigger) MatchFields added in v0.2.0

func (t IncidentTrigger) MatchFields(title, severity, environment, namespace string, labels map[string]string) bool

MatchFields reports whether an incident passes this trigger policy: matched by Match and not excluded by a non-empty Ignore. Enablement is the source's job (sources.alertmanager); matching here is purely criteria. title is the alertname.

type InstantRecall

type InstantRecall struct {
	Enabled              bool    `yaml:"enabled"`
	MinScore             float64 `yaml:"min_score"`              // similarity floor for the top hit
	MarginGap            float64 `yaml:"margin_gap"`             // top hit must beat the runner-up by at least this
	SoloFloor            float64 `yaml:"solo_floor"`             // confident bar when there is only one hit (higher than MinScore)
	RequireWorkloadMatch bool    `yaml:"require_workload_match"` // true = exact namespace+workload; false = namespace-level agreement is enough
	OutcomePrior         float64 `yaml:"outcome_prior"`          // Beta prior strength for outcome decay
	OutcomeFloor         float64 `yaml:"outcome_floor"`          // reject a recall when the outcome factor drops below this

	// Hybrid switches recall to fused BM25 + embedding retrieval, gated on COSINE
	// similarity instead of the BM25 score above. Requires model.embeddings to be
	// configured (else recall stays BM25). EXPERIMENTAL — tune the cosine thresholds
	// against the instant-recall eval before relying on it; the defaults are
	// conservative placeholders, not measured values.
	Hybrid          bool    `yaml:"hybrid"`            // enable hybrid (cosine-gated) recall
	HybridMinScore  float64 `yaml:"hybrid_min_score"`  // cosine floor for the top hit (default 0.80)
	HybridMarginGap float64 `yaml:"hybrid_margin_gap"` // cosine margin over the runner-up (default 0.05)
}

InstantRecall short-circuits the investigation loop when the catalog has a high-confidence match for the symptom. Off by default; MinScore is the BM25 relevance floor (tune for your catalog).

type Investigation

type Investigation struct {
	Coalesce                  Coalesce  `yaml:"coalesce"`
	RateLimit                 RateLimit `yaml:"rate_limit"`
	MaxSteps                  int       `yaml:"max_steps"`                    // 0 ⇒ loop default (20)
	MaxToolOutputBytes        int       `yaml:"max_tool_output_bytes"`        // 0 ⇒ unlimited
	MaxTokensPerInvestigation int       `yaml:"max_tokens_per_investigation"` // 0 ⇒ unlimited
	Timeout                   Duration  `yaml:"timeout"`                      // per-investigation deadline; 0 ⇒ default (10m) via applyDefaults
	ToolTimeout               Duration  `yaml:"tool_timeout"`                 // per-TOOL-call timeout so one hung tool can't eat the budget; 0 ⇒ default (60s) at construction

	// Compaction selects how mid-loop history compaction treats the tool outputs it
	// elides once the estimate crosses the compaction target. "" / "elide" is the
	// default: drop their bodies for short markers (lossy). "summarize" first asks a
	// model (the verify-tier model when configured, else the main model) for one
	// compact factual digest of the batch and keeps that in place of the markers,
	// falling back to plain elision on any summarizer error/refusal/truncation.
	Compaction string `yaml:"compaction"` // "" | "elide" (default) | "summarize"

	// PodLogNamespaces lists extra namespaces (beyond the incident's own) that
	// pod_logs may read controller/crash logs from. pod_logs streams raw pod logs
	// (which carry secrets/PII) to the external LLM, so the model is constrained to
	// the incident namespace plus this allowlist at the application layer — not just
	// by Kubernetes RBAC. Set this to match the Helm rbac.controllerLogNamespaces
	// (e.g. [flux-system]); empty means the incident namespace only.
	PodLogNamespaces []string `yaml:"pod_log_namespaces"`

	// ProgressUpdates opts into interim progress notifications during a long
	// investigation. Off by default (zero behaviour change, zero extra model calls).
	ProgressUpdates ProgressUpdates `yaml:"progress_updates"`
}

Investigation holds cost/throughput controls on the alert→investigation→LLM path.

type LeaderElection

type LeaderElection struct {
	Enabled bool   `yaml:"enabled"`
	Name    string `yaml:"name"` // Lease name (default "runlore-leader")
}

LeaderElection configures high availability. When enabled, replicas elect a leader via a Lease; only the leader runs the informer watch + investigation queue and reports ready (so the Service routes webhooks to it). Run >1 replica for failover. Disabled by default (single-replica / local).

type Logging

type Logging struct {
	Format string `yaml:"format"` // "text" (default) | "json"
	Level  string `yaml:"level"`  // "debug" | "info" (default) | "warn" | "error"
}

Logging configures the structured logger. Format selects human-readable text (default, for local CLI) or JSON (for in-cluster log aggregation). Level sets verbosity. Both are overridable at startup via RUNLORE_LOG_FORMAT / RUNLORE_LOG_LEVEL (see internal/logging).

type MCP added in v0.3.0

type MCP struct {
	Servers []MCPServer `yaml:"servers"`
}

MCP configures outbound connections to external MCP servers whose tools the investigation loop may call. Empty Servers disables it (the default — MCP is opt-in).

type MCPServer added in v0.3.0

type MCPServer struct {
	Name     string `yaml:"name"` // identifier; namespaces its tools as name__tool
	Endpoint `yaml:",inline"`
}

MCPServer is one external MCP server reachable over streamable-HTTP.

type MatrixNotify

type MatrixNotify struct {
	Homeserver     string `yaml:"homeserver"`
	RoomID         string `yaml:"room_id"`
	AccessTokenEnv string `yaml:"access_token_env"` // env var holding the access token
}

MatrixNotify configures Matrix delivery.

type Model

type Model struct {
	Provider  string `yaml:"provider"`    // "openai" (default) | "anthropic" | "gemini"
	BaseURL   string `yaml:"base_url"`    // OpenAI: required; Anthropic/Gemini: optional (built-in default endpoint). Must be https when api_key_env is set on a public host (validated).
	Model     string `yaml:"model"`       // model name
	APIKeyEnv string `yaml:"api_key_env"` // env var holding the API key (empty = keyless)
	// MaxTokens caps the model's output (generated) tokens per request. 0 = use the
	// 8192 default. Streaming providers send it (Anthropic max_tokens, OpenAI
	// max_tokens, Gemini generationConfig.maxOutputTokens); a too-low value truncates.
	MaxTokens int `yaml:"max_tokens"`
	// Effort opts into deeper model reasoning per request. Provider-specific
	// vocabulary, validated at startup: anthropic low|medium|high|max (sent as
	// output_config.effort), openai minimal|low|medium|high (sent as
	// reasoning_effort). Empty = omitted from requests (today's behavior). Not
	// supported for provider gemini (its thinkingConfig has replay semantics —
	// thought signatures — the provider-agnostic history can't carry). Models that
	// don't support the knob return a 400, which is classified permanent.
	Effort string `yaml:"effort"`
	// Thinking opts into adaptive extended thinking, sent as thinking:{type:"adaptive"}.
	// Only value is "adaptive"; only supported for provider anthropic (the client
	// replays the signed thinking blocks across the tool loop). Empty = omitted from
	// requests (today's behavior, byte-for-byte). Validated at startup; any other value
	// or any non-anthropic provider is a clear config error. Interacts with effort:
	// both may be set (effort is soft guidance for how much thinking Claude does).
	// Give max_tokens headroom — thinking consumes output tokens.
	Thinking string `yaml:"thinking"`
	// Verify optionally routes the adversarial verify pass to a cheaper/faster model;
	// unset fields inherit from the parent above (so `verify: {model: <cheap>}` reuses
	// the same provider/endpoint/key). Absent ⇒ verify runs on the main model.
	Verify *ModelOverride `yaml:"verify"`
	// Embeddings optionally configures an OpenAI-compatible /embeddings endpoint used
	// for hybrid recall (instant_recall.hybrid). Unset ⇒ BM25-only recall.
	Embeddings *Embeddings `yaml:"embeddings"`
	// Pricing optionally sets token rates so RunLore can estimate and report a
	// per-investigation cost. Unset ⇒ token totals are reported without a dollar
	// figure. Rates are validated non-negative.
	Pricing *Pricing `yaml:"pricing"`
}

Model configures the LLM used for investigation. Provider selects the wire protocol: "openai" (default, OpenAI-compatible: vLLM/Ollama/OpenAI) or "anthropic" (native Messages API). When unconfigured, serve uses the log-only investigator.

type ModelOverride

type ModelOverride struct {
	Provider  string `yaml:"provider"`
	BaseURL   string `yaml:"base_url"`
	Model     string `yaml:"model"`
	APIKeyEnv string `yaml:"api_key_env"`
	// MaxTokens overrides the parent's effective output-token cap for the verify pass;
	// 0 inherits the parent's effective value.
	MaxTokens int `yaml:"max_tokens"`
	// Effort overrides the parent's effort for the verify pass; empty inherits the
	// parent's value (same vocabulary and validation as model.effort).
	Effort string `yaml:"effort"`
	// Thinking overrides the parent's thinking mode for the verify pass; empty inherits
	// the parent's value (same vocabulary and validation as model.thinking). Note the
	// verify pass always forces a tool_choice, so the Anthropic client drops thinking
	// for that request anyway — this knob only affects any non-forced verify calls.
	Thinking string `yaml:"thinking"`
	// Pricing overrides the parent's token rates for the verify pass (a cheaper
	// verify model has its own cost); nil inherits model.pricing.
	Pricing *Pricing `yaml:"pricing"`
}

ModelOverride is a partial Model used to route the verify pass to a cheaper model; empty fields inherit from the parent Model.

type Network

type Network struct {
	Provider string     `yaml:"provider"` // "" (disabled) | hubble | aws-vpc-flow-logs | gcp-firewall-logs
	Hubble   HubbleCfg  `yaml:"hubble"`   // when provider=hubble
	AWS      AWSFlowCfg `yaml:"aws"`      // when provider=aws-vpc-flow-logs
	GCP      GCPFlowCfg `yaml:"gcp"`      // when provider=gcp-firewall-logs

	// URL keeps the pre-pluggable `network: {url: ...}` shape working: a bare url with
	// no provider is treated as Hubble (with a deprecation warning at wiring time).
	URL string `yaml:"url"`
}

Network configures the network-flow data source backing the network_drops tool. The signal is pluggable and CNI-agnostic: RunLore does NOT assume Cilium (or any particular CNI). Empty Provider disables the tool (the default — network is opt-in).

func (*Network) UnmarshalYAML

func (n *Network) UnmarshalYAML(value *yaml.Node) error

UnmarshalYAML decodes the Network block and applies the legacy back-compat mapping: a bare `network: {url: ...}` (the old Hubble-only shape) becomes provider=hubble.

type Notify

type Notify struct {
	Slack  SlackNotify          `yaml:"slack"`
	Matrix MatrixNotify         `yaml:"matrix"`
	Extra  map[string]yaml.Node `yaml:",inline"` // notify.<name> blocks for registered (non-built-in) notifiers
}

Notify configures where investigation findings are delivered.

type Outcome

type Outcome struct {
	LedgerPath string `yaml:"ledger_path"` // append-only JSONL path (e.g. the git-sync mirror PV); empty disables
}

Outcome configures the learning-loop outcome ledger.

type Pricing added in v0.3.0

type Pricing struct {
	InputUSDPerMTok       float64 `yaml:"input_usd_per_mtok"`
	OutputUSDPerMTok      float64 `yaml:"output_usd_per_mtok"`
	CachedInputUSDPerMTok float64 `yaml:"cached_input_usd_per_mtok"`
}

Pricing sets model token rates in USD per MILLION tokens, used to estimate a per-investigation cost. All rates are optional and default to 0; a rate must be non-negative.

type ProgressUpdates added in v0.3.0

type ProgressUpdates struct {
	Enabled    bool `yaml:"enabled"`
	EverySteps int  `yaml:"every_steps"` // emit a ping every N steps; 0 ⇒ default 5 (applyDefaults). Must be > 0 when enabled.
}

ProgressUpdates configures opt-in interim progress notifications: a long investigation (up to 20 steps) is otherwise silent until the final message. Off by default. When enabled, the loop emits one ping every EverySteps steps to any notifier that supports it (Slack first); a ping is best-effort and never fails the investigation.

type RateLimit

type RateLimit struct {
	MaxPerWindow int      `yaml:"max_per_window"` // 0 ⇒ unlimited
	Window       Duration `yaml:"window"`
	MaxRequeues  int      `yaml:"max_requeues"` // drop a key after this many backoff requeues
}

RateLimit caps investigation starts per sliding window.

type ServerConfig

type ServerConfig struct {
	// WebhookTokenEnv names an env var holding a shared secret required on
	// POST /webhook/alertmanager as "Authorization: Bearer <token>". Empty leaves
	// the webhook unauthenticated (rejected by Validate when actions.mode=auto).
	WebhookTokenEnv string `yaml:"webhook_token_env"`
}

ServerConfig configures the HTTP ingress.

type SlackNotify

type SlackNotify struct {
	WebhookURLEnv    string   `yaml:"webhook_url_env"`    // env var holding the incoming-webhook URL
	BotTokenEnv      string   `yaml:"bot_token_env"`      // env var holding a bot token (xoxb-…) for chat.postMessage
	Channel          string   `yaml:"channel"`            // channel ID or name to post to (required with bot_token_env)
	SigningSecretEnv string   `yaml:"signing_secret_env"` // env var with the Slack signing secret (verifies button clicks)
	ApproverIDs      []string `yaml:"approver_ids"`       // Slack user IDs allowed to approve actions (empty = no Slack approvals)
}

SlackNotify configures Slack delivery and (for rung-2 actions) interactive approve/reject buttons. Delivery uses either an incoming webhook (WebhookURLEnv) or a bot token posting to a channel via chat.postMessage (BotTokenEnv+Channel); if both are set, the bot token wins.

type Telemetry

type Telemetry struct {
	MetricsEnabled bool   `yaml:"metrics_enabled"` // serve OTel metrics on GET /metrics (Prometheus exposition)
	OTLPEndpoint   string `yaml:"otlp_endpoint"`   // optional OTLP push (phase-2); empty ⇒ scrape-only
}

Telemetry configures OpenTelemetry metrics export.

type TriggerPolicy

type TriggerPolicy struct {
	Incidents      IncidentTrigger      `yaml:"incidents"`       // primary trigger
	GitOpsFailures GitOpsFailureTrigger `yaml:"gitops_failures"` // secondary trigger
}

TriggerPolicy decides what RunLore reacts to.

Jump to

Keyboard shortcuts

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