Files
2026-07-13 17:55:40 +08:00

4.9 KiB

Why

The Host Agent today cannot start unattended on a fresh install: it requires an operator to hand-carry an out-of-band HOST_AGENT_ENROLLMENT_TOKEN (issued via CLOUD_ENROLLMENT_TOKENS_JSON on the cloud side) before it will enroll, and it accepts any HOST_AGENT_CONTROL_PLANE_URL an installer happens to set, which for the single home deployment at https://amcp.home.jerryyan.top is unnecessary ceremony. There is also no local gate preventing the daemon from starting with no operator ever having touched the machine, and no local record of who set it up. This change removes the pre-issued-token requirement for this deployment, fixes the control-plane address, and adds a one-time local setup gate, while leaving the existing token-based and static-credential paths intact for other deployments.

What Changes

  • Add a Host Agent CLI first-run bootstrap: if no local account file exists, device-host-agent interactively prompts (via getpass) for a username and password, hashes the password, and persists the credential atomically with restricted file permissions before continuing. On later starts, if the account file exists, the daemon starts straight into background polling with no prompt.
  • Change host_agent/config.py::load_host_agent_config default for HOST_AGENT_CONTROL_PLANE_URL from http://127.0.0.1:8001 to https://amcp.home.jerryyan.top; the environment variable still overrides it for development/testing.
  • BREAKING (new deployments only, additive for existing ones): Remove the hard requirement for HOST_AGENT_ENROLLMENT_TOKEN when no local identity and no static HOST_AGENT_HOST_ID/HOST_AGENT_TOKEN are configured. host_agent/enrollment.py::resolve_host_identity now falls back to an unauthenticated self-service enrollment call when no enrollment token is configured, instead of raising HostAgentConfigurationError.
  • Add a cloud-side self-service enrollment mode, gated by a new CLOUD_SELF_SERVICE_ENROLLMENT_ENABLED flag (default false): when enabled, POST /internal/v1/enrollments accepts requests with no enrollment-token bearer credential and stores enrollment_token_digest = NULL for that Host row (the column is already nullable). When the flag is disabled, current behavior (token required, 401 otherwise) is unchanged.
  • Existing static-credential (HOST_AGENT_HOST_ID/HOST_AGENT_TOKEN), token-based enrollment (HOST_AGENT_ENROLLMENT_TOKEN + CLOUD_ENROLLMENT_TOKENS_JSON), and revocation paths from edge-host-enrollment are unchanged and remain fully supported side by side with self-service enrollment.
  • No changes to host_agent/heartbeat.py — periodic device-status reporting already exists and continues to run against the (now-fixed) control-plane URL; this change only confirms the wiring stays intact once the URL and enrollment path change.

Capabilities

New Capabilities

  • host-agent-local-bootstrap: First-run interactive local account creation gate for the Host Agent CLI — credential storage format, hashing, one-time prompt behavior, and non-interactive skip on subsequent starts.

Modified Capabilities

  • edge-host-enrollment: Add a cloud-side self-service enrollment mode that does not require a pre-issued enrollment token, and change the Host Agent's default control-plane URL and fallback behavior when no enrollment token is configured. (Note: this capability's spec currently lives only in the not-yet-archived openspec/changes/edge-host-enrollment/ change, not in canonical openspec/specs/; this change's delta is authored against that pending spec and should be reconciled when edge-host-enrollment is archived.)

Impact

  • Host Agent (apps/device-host-agent): new host_agent/local_account.py (or similarly named) module and CLI wiring in host_agent/cli.py; host_agent/config.py default URL change; host_agent/enrollment.py::resolve_host_identity fallback behavior change; new local credential file (default path under the existing tasks/ state directory, permissions 0600).
  • Cloud Platform (packages/cloud-platform/cloud, apps/cloud-api): control_config.py gains CLOUD_SELF_SERVICE_ENROLLMENT_ENABLED; internal_api/api.py::enroll_host gains a self-service path; no schema migration required (enrollment_token_digest is already nullable).
  • Dependencies: no new third-party dependency for password hashing is planned (stdlib-based); to be confirmed in design.md.
  • Deployment/docs: .env.example, compose.yaml/compose.deploy.yaml, and docs/CLOUD_DEPLOYMENT.md need the new flag documented; docs/MACOS_IPHONE_SETUP.md needs the first-run local-account step documented.
  • Security posture: enabling CLOUD_SELF_SERVICE_ENROLLMENT_ENABLED means any network caller reaching the control-plane URL can self-register as a Host with no approval step; this is an explicit, accepted tradeoff for the single-operator home deployment and is opt-in (default off) for other deployments.