plans: replace ASCII architecture diagrams with Mermaid
4 diagrams: container stack, OODA loop, knowledge graph, deploy flow
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user