audit

package
v0.0.0-...-cdd3c55 Latest Latest
Warning

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

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

Documentation

Overview

Package audit — Timeline reconstruction.

Per HELM 2030 Spec §5.3:

Audit timeline reconstruction assembles a chronological view
of all governance-relevant events for forensic analysis.

Resolves: GAP-10.

Index

Constants

View Source
const (
	// AATVersion identifies the draft revision this export targets.
	AATVersion = "draft-sharif-agent-audit-trail-00"

	// AATGenesisHash is the previous_record_hash of the first record in a chain.
	AATGenesisHash = "0000000000000000000000000000000000000000000000000000000000000000"
)

Variables

View Source
var (
	// ErrAATChainBroken is returned when hash-chain verification fails.
	ErrAATChainBroken = errors.New("audit: aat hash chain broken")
	// ErrAATBadSignature is returned when a record signature does not verify.
	ErrAATBadSignature = errors.New("audit: aat record signature invalid")
	// ErrAATEmptyAgentID is returned when the exporting agent identity is empty.
	ErrAATEmptyAgentID = errors.New("audit: aat agent_id must not be empty")
)
View Source
var (
	// ErrEmptyTenantID is returned when tenant ID is empty.
	ErrEmptyTenantID = errors.New("audit: tenant_id must not be empty")
	// ErrInvalidTimeRange is returned when start time is after end time.
	ErrInvalidTimeRange = errors.New("audit: start_time must be before end_time")
	// ErrStoreNotConfigured is returned when audit export is invoked without a backing store.
	ErrStoreNotConfigured = errors.New("audit: store not configured (fail-closed)")
)

Functions

func MarshalAATJSONL

func MarshalAATJSONL(records []AATRecord) ([]byte, error)

MarshalAATJSONL serializes records as JSON Lines, one JCS-canonical record per line. Output is byte-deterministic for identical input.

func VerifyAATChain

func VerifyAATChain(records []AATRecord) error

VerifyAATChain re-derives every record hash, checks the SHA-256 chain from AATGenesisHash, and verifies Ed25519 signatures where present.

Types

type AATRecord

type AATRecord struct {
	AATVersion         string            `json:"aat_version"`
	RecordID           string            `json:"record_id"`
	Sequence           uint64            `json:"sequence"`
	Timestamp          string            `json:"timestamp"`
	AgentID            string            `json:"agent_id"`
	ActionType         string            `json:"action_type"`
	Action             string            `json:"action"`
	Resource           string            `json:"resource"`
	PayloadHash        string            `json:"payload_hash"`
	Metadata           map[string]string `json:"metadata,omitempty"`
	PreviousRecordHash string            `json:"previous_record_hash"`
	RecordHash         string            `json:"record_hash"`
	Signature          *AATSignature     `json:"signature,omitempty"`
}

AATRecord is a single AAT-conformant audit record. Mandatory fields per the draft: aat_version, record_id, sequence, timestamp, agent_id, action_type, action, resource, payload_hash, previous_record_hash, record_hash. signature is optional.

func ConvertEntriesToAAT

func ConvertEntriesToAAT(entries []*store.AuditEntry, agentID string, signer AATSigner) ([]AATRecord, error)

ConvertEntriesToAAT converts append-only audit store entries into an AAT-conformant record chain. Entries are processed in the given order; the chain is rooted at AATGenesisHash. When signer is non-nil every record hash is signed for non-repudiation.

type AATSignature

type AATSignature struct {
	Algorithm string `json:"algorithm"`
	PublicKey string `json:"public_key"`
	Value     string `json:"value"`
}

AATSignature is the optional non-repudiation envelope on a record.

type AATSigner

type AATSigner interface {
	Algorithm() string
	PublicKey() []byte
	Sign(digest []byte) ([]byte, error)
}

AATSigner signs record hashes. The draft permits ECDSA; HELM's native deterministic implementation is Ed25519. Any algorithm satisfying this interface may be plugged in.

type AuditEvidencePack

type AuditEvidencePack struct {
	TenantID    string    `json:"tenant_id"`
	GeneratedAt time.Time `json:"generated_at"`
	Checksum    string    `json:"checksum"`
	DownloadURL string    `json:"download_url,omitempty"` // If stored in bucket
	Events      []Event   `json:"events"`
}

AuditEvidencePack represents the exported bundle.

type Ed25519AATSigner

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

Ed25519AATSigner signs AAT records with an Ed25519 private key. Ed25519 signatures are deterministic, preserving byte-identical exports.

func NewEd25519AATSigner

func NewEd25519AATSigner(key ed25519.PrivateKey) (*Ed25519AATSigner, error)

NewEd25519AATSigner wraps an Ed25519 private key as an AATSigner.

func (*Ed25519AATSigner) Algorithm

