3.9 KiB
Why
apps/device-host-agent is a headless outbound worker: it has no HTTP server, no static assets, and no way to inspect or manage a running instance except by reading log output or editing tasks/*.sqlite3/tasks/*.json files by hand on the edge machine. Operators installing a new Host on an edge device (Mac/iPhone rig, etc.) currently must use device-host-agent setup (terminal-only, getpass) to create the local account, and have no local way to see heartbeat/enrollment status, review or edit locally registered devices, or check why the last assignment failed, without SSH-ing in and reading raw state files or cross-referencing the Cloud Console (which only shows what the Host last reported, not local-only state like unenrolled devices). A minimal local web page closes that operational gap.
What Changes
- Add an embedded, server-rendered local web console to the Host Agent process: plain HTML responses from a lightweight HTTP server (no separate frontend build, no SPA framework), with a handful of endpoints returning small JSON fragments that a few inline
<script>blocks poll to refresh sections of the page without a full reload. - Web console covers: status/monitoring (heartbeat/last-seen, enrollment/identity state, registered local devices and their status, current assignment/execution progress, sanitized effective config such as
control_plane_urlandhost_idwithtokennever rendered), local device management (add/edit/remove entries instorage/device_config.py'sDeviceConfigStore), account settings (change the local account password in place; creating the first account remains the job ofdevice-host-agent setup), and recent assignment/heartbeat history (a new bounded local log, since the Host Agent does not currently retain any local record of past assignments after reporting results to the control plane). - New
HostAgentConfigfields to gate and bind the console: disabled by default, and when enabled defaults to binding127.0.0.1only; binding to a non-loopback address is possible but requires an explicit opt-in and is treated as a documented, operator-accepted risk (no built-in TLS or rate limiting — see design.md threat model). - Web login reuses the existing
host_agent/local_account.pyPBKDF2 credential (same account asdevice-host-agent setupcreates/resets); no second credential store. device-host-agentgains a new optional dependency on a minimal ASGI/WSGI server library to host the embedded HTTP server;HostAgentApplicationstarts/stops it alongside the existing heartbeat and claim loop.
Capabilities
New Capabilities
host-agent-local-console: embedded local-only web UI for the Host Agent covering status monitoring, local device CRUD, local account password change, and bounded recent-assignment/heartbeat history, authenticated against the existing local account and disabled/loopback-bound by default.
Modified Capabilities
(none — host-agent-protocol covers the outbound cloud protocol and is unaffected; this change only adds a local-only inbound surface)
Impact
- Affected code:
apps/device-host-agent/host_agent/(newwebmodule/package,app.pywiring,config.pynew fields),apps/device-host-agent/pyproject.toml(new HTTP server dependency),storage/device_config.py(consumed for device CRUD, no schema break expected), new local history storage (new SQLite table or file, scoped to the Host Agent). - Not affected:
cloud.*,apps/cloud-api,cloud-console/,console/,host-agent-protocoloutbound behavior,openspec/changes/edge-host-self-enrollment(its CLI-only local-account bootstrap requirement is unchanged and remains the only way to create the first account; this change only adds a way to change the password afterward through the web UI). - Operational impact: a new local listening port on edge devices when explicitly enabled; default-off and loopback-only by default keep the default deployment posture unchanged.