Isolation & security

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

The backend code has landed and compiles: the container CLI client (crates/jackin-runtime/src/apple_container_client.rs), the launch/attach/reconnect/stop/remove/session-contract orchestration (crates/jackin-runtime/src/runtime/apple_container.rs), the JACKIN_CAPSULE_FORCE_DAEMON capsule patch (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 (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 (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: crates/jackin-runtime/src/runtime/backend.rs defines ContainerBackend with required finalize, Docker and Apple Container implementations, and manifest-based backend resolution. crates/jackin-runtime/src/runtime/cleanup.rs routes purge guards, eject, and exile_all through it; 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 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.

Remaining work

  1. Phase 0 empirical validation — requires macOS 26 ARM hardware with apple/container v0.11.0+. Run 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 finalizationContainerBackend::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 confirming --cap-add CAP_SYS_ADMIN works inside an apple/container VM.

Out of scope

On this page