# Apple Container Backend (https://jackin.tailrocks.com/roadmap/apple-container-backend/)



**Status**: Partially implemented — launch-path backend selection, manifest schema, session-contract/telemetry output, and persisted-instance lifecycle dispatch are wired and compile; Phase 0 hardware validation and real Apple Container finalization remain open.

## Shipped facts [#shipped-facts]

The backend code has landed and compiles: the `container` CLI client (<RepoFile path="crates/jackin-runtime/src/apple_container_client.rs" />), the launch/attach/reconnect/stop/remove/session-contract orchestration (<RepoFile path="crates/jackin-runtime/src/runtime/apple_container.rs" />), the `JACKIN_CAPSULE_FORCE_DAEMON` capsule patch (<RepoFile path="crates/jackin-capsule/src/main.rs" />, gated on `forced_daemon_mode` so an inherited env var can't capture a client-mode invocation), and the instance-manifest `BackendResources` union (<RepoFile path="crates/jackin-instance/src/manifest.rs" />, `INSTANCE_MANIFEST_VERSION` 2). The config/workspace `[runtime] default_backend` / `[runtime] backend` fields landed at schema version `v1alpha8` with migration fixtures.

**Backend selection for `jackin load` is wired:** the load pipeline (<RepoFile path="crates/jackin-runtime/src/runtime/launch/launch_pipeline.rs" />) reads `[runtime].backend` / `[runtime].default_backend` via `resolve_backend` (unit-tested, fails closed on an unrecognised backend string) and routes a fresh load to `apple_container::launch`, so `apple-container` is a selectable backend at launch (`jackin load the-architect . --backend apple-container`).

**Session contract and telemetry are also wired, not just planned:** `apple_container::launch` calls `print_session_contract` (kernel boundary, mounts, DinD state, residual risks) and `check_dns` on attach, and emits `debug_log!("apple-container", …)` lines for version probe, container run, capsule-ready, and DNS check.

**Persisted lifecycle dispatch is wired:** <RepoFile path="crates/jackin-runtime/src/runtime/backend.rs" /> defines `ContainerBackend` with required `finalize`, Docker and Apple Container implementations, and manifest-based backend resolution. <RepoFile path="crates/jackin-runtime/src/runtime/cleanup.rs" /> routes purge guards, `eject`, and `exile_all` through it; <RepoFile path="crates/jackin-runtime/src/runtime/attach.rs" /> routes `hardline` through it. Legacy manifests with no backend field still resolve to Docker.

**Still to prove end-to-end:** Apple Container `finalize` intentionally returns an explicit Phase 0 error from the backend trait. The real post-attach dirty-exit/finalization behavior needs macOS 26 ARM hardware validation before it can claim parity with the Docker path.

**The VM path itself is empirical, not code:** launch/attach runs the `container` CLI and rootless DinD inside an apple/container VM, which **cannot be exercised without macOS 26 ARM hardware** — the Phase 0 gate. Run <RepoFile path="scripts/phase0-apple-container.sh" /> there to validate it; nothing in this branch claims Phase 0 has passed, and the launch dispatch currently starts then reclaims the Docker sidecar pending the Phase-0 reorder.

Full architecture (runtime stack, CLI shell-out surface, manifest/schema detail, telemetry spec, known v0.11.0 limitations, design alternatives): [Apple Container backend — architecture and design](/reference/research/isolation/apple-container-backend/).

## Remaining work [#remaining-work]

1. **Phase 0 empirical validation** — requires macOS 26 ARM hardware with `apple/container` v0.11.0+. Run <RepoFile path="scripts/phase0-apple-container.sh" />; result decides whether rootless DinD works inside apple/container VMs and whether the Docker-sidecar-then-reclaim ordering in the launch pipeline can be reordered to skip starting the sidecar at all.
2. **Implement real Apple Container finalization** — `ContainerBackend::finalize` currently returns an explicit Phase 0 error for Apple Container; after hardware validation, wire the post-attach dirty-exit/finalization behavior to match the Docker lifecycle semantics where possible.
3. **Rootless DinD validation** — blocked on the [Docker runtime hardening contract](/roadmap/docker-runtime-hardening-contract/) confirming `--cap-add CAP_SYS_ADMIN` works inside an apple/container VM.

## Out of scope [#out-of-scope]

* smolvm as an alternative VM backend — separate fallback track, see [smolvm backend research](/reference/research/isolation/smolvm-backend/).
* Network egress enforcement at the VM boundary — tracked by [Network egress policy](/roadmap/network-egress-policy/).

## Related work [#related-work]

* [Agent isolation architecture](/reference/research/security/isolation-architecture/agent-isolation-architecture/) — master architecture doc; Apple Container is Layer 2 (VM boundary).
* [Docker runtime hardening contract](/roadmap/docker-runtime-hardening-contract/) — prerequisite; rootless DinD must validate before Phase 0 starts.
* [jackin-exec](/roadmap/jackin-exec/) — Layer 3 credential injection; works on top of any backend including apple-container.
* [Selectable sandbox backends](/reference/research/security/sandbox-backends/selectable-sandbox-backends/) — umbrella for Docker and Apple Container as the two runtime families.
* [Session contract and explain mode](/roadmap/session-contract-explain-mode/) — Apple Container backend must feed the session contract with kernel boundary, caps, mounts.
