Files
oikos/internal/db/queries/operations.sql
dtoro c9975d60a5 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)
2026-07-07 08:49:59 +02:00

57 lines
2.5 KiB
SQL

-- name: ListSignals :many
SELECT sig.entity_id, se.slug, sig.kind, sig.severity, sig.state,
te.slug AS target_slug, sig.check_id, sig.evidence, sig.likely_cause,
sig.occurrence_count, sig.flap_count, sig.hold_down_until,
sig.mute_until, sig.first_seen_at, sig.last_seen_at
FROM signals sig
JOIN entities se ON se.id = sig.entity_id
LEFT JOIN entities te ON te.id = sig.target_entity_id
WHERE (sqlc.narg('state')::text IS NULL OR sig.state = sqlc.narg('state'))
AND (sqlc.narg('severity')::text IS NULL OR sig.severity = sqlc.narg('severity'))
AND (sqlc.narg('target')::text IS NULL OR te.slug = sqlc.narg('target'))
AND (sqlc.narg('kind')::text IS NULL OR sig.kind = sqlc.narg('kind'))
AND (sqlc.narg('cursor')::text IS NULL OR se.slug > sqlc.narg('cursor'))
ORDER BY se.slug
LIMIT sqlc.arg('lim');
-- name: ListEntityStatus :many
SELECT e.slug, e.type, st.health, st.last_check_at
FROM entity_status st JOIN entities e ON e.id = st.entity_id
ORDER BY e.slug;
-- name: GetIdempotentResponse :one
SELECT response_code, response_body, request_hash FROM idempotency_keys
WHERE actor = $1 AND key = $2;
-- name: PutIdempotentResponse :exec
INSERT INTO idempotency_keys (actor, key, request_hash, response_code, response_body)
VALUES ($1, $2, $3, $4, $5)
ON CONFLICT (actor, key) DO NOTHING;
-- name: InsertAuditEntry :exec
INSERT INTO audit_log (actor_type, actor_id, action, entity_id, method, path,
status_code, detail, source_ip, correlation_id)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);
-- name: InsertEvent :one
INSERT INTO events (type, entity_id, severity, source, data, correlation_id)
VALUES ($1, $2, $3, $4, $5, $6)
RETURNING id, ts;
-- name: ListEvents :many
SELECT id, ts, type, entity_id, severity, source, data, correlation_id
FROM events
WHERE (sqlc.narg('type')::text IS NULL OR type = sqlc.narg('type'))
AND (sqlc.narg('entity_id')::uuid IS NULL OR entity_id = sqlc.narg('entity_id'))
AND (sqlc.narg('severity')::text IS NULL OR severity = sqlc.narg('severity'))
AND (sqlc.narg('correlation_id')::text IS NULL OR correlation_id = sqlc.narg('correlation_id'))
AND (sqlc.narg('from_ts')::timestamptz IS NULL OR ts >= sqlc.narg('from_ts'))
AND (sqlc.narg('to_ts')::timestamptz IS NULL OR ts <= sqlc.narg('to_ts'))
AND (sqlc.narg('before_id')::bigint IS NULL OR id < sqlc.narg('before_id'))
ORDER BY id DESC
LIMIT sqlc.arg('lim');
-- name: ListEventsAfter :many
SELECT id, ts, type, entity_id, severity, source, data, correlation_id
FROM events WHERE id > $1 ORDER BY id ASC LIMIT $2;