Files
home-network-k3s/agents/task-board.md
T
jakman85andClaude Opus 4.8 cde2f2330c Resolve OQ-4: scoped Cloudflare API token for DNS-01 + ExternalDNS
Operator chose Option A. cert-manager solves ACME DNS-01 and ExternalDNS
manages *.home.keithjackson.dev records via a scoped Cloudflare token
(Zone.DNS.Edit, keithjackson.dev), stored SOPS-encrypted. Operator provides
the token once (new prereq T-2.4p); T-2.4/T-2.5 unblocked. Only OQ-BKP
(off-cluster DR backup target, Phase 4) remains open.

Updated: docs 00,08,09; task board.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-08-15 23:02:59 -05:00

106 lines
9.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Task Board
The live who's-doing-what. Agents **claim** an item (set Owner + Status) before starting, respect
`Blocked-by`, and mark `done` only after its **automated, reproducible behavior test passes green**
([`definition-of-done.md`](definition-of-done.md), [`../docs/14-testing-and-conformance.md`](../docs/14-testing-and-conformance.md)).
Seeded from [`../roadmap/phases.md`](../roadmap/phases.md) + [`../roadmap/workstreams.md`](../roadmap/workstreams.md).
> **This board is the one working surface agents may edit** (claim items, update status, add
> items/escalations). The specs, ADRs, and roadmap are **not** editable by agents (R-TEST-06) —
> raise spec problems here as an `OQ-*` escalation for the human. Every "**Prove …**" task below is
> an automated conformance test (co-owned with **WS-TEST**), not a manual demo.
**Status values:** `todo` · `in-progress` · `blocked` · `review` · `done`
**Add new items** at the bottom of the relevant phase; keep IDs stable.
---
## Phase 0 — Foundations
| ID | Task | WS | Serves | Blocked-by | Owner | Status |
|---|---|---|---|---|---|---|
| T-0.1 | Create implementation repo structure (platform/apps/catalog/clusters) | WS-GITOPS | R-GITOPS-02 | — | — | todo |
| T-0.2 | CI: lint + schema validation + build/dry-run gates | WS-GITOPS | R-GITOPS-01 | T-0.1 | — | todo |
| T-0.3 | Author ServiceDefinition schema + renderer contract | WS-GITOPS | R-GITOPS-02 | T-0.1 | — | todo |
| T-0.4 | Conformance harness: **Chainsaw** runner + reproducibility contract + JUnit + coverage report + CI merge gate | WS-TEST | R-TEST-01/02/03/04 | T-0.1 | — | todo |
| T-0.5 | L0 **Kyverno** policy gate (default-deny present, no plaintext secrets, schema-valid ServiceDefinitions) | WS-TEST | R-TEST-01, R-NET-01, R-SEC-01 | T-0.4 | — | todo |
## Phase 1 — dev/test Cluster Bring-up
| ID | Task | WS | Serves | Blocked-by | Owner | Status |
|---|---|---|---|---|---|---|
| T-1.1 | OpenTofu libvirt module for 3 node VMs (+ Longhorn data disk) | WS-INFRA | R-ENV-01 | — | — | todo |
| T-1.2 | cloud-init baseline (users, SSH, sysctls, virt/Longhorn prereqs) | WS-INFRA | R-ENV-01 | T-1.1 | — | todo |
| T-1.3 | Ansible: k3s HA install, Cilium CNI, disable flannel/kube-proxy/Traefik | WS-INFRA | R-PLAT-01 | T-1.2 | — | todo |
| T-1.4 | Bootstrap Flux + SOPS age key | WS-GITOPS/WS-SEC | R-GITOPS-01, R-SEC-01 | T-1.3 | — | todo |
| T-1.5 | Prove node destroy/rebuild from IaC (no data loss) | WS-INFRA | R-ENV-01, R-STATE-01 | T-1.4 | — | todo |
## Phase 2 — Platform Core (net/storage/TLS/DNS/ingress)
| ID | Task | WS | Serves | Blocked-by | Owner | Status |
|---|---|---|---|---|---|---|
| T-2.1 | Longhorn (3-replica StorageClass) + `bulk` external-mount indirection (media lives off-cluster, backing TBD — OQ-2 resolved) | WS-STORAGE | R-STATE-02/04 | T-1.4 | — | todo |
| T-2.2 | Default-deny network baseline (per-namespace) + Hubble | WS-NET | R-NET-01/03 | T-1.3 | — | todo |
| T-2.3 | Render `dependencies` → CiliumNetworkPolicy from ServiceDefinition | WS-NET/WS-GITOPS | R-NET-02 | T-0.3, T-2.2 | — | todo |
| T-2.4p | **Prereq:** operator creates scoped Cloudflare API token (`Zone·DNS·Edit`, `keithjackson.dev`); store SOPS-encrypted | WS-SEC | R-TLS-01, R-SEC-01 | — | — | todo |
| T-2.4 | cert-manager + Let's Encrypt DNS-01 wildcard `*.home.keithjackson.dev` (via Cloudflare token) | WS-SEC | R-TLS-01/02/03 | T-1.4, T-2.4p | — | todo |
| T-2.5 | ExternalDNS (Cloudflare token) + Gateway API listeners (VIP via **Cilium L2 announcement**) + split-horizon (PiHole) | WS-NET | R-DNS-01/02/03 | T-2.4 | — | todo |
| T-2.6 | Prove: default-deny (DNS-only probe), PVC survives rebuild, trusted cert, auto-DNS | WS-NET/STORAGE/SEC | R-NET/STATE/TLS/DNS | T-2.1..2.5 | — | todo |
| T-2.7 | Deploy **Kyverno in-cluster as admission enforcer** (same policies as the CI L0 gate) | WS-TEST/WS-SEC | R-SEC-02, R-NET-01, R-SEC-01 | T-1.4, T-0.5 | — | todo |
## Phase 3 — Egress & VPN (single WAN; no multi-WAN — OQ-1)
| ID | Task | WS | Serves | Blocked-by | Owner | Status |
|---|---|---|---|---|---|---|
| T-3.0 | L3 fault-injection harness — **in-cluster Chainsaw Job** (CI-triggered, scoped test SA) using `script`/`try`/`finally` (force tunnel down, kill node, inject bad image, trigger restore) | WS-TEST | R-TEST-05, R-SEC-02 | T-0.4 | — | todo |
| T-3.1 | Egress classes; Cilium Egress Gateway wiring (steer `vpn` pods → gateway) | WS-NET | R-NET-04/05 | T-2.2 | — | todo |
| T-3.2p | **Prereq:** obtain ExpressVPN manual OpenVPN-UDP config + manual creds; store SOPS-encrypted | WS-SEC | R-NET-05 | — | — | todo |
| T-3.2 | **Single shared in-cluster ExpressVPN gateway** (OpenVPN UDP, active/standby) + centrally-enforced kill-switch (ADR-0012) | WS-NET | R-NET-05/06 | T-3.1, T-3.2p | — | todo |
| ~~T-3.3~~ | ~~Edge-router multi-WAN split~~ — **out of scope** (single WAN, dumb SOHO edge; OQ-1) | WS-NET | R-NET-04 | — | — | won't-do |
| T-3.4 | Prove: VPN IP egress, **kill-switch fail-closed (central)**, egress-class flip via git | WS-NET | R-NET-05/06/07 | T-3.0, T-3.2 | — | todo |
## Phase 4 — Observability, Backup/DR & Updates
| ID | Task | WS | Serves | Blocked-by | Owner | Status |
|---|---|---|---|---|---|---|
| T-4.1 | kube-prometheus-stack + Loki + Alloy + Alertmanager(email) | WS-OBS | R-OBS-01/02/03 | T-2.1 | — | todo |
| T-4.2 | Platform-health alerts (node/Longhorn/Flux/cert/VPN/backup) | WS-OBS | R-OBS-04 | T-4.1 | — | todo |
| T-4.3 | Velero + Longhorn off-cluster backup schedule (**needs backup-target choice** — S3/NFS endpoint) | WS-STORAGE | R-STATE-03 | T-2.1, OQ-BKP | — | todo |
| T-4.4 | DR drill: restore namespace + volumes from off-cluster backup | WS-STORAGE | R-STATE-03 | T-4.3 | — | todo |
| T-4.5 | Flux image-automation + Renovate + per-service update policy | WS-UPDATE | R-UPD-01/02/03 | T-0.3, T-4.1 | — | todo |
| T-4.6 | Prove: auto stable update on schedule, bad-update auto-rollback+alert, pin holds | WS-UPDATE | R-UPD-* | T-4.5 | — | todo |
## Phase 5 — IaaS Proof (KubeVirt)
| ID | Task | WS | Serves | Blocked-by | Owner | Status |
|---|---|---|---|---|---|---|
| T-5.1 | Install KubeVirt + CDI; Longhorn-backed VM disks | WS-VM | R-PLAT-03 | T-2.1, T-2.2 | — | todo |
| T-5.2 | `kind: vm` ServiceDefinition path; run one representative VM | WS-VM/WS-GITOPS | R-PLAT-03/04 | T-5.1, T-0.3 | — | todo |
| T-5.3 | Prove: VM lifecycle via kubectl/virtctl, rebuild w/o data loss, default-deny+egress, guest auto-update | WS-VM | R-PLAT-03, R-NET-*, R-UPD-* | T-5.2 | — | todo |
## Phase 6 — Service Onboarding + C2
| ID | Task | WS | Serves | Blocked-by | Owner | Status |
|---|---|---|---|---|---|---|
| T-6.1 | Onboard **pihole** (DNS underpinning) | WS-APPS | R-DNS-03 | T-2.5 | — | todo |
| T-6.1a | Onboard **gitea** early (bootstrapping-critical; self-hosts GitOps source + CI/CD) | WS-APPS | R-STATE-03 | T-4.4 | — | todo |
| T-6.1b | Migrate GitOps source local→Gitea; move CI to **Gitea Actions** (Kyverno gate + Chainsaw Job trigger; PR merge gate); off-cluster repo mirror | WS-GITOPS | R-GITOPS-01, R-TEST-03 | T-6.1a | — | todo |
| T-6.2 | Onboard **plex** (bulk tier + public exposure) | WS-APPS | R-STATE-04 | T-2.6, T-6.1 | — | todo |
| T-6.3 | Onboard **qbittorrent, jackett** (VPN + kill-switch) | WS-APPS | R-NET-05/06 | T-3.4 | — | todo |
| T-6.4 | Onboard **sonarr, radarr** (VPN + arr↔downloader allows) | WS-APPS | R-NET-02/05 | T-6.3 | — | todo |
| T-6.5 | Onboard **seerr** (allows to arr + plex) | WS-APPS | R-NET-02 | T-6.2, T-6.4 | — | todo |
| T-6.6 | Onboard **nextcloud** (DR-critical + backups) | WS-APPS | R-STATE-03 | T-4.4 | — | todo |
| T-6.7 | Onboard **minecraft, unifi, semaphore, kasm** | WS-APPS | app reqs | T-2.6 | — | todo |
| T-6.8 | C2 UI: Homepage root + Grafana + Headlamp + Flux status + auth | WS-C2 | R-C2-01/02 | T-4.2, T-6.* | — | todo |
## Phase 7 — Production Readiness (CLOSED until operator opens it)
| ID | Task | WS | Serves | Blocked-by | Owner | Status |
|---|---|---|---|---|---|---|
| T-7.1 | Bare-metal provisioning checklist (design-only) | WS-INFRA | R-ENV-03 | — | — | todo |
| T-7.2 | prod overlay (no base edits) + cutover plan | WS-INFRA/WS-GITOPS | R-ENV-02 | Phases 1–6 done | — | blocked |
| T-7.3 | Full prod DR drill | WS-STORAGE | R-STATE-03 | T-7.2 | — | blocked |
---
## Open questions
| OQ | Question | Blocks | Status |
|---|---|---|---|
| OQ-1 | WAN count + edge router | — | ✅ resolved: 1 WAN, dumb SOHO edge; multi-WAN out of scope; VPN + segmentation in-cluster |
| OQ-2 | Bulk-media home | — | ✅ resolved: media outside cluster, backing TBD later (not blocking) |
| OQ-3 | VPN provider/protocol | — | ✅ resolved: ExpressVPN, single shared in-cluster tunnel, OpenVPN UDP (ADR-0012) |
| OQ-4 | DNS-01 challenge access | — | ✅ resolved: scoped **Cloudflare API token** (Zone·DNS·Edit), SOPS-encrypted; drives cert-manager + ExternalDNS. Operator provides token (T-2.4p) |
| **OQ-BKP** | **Off-cluster DR backup target** (S3/NFS endpoint) | T-4.3 | ⛔ **OPEN** — needed by Phase 4, not Phase 2 |