53 lines
1.2 KiB
Go
53 lines
1.2 KiB
Go
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...)
|
|
}
|
|
}
|