Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 14 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ real Linux CLI/runtime in an ephemeral container
|---|---|
| Windows 10/11 x64 + Docker Desktop (Linux containers) + PowerShell | **Supported** — this is the validated configuration |
| cmd.exe invocation of shims | Works for the common cases; less battle-tested than PowerShell |
| WSL2 | **Not yet supported.** The selected native-Linux frontend has an explicit fail-closed runtime boundary plus fixed-layout and install/config lifecycle commands; runtime/Docker wiring and real Docker Desktop WSL qualification remain. See [docs/wsl.md](docs/wsl.md) |
| WSL2 | **v2 runtime wired; activation gated.** The native Linux runtime uses the fixed private WSL layout and Docker Desktop's WSL integration directly, but production dispatch remains fail-closed until retained-container orphan reconciliation and real WSL2 qualification land. See [docs/wsl.md](docs/wsl.md) |
| Windows 11 ARM64 | **CI/release-artifact/update-path qualified only, not supported yet.** Native tests/build/dispatch run on GitHub-hosted ARM64 hardware, the release workflow produces a reproducible ARM64 archive, and self-update selects and verifies that archive by `GOARCH`; real Docker Desktop ARM64 E2E qualification remains |
| Linux / macOS hosts | **Not supported.** The program is Go and cross-compiles, but shim installation, path mapping and doctor checks are Windows-specific |
| Windows containers | Not supported; images are Linux images |
Expand Down Expand Up @@ -924,13 +924,12 @@ a false failure; run `cb setup` to append the current default profiles.

### Native WSL layout and installation

`cb wsl prepare --check` is a read-only exception to the still-gated native
WSL frontend. It derives the fixed distribution-local layout from the current
`cb wsl prepare --check` derives the fixed distribution-local layout from the current
Linux account, UID, distribution name and machine identity, validates
ownership, permissions, symlink boundaries and filesystem locality, and lists
missing directories. `--apply` explicitly creates only those directories and
revalidates the result. It does not install `cb`, create shims or config, access
Docker, or enable ordinary commands. See [docs/wsl.md](docs/wsl.md).
revalidates the result. It does not install `cb`, create shims or config, or
access Docker. See [docs/wsl.md](docs/wsl.md).

`cb wsl install --check` adds a read-only plan over the same fixed layout. It
loads only the root-owned `/etc/container-bin/policy.toml` policy path and the
Expand All @@ -949,8 +948,9 @@ replacing foreign objects. A signed-registry policy disables automatic registry
creation/upgrades and requires an already provisioned authenticated registry.
The bootstrap executable must itself be a bounded, current-user-owned regular
non-symlink file with safe executable permissions. This command still does not
contact Docker or enable ordinary WSL tool execution; the runtime and real E2E
gates remain. See [docs/wsl.md](docs/wsl.md).
contact Docker itself. Install reports the wired-but-gated runtime state;
managed tool dispatch remains fail-closed until orphan reconciliation and real
WSL2 qualification land. See [docs/wsl.md](docs/wsl.md).

### Self-update release selection

Expand Down Expand Up @@ -1110,11 +1110,13 @@ benchmark methodology and the disposable-container tradeoff are in

## Current limitations

