audit

package
v0.0.0-...-b3bc5c9 Latest Latest
Warning

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

Go to latest
Published: May 22, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package audit emits HMAC-signed audit-chain entries for admin mutations. Per gocodealone-multisite SPEC.md T26.

The chain links each entry to the prior entry's signature, so any row mutation invalidates the chain from that point forward. The signing key (MULTISITE_AUDIT_SIGN_KEY) is rotated via the `wfctl multisite audit-rotate` runbook (docs/runbook/backup.md).

In-memory Sink ships here; production wires a postgres-backed Sink via workflow-plugin-audit-chain (separate module).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Entry

type Entry struct {
	ID         int64
	OccurredAt time.Time
	Actor      string // user_id (or "system" for bootstrap entries)
	TenantID   int64  // 0 for cross-tenant ops
	Action     string // "tenant.create", "page.update", etc.
	Subject    string // resource id ("page:42")
	Meta       map[string]any
	PrevSig    string // hex; "" for the first entry
	Sig        string // HMAC-SHA256(prev_sig || canonical(entry))
}

Entry is one audit record.

type Logger

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

Logger produces signed entries + appends them to the configured Sink.

func New

func New(signKey string, sink Sink) *Logger

New returns a Logger. signKey must be non-empty.

func (*Logger) Record

func (l *Logger) Record(actor string, tenantID int64, action, subject string, meta map[string]any) (Entry, error)

Record signs + appends one entry. Always returns the canonical stored copy.

func (*Logger) Verify

func (l *Logger) Verify(tenantID int64) (int, error)

Verify walks the chain returned by Sink.List + returns the first index that breaks (i.e. the first row whose stored Sig does not match the recomputed value). Returns -1 if the whole chain verifies.

type MemorySink

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

MemorySink stores audit entries in-process. Used for tests + local dev.

func NewMemorySink

func NewMemorySink() *MemorySink

func (*MemorySink) Append

func (s *MemorySink) Append(e Entry) (Entry, error)

func (*MemorySink) List

func (s *MemorySink) List(tenantID int64) ([]Entry, error)

type Sink

type Sink interface {
	Append(entry Entry) (Entry, error)
	List(tenantID int64) ([]Entry, error)
}

Sink persists audit entries.

Jump to

Keyboard shortcuts

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