phase 2 (part 2): sqlc queries, audit/event helpers, event NOTIFY trigger
- sqlc.yaml + internal/db/queries/*.sql: typed queries for entities, relationships, ontology, operations (signals, events, audit, idempotency, entity_status) - internal/db/sqlcgen/: generated Go from sqlc (pgx/v5) - internal/observability/record.go: Audit() and Event() helpers that write in the caller's transaction (SG10). actorLabel is interim text identity in detail JSON until OIDC resolution lands; actor_id column exists but is not yet populated - migrations/008: post-commit pg_notify trigger on events table for SSE fan-out (SG8/SG10)
This commit is contained in:
65
internal/observability/record.go
Normal file
65
internal/observability/record.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package observability
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/dtoro/oikos/internal/db/sqlcgen"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// Audit writes an audit_log entry. Pass a transaction-bound Queries so the
|
||||
// entry commits or rolls back atomically with the state change it records.
|
||||
//
|
||||
// actorLabel is the interim textual actor identity ("operator:dev",
|
||||
// "agent:mcp") recorded in detail; actor_id (a Person/Agent entity UUID)
|
||||
// starts being populated when OIDC identity resolution lands.
|
||||
func Audit(ctx context.Context, q *sqlcgen.Queries, actorType, actorLabel,
|
||||
action string, entityID *uuid.UUID, method, path, correlationID string,
|
||||
detail map[string]any) error {
|
||||
|
||||
if detail == nil {
|
||||
detail = map[string]any{}
|
||||
}
|
||||
detail["actor"] = actorLabel
|
||||
detailJSON, _ := json.Marshal(detail)
|
||||
|
||||
var corr *string
|
||||
if correlationID != "" {
|
||||
corr = &correlationID
|
||||
}
|
||||
return q.InsertAuditEntry(ctx, sqlcgen.InsertAuditEntryParams{
|
||||
ActorType: actorType,
|
||||
Action: action,
|
||||
EntityID: entityID,
|
||||
Method: &method,
|
||||
Path: &path,
|
||||
Detail: detailJSON,
|
||||
CorrelationID: corr,
|
||||
})
|
||||
}
|
||||
|
||||
// Event emits a structured event in the caller's transaction (SG10). The
|
||||
// post-commit NOTIFY trigger (migration 008) fans it out to SSE subscribers.
|
||||
func Event(ctx context.Context, q *sqlcgen.Queries, eventType string,
|
||||
entityID *uuid.UUID, severity, source string, correlationID string,
|
||||
data map[string]any) error {
|
||||
|
||||
dataJSON, _ := json.Marshal(data)
|
||||
if data == nil {
|
||||
dataJSON = []byte("{}")
|
||||
}
|
||||
var corr *string
|
||||
if correlationID != "" {
|
||||
corr = &correlationID
|
||||
}
|
||||
_, err := q.InsertEvent(ctx, sqlcgen.InsertEventParams{
|
||||
Type: eventType,
|
||||
EntityID: entityID,
|
||||
Severity: severity,
|
||||
Source: source,
|
||||
Data: dataJSON,
|
||||
CorrelationID: corr,
|
||||
})
|
||||
return err
|
||||
}
|
||||
Reference in New Issue
Block a user