Documentation
¶
Overview ¶
Package audit is the admin-action audit trail engine: a bounded in-memory ring (the newest MaxRing entries), optional append-only JSONL persistence with rotation, paginated/time-filtered reads over both, and the Data-Plane → Control-Plane push queue. Extracted from package main's store.go per ADR-0002 (store.go decomposition Phase B).
package main keeps the surfaces: the auditEvent/auditEventDiff request wrappers (actor enrichment from the session cookie), the C2c audit-completion middleware (which observes the wrappers, not this engine), the API handlers, and the CP push loop (which drains/requeues through this package). Two inversion points: the SIEM hook (main wires a closure over its syslog singleton — the forwarder is runtime-configured, so the closure reads it at call time) and the DP-mode flag (set by main's cluster wiring; when on, Add also queues for CP push).
Index ¶
- Constants
- func Add(e Entry)
- func ClearPersistForTest()
- func Close() error
- func DPMode() bool
- func Init(path string) error
- func PersistActive() bool
- func Requeue(events []Entry)
- func ResetForTest() (restore func())
- func SetDPMode(on bool)
- func SetPersistForTest(w io.Writer) (restore func())
- func SetSIEM(fn func(Entry))
- func SwapRingForTest() (restore func())
- type Entry
Constants ¶
const MaxRing = 500
MaxRing bounds the in-memory ring. Tests MUST NOT assert on len() deltas of Get() — under cumulative suites the ring saturates and adding an entry evicts the oldest (see the CLAUDE.md test-authoring pitfall).
Variables ¶
This section is empty.
Functions ¶
func Add ¶
func Add(e Entry)
Add appends an entry to the in-memory ring and, when configured, to the persistent JSONL file, the SIEM hook, and the DP push queue.
func ClearPersistForTest ¶
func ClearPersistForTest()
ClearPersistForTest drops the persistence wiring without closing it (used after a shutdown-hook test has already closed the file, so a later restore or Close cannot double-close).
func Close ¶
func Close() error
Close releases the persistent file handle (best-effort; shutdown hook). Safe when persistence was never initialised.
func Init ¶
Init opens path for append-only JSONL persistence with rotation. Existing entries are loaded into the in-memory ring on startup. If path is empty this is a no-op (backwards-compatible). F18: Rotates at 50 MB (same as the system log) to prevent unbounded disk growth.
func PersistActive ¶
func PersistActive() bool
PersistActive reports whether a persistent file handle is wired. Used both by tests (shutdown-hook coverage) and by the admin API (GET /api/stats) to surface a silent Init failure: compare against the caller's own configured path to detect an operator-configured log that fell back to volatile in-memory storage.
func Requeue ¶
func Requeue(events []Entry)
Requeue prepends failed events back into the pending queue so they are retried on the next push interval instead of being lost (newest kept under the cap).
func ResetForTest ¶
func ResetForTest() (restore func())
ResetForTest snapshots and clears the ring + persistence state, returning a restore func. Replaces the pre-extraction pattern of tests swapping the package globals directly.
func SetDPMode ¶
func SetDPMode(on bool)
SetDPMode marks this node as a Data Plane (enables CP push queuing).
func SetPersistForTest ¶
SetPersistForTest points JSONL persistence at w (path stays empty so reads keep using the ring), returning a restore func.
func SetSIEM ¶
func SetSIEM(fn func(Entry))
SetSIEM installs the SIEM forwarding hook called after every Add.
func SwapRingForTest ¶
func SwapRingForTest() (restore func())
SwapRingForTest snapshots and clears ONLY the in-memory ring, returning a restore func (persistence state untouched).
Types ¶
type Entry ¶
type Entry struct {
TS int64 `json:"ts"` // Unix milliseconds
Time string `json:"time"` // human-readable "2006-01-02 15:04:05"
Actor string `json:"actor"` // client IP (or authenticated username)
Action string `json:"action"` // "policy.add" | "blocklist.remove" | …
Object string `json:"object"` // the specific item that changed (human-readable name)
ObjectID string `json:"objectId,omitempty"` // stable ULID of the changed item, when it has one — survives rename, so an object's audit trail is correlatable by ID (§1 identity seam)
Detail string `json:"detail"` // extra context (never contains credentials)
Before string `json:"before,omitempty"` // JSON snapshot before the change
After string `json:"after,omitempty"` // JSON snapshot after the change
}
Entry captures every configuration change made through the UI/API so operators can answer "Who changed What, and When?" — a core SOC requirement. Actor is the client IP of the UI caller, enriched with the authenticated admin identity when available. Action follows a "resource.verb" naming scheme (e.g. "policy.add").
func GetMemory ¶
GetMemory returns paginated, optionally time-filtered entries from the in-memory ring (newest-first).
func GetPersistent ¶
GetPersistent reads the JSONL audit log file with pagination. Returns entries newest-first. If from/to are non-zero, filters by timestamp. Falls back to the in-memory ring if no file is configured.