D-113(a2) step 1: thin OPNsense REST API client + harness
First delivery under the D-113 ruling (stay on OPNsense, move config off hand-authored
config.xml and onto the documented REST API).

  scripts/opnsense-api.sh        -- [--dry-run] <GET|POST> <api-path> [json-body]
  tests/opnsense-api/run-tests.sh -- offline harness, 21 PASS, no network, no real key

Gauntlet ALL GREEN (53 harnesses, was 52). repo-lint 0 fail.

Design decisions that the harness now enforces:

- THE SECRET NEVER REACHES ARGV. Credentials are read from a file and handed to curl via
  --config on STDIN. `curl -u key:secret` would put the secret in argv, where any user on the
  box can read it out of `ps`. Harness T9 stubs curl with an argv recorder and asserts the
  secret is absent from argv and present on stdin -- so a future "simplification" to `curl -u`
  turns the harness red. That case is the point of the file.
- The API host is NEVER inferred (hard rule 2): $OPNSENSE_API_HOST unset is a loud failure, not
  a silent default of 10.10.0.1 (T3).
- --insecure is deliberate and scoped: the edge's self-signed cert is REGENERATED ON EVERY BOOT
  (measured -- "Created web GUI TLS certificate" appears in the config revision trail after each
  reboot), so pinning it is pointless. Acceptable ONLY on the private lab LAN leg; never to be
  copied to a tenant-facing surface.
- Dry-run reads no credentials (T11), which is what lets the harness prove URL construction
  offline.

NOT RUN against the edge yet, and blocked on one thing: the API is alive (lighttpd on 443
answers 401) but root has 0 API keys. Minting one is a GUI action (System > Access > Users >
root > API keys), deliberately NOT automated -- writing apikeys into config.xml by hand is the
exact anti-pattern D-113 just retired. Key lands in ~/vr1-office1-creds/opnsense-api.txt,
operator-only, never read into agent context (SEC-007 covers that directory).

Proof-of-path once the key exists: drive yesterday's DHCP subnet through the API and confirm it
round-trips. If it does, the template retires to a minimal bootstrap config (sshd + root key +
console + apikey) and DHCP/firewall/interfaces move to the API. If it cannot express it, that is
the signal to revisit D-113.

Revert: git rm scripts/opnsense-api.sh && git rm -r tests/opnsense-api/ (nothing live touched).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01B6Fzre1CxCY8tzwFCudu57
1 parent 49b3dc7 commit 268eb0335754fe4103cdf3d2467ccf345183a9fa
@JANeumatrix JANeumatrix authored 17 hours ago
Showing 40 changed files
View
docs/changelog-20260713-opnsense-api-client.md 0 → 100644
View
docs/session-ledger.md
View
scripts/opnsense-api.sh 0 → 100755
View
tests/carve-host-interfaces/fakebin/maas 100644 → 100755
File mode changed
View
tests/opnsense-api/run-tests.sh 0 → 100755
View
tests/phase-00-maas-standup/fakebin/maas 100644 → 100755
File mode changed
View
tests/phase-02/fakebin/jq 100644 → 100755
File mode changed
View
tests/phase-02/fakebin/juju 100644 → 100755
File mode changed
View
tests/phase-03-adminrc/fakebin/juju 100644 → 100755
File mode changed
View
tests/phase-03-adminrc/fakebin/openssl 100644 → 100755
File mode changed
View
tests/phase-03-adminrc/fakebin/openstack 100644 → 100755
File mode changed
View
tests/phase-03/fakebin/jq 100644 → 100755
File mode changed
View
tests/phase-03/fakebin/juju 100644 → 100755
File mode changed
View
tests/phase-04-create/fakebin/maas 100644 → 100755
File mode changed
View
tests/phase-04-create/fakebin/openstack 100644 → 100755
File mode changed
View
tests/phase-04-internal-cert-san/fakebin/juju 100644 → 100755
File mode changed
View
tests/phase-04-internal-cert-san/fakebin/openstack 100644 → 100755
File mode changed
View
tests/phase-04/fakebin/maas 100644 → 100755
File mode changed
View
tests/phase-04/fakebin/openstack 100644 → 100755
File mode changed
View
tests/phase-05-amphora/fakebin/curl 100644 → 100755
File mode changed
View
tests/phase-05-amphora/fakebin/juju 100644 → 100755
File mode changed
View
tests/phase-05-amphora/fakebin/openstack 100644 → 100755
File mode changed
View
tests/phase-05-amphora/fakebin/sha256sum 100644 → 100755
File mode changed
View
tests/phase-05-amphora/fakebin/wget 100644 → 100755
File mode changed
View
tests/phase-05/fakebin/juju 100644 → 100755
File mode changed
View
tests/phase-05/fakebin/openstack 100644 → 100755
File mode changed
View
tests/phase-06-bootstrap/fakebin/curl 100644 → 100755
File mode changed
View
tests/phase-06-bootstrap/fakebin/openstack 100644 → 100755
File mode changed
View
tests/phase-06-bootstrap/fakebin/sha256sum 100644 → 100755
File mode changed
View
tests/phase-06-bootstrap/fakebin/wget 100644 → 100755
File mode changed
View
tests/phase-06-capi-stack/fakebin/ssh 100644 → 100755
File mode changed
View
tests/phase-06-k8s-bootstrap/fakebin/ssh 100644 → 100755
File mode changed
View
tests/phase-06-kubeconfig-gate/fakebin/kubectl 100644 → 100755
File mode changed
View
tests/phase-06-kubeconfig-gate/fakebin/ssh 100644 → 100755
File mode changed
View
tests/phase-06-mgmt-vm/fakebin/openstack 100644 → 100755
File mode changed
View
tests/phase-06-net-setup/fakebin/openstack 100644 → 100755
File mode changed
View
tests/phase-07-conductor-graft/fakebin/juju 100644 → 100755
File mode changed
View
tests/phase-07-conductor-graft/fakebin/kubectl 100644 → 100755
File mode changed
View
tests/phase-07-conductor-graft/fakebin/openstack 100644 → 100755
File mode changed
View
tests/reenroll-hosts/fakebin/maas 100644 → 100755
File mode changed