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.
72 lines
2.1 KiB
Go
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()
|
|
} |