# 00 — Vision & Scope ## Vision Build a home platform that behaves like a small private cloud. An operator declares a service — a container app *or* a virtual machine — in git, and the platform provisions it, secures it, exposes it under a trusted TLS URL, routes its traffic on the correct WAN, protects its data, updates it automatically, and reports on its health. Onboarding a new service is a pull request against a catalog, not a weekend of manual work. The platform is delivered in two stages: - **dev/test** on local KVMs — the active build target, used to prove viability. - **prod** on 3 mini-PCs — the eventual home, designed for now but not built on yet. ## Personas - **Operator (primary user)**: runs the home network; wants to onboard/offboard services with minimal ceremony and zero data loss. - **Platform (the system)**: reconciles declared state, enforces isolation and egress policy, renews certificates, updates workloads, and raises alerts. - **Implementation agents**: the AI teams building the platform from this spec. ## In scope - A k3s-based platform with distributed storage (Longhorn) across 3 nodes. - Container workloads (PaaS) and VM workloads (IaaS) through one Kubernetes surface. - GitOps delivery, automated updates, trusted TLS, DNS, ingress. - Network isolation (default-deny east-west) and multi-WAN egress including VPN routing. - Observability with email + dashboard alerting. - A command-and-control web UI at the root of `home.keithjackson.dev`. - The initial service catalog (13 services, see [`13-service-catalog.md`](13-service-catalog.md)). ## Out of scope (for now) - Building on production mini-PC hardware (design-only until the roadmap flips it to active). - Multi-tenant / multi-operator RBAC beyond a single operator + platform automation. - Public multi-user SaaS concerns (billing, per-tenant isolation beyond network policy). - Non-`keithjackson.dev` domains. ## The domain & DNS model - Public apex `*.keithjackson.dev` is available and its records resolve to the network's public IP. - All platform services live under `*.home.keithjackson.dev`. - Each service is reachable at `.home.keithjackson.dev` (e.g. `plex.home.keithjackson.dev`). - The **root** `home.keithjackson.dev` serves the **Command & Control (C2) center** UI. ## Requirements (stable IDs) Requirement IDs are stable references used across ADRs, specs, the task board, and PRs. `MUST` is mandatory; `SHOULD` is strongly preferred and requires an ADR to deviate. ### Platform & API surface — `R-PLAT-*` - **R-PLAT-01** — The platform MUST run on k3s across 3 nodes with production-grade HA control plane in prod; dev/test MAY run fewer nodes but MUST exercise the same multi-node topology. - **R-PLAT-02** — Container workloads MUST be onboarded and managed declaratively via the Kubernetes API, `kubectl`-class CLI, and YAML. - **R-PLAT-03** — Virtual-machine workloads MUST be created, managed, and destroyed through the *same* Kubernetes API/CLI/YAML surface as containers (no separate hypervisor management plane for application VMs). - **R-PLAT-04** — The platform MUST support create / destroy / rebuild of any workload on demand. ### GitOps & delivery — `R-GITOPS-*` - **R-GITOPS-01** — All application and platform desired state MUST be defined in git and reconciled automatically (pull-based GitOps). - **R-GITOPS-02** — Onboarding a new service MUST be expressible as a change to a versioned catalog in git. - **R-GITOPS-03** — The system MUST detect and correct drift between git and cluster state. ### Networking, isolation & egress — `R-NET-*` - **R-NET-01** — East-west traffic between services MUST be **denied by default**; communication is allowed only by explicit, port-level configuration (firewall-like). - **R-NET-02** — Allow rules MUST be declarative, reviewable in git, and scoped per source → destination → port/protocol. - **R-NET-03** — Networks MUST be configurable and isolatable (segments/namespaces with enforced boundaries). - **R-NET-04** — The platform MUST support **multiple egress paths** selected by routing rules. Per OQ-1 the environment has **one physical commercial WAN and no multi-ISP plans**, so this is realized as two paths — the local `internet` path and the in-cluster `vpn` path — not multi-ISP routing. Physical multi-WAN (multiple ISP uplinks) is **out of scope** unless a future ADR reopens it. - **R-NET-05** — A service MUST be able to declare its **egress class**: `internet` (standard local network/internet) or `vpn` (routed through a custom VPN connection). VPN routing MUST be enforced **outside the service** (a single shared in-cluster gateway), so a service cannot leak by misconfiguration (ADR-0013, OQ-3). - **R-NET-06** — VPN-class egress MUST enforce a **kill-switch**: if the VPN tunnel is down, the service MUST NOT leak traffic to the standard internet. - **R-NET-07** — Egress class MUST be a declarative property of the service, changeable via GitOps without re-architecting the workload. ### Storage & state — `R-STATE-*` - **R-STATE-01** — Stateful data MUST survive destroy/rebuild of the workload (PaaS and IaaS). - **R-STATE-02** — Persistent storage MUST be distributed/replicated across the 3 nodes (Longhorn) so a single node loss does not lose data. - **R-STATE-03** — The platform MUST provide scheduled backups to an **off-cluster** target and a tested restore path (disaster recovery). - **R-STATE-04** — Bulk media storage (Plex library) MUST have a capacity strategy distinct from replicated app-config storage (replicating multi-TB media 3× is out of scope; see ADR-0003). ### Automated updates — `R-UPD-*` - **R-UPD-01** — Services MUST update to the latest **stable** versions on a schedule. - **R-UPD-02** — Updates MUST require **no human, no AI, and no hand-authored GitOps change** to occur. Automation controllers acting on declarative policy are the permitted mechanism. - **R-UPD-03** — Update policy MUST be per-service configurable (cadence, stability channel, pin/hold, auto-rollback on failed health). ### TLS & certificates — `R-TLS-*` - **R-TLS-01** — Every externally reachable service MUST present TLS from a **credible, trusted, non-self-signed** authority. - **R-TLS-02** — Certificates MUST be automatically **issued, renewed, and revoked** without manual steps. - **R-TLS-03** — Certificate issuance MUST work for internal-only services (no requirement to expose a service publicly just to validate a certificate). ### DNS & ingress — `R-DNS-*` - **R-DNS-01** — Services MUST be reachable at `.home.keithjackson.dev`. - **R-DNS-02** — DNS records MUST be managed automatically from declared service intent. - **R-DNS-03** — Internal clients MUST resolve service names correctly (split-horizon where public and internal answers differ). ### Observability & alerting — `R-OBS-*` - **R-OBS-01** — Services MUST be monitored (metrics, logs, health). - **R-OBS-02** — Issues MUST be reported by **email**. - **R-OBS-03** — Issues and health MUST be visible on **dashboards**. - **R-OBS-04** — The platform MUST alert on its own health (nodes, storage, GitOps reconciliation, certificate expiry, VPN tunnel state, backup success). ### Command & control — `R-C2-*` - **R-C2-01** — The root `home.keithjackson.dev` MUST serve a UI that surfaces the services running in the cluster and links to them. - **R-C2-02** — The C2 UI MUST surface platform health (cluster, storage, GitOps, alerts) and provide controlled operational actions where safe. ### Security & secrets — `R-SEC-*` - **R-SEC-01** — Secrets MUST NOT be stored in plaintext in git; they MUST be encrypted at rest in the repo and decrypted only in-cluster. - **R-SEC-02** — The platform MUST follow least-privilege for workload identities and network reach. - **R-SEC-03** — All the above properties MUST be demonstrable/auditable (an operator can prove isolation, egress path, cert validity, and backup integrity). ### Environments — `R-ENV-*` - **R-ENV-01** — dev/test MUST be provisioned as local KVMs via IaC: created, baselined, cluster- joined, and managed as code. - **R-ENV-02** — The same GitOps configuration MUST promote from dev/test to prod with only environment-scoped overrides. - **R-ENV-03** — prod is a 3× mini-PC bare-metal k3s cluster with local storage; it MUST NOT be an active development surface until the roadmap declares it ready. ### Conformance testing & governance — `R-TEST-*` - **R-TEST-01** — Every requirement MUST be verified by **automated, behavior-based tests** (Given/When/Then style) that assert observable system behavior, not implementation internals. - **R-TEST-02** — Tests MUST be **reproducible**: deterministic, hermetic (create and tear down their own fixtures), version-pinned, and runnable by a single command locally and in CI against any conforming cluster, producing machine-readable, requirement-tagged results. - **R-TEST-03** — A **conformance suite** MUST gate delivery: merges are blocked unless the tests for the touched requirements pass, and phase exits are blocked unless the phase's full suite passes. "Demonstrated" means "the automated test passes," never a manual one-off. - **R-TEST-04** — Tests MUST be **traceable**: each test declares the requirement ID(s) it verifies, and a coverage report maps every `R-*` requirement to its verifying test(s). Uncovered requirements are a gap to close, not an acceptable state. - **R-TEST-05** — Safety-critical behaviors (default-deny, VPN kill-switch, data-survival on rebuild, DR restore, auto-rollback) MUST be verified by **fault-injection** behavior tests that prove fail-closed / no-data-loss outcomes, not merely happy-path checks. - **R-TEST-06 (governance)** — **AI agents MUST NOT modify the specifications** (this `docs/` tree, the requirements, or accepted ADRs). Specs are changed only by the human operator/architect. Agents that find a spec wrong, blocking, ambiguous, or missing MUST **stop and escalate** and MAY draft a proposal, but MUST NOT self-approve or merge a spec/ADR change (see [`AGENTS.md`](../AGENTS.md) §2 and §11). ## Acceptance philosophy Each requirement class maps to an **automated, reproducible, behavior-based conformance test** in dev/test (`R-TEST-*`). "Done" means *the conformance test for the touched requirements passes* — a green, reproducible result traced to requirement IDs — never "manifest merged" and never a manual demonstration. The testing approach is specified in [`docs/14-testing-and-conformance.md`](14-testing-and-conformance.md) and [ADR-0010](../decisions/adr-0010-conformance-testing.md); the gate checklist lives in [`agents/definition-of-done.md`](../agents/definition-of-done.md). **Governance:** the specifications are human-owned and **immutable to agents** (R-TEST-06). Agents implement against the spec and prove conformance with tests; they never edit the spec to fit the implementation. ## Open questions ### Resolved (2026-08-15) - **OQ-1 (WAN / edge)** — **RESOLVED**: one commercial WAN, no multi-ISP plans; dumb SOHO edge (no VLAN/VPN/services). All segmentation + VPN in-cluster; edge does NAT + port-forward only. Physical multi-WAN out of scope. See [`03`](03-networking-isolation-and-egress.md), [`09`](09-dns-and-ingress.md). - **OQ-2 (bulk media)** — **RESOLVED (deferred backing)**: Plex bulk media lives **outside the cluster**; the specific backing is **TBD later** and does not block the core platform. Plex's metadata DB still lives on replicated Longhorn. The **off-cluster DR backup target** (for app config, Nextcloud, Gitea, etc.) remains to be chosen at Phase 4. See [`04`](04-storage-and-state.md). - **OQ-3 (VPN)** — **RESOLVED**: **PIA** via Gluetun, cluster-provisioned, **single shared in-cluster tunnel** over **WireGuard** (non-TCP), native port forwarding, rules enforced outside the service (ADR-0013, supersedes ADR-0012's ExpressVPN choice). See [`03`](03-networking-isolation-and-egress.md). - **OQ-4 (TLS/DNS challenge access)** — **RESOLVED**: a **scoped Cloudflare API token** (`Zone·DNS·Edit`, `keithjackson.dev`), SOPS-encrypted, drives cert-manager DNS-01 and ExternalDNS. The static `*.keithjackson.dev` wildcard covers reachability but not TXT-challenge writes; the token handles issuance + record automation. Operator provides the token once. See [`08`](08-tls-and-certificates.md). ### Still open - **OQ-BKP (off-cluster DR backup target)**: which S3-compatible endpoint or NFS host stores Velero/Longhorn backups of the irreplaceable tier. Needed by **Phase 4**, not blocking Phase 2. See [`04`](04-storage-and-state.md).