--- name: lifecycle-destroy-node risk_class: destructive inputs: [node_name] verification: "MCP get_blast_radius returns unknown-entity; pct list on the backend no longer shows it" docs_update_checklist: [archaeology_entry, containers_index_update] transition: "deprecated -> destroyed" --- # Lifecycle: destroy a node **Destructive.** Requires operator approval + typed confirmation phrase per `seeds/policy.yaml`. Requires (ontology): backups verified, secrets recipients removed + re-keyed, ingress/DNS removed, archaeology entry, ledger entry. 1. Confirm the node is `deprecated` with zero `affected_by` edges (MCP `get_blast_radius`) — do not skip this even if the deprecation runbook was followed recently; state can drift. 2. **If it's an enrolled client: no current tool for revoking its age key / removing its Infisical identity.** The old `homelab client remove` (age key revocation + SOPS re-key + inventory removal, all one destructive-class CLI call) is retired along with the rest of that CLI and hasn't been re-verified against the current enrollment architecture (`POST /api/v1/clients/enroll` + Infisical machine identities) — see the "Open questions" section in [agent-enrollment.md](../../operations/agent-enrollment.md). Until that's confirmed, treat key/identity revocation as a manual step: at minimum remove the client's `age_pubkey` from any SOPS recipient lists and rotate credentials whose ciphertext it already decrypted. 3. Remove any ingress route (Caddy config repo) and DNS record still pointing at it. 4. Verify backups of anything on it are retained per policy before the disk goes away (see `backs-up-to`). 5. Destroy the LXC/VM (`pct destroy` / `qm destroy`). 6. Update the entity's `state` to `destroyed` in `seeds/inventory.yaml` (or move it to an `archaeology:`-style section if the schema still has one) — `pve_id`, `destroyed` date, `reason` — then `oikos seed` to ingest. Add a row to `containers/index.md` "Recently destroyed" table (kept for human-readable browsing alongside the structured data). 7. No manual ledger step — mutations through the API are recorded automatically in the `audit_log` table (MCP `get_audit_trail`, `get_change_history`). The old `oikos/ledger.py append` was retired when this became automatic. If the destroy fails partway (e.g. secrets not fully revoked but pct destroy errors), finish the remaining steps manually and note the partial state in an investigation (MCP `upsert_knowledge`, `kind: investigation`).