Skip to main content

🧩 Core packages

This is the source-tree guide. Read the overview first for behavior. The dependency rules below are enforced in the repository by scripts/check-architecture.sh. Capability tiers (Community and Pro) are defined in internal/feature.

Packages​

Each line matches the package's doc.go.

PackageWhat it does
cmd/kwatchThin entrypoint: flags, subcommands, calls app.
internal/appAssembles kwatch and owns its process lifecycle: clients, Lease, supervision, readiness, shutdown.
internal/inventoryThe in-memory model of the cluster: entities, relations, attributes and recent changes. Knows nothing about Kubernetes.
internal/inventory/kubeTurns Kubernetes objects into observations: one schema per kind, discovery, watch modes, kubelet stats, probes, log reads.
internal/inventory/kube/dynamicwatchShared dynamic informer mechanics for discovered kinds.
internal/detectionFinds abnormal conditions (findings with health and mode); the tracker reports raised, changed and cleared.
internal/detection/detectorsThe built-in detectors. Read entity attributes, return findings.
internal/detection/reasonsStable reason codes. A leaf, shared by every layer.
internal/rootcauseWhat the root-cause engine shares with the layers above it: the Cause record, confidence levels, scheduler-message helpers.
internal/rootcause/explainThe engine: propagation table, candidate walk, scorers, greedy weighted set-cover solver, incremental cache.
internal/incidentGroups findings that share a cause into an incident and decides when people hear about it: announce, update, resolve.
internal/notificationThe provider-neutral Message, severities and rendering helpers. A leaf.
internal/notification/composeWrites the note for an incident decision as a short narrative.
internal/scopeNamespaces, reasons, silences and maintenance holds: which findings are in scope.
internal/pipelineThe decision loop, bounded investigation and storage workers, downtime reconciliation, audit entries.
internal/pipeline/announceStartup summary, digest, roll-up and namespace outage collecting.
internal/pipeline/coverageMemory and timings of the coverage backstop; its doc.go explains the whole check.
internal/pipeline/investigateEvidence investigators run by the investigation pool.
internal/storageThe bbolt state file: one bucket per data class, epoch fencing, retention, reset.
internal/deliveryRouting, retries, pacing, fallback and provider dispatch.
internal/delivery/transportThe shared outbound HTTP boundary providers use.
internal/delivery/apiThe small contracts shared by delivery and the provider catalog.
internal/delivery/providertestProvider test fixtures. Never imported by production code.
internal/delivery/signingAWS request signing for providers that talk to AWS.
internal/alert/*One adapter per provider: builds the payload, sends it through transport.
internal/alert/catalogStatically links provider adapters and constructs them.
internal/provider/catalogProvider identities and metadata.
internal/health/healthz, /readyz, /availabilityz, /health and /metrics, plus /status when healthCheck.statusEndpoint is on.
internal/statusThe read-only report that /status serves.
internal/metricsThe process-wide Prometheus registry; labels are always bounded.
internal/configLoads, normalizes and validates configuration.
internal/config/crdWatches KwatchConfig resources, including late installs.
internal/rbacAudits the permissions kwatch uses and reports what is missing.
internal/kubeclientKubernetes client construction and informer helpers. Only app constructs clients.
internal/redactRemoves secrets from text before kwatch keeps or sends it. A leaf.
internal/format, internal/ratelimit, internal/clockPure text helpers, the rate-limit error type, the time dependency.
internal/auditOne JSON line per incident decision, for offline scoring.
internal/replayRecords and replays observations on a simulated clock. Test tooling; only internal/flight imports it in production code, for its log format and sanitizer.
internal/flightThe flight recorder: a bounded, sanitized ring of the observation stream in the state file, and kwatch replay-export.
internal/selfcheckPer-rule counts of whether recovery followed a change to the named cause. Display only.
internal/scenariosLabelled scenario library and the scorecard gate. Tests only.
internal/scorecardMeasures notification quality against the production goals.
internal/feature, internal/heartbeat, internal/telemetry, internal/upgrader, internal/versionFeature identifiers, the external heartbeat ping, adoption telemetry, release check, build version.
internal/architectureTests that enforce repository layout. No production code.

Import direction​

The flow is the dependency direction. Lower layers never import upper ones.

inventory → detection → rootcause → incident → notification/compose
→ pipeline → app

The script enforces these rules:

  • inventory imports none of detection, rootcause, incident, notification, pipeline, storage, scope, delivery, alert, app, health or rbac. Only inventory/kube may import Kubernetes libraries.
  • detection does not import rootcause, incident, notification, pipeline, storage, scope, delivery, alert or app. rootcause does not import incident or anything above it. incident does not import notification, pipeline, storage, scope, delivery, alert or app. notification/compose does not import pipeline, storage, scope, delivery, alert or app.
  • storage imports no domain package. scope imports nothing at or above rootcause, and rbac nothing at or above detection.
  • pipeline does not import delivery, alert, app, health or config. Only app (and replay, which is test tooling) imports pipeline. Its subpackages announce, coverage and investigate never import pipeline or each other; the pipeline wires them.
  • Leaf packages (notification, format, redact, ratelimit, detection/reasons) import no upper layer.
  • alert/* and delivery import no domain package, no kube, no Kubernetes client library and not app. Providers never use net/http directly; they call delivery/transport, which decides status classification, timeout and retry.
  • Clients are built in internal/kubeclient and internal/app only. Dynamic informers are built only in dynamicwatch. config.Config is read only by config, app and commands. Production code does not call time.Now (use an injected clock), http.DefaultClient, net.DefaultResolver, context.WithValue or dynamic Prometheus label values.
  • Retired packages (controller, insight, persistence, handler, monitor, model, message and others listed in the script) must not return.

Where to put new code​

You want toPut it in
Detect a new abnormal statedetection/detectors, reason in detection/reasons
Teach root cause a new way failure spreadsA row in rootcause/explain/table_rows*.go
Watch a new kind or add a sourceinventory/kube (schema, registration, watch mode)
Say a new fact in the messageA sentence writer in notification/compose
Prove a behavior end to endA labelled scenario in internal/scenarios
Add a providerinternal/alert/<provider>, catalog metadata, transport tests
Change the state fileinternal/storage, bump SchemaVersion

See Contributing for the full guides.