audit

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Oct 1, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package audit provides audit logging types and storage.

Index

Constants

This section is empty.

Variables

View Source
var ErrNotFound = errors.New("audit entry not found")

ErrNotFound means no audit entry exists under the identifier asked for. The API answers 404, and it asks by cause rather than by reading the message, which is how every other layer here reports a thing that is not there.

Functions

func JobIDFrom

func JobIDFrom(
	ctx context.Context,
) string

JobIDFrom returns the job a request created, or the empty string when it created none.

func RecordJobID

func RecordJobID(
	ctx context.Context,
	jobID string,
)

RecordJobID notes the job a request created. Called by the job client for every dispatch; a context with no sink — a background task, an agent, a test — is left alone.

The first job wins. A broadcast is one job across many agents, and a request that somehow dispatches twice is better described by the job it started with than by the last one it happened to make.

func Summarize

func Summarize(
	body []byte,
	contentType string,
) string

Summarize returns what a request asked for, in a form an audit log can keep: the JSON body with sensitive values replaced and the whole thing capped.

A body that is not JSON is described rather than stored, because an audit entry is not the place to keep an arbitrary upload. An empty body summarizes to nothing at all, so a request with no body adds no field.

func WithJobIDSink

func WithJobIDSink(
	ctx context.Context,
) context.Context

WithJobIDSink returns a context that collects the job ID a request creates.

Types

type Entry

type Entry struct {
	// ID is the unique identifier for this audit entry.
	ID string `json:"id"`
	// Timestamp is when the request was processed.
	Timestamp time.Time `json:"timestamp"`
	// User is the authenticated subject (from JWT sub claim).
	User string `json:"user"`
	// Roles are the roles from the JWT token.
	Roles []string `json:"roles"`
	// Method is the HTTP method (GET, POST, PUT, DELETE).
	Method string `json:"method"`
	// Path is the request URL path.
	Path string `json:"path"`
	// OperationID is the OpenAPI operation ID (if available).
	OperationID string `json:"operation_id,omitempty"`
	// SourceIP is the client's IP address.
	SourceIP string `json:"source_ip"`
	// ResponseCode is the HTTP response status code.
	ResponseCode int `json:"response_code"`
	// DurationMs is the request processing time in milliseconds.
	DurationMs int64 `json:"duration_ms"`
	// TraceID is the OpenTelemetry trace ID for correlation.
	TraceID string `json:"trace_id,omitempty"`
	// JobID is the job the request created, empty for a request that created
	// none. It is what joins an audit entry to the job's own status timeline.
	JobID string `json:"job_id,omitempty"`
	// RequestSummary is what the request asked for, with sensitive values
	// replaced. Recorded for methods that change something, because "who ran
	// command/shell against which host" without the command is not an answer.
	RequestSummary string `json:"request_summary,omitempty"`
}

Entry represents a single audit log record.

type Publisher

type Publisher interface {
	Publish(
		ctx context.Context,
		subject string,
		data []byte,
	) error
}

Publisher defines the interface for publishing messages to NATS subjects.

type Store

type Store interface {
	// Write persists an audit entry.
	Write(
		ctx context.Context,
		entry Entry,
	) error

	// Get retrieves a single audit entry by ID.
	Get(
		ctx context.Context,
		id string,
	) (*Entry, error)

	// List retrieves audit entries with pagination.
	// Returns the entries, total count, and any error.
	List(
		ctx context.Context,
		limit int,
		offset int,
	) ([]Entry, int, error)

	// ListAll retrieves all audit entries without pagination.
	ListAll(
		ctx context.Context,
	) ([]Entry, error)
}

Store defines the interface for audit log persistence.

type StreamStore

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

StreamStore implements Store backed by a NATS JetStream stream.

func NewStreamStore

func NewStreamStore(
	logger *slog.Logger,
	stream jetstream.Stream,
	publisher Publisher,
	subject string,
) *StreamStore

NewStreamStore creates a new StreamStore.

func (*StreamStore) Get

func (s *StreamStore) Get(
	ctx context.Context,
	id string,
) (*Entry, error)

Get retrieves a single audit entry by ID.

func (*StreamStore) List

func (s *StreamStore) List(
	ctx context.Context,
	limit int,
	offset int,
) ([]Entry, int, error)

List retrieves audit entries with pagination, newest-first. Returns the entries, total count, and any error.

func (*StreamStore) ListAll

func (s *StreamStore) ListAll(
	ctx context.Context,
) ([]Entry, error)

ListAll retrieves all audit entries without pagination, newest-first.

func (*StreamStore) Write

func (s *StreamStore) Write(
	ctx context.Context,
	entry Entry,
) error

Write persists an audit entry by publishing to the stream.

Directories

Path Synopsis
Package export provides pluggable audit log export with pagination.
Package export provides pluggable audit log export with pagination.
mocks
Package mocks is a generated GoMock package.
Package mocks is a generated GoMock package.
Package mocks is a generated GoMock package.
Package mocks is a generated GoMock package.

Jump to

Keyboard shortcuts

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