Retroactive changelog for commit 522ba7d (the script) and 3b01dd4 (the D-113 amendment). The code shipped with a green harness and a clean lint, but without this entry -- the delivery rule requires all three. Closing that gap; no code changes here.
D-113(a2) asserts the OPNsense edge is configured "via the REST API", and lists interfaces among the API-covered surfaces. Measured on the live Office1 edge (OPNsense 26.1): that is false. Interfaces > [LAN] is served by the LEGACY page /interfaces.php?if=lan. Only the Devices and Neighbors sub-trees were ever migrated to MVC. There is no REST endpoint for a base interface's ipaddrv6.
The claim was inferred from DHCP and firewall being API-native, and never measured. It sat in an ADOPTED decision as if it were a fact. D-113 now carries the amendment.
scripts/opnsense-set-iface-v6.php -- runs ON the edge; loads the LIVE config through OPNsense's own Config singleton, mutates exactly two leaf fields (ipaddrv6, subnetv6), asserts the interface count is unchanged, and lets the vendor's own code serialize it.scripts/opnsense-set-interface-v6.sh -- ships the setter over SSH, runs it, applies with configctl interface reconfigure, then proves the address is on the wire.tests/opnsense-set-interface-v6/run-tests.sh -- offline harness, 40/40 PASS (ssh/scp stubbed; no edge contacted).DRY BY DEFAULT. Without --commit nothing is written and nothing is applied.
The distinction is the whole point, and it is the difference between this and the path D-113(a2) deleted. It never authors a config. It mutates two leaves of the edge's own live config object through the vendor's own model -- the identical code path interfaces.php runs on Save. Nothing is replaced wholesale, so the API-managed Kea DHCP and the firewall rules cannot be clobbered (standing lesson 1: a full rendered config.xml push WOULD clobber them).
Same principle as opnsense-bootstrap-apikey.sh: call the vendor's interface, do not re-implement the internals.
tcsh. A $(...) inside a quoted remote command dies with "Illegal variable name", and it dies QUIETLY. Every remote command here is fed to sh -s over stdin (standing lesson 5).configctl interface reconfigure, and hence the verify reads ifconfig -- the KERNEL -- and not the config file. A {"result":"saved"}-style self-report is not evidence.This is Stage 2 close-out item C1, and C1 is still OPEN. The script exists; the address is not on the edge. Executing it is a live mutation and remains operator-gated.
Two things to carry into that execution:
/api/radvd/settings/addEntry). The address alone is not the deliverable; the LAN needs RA to be useful.Stage 3 builds DC0's and DC1's edges from the same module. This script takes them verbatim -- only the host and address change. That was the operator's stated reason for scripting it rather than clicking it once in the GUI: the same treatment gets paid three times.
The interface-name-to-device mapping is a hardcoded lan->vtnet0 / wan->vtnet1 sed. It is correct for the Office1 edge as built, but it is an ASSUMPTION about device ordering that a DC edge with a different NIC count could break. It would fail loudly (the verify reads the wrong device and the script exits 2), not silently. Worth deriving from the edge's own config before Stage 3 reuses it.
git rm scripts/opnsense-set-interface-v6.sh scripts/opnsense-set-iface-v6.php git rm -r tests/opnsense-set-interface-v6/ git rm docs/changelog-20260714-opnsense-set-interface-v6.md
Nothing live depends on these: the script has never been run with --commit, so the live edge is unaffected by its existence. The D-113 amendment prose (3b01dd4) is a separate revert and should be KEPT regardless -- it records a measurement, not a tool.