Skip to content

docs(product): design embedded-mode revival — dual-mode returns, finish macOS (RIG-3139) - #833

Open
rigel-mintaka wants to merge 3 commits into
mainfrom
compass-native/rig-3139-embedded-revival
Open

docs(product): design embedded-mode revival — dual-mode returns, finish macOS (RIG-3139)#833
rigel-mintaka wants to merge 3 commits into
mainfrom
compass-native/rig-3139-embedded-revival

Conversation

@rigel-mintaka

@rigel-mintaka rigel-mintaka commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Reverses the RIG-2542 client-only retirement: brings mode="embedded" back to the native app as the low-friction onboarding / local-dev front door, ADDED ALONGSIDE the fully-surviving client mode, and designs finishing it for macOS. Matt's 2026-09-01 ruling: support BOTH podman and microVM runners going forward, so embedded mode returns and gets finished for macOS.

The retirement's premise is falsified. The client-only epic (DL-235) was driven by one upstream constraint — the container Runner being dropped once the microVM Runner lands, which requires a KVM floor. Keeping both runners makes rootless podman a permanent supported tier for single-tenant deployments, so the KVM-gating that retired embedded is gone and the retirement reverses cleanly: the supervisor design was never unbuilt (DL-108 stayed Active), only the app's invocation of it was deleted.

Client mode survives whole. This removes the word "only" from the client-only thesis, not the client. The client surface stays first-class and is the recommended steady-state for a real self-host deployment (always-on stack on a VPS/EC2, app connects over TLS) and the only mode for the managed product.

Topology — three funnel entries

  • embedded-local — rootless podman on the user's own machine; the app spawns/supervises a local stack. Onboarding + local dev, zero-config. NOT the production steady-state.
  • self-host-stack — CLIENT mode against an always-on VPS/EC2 running compass-stack up. The suggested self-host steady-state. Unchanged (the built T5 surface).
  • managed-hosted — microVM-only multi-tenant, client mode.

