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
- Variables
- func MarshalAATJSONL(records []AATRecord) ([]byte, error)
- func VerifyAATChain(records []AATRecord) error
- type AATRecord
- type AATSignature
- type AATSigner
- type AuditEvidencePack
- type Ed25519AATSigner
- type Event
- type EventType
- type ExportRequest
- type Exporter
- type Logger
- type StoreLogger
- type TLEventKind
- type Timeline
- type TimelineEvent
Constants ¶
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 ¶
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") )
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 ¶
MarshalAATJSONL serializes records as JSON Lines, one JCS-canonical record per line. Output is byte-deterministic for identical input.
func VerifyAATChain ¶
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
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 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 ¶
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 NewLoggerWithWriter ¶
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
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 ¶
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.