Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
08fdaf3
docs/container-dev: record Phase 0 de-risk findings and GO
jetm Jul 21, 2026
611b11e
avocado-cli: Scaffold container dev mode module with TLS/WS deps
jetm Jul 21, 2026
dbdaece
container-dev: Add typed config for Container Dev Mode
jetm Jul 21, 2026
79125f3
container: Add Container Dev Mode command skeleton
jetm Jul 22, 2026
465f01f
container-dev: Add per-project content-addressed blob store
jetm Jul 22, 2026
a286627
container_dev: Add OCI Distribution read handlers
jetm Jul 22, 2026
4ca1bdb
container_dev: Add OCI write router with Basic auth gating
jetm Jul 22, 2026
b6b9f51
container_dev: Add Bearer read/control token validator (task 3.4)
jetm Jul 22, 2026
daf8122
container-dev: Add garbage collection and mid-pull prune guard
jetm Jul 22, 2026
e5f88e3
container-dev: Add per-session TLS material and token mint
jetm Jul 22, 2026
8d402a2
container_dev: Add dedicated TLS bulk read listener
jetm Jul 22, 2026
bfd6a90
container_dev: Add engine driver abstraction for tag event watching
jetm Jul 22, 2026
deadd90
container_dev: Add engine-driver watcher and sync orchestration
jetm Jul 22, 2026
c9f083c
container-dev: Add cross-arch guard to refuse wrong-arch image syncs
jetm Jul 22, 2026
2c03c05
container_dev: Add control-only WebSocket channel (task 5.1)
jetm Jul 22, 2026
7cf3923
commands/container: Implement container dev up/down/status lifecycle
jetm Jul 22, 2026
c7fd6c7
container/dev: Implement `sync` and `prune` subcommands
jetm Jul 22, 2026
ed20eee
container_dev/ws: Terminate TLS on the control WebSocket
jetm Jul 22, 2026
d9b107e
tests: Add security assertions for container dev mode auth gates
jetm Jul 22, 2026
d605697
tests: Add cross-arch refusal integration tests for container dev mode
jetm Jul 22, 2026
9f08d4c
container/dev: Add discoverable control-WS endpoint to bootstrap payload
jetm Jul 22, 2026
a14aac0
container-dev: Add authenticated VM write path with TLS and CA delivery
jetm Jul 23, 2026
cc7524c
tests: Add container dev mode end-to-end round-trip tests
jetm Jul 23, 2026
bda772e
docs/container-dev: Add from-scratch VM write-path lab harness
jetm Jul 23, 2026
b12734c
container/dev: correct the write-listener exposure comments
jetm Jul 28, 2026
f2efd5c
container/dev: wire the cross-arch guard into the live sync path
jetm Jul 28, 2026
2f67ddf
container/dev: prove session ownership before signalling its pid
jetm Jul 28, 2026
d7ec6d6
container/dev: mark the per-device status fields as not yet live
jetm Jul 28, 2026
4f59d40
container-dev/registry: bound the write path's memory
jetm Jul 28, 2026
1248668
container/dev: take the session lock before `up` has side effects
jetm Jul 28, 2026
e29b8ac
container-dev/registry: make the upload TTL actually testable
jetm Jul 28, 2026
866a6e5
container/dev: resolve the image id for a manual sync
jetm Jul 28, 2026
8dbf6a5
container-dev/tests: prove the control server and guard share one arc…
jetm Jul 28, 2026
93ce980
container-dev: carry the image architecture into desired state
jetm Jul 28, 2026
2076b68
container-dev: scope arch-book entries to live sessions
jetm Jul 28, 2026
db4ec9e
container-dev/registry: stream blob uploads to the store
jetm Jul 28, 2026
c5b31ca
container-dev: restore the bounds streaming and the early lock removed
jetm Jul 29, 2026
c275935
container-dev/ws: filter the broadcast fan-out on architecture too
jetm Jul 29, 2026
8905ad7
container-dev: fix the session lock's real conflict and four false cl…
jetm Jul 29, 2026
6229d7f
container-dev/registry: stream stored blobs instead of reading them w…
jetm Jul 29, 2026
90db31c
container-dev: create the bootstrap token file already private
jetm Jul 29, 2026
c550180
container/dev: notify the registry manifest digest, not the engine im…
jetm Jul 31, 2026
540845c
container/dev: scope the watcher to the declared images and kill canc…
jetm Jul 31, 2026
1be1da1
container-dev/lab: stop the generated env.sh shipping two broken defa…
jetm Jul 31, 2026
f039e3b
container-dev/lab: script the demo app + its owning unit
jetm Jul 31, 2026
926a978
container-dev/lab: single demo driver that names the machine for ever…
jetm Jul 31, 2026
5ce416b
container-dev/lab: add a native topology, and record what it exposes
jetm Jul 31, 2026
d7f85b1
container-dev/lab: drop the native-mode caveat, the agent fix landed
jetm Jul 31, 2026
b0dba44
container-dev/lab: choose the builder by daemon version, not by assum…
jetm Jul 31, 2026
9abe9a7
container/dev: stream the bootstrap instead of decoding it on the device
jetm Aug 3, 2026
831ba43
container-dev/lab: run the demo against Avocado OS, not a Debian stan…
jetm Aug 3, 2026
ad111ee
container-dev/lab: give the HITL target public root CAs
jetm Aug 3, 2026
2c8e854
docs(container-dev): drop the verify step that checked its own source…
jetm Aug 3, 2026
2badb34
container_dev: close the eleven silent-success paths in the dev loop
jetm Aug 4, 2026
d238fea
container-dev/lab: stop the config template executing its own comments
jetm Aug 4, 2026
143bd24
container-dev/lab: judge delivery by image identity, not by tag presence
jetm Aug 4, 2026
62379f3
container dev: route the engine subcommands and stop the watcher lying
jetm Aug 4, 2026
7a05d37
container dev: send the owning unit and surface what the device reports
jetm Aug 4, 2026
e2afb0e
container dev: test the service keying and Status wiring, not just th…
jetm Aug 4, 2026
c1fbedb
container-dev/lab: stop `up` reporting the previous session's write port
jetm Aug 4, 2026
fdfcf86
container-dev/lab: read seed's version from the image, not from an ar…
jetm Aug 4, 2026
c320945
container-dev/lab: anchor the version check, and read it without runn…
jetm Aug 4, 2026
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
237 changes: 231 additions & 6 deletions Cargo.lock

