Documentation
¶
Overview ¶
Package eventlog wraps the audit log for forensic and compliance use cases (Task 20119): tail (with optional follow), filter, replay into a fresh database, and verify the SHA-256 hash chain.
The append-only `audit_events` table itself lives in pkg/statedb so that mutation hot-paths (UpsertTask, AppendStep, SetConfigBlob, SaveState) can emit rows without an import cycle. This package supplies the workdir-aware API and operator-facing workflows on top.
The audit log is best-effort by design: a stuck DB cannot block user work. `cloop events verify` is the explicit check that the chain is intact; detected breaks tell operators the journal lost or had rows tampered with.
Index ¶
- Variables
- type AuditEvent
- type AuditFilter
- type Log
- func (l *Log) Append(ev *AuditEvent) error
- func (l *Log) Close() error
- func (l *Log) DB() *statedb.DB
- func (l *Log) DistinctActors() ([]string, error)
- func (l *Log) DistinctEntityTypes() ([]string, error)
- func (l *Log) List(f AuditFilter) ([]AuditEvent, int, error)
- func (l *Log) MaxID() (int64, error)
- func (l *Log) Path() string
- func (l *Log) ReconstructTask(taskID int) (TaskStory, error)
- func (l *Log) Tail(ctx context.Context, opts TailOptions, out chan<- AuditEvent) error
- func (l *Log) Verify() (VerifyReport, error)
- type ReplayOptions
- type ReplayReport
- type TailOptions
- type TaskRunStory
- type TaskStory
- type VerifyReport
Constants ¶
This section is empty.
Variables ¶
var ErrNoProject = errors.New("eventlog: no .cloop/state.db found at workdir")
ErrNoProject is returned when the resolved workdir has no SQLite state DB yet — usually because cloop init has not been run.
Functions ¶
This section is empty.
Types ¶
type AuditEvent ¶
type AuditEvent = statedb.AuditEvent
AuditEvent re-exports statedb.AuditEvent so callers don't need to import both packages.
type AuditFilter ¶
type AuditFilter = statedb.AuditFilter
AuditFilter re-exports statedb.AuditFilter.
type Log ¶
type Log struct {
// contains filtered or unexported fields
}
Log is a handle to an audit log. Concurrency: safe for use by multiple goroutines as long as Close is only called once.
func Open ¶
Open opens a handle to the audit log at the resolved state.db path. The caller must Close.
func (*Log) Append ¶
func (l *Log) Append(ev *AuditEvent) error
Append records one event. Caller-supplied actor/event_type/etc. flow through to the row; the package fills timestamp + hash chain.
func (*Log) DB ¶
DB returns the underlying *statedb.DB. Exposed so callers that already need other statedb operations against the same database don't open a second connection.
func (*Log) DistinctActors ¶
DistinctActors returns the sorted list of actor values seen in the log. Used by the Web UI's filter dropdown.
func (*Log) DistinctEntityTypes ¶
DistinctEntityTypes returns the sorted list of entity types seen.
func (*Log) List ¶
func (l *Log) List(f AuditFilter) ([]AuditEvent, int, error)
List returns events matching the filter and the unfiltered total count.
func (*Log) ReconstructTask ¶ added in v0.0.2
ReconstructTask assembles one task's whole history — every execution, the executor each ran on, the credentials it held and how it ended — from the audit trail alone (Task 20282).
It reads no table but audit_events. See pkg/statedb/audit_story.go for why that restriction is the feature rather than an implementation detail.
func (*Log) Tail ¶
func (l *Log) Tail(ctx context.Context, opts TailOptions, out chan<- AuditEvent) error
Tail streams events to out in id-ascending order. When Follow is false the function returns once it has caught up to MaxID at the time of the call. When Follow is true the function only returns on context cancellation.
The channel out is closed before Tail returns (success or error). The caller may pass an unbuffered channel; Tail respects ctx during sends.
func (*Log) Verify ¶
func (l *Log) Verify() (VerifyReport, error)
Verify recomputes the SHA-256 chain from the genesis row to head. Returns (report, nil) for a clean verification, including reports where OK=false: the inner Reason describes the break. The error return is reserved for driver/IO failures.
type ReplayOptions ¶
type ReplayOptions struct {
FromID int64 // 0 or 1 = entire history; >1 = only events with id >= FromID
OnEvent func(ev AuditEvent) // optional per-event callback (e.g. progress)
StopAt int64 // 0 = no upper bound; otherwise stop after id == StopAt
// AllowTruncated permits a replay that starts after a retention prune
// (Task 20218).
//
// Replay rebuilds state by applying every mutation in order, so it is only
// complete if it starts at the first one. Once a prefix has been pruned,
// the rows before the boundary live in a sealed archive and not in this
// database — a replay from "the beginning" would quietly produce a partial
// database that looks whole. Refusing is the safe default; this opts into
// the partial rebuild deliberately, which is the right call when the tail
// is all the operator wanted.
AllowTruncated bool
}
ReplayOptions controls Replay behaviour.
type ReplayReport ¶
type ReplayReport struct {
DestPath string
EventsRead int
TasksWritten int
StepsWritten int
ConfigWrites int
Skipped int
BreakAtID int64 // first id whose payload could not be applied (0 = none)
BreakReason string
StartedAt time.Time
FinishedAt time.Time
// Truncated reports that a retention prune removed events older than the
// replay's starting point, so the rebuild is of the surviving tail rather
// than of the whole history. Set only when the caller passed
// AllowTruncated; without it a truncated trail is an error.
Truncated bool
TruncatedThroughID int64
ArchivePath string
}
ReplayReport summarises what Replay applied.
func Replay ¶
func Replay(ctx context.Context, srcWorkDir, destPath string, opts ReplayOptions) (*ReplayReport, error)
Replay reads audit events from the source workdir and applies them to a fresh SQLite database at destPath. The destination is created if missing; if it already exists Replay returns an error rather than overwriting — the operator should remove or rename it first.
Replay disables audit emission on the destination DB so the rebuild does not append a second copy of the events to the new audit log. The hash chain in the destination therefore restarts empty; if the operator wants to preserve the chain they can copy the audit_events table separately.
type TailOptions ¶
type TailOptions struct {
FromID int64 // start streaming events with id >= FromID (1 = beginning)
Follow bool // when true, keep polling for new events; when false, return at head
Poll time.Duration // follow-mode polling interval (default 500ms)
Filter AuditFilter // additional filtering (Order/Limit/Offset/FromID are overridden)
BatchSize int // events per query (default 200, capped at 5000)
}
TailOptions controls Tail behaviour.
type TaskRunStory ¶ added in v0.0.2
type TaskRunStory = statedb.TaskRunStory
TaskRunStory is one execution within a TaskStory.
type TaskStory ¶ added in v0.0.2
TaskStory and TaskRunStory are one task's reconstructed history and one of its executions. Aliased here so callers of this package do not have to import pkg/statedb to name what ReconstructTask returns.
type VerifyReport ¶
type VerifyReport = statedb.AuditVerifyReport
VerifyReport re-exports statedb.AuditVerifyReport.