auditlog

package
v0.40.7 Latest Latest
Warning

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

Go to latest
Published: May 28, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package auditlog provides the dedicated audit-event stream for SpeechKit.

Audit events are separate from the runtime log (cmd/speechkit/logging.go): the runtime log is for operator troubleshooting (debug-level slog JSON); the audit log is the customer's source of truth for SOC 2 / ISO 27001 / BSI C5 evidence and DSGVO Art. 30 verification.

Schema is documented in docs/compliance/audit-event-catalog.md and versioned via the _schema_version field. Major-version bumps require a CHANGELOG entry with SIEM-ingestion migration notes.

Usage:

if err := auditlog.AppendEvent(ctx, auditlog.Record{
    Event: auditlog.EventProviderSelected,
    Actor: auditlog.Actor{UserSID: sid},
    Resource: map[string]any{
        "provider_name": "whisper-cpp",
        "provider_kind": "stt",
        "endpoint_host": "127.0.0.1:8123",
        "strategy":      "local-only",
    },
    Outcome: auditlog.OutcomeSuccess,
}); err != nil {
    slog.Warn("audit-log append failed", "err", err)
}

AppendEvent never returns an error that should crash the call site; it reports the failure via the returned error so the runtime log captures it. Call sites log-and-continue rather than abort the user action.

Index

Constants

View Source
const SchemaVersion = "1"

SchemaVersion is bumped when the audit-event JSON shape changes in a way that breaks downstream SIEM ingestion. Increment requires a CHANGELOG.md entry under "## Audit-Log Schema" with migration notes.

Variables

This section is empty.

Functions

func AppendEvent

func AppendEvent(ctx context.Context, ev Record) error

AppendEvent serialises one Record and appends it to today's audit log. Returns an error if the write fails; callers MUST log-and-continue rather than abort the user action.

The ctx parameter is reserved for future trace propagation; the current implementation ignores it.

func CloseEventLog

func CloseEventLog()

CloseEventLog is a no-op on non-Windows platforms.

func Configure

func Configure(enabled_ bool, dir string, retentionDays_ int, eventLogEnabled bool)

Configure is a backward-compatible wrapper around ConfigureFromOptions. Prefer ConfigureFromOptions for new call sites. When eventLogEnabled = true, each AppendEvent call also mirrors the record to the Windows Event Log source "kombify SpeechKit" (no-op on non-Windows). The source must be registered first via InstallEventLogSource (admin-required).

func ConfigureFromOptions

func ConfigureFromOptions(opts ConfigOptions) error

ConfigureFromOptions configures the audit-log package from a ConfigOptions value. Must be called once during startup before any AppendEvent call. When Enabled = false, all subsequent AppendEvent calls are no-ops. The file sink is always the canonical sink; Event Log and OTLP are mirrors. Failure to open optional sinks (Event Log, OTLP) is non-fatal and is logged at slog.Warn; the file sink remains active regardless.

func ConfigureOTLP

func ConfigureOTLP(endpoint, certFile, keyFile, caFile string) error

ConfigureOTLP creates an OTLP exporter targeting endpoint with optional mTLS. Returns nil when endpoint is empty (sink disabled). Idempotent: re-calling shuts down the previous provider and starts a new one.

Endpoint format: hostname:port (e.g. "loki.internal.example:4318"). HTTPS with mTLS is used when certFile + keyFile are provided. Plain HTTP (no TLS) is used when no cert files are present — suitable for dev/test deployments behind an authenticating proxy.

caFile is optional; when non-empty its PEM certificate(s) are added to the root CA pool for server-certificate verification.

func InstallEventLogSource

func InstallEventLogSource() error

InstallEventLogSource is a no-op on non-Windows platforms.

func OpenEventLog

func OpenEventLog() error

OpenEventLog is a no-op on non-Windows platforms.

func ResetForTests

func ResetForTests()

ResetForTests releases the current file handle and clears all package state. INTENDED FOR TEST USE ONLY. Call from internal/auditlogtest.Reset (not directly from outside this module). A direct production call silently destroys the audit stream — a compliance bug.

func ShutdownOTLP

func ShutdownOTLP()

ShutdownOTLP flushes pending records and closes the provider. Called from ResetForTests and during graceful shutdown. Safe to call when not configured.

