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
10 changes: 10 additions & 0 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,7 @@ 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/wslfs native WSL filesystem ownership/mode preflight
internal/selfupdate canonical release selection and read-only plan (leaf)
```

Expand All @@ -312,6 +313,7 @@ lockfile -> atomicio, policy, registry, toml
pathmap -> registry
registry -> atomicio, toml
policy -> toml
wslfs -> hostenv
atomicio, dockervol, hostenv, mutationlock, selfupdate, toml -> (leaves)
```

Expand All @@ -338,6 +340,14 @@ release workflow inject it with `-ldflags "-X main.version=..."`, so that symbol
path is part of the release contract. Packages that need it take it as a
parameter.

`internal/wslfs` is an unexposed Linux-only preflight over the fixed layout
derived by `internal/hostenv`. It accepts only a real current-user-owned home on
the distribution root filesystem device, creates missing ContainerBin layout
directories without repairing existing objects, and validates strict modes for
managed registry, lock, binary and management-shim endpoints. The non-Linux
build-tagged implementation always rejects the operation. Frontend wiring,
registry-derived tool shims and Docker integration remain later WSL slices.

After the host runtime boundary is enforced, `cb self-update --check` is
dispatched before machine policy and registry loading. Release selection
therefore remains available when either local configuration source is missing
Expand Down
44 changes: 17 additions & 27 deletions docs/roadmap-decisions.md
Original file line number Diff line number Diff line change
Expand Up @@ -293,47 +293,37 @@ exception, expiry and outage policy.
This is priority/order guidance, not permission to merge.

Merged foundations are removed from the remaining queue: RM-26 shipped in PR
#74, enterprise-policy foundation in PR #75, RM-31 selection/check in PR #76,
the WSL host boundary in PR #77, native Windows ARM64 CI in PR #78, and
reproducible ARM64 release packaging in PR #86. Unmerged pull-request coverage
is not completion.

1. **Per-project overlay trust foundation**
- project overlay parsing independent of global registry;
- add-only collision rules;
- external trust store bound to canonical root + overlay digest;
- `cb trust` / `cb untrust` / inspect/doctor;
- initial restricted capability set.

2. **Registry-signature enterprise policy**
- detached Ed25519 signature envelope over exact registry bytes;
- trusted-key rotation/revocation policy;
- verify before parsing/acting on registry content.

3. **Image trust**
#74, enterprise policy and signed registries in PRs #75 and #84, per-project
overlay trust in PR #80, RM-31 selection/staging/verification in PRs #76, #81
and #82, the WSL host boundary and native layout identity in PRs #77 and #83,
native Windows ARM64 CI in PR #78, and reproducible ARM64 release packaging in
PR #86. Unmerged pull-request coverage is not completion.

1. **Image trust**
- cosign verifier configuration and verifier hash validation;
- per-repository trust policy;
- lock schema/evidence migration;
- online/offline verification and stale-evidence behavior.

4. **Remaining RM-31 self-update**
- selection/check/dry-run API is merged in PR #76;
- bounded canonical GitHub release download/staging;
- `gh attestation verify` policy integration;
2. **Remaining RM-31 self-update**
- selection/check, bounded staging and `gh attestation verify` are merged in
PRs #76, #81 and #82;
- Windows helper transaction, managed-shim reconciliation and rollback;
- release/self-test E2E.

5. **Remaining WSL2**
- narrow reusable Linux host interfaces and fail-closed boundary are merged in PR #77;
- native WSL config/shim/state layout;
3. **Remaining WSL2**
- narrow reusable Linux host interfaces, fail-closed boundary and native
layout/state identity are merged in PRs #77 and #83;
- Linux ownership, permission and symlink preflight is implemented but not
yet wired into an enabled frontend;
- Docker Desktop WSL integration;
- project identity and cross-boundary rejection tests;
- real WSL Docker E2E.

