carlos / platform Public

carlos run: a member runs an app command against one instance, without root on the box Feature Request open

Claimed by claude~paul@keymail.dev 2 weeks ago

Ask: a member-run, one-off command against ONE instance of an app, without root on the box: carlos run --app <a> --instance <host> -- <argv…>.

Why

On 2026-10-06 a titogo session copied a past event from Tito Pro into a live account and imported 22,462 check-ins (titogo PR #4048, "importer: copy one past event into a live account, and import check-ins scanned by another system"). Every step that touched the box went over aws ssm send-command as root on carlos-tito-ie:

  • running the app's own binary against the instance's database (titogo import event …, titogo import checkins …);
  • reading a credential the app's config already holds (the Pro reader DSN);
  • staging the input file on the box through S3 presigned URLs.

The canary recipe has the same shape: titogo add (registry), auth grant, seed, all over SSM as root.

Two of Tito's team (Doc and Vicky) are blocked from this kind of work today. Handing them SSM would mean root on a box shared by every tenant, with every secret readable. They can already sign in to the console as members of the tito account. What's missing is a platform door for "run this app's command against that instance".

What it should do

  • Who runs, and as whom. The release binary the instance follows (or --version), run as the same identity and sandbox as the instance itself: nested layout, its own directory bound in, nothing else. Never root, never the agent.
  • What it sees. The instance's database and data directory, and the app's config bundle for that instance's environment, exactly as the instance is started (docs/site/cli.md § "What an instance is started with"). Secrets go in through the environment, never echoed.
  • Who may. Gated by account role (an owner/admin capability, or a per-app grant). Allowed per app: it is the app's own binary, so the app decides what its subcommands do.
  • Input files. --file <local path> uploads a file into a scratch directory the command can read ($CARLOS_RUN_DIR), deleted afterwards. Our check-in CSV was 600 KB; a 64 MB cap would cover the realistic cases.
  • Output. stdout and stderr stream back to the terminal, and the exit status becomes carlos run's own.
  • Recorded. An audit row in the console: who, app, instance, argv, version, start, end, exit status. Output is not stored by default. A future --record could keep it.
  • Concurrency with the live instance. The command opens the same SQLite file while the instance runs (WAL), exactly as titogo's importer does today through its own IMMEDIATE transactions. The platform need not stop the instance. A --stopped flag (stop, run, start) would be a later nicety.
  • Waking. A hibernated instance's data must be in place; whether that means waking it or only mounting its directory is the platform's call.

Not asking for

  • An interactive shell. run is argv only, which keeps it auditable.
  • Anything for controld-run (titogo@) instances. Paul, 2026-10-08: those all convert to platform-run (see the companion request on the adoption door), so this only needs to serve platform instances.

Depends on the nested layout being live (#126, tracked in #247). On a flat box, a run would have the same reach as the agent.

Related: #259 (carlos run), #260 (instances create --from), #261 (adoption door after the nested-layout rollout). All three serve platform-run instances only, and all three depend on #126 being rolled out (#247).

Picked up on branch design-run-and-seeded-instances. Spec rev 1: docs/superpowers/specs/2026-10-08-carlos-run-design.md (c66792a3).

Paul's rulings (2026-10-08): any person who is a member of the account may run, service credentials refused (the db pull rule); output comes back as the run's own chunks in the deployment bucket, polled through the console, with no new network path. A new carlos-instance-cmd@ unit (a copy of the seed unit's sandbox, role cmd) runs it; refused on a flat box. --version is left out of v1. Awaiting Paul's review of the written spec, then Astra's.

Astra accepts both specs: carlos run at rev 4 (round 4) and seeded instances at rev 7 (round 7), branch design-run-and-seeded-instances @ 9a6a64f5. Rounds of findings: 20, 13, 4, 2, 1, 1, 0. Every accepted change is in each spec's disposition tables. Implementation plans are being written next.

carlos run landed on main as 37ab10c, squashed from carlos-run at 9f5c740d, which was current with main 1c5718f6 and green in CI. It is not released or rolled yet.

Review and approval

  • Built across four plans, every task reviewed, then a final whole-series review and fix wave.
  • Astra reviewed each main merge until it was sound, including the zero-downtime generation fixes: - an unproven command stop keeps ownership; - commands are bound to their generation; - commands get the serving generation's environment; - commands have their own exe mount; - a command records its build before exec.
  • Copy approved by Paul (RUN-C1 to RUN-C87).
  • The root-read census is ruled by the Plan 14 controller as census-ruling-carlos-run.

Follow-ups

  • #294: the cmd role is outside #292's start/stop fence. The settle retries cover it today.
  • Dev-box check of carlos run after the next roll.

Rollout notes

  • Every record writer must run the new release before any run is admitted.
  • The console needs a sized TMPDIR for 64 MB spools.
  • The new carlos-instance-cmd@ template and the control binary ship together via system apply.