package engine import ( "context" "log/slog" "git.cloudinit.dev/coreci/orca/internal/store" ) // Audit wraps a slog.Logger and persists structured audit entries to SQLite. type Audit struct { repo *store.AuditRepo log *slog.Logger } func NewAudit(repo *store.AuditRepo, log *slog.Logger) *Audit { if log == nil { log = slog.Default() } return &Audit{repo: repo, log: log} } func (a *Audit) Record(ctx context.Context, actor, action, resource, result string, err error, meta map[string]any) { entry := &store.AuditEntry{ Actor: actor, Action: action, Resource: resource, Result: result, Metadata: meta, } if err != nil { entry.Error = err.Error() } if persistErr := a.repo.Append(ctx, entry); persistErr != nil { a.log.Error("audit persist failed", slog.String("action", action), slog.String("resource", resource), slog.String("error", persistErr.Error())) } attrs := []any{ slog.String("actor", actor), slog.String("action", action), slog.String("resource", resource), slog.String("result", result), } if err != nil { attrs = append(attrs, slog.String("error", err.Error())) a.log.Warn("audit", attrs...) } else { a.log.Info("audit", attrs...) } }