Help us shape the future of Go! Take the 2026 Go Developer Survey

audit

package
v0.6.0 Latest Latest
Warning

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

Go to latest
Published: Oct 24, 2026 License: Apache-2.0 Imports: 17 Imported by: 0

Documentation

Overview

Package audit is tailkeeper's append-only, hash-chained JSONL log (spec §14).

Each line carries seq (1, 2, ...), prev (the previous line's hash, "" for the first) and hash ("sha256:" + hex of the canonical JSON of the line without its hash field). A plain SHA-256 chain detects damage and naive edits; it does not stop someone who can rewrite the file and recompute the chain, and it cannot tell when lines were removed from the end. Exports anchor both (spec §14).

Rotate starts a new log and keeps the old one beside it as an archive; the new log's first entry records where the archive ends, and Verify checks it.

Index

Constants

View Source
const FileName = "audit.jsonl"

FileName is the audit log's name inside the logs directory.

View Source
const MaxLine = 32 << 10

MaxLine is the largest line Append writes. Append reads the previous line from the last 64 KiB of the file, so every line must fit well inside that.

View Source
const Version = 2

Version is the line format version.

Variables

This section is empty.

Functions

func RotateSupported

func RotateSupported() bool

RotateSupported reports whether Rotate works here: it needs the file lock, which Windows does not have yet.

func Tail

func Tail(path string, n int) ([]map[string]any, error)

Tail returns up to n of the most recent entries, oldest first.

func Verify

func Verify(path string) (int, error)

Verify checks the whole chain and returns the number of valid lines. The error names the first broken line. A log that starts with a rotation must continue the archive it names, when that archive is present; VerifyHistory also checks the archives' own chains.

Types

type Log

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

Log appends to one audit file. It is safe for concurrent use by several processes: appends take an exclusive file lock. Windows has no file lock yet: there the appends of one process exclude each other, and two processes can still fork the chain.

func Open

func Open(path string, now func() time.Time) (*Log, error)

Open creates the directory (0700) and file (0600) if needed.

func (*Log) Append

func (l *Log) Append(event string, fields map[string]any) (err error)

Append writes one event. fields must be JSON-marshalable and must not use the reserved names v, seq, ts, prev, event or hash.

func (*Log) Path

func (l *Log) Path() string

Path is the log file path.

func (*Log) Rotate

func (l *Log) Rotate() (string, error)

Rotate starts a new log and keeps the old one beside it as an archive named audit-<UTC time>.jsonl, which it returns. The new log's first entry, event "rotated", names the archive and its last seq and hash: Verify checks that a present archive still ends there, and VerifyHistory also checks its chain.

Rotate refuses a log that fails verification, so a rotation never hides damage, and a symbolic link, which the rename would replace with a file. The log path never goes missing: the archive is a hard link made first, and the new log replaces the path in one rename. Archives are kept until the owner deletes them.

func (*Log) SetLockWait

func (l *Log) SetLockWait(d time.Duration)

SetLockWait sets how long Append waits for a lock someone else holds; 0 restores the default of 2 seconds.

type Segment

type Segment struct {
	Path    string
	Lines   int  // valid lines
	Missing bool // named by the newer file's rotation but not present, so not checked
}

Segment is one file of a log's history.

func VerifyHistory

func VerifyHistory(path string) ([]Segment, error)

VerifyHistory verifies the log and then, through the rotation each file starts with, every archive before it that is still present, newest first. A missing archive ends the history, and its Segment says so.

Jump to

Keyboard shortcuts

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