6. **RM-30 Authenticode**
4. **RM-30 Authenticode**
- only after certificate/protected signing prerequisites exist.

7. **RM-29 Windows ARM64**
5. **RM-29 Windows ARM64**
- **lowest priority**;
- native hosted ARM64 CI is merged in PR #78;
- architecture-specific release packaging is merged in PR #86;
Expand Down
13 changes: 7 additions & 6 deletions docs/roadmap-implementation-requirements.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ decision.

Status snapshot: **2026-09-25**. The earlier 2026-09-17 snapshot counted every
unchecked roadmap line as unfinished work; that is no longer an accurate model.
RM-26 pipx, the enterprise-policy foundation, the RM-31 selection/check slice,
the WSL host boundary, native Windows ARM64 CI, and reproducible ARM64 release
RM-26 pipx, per-project overlay trust, signed-registry policy, the RM-31
selection/check/staging/verification slices, the WSL host boundary and native
layout identity, native Windows ARM64 CI, and reproducible ARM64 release
packaging have since shipped. The
maintainer has also explicitly accepted product/security dispositions for the
remaining design gates. Use the readiness table below plus
Expand Down Expand Up @@ -72,14 +73,14 @@ The minimum delivery gate for a code change is:
| RM-26 Python global CLI exposure | **Completed in PR #74** | Stateful pipx + `cb expose pipx` shipped; plain pip `/venv/bin` remains intentionally unexposed |
| RM-29 Windows ARM64 | **Native CI and release packaging shipped / update and hardware work remain** | PR #78 added native hosted ARM64 CI and PR #86 added reproducible release packaging; ARM64 self-update selection and real Windows-on-Arm + Docker Desktop E2E remain |
| RM-30 Authenticode | **Design complete / externally blocked** | Provision real code-signing certificate and protected signing mechanism |
| RM-31 self-update | **Selection/check foundation shipped** | PR #76 shipped selection/check behavior; staging, verification, transactional apply and E2E remain |
| RM-31 self-update | **Selection, staging and verification shipped** | PRs #76, #81 and #82 shipped the read-only plan, fail-closed staging and provenance verification; transactional apply and E2E remain |
| RM-34 Cargo expose enhancement | **Intentionally deferred** | Existing expose-all/explicit selection are sufficient; reopen only for concrete unmet use case |
| Linux/macOS hosts | **Demand-gated** | WSL may factor reusable Linux host code; standalone support needs its own demand and qualification |
| Enterprise policy | **Foundation shipped / signed registry remains** | PR #75 shipped the machine-owned constraint layer; authenticated registry and image-trust slices remain |
| Enterprise policy | **Foundation and signed registry shipped / image trust remains** | PRs #75 and #84 shipped the machine-owned constraint layer and authenticated registry; image trust remains |
| Image trust | **Design complete / sequenced** | Implement after signed-registry policy using policy-driven Sigstore/cosign verification |
| Plugin/provider architecture | **Intentionally deferred** | Reopen only after at least two real integrations cannot fit the declarative model |
| WSL2 | **Host boundary shipped / implementation remaining** | PR #77 shipped the fail-closed host boundary; native layout, Docker Desktop integration and real WSL qualification remain |
| Per-project overlays | **Design complete / implementation-ready** | Implement add-only digest-bound trust model on the merged enterprise-policy foundation |
| WSL2 | **Host boundary and layout identity shipped / implementation remaining** | PRs #77 and #83 shipped the fail-closed host boundary and fixed native layout/state identity; filesystem preparation is implemented but unexposed, while frontend wiring, Docker Desktop integration and real WSL qualification remain |
| Per-project overlays | **Completed in PR #80** | Add-only digest-bound trust model shipped on the merged enterprise-policy foundation |
| Release SBOM | **Conditionally deferred** | Trigger on shipped third-party/runtime dependencies or concrete compliance/consumer demand |
| Snyk | **Conditionally deferred** | Trigger only for a real coverage gap plus owner/account/token and triage/outage policy |
| Issue #69 | **Completed** | Superseded by merged implementation; no remaining roadmap dependency |
Expand Down
49 changes: 33 additions & 16 deletions docs/wsl.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ Linux shims inside one WSL2 distribution, using Docker Desktop's supported WSL
integration. A Windows `cb.exe` launched through WSL interoperability is not the
WSL frontend, and standalone Linux remains a separate, demand-gated product.

