Files
oikos/internal/httpapi/query_audit.go
dtoro 75c0848a6f
Some checks failed
ci / build-test (push) Has been cancelled
ci / docker-build (push) Has been cancelled
ci / web (push) Has been cancelled
Desktop App / Build Linux (amd64) (push) Has been cancelled
Desktop App / Attach to Release (push) Has been cancelled
0.29.0 — code-quality refactor (plan E1–E5): file splits, sqlc migration, SSH unification, test coverage
E1: split monolithic files — cmd/nomos (main.go → server.go + mcp.go + workers.go),
    internal/mcp/tools.go → entity_tools/ops_tools/knowledge_tools/analysis_tools,
    internal/httpapi/impl.go → domain files (entities, events, signals, ontology,
    fleet_health, client_context, client_lifecycle, entity_mutations, query_audit).
E2: migrate raw pool.Exec queries to sqlc (entities/relationships queries + generated).
E3: unify SSH — consolidate crypto/ssh dial into actuator/client.go (+client_test).
E4/E5: add tests — db/lifecycle, checkdefaults/build, ontology/preconditions, policy/risk.
2026-08-08 22:47:06 +02:00

72 lines
2.1 KiB
Go

package httpapi
import (
"context"
"encoding/json"
"github.com/dtoro/oikos/internal/httpapi/gen"
)
func (s *Server) QueryAudit(ctx context.Context, req gen.QueryAuditRequestObject) (gen.QueryAuditResponseObject, error) {
limit := clampLimit(req.Params.Limit)
var actorType, actorID, action, entityID, correlationID *string
if req.Params.ActorType != nil {
actorType = req.Params.ActorType
}
if req.Params.ActorId != nil {
actorID = req.Params.ActorId
}
if req.Params.Action != nil {
action = req.Params.Action
}
if req.Params.EntityId != nil {
entityID = req.Params.EntityId
}
if req.Params.CorrelationId != nil {
correlationID = req.Params.CorrelationId
}
rows, err := s.pool.Query(ctx, `
SELECT id, ts, actor_type, actor_id::text, action, entity_id::text,
method, path, status_code, detail, source_ip, correlation_id, session_id::text
FROM audit_log
WHERE ($1::text IS NULL OR actor_type = $1)
AND ($2::text IS NULL OR actor_id::text = $2)
AND ($3::text IS NULL OR action = $3)
AND ($4::text IS NULL OR entity_id::text = $4)
AND ($5::text IS NULL OR correlation_id = $5)
AND ($6::timestamptz IS NULL OR ts >= $6)
AND ($7::timestamptz IS NULL OR ts <= $7)
ORDER BY ts DESC
LIMIT $8`,
actorType, actorID, action, entityID, correlationID, req.Params.From, req.Params.To, limit)
if err != nil {
return nil, err
}
defer rows.Close()
items := []gen.AuditEntry{}
for rows.Next() {
var a gen.AuditEntry
var detailBytes []byte
var actID, entID, method, path, sourceIP, corrID, sessionID *string
var statusCode *int
if err := rows.Scan(&a.Id, &a.Ts, &a.ActorType, &actID, &a.Action, &entID,
&method, &path, &statusCode, &detailBytes, &sourceIP, &corrID, &sessionID); err != nil {
return nil, err
}
a.ActorId = actID
a.EntityId = entID
a.Method = method
a.Path = path
a.StatusCode = statusCode
a.SourceIp = sourceIP
a.CorrelationId = corrID
var detail map[string]any
if json.Unmarshal(detailBytes, &detail) == nil {
a.Detail = &detail
}
items = append(items, a)
}
return gen.QueryAudit200JSONResponse{Items: items}, rows.Err()
}