diff --git a/docs/CURRENT-STATE.md b/docs/CURRENT-STATE.md index a7dda0f..8543295 100644 --- a/docs/CURRENT-STATE.md +++ b/docs/CURRENT-STATE.md @@ -108,15 +108,11 @@ (GA-F01) and the subject of the pending D-130 ruling (section 8). Root-cause mechanism, verified against provider v0.9.8 source: `docs/finding-20260718-voffice1-cloudinit-seed-replace.md:186-228`. -ii. Autostart: LIVE is `enable` on both domains (measured, 2.2). CONFIG - authors `autostart = true` (D-127, `docs/design-decisions.md:3914`). - But STATE records NO autostart attribute on either domain (empirical: - `tofu state show ... | grep -c autostart` -> 0, finding doc:140-145), - so the plan still shows 2 in-place changes -- and a provider-source - read confirms an autostart-only update BOUNCES the guest (finding - doc:162-184). Live matches intent; state cannot see it; an unscoped - apply would still cause an outage. Resolution belongs to the gated - reconcile (section 6, gate G6) -- NOT to a quiet re-plan. +ii. Autostart: RESOLVED 2026-07-19 by the G6 state surgery (operator- + ruled (ii), gate row G6): state now records `autostart = true` on + both domains (`state show | grep -c autostart` -> 1 each); the 2 + in-place changes are gone from the plan (section 5 capture). Guests + were never touched. iii. The six `vr1-dc0` plane networks exist live and in state but are REMOVED from config -- the INTENDED Model B relocation (planes get recreated inside `vvr1-dc0` by the inner root, @@ -189,14 +185,17 @@ - pre-reboot gate was 5/0/6 (recorded at `docs/dc0-deploy-readiness.md:59`, `docs/session-ledger.md:278`). -7/2/7 was the post-reboot SYMPTOM of the D-130 seed-volume defect -(decomposition at `docs/audit/env-snapshot-20260718.md:33-46`). D-130 is -now RULED and implemented (2026-07-19): the v8 capture measures the -post-fix plan at 6/2/6 (`docs/audit/outer-plan-20260719-v8-ignorechanges -.txt`; same-day baseline re-confirmed 7/2/7 pre-fix). The 2 changes are -the state-blind autostart updates, whose removal is gate G6's reconcile. -The FINAL expected triple gets recorded HERE with the G7 re-plan capture -after G6 closes -- until then this document may not justify an apply. +The EXPECTED outer plan triple is **6 add / 0 change / 6 destroy**, +recorded 2026-07-19 with its evidencing capture +(`docs/audit/outer-plan-20260719-postG6.txt`, "Plan: 6 to add, 0 to +change, 6 to destroy."). WHY: 6 add = the 5 committed DC0 creates +(vvr1_dc0 domain/disk/seed/cloudinit + vr1_dc0_uplink) + voffice1's +benign staging-ISO re-create; 6 destroy = exactly the 6 empty relocated +planes; 0 change = D-130's guard suppressed the seed replace (v8) AND +the G6 state surgery recorded the already-true autostart. History: 7/2/7 +was the post-reboot symptom (decomposition at +`docs/audit/env-snapshot-20260718.md:33-46`); 6/2/6 was post-D-130 +pre-reconcile (v8 capture). A future plan differing from 6/0/6 is a STOP. ## 6. Open gates @@ -207,11 +206,11 @@ |---|------|----------------|-------|---------------------------| | G1 | Audit Phase 3: fresh-agent grounding test | 3 clean-context probes score the 7-question set against this doc; holes map made | session | CLOSED 2026-07-18: 3 probes, 21/21 PASS, holes H1 (amended into G9) + H2 (no action) -- `docs/audit/phase3-grounding-test-20260718.md` | | G2 | Audit Phase 4: GA-R1..R7 structural rulings + the stage-status vocabulary A/B | ruling-type gate (GA-R6 rule 6): closes when every item carries a GA-R5 Status block | operator | CLOSED 2026-07-18: all seven GA-R + vocabulary (Option A + H1) RATIFIED, utterances quoted (`docs/audit/ga-rulings.md`, through commit `fe4f1c4` + this one) | -| G3 | Audit Phase 5: repair sweep of GA-F01..F15 (incl. memory hygiene GA-F05..F08, skill sweep) | operator-gated fix batches, each commit naming its GA-F | operator + session | Batch 0 OPENED by operator 2026-07-19; items 0.1 (repo-lint L10, GA-R1/C1), 0.2 (SEC repoint, GA-R4/F3), 0.3 (counter hardening, GA-F15), 0.4 (extractor vocab scan, GA-F10/H1) landed; Batch 0 CLOSED (verification passed 2026-07-19); Batch 1 OPEN: v8+v7 run (G4 CLOSED), D-130 RULED+implemented (G5 CLOSED); next G6 reconcile ruling -> triple -> G7 re-plan; Batches 2-6 await gates; FREEZE holds for un-gated surfaces | +| G3 | Audit Phase 5: repair sweep of GA-F01..F15 (incl. memory hygiene GA-F05..F08, skill sweep) | operator-gated fix batches, each commit naming its GA-F | operator + session | Batch 0 OPENED by operator 2026-07-19; items 0.1 (repo-lint L10, GA-R1/C1), 0.2 (SEC repoint, GA-R4/F3), 0.3 (counter hardening, GA-F15), 0.4 (extractor vocab scan, GA-F10/H1) landed; Batch 0 CLOSED (verification passed 2026-07-19); Batch 1 items 1-7 COMPLETE (G4/G5/G6/G7 all CLOSED; triple 6/0/6 recorded), batch close verification pending; Batches 2-6 await gates; FREEZE holds for un-gated surfaces | | G4 | The two D-130 verifications | run them, capture output | session | CLOSED 2026-07-19: v8 suppression CONFIRMED (7/2/7 -> 6/2/6, zero forces-replacement; `docs/audit/outer-plan-20260719-v8-ignorechanges.txt` + `-baseline.txt`); v7 no-bounce under running domain, zero residue (`docs/audit/throwaway-v7-20260719.txt`) | | G5 | D-130 mechanism ruling (seed-volume durable fix) | operator rules in Phase 5, quoting G4's captured output | operator | CLOSED 2026-07-19: D-130 ADOPTED (a) ignore_changes (`docs/design-decisions.md` D-130, GA-R5 utterance quoted); implemented in `modules/cloudinit-vm` + `tests/cloudinit-vm` | -| G6 | State reconcile of autostart + seed WITHOUT bouncing guests | gated mechanism per the finding: `tofu import` (reads autostart back) or state surgery, or an operator-scheduled maintenance-window apply; `-refresh-only` is PROVEN a no-op | operator | Operator earlier selected reconcile-first (finding doc:136); superseded into audit sequencing by `2b718f5`; nothing reconciled yet | -| G7 | New captured plan == the post-D-130 expected triple recorded in section 5 | re-plan to a capture file after G5+G6 | session | Impossible today: expected triple UNRESOLVED (section 5) | +| G6 | State reconcile of autostart + seed WITHOUT bouncing guests | gated mechanism, operator-ruled (S3) | operator | CLOSED 2026-07-19: ruled (ii) state surgery (GA-R5); pull -> inject autostart:true on both domains -> push (serial 22->23, backup `terraform.tfstate.pre-G6-20260719`); guests never touched (ids 1/2 unchanged, running) | +| G7 | New captured plan == the expected triple recorded in section 5 | re-plan to a capture file after G5+G6 | session | CLOSED 2026-07-19: capture `docs/audit/outer-plan-20260719-postG6.txt` = 6/0/6, equals section 5 exactly | | G8 | Same-session pre-apply re-verify: 6 planes still empty (0 leases / 0 attached domains) | run in the SAME session as the apply | session | Last verified in a prior session only (finding doc:259-265) | | G9 | DC0 outer apply (deploy step A) | operator-gated, logged (`run-logged.sh`), after G1-G8; audit exit criteria met (charter Phase 6). CANONICAL ENTRY DOC (probe hole H1): `runbooks/dc-dc-phase2-tofu-dc-substrate.md`, with `docs/dc0-deploy-readiness.md` section E as the step table | operator | STOPPED (`43b29d7`); state shows nothing DC0 applied | | G10 | Deploy steps B-E in-sequence gates: SEC-010 `--host-nodes --check` on vvr1-dc0; depth-4 nested boot; D-125 foreign-MAC egress test; MAAS reachability + `TF_VAR_maas_api_key` before step D; netem placeholder step E | exercised during the gated deploy | session (each mutation operator-approved) | Not reached (`docs/dc0-deploy-readiness.md:67-84,170-179`) | diff --git a/docs/audit/outer-plan-20260719-postG6.txt b/docs/audit/outer-plan-20260719-postG6.txt new file mode 100644 index 0000000..201716e --- /dev/null +++ b/docs/audit/outer-plan-20260719-postG6.txt @@ -0,0 +1,390 @@ +module.vr1_dc0_planes.libvirt_network.plane["replication"]: Refreshing state... [id=295dca85-52de-4e78-9894-16e48d969654] +module.vr1_dc1_storage.libvirt_pool.dc: Refreshing state... [id=4a1df114-ee04-4c80-9233-cc0c140c8556] +module.vr1_dc0_planes.libvirt_network.plane["metal-admin"]: Refreshing state... [id=29eca094-9b40-4e8c-9750-d1c7857f0a3c] +module.vr1_dc0_planes.libvirt_network.plane["metal-internal"]: Refreshing state... [id=99768f9d-256a-4a89-90dd-38de04efea03] +module.vr1_dc0_planes.libvirt_network.plane["data-tenant"]: Refreshing state... [id=31782537-790a-4399-a3a9-64dce7232e7b] +module.vr1_dc0_planes.libvirt_network.plane["storage"]: Refreshing state... [id=e5558f0e-9601-48fc-8eff-6a0e6adad0d7] +module.vr1_dc0_planes.libvirt_network.plane["provider-public"]: Refreshing state... [id=3bb1e17c-53ce-4c1a-a4af-c9d6ad1f1c1b] +module.mesh_vr1_dc0_vr1_dc1.libvirt_network.link: Refreshing state... [id=9cbc8589-9f40-48e6-872e-ef3abfe29a93] +module.office1_network.libvirt_network.office1_local: Refreshing state... [id=8fdd2a97-417c-44d4-89e4-ae8d65594135] +module.office1_storage.libvirt_pool.dc: Refreshing state... [id=5f94194c-69c1-4b04-a85f-c18d87303a03] +module.mesh_vr1_dc1_office1.libvirt_network.link: Refreshing state... [id=38a20d2d-cd91-4604-a5f4-8e2a6609633c] +module.mesh_vr1_dc0_office1.libvirt_network.link: Refreshing state... [id=8318548f-c3d6-4e06-bef4-fe3f11d68125] +module.vr1_dc0_storage.libvirt_pool.dc: Refreshing state... [id=7ce1101c-a89e-40ca-9263-5f572bee40a9] +module.voffice1.libvirt_cloudinit_disk.seed: Refreshing state... [id=775234004c2669d9] +module.office1_opnsense.libvirt_volume.disk: Refreshing state... [id=/var/lib/libvirt/vr1/office1/office1-opnsense-disk.qcow2] +module.ubuntu_noble_base.libvirt_volume.base: Refreshing state... [id=/var/lib/libvirt/vr1/office1/ubuntu-24.04-base.qcow2] +module.voffice1.libvirt_volume.seed: Refreshing state... [id=/var/lib/libvirt/vr1/office1/voffice1-cloudinit.iso] +module.voffice1.libvirt_volume.disk: Refreshing state... [id=/var/lib/libvirt/vr1/office1/voffice1-disk.qcow2] +module.office1_opnsense.libvirt_domain.vm: Refreshing state... [name=office1-opnsense] +module.voffice1.libvirt_domain.vm: Refreshing state... [name=voffice1] + +Note: Objects have changed outside of OpenTofu + +OpenTofu detected the following changes made outside of OpenTofu since the +last "tofu apply" which may have affected this plan: + + # module.office1_opnsense.libvirt_domain.vm has changed + ~ resource "libvirt_domain" "vm" { + ~ id = 13 -> 2 + name = "office1-opnsense" + # (11 unchanged attributes hidden) + } + + # module.voffice1.libvirt_domain.vm has changed + ~ resource "libvirt_domain" "vm" { + ~ id = 14 -> 1 + name = "voffice1" + # (11 unchanged attributes hidden) + } + + +Unless you have made equivalent changes to your configuration, or ignored the +relevant attributes using ignore_changes, the following plan may include +actions to undo or respond to these changes. + +───────────────────────────────────────────────────────────────────────────── + +OpenTofu used the selected providers to generate the following execution +plan. Resource actions are indicated with the following symbols: + + create + - destroy + +OpenTofu will perform the following actions: + + # module.voffice1.libvirt_cloudinit_disk.seed will be created + + resource "libvirt_cloudinit_disk" "seed" { + + id = (known after apply) + + meta_data = <<-EOT + instance-id: voffice1-d114 + local-hostname: voffice1 + EOT + + name = "voffice1-cloudinit" + + network_config = <<-EOT + version: 2 + ethernets: + lan: + match: + name: "en*" + dhcp4: true + EOT + + path = (known after apply) + + size = (known after apply) + + user_data = <<-EOT + #cloud-config + hostname: voffice1 + fqdn: voffice1.cloud.neumatrix.local + manage_etc_hosts: true + users: + - name: jessea123 + groups: [adm, sudo] + shell: /bin/bash + sudo: "ALL=(ALL) NOPASSWD:ALL" + ssh_authorized_keys: + - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINOgHIEyfMecOJ/G2Tbw5kKMd4ofUfxdyhVb00cjcpUX vr1-office1-svc + package_update: true + packages: + - qemu-guest-agent + runcmd: + - [systemctl, enable, --now, qemu-guest-agent] + EOT + } + + # module.vr1_dc0_planes.libvirt_network.plane["data-tenant"] will be destroyed + # (because libvirt_network.plane is not in configuration) + - resource "libvirt_network" "plane" { + - autostart = true -> null + - domain = { + - name = "data-tenant.vr1-dc0.cloud.neumatrix.local" -> null + } -> null + - id = "31782537-790a-4399-a3a9-64dce7232e7b" -> null + - mtu = { + - size = 9000 -> null + } -> null + - name = "vr1-dc0-data-tenant" -> null + - uuid = "31782537-790a-4399-a3a9-64dce7232e7b" -> null + } + + # module.vr1_dc0_planes.libvirt_network.plane["metal-admin"] will be destroyed + # (because libvirt_network.plane is not in configuration) + - resource "libvirt_network" "plane" { + - autostart = true -> null + - domain = { + - name = "metal-admin.vr1-dc0.cloud.neumatrix.local" -> null + } -> null + - id = "29eca094-9b40-4e8c-9750-d1c7857f0a3c" -> null + - mtu = { + - size = 9000 -> null + } -> null + - name = "vr1-dc0-metal-admin" -> null + - uuid = "29eca094-9b40-4e8c-9750-d1c7857f0a3c" -> null + } + + # module.vr1_dc0_planes.libvirt_network.plane["metal-internal"] will be destroyed + # (because libvirt_network.plane is not in configuration) + - resource "libvirt_network" "plane" { + - autostart = true -> null + - domain = { + - name = "metal-internal.vr1-dc0.cloud.neumatrix.local" -> null + } -> null + - id = "99768f9d-256a-4a89-90dd-38de04efea03" -> null + - mtu = { + - size = 9000 -> null + } -> null + - name = "vr1-dc0-metal-internal" -> null + - uuid = "99768f9d-256a-4a89-90dd-38de04efea03" -> null + } + + # module.vr1_dc0_planes.libvirt_network.plane["provider-public"] will be destroyed + # (because libvirt_network.plane is not in configuration) + - resource "libvirt_network" "plane" { + - autostart = true -> null + - domain = { + - name = "provider-public.vr1-dc0.cloud.neumatrix.local" -> null + } -> null + - id = "3bb1e17c-53ce-4c1a-a4af-c9d6ad1f1c1b" -> null + - mtu = { + - size = 9000 -> null + } -> null + - name = "vr1-dc0-provider-public" -> null + - uuid = "3bb1e17c-53ce-4c1a-a4af-c9d6ad1f1c1b" -> null + } + + # module.vr1_dc0_planes.libvirt_network.plane["replication"] will be destroyed + # (because libvirt_network.plane is not in configuration) + - resource "libvirt_network" "plane" { + - autostart = true -> null + - domain = { + - name = "replication.vr1-dc0.cloud.neumatrix.local" -> null + } -> null + - id = "295dca85-52de-4e78-9894-16e48d969654" -> null + - mtu = { + - size = 9000 -> null + } -> null + - name = "vr1-dc0-replication" -> null + - uuid = "295dca85-52de-4e78-9894-16e48d969654" -> null + } + + # module.vr1_dc0_planes.libvirt_network.plane["storage"] will be destroyed + # (because libvirt_network.plane is not in configuration) + - resource "libvirt_network" "plane" { + - autostart = true -> null + - domain = { + - name = "storage.vr1-dc0.cloud.neumatrix.local" -> null + } -> null + - id = "e5558f0e-9601-48fc-8eff-6a0e6adad0d7" -> null + - mtu = { + - size = 9000 -> null + } -> null + - name = "vr1-dc0-storage" -> null + - uuid = "e5558f0e-9601-48fc-8eff-6a0e6adad0d7" -> null + } + + # module.vr1_dc0_uplink.libvirt_network.site_wan will be created + + resource "libvirt_network" "site_wan" { + + autostart = true + + domain = { + + name = "vr1-dc0-uplink" + } + + forward = { + + mode = "nat" + } + + id = (known after apply) + + ips = [ + + { + + address = "172.30.2.1" + + prefix = 24 + }, + ] + + mtu = { + + size = 1500 + } + + name = "vr1-dc0-uplink" + + uuid = (known after apply) + } + + # module.vvr1_dc0.libvirt_cloudinit_disk.seed will be created + + resource "libvirt_cloudinit_disk" "seed" { + + id = (known after apply) + + meta_data = <<-EOT + instance-id: vvr1-dc0-d123 + local-hostname: vvr1-dc0 + EOT + + name = "vvr1-dc0-cloudinit" + + network_config = <<-EOT + version: 2 + ethernets: + mgmt: + match: + name: "enp1s0" + set-name: mgmt + addresses: ["172.31.0.2/30"] + routes: + - to: "10.10.0.0/22" + via: "172.31.0.1" + uplink: + match: + name: "enp2s0" + set-name: uplink + dhcp4: false + dhcp6: false + bridges: + br-vr1-dc0-wan: + interfaces: [uplink] + dhcp4: false + dhcp6: false + parameters: + stp: false + forward-delay: 0 + EOT + + path = (known after apply) + + size = (known after apply) + + user_data = <<-EOT + #cloud-config + hostname: vvr1-dc0 + fqdn: vvr1-dc0.cloud.neumatrix.local + manage_etc_hosts: true + users: + - name: jessea123 + groups: [adm, sudo] + shell: /bin/bash + sudo: "ALL=(ALL) NOPASSWD:ALL" + ssh_authorized_keys: + # D-126 per-env-key (ruling 2026-07-16, option a): vvr1-dc0 authorizes the DEDICATED + # dc0 key, NOT office1's -- per-env blast-radius isolation. Inner root's qemu+ssh matches. + - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAID54oMqwY4majxq4oWpBviXb6DlVyj99TUPxDkhszcZG vr1-dc0_svc (D-126 per-env key) + package_update: true + packages: + - qemu-guest-agent + runcmd: + - [systemctl, enable, --now, qemu-guest-agent] + EOT + } + + # module.vvr1_dc0.libvirt_domain.vm will be created + + resource "libvirt_domain" "vm" { + + autostart = false + + cpu = { + + features = [] + + mode = "host-passthrough" + } + + devices = { + + disks = [ + + { + + driver = { + + type = "qcow2" + } + + source = { + + volume = { + + pool = "vr1-dc0-pool" + + volume = "vvr1-dc0-disk.qcow2" + } + } + + target = { + + bus = "virtio" + + dev = "vda" + } + }, + + { + + device = "cdrom" + + source = { + + volume = { + + pool = "vr1-dc0-pool" + + volume = "vvr1-dc0-cloudinit.iso" + } + } + + target = { + + bus = "sata" + + dev = "sda" + } + }, + ] + + interfaces = [ + + { + + model = { + + type = "virtio" + } + + source = { + + network = { + + network = "mesh-vr1-dc0-office1" + } + } + }, + + { + + model = { + + type = "virtio" + } + + source = { + + network = { + + network = "vr1-dc0-uplink" + } + } + }, + ] + } + + features = { + + acpi = true + + apic = {} + } + + id = (known after apply) + + memory = 425984 + + memory_unit = "MiB" + + name = "vvr1-dc0" + + os = { + + type = "hvm" + + type_arch = "x86_64" + + type_machine = "q35" + } + + running = true + + type = "kvm" + + uuid = (known after apply) + + vcpu = 108 + } + + # module.vvr1_dc0.libvirt_volume.disk will be created + + resource "libvirt_volume" "disk" { + + allocation = (known after apply) + + backing_store = { + + format = { + + type = "qcow2" + } + + path = "/var/lib/libvirt/vr1/office1/ubuntu-24.04-base.qcow2" + } + + capacity = 3221225472000 + + id = (known after apply) + + key = (known after apply) + + name = "vvr1-dc0-disk.qcow2" + + path = (known after apply) + + physical = (known after apply) + + pool = "vr1-dc0-pool" + + target = { + + format = { + + type = "qcow2" + } + + path = (known after apply) + } + } + + # module.vvr1_dc0.libvirt_volume.seed will be created + + resource "libvirt_volume" "seed" { + + allocation = (known after apply) + + capacity = (known after apply) + + create = { + + content = { + + url = (known after apply) + } + } + + id = (known after apply) + + key = (known after apply) + + name = "vvr1-dc0-cloudinit.iso" + + path = (known after apply) + + physical = (known after apply) + + pool = "vr1-dc0-pool" + } + +Plan: 6 to add, 0 to change, 6 to destroy. + +───────────────────────────────────────────────────────────────────────────── + +Note: You didn't use the -out option to save this plan, so OpenTofu can't +guarantee to take exactly these actions if you run "tofu apply" now.