---
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`).