- Windows x64 + Docker Desktop (Linux containers) only. WSL2 runtime detection,
fixed-layout preparation and the native install/config/shim lifecycle are
present, but native WSL execution remains gated until runtime, state, Docker
Desktop and real WSL qualification slices land. Windows ARM64 has
native non-Docker CI coverage, but no published artifact or support claim.
- Windows x64 + Docker Desktop (Linux containers) is the currently qualified
release target. The native WSL2 runtime, fixed-layout installation, project
mapping, managed volumes, Engine lifecycle, stdio/TTY, resize, signal and exit
propagation are wired, but activation still requires retained-container
orphan reconciliation plus real WSL2 + Docker Desktop qualification. Windows
ARM64 has native non-Docker CI
coverage and published release artifacts, but no Docker support claim.
- First invocation of a tool after `cb lock` may still need images present
locally (`cb lock` pulls them; `cb self-test` never pulls).
- Container startup adds latency compared to native binaries (typically
Expand Down
47 changes: 31 additions & 16 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ internal/registry Tool/Registry, TOML parser, defaults, registry file
internal/toml the shared TOML subset lexer (leaf)
internal/atomicio crash-safe write + .bak recovery (leaf)
internal/mutationlock the registry mutation lock primitive (leaf)
internal/hostenv host classification and gated WSL layout (leaf)
internal/hostenv host classification and fixed WSL layout (leaf)
internal/terminal shared stdin/stdout character-device decision (leaf)
internal/wslfs native WSL filesystem ownership/mode preflight
internal/wslshim native WSL registry-derived shim preflight/mutation
Expand All @@ -351,14 +351,15 @@ internal/wslpathmap native WSL project argument mapping
internal/wsldocker native WSL Docker Desktop integration proof
internal/wslvolume native WSL namespaced volume identity/lifecycle and
stateful-tool binding planning
internal/wslrun native WSL fixed-layout tool runtime orchestration
internal/selfupdate release selection, staging, verification and replacement
```

The exact import edges, from `go list -f '{{.ImportPath}} {{.Imports}}' ./...`,
project-internal imports only:

```
main -> cli, diag, dockerrun, hostenv, mutationlock, policy, projectconfig, registry, selfupdate, state, wslfs, wslinstall
main -> cli, diag, dockerrun, hostenv, mutationlock, policy, projectconfig, registry, selfupdate, state, wslfs, wslinstall, wslrun
cli -> atomicio, diag, dockerrun, dockervol, lockfile, pathmap, policy, registry, statearchive, toml
projectconfig -> atomicio, pathmap, policy, registry, toml
diag -> dockerrun, dockervol, lockfile, pathmap, policy, registry
Expand All @@ -376,6 +377,7 @@ wslproject -> hostenv, registry
wslpathmap -> registry, wslproject
wsldocker -> hostenv
wslvolume -> hostenv, registry, wsldocker, wslproject
wslrun -> hostenv, lockfile, policy, registry, wsldocker, wslfs, wslpathmap, wslproject, wslshim, wslvolume
selfupdate -> mutationlock, registry
atomicio, dockervol, hostenv, mutationlock, terminal, toml -> (leaves)
```
Expand Down Expand Up @@ -425,18 +427,18 @@ composed after `internal/wslfs` validates the same layout's home, intermediate
path and filesystem-device boundary. It never replaces or removes foreign
objects and never discovers unrelated directory entries.

`internal/wslinstall` composes those two boundaries into the explicitly gated
`internal/wslinstall` composes those two boundaries into the explicit
`cb wsl install --check|--apply` lifecycle. Check mode validates the layout
before read-only fixed-path policy/registry access and reports the exact
registry, binary and shim work without recovering backups. Apply mode prepares
the layout, revalidates it under `main`'s signal-aware mutation lock, recovers
or upgrades an unsigned registry at mode `0600` (or requires an authenticated
pre-provisioned signed registry), atomically publishes the validated running
binary at the fixed path, then reconciles the management and registry-derived
tool symlinks through `internal/wslshim`. It performs no Docker I/O and leaves
ordinary WSL dispatch gated.
tool symlinks through `internal/wslshim`. It performs no Docker I/O; ordinary
managed tool dispatch revalidates the resulting identity in `internal/wslrun`.

`internal/wslproject` is an unexposed profile-aware selector and classifier for
`internal/wslproject` is a profile-aware selector and classifier for
native WSL project roots. It applies the registry's nearest/outermost marker
policy or an exact trusted overlay root, then proves both the selected root and
the starting working directory. Marker names must be single Linux path elements,
Expand All @@ -449,16 +451,16 @@ DrvFs or WSL virtiofs mount. Custom DrvFs roots, entire-drive roots, ambiguous
`/mnt` paths and Windows spellings fail closed. The package preserves the exact
Linux spelling and does not translate between Windows and WSL path identities.

`internal/wsldocker` is an unexposed native-WSL detector for Docker Desktop's
`internal/wsldocker` is the native-WSL detector for Docker Desktop's
supported distribution integration. It rejects Docker endpoint/TLS/API
environment overrides and uses a direct Engine API request on the root-owned,
non-world-writable `/var/run/docker.sock`, without loading an ambient Docker CLI
or context. The connected peer must be root and the socket device/inode must be
stable across the request. The engine must report the exact Linux Docker
Desktop name/OS, a Microsoft WSL2 kernel and Docker Desktop's address label.
The probe has fixed time and output bounds. A reachable local or remote Docker
Engine is deliberately insufficient; later frontend wiring must repeat this
proof and retain the explicit Unix endpoint for every Docker operation. Its
Engine is deliberately insufficient; each runtime operation repeats this proof
and retains the explicit Unix endpoint. Its
separate attach transport admits only a live-stream POST for an exact full
container ID, repeats the complete socket/peer proof, bounds the upgrade and
error response, and returns a context-bound duplex stream with explicit TTY
Expand All @@ -467,14 +469,11 @@ the upgraded connection and unblocks I/O. Sibling proof-bound primitives decode
strict non-TTY multiplexed output and perform exact container inspection, wait,
TTY resize, signal, start, creation and stopped-container cleanup operations.
Creation admits only one canonical project bind, exact namespace-prefixed
volumes and a
fixed unprivileged auto-remove configuration; it generates a unique run label,
volumes and an explicit auto-remove/retention configuration; it generates a unique run label,
rejects Engine warnings and re-inspects the stopped container before returning
its immutable identity. Cleanup accepts only that identity, re-proves all
ownership labels, refuses a running or non-auto-remove object, deletes without
force and verifies absence. These primitives are not yet wired into an enabled
container lifecycle; terminal event collection, host-signal
interception/forwarding and end-to-end exit propagation remain.
ownership labels, refuses a running object or changed retention mode, deletes
without force and verifies absence.

`internal/wslvolume` defines the WSL Docker-volume identity and bounded control
lifecycle. A volume name starts with `cb-<wsl-namespace>-`;
Expand All @@ -492,7 +491,23 @@ identity constructed by this package and its complete labels plus local
driver/scope. The package also preflights an entire stateful profile's
project/shared binding set, re-proves the exact project root before deriving
project identities, and ensures each distinct identity only after the complete
plan validates. Container/frontend and state-command wiring remain gated.
plan validates. Tool-time composition is wired but the host boundary keeps it
activation-gated until orphan reconciliation lands; native state commands remain.

`internal/wslrun` is the native WSL vertical orchestrator. It requires the
fixed layout, private registry, managed binary and exact invoked shim; resolves
images only through the fixed WSL lockfile and machine policy; selects and maps
one proven project; validates the complete command/environment/mount plan before
volume mutation; then composes create, attach, start, wait, resize, signal and
cleanup. It retains the owned container until the wait response records the
exit status, so daemon auto-remove cannot race fast tools. Non-TTY streams use
strict Docker framing; TTY sessions use raw terminal mode, resize events and an
explicit Linux signal-forwarding set. Any runtime failure cancels live I/O,
proof-bound kills the container, waits for stop and performs non-force cleanup.
The production host boundary does not yet dispatch into this orchestrator:
SIGKILL of the host shim can bypass every in-process defer and strand a retained
container, so activation waits for proof-bound orphan reconciliation rather
than making an unsafe partial support claim.

After the host runtime boundary is enforced, `cb self-update` is dispatched
before machine policy and registry loading. Release selection therefore remains
Expand Down
16 changes: 7 additions & 9 deletions docs/roadmap-decisions.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ items from being repeatedly rediscovered as if they were immediately actionable.
| RM-24 Python / uv | **Keep both** | Decision complete. Built-in `python`/`pip` keep the dedicated Python provider; `uv`/`uvx` remain separate opt-in stateful profiles. |
| RM-26 Python global CLI exposure | **pipx yes; plain pip expose no** | Completed in PR #74. The separate stateful pipx profile and managed store shipped; project/compat `/venv/bin` remains intentionally unexposed. |
| RM-34 Cargo expose enhancement | **Intentionally deferred** | Existing expose-all and explicit binary selection are sufficient. Reopen only for a concrete unmet use case. |
| WSL2 | **Native WSL frontend** | Host boundary shipped in PR #77. Fixed-layout preparation and the native install/config/shim lifecycle are explicitly available, while runtime/Docker wiring and real WSL qualification remain. No Windows↔WSL path/state guessing. |
| WSL2 | **Native WSL frontend** | Fixed-layout install plus managed-tool runtime/Docker composition are wired behind the host gate. Retained-container orphan reconciliation, native state commands, integration corpus and real WSL qualification remain before activation. No Windows↔WSL path/state guessing. |
| Enterprise policy | **Machine-owned constraint layer** | Foundation shipped in PR #75. Authenticated registry and image-trust follow-ups must extend this boundary and cannot be weakened by lower layers. |
| Image trust | **Policy-driven Sigstore/cosign at lock time** | Ready after signed-registry policy. Digest locking remains default where policy permits. Required trust never silently falls back to digest-only. |
| Per-project overlays | **Explicit digest-bound, add-only trust model** | Implementation-ready on the merged policy foundation. Initial overlays exclude host mounts, env prefixes and shared cross-project volumes. |
Expand Down Expand Up @@ -344,21 +344,19 @@ is not completion.
layout/state identity are merged in PRs #77 and #83;
- explicit read-only/apply Linux ownership, permission and symlink layout
preparation plus the fixed-path native install/config lifecycle are
implemented; ordinary runtime integration remains gated;
implemented; ordinary managed tool dispatch is composed but remains
activation-gated pending orphan reconciliation;
- Docker Desktop WSL integration proof, proof-bound bounded control requests,
the separately constrained attach transport, strict raw-stream decoder,
exact container inspection, wait, TTY-resize, signal, start, creation and
stopped-container cleanup operations are implemented but not yet wired
into an enabled frontend; terminal event collection, host-signal
interception and forwarding policy, and end-to-end exit-code propagation
remain;
stopped-container cleanup operations are wired with terminal events,
host-signal forwarding, retained-container cleanup and exit propagation;
- namespace-prefixed/labeled WSL volume identity plus proof-bound exact
inspect/create/remove and namespace discovery are implemented; tool-time
creation and state/GC/backup/restore command integration remain;
creation is wired while state/GC/backup/restore command integration remains;
- profile-aware nearest/outermost/trusted project-root selection, canonical
project and descendant storage classification (including symlink and
nested-mount rejection), and proof-consuming argument mapping are
implemented but not yet wired into an enabled frontend;
nested-mount rejection), and proof-consuming argument mapping are wired;
- project identity and cross-boundary rejection integration tests;
- real WSL Docker E2E.

Expand Down
Loading
Loading