carlos / platform Public

Boxes should self-update the platform binary via a channel subscription Idea open

Migrated from github.com/carlosframework/platform issue #333, opened 2026-08-28. GitHub issues are closed for this repo; see AGENTS.md, "Work is tracked on amadan, not GitHub".

Still outstanding: Boxes should self-update the platform binary via a channel subscription rather than an operator-run script.

---

Problem

Rolling a new platform binary today is an operator-side push: build (or fetch) the arm64 binary, upload it to each deployment's bootstrap/carlos bucket key, then run update-platform-binary.sh over SSM per box (install, re-stage embedded units, sysusers-before-tmpfiles, re-arm the adopt timer/path units, restart the edge). That has two structural costs:

  1. It makes every platform roll a vendor concern. Tito is a third-party deployment; a platform-dev session holding SSM access to a customer's boxes to push binaries is the wrong trust shape (Paul, 2026-08-27/28 — tito rolls are moving to a Tito-side operator agent as the near-term fix; runbook now lives in amadan.net/tito/carlos-infrastructure).
  2. It doesn't scale with boxes. 9 boxes today, per-box SSM invocations, ordering rules held in operator memory (home boxes before region edges, #300).

Idea

The platform already has exactly the machinery this needs — releases, channels, and a box-side adoption loop. Let the platform binary be a subscriber of its own releases:

  • Platform builds are shipped as releases on a reserved channel (e.g. platform/stable, with platform/canary below it for staged rollouts).
  • Each box subscribes (a host.env or registry setting; per-box channel choice gives canary boxes for free).
  • The adoption pass notices a new platform release, verifies signature + sha against the embedded release key, and installs: the same dance update-platform-binary.sh does today — binary swap, bootstrap -root unit staging, sysusers applied before tmpfiles (the #104 group-resolution trap), tmpfiles, daemon-reload, re-arm carlos-adopt.timer/carlos-adopt.path/carlos-stage.path/carlos-restart.path, then a graceful edge restart.
  • Postconditions stay postconditions: a box that can't verify or whose units don't come back active must roll back to the previous binary and report, not stay half-updated.

What this retires

  • update-platform-binary.sh and per-deployment roll runbooks (flagship, tito, dev).
  • The vendor needing box access on third-party deployments for routine updates.

Cares

  • Self-update ordering across a fleet (home box first? staggered?) becomes a policy the platform owns instead of operator lore.
  • The updater must never break the static-user tenants trap that update-platform-binary.sh exists to avoid (full carlos bootstrap re-chowns /data — that's why the script stages units into a temp root instead).
  • Interaction with carlos update (#161's CLI self-update): same verification chain, different artifact/trigger — worth sharing the signature plumbing.