Files
agentic-mobile-control/openspec/changes/host-agent-local-console/proposal.md
T
2026-07-14 07:31:31 +08:00

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_url and host_id with token never rendered), local device management (add/edit/remove entries in storage/device_config.py's DeviceConfigStore), account settings (change the local account password in place; creating the first account remains the job of device-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 HostAgentConfig fields to bind and retain console state: the Console starts with every Host Agent and binds 127.0.0.1 by default; 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.py PBKDF2 credential (same account as device-host-agent setup creates/resets); no second credential store.
  • device-host-agent gains a new optional dependency on a minimal ASGI/WSGI server library to host the embedded HTTP server; HostAgentApplication starts/stops it alongside the existing heartbeat and claim loop.

Capabilities

New Capabilities

  • host-agent-local-console: embedded local 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 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/ (new web module/package, app.py wiring, config.py new 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-protocol outbound 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: every Host Agent opens a local listener on startup; loopback-only binding by default limits that new surface to the edge machine itself.