The security boundary follows the trust model, not deployment uniformly (DL-318, compass-obs PR #804): managed multi-tenant is microVM-only because it isolates untrusted tenant code; a single-tenant box running the operator's own code has no untrusted tenant, so rootless podman is the correct boundary — a permanent tier needing no /dev/kvm.

Ledger delta (this PR)

New rows DL-319 (dual-mode thesis), DL-320 (dual-mode app.toml), DL-321 (sidecar bundle sans postgres). Status flips: DL-235 → superseded by DL-319, DL-237 → DL-320, DL-238 → DL-321. DL-236 and DL-259 stay Active (partial supersession recorded by citation in DL-319's cell, per the never-reword convention); DL-215/DL-217/DL-106 keep their existing status (mechanism/shape restored by citation, no resurrection edit).

Open Questions

Seven load-bearing OQs carry recommendations for Matt's gate (postgres-as-container for embedded; embedded-as-absent-app.toml-default with a first-run confirm; --mode override restoration; Windows deferral; the #804 freeze-order dependency; the darwin AF_UNIX-over-virtiofs socket-topology gap; and — added by the review fold — whether to add a podman-version FATAL preflight check, OQ-8); one non-load-bearing deferral (quit-anyway on failed teardown). Per the design skill, load-bearing OQs are resolved at Matt's freeze; the record designs against stated assumptions meanwhile.

Review

Drafted by a design subagent, red-teamed by a design-critic subagent (12 findings, all folded), then driver-reviewed and run through the mandatory review pass (one adversarial reviewer). The review returned 0 high, 1 medium, 1 low; both folded in commit 1988521d:

  • Medium — §A3 delta 3's rationale for NOT preflighting the podman ≥ 4.3 floor ("the runner's own legible refusal is the error surface") is false on the embedded path: the runner is the last step of stack.Up, spawned via cmd.Start() (a launch that returns before its startup gate runs), Up already reached Ready at the server poll so it returns nil, and runStackUp deletes the runner's stderr unread on exit 0 — so on a rootless-podman-<4.3 host (Ubuntu 22.04 LTS = podman 3.4.4) embedded launches apparently-green but agent-dead with no legible error. Fixed: drop the false prose, design a podman-version FATAL check into preflight v2 (delta 4, reusing runtime.VerifyUsernsRemapSupport), thread it through T-2 (do/test + runner-alive smoke, not just board-renders), and mint OQ-8 [load-bearing] flagging it as a reversal of the draft's affirmative no-check ruling for Matt's gate.
  • Low — §A2 overclaimed prependExecDirToPath returns verbatim; its doc-comment sidecar list names compass-postgres, which DL-321 drops. Reconciled in §A2 and T-2.

Implementation is decomposed into per-task follow-ups filed after freeze.

Spec-impact: none.
Ledger-impact: adds DL-319/320/321; flips DL-235/237/238 to superseded.
Refs RIG-3139, RIG-1662
Co-authored-by: Matt Wilkinson matt@rigel.build

…sh macOS (RIG-3139)

Reverses the RIG-2542 client-only retirement: brings `mode="embedded"` back to the native app as the low-friction onboarding / local-dev front door, ADDED ALONGSIDE the fully-surviving client mode, and designs finishing it for macOS. Matt's 2026-09-01 ruling: support BOTH podman and microVM runners going forward, so embedded mode returns and gets finished for macOS.

**The retirement's premise is falsified.** The client-only epic (DL-235) was driven by one upstream constraint — the container Runner being dropped once the microVM Runner lands, which requires a KVM floor. Keeping both runners makes rootless podman a permanent supported tier for single-tenant deployments, so the KVM-gating that retired embedded is gone and the retirement reverses cleanly: the supervisor design was never unbuilt (DL-108 stayed Active), only the app's invocation of it was deleted.

**Client mode survives whole.** This removes the word "only" from the client-only thesis, not the client. The client surface stays first-class and is the recommended steady-state for a real self-host deployment (always-on stack on a VPS/EC2, app connects over TLS) and the only mode for the managed product.

### Topology — three funnel entries

- **embedded-local** — rootless podman on the user's own machine; the app spawns/supervises a local stack. Onboarding + local dev, zero-config. NOT the production steady-state.
- **self-host-stack** — CLIENT mode against an always-on VPS/EC2 running `compass-stack up`. The suggested self-host steady-state. Unchanged (the built T5 surface).
- **managed-hosted** — microVM-only multi-tenant, client mode.

The security boundary follows the trust model, not deployment uniformly (DL-318, compass-obs PR #804): managed multi-tenant is microVM-only because it isolates untrusted tenant code; a single-tenant box running the operator's own code has no untrusted tenant, so rootless podman is the correct boundary — a permanent tier needing no `/dev/kvm`.

### Ledger delta (this PR)

New rows DL-319 (dual-mode thesis), DL-320 (dual-mode app.toml), DL-321 (sidecar bundle sans postgres). Status flips: DL-235 → superseded by DL-319, DL-237 → DL-320, DL-238 → DL-321. DL-236 and DL-259 stay Active (partial supersession recorded by citation in DL-319's cell, per the never-reword convention); DL-215/DL-217/DL-106 keep their existing status (mechanism/shape restored by citation, no resurrection edit).

### Open Questions

Six load-bearing OQs carry recommendations for Matt's gate (postgres-as-container for embedded, embedded-as-absent-app.toml-default with a first-run confirm, `--mode` override restoration, Windows deferral, the #804 freeze-order dependency, and the darwin AF_UNIX-over-virtiofs socket-topology gap); one non-load-bearing deferral (quit-anyway on failed teardown). Per the design skill, load-bearing OQs are resolved at Matt's freeze; the record designs against stated assumptions meanwhile.

Drafted by a `design` subagent, red-teamed by a `design-critic` subagent (12 findings, all folded), and driver-reviewed before submit. Implementation is decomposed into per-task follow-ups filed after freeze.

Spec-impact: none.
Ledger-impact: adds DL-319/320/321; flips DL-235/237/238 to superseded.
Refs RIG-3139, RIG-1662
Co-authored-by: Matt Wilkinson <matt@rigel.build>
@linear-code

linear-code Bot commented Sep 1, 2026

Copy link
Copy Markdown

RIG-3139

RIG-1662

@trunk-io

trunk-io Bot commented Sep 1, 2026

Copy link
Copy Markdown

Merging to main in this repository is managed by Trunk.

  • To merge this pull request, check the box to the left or comment /trunk merge below.

After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown

Compass engineering docs preview: https://compass-native-rig-3139-embe.compass-eng-docs.pages.dev

Deployed from compass-native/rig-3139-embedded-revival at 175698c.

Changed pages:

rigel-mintaka and others added 2 commits September 1, 2026 01:58
…IG-3139)

Addresses the mandatory review pass on the embedded-revival design record. One medium (blocks hand-off) plus one low, both grounded against main f92bed5.

Medium: §A3 delta 3's rationale for not preflighting the podman >= 4.3 floor ("the runner's own legible refusal is the error surface") is false on the embedded launch path. Traced against main: the runner is the LAST step of stack.Up (stack.go:283-291), spawned via Supervisor.Start -> cmd.Start() (process.go:71, a launch that returns before the runner's startup gate runs); Up already reached Ready at the server poll (stack.go:265-267) so it returns nil regardless; runStackUp reads the captured runner stderr only on a non-zero exit and deletes it unread on exit 0 (embedded.go:224-246 at efea2d2-); and the pre-Ready postgres container uses plain --userns=keep-id (postgres_container.go:171), not the :uid= form, so it never surfaces the floor earlier. Net: on a rootless-podman-<4.3 host (Ubuntu 22.04 LTS = podman 3.4.4) embedded launches apparently-green but agent-dead with no legible error. Fixed by dropping the false prose, designing a podman-version FATAL check into preflight v2 as delta 4 (reusing runtime.VerifyUsernsRemapSupport, podman.go:504), threading it through T-2's do/test/smoke (runner-alive smoke, not just board-renders), and minting OQ-8 [load-bearing] flagging the check as a reversal of the draft's affirmative no-check ruling for Matt's gate.

Low: §A2 overclaimed prependExecDirToPath returns "verbatim" — its doc-comment sidecar list (compass-postgres/compass-server/compass-runner at embedded.go:367) names a binary DL-321 drops from the bundle. Reconciled to compass-server/compass-runner in §A2 and called out in T-2.

Ledger untouched (DL-319/320/321 + flips stand from the prior commit).

Spec-impact: none
Ledger-impact: none (design-record prose + plan only; ledger delta unchanged from prior commit)
Refs RIG-3139, RIG-1662
Co-authored-by: Matt Wilkinson <matt@rigel.build>
@rigel-mintaka
rigel-mintaka marked this pull request as ready for review September 1, 2026 06:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant