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
21 changes: 16 additions & 5 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 | **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) |
| WSL2 | **v2 runtime wired; activation gated.** The native Linux runtime uses the fixed private WSL layout and Docker Desktop's WSL integration directly, including proof-bound retained-container orphan recovery, but production dispatch remains fail-closed until native state commands, integration coverage 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 @@ -949,8 +949,18 @@ 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 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).
managed tool dispatch remains fail-closed until native state commands,
integration coverage and real WSL2 qualification land. See
[docs/wsl.md](docs/wsl.md).

`cb wsl cleanup --check` reports exact namespace-owned retained runtime
containers as active or orphaned without mutation. `--apply` stops, waits and
removes only re-proven orphans; ordinary tool startup performs the same pass
automatically. A process-held private lease protects active runs, and the
namespace coordinator remains held across container creation and lease
publication so cleanup cannot guess across that race. Unlocked lease evidence
whose exact namespace no longer contains a matching retained container is
reported and reaped by `--apply`; locked leases are always preserved.

### Self-update release selection

Expand Down Expand Up @@ -1113,8 +1123,9 @@ benchmark methodology and the disposable-container tradeoff are in
- 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
propagation plus retained-container orphan reconciliation are wired, but
activation still requires native state commands, integration coverage and
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
Expand Down
18 changes: 13 additions & 5 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,7 @@ 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. Tool-time composition is wired but the host boundary keeps it
activation-gated until orphan reconciliation lands; native state commands remain.
activation-gated while native state commands and qualification remain.

`internal/wslrun` is the native WSL vertical orchestrator. It requires the
fixed layout, private registry, managed binary and exact invoked shim; resolves
Expand All @@ -504,10 +504,18 @@ 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.
Before creation it holds a namespace coordinator and reconciles retained runs.
Each created run publishes a private process-held lease before the coordinator
is released. Reconciliation preserves locked active leases and mutates only an
unlocked or lease-less candidate whose complete labels, retention and stream
configuration were freshly re-proven. A running orphan is killed and waited;
all orphan removal uses the same proof-bound non-force lifecycle. Explicit
`cb wsl cleanup --check|--apply` exposes that recovery path. The same
coordinator-held pass enumerates managed lease names and reaps an unlocked
lease only when complete namespace discovery contains no matching run; locked
lease-only records remain untouched. The production host
boundary still does not dispatch into this orchestrator until native state
commands, integration coverage and real WSL qualification complete.

After the host runtime boundary is enforced, `cb self-update` is dispatched
before machine policy and registry loading. Release selection therefore remains
Expand Down
7 changes: 5 additions & 2 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** | 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. |
| WSL2 | **Native WSL frontend** | Fixed-layout install, managed-tool runtime/Docker composition and proof-bound retained-container orphan reconciliation are wired behind the host gate. 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 @@ -345,7 +345,7 @@ is not completion.
- explicit read-only/apply Linux ownership, permission and symlink layout
preparation plus the fixed-path native install/config lifecycle are
implemented; ordinary managed tool dispatch is composed but remains
activation-gated pending orphan reconciliation;
activation-gated pending state-command integration and qualification;
- 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
Expand All @@ -357,6 +357,9 @@ is not completion.
- 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 wired;
- process-held per-run leases, create-to-lease namespace serialization,
proof-bound automatic orphan recovery and explicit read-only/apply cleanup
are implemented for retained runtime containers;
- project identity and cross-boundary rejection integration tests;
- real WSL Docker E2E.

Expand Down
12 changes: 6 additions & 6 deletions docs/roadmap-implementation-requirements.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ The minimum delivery gate for a code change is:
| 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 | **Online/offline production and runtime authorization implemented / private-registry work remains** | Add an explicit private-registry credential bridge |
| Plugin/provider architecture | **Intentionally deferred** | Reopen only after at least two real integrations cannot fit the declarative model |
| WSL2 | **Native tool runtime wired / activation remaining** | The fixed install/config/shim lifecycle, project proof/mapping, namespaced tool-time volumes, direct Docker Desktop Engine lifecycle, stdin/output framing, raw TTY, resize, signal forwarding, retained-container cleanup and exit propagation are composed behind the fail-closed host gate. Retained-container orphan reconciliation, native state-management commands, integration corpus and real WSL2 + Docker Desktop qualification remain before activation. |
| WSL2 | **Native tool runtime wired / activation remaining** | The fixed install/config/shim lifecycle, project proof/mapping, namespaced tool-time volumes, direct Docker Desktop Engine lifecycle, stdin/output framing, raw TTY, resize, signal forwarding, retained-container cleanup, orphan reconciliation and exit propagation are composed behind the fail-closed host gate. Native state-management commands, integration corpus and real WSL2 + Docker Desktop qualification remain before activation. |
| 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 |
Expand Down Expand Up @@ -612,9 +612,10 @@ Docker Desktop WSL integration proof, create/attach/start/wait/resize/signal/
cleanup, strict non-TTY output decoding, raw TTY mode, terminal resize events,
host-signal forwarding and exact exit-code propagation. Containers are retained
until wait records the exit status and are then removed through the proof-bound
cleanup path, avoiding an auto-remove race for fast tools. Because uncatchable
host-shim death can bypass that in-process cleanup, production activation waits
for proof-bound orphan reconciliation. Native state-command integration,
cleanup path, avoiding an auto-remove race for fast tools. Process-held run
leases and a namespace coordinator close the create-before-lease race; automatic
startup and explicit `cb wsl cleanup --check|--apply` re-prove and recover only
exact unlocked or lease-less retained runs. Native state-command integration,
project/cross-boundary integration coverage and real WSL qualification remain.