Large diffs are not rendered by default.

23 changes: 23 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,15 @@ tokio = { version = "1.0", features = [
"rt-multi-thread",
"process",
"io-util",
"fs",
"signal",
"time",
"sync",
] }
# `io` only, for ReaderStream: the registry streams stored blobs off disk instead
# of sizing an allocation by the blob. Already in the tree transitively (axum,
# tokio-tungstenite), so this adds an explicit edge rather than a new dependency.
tokio-util = { version = "0.7", features = ["io"] }
thiserror = "2.0"
directories = "6.0"
reqwest = { version = "0.13", default-features = false, features = [
Expand Down Expand Up @@ -70,7 +75,25 @@ tough = { version = "0.22", default-features = false }
semver = "1"
crossterm = "0.29"
num_cpus = "1.16"
# Container Dev Mode embedded registry server surface. Pure-Rust HTTP/TLS/WS
# stack pinned to the aws-lc-rs rustls provider already linked via reqwest, so
# no new C toolchain requirement is introduced. rcgen and tokio-tungstenite
# both default to aws_lc_rs; do not enable a `ring` feature here or a second
# crypto provider would be linked.
axum = "0.8"
rustls = "0.23"
tokio-rustls = "0.26"
rcgen = { version = "0.13", default-features = false, features = [
"crypto",
"pem",
"aws_lc_rs",
] }
tokio-tungstenite = { version = "0.26", features = ["rustls-tls-native-roots"] }

[dev-dependencies]
# `oneshot` drives the write router directly, so a body stream that ERRORS can be
# injected deterministically - a truncated real HTTP body just makes the server
# wait for bytes that never arrive.
tower = { version = "0.5", features = ["util"] }
tokio-test = "0.4"
serial_test = "3.0"
67 changes: 67 additions & 0 deletions docs/container-dev/lab/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Container Dev Mode - local VM write-path lab

A from-scratch harness to exercise Container Dev Mode's authenticated VM write
path (task 7.1) on Linux, without hardware. It stands up a disposable Debian 12
"engine VM" under QEMU user-mode networking so the guest reaches the host at
`10.0.2.2` exactly like the macOS `avocado-vm`, then runs the end-to-end verify.

This is the setup the 2026-07-23 field note ("Container Dev Mode VM push") was
written from; it validated the path 8/8 and caught two real bugs (a plain-HTTP
write listener where the guest required HTTPS, and a 2 MiB body limit that
413'd real layers).

## What's here

- `setup-lab.sh` - idempotent provisioner: ssh keypair, cloud-init seed
(`docker.io` + root login), a copy-on-write overlay off the Debian base, a
QEMU SLIRP boot with an ssh hostfwd, a forward of the guest dockerd to the
socket `is_vm_routing_active()` resolves, and an `env.sh` for the verify step.
- `avocado.yaml` - the minimal `container_dev` runtime config the lab uses.
- `../verify-vm-write-path.sh` - the actual end-to-end assertion (built image ->
authenticated push over `10.0.2.2` HTTPS -> single-layer sync). Sourced env
comes from the generated `env.sh`.

Generated state (the qcow2 overlay, ssh key, cloud-init seed, `env.sh`) is
written to a work dir OUTSIDE this repo (`$AVOCADO_CDM_LAB_WORK`, default
`~/.cache/avocado-cdm-lab`) so a ~900 MB overlay never lands in git.

## Prerequisites

Host packages: `qemu-system-x86_64`, `qemu-img`, `cloud-image-utils`
(`cloud-localds`), `ssh`/`ssh-keygen`, and the `docker` client.

## Run it (from scratch)

```bash
# 1. one-time: download a Debian 12 generic-cloud base image
WORK="${AVOCADO_CDM_LAB_WORK:-$HOME/.cache/avocado-cdm-lab}"
mkdir -p "$WORK"
curl -L -o "$WORK/debian12.qcow2" \
https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-genericcloud-amd64.qcow2

# 2. build the avocado CLI (the lab points AVOCADO_BIN at target/debug/avocado)
cargo build --bin avocado

# 3. stand up the engine VM (interactive: it runs ssh-keygen + touches ~/.ssh)
bash docs/container-dev/lab/setup-lab.sh

# 4. run the end-to-end verify
source "$WORK/env.sh"
docs/container-dev/verify-vm-write-path.sh
```

Optional: set `BBAPPEND` to the meta-avocado
`meta-avocado-qemu/recipes-core/base-files/base-files_%.bbappend` path so the
verify script also checks the guest trust-store-dir overlay; leave it empty to
skip that check.

## Tear down

```bash
WORK="${AVOCADO_CDM_LAB_WORK:-$HOME/.cache/avocado-cdm-lab}"
kill "$(cat "$WORK/qemu.pid")" 2>/dev/null || true
pkill -f "$HOME/.avocado/vm/docker.sock:" 2>/dev/null || true
```

Deleting `$WORK/engine.qcow2` gives a clean VM on the next run; the base image
and ssh key are reused.
24 changes: 24 additions & 0 deletions docs/container-dev/lab/avocado.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# HOST-side session config for the Container Dev Mode lab.
#
# There are deliberately two avocado.yaml files in this lab and they do different
# jobs. This one is read by the host CLI (`container dev up` runs from this
# directory) and only has to carry the `container_dev` block. The one setup-lab.sh
# renders into $AVOCADO_CDM_LAB_WORK/hitl is the RUNTIME BUILD config - it composes
# the Avocado OS image with avocado-ext-docker and avocado-ext-container-agent-dev.
# That one is generated rather than tracked because the agent extension is not in
# the published feed and has to be sourced by absolute path.
#
# A runtime carrying a `container_dev` block is all that enables the feature
# (see src/utils/container_dev/config.rs). The watched image ref must match the
# image the verify script builds on the VM engine (TEST_IMAGE, default
# my-app:dev). `registry.port` is the bulk *read* listener; the authenticated
# *write* listener uses AVOCADO_CONTAINER_DEV_WRITE_PORT (default 5601).
runtimes:
dev:
target: qemux86-64
container_dev:
images:
- ref: my-app:dev
service: app
registry:
port: 5599
Loading
Loading