func (s *Ed25519AATSigner) Algorithm() string

func (*Ed25519AATSigner) PublicKey

func (s *Ed25519AATSigner) PublicKey() []byte

func (*Ed25519AATSigner) Sign

func (s *Ed25519AATSigner) Sign(digest []byte) ([]byte, error)

type Event

type Event struct {
	ID        string                 `json:"id"`
	TenantID  string                 `json:"tenant_id"`
	ActorID   string                 `json:"actor_id"`
	Type      EventType              `json:"type"`
	Action    string                 `json:"action"`
	Resource  string                 `json:"resource"`
	Timestamp time.Time              `json:"timestamp"`
	Metadata  map[string]interface{} `json:"metadata,omitempty"`
}

Event represents a structured audit record.

type EventType

type EventType string

EventType defines the category of the audit event.

const (
	EventAccess   EventType = "ACCESS"
	EventMutation EventType = "MUTATION"
	EventSystem   EventType = "SYSTEM"
	EventPolicy   EventType = "POLICY"
)

type ExportRequest

type ExportRequest struct {
	TenantID  string    `json:"tenant_id"`
	StartTime time.Time `json:"start_time"`
	EndTime   time.Time `json:"end_time"`
}

ExportRequest defines what to export.

type Exporter

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

Exporter handles the creation of evidence packs.

func NewExporter

func NewExporter(s *store.AuditStore) *Exporter

func (*Exporter) GenerateAAT

func (e *Exporter) GenerateAAT(ctx context.Context, req ExportRequest, agentID string, signer AATSigner) ([]byte, error)

GenerateAAT exports the requested audit window as an AAT-conformant JSON Lines document. Fail-closed: requires a configured store.

func (*Exporter) GeneratePack

func (e *Exporter) GeneratePack(ctx context.Context, req ExportRequest) ([]byte, string, error)

GeneratePack creates a zip file containing the audit logs and a manifest with checksums.

type Logger

type Logger interface {
	Record(ctx context.Context, eventType EventType, action, resource string, metadata map[string]interface{}) error
}

Logger defines the interface for recording audit events.

func NewLogger

func NewLogger() Logger

NewLogger creates a Logger writing to os.Stdout.

func NewLoggerWithWriter

func NewLoggerWithWriter(w io.Writer) Logger

NewLoggerWithWriter creates a Logger writing to the given writer. This allows injection for testing and custom sinks.

type StoreLogger

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

func NewStoreLogger

func NewStoreLogger(s *store.AuditStore) *StoreLogger

func (*StoreLogger) Record

func (l *StoreLogger) Record(ctx context.Context, eventType EventType, action, resource string, metadata map[string]interface{}) error

type TLEventKind

type TLEventKind string

TLEventKind classifies timeline events (prefixed to avoid collision with audit.EventType).

const (
	TLEventDecision   TLEventKind = "DECISION"
	TLEventExecution  TLEventKind = "EXECUTION"
	TLEventApproval   TLEventKind = "APPROVAL"
	TLEventDenial     TLEventKind = "DENIAL"
	TLEventEscalation TLEventKind = "ESCALATION"
	TLEventSpend      TLEventKind = "SPEND"
	TLEventPolicy     TLEventKind = "POLICY_CHANGE"
	TLEventDispute    TLEventKind = "DISPUTE"
)

type Timeline

type Timeline struct {
	TenantID string          `json:"tenant_id"`
	From     time.Time       `json:"from"`
	To       time.Time       `json:"to"`
	Events   []TimelineEvent `json:"events"`
}

Timeline is a reconstructed chronological audit record.

func NewTimeline

func NewTimeline(tenantID string, from, to time.Time) *Timeline

NewTimeline creates an empty timeline for a period.

func (*Timeline) Add

func (t *Timeline) Add(event TimelineEvent)

Add inserts an event and keeps the timeline sorted.

func (*Timeline) Filter

func (t *Timeline) Filter(eventType TLEventKind) []TimelineEvent

Filter returns events matching a given type.

func (*Timeline) ForActor

func (t *Timeline) ForActor(actorID string) []TimelineEvent

ForActor returns events for a specific actor.

func (*Timeline) ForRun

func (t *Timeline) ForRun(runID string) []TimelineEvent

ForRun returns events for a specific run.

type TimelineEvent

type TimelineEvent struct {
	ID        string            `json:"id"`
	Timestamp time.Time         `json:"timestamp"`
	Type      TLEventKind       `json:"type"`
	ActorID   string            `json:"actor_id"`
	RunID     string            `json:"run_id,omitempty"`
	Summary   string            `json:"summary"`
	Evidence  []string          `json:"evidence_refs,omitempty"`
	Metadata  map[string]string `json:"metadata,omitempty"`
}

TimelineEvent is a single event in the audit timeline.

Jump to

Keyboard shortcuts

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