- Consolidate Oikos on mac-mini (2026-07-06) - Client lifecycle in Go (2026-07-07) - Comprehensive audit & next steps (2026-07-07) - DB as source of truth (2026-07-07) - MCP tool completion (2026-07-07) Paths fixed in index.md to reflect planes/done/ locations. Active plans remaining: Prometheus LXC (Planned), implementation audit (Active).
365 lines
15 KiB
Markdown
365 lines
15 KiB
Markdown
# 2026-07-07 — Comprehensive audit: stale files, state gaps, and next steps
|
||
|
||
**Status:** Done (2026-07-08) — all actionable cleanup items resolved. Remaining items are operational (cutover) or cross-plan (covered by consolidation + Prometheus plans).
|
||
|
||
## Executive summary
|
||
|
||
Oikos is in a stable intermediate state: Go rewrite (Phases 1–6) is implemented and
|
||
running in Docker on mac-mini, the narrative wiki has been restructured into
|
||
`knowledge/wiki/`, and the strong migration (Tier 1 + 2) is complete. But the
|
||
transition left behind stale artifacts, half-updated plans, and several documentation
|
||
gaps that create confusion for agents and operators.
|
||
|
||
This plan catalogs every stale file and gap found, assigns ownership, and proposes a
|
||
prioritized work queue for the next 2–4 weeks. **No action is taken by this plan
|
||
itself** — it is the map from which concrete work items are drawn.
|
||
|
||
---
|
||
|
||
## 1. Stale files — catalog
|
||
|
||
### 1.1 Python kernel (`oikos/*.py`) — 11 files
|
||
|
||
| File | Risk | Verdict |
|
||
|------|------|---------|
|
||
| `oikos/__init__.py` | Low | Package init. Harmless but unused. |
|
||
| `oikos/approve.py` | Low | Superseded by `internal/domain/approval.go`. Remove. |
|
||
| `oikos/decide.py` | Low | Superseded by `internal/policy/classify.go`. Remove. |
|
||
| `oikos/drift.py` | **Medium** | Superseded by `internal/scheduler/scheduler.go`. References old paths (`containers/121-caddy.md` at L218). Remove. |
|
||
| `oikos/ledger.py` | **Medium** | Superseded by DB view + `internal/notifier/notifier.go`. Remove. |
|
||
| `oikos/policy.py` | Low | Superseded by `internal/policy/classify.go`. Remove. |
|
||
| `oikos/relations.py` | Low | Superseded by `blast_radius()` SQL function + `internal/ontology/`. Remove. |
|
||
| `oikos/scheduler.py` | **Medium** | Superseded by `internal/scheduler/`. Referenced by Prometheus plan. Remove. |
|
||
| `oikos/signal.py` | Low | Superseded by signals table (migration 003) + `internal/domain/signal.go`. Remove. |
|
||
| `oikos/gen-topology.py` | **High** | Still active — writes `knowledge/wiki/infrastructure/topology.md`, consumed by `homelab` CLI. **Keep until ported to Go.** |
|
||
| `oikos/gen_topology_lib.py` | **High** | Imported by `gen-topology.py`. **Keep until ported.** |
|
||
|
||
**Action:** Remove the 9 superseded `.py` files. Keep `gen-topology.py` +
|
||
`gen_topology_lib.py` until a Go equivalent exists. Update `.gitignore` and any
|
||
cross-references (Prometheus plan, bin/homelab docs).
|
||
|
||
### 1.2 `.hermes/plans/` — 7 files
|
||
|
||
These plans live in `.hermes/plans/` but the wiki-hq convention (`plans/index.md` L125,
|
||
`.agents/domains/operations/schema.md`) mandates all plans go in `plans/`. The strong
|
||
migration assessment (`.hermes/plans/2026-07-05_strong-migration-assessment.md`) is
|
||
particularly valuable and has already been executed.
|
||
|
||
| File | Status | Action |
|
||
|------|--------|--------|
|
||
| `2026-06-03_110000-library-ssd-migration-to-ludo-mini.md` | Superseded by strong migration | Move to `plans/done/` |
|
||
| `2026-06-03_150000-homelab-structure-revision.md` | Executed (is this repo structure) | Move to `plans/done/` |
|
||
| `2026-06-03_223218-dhcp-pool-exclude-static-ips.md` | Executed | Move to `plans/done/` |
|
||
| `2026-06-05_170000-prevent-dhcp-ip-drift.md` | Executed | Move to `plans/done/` |
|
||
| `2026-06-06_232200-authentik-frequent-login-fix.md` | Executed | Move to `plans/done/` |
|
||
| `2026-06-06_234500-caddyfile-truncation-permanent-fix.md` | Executed | Move to `plans/done/` |
|
||
| `2026-07-05_strong-migration-assessment.md` | Executed (Phases 1–2d done) | Move to `plans/done/`, add Phase 3 status note |
|
||
|
||
### 1.3 `oikos/cards/` — 45 context cards
|
||
|
||
These `.md` files are consumed by the Python MCP server's `explain` tool
|
||
(`mcp/server.py:38` referenced `CARD_DIR`). The Go MCP server (`internal/mcp/`) now
|
||
serves entity context from the database via `get_entity` / `list_entities`.
|
||
|
||
| Risk | Verdict |
|
||
|------|---------|
|
||
| **Medium** | Cards are redundant with DB entities but may still be read by the legacy `bin/homelab` Python CLI for `homelab explain`. If `bin/homelab` is ported to Go (via generated OpenAPI client), these become dead weight. |
|
||
|
||
**Action:** Verify whether `bin/homelab explain` reads `oikos/cards/` or queries the
|
||
API. If it reads cards: mark them as "keep until homelab CLI ported." If it queries the
|
||
API: remove cards and mention in the next Go release.
|
||
|
||
### 1.4 `secrets-issuance/` — identity issuance service
|
||
|
||
Still running on apps/105 (LXC) as `secrets-issuance.service`. The Docker stack
|
||
hasn't taken over this function yet. The cutover checklist (`scripts/cutover-checklist.md:5`)
|
||
notes "Disable apps/105 services" as ticked, but secrets-issuance was specifically stopped,
|
||
not replaced.
|
||
|
||
| Risk | Verdict |
|
||
|------|---------|
|
||
| **Medium** | If apps/105 is destroyed (cutover cleanup), secrets issuance must be replaced or explicitly decommissioned. |
|
||
|
||
**Action:** Decide: (a) port secrets issuance to Docker stack, or (b) decommission it
|
||
(age keys can be generated ad-hoc on each client). Document the decision.
|
||
|
||
### 1.5 Traefik references
|
||
|
||
`knowledge/sources/references/cert-sync-and-traefik-config.md` and
|
||
`inventory.yaml:245` (`vps/management.json.tmpl` references traefik) refer to a reverse
|
||
proxy that was replaced by Caddy for internal routing. Traefik **still runs on the VPS**
|
||
for public termination, so the references may be valid — but the doc is unclear.
|
||
|
||
**Action:** Audit traefik references. If VPS traefik is still active, document its
|
||
scope (public termination only, not internal). If fully replaced, remove the references.
|
||
|
||
---
|
||
|
||
## 2. Plan status drift
|
||
|
||
### 2.1 TRMNL (128) — marked "Planned" but done
|
||
|
||
`plans/2026-06-24-trmnl-plugins-lxc.md` shows status "Planned" but:
|
||
- LXC 128 exists in `inventory.yaml` with IP `192.168.8.211`
|
||
- Wiki page `knowledge/wiki/containers/128-trmnl.md` exists
|
||
- `hosts/trmnl.yaml` exists
|
||
- Caddy route `trmnl.hubris.network` exists
|
||
- Service `services.trmnl` exists in `inventory.yaml`
|
||
|
||
**Action:** Mark TRMNL plan as "Done", move to `plans/done/`, add changelog entries
|
||
on affected pages (as specified in the plan's "Post-migration" section).
|
||
|
||
### 2.2 Consolidation plan — cutover incomplete
|
||
|
||
`plans/2026-07-06-consolidate-oikos-control-plane-onto-mac-mini.md` status says
|
||
"Phase 1-6 implemented, pending cutover." The cutover checklist has 5 pending items:
|
||
|
||
1. **Infisical bootstrap** — `profiles: [infisical]` in compose but `OIKOS_SECRET_BACKEND`
|
||
env not set. SOPS fallback is active.
|
||
2. **Watchdog tested** — pending API stop + Matrix alert verification.
|
||
3. **Rollback drill** — `scripts/rollback.sh` never rehearsed.
|
||
4. **Rollback verify health + re-deploy** — depends on #3.
|
||
5. **Cleanup** — apps/105 webhooks not removed, LXC not archived.
|
||
|
||
**Action:** These 5 items are the highest-priority operational work. Schedule a 1-hour
|
||
window to complete them.
|
||
|
||
### 2.3 Prometheus plan — references Python
|
||
|
||
`plans/2026-07-05-oikos-prometheus-lxc.md:60` says "Extend `oikos/scheduler.py`'s
|
||
disk/temp probes" but the scheduler is now Go (`internal/scheduler/`). The plan also
|
||
references `bin/homelab` Python CLI commands for provisioning.
|
||
|
||
**Action:** Update the plan to reference the Go check_defs system (migration 003,
|
||
`check_defs` table) and the new `homelab` CLI (or `oikos` binary commands).
|
||
|
||
---
|
||
|
||
## 3. Documentation gaps
|
||
|
||
### 3.1 Missing container wiki pages
|
||
|
||
Two containers exist in `inventory.yaml` and `hosts/*.yaml` but have no wiki page:
|
||
|
||
| Container | PVE ID | Host | Wiki page |
|
||
|-----------|--------|------|-----------|
|
||
| seanime | 133 | strong | **Missing** |
|
||
| romm | 134 | strong | **Missing** |
|
||
|
||
**Action:** Create `knowledge/wiki/containers/133-seanime.md` and
|
||
`knowledge/wiki/containers/134-romm.md` from the data in `hosts/seanime.yaml` and
|
||
`hosts/romm.yaml`.
|
||
|
||
### 3.2 Host pages for `strong.md` and `hubris.md` — stale resource math
|
||
|
||
`knowledge/wiki/hosts/hubris.md` and `knowledge/wiki/hosts/strong.md` may still
|
||
reflect pre-migration resource allocation. The strong migration moved elementsynapse,
|
||
house, arriman, jellyfin, and grimmory — both pages need updated guest lists and
|
||
resource math.
|
||
|
||
**Action:** Audit both host pages against live `pct list` on each Proxmox node.
|
||
Update guest tables and RAM/CPU summaries.
|
||
|
||
### 3.3 `knowledge/wiki/infrastructure/topology.md` — Mermaid graph
|
||
|
||
Generated by `oikos/gen-topology.py`. Should be verified to include:
|
||
- strong and its guests (vmbr1 range 192.168.8.241–249)
|
||
- romm (134) and seanime (133)
|
||
- teddycloud (131)
|
||
- grimmory (130) on strong (not hubris)
|
||
|
||
**Action:** Run `oikos/gen-topology.py` and verify topology reflects current state.
|
||
Commit the regenerated file.
|
||
|
||
### 3.4 No ADR for Go rewrite completion
|
||
|
||
ADR-0001 ("Go single binary") was written as a forward-looking decision. No ADR
|
||
documents the completed rewrite as an accepted/implemented decision with retroactive
|
||
context on why the Python→Go transition happened when it did.
|
||
|
||
**Action:** Add an ADR-0011 documenting the completed Go rewrite with dates, phases,
|
||
and the rationale for the timing.
|
||
|
||
### 3.5 Un-enrolled hosts tracked in inventory
|
||
|
||
Several hosts have `age_pubkey: ''` in `inventory.yaml`:
|
||
- jellyfin, paperless, gitea, nextcloud, sophia, mule-images, caddy, arriman
|
||
|
||
These are documented as "not enrolled" in their host files. This is intentional
|
||
(not all LXCs need homelab-context) but the pattern should be documented in the
|
||
wiki as a convention.
|
||
|
||
**Action:** Add a section to `knowledge/wiki/infrastructure/homelab-context.md`
|
||
(or `.agents/operations/agent-enrollment.md`) explaining when enrollment is expected
|
||
vs. skipped.
|
||
|
||
---
|
||
|
||
## 4. Technical debt — Go codebase
|
||
|
||
### 4.1 `bin/homelab` — still a Python shim?
|
||
|
||
The `.gitignore` says "oikos/ kernel files are still imported by bin/homelab for
|
||
operational CLI commands." If `bin/homelab` is a compiled Go binary (as the README
|
||
and ADR-0001 suggest), then the Python kernel files should not be needed.
|
||
|
||
**Action:** Verify what `bin/homelab` is (run `file bin/homelab`). If it's a Go
|
||
binary and doesn't import Python, the 9 superseded `.py` files in `oikos/` are
|
||
safe to delete.
|
||
|
||
### 4.2 `oikos/build_hosts.go` — Python equivalent still exists
|
||
|
||
`cmd/oikos/build_hosts.go` exists alongside `mcp/build_host_files.py`. Both
|
||
generate `hosts/*.yaml` from `inventory.yaml`. Are both active? If the Go version
|
||
works, the Python version is stale.
|
||
|
||
**Action:** Compare output of both generators. If identical, remove the Python
|
||
version and update the `homelab` CLI to use the Go generator.
|
||
|
||
### 4.3 `scripts/dns-sync.py` — standalone Python
|
||
|
||
This script syncs DNS records to Technitium. It's operational and has no Go
|
||
equivalent yet. Not stale, but should be tracked as "port to Go."
|
||
|
||
**Action:** Add to Go rewrite backlog as a follow-up item.
|
||
|
||
### 4.4 `scripts/validate-seeds.py` — standalone Python
|
||
|
||
Validates `seeds/*.yaml`. Could be folded into `oikos seed` as a `--validate` flag.
|
||
|
||
**Action:** Add to Go rewrite backlog. Low priority.
|
||
|
||
---
|
||
|
||
## 5. Operational backlog (prioritized)
|
||
|
||
### P0 — Immediate (this week)
|
||
|
||
1. **[Cutover] Complete cutover checklist** — the 5 pending items from `scripts/cutover-checklist.md`:
|
||
- Infisical bootstrap (or decide: defer and stay on SOPS)
|
||
- Watchdog end-to-end test
|
||
- Rollback drill (`scripts/rollback.sh` rehearsal)
|
||
- Rollback verify + re-deploy
|
||
- apps/105 cleanup (remove Gitea webhooks, archive LXC)
|
||
|
||
2. **[Docs] Create wiki pages for seanime (133) and romm (134)**
|
||
|
||
3. **[Plans] Mark TRMNL plan as done**, move to `plans/done/`, write changelogs
|
||
|
||
### P1 — Near-term (next 1-2 weeks)
|
||
|
||
4. **[Cleanup] Migrate `.hermes/plans/` → `plans/done/`** for all 7 files
|
||
|
||
5. **[Cleanup] Remove 9 superseded `oikos/*.py` files** (all except gen-topology*)
|
||
— after verifying `bin/homelab` doesn't import them
|
||
|
||
6. **[Docs] Audit and update strong.md + hubris.md** guest lists and resource math
|
||
|
||
7. **[Docs] Regenerate `knowledge/wiki/infrastructure/topology.md`** to reflect
|
||
current state (strong guests, new LXCs)
|
||
|
||
8. **[Plans] Update Prometheus plan** — port Python references to Go equivalents
|
||
|
||
### P2 — Medium-term (2-4 weeks)
|
||
|
||
9. **[Docs] ADR-0011** — document the completed Go rewrite
|
||
|
||
10. **[Docs] Document enrollment convention** — when LXCs get homelab-context vs.
|
||
when they skip it
|
||
|
||
11. **[Cleanup] Audit and resolve oikos/cards/** — verify whether still consumed
|
||
|
||
12. **[Cleanup] Traefik reference audit** — document or remove old traefik mentions
|
||
|
||
13. **[Plans] Complete wiki-hq adoption Phases 3–5** from
|
||
`plans/2026-07-06-adopt-wiki-hq-doc-architecture.md`:
|
||
- Phase 4 — runbooks → skills (reshape remaining runbooks into `.agents/skills/`)
|
||
- Phase 5 — writing-style + README pass + docs-lint
|
||
|
||
14. **[Code] Compare `mcp/build_host_files.py` vs `cmd/oikos/build_hosts.go`**
|
||
— remove duplicate if outputs match
|
||
|
||
### P3 — Backlog (when capacity allows)
|
||
|
||
15. **[Code] Port `oikos/gen-topology.py` to Go** — the last Python holdout
|
||
|
||
16. **[Code] Port `scripts/dns-sync.py` to Go** — add to `oikos` binary
|
||
|
||
17. **[Code] Fold `scripts/validate-seeds.py` into `oikos seed --validate`**
|
||
|
||
18. **[Infra] Prometheus LXC provisioning** — per the updated plan
|
||
|
||
19. **[Infra] Strong Phase 3** — migrate mule-images (120) per strong migration
|
||
assessment
|
||
|
||
20. **[Docs] Port `knowledge/sources/references/cert-sync-and-traefik-config.md`**
|
||
to reflect current Caddy-based cert management
|
||
|
||
---
|
||
|
||
## 6. File inventory — what to keep, what to remove
|
||
|
||
### Keep (active)
|
||
```
|
||
cmd/oikos/** cmd/hermes/**, internal/**, api/openapi.yaml, compose/**, migrations/**,
|
||
seeds/**, docs/adr/**, docker-compose.yml, Makefile, go.mod, go.sum, sqlc.yaml,
|
||
inventory.yaml, hosts/*.yaml, .sops.yaml, .gitignore, .gitea/**,
|
||
knowledge/**, .agents/**, plans/**, README.md, AGENTS.md,
|
||
hermes/**, oikos/gen-topology.py, oikos/gen_topology_lib.py,
|
||
scripts/{deploy,rollback,watchdog,verify-phase6}.sh, scripts/sync/**,
|
||
scripts/check-caddy-backends.sh, scripts/cutover-checklist.md,
|
||
secrets/**, secrets-issuance/**, bin/homelab, mcp/build_host_files.py,
|
||
ssh/**, tools/**, vps/**, ledger/**, bootstrap.sh,
|
||
scripts/dns-sync.py, scripts/validate-seeds.py (keep until ported)
|
||
```
|
||
|
||
### Remove
|
||
```
|
||
oikos/__init__.py, oikos/approve.py, oikos/decide.py, oikos/drift.py,
|
||
oikos/ledger.py, oikos/policy.py, oikos/relations.py, oikos/scheduler.py,
|
||
oikos/signal.py
|
||
```
|
||
|
||
### Migrate
|
||
```
|
||
.hermes/plans/*.md → plans/done/
|
||
oikos/cards/*.md → TBD (remove if unused, keep if bin/homelab reads them)
|
||
```
|
||
|
||
### Decide
|
||
```
|
||
secrets-issuance/ → port to Docker or decommission?
|
||
oikos/cards/ → still consumed by bin/homelab explain?
|
||
mcp/build_host_files.py → redundant with cmd/oikos/build_hosts.go?
|
||
```
|
||
|
||
---
|
||
|
||
## 7. Decisions requested
|
||
|
||
These require operator input before proceeding:
|
||
|
||
1. **Infisical now or later?** Bootstrap Infisical (Phase 5 production) now or defer
|
||
and continue with SOPS-only? Risk: Infisical adds Redis + Infisical container to
|
||
the Docker stack on mac-mini with non-trivial setup.
|
||
|
||
2. **Secrets issuance: port or kill?** If we decommission `secrets-issuance/`, new
|
||
clients generate their own age key and the operator adds the pubkey manually.
|
||
Simpler but loses automated enrollment.
|
||
|
||
3. **apps/105: archive or destroy?** After Docker cutover cleanup, does apps/105
|
||
stay as a warm spare or get archived per lifecycle rules?
|
||
|
||
4. **oikos/cards/: keep or drop?** Verify `bin/homelab explain` behavior. If it
|
||
queries the API, cards are dead weight. If it reads files, they stay until the
|
||
CLI is ported.
|
||
|
||
---
|
||
|
||
## Changelog
|
||
|
||
### 2026-07-07 — comprehensive audit created
|
||
Catalog of 20+ stale files, plan status drift, documentation gaps, and
|
||
prioritized operational backlog. Covers Python kernel cleanup, .hermes/plans/
|
||
migration, oikos/cards/ assessment, cutover completion, and missing wiki pages.
|