Implementation must define native config/shim location, Docker endpoint,
Expand Down Expand Up @@ -726,8 +727,7 @@ in PR #91.
2. Signed-registry enterprise policy.
3. Image trust at lock time, after signed-registry policy merges.
4. Remaining RM-31 real published-release/self-test E2E qualification.
5. Native WSL retained-container orphan reconciliation, remaining state
commands, integration corpus and real E2E.
5. Native WSL remaining state commands, integration corpus and real E2E.
6. RM-30 Authenticode only after certificate/protected-signing prerequisites exist.
7. RM-29 real Windows-on-Arm + Docker Desktop qualification last; do not delay
higher-value work for it.
Expand Down
15 changes: 12 additions & 3 deletions docs/security-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ readable, and dangerous to let others edit.
authenticates signed registries when required, and reconciles only the fixed
managed binary and provenance-checked symlinks. The ordinary managed-tool
runtime is composed and tested but remains behind this host gate until
retained-container orphan reconciliation and real qualification land;
native state commands, integration coverage and real qualification land;
unsupported native management commands remain rejected.
- **Native WSL installation does not adopt ambient files.** The bootstrap
executable is the exact OS-reported running image and must be a bounded,
Expand Down Expand Up @@ -174,8 +174,17 @@ readable, and dangerous to let others edit.
container, waits under a fresh bound and then invokes the same non-force
proof-bound removal. Cleanup errors are never hidden by the original failure.
An uncatchable host-shim SIGKILL can bypass every in-process cleanup path, so
production activation remains gated until a separate proof-bound orphan
reconciliation mechanism handles both running and stopped retained objects.
each run owns a private process-held lease and container creation is serialized
with lease publication by a namespace coordinator. Automatic startup and
explicit `cb wsl cleanup --apply` discover only exact namespace labels, then
re-prove the full immutable container contract before mutation. Locked leases
preserve active runs. Missing or unlockable leases identify recoverable
orphans while the coordinator is held; running orphans are killed and waited,
stopped orphans are removed directly, and all deletion remains proof-bound
and non-force. Unlocked lease evidence is reaped only when complete namespace
discovery has no matching retained container; locked leases are preserved.
Unsafe lease files or any ambiguous candidate stop the complete
preflight before its first mutation.
- **Machine policy cannot be redirected or weakened.** A present enterprise
policy is loaded only from the fixed OS path, requires administrator/root
ownership and restrictive permissions, and authorizes the already-resolved
Expand Down
32 changes: 28 additions & 4 deletions docs/wsl-process-contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

This document defines the process semantics implemented by ContainerBin's
native-Linux frontend inside WSL2. The runtime is composed and covered in this
tree, but production dispatch remains activation-gated until retained-container
orphan reconciliation and real WSL2 + Docker Desktop qualification land.
tree, but production dispatch remains activation-gated until the required
native state commands, integration corpus and real WSL2 + Docker Desktop
qualification land.
The corresponding Windows behavior is documented separately in
[the Windows shell/process contract](shell-contract.md).

Expand Down Expand Up @@ -58,6 +59,28 @@ Engine wait, captures the `0..255` status, drains output, and removes the stoppe
container through the proof-bound non-force cleanup path. Every control or
stream connection repeats the Docker Desktop WSL socket and peer proof.

Before creating a runtime container, ContainerBin holds a namespace coordinator
lock, discovers exact namespace-labeled retained runs, and re-inspects every
candidate before mutation. Each live run owns a private `0600` lease file keyed
by its cryptographic run ID and keeps an exclusive lock on that file for the
process lifetime. The coordinator remains locked across container creation and
lease publication, so reconciliation cannot observe a newly created container
without its liveness decision. Locked leases are active and are never touched.
Missing or unlockable leases identify an orphan only while the coordinator is
held. Running orphans are sent SIGKILL, waited, and then removed; stopped
orphans are removed directly. Every removal reuses the exact proof-bound,
non-force container lifecycle.

`cb wsl cleanup --check` reports active and orphaned retained runs without
mutation. Explicit `--apply` performs the same proof-bound reconciliation used
automatically before ordinary execution. Malformed labels, changed container
configuration, unsafe lease files or incomplete proofs stop the whole preflight
before its first mutation. A lease path is removed only after exact container
absence is established; otherwise it remains as recovery evidence. A later
coordinator-held pass enumerates managed lease names, preserves every locked
lease, and reaps an unlocked lease only when complete namespace discovery has
no matching run identity.

## Streams and TTY

ContainerBin always attaches stdin, stdout and stderr. Non-TTY stdin is copied
Expand Down Expand Up @@ -113,8 +136,9 @@ joined to the original diagnostic. The top level maps infrastructure failures
to ContainerBin's documented exit code 120. Catchable host signals remain
intercepted until that cleanup finishes, so their default disposition cannot
terminate the shim inside the bounded cleanup window and strand a retained
container. SIGKILL remains uncatchable and is covered by the activation gate's
orphan-reconciliation requirement.
container. SIGKILL remains uncatchable; the process-held lease is automatically
unlocked by the kernel and the next automatic or explicit reconciliation pass
recovers the retained container.

A failed start response is treated as transport-ambiguous: the Engine may have
accepted the request before the connection failed. Cleanup therefore attempts
Expand Down
Loading
Loading