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 ¶
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 NewAsyncAuditorOn ¶ added in v0.1.13
NewAsyncAuditorOn is NewAsyncAuditorWithClose with the flusher a background task of b. On a closed bus the auditor starts closed: it records nothing.
func NewAsyncAuditorWithClose ¶
func NewAsyncAuditorWithClose(sink Sink, closeSink func() error, queueSize int) *AsyncAuditor
NewAsyncAuditorWithClose starts a flusher goroutine and closes the sink (when closeSink is non-nil) after draining. Call Close to drain and stop.
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.
type Event ¶
type Event struct {
Time time.Time `json:"time"`
DecisionID string `json:"decisionId,omitempty"`
Role string `json:"role,omitempty"`
// User and Roles identify a configured user and its roles; Grants lists
// the covering grant IDs of the authorization decisions.
User string `json:"user,omitempty"`
Roles []string `json:"roles,omitempty"`
Grants []string `json:"grants,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
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 ¶
OpenFileSink opens path with owner-only permissions.