Documentation
¶
Overview ¶
Package processreport ingests an enrolled agent's running-process report and feeds the two consumers that gave the behavior baseline no input before it existed: the per-host running-process projection (#594 B5) and the behavior baseline learner (#594 D). The shipped agent reported host package inventory but never its processes, so the statistical baseline in internal/domain/baseline never saw a single observation. This closes that gap on the agent transport plane.
The asset a report is attributed to is NEVER taken from the agent's request. It is resolved server-side from the authenticated agent's canonical telemetry binding, exactly as telemetry and detection ingest resolve it, so an agent cannot report processes for a host it does not own.
Index ¶
Constants ¶
const MaxProcesses = 4096
MaxProcesses bounds one report. A host with more live processes than this ships the first MaxProcesses; the baseline features (process count as a spawn-rate proxy, distinct exec paths) saturate well below it, so the cap costs no fidelity while keeping a misbehaving or compromised agent from flooding the projection.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type AssetResolver ¶
type AssetResolver interface {
ResolveTelemetryAsset(ctx context.Context, agentID shared.ID) (shared.ID, error)
}
AssetResolver maps an authenticated agent to the canonical host asset the control plane bound to it. *postgres.TelemetryTransportRepository and the in-memory twin satisfy it via ResolveTelemetryAsset.
type Learner ¶
Learner folds the just-reported profile into the asset's behavior baseline. *behaviorbaseline.Service satisfies it. Optional: nil means the projection is stored but no baseline observation is taken.
type Process ¶
Process is one running process as the agent observed it, free of any domain or transport type.
type ProcessStore ¶
type ProcessStore interface {
SaveProcesses(ctx context.Context, snapshots []ports.ProcessSnapshot) error
// ReplaceRunningProcesses makes the asset's running set exactly the reported snapshots, retiring any
// process that exited since the last report. Used for a COMPLETE report (the agent saw every process).
ReplaceRunningProcesses(ctx context.Context, assetID shared.ID, snapshots []ports.ProcessSnapshot) error
}
ProcessStore persists the running-process projection. ports.EndpointProcessStore satisfies it.
type Result ¶
Result reports what a report produced, for the agent-plane response and the audit trail. LearnErr is non-empty when the snapshots were saved but folding them into the behavior baseline failed: the report still succeeds (the snapshots are durable), so the caller logs LearnErr rather than failing the agent.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service ingests a report: resolve the asset, persist the snapshots, then learn.
func NewService ¶
func NewService(resolver AssetResolver, store ProcessStore, learner Learner, clock ports.Clock) (*Service, error)
NewService validates its required dependencies. learner is optional.
func (*Service) Report ¶
func (s *Service) Report(ctx context.Context, tenantID, agentID shared.ID, procs []Process, complete bool) (Result, error)
Report resolves the agent's canonical asset, persists the running processes as snapshots under the agent's tenant, then folds the profile into the behavior baseline. The tenant is taken from the authenticated agent; the ctx it saves under is bound to that tenant so the store's RLS holds. An agent with no established binding yet (it has not reported inventory) is a validation error, not a 500: the binding is a prerequisite the agent satisfies by shipping inventory first. Report ingests one agent report. complete is true when the agent enumerated every live process (it did not hit its cap); a complete report REPLACES the asset's running set so processes that exited since the last report are retired, and a truncated report only upserts (retiring absent rows would wrongly drop live processes beyond the cap).