docs: update for Go rewrite reality — OIKOS.md build status, deprecation notices
- .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.
This commit is contained in:
207
.agents/OIKOS.md
207
.agents/OIKOS.md
@@ -95,133 +95,94 @@ Generated views: [infrastructure/topology.md](../knowledge/wiki/infrastructure/t
|
||||
- Agents are terse ([caveman.md](shared/caveman.md)), verify claims, and fix
|
||||
collateral drift when found.
|
||||
|
||||
## Build status (30-day roadmap, started 2026-07-05)
|
||||
## Build status (Go rewrite — 2026-07-06 consolidation plan)
|
||||
|
||||
- **Week 1**: policy, ontology, service contract, archaeology, topology
|
||||
generator, this brief. Shipped.
|
||||
- **Week 2**: context cards, `homelab service <name> …`, change ledger,
|
||||
`node relations`, runbooks. Shipped.
|
||||
- **Week 3**: ops scheduler + state cache (`homelab service <name> health`
|
||||
is cache-first, `--live` forces a probe), drift detectors, signal engine
|
||||
(`homelab signal …`), decision classifier (`homelab decide …`), approval
|
||||
engine (`homelab approval …` — shared-HMAC grants; Matrix delivery is
|
||||
Hermes's existing `@dtoro:avispero` send path, not a new bot, see
|
||||
`oikos/approve.py`), daily brief + weekly report (`oikos/report.py`).
|
||||
Shipped, except: Prometheus is still `planned` (see
|
||||
[plans/2026-07-05-oikos-prometheus-lxc.md](../plans/2026-07-05-oikos-prometheus-lxc.md)) —
|
||||
trend signals (disk-full prediction, temp creep) wait on that LXC; the
|
||||
scheduler's disk check today is point-in-time only, and CPU/NVMe
|
||||
temperature isn't probed at all yet (no confirmed sensor path on
|
||||
hubris/strong). DNS-vs-inventory and generic tracked-config-cleanliness
|
||||
drift checks are also deferred (see `oikos/drift.py` docstring).
|
||||
- **Week 4**: Oikos Console v0 shipped — signals landing page, service
|
||||
grid + detail, node/blast-radius view, live Mermaid graph, drift view,
|
||||
approvals queue (approve/deny, destructive confirmation-phrase
|
||||
enforced), daily/weekly reports. Server-rendered FastAPI + Jinja2, no
|
||||
SPA build chain, tested end-to-end against live production data (see
|
||||
`oikos/console/`). Deploys as a third webhook on `dtoro/Homelab-Docs`
|
||||
(`/opt/oikos-console`, port :9831) — see
|
||||
[oikos/console/deploy/README.md](../oikos/console/deploy/README.md) for
|
||||
the Caddy route and Gitea webhook registration this repo can't do for
|
||||
itself. Approval grants are now single-use (a second `check_grant` call
|
||||
for the same request fails even within the TTL) and already exact-bound
|
||||
to request id + entity + action.
|
||||
**Not shipped as originally planned:** per-agent *age-key-signed*
|
||||
request authentication — age has no signing primitive (it's an
|
||||
encryption-only keypair format), so "age-key-signed" wasn't
|
||||
buildable as stated. The real alternative (SSH-key signing via
|
||||
`ssh-keygen -Y sign`/`-Y verify`, using each host's already-provisioned
|
||||
SSH key) is real and buildable, but needs SSH public keys recorded in
|
||||
inventory first — not there today. Moved to the 60/90-day backlog.
|
||||
Authentik step-up re-auth on the approve/deny route is documented but
|
||||
needs a live Authentik instance to configure — also backlog.
|
||||
Docs pass done (this file, AGENTS.md, operations/commands.md); found
|
||||
and fixed two more stale references while at it (DNS section still
|
||||
pointed at destroyed LXC 124/dnsmasq instead of Technitium on 107, and
|
||||
a `claudio-monitor` reference that's been deprecated since 2026-06-04).
|
||||
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](../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.
|
||||
|
||||
### Real drift found while building Week 3 (unresolved, needs operator action)
|
||||
**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/`.
|
||||
|
||||
The drift detectors surfaced genuine, currently-true findings on first
|
||||
run against production — recorded here rather than silently fixed, since
|
||||
each is a `config_mutation`/`destructive`-class decision:
|
||||
**Phase 2 — API (DONE):**
|
||||
- Single binary `cmd/oikos` with `oikos api` serving 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/`.
|
||||
|
||||
- `republic-laptop` has no `age_pubkey:` in `inventory.yaml`, but its real
|
||||
age key is granted on nearly every shared secret in `.sops.yaml`
|
||||
(`age1vf8h7...`) — the enrollment write-back to inventory never
|
||||
happened. Fix: `homelab client add republic-laptop --finalize-pubkey
|
||||
age1vf8h7s8mqsn2q5eadgpdupsj4mwn8zguc77d85ws3xj40sl9rgksx2rxw6`.
|
||||
- `grimmory` has an `age_pubkey` in inventory but is missing from
|
||||
`secrets/hello.yaml`'s recipient list — incomplete enrollment the
|
||||
other direction. Fix: re-run `homelab client add grimmory
|
||||
--finalize-pubkey <its key>`.
|
||||
- `pve_id 131` exists live on hubris (`pct list`) with no inventory entry
|
||||
— investigate before assuming it's a stale ID (see the Prometheus LXC
|
||||
plan doc above, which flags this explicitly).
|
||||
- Three `lifecycle-pve-id-reuse` info findings (100, 106, 107 each shared
|
||||
between an active host and an archaeology entry) — expected/benign ID
|
||||
reuse after destroy, no action needed.
|
||||
**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/`.
|
||||
|
||||
## 60/90-day backlog
|
||||
**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/`.
|
||||
|
||||
Derived from gaps observed while building the 30-day roadmap, not
|
||||
guesswork. Roughly ordered by what unblocks the most:
|
||||
**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 secret` CLI: list, migrate (SOPS → Infisical), export-sops
|
||||
(DR fallback). Infisical SDK v0.8.0.
|
||||
- Rotation runbook at `secrets/rotation.md`.
|
||||
- Docker compose: `infisical` + `redis` services (profile: infisical).
|
||||
|
||||
- **Fix the oikos-console deploy webhook's signature mismatch.** Console
|
||||
is live on apps (105) via a manual `deploy.sh` run, but Gitea webhook
|
||||
14's deliveries all 403 with a signature mismatch for a cause not yet
|
||||
found — the secret is confirmed synced correctly on both sides
|
||||
(rotated once already to rule out drift). Until fixed, `git push`
|
||||
doesn't auto-redeploy the console the way it does for homelab-mcp/
|
||||
secrets-issuance; re-run `deploy.sh` on apps manually after changes.
|
||||
See [oikos/console/deploy/README.md](../oikos/console/deploy/README.md).
|
||||
- **SSH-key-signed approval requests.** Replaces the design note in
|
||||
Week 4: age keys can't sign (encryption-only format), so per-agent
|
||||
request authentication needs `ssh-keygen -Y sign`/`-Y verify` against
|
||||
each host's existing SSH key. Blocked on a schema gap: inventory
|
||||
doesn't record SSH public keys today, only ports/users. First step is
|
||||
populating that field on enrollment, then wiring `oikos/approve.py` to
|
||||
require and verify a signature over the request payload.
|
||||
- **Authentik step-up re-auth** on the Console's `/approvals` POST route
|
||||
— needs a live Authentik `PromptStage`/reauth flow scoped to that path;
|
||||
not configurable without a running instance to test against.
|
||||
- **Prometheus provisioning** (see
|
||||
[plans/2026-07-05-oikos-prometheus-lxc.md](../plans/2026-07-05-oikos-prometheus-lxc.md))
|
||||
— unblocks trend signals (disk-full prediction, temp creep) and real
|
||||
sparklines in the Console; investigate the undocumented `pve_id 131`
|
||||
on hubris first.
|
||||
- **CPU/NVMe temperature probing** in the scheduler — needs a confirmed
|
||||
sensor path on hubris and strong (lm-sensors vs vendor tool) before a
|
||||
real check can be written; guessing one risks a probe that silently
|
||||
never fires.
|
||||
- **DNS-vs-inventory drift check** — compare Technitium zone records
|
||||
against `services.*.url`/`public_host`; not implemented (`oikos/drift.py`
|
||||
has no Technitium API wiring yet).
|
||||
- **Generic tracked-config-cleanliness drift check** — today only caddy's
|
||||
`/etc/caddy` git-checkout path is hardcoded in `oikos/drift.py`; every
|
||||
other service with a `config_repo` needs its local checkout path
|
||||
recorded (a `mutation_path`-style field, same gap Week 1's service
|
||||
contract flagged but didn't backfill) before this generalizes.
|
||||
- **Per-service policy overrides** (`oikos/policy.yaml`
|
||||
`service_overrides`) — schema is ready (caddy/dns already use it);
|
||||
populate more as specific services turn out to need non-default risk
|
||||
classes.
|
||||
- **Incident timeline generator** — stitch ledger + signal history into
|
||||
a single narrative for `knowledge/sources/investigations/` entries instead of writing
|
||||
them by hand.
|
||||
- **Secret access audit** — who-can-decrypt-what report from
|
||||
`.sops.yaml` + inventory `age_pubkey`s, extending what
|
||||
`oikos/drift.py`'s SOPS check already partially does.
|
||||
- **Restore drills** — exercise `backs-up-to` (once populated) by
|
||||
actually restoring from a backup target on a schedule, not just
|
||||
checking freshness.
|
||||
- **Multi-agent delegation model** — more than one agent acting
|
||||
concurrently; needs the ledger's `agent` field to carry real identity
|
||||
(age pubkey, not just hostname) consistently, which it mostly does
|
||||
already but hasn't been stress-tested with concurrent writers.
|
||||
- **Grafana** — only if the Console's own Prometheus-backed sparklines
|
||||
turn out to be insufficient once Prometheus ships.
|
||||
- **"Generalize later" extraction** — the original decision was personal-
|
||||
first, generalize-later (see Week 1). Once patterns stabilize, extract
|
||||
a config-driven Oikos core with no `hubris.network`/`hubris`/`strong`
|
||||
hardcoding, so it's installable on a different homelab.
|
||||
**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.md` is 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](../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
|
||||
|
||||
Reference in New Issue
Block a user