0.22.0 — full MCP agent surface: 19 new tools, async run, session reliability
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

Stage 1 — Foundation:
- Target validation: iptables + systemctl/docker target-type gates
- Async run for long-running commands (sleep/wait/poll loops)
- audit_log.session_id plumbing (SQL, sqlcgen, 18 call sites)

Stage 2 — External agent observe (11 tools):
- get_dashboard_summary, get_ontology, list_checks, list_executions
- get_knowledge_revisions, get_knowledge_duplicates, get_knowledge_orphans
- list_knowledge_tags, list_entity_sessions, find_entities_by
- 3 resource templates: oikos://entity/{slug}, knowledge/{id}, execution/{id}

Stage 3 — Nomos reliability:
- complete_task(success) refused without verification (upgraded from warn)
- sessionHasPlan excludes replaced steps (forces propose_plan after reopen)
- Bash syntax validation in run() (rejects literal \n, flag-space typos)
- Scope gate in SOUL.md (ask before pivoting to unrelated subsystem)

Stage 4 — External agent act (9 mutation tools):
- ack_signal, resolve_signal, mute_signal, cancel_execution
- update_check, delete_knowledge, restore_knowledge
- merge_knowledge, rename_knowledge_tag
This commit is contained in:
2026-08-04 23:51:55 +02:00
parent 85f0bb67fa
commit 4e294b3630
20 changed files with 1264 additions and 41 deletions

View File

@@ -818,7 +818,7 @@ func (s *Server) QueryAudit(ctx context.Context, req gen.QueryAuditRequestObject
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
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)
@@ -839,10 +839,10 @@ func (s *Server) QueryAudit(ctx context.Context, req gen.QueryAuditRequestObject
for rows.Next() {
var a gen.AuditEntry
var detailBytes []byte
var actID, entID, method, path, sourceIP, corrID *string
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); err != nil {
&method, &path, &statusCode, &detailBytes, &sourceIP, &corrID, &sessionID); err != nil {
return nil, err
}
a.ActorId = actID
@@ -1000,6 +1000,7 @@ func (s *Server) CreateEntity(ctx context.Context, req gen.CreateEntityRequestOb
entityID := inserted.ID
if auditErr := observability.Audit(ctx, q, actorType, actor, "create",
&entityID, "POST", "/api/v1/entities", "",
nil,
map[string]any{"type": req.Body.Type, "slug": slug}); auditErr != nil {
return nil, auditErr
}
@@ -1110,6 +1111,7 @@ func (s *Server) PatchEntity(ctx context.Context, req gen.PatchEntityRequestObje
patchActorType, patchActor := actorInfo(ctx)
if auditErr := observability.Audit(ctx, q, patchActorType, patchActor, "patch",
&id, "PATCH", "/api/v1/entities/"+req.Id, "",
nil,
map[string]any{"version": expectedVersion}); auditErr != nil {
return nil, auditErr
}
@@ -1239,6 +1241,7 @@ func (s *Server) EnrollClient(ctx context.Context, req gen.EnrollClientRequestOb
entityID := id
_ = observability.Audit(ctx, q, "operator", actor, "enroll",
&entityID, "POST", "/api/v1/clients/enroll", "",
nil,
map[string]any{"slug": req.Body.Slug, "mesh_ip": meshIP})
_ = observability.Event(ctx, q, "client.enrolled", &entityID,
"info", "oikos-api", "",
@@ -1433,6 +1436,7 @@ func (s *Server) ProvisionEntity(ctx context.Context, req gen.ProvisionEntityReq
_, actor := actorInfo(ctx)
_ = observability.Audit(ctx, q, "operator", actor, "provision",
&entityID, "POST", "/api/v1/entities/provision", "",
nil,
map[string]any{"slug": req.Body.Slug, "host": hostSlug})
_ = observability.Event(ctx, q, "entity.provisioned", &entityID,
"info", "oikos-api", "",