The tunnel client now has a desktop UI over the same internal/client
service: status with live connection state, routes with add/remove/copy,
live logs, settings, profile import, and a start/stop button that runs
the bridge in-process. It uses the existing ~/.config/tunnel/config.json
and shows a warning banner with a stop button when the CLI service is
already running and claiming the routes.
Tunnels now get a per-tunnel certificate from the configured ACME CA
(Let's Encrypt by default) with DNS-01 through Porkbun, keeping the
client's CSR and key. Issuance is asynchronous (issuing/ready/failed);
the account persists in the store, renewals run in a 30-day window with
retries, and a failed renewal keeps the old certificate serving.
Switching from the local CA reissues existing tunnels automatically,
and the admin dashboard shows the issuer and certificate state.
Verified against Pebble and Let's Encrypt staging.
HTTP API per the recorded contract, bridge WebSocket, SNI relay with
pass-through tunnel TLS, local CA issuance, JSON store. Verified
end-to-end with the official opentunnel CLI.