The implemented foundation establishes the runtime boundary and the fixed
native-WSL layout contract. It does not publish a Linux artifact or enable WSL
execution yet. Until the remaining filesystem, Docker and qualification slices
land, non-bootstrap commands fail closed on every host except native Windows.
The implemented foundation establishes the runtime boundary, fixed native-WSL
layout contract and an unexposed filesystem-preparation step. It does not
publish a Linux artifact or enable WSL execution yet. Until the remaining
frontend wiring, Docker and qualification slices land, non-bootstrap commands
fail closed on every host except native Windows.

## Runtime classification

Expand Down Expand Up @@ -47,18 +48,33 @@ root:
| lockfile | `~/.config/container-bin/container-bin.lock` |
| private state | `~/.local/state/container-bin` |

The home directory must be a canonical absolute Linux path in the distribution
filesystem. A home under `/mnt` is rejected rather than placing trust or state
files on a Windows filesystem. The machine policy location remains the separate
The home directory must be a canonical absolute Linux path on the same
filesystem device as the distribution root. A lexical `/mnt` check rejects the
default Windows-drive layout early; filesystem preparation then rejects a
symlinked home, a
[custom DrvFs automount root](https://learn.microsoft.com/windows/wsl/wsl-config#automount-settings),
a bind-mounted Windows home, and any other separate filesystem rather than
guessing its trust semantics. This is deliberately narrower than accepting
every possible Linux `/home` mount: support for a separate native filesystem
needs its own filesystem-type and ownership qualification. The machine policy
location remains the separate
administrator-owned `/etc/container-bin/policy.toml` contract.

Later filesystem wiring must create config and state directories as private,
current-user-owned directories; create registry and lock files with mode `0600`;
install the managed binary with mode `0755`; and reject an existing shim
directory that is group- or world-writable. It must never repair permissions on
an unrelated shared directory by guessing ownership intent. Tool shims are
native Linux symlinks to the managed binary, and collisions with unrelated
files or links fail closed.
The filesystem checks are a point-in-time preflight, not a durable path handle.
The later wiring slice must revalidate managed paths at each mutation boundary
or use descriptor-relative, no-follow traversal so a path swap after preflight
cannot redirect a registry, lockfile, binary, or shim operation.

The unexposed `internal/wslfs` preparation step creates only missing fixed
layout directories. Config, state and managed-binary directories must be
private and current-user-owned; existing registry and lock files must be
regular non-symlink files with mode `0600`; and an existing managed binary must
be a regular non-symlink file with mode `0755`. The shim directory must be
current-user-owned, owner-accessible and not group- or world-writable. Existing
permissions and ownership are never repaired by guessing intent. The management
shim, when present, must be a current-user-owned symlink to the fixed managed
binary; unrelated files or links fail closed. Tool-shim enumeration remains a
later registry/install wiring concern.

Every ContainerBin-managed Docker object in WSL is scoped to one exact tuple:

Expand All @@ -78,8 +94,9 @@ distribution therefore cannot silently adopt existing state.

Later reviewable slices must still implement and qualify all of the following:

1. Linux ownership, permission and symlink enforcement for the accepted native
layout;
1. wire the implemented Linux ownership, permission and symlink preflight into
the native installer/config lifecycle and extend it to registry-derived tool
shims;
2. wiring the accepted distribution/machine/user namespace into shared and
project volume creation and lifecycle commands;
3. native Linux path, symlink, case, stdin/TTY and signal semantics;
Expand Down
Loading
Loading