Types

type Actor

type Actor struct {
	UserSID   string `json:"user_sid,omitempty"`
	SessionID string `json:"session_id,omitempty"`
}

Actor identifies who or what triggered the audited action.

type ConfigOptions

type ConfigOptions struct {
	// Enabled gates the entire audit log. When false, AppendEvent is a no-op.
	Enabled bool
	// Dir is the directory under which audit-YYYY-MM-DD.log files are written.
	Dir string
	// RetentionDays is the number of days to keep audit files. Zero → 90 days.
	RetentionDays int
	// EventLogEnabled mirrors records to the Windows Event Log source
	// "kombify SpeechKit". No-op on non-Windows.
	EventLogEnabled bool
	// OTLPEndpoint is the host:port of the OTLP HTTP log receiver. Empty
	// disables the OTLP sink.
	OTLPEndpoint string
	// OTLPCertFile and OTLPKeyFile enable mTLS for the OTLP sink when both
	// are non-empty. OTLPCAFile is optional and adds to the root CA pool.
	OTLPCertFile string
	OTLPKeyFile  string
	OTLPCAFile   string
}

ConfigOptions holds all configuration for the audit-log package. Use ConfigureFromOptions instead of the older positional-arg Configure. The options struct scales for additional sinks (Phase 3+) without growing the positional-arg list further.

type Event

type Event string

Event is the namespaced identifier of an audit event type. Every event used in code MUST appear here and in docs/compliance/audit-event-catalog.md.

const (
	EventProviderSelected       Event = "provider.selected"
	EventVoiceAgentSessionStart Event = "voiceagent.session.start"
	EventVoiceAgentSessionEnd   Event = "voiceagent.session.end"
	EventSettingsChanged        Event = "settings.changed"
	EventUpdateInstalled        Event = "update.installed"
	EventAuthFailed             Event = "auth.failed"
	EventPrivacyExport          Event = "privacy.export"
	EventPrivacyDelete          Event = "privacy.delete"
	// EventPolicyApplied is emitted once at startup after config is loaded,
	// when registry policy values are present. Resource fields: "source"
	// (registry hive that first contributed a value) and "keys_locked_count"
	// (total number of registry values that overrode config.toml).
	EventPolicyApplied Event = "policy.applied"

	// EventBYOKKeyUpdated is emitted when the customer sets a new BYOK API key
	// for any provider (OpenAI, Groq, Google, HuggingFace). Resource fields:
	// "provider_name" (string), "region" (string, empty for non-regional
	// providers), "fingerprint_truncated" (first 16 hex chars of SHA-256 of the
	// key — correlates events without leaking the key itself).
	EventBYOKKeyUpdated Event = "byok.key_updated"

	// EventModeStart is emitted when a SpeechKit mode runtime transitions to
	// Running (Outcome=success) or to Failed from Starting (Outcome=failure).
	// Source: subscribers of pkg/speechkit/lifecycle.Registry. Resource
	// fields: "mode" (string), "requires" (array of SharedDepKey, omitted
	// when empty), "error" (string, only on failure). See
	// docs/compliance/audit-event-catalog.md "mode.start" for the full
	// contract incl. the mode.start/mode.stop pairing rule.
	EventModeStart Event = "mode.start"

	// EventModeStop is emitted when a SpeechKit mode runtime transitions to
	// Stopped (Outcome=success) or to Failed from Stopping (Outcome=failure).
	// Resource fields mirror EventModeStart with "released" instead of
	// "requires" — the shared deps the runtime relinquished as it stopped.
	EventModeStop Event = "mode.stop"
)

type Outcome

type Outcome string

Outcome is the success/failure state of the audited action.

const (
	OutcomeSuccess Outcome = "success"
	OutcomeFailure Outcome = "failure"
)

type Record

type Record struct {
	SchemaVersion string         `json:"_schema_version"`
	Timestamp     time.Time      `json:"ts"`
	Event         Event          `json:"event"`
	Actor         Actor          `json:"actor"`
	Resource      map[string]any `json:"resource,omitempty"`
	Outcome       Outcome        `json:"outcome"`
	TraceID       string         `json:"trace_id,omitempty"`
}

Record is the serialised shape of one audit-log line.

Jump to

Keyboard shortcuts

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