audit

package
v0.1.8 Latest Latest
Warning

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

Go to latest
Published: Jul 12, 2026 License: MIT Imports: 11 Imported by: 0

Documentation

Overview

Package audit defines a best-effort, non-blocking audit sink. An Auditor records every tool call (who/when/what/result) for compliance. The async implementation drops events under backpressure and counts them rather than ever blocking or failing the main business flow (invariant I12).

Index

Constants

This section is empty.

Variables

View Source
var ErrSinkClosed = errors.New("audit: sink closed")

ErrSinkClosed is returned by Record on a closed AsyncAuditor.

Functions

func RedactInput

func RedactInput(input json.RawMessage, sensitive map[string]bool) json.RawMessage

RedactInput removes values for configured sensitive fields and hashes transaction handles before tool input is queued for persistence.

Types

type AsyncAuditor

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

AsyncAuditor pushes events to a bounded queue drained by a background flusher. On overflow it drops and counts (atomic) instead of blocking.

func NewAsyncAuditor

func NewAsyncAuditor(sink Sink, queueSize int) *AsyncAuditor

NewAsyncAuditor starts a flusher goroutine. Call Close to drain and stop.

func NewAsyncAuditorWithClose

func NewAsyncAuditorWithClose(sink Sink, closeSink func() error, queueSize int) *AsyncAuditor

NewAsyncAuditorWithClose starts an auditor and closes the sink after draining.

func (*AsyncAuditor) Close

func (a *AsyncAuditor) Close()

Close stops accepting events and waits for the flusher to drain the queue.

func (*AsyncAuditor) Dropped

func (a *AsyncAuditor) Dropped() int64

Dropped returns the count of events dropped due to a full queue.

func (*AsyncAuditor) Record

func (a *AsyncAuditor) Record(_ context.Context, e Event) error

Record enqueues an event non-blocking. On a full queue it drops and counts.

type Auditor

type Auditor interface {
	Record(ctx context.Context, e Event) error
}

Auditor records an Event. It must not block or fail the caller (invariant I12).

type Event

type Event struct {
	Time          time.Time       `json:"time"`
	DecisionID    string          `json:"decisionId,omitempty"`
	Role          string          `json:"role,omitempty"`
	Entity        string          `json:"entity,omitempty"`
	Action        string          `json:"action,omitempty"`
	Tool          string          `json:"tool"`
	Input         json.RawMessage `json:"input,omitempty"`
	ResultSummary string          `json:"resultSummary,omitempty"`
	Cost          *cost.Plan      `json:"cost,omitempty"`
	Allowed       bool            `json:"allowed"`
	// Code is the stable machine denial code (core/tool Denial.Code) when the
	// call was rejected by a governed path. Empty with Allowed=false means an
	// internal or protocol-level failure that is not reflected to clients.
	Code         string        `json:"code,omitempty"`
	Error        string        `json:"error,omitempty"`
	Duration     time.Duration `json:"-"`
	ReturnedRows int64         `json:"returnedRows"`
}

Event records one tool invocation for compliance. DecisionID correlates the event with the MCP response and trace span of the same call.

The JSON field names below are a frozen public contract (see docs/tool-contract.md): adding a new optional field is compatible; renaming or removing a field is breaking. Duration serializes as integer milliseconds under "durationMs". Cost is reserved: its inner structure is not yet part of the frozen contract.

func (Event) MarshalJSON added in v0.1.6

func (e Event) MarshalJSON() ([]byte, error)

MarshalJSON emits Duration as integer milliseconds ("durationMs") so the JSON Lines contract does not depend on Go's nanosecond Duration encoding.

type FileSink

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

FileSink is a long-lived JSON-lines audit sink.

func OpenFileSink

func OpenFileSink(path string) (*FileSink, error)

OpenFileSink opens path with owner-only permissions.

func (*FileSink) Close

func (s *FileSink) Close() error

Close flushes and closes the file.

func (*FileSink) Record

func (s *FileSink) Record(event Event) error

Record appends one event.

type NoopAuditor

type NoopAuditor struct{}

NoopAuditor discards everything.

func (NoopAuditor) Record

func (NoopAuditor) Record(_ context.Context, _ Event) error

Record is a no-op.

type Sink

type Sink func(Event) error

Sink consumes one event. Errors are ignored (best-effort).

Jump to

Keyboard shortcuts

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