plans: replace ASCII architecture diagrams with Mermaid

4 diagrams: container stack, OODA loop, knowledge graph, deploy flow
This commit is contained in:
2026-07-06 22:34:53 +02:00
parent bead722fac
commit fe54af30f6

View File

@@ -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