# UI and CLI reliability fixes — 2026-10-30 ## Behavior - Bare `/log` works. The command executor contains handler panics so a bad command cannot terminate the router service. - HTTP (`www`) and HTTPS (`www-ssl`) are gated independently, using the actual TLS connection rather than a client-supplied forwarded header. - SSH exec reports failures with exit status 1. SSH request decoding preserves full command lengths and decodes PTY sizes using the SSH wire format. - CLI arguments accept single/double quotes, including comments containing spaces. Unterminated quotes produce a syntax error; no shell is invoked. - The standalone `debtik-cli` authenticates in interactive and single-command modes, validates login success, preserves buffered terminal data and restores terminal state on signals. Single-command mode requires credentials. - Bandwidth duration 0 runs until Stop. Rolling telemetry retains 200 samples, while summary rates use complete byte totals and elapsed time; peaks and mean jitter include samples evicted from the window. Loss uses cumulative counts. - The UI tracks sample elapsed time within a session rather than array length, so rolling history keeps updating after 100 seconds. A new session resets the cursor. SSE observers have individual bounded queues and unsubscribe cleanly. - Stop reports API rejection instead of showing success. A successful Stop request waits for test status to confirm completion. - Concurrent identical API GETs share one request with independent response copies. Core refresh cycles do not overlap; infrequently changing summaries refresh every 30 seconds. Active views still refresh their own data. Duplicate certificate/service requests were removed. - A visible header status identifies incomplete/unavailable telemetry and the last successful update. API reads have a 15-second timeout. Core/traffic updates pause in hidden tabs, resume on visibility, and session pollers stop on logout. Bearer injection is restricted to this origin's API. - Both BGP status badges update; the HTML contains no duplicate IDs. - Bandwidth server telemetry preserves unsaved modal fields. Opening the modal starts from the latest stored configuration rather than stale unsaved edits. - AeroTUN setup explains disabled drafts, local identity creation, reciprocal peer keys, shared PSKs and allowed source prefixes. The first v3 draft stays open and displays its generated public key with a copy control. Private keys and saved PSKs are never returned by the UI/API. Copy the initial PSK before saving if it needs to be transferred to the peer; later blank edits retain it. Tunnel status distinguishes saved/disabled, stopped, connecting, connected and failed. A successful Start reports interface startup rather than connection. ## AeroTUN CLI Read-only users can inspect public configuration and runtime state: ```text /interface aerotun print /interface aerotun print detail=yes ``` Only full administrators can generate a shared PSK or change configuration: ```text /interface aerotun genkey /interface aerotun add name=aerotun1 mode=server local-address=10.99.1.1/30 peer-address=10.99.1.2/32 allowed-ips=10.99.1.2/32 psk= disabled=yes comment="office uplink" /interface aerotun set aerotun1 peer-public-key= /interface aerotun enable aerotun1 /interface aerotun disable aerotun1 /interface aerotun start aerotun1 /interface aerotun stop aerotun1 /interface aerotun remove aerotun1 ``` `add` defaults to v3 with compression off and disabled until configured. It prints the generated public key. `set` preserves unspecified fields and stored identity. The identifier can be either name or ID. Completion includes actions, parameters and configured tunnel names. Allowed prefixes authorize peer source addresses; they do not install routed LAN prefixes. ## Verification ```sh go test ./... go vet ./... go test -race ./internal/cli ./internal/api ./internal/bwtest ./cmd/debtik-cli node --test scripts/ui-regression.test.cjs ``` The Go tests include a real loopback continuous session exceeding ten seconds, bidirectional traffic, Stop, broadcast observers, retained-window summaries, HTTP/HTTPS independence, quoted arguments, AeroTUN privilege checks and secret redaction, standalone authentication and actual SSH exec exit statuses. With Playwright available as a development tool: ```sh DEBTIK_TEST_URL=http://127.0.0.1:8080 node scripts/ui-smoke.cjs ``` Optional environment variables: `DEBTIK_TEST_USER`, `DEBTIK_TEST_PASSWORD`, `PLAYWRIGHT_MODULE`, `UI_TEST_ARTIFACTS`. The smoke test logs into the specified appliance, visits 26 views, and uses intercepted responses for rejected Stop, failed telemetry and draft creation. It does not save real tunnel/server configuration. It logs out its own session afterward. Development browser tools are not a runtime dependency of the appliance. ## Deployment and recovery Both Linux amd64/veth and Linux arm64/TUN appliances received the updated server and CLI. AeroTUN configuration hashes and peer identities were unchanged. Backups on both hosts: `/root/.local/share/debtik-backups/ui-cli-20261030T140028Z/`. Builds, test logs and browser artifacts: `/root/.local/share/debtik-builds/ui-cli-fixes/`. Live checks confirmed overlay ping, CLI inspection, SSH exit status, continuous UDP in both directions and two simultaneous SSE observers receiving the same 23 samples. The capped 200 kbit/s test measured about 194/196 kbit/s with no reported loss; this was a functionality check, not a capacity benchmark. The 35 browser checks passed against each deployed host (26 views plus nine behavior checks), with zero JavaScript runtime errors. Rollback timers were cancelled after verification; both backups contain a `committed` marker.