Documentation
¶
Overview ¶
Package agent implements the service layer behind the scoped /v1/agent/* tool surface: the triage bundle, the read-only context passthroughs, timeline notes, and the typed-action proposal path that delegates to Stream B's action executor. Every method here is reached only through the auth middleware's agent-scope switch, which 403s an agent token on any incident but its own.
Index ¶
- Variables
- func SetActionExecutor(e ActionExecutor)
- type ActionExecutor
- type ActionRequest
- type ActionResult
- type RunSummary
- type Service
- func (s *Service) AllowedJobs(id uuid.UUID) ([]string, error)
- func (s *Service) Bundle(id uuid.UUID) (*iincident.Bundle, error)
- func (s *Service) FailingLog(inc *models.Incident) (string, bool, error)
- func (s *Service) History(inc *models.Incident, jobAlias string, allowed []string) ([]RunSummary, error)
- func (s *Service) Incident(id uuid.UUID) (*models.Incident, error)
- func (s *Service) Note(inc *models.Incident, text string) (*models.AgentAction, error)
- func (s *Service) ProposeAction(inc *models.Incident, req ActionRequest) (*ActionResult, error)
- func (s *Service) Why(inc *models.Incident, task string) (*runstorage.WhyExplanation, error)
- func (s *Service) WithDatabase(conn *gorm.DB) *Service
Constants ¶
This section is empty.
Variables ¶
var ErrForbiddenJob = errors.New("agent: job is outside the incident's frozen allowlist")
ErrForbiddenJob is returned when a context read targets a job outside the incident's frozen allowlist. The controller maps it to 403.
var ErrIncidentNotFound = errors.New("agent: incident not found")
ErrIncidentNotFound is returned when the addressed incident does not exist.
var ErrNoFailingRun = errors.New("agent: incident has no failing run")
ErrNoFailingRun is returned when the incident has no addressable failing run.
var ErrUnknownActionType = errors.New("agent: action type is required")
ErrUnknownActionType is returned when the action type is empty/unrecognized at the surface level (deep validation is the executor's job).
Functions ¶
func SetActionExecutor ¶
func SetActionExecutor(e ActionExecutor)
SetActionExecutor registers the server-side action executor. Wired once at startup (cmd/start/start.go, behind the remediation master gate).
Types ¶
type ActionExecutor ¶
type ActionExecutor interface {
ExecuteAgentAction(ctx context.Context, req ActionRequest) (*ActionResult, error)
}
ActionExecutor is the server-side action executor: it validates a typed action against the effective playbook, executes tier-1/2 actions, routes tier-3 through the approval gate (creating the ApprovalRequest a human decides on), and records the AgentAction audit row with the correct actor/tier/status.
It is registered at startup by cmd/start (an adapter over internal/incident.Executor), inside the CAESIUM_AGENT_REMEDIATION_ENABLED master gate.
type ActionRequest ¶
type ActionRequest struct {
IncidentID uuid.UUID `json:"-"`
// TokenID is the API key that authenticated this request, set by the
// controller and never by the client. An agent session's credential is minted
// per session and recorded on AgentSession.TokenID, so this is what identifies
// WHICH session proposed the action — the audit spine links the row to the
// container that made it, and the approval flow ends that session (not merely
// the newest one on the incident) while a human decides.
TokenID *uuid.UUID `json:"-"`
Type string `json:"type"`
Params json.RawMessage `json:"params,omitempty"`
}
ActionRequest is a typed remediation action proposed/executed by the agent through POST /v1/agent/incidents/:id/actions. The incident id comes from the route (and is scope-checked by the middleware); the agent supplies the action type and its params.
type ActionResult ¶
type ActionResult struct {
Action *models.AgentAction `json:"action"`
Disposition string `json:"disposition"`
}
ActionResult is what the actions endpoint returns: the recorded AgentAction row and a coarse disposition (proposed | executed | failed | awaiting_approval).
type RunSummary ¶
type RunSummary struct {
ID uuid.UUID `json:"id"`
Status string `json:"status"`
Error string `json:"error,omitempty"`
StartedAt time.Time `json:"started_at"`
CompletedAt *time.Time `json:"completed_at,omitempty"`
DurationMS int64 `json:"duration_ms,omitempty"`
}
RunSummary is one run in the read-only context history passthrough.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service wraps the incident package for the REST controllers, mirroring the thin service pattern used by lineage/why (a context + a *gorm.DB, with a WithDatabase override for tests).
func (*Service) AllowedJobs ¶
AllowedJobs returns the incident's frozen agent read-scope allowlist.
func (*Service) Bundle ¶
Bundle assembles the triage bundle for an incident.
The playbook it surfaces comes from iincident.ResolvePlaybook — the SAME resolver the action executor enforces with. Briefing the agent from the bootstrap default profile (what this did before) while judging its proposals against the job-scoped policy meant the two disagreed: the agent could plan correctly from its brief and still be denied, or believe it was constrained when it was not.
func (*Service) FailingLog ¶
FailingLog returns the scrubbed log tail of the incident's failing task. The A5 scrubber's high-entropy heuristic strips credential-shaped tokens; exact secret-value removal is not available post-hoc (resolved secrets are never persisted).
func (*Service) History ¶
func (s *Service) History(inc *models.Incident, jobAlias string, allowed []string) ([]RunSummary, error)
History returns recent runs for the incident's own job, or — when jobAlias is supplied — for that job PROVIDED it is within the incident's frozen allowlist. A request for an out-of-allowlist job is refused (ErrForbiddenJob), which is the read-scope boundary for agent tokens.
func (*Service) ProposeAction ¶
func (s *Service) ProposeAction(inc *models.Incident, req ActionRequest) (*ActionResult, error)
ProposeAction records/executes a typed action for an incident. It delegates entirely to the registered executor (validation, tier routing, approval-gate creation, execution, audit).
The executor-nil fallback below records a bare `proposed` AgentAction with NO tier evaluation and NO ApprovalRequest. It exists only so this package's unit tests can exercise the surface without constructing the whole incident executor, and for a server that never enabled remediation. Do not rely on it as a product path: a tier-3 action recorded through it is unapprovable, because nothing created the approval row.
func (*Service) Why ¶
func (s *Service) Why(inc *models.Incident, task string) (*runstorage.WhyExplanation, error)
Why returns the causal explanation for a task in the incident's failing run.