audit

package
v0.66.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 30, 2026 License: MIT Imports: 8 Imported by: 0

Documentation

Overview

Package audit hosts the JSONL audit-log writer used by the host-side infra.admin workflow module to record every admin action (read or future-mutating). Writer is concurrent-safe, append-only, and reopens its file handle on SIGHUP so external log-rotation tools (logrotate, etc.) can move the file aside without losing subsequent entries.

Design: docs/plans/2026-05-27-infra-admin-dynamic-design.md §Security Review Plan: docs/plans/2026-05-27-infra-admin-dynamic.md (Task 14)

**Wire format**: protojson over workflow.iac.v1.AdminAuditEntry. Per design §Access logging: "Each line is AdminAuditEntry proto-JSON. Reader `wfctl infra admin audit-tail --base-url ...` (HTTP-backed)". Writing via protojson preserves the strict-contract invariant that on-disk lines are byte-identical to what the HTTP audit-tail endpoint serves, so the CLI's protojson.Unmarshal decoder works end-to-end.

Earlier T14 draft (commit 42b9e1c11) defined an Entry struct with 10 plan-listed fields including `ts time.Time`, `action_id`, `dry_run`, `confirm_destroy` — but the design proto AdminAuditEntry has only 7 fields and uses `ts_unix int64`. Per spec-reviewer T14 F1 + strict-interpretation invariant ("design wins when plan/ design diverge"), Entry is now a thin alias for the proto message with no host-only extras. If v1.1 needs the extras, that's an ADR-tracked schema amendment, not a quiet plan-extra add.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Entry

type Entry = adminpb.AdminAuditEntry

Entry is a re-export of the proto AdminAuditEntry message so audit-package callers don't have to import the adminpb package directly. The writer's Write method marshals via protojson, so any field added to the proto becomes available to writers without an audit-package code change.

Strict contract: this MUST stay an alias rather than a parallel struct definition. The spec-reviewer T14 F1 follow-up moved from a host-only struct to this alias precisely to eliminate the drift surface between the writer + the typed wire shape.

type Writer

type Writer struct {
	// contains filtered or unexported fields
}

Writer wraps an append-only JSONL file with concurrent-safe writes and SIGHUP reopen. The host module (T15) holds one Writer for the lifetime of the infra.admin module; tests can create + close them at will.

Close-safety: double-Close is a no-op. Post-Close Write returns a clear error rather than silently dropping audit entries — losing audit data is worse than a noisy error per design Security Review.

SIGHUP handling: the writer registers a signal handler on Open that reopens the file path under the mutex. External rotation (logrotate, mv + SIGHUP) works without losing in-flight writes.

func Open

func Open(path string) (*Writer, error)

Open creates or appends-to the audit file at path and starts the SIGHUP-reopen goroutine. Per design Security Review: a non-nil error MUST be treated as FATAL at module Init — silently failing to open the audit log is the opposite of the "default-audit- everything" posture the design mandates. The caller (T15 module Init) propagates Open errors up as a module-init failure.

func (*Writer) Close

func (w *Writer) Close() error

Close stops the SIGHUP goroutine, unregisters the signal handler, and closes the file handle. Double-Close is a no-op; post-Close Write returns a clear error.

func (*Writer) Write

func (w *Writer) Write(e *Entry) error

Write serializes the entry to one protojson line + newline and appends it under the mutex. Closed-after returns a clear error rather than silently dropping the entry — losing audit data is worse than a noisy error per design Security Review.

SchemaVersion is set to 1 on the caller-provided entry before marshaling so callers cannot accidentally emit a different version. If the schema ever bumps to 2, this is the single change-point.

The entry is taken by pointer because adminpb.AdminAuditEntry (the alias target) holds internal protobuf state; passing by value would copy that state and trigger a vet warning.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL