rootfs apps: rev 4, carlos console shorthand, stateless replicas before the Kubernetes move
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 file changed,
+40
−15
docs/superpowers/specs/2026-10-24-rootfs-apps-design.md+40 −15
CI cancelled — superseded by a newer push — run details
diff --git a/docs/superpowers/specs/2026-10-24-rootfs-apps-design.md b/docs/superpowers/specs/2026-10-24-rootfs-apps-design.md| index 9998bbb30..4c0e843e9 100644 |
| --- a/docs/superpowers/specs/2026-10-24-rootfs-apps-design.md |
| +++ b/docs/superpowers/specs/2026-10-24-rootfs-apps-design.md |
| @@ -1,12 +1,14 @@ |
| # Rootfs apps: run any Linux app on your own boxes, isolated like a CARLOS instance |
| **Date:** 2026-10-24 |
| -**Revision:** 3. Draft from a brainstorming session with Paul, 2026-10-24. |
| +**Revision:** 4. Draft from a brainstorming session with Paul, 2026-10-24. |
| Rev 2 answers Astra's builder check (`CODEX-FINDINGS-ROOTFS-APPS-R1.md`, |
| six questions): §5.0 is new, §5.6 and §5.7 are narrowed, §5.2 settles |
| deploy overlap. Marked **(B1-n)**. Rev 3 adds the `release` process |
| (§5.2.1, Paul: "Perfect"), makes `carlos run` part of v1 (§5.5) and adds |
| -interactive sessions (§5.10). |
| +interactive sessions (§5.10). Rev 4: `carlos console` as a declared |
| +shorthand (§5.10), and Q1 answered: stateless replicas land before |
| +step 3 (§6, §13). |
| **Discussion:** amadan carlos/platform #366. |
| **Base:** origin/main 64a002c8. |
| @@ -251,8 +253,8 @@ The manifest names processes: |
| } |
| ``` |
| -- Exactly one `web`, required. At most one `release` (§5.2.1). Zero or |
| - more others, which are workers, names matching a |
| +- Exactly one `web`, required. At most one `release` (§5.2.1) and at |
| + most one `console` (§5.10). Zero or more others, which are workers, names matching a |
| short identifier pattern. Commands are argv arrays, absolute or |
| resolved against the image's `PATH`. Optional `env` (plain values, |
| no secrets) and `working_dir` per process. |
| @@ -503,9 +505,22 @@ interactive session needs a live, two-way stream with a terminal. |
| - **Command.** `carlos run --interactive` (`-it`), e.g. |
| `carlos run -it --app shop --instance shop.example.com -- bin/rails console`. |
| - My call over a new `carlos console` verb: "the console" already names |
| - the control plane in the docs and CLI, and `-it` is what Docker and |
| - kubectl users expect. |
| + `-it` is what Docker and kubectl users expect. |
| +- **`carlos console` is shorthand** (Paul, 2026-10-24) for |
| + `carlos run -it` of the app's declared `console` process: |
| + ```json |
| + "console": {"command": ["bin/rails", "console"]} |
| + ``` |
| + The platform never inspects an image to guess the framework (R6). |
| + Detection happens on the developer's machine: `carlos ship` fills in |
| + `console` when the source looks like a known framework and the |
| + manifest does not declare one, and says what it filled in. Rails |
| + (`bin/rails` and `config/application.rb`): `bin/rails console`. |
| + Laravel (`artisan`): `php artisan tinker`. Django (`manage.py`): |
| + `python manage.py shell`. An explicit `console` always wins. An app |
| + with no `console` gets a refusal from `carlos console` that names |
| + `carlos run -it` and the manifest key. `console` is never started by |
| + the platform on its own; it exists only to be run interactively. |
| - **Transport.** CLI to console over a WebSocket; console to box over the |
| box's existing outbound tunnel (fleet boxes have no inbound path, and |
| need none); on the box, the agent asks the control service for a |
| @@ -520,7 +535,7 @@ interactive session needs a live, two-way stream with a terminal. |
| `carlos run`, an idle timeout, and the run design's maximum duration. |
| - Works for binary apps too, if they ship a shell or REPL; nothing here |
| is rootfs-only except the image the session runs from. |
| -- Not required for step 1 of §6. Required before step 3: a team leaving |
| +- Not required for step 1 of §6. Required before step 4: a team leaving |
| Kubernetes uses `kubectl exec -it ... rails console` and will miss it. |
| ## 6. Order of work |
| @@ -531,10 +546,13 @@ interactive session needs a live, two-way stream with a terminal. |
| §5.8. Neutral names in everything (`shop`, `example.com`). |
| 2. **A tenant's own single-tenant deployment goes nested.** Separate |
| work, outside this design. It is what makes isolation real there. |
| -3. **The Rails app off Kubernetes** onto that deployment: MySQL and |
| +3. **Stateless replicas** (separate design, §12). Paul, 2026-10-24: they |
| + land before the Kubernetes move. |
| +4. **The Rails app off Kubernetes** onto that deployment: MySQL and |
| Redis in the same region through §5.9's egress allow, Sidekiq as a |
| - declared worker, existing uploads through env keys. Whether it also |
| - needs stateless replicas first is §13 Q1. |
| + declared worker, existing uploads through env keys, several copies on |
| + several boxes, `release` run once per release (§5.2.1), and |
| + interactive sessions (§5.10). |
| ### 6.1 What the sample app must show |
| @@ -628,14 +646,18 @@ resource IDs. Managed databases are the customer's choice of endpoint. |
| - Seeds for rootfs are desirable, not required for v1; `carlos run` is |
| required. |
| - `release` timeout 10 minutes by default (§5.2.1). |
| -- Interactive sessions as `carlos run -it`, not `carlos console`; off by |
| - default per app; needed before step 3, not step 1 (§5.10). |
| +- Interactive sessions as `carlos run -it`, with `carlos console` as the |
| + shorthand for a declared `console` process that `carlos ship` fills in |
| + locally for Rails, Laravel and Django; off by default per app; needed |
| + before step 4, not step 1 (§5.10). |
| - The egress allow is in this design because step 3 cannot happen |
| without it, but it is not needed for step 1 and can land after it. |
| ## 12. Follow-ups (separate designs) |
| -- **Stateless replicas** (wanted, Paul 2026-10-24): N copies of an app |
| +- **Stateless replicas** (wanted, and a prerequisite for the Kubernetes |
| + move, Paul 2026-10-24). It must also define `release`'s run-once |
| + scope (§5.2.1) and how a "no local database" app is declared (§5.6): N copies of an app |
| with no local state, on several boxes, behind the edge or a load |
| balancer, with no lease and no litestream. Two kinds of first user: |
| rootfs apps that declare no local database, and existing binary apps |
| @@ -657,4 +679,7 @@ settled above as my calls. B1-6 is Q1. |
| sense", and some apps already keep all their state in S3 with |
| compare-and-swap. So the stateless-replicas design is wanted, for |
| those apps as much as for rootfs ones. Its order relative to step 3 is |
| - still open. |
| + still open. **Answered (Paul, 2026-10-24): yes, stateless replicas land |
| + before the Kubernetes migration.** §6 now has it as step 3. |
| + |
| +No open questions remain. |