The READ half was proven earlier today. This closes the other half: configuration written through the REST API reaches the running daemon. (a2) is now demonstrated end to end, not argued.
POST kea/dhcpv4/set_subnet/93473635-f2aa-5c0a-986c-438e59088c6c -> {"result":"saved"}
POST kea/service/reconfigure -> {"status":"ok"}
GET kea/service/status -> {"status":"running"}
Deliberately IDEMPOTENT: the payload was the exact values read back from the API moments before (subnet 10.10.0.0/24, pools 10.10.0.100-10.10.0.199, routers/domain_name_servers 10.10.0.1, description "LAN DHCP"). Nothing about the edge's behaviour should change -- the point was to exercise the WRITE path, not to alter the edge.
The API saying {"result":"saved"} is the service's own verdict. What was actually measured on the box:
kea-dhcp4 pid 30027 (RESTARTED), bound udp4 10.10.0.1:67
Kea's OWN generated config (/usr/local/etc/kea/kea-dhcp4.conf -- the daemon's JSON, not OPNsense's XML):
interfaces : ['vtnet0'] subnet : 10.10.0.0/24 pools : ['10.10.0.100-10.10.0.199'] routers : 10.10.0.1 domain-name-servers : 10.10.0.1 domain-name : office1.vr1.cloud.neumatrix.local
Router unaffected (the endpoint touches only Kea, but verify, never assume): WAN 172.30.1.2, LAN 10.10.0.1, default route 172.30.1.1, 8 LAN pass rules loaded in pf, egress to 1.1.1.1 at 0.0% packet loss.
The full chain works: API write -> OPNsense renders -> Kea loads -> daemon serves.
OPNsense GET returns select fields as {value: {selected: 0|1}}; SET expects the comma-joined selected values. A GET response is therefore NOT directly re-POSTable -- it must be flattened:
{"routers": {"10.10.0.1": {"value": "10.10.0.1", "selected": 1}}} # what GET returns
{"routers": "10.10.0.1"} # what SET expects
kea/service/reconfigure is the apply verb (ServiceController extends ApiMutableServiceControllerBase; $internalServiceName = 'kea'). Without it the config is saved but the daemon is not reloaded.
DHCP on this edge is now API-managed. Pushing a full rendered config.xml would clobber it. Do not run the old scp/install/reboot path against Office1. The template must be reduced to a minimal bootstrap (sshd + root key + console) before it is used again -- that is the next step under D-113(a2), and it is NOT yet done.
Re-POST the previous values (they are unchanged, so nothing to undo), or from the GUI: Services > Kea DHCP > DHCPv4 > Subnets. The pre-API config.xml backups remain in /conf/backup/ on the edge.