- .agents/OIKOS.md: rewrote entire Build Status section from Python 30-day roadmap to Go Phases 1-6 status. Added Python-era backlog preservation. - knowledge/wiki/containers/105-apps.md: added DEPRECATED notices for homelab-mcp and secrets-issuance services, pointing to Go equivalents and cutover checklist. - knowledge/wiki/infrastructure/auto-deploy.md: marked webhook ids 10+11 as deprecated, replaced Go Docker stack. - knowledge/wiki/infrastructure/index.md: noted topology gen as Python with Go DB-native replacement planned. - .agents/operations/hermes-agent.md: updated MCP references from FastMCP SSE Python to Streamable HTTP Go SDK. - .agents/shared/writing-style.md: updated MCP reference, topology note. - .agents/domains/knowledge/schema.md: updated MCP server reference.
9.7 KiB
Oikos — the operating model
Oikos (Greek: household) is the agent operating system layered on this
repo. It is not new infrastructure: inventory.yaml is the kernel data
structure, the homelab CLI and MCP server are the syscall surface, and
this page defines the rules everything above them follows.
Read this after AGENTS.md. Machine-readable companions: oikos/ontology.yaml (systems model), oikos/policy.yaml (risk & approval).
The kernel loop: OODA
Every Oikos activity — scheduled probe, agent task, operator request — is one pass through Observe → Orient → Decide → Act:
- Observe — probes, drift detectors, and agent findings produce Signals (structured records, not loose messages): pending updates, high temperature, low disk, service down, cert expiry, stale backup, inventory drift.
- Orient — walk the ontology graph: what entity is affected, what depends on it (blast radius), its lifecycle state, whether a runbook matches, what the ledger says about past attempts.
- Decide — the classifier scores risk class × blast radius ×
confidence and routes:
- auto-act: within autonomy policy, high confidence, contained radius
- escalate: operator approval via Matrix (✅/❌ reaction) or the
Oikos Console's
/approvalspage (destructive actions additionally need a typed confirmation phrase either way) - queue: informational — console + reports The classifier can only lower autonomy relative to policy, never raise it. When in doubt, escalate.
- Act — execute through
homelabcommands or runbooks (never ad-hoc SSH), then verify with the action's verification command, write a ledger entry, resolve the Signal, and update docs in the same session.
Primitives
| Primitive | What it is | Lives in |
|---|---|---|
| Host / Service | topology entities | inventory.yaml (+ generated hosts/*.yaml) |
| Secret | SOPS+age encrypted value, per-client recipients | secrets/ + .sops.yaml |
| Runbook | executable workflow with risk class + verification | .agents/skills/<name>/SKILL.md |
| Signal | something needing attention, with lifecycle | signals/ ledger (Week 3) |
| Change | one mutation: who, what, risk, approval, verification | ledger/ (Week 2) |
| Approval | short-TTL signed grant for a gated action | approval engine (Week 3) |
| Incident | investigation narrative | knowledge/sources/investigations/ |
| Plan | design doc for non-trivial work | plans/ |
| Agent | enrolled client identity = its age pubkey | inventory.yaml + .sops.yaml |
Risk classes (enforced, not advisory)
From oikos/policy.yaml:
- read_only — status, logs, docs, inventory. Unattended.
- reversible_low — restart, cache clear, sync pull. Unattended + ledger.
- config_mutation — tracked-config edits (commit+push, never local), deploys, upgrades, DNS/ingress changes. Operator approval.
- destructive — destroy, format, wipe, rotate, revoke. Approval + typed confirmation phrase.
Lifecycle gates modify these: provisioning nodes are freely mutable
(nothing depends on them); deprecated nodes accept no new dependents;
anything touching a destroyed node is drift.
The systems model
Eight domains — physical, compute, network, storage, software,
identity & access, operations, external — cover everything in the lab;
entities are connected by typed edges (hosts, provides, mounts,
stores-on, routes-to, can-decrypt, depends-on, backs-up-to, …)
defined in oikos/ontology.yaml. Rule of
completeness: if it can break, be changed, or hold data, it has an
entity and edges. Blast-radius questions ("what breaks if strong goes
down?") are graph walks, not doc archaeology.
Nodes move through an explicit lifecycle —
planned → provisioning → active → migrating → deprecated → destroyed —
stored as state: in inventory (absent = active). Destroyed nodes live in
the archaeology: section. Each transition is a runbook checklist;
deprecation completes only when inbound edges reach zero.
Generated views: infrastructure/topology.md
(Mermaid, regenerated from inventory) and the live, clickable version at
oikos.hubris.network/graph once the Console is deployed.
Conventions carried forward
- Inventory is the truth; live state wins over narrative docs.
- Prefer
homelabCLI and MCP over ad-hoc SSH. - Meaningful changes update docs in the same session.
- Secrets are decrypted locally via per-client keys; never into docs/comments.
- Tracked configs change by commit + push, not local edits.
- Netbird is the preferred mesh path for new traffic.
- Agents are terse (caveman.md), verify claims, and fix collateral drift when found.
Build status (Go rewrite — 2026-07-06 consolidation plan)
The Oikos runtime was rewritten from Python to Go over 6 phases. See
plans/2026-07-06-consolidate-oikos-control-plane-onto-mac-mini.md
for the full plan. The Python codebase (oikos/*.py, mcp/server.py,
oikos/console/) is legacy — the Flask console and Python MCP server have
been removed. The Python kernel files (oikos/*.py) remain only because
bin/homelab still imports them for operational CLI commands.
Phase 1 — Ontology + DB (DONE):
migrations/(001–009): TimescaleDB hypertables, entity_status, CAGGs, retention policies. Forward-only, idempotent.seeds/{ontology,inventory,policy}.yaml: DB-native bootstrap + DR export.blast_radius()SQL CTE, type hierarchy, abstract types, relationship validation.- Go packages:
internal/db/,internal/ontology/,internal/domain/.
Phase 2 — API (DONE):
- Single binary
cmd/oikoswithoikos apiserving REST (:8090) + MCP on the same service layer. OpenAPI-first (api/openapi.yaml) with oapi-codegen + chi. RFC 9457 problem+json errors. Cursor pagination, If-Match/ETag optimistic concurrency, idempotency keys, SSE event stream, OIDC JWT + static bearer auth, audit middleware. - Go packages:
internal/httpapi/,internal/httpapi/gen/.
Phase 3 — Control loop (DONE):
- Scheduler (
oikos scheduler): check_defs runner, signal dedup/flap suppression, entity_status. HTTP, TCP, disk, cert-expiry probes. - Actuator: SSH skill procedure execution with context-aware timeouts, circuit breaker, retry budgets, error classification.
- Learning engine: hourly pattern extraction, Wilson confidence bounds, anomaly detection, skills with validated patterns.
- Notifier: Matrix badge delivery, approval token generation (HMAC, single-use, hashed), DB rendezvous pattern.
- Policy classifier: risk class determination, autonomy routing, blast-radius computation, kill-switch support.
- Go packages:
internal/scheduler/,internal/actuator/,internal/learning/,internal/notifier/,internal/policy/.
Phase 4 — Agent / Hermes (DONE):
- Standalone Hermes MCP client binary (
cmd/hermes) with gateway mode (:8092). Structured queries + natural-language routing to 15 MCP tools. Agent activity logging on every tool call. No SSH keys. hermes/directory with config, SOUL.md, homelab-ops skill.- Hermes Docker service in
docker-compose.yml(profile: full). - Go packages:
cmd/hermes/,compose/hermes/.
Phase 5 — Secrets / Infisical (DONE):
internal/secrets/: backend abstraction (Manager) with primary (Infisical) and fallback (SOPS) backends. Machine identities via UniversalAuth. In-memory cache with TTL.oikos secretCLI: list, migrate (SOPS → Infisical), export-sops (DR fallback). Infisical SDK v0.8.0.- Rotation runbook at
secrets/rotation.md. - Docker compose:
infisical+redisservices (profile: infisical).
Phase 6 — Deploy + cutover (DONE, pending production cutover):
- CI pipeline:
.gitea/workflows/ci.yml(Gitea Actions — build, vet, lint, test, docker build). - Deploy:
scripts/deploy.sh(git pull → docker build → compose up → health check), SHA-tagged images, rolling restart. - Caddy config:
compose/caddy/Caddyfile.oikos(oikos/mcp/hermes → mac-mini mesh :8090/:8092). - Watchdog:
scripts/watchdog.sh(2min cron, Matrix alert on failure). - Verification:
scripts/verify-phase6.sh(14/14 checks pass). - Rollback:
scripts/rollback.sh(checkout SHA + pg_restore). - Cutover checklist:
scripts/cutover-checklist.md.
Current deployment:
- Dev stack:
docker compose --profile dev up(postgres, api, scheduler, notifier) on mac-mini. Hermes runs with--profile full. - Production: apps/105 still hosts the Python MCP + secrets-issuance.
Cutover checklist at
scripts/cutover-checklist.mdis the execution plan to move production to the Docker stack.
Python-era backlog (superseded)
The original 30-day roadmap (Python, shipped 2026-06/07) delivered:
context cards, change ledger, node relations, runbooks, ops scheduler,
drift detectors, signal engine, classifier, approval engine, and the
FastAPI+Jinja2 Oikos Console. All of these have been re-implemented in
the Go rewrite. The backlog items below that referenced Python paths
(oikos/approve.py, oikos/drift.py, oikos/console/) are now addressed
by the Go equivalents listed above.
Outstanding from the Python era (not yet in Go):
- Prometheus provisioning (see plans/2026-07-05-oikos-prometheus-lxc.md)
- CPU/NVMe temperature probing (blocked on sensor path discovery)
- SSH-key-signed approval requests (blocked on inventory schema)
- Multi-agent delegation (blocked on ledger identity field)
- Restore drills on a schedule