From fe54af30f69cdbe389ed968baea42363c97af9e8 Mon Sep 17 00:00:00 2001 From: dtoro Date: Mon, 6 Jul 2026 22:34:53 +0200 Subject: [PATCH] plans: replace ASCII architecture diagrams with Mermaid 4 diagrams: container stack, OODA loop, knowledge graph, deploy flow --- ...idate-oikos-control-plane-onto-mac-mini.md | 141 +++++++++++------- 1 file changed, 85 insertions(+), 56 deletions(-) diff --git a/plans/2026-07-06-consolidate-oikos-control-plane-onto-mac-mini.md b/plans/2026-07-06-consolidate-oikos-control-plane-onto-mac-mini.md index a98508e..2526cf8 100644 --- a/plans/2026-07-06-consolidate-oikos-control-plane-onto-mac-mini.md +++ b/plans/2026-07-06-consolidate-oikos-control-plane-onto-mac-mini.md @@ -43,63 +43,92 @@ to multi-node later. ## Target architecture -``` -┌──────────────────────────────────────────────────────────────────────┐ -│ mac-mini (Docker host, always-on) │ -│ │ -│ ┌──────────────┐ ┌────────────┐ ┌───────────────────────────┐ │ -│ │ PostgreSQL │ │ Infisical │ │ Hermes Agent (gateway) │ │ -│ │ │ │ (secrets) │ │ + homelab skills │ │ -│ │ • inventory │ │ │ │ + MCP client → API │ │ -│ │ • signals │ │ │ │ + SSH keys (mounted) │ │ -│ │ • ledger │ │ │ │ │ │ -│ │ • knowledge │ │ │ │ Any workstation connects │ │ -│ │ • state │ │ │ │ via Hermes gateway protocol │ │ -│ │ • approvals │ │ │ │ │ │ -│ └──────┬────────┘ └─────────────┘ └──────────┬────────────────┘ │ -│ │ │ │ -│ ┌──────┴─────────────────────────────────────────┴──────────────┐ │ -│ │ Oikos API (REST + MCP, one service) │ │ -│ │ │ │ -│ │ MCP interface (agent context): │ │ -│ │ get_host, list_services, search_knowledge, get_entity, │ │ -│ │ get_relations, get_change_history, get_state_snapshot │ │ -│ │ │ │ -│ │ REST interface (operations + operator): │ │ -│ │ GET /api/v1/hosts, /services, /signals, /approvals │ │ -│ │ POST /api/v1/exec — gated execution (actuator) │ │ -│ │ POST /api/v1/approve — operator approval │ │ -│ │ POST /api/v1/deploy — trigger service deploy │ │ -│ │ WS /api/v1/events — real-time signal/approval stream │ │ -│ │ │ │ -│ │ Policy enforcement, risk classification, ledger recording │ │ -│ └──────────────────────┬───────────────────────────────────────────┘ │ -│ │ │ -│ ┌──────────────────────┴───────────────────────────────────────────┐ │ -│ │ Scheduler (Observe) + Actuator (Act) │ │ -│ │ • Periodic probes (10-min) → signals in DB │ │ -│ │ • Reads open signals, classifies via decide.py │ │ -│ │ • Auto-acts (reversible_low) or escalates (approval) │ │ -│ │ • SSH to hubris/strong for probes + execution │ │ -│ └──────────────────────┬───────────────────────────────────────────┘ │ -│ │ │ -│ ┌──────────────────────┴───────────────────────────────────────────┐ │ -│ │ Notifier (abstracted, pluggable) │ │ -│ │ • Matrix (current) — alerts, approval requests │ │ -│ │ • Future: webhook, email, Slack, etc. │ │ -│ └──────────────────────────────────────────────────────────────────┘ │ -│ │ -│ Deploy: Gitea webhook → docker compose build + up -d │ -│ Volumes: pg-data, infisical-data, ssh-keys (ro mount), hermes-config │ -│ Network: Docker bridge (internal) + host network (SSH outbound) │ -└──────────────────────────────────────────────────────────────────────┘ +### Container stack on mac-mini -External: - Caddy (LXC 121) → mac-mini mesh IP :8090 (API), future UIs - apps/105 → fallback, kept running until Docker OS proven - hubris/strong → SSH targets for scheduler/actuator - Any workstation → Hermes gateway (connects to agent in Docker) - Gitea (LXC 104) → webhook triggers Docker rebuild +```mermaid +graph TB + subgraph mac-mini["mac-mini — Docker host, always-on"] + subgraph services["Docker Compose"] + PG["PostgreSQL\n• inventory (synced from YAML)\n• signals • ledger\n• knowledge graph\n• state snapshots\n• approvals"] + INF["Infisical\n(secrets manager)"] + HERMES["Hermes Agent — gateway mode\n+ homelab skills\n+ MCP client → API\n+ SSH keys (mounted)"] + API["Oikos API — REST + MCP\n\nMCP: get_host, list_services,\nsearch_knowledge, get_relations\nREST: /hosts, /services, /signals,\n/exec, /approve, /deploy, /events\n\nPolicy enforcement + risk\nclassification + ledger"] + SCHED["Scheduler (Observe)\n+ Actuator (Act)\n• 10-min probes → DB\n• Classify → auto-act or escalate\n• SSH to hubris/strong"] + NOTIFIER["Notifier — abstracted\n• Matrix (current): alerts,\napproval requests\n• Future: webhook, email, etc."] + end + DEPLOY["Gitea webhook →\ndocker compose build + up -d"] + VOLS["Volumes: pg-data, infisical-data,\nssh-keys (ro), hermes-config"] + end + + HERMES -- MCP --> API + API --> PG + SCHED --> PG + SCHED -- SSH --> HUBRIS + SCHED -- SSH --> STRONG + API -- "escalate" --> NOTIFIER + NOTIFIER -- "alerts + approvals" --> MATRIX + DEPLOY -- "rebuild" --> services + + subgraph external["External"] + CADDY["Caddy (LXC 121)\n→ mac-mini mesh :8090"] + APPS["apps/105 (fallback)\nkept running until proven"] + HUBRIS["hubris (PVE)"] + STRONG["strong (PVE)"] + GITEA["Gitea (LXC 104)\nwebhook trigger"] + MATRIX["Matrix (LXC 118)"] + WS["Any workstation\nHermes remote → gateway"] + end + + CADDY -- reverse_proxy --> API + GITEA -- webhook --> DEPLOY + WS -- "Hermes gateway" --> HERMES + APPS -. "fallback" .- API +``` + +### OODA loop — the control flow + +```mermaid +flowchart LR + OBSERVE["Observe\nScheduler probes:\n• HTTP health\n• disk usage\n• drift detection"] --> ORIENT["Orient\nRelations graph walk:\n• blast radius\n• lifecycle state\n• runbook match"] + ORIENT --> DECIDE["Decide\nRisk classifier:\nrisk × blast × confidence"] + DECIDE -- "auto-act\n(reversible_low,\ncontained, confident)" --> ACT["Act\nExecute via SSH/API\n→ verify → resolve\n→ ledger entry"] + DECIDE -- "escalate\n(approval needed)" --> APPROVE["Approval request\n→ Matrix ✅/❌\n→ grant or deny"] + APPROVE -- "approved" --> ACT + APPROVE -- "denied" --> RESOLVE["Resolve signal\nnote: denied"] + ACT --> OBSERVE +``` + +### Knowledge graph — docs to DB + +```mermaid +flowchart TB + subgraph repo["Repo (git-tracked)"] + INV["inventory.yaml\ndeclarative topology"] + DOCS["docs/\n• containers/105-apps.md\n• hosts/hubris.md\n• infrastructure/dns.md\n• investigations/..."] + end + subgraph db["PostgreSQL"] + ENT["entities table\n(host:hubris, service:caddy, ...)"] + REL["relations table\n(hosts, provides, depends-on, ...)"] + KNOW["knowledge_entities table\n(doc:105-apps, doc:hubris, ...)"] + KNOWREL["knowledge_relations table\n(describes, relates-to, runbook-for)"] + end + INGEST["Ingest pipeline\n(runs on deploy)"] + INV --> INGEST --> ENT + INV --> INGEST --> REL + DOCS --> INGEST --> KNOW + DOCS --> INGEST --> KNOWREL + KNOW -. "linked by entity_id" .- ENT +``` + +### Deploy flow + +```mermaid +flowchart LR + DEV["Operator\nedits repo"] --> PUSH["git push"] --> GITEA["Gitea\n(LXC 104)"] + GITEA -- "webhook" --> MACMINI["mac-mini\ndeploy script"] + MACMINI -- "git pull" --> REPO["repo clone"] + MACMINI -- "docker compose\nbuild + up -d" --> STACK["OS containers\nrebuilt + restarted"] + STACK -- "ingest" --> DB["PostgreSQL\nupdated"] ``` ## Repo reorganization