Add integration tests based on testcontainers
This commit is contained in:
@@ -94,13 +94,13 @@ remaining limitations, next concrete action.>
|
||||
<Coordinator acceptance decision and timestamp, or exact blocker.>
|
||||
```
|
||||
|
||||
Use ISO 8601 timestamps with offsets for progress. Keep evidence concise and reproducible, with redacted excerpts or artifact paths rather than large logs. Distinguish planned commands from executed commands and unavailable checks from passing checks. Keep the plan self-contained by summarizing discoveries that affect the next task, not just linking to an agent conversation.
|
||||
Use ISO 8601 timestamps with offsets for progress. Keep evidence concise and reproducible, following [execution records](docs/EXECUTION_RECORDS.md); diagnostic attempts belong outside this plan. Use redacted excerpts or artifact paths rather than large logs. Distinguish planned commands from executed commands and unavailable checks from passing checks. Keep the plan self-contained by summarizing discoveries that affect the next task, not just linking to an agent conversation.
|
||||
|
||||
## Validation gates
|
||||
|
||||
For Rust milestones, use the relevant focused tests and the formatting, Clippy, default tests, and release-build commands in AGENTS.md. Add exact commands when targets exist; do not invent passing outputs. Unit and fixture checks run without root. Use standard-library test adapters rather than an additional mock framework.
|
||||
|
||||
Container suites are opt-in and use pinned/cached Alpine images, fresh server/client containers, synthetic keys, isolated dual-stack networking, and scoped `NET_ADMIN`. The real runtime adapter executes inside the server container. Missing Docker/kernel/IPv6 prerequisites are incomplete validation, not success. Alpine fixture application is not a production systemd test.
|
||||
Container suites are opt-in and use pinned/cached Alpine images, fresh server/client containers, synthetic keys, isolated networking, and scoped `NET_ADMIN`. The real runtime adapter executes inside the server container. Missing prerequisites required by a suite are incomplete validation, not success. Milestone 8 validates IPv4 networking only by user direction; IPv6 capability and traffic remain unverified while the production dual-stack requirement remains in force. Alpine fixture application is not a production systemd test.
|
||||
|
||||
Actual systemd/D-Bus acceptance runs in a disposable VM. Never use production to fill gaps in test coverage. Final release acceptance requires relevant unit, Alpine WireGuard, and VM systemd results reported separately. Document blockers without silently weakening the gate.
|
||||
|
||||
@@ -117,7 +117,7 @@ Each row is a delivery milestone, not a completion claim. Expand its record befo
|
||||
| 5 | Runtime observation and systemd restart adapter | 4 | accepted |
|
||||
| 6 | Client configuration delivery and reissue lifecycle | 5 | accepted |
|
||||
| 7 | Complete terminal management workflow | 6 | accepted |
|
||||
| 8 | Alpine Testcontainers integration | 7; suitable disposable Docker environment | pending |
|
||||
| 8 | Alpine Testcontainers integration | 7; suitable disposable Docker environment | accepted |
|
||||
| 9 | Real systemd acceptance and release readiness | 8; disposable systemd VM | pending |
|
||||
|
||||
### Milestone 1 — Rust foundation, settings, and domain states
|
||||
@@ -2623,9 +2623,361 @@ all planned coordinator gates. M8/M9 retain real WireGuard/systemd release gates
|
||||
|
||||
### Milestone 8 — Alpine Testcontainers integration
|
||||
|
||||
Implement opt-in Rust container tests and a minimal pinned Alpine image with `wireguard-tools` and `iproute2`. Cache images, use fresh isolated resources, build an Alpine-compatible test executable (prefer musl), and exercise the real runtime adapter within the server container. Avoid new helpers outside approved dependencies without agreement.
|
||||
Status: accepted (2026-10-25T20:43:00+03:00; M8.1–M8.7 complete, independent
|
||||
review closed, scoped IPv4 Alpine gates passed).
|
||||
Prerequisites: milestones 1–7 accepted; pinned Rust toolchain; an explicitly
|
||||
selected disposable Docker-compatible Linux environment with kernel WireGuard,
|
||||
scoped NET_ADMIN and IPv4 support; an Alpine-compatible test executable.
|
||||
Missing prerequisites are blockers/incomplete evidence, never passing tests.
|
||||
|
||||
Acceptance: prerequisite checks and cleanup work; real dual-stack tunnels produce handshake/counter changes; creation/Commit leaves runtime unchanged until explicit test-only application; deletion retains access/address reservation until application; restored saved state does not implicitly apply. No host network, host D-Bus, production mounts, privileged default, or automatic module loading. Systemd coverage is explicitly excluded.
|
||||
#### Outcome and scope
|
||||
|
||||
Add an opt-in Rust Testcontainers suite using small Alpine server/client images.
|
||||
Exercise the actual application, encrypted vault/persistence/delivery APIs, and
|
||||
M5's real rustix Generic Netlink reader inside the server container against real
|
||||
kernel WireGuard interfaces. Establish real tunnels, generate IPv4 traffic,
|
||||
and prove that saved changes remain separate from runtime application.
|
||||
The user explicitly excluded IPv6 capability and traffic tests on 2026-10-22.
|
||||
Production dual-stack behavior in SPEC.md is unchanged; real IPv6 behavior is
|
||||
therefore unverified by this milestone.
|
||||
|
||||
Read SPEC.md Operations and states, Connection delivery, Backups and restoration,
|
||||
Client screen and statistics, and acceptance criteria; ADRs 0001–0003; TESTING.md,
|
||||
ENVIRONMENT.md, RUNTIME.md, DELIVERY.md, VAULT_FORMAT.md, PERSISTENCE.md,
|
||||
BACKUP_FORMAT.md, DEPENDENCIES.md and current application/worker code.
|
||||
|
||||
This is real-WireGuard integration, not real-systemd acceptance. Alpine fixtures
|
||||
have no systemd; a test-only apply operation may configure the interface explicitly.
|
||||
Actual zbus service job behavior, production restart and VM acceptance remain M9.
|
||||
M7's synthetic TUI/PTY evidence remains separate; M8 does not require live terminal
|
||||
screens, phone QR decoding, public Internet access, external DNS, production
|
||||
configuration, new product commands, or a production apply mode.
|
||||
|
||||
#### Existing code and integration constraints
|
||||
|
||||
- M1–M7 are accepted. The normal executable now starts the management TUI; do not
|
||||
invoke it with host/production settings as a shortcut for a test driver.
|
||||
- Application has open-from-store, setup/import, creation, Commit, delivery/reissue,
|
||||
deletion, backup/list/restore and confirmed restart flows. Use these real APIs,
|
||||
not a parallel shell-only client manager that would leave application behavior
|
||||
untested. Public-key identity and source preservation remain authoritative.
|
||||
- Real observation is `runtime::transport::observe_interface`, currently crate-
|
||||
private, with the validated decoder and bounded rustix transport. Do not use
|
||||
only `wg show` output or a fake observation as evidence that this reader works.
|
||||
- `Application::restart` always invokes the actual zbus path, while injected
|
||||
restart functions are private. Plan an in-crate test seam so a test-only fixture
|
||||
service operation can apply peers and the real observation/persistence path can
|
||||
verify them. Preserve backup ordering and per-attempt authority from M5.
|
||||
- Prefer cfg(test) in-container test scenarios/driver code, compiled for musl and
|
||||
selected explicitly, to reach private adapters without exposing an unauthenticated
|
||||
public apply API. If another arrangement is needed, document its compile-time
|
||||
isolation before implementation. No environment variable may switch production
|
||||
restart to a fake service or bypass password/backup/root checks.
|
||||
- The TUI ApplicationWorker already has synthetic workflow tests. An optional
|
||||
in-container worker scenario may test its real statistics reader, but network
|
||||
acceptance must not depend on automating every terminal key sequence again.
|
||||
- No Testcontainers crate, container image recipe or integration driver is present.
|
||||
Add approved `testcontainers` as a dev-dependency with compatible pinned version
|
||||
and minimal features. Prefer its supported synchronous facade if it avoids a
|
||||
direct executor dependency. Other direct helpers, Docker client crates or
|
||||
Tokio still require prior agreement; transitive dependencies are not new direct
|
||||
approvals. Use Cargo.lock and inspect official APIs for the selected version.
|
||||
- Native tools use system Rust 1.97.1; musl readiness was previously unverified.
|
||||
Recheck rather than assuming rust-toolchain.toml installed targets or a linker.
|
||||
|
||||
#### Context and implementation steps
|
||||
|
||||
Use GPT-6-Sol/medium coordination and GPT-6-Luna/high implementation, fresh review
|
||||
and repairs. Execute bounded tasks sequentially with one writer and explicit file
|
||||
ownership. The coordinator alone updates milestone acceptance and evidence.
|
||||
|
||||
| Task | Owner | Files and deliverable |
|
||||
| --- | --- | --- |
|
||||
| M8.1 | implementer | `docs/TESTING.md`/ENVIRONMENT additions and test support: exact opt-in architecture, prerequisites, image/build and driver contracts |
|
||||
| M8.2 | implementer | `tests/containers/alpine/Dockerfile`, fixture-only setup scripts, musl build recipe: small reproducible cached image and executable compatibility checks |
|
||||
| M8.3 | implementer | `tests/testcontainers_wireguard.rs`, `tests/support/` modules and Cargo files: host orchestration, private network/container ownership, prerequisite checks, bounded execution and cleanup |
|
||||
| M8.4 | implementer | in-crate cfg(test) scenarios/private adapters, test driver coordination: real netlink reads, fixture apply and application state verification inside server |
|
||||
| M8.5 | implementer | container scenarios and TESTING/README documentation: required lifecycle, restore, delivery/import/failure assertions and executed evidence |
|
||||
| M8.6 | reviewer, repairer | Independent isolation, real-adapter coverage and negative-test review; bounded fixes and real-suite re-review |
|
||||
| M8.7 | coordinator | Default and explicit container gates, redacted results, prerequisites/limitations, acceptance and M9 handoff |
|
||||
|
||||
M8.1 defines two execution locations: host harness uses Testcontainers to manage
|
||||
containers; server-side code uses the real application and kernel reader in that
|
||||
container's namespaces. Document how driver sessions persist across staged create,
|
||||
Commit, first delivery and apply phases, and how the client is configured from the
|
||||
actual delivered file. Do not lose the creation session between Commit and first
|
||||
issue or reconstruct password-free authority on reopen.
|
||||
|
||||
Choose a named ignored integration target/scenarios or another explicit opt-in
|
||||
mechanism that default cargo test never starts. The host suite must also opt into
|
||||
all in-container scenario processes. Ensure --ignored does not select unrelated
|
||||
privileged tests. Fail an explicitly requested suite nonzero on missing required
|
||||
prerequisites; never return early with a successful test result labelled skipped.
|
||||
|
||||
M8.2 pins an Alpine base release/digest and records the resolved image identity
|
||||
and package versions. Install only wireguard-tools, iproute2 and minimal fixture
|
||||
requirements. Use BusyBox capabilities when sufficient; justify any extra package
|
||||
in the test recipe. Runtime images contain no Cargo registry/compiler or systemd.
|
||||
Build/cache image layers and compatible driver artifacts before repeated tests;
|
||||
use fresh mutable containers/volumes for each scenario, not reusable dirty servers.
|
||||
Keep build context small with explicit copies/ignore rules, no .git, host Backup,
|
||||
credentials or private configuration. Never bake generated keys into image layers.
|
||||
|
||||
Build server/client driver code for x86_64-unknown-linux-musl or in a pinned
|
||||
Alpine builder matching the toolchain. Inspect dynamic requirements and actually
|
||||
execute a harmless readiness command inside Alpine. Do not rely on a glibc host
|
||||
binary, target name or successful host compilation as runtime compatibility proof.
|
||||
Only build required test targets; avoid pulling compiler/debug layers into the
|
||||
small runtime fixture. No global package installation or toolchain update is
|
||||
implicitly authorized by a missing cross-build prerequisite.
|
||||
|
||||
M8.3 checks Docker API access and explicit disposable-environment selection.
|
||||
Do not use a configured remote daemon without establishing that it is the selected
|
||||
non-production test environment. Probe WireGuard interface creation inside
|
||||
a disposable probe container, never by creating host interfaces or loading modules.
|
||||
Container tools alone do not supply the host kernel module. Refuse to repair
|
||||
prerequisites via SYS_MODULE, privileged mode or host sysctl changes automatically.
|
||||
|
||||
Create a dedicated uniquely named IPv4 network with a test subnet that does
|
||||
not overlap the tunnel ranges. Run server/client as container root with scoped
|
||||
NET_ADMIN in their own network/PID namespaces; no host networking, namespace joins
|
||||
to host, host D-Bus, host /etc/wireguard, Docker socket mount, or production binds.
|
||||
No host UDP publication is needed for container-to-container endpoints. Use
|
||||
container-internal reachable endpoint/port values, not localhost mapped ports.
|
||||
All settings/server/vault/output paths are private fixture directories created
|
||||
with the application's required permissions.
|
||||
|
||||
Use Testcontainers copy/exec APIs or an explicitly safe bounded transport for
|
||||
fixture data. Secret-bearing configs/passwords never enter command arguments,
|
||||
image metadata, public environment variables or raw stdout/stderr logs. Any
|
||||
necessary copied plaintext exists only in private temporary/container storage.
|
||||
Generate keys per scenario. Reports carry public keys, phase/status and redacted
|
||||
categories, not full configurations, QR matrices or `wg show all dump` output.
|
||||
|
||||
Bound image/start/driver/readiness/traffic/teardown operations. Poll explicit
|
||||
conditions with monotonic deadlines, not fixed sleeps. Use unique ownership and
|
||||
RAII/explicit cleanup for containers, networks and volumes on failures as well as
|
||||
success; cleanup must not mask the original failure or delete unrelated resources.
|
||||
Do not default to retain-failed-containers with secrets. Report leftover owned
|
||||
resources if daemon failure prevents cleanup.
|
||||
|
||||
M8.4 keeps fixture `ip`/`wg` calls solely in setup or test-only apply code. It may
|
||||
use wg-quick strip or equivalent explicit fixture setup, but must not execute
|
||||
arbitrary imported hooks. Handle optional DNS/MTU fields in delivered configs via
|
||||
a documented fixture setup, without mutating the delivered payload just to pass.
|
||||
Avoid an unneeded resolvconf dependency by configuring networking explicitly when
|
||||
appropriate. No subprocess apply path is added to production.
|
||||
|
||||
Configure endpoint reachability outside the tunnel before full-tunnel policy so
|
||||
an encrypted UDP endpoint is not recursively routed into its own VPN. Set full
|
||||
IPv4 routes within the client's isolated namespace only. Exercise traffic
|
||||
to server tunnel addresses; an external Internet gateway/DNS is not required and
|
||||
successful tunnel reachability does not claim public Internet egress works.
|
||||
Ensure test success cannot come from the Docker underlay: target tunnel-only
|
||||
addresses, use an explicit interface/route assertion, and verify public counters
|
||||
through the actual rustix reader. Test-only service apply reports must be labelled
|
||||
fixture results, never actual systemd job evidence.
|
||||
|
||||
If fixture restart orchestration verifies and releases application reservations,
|
||||
use the existing private adapter seam with a real backup, fixture apply, actual
|
||||
netlink read/comparison and journaled verification. Do not simply call
|
||||
mark_applied or clear reservations to satisfy assertions. A direct fixture apply
|
||||
outside that orchestration proves only kernel state change; it cannot by itself
|
||||
prove the production successful-restart state transition.
|
||||
|
||||
M8.5 implements these required scenarios, splitting tests where isolation helps:
|
||||
|
||||
1. **Baseline and reader interoperability.** Bring up a server plus an existing
|
||||
client with synthetic configuration, establish real IPv4 tunnel traffic,
|
||||
and observe the configured interface's complete peer set, routes, nonzero fresh
|
||||
handshake and increasing counters through the actual Rust reader. Capture
|
||||
before/after counters, not exact packet-byte totals. Empty/not-yet-handshaken
|
||||
observations must not be misreported as a reader failure or online heuristic.
|
||||
2. **Create, Commit, deliver, then apply.** Use Application to prepare a new client,
|
||||
Commit and save the actual first-delivery file (QR optional). Assert saved
|
||||
server/vault change, mandatory pre-Commit archive, unchanged runtime peers and
|
||||
explicit activation warning. Configure a fresh client from delivered bytes;
|
||||
prove it cannot reach tunnel-only targets before apply. Apply through the
|
||||
test-only boundary, then require real handshake and IPv4 traffic.
|
||||
3. **Saved deletion versus live access.** Delete and Commit an active client;
|
||||
assert current vault record removal, existing backup retention, and unchanged
|
||||
runtime peer/access before apply. Reopen saved state to verify the IP remains
|
||||
reserved. After fixture restart plus real verification/persistence, assert
|
||||
peer removal, failed fresh tunnel traffic and address release. Use a finite
|
||||
negative-check window and establish a working baseline so unrelated setup
|
||||
failure cannot masquerade as successful revocation.
|
||||
4. **Backup/restore separation.** Save a known client set, mutate/Commit, preview
|
||||
and restore the archive without providing a vault password. Assert restored
|
||||
settings/server/vault/state and precautionary backup, plus unchanged kernel
|
||||
state until explicit fixture apply. Then verify the restored peer set and
|
||||
renewed tunnel traffic. Restoration alone never releases pending addresses.
|
||||
5. **Import, reissue and file safety.** Import a valid generated existing client
|
||||
plus invalid/conflicting candidates from private source files. Assert original
|
||||
bytes unchanged, anomalies visible and conflicts blocked. Reopen and reissue
|
||||
a matched client through password-authorized output; verify wrong password
|
||||
fails and a valid delivered file can configure a real tunnel. Preserve first-
|
||||
issue/password boundaries and do not add plaintext source fallback.
|
||||
6. **Failure prevents application.** Produce a deterministic backup failure in the
|
||||
container (not chmod-only when root can bypass it) and assert Commit/fixture
|
||||
restart does not install/apply prepared changes or release addresses. Cover
|
||||
default reader deadline/missing-interface behavior inside its namespace without
|
||||
changing host state. Keep already exhaustive malformed/archive/failure-unit
|
||||
cases in ordinary tests rather than duplicating them in every costly container.
|
||||
|
||||
For all negative reachability assertions, stop/restart client traffic as needed
|
||||
and use new requests; stale timestamps/counters or buffered packets cannot prove
|
||||
continued/revoked access. Use a fixture endpoint/traffic generator with its own
|
||||
bounded error classification. Record that IPv6 traffic is intentionally untested.
|
||||
|
||||
#### Acceptance and validation
|
||||
|
||||
- [x] M8-A1: documented opt-in commands run an actual Testcontainers suite with
|
||||
pinned/cached Alpine runtime images and compatible in-container driver; default
|
||||
tests/help/version do not start Docker, require root or query host interfaces.
|
||||
- [x] M8-A2: explicit prerequisite checks reject unavailable daemon/kernel/capability
|
||||
or incompatible artifacts as incomplete/failure; no production or automatic
|
||||
privileged/module/sysctl workaround is used.
|
||||
- [x] M8-A3: isolated real peers establish IPv4 traffic, and the actual
|
||||
rustix reader reports complete public peer/routes, fresh handshake and traffic
|
||||
increments without relying solely on wg text or fake decoded observations.
|
||||
- [x] M8-A4: new client creation/Commit/file delivery use real Application and vault
|
||||
APIs; the delivered configuration works only after explicit fixture application,
|
||||
and Commit itself never changes runtime state.
|
||||
- [x] M8-A5: saved deletion removes only current secret, keeps archives and retains
|
||||
reservation/live peer until explicit apply; actual observation and journaled
|
||||
verification precede reservation release. Fresh traffic is revoked afterward.
|
||||
- [x] M8-A6: password-free restore replaces the saved set but does not apply it;
|
||||
fixture apply restores real tunnel behavior. Source files remain unchanged and
|
||||
imported conflict/wrong-password outputs remain blocked.
|
||||
- [x] M8-A7: deterministic mandatory-backup failure prevents protected write/apply;
|
||||
negative traffic and missing-interface results cannot pass due to unrelated
|
||||
broken setup or a silent empty/partial observation.
|
||||
- [x] M8-A8: fixture adapter cannot be selected in production or bypass root/password/
|
||||
backup controls; no public alternate restart API or runtime environment bypass
|
||||
is introduced. Alpine results explicitly exclude actual zbus/systemd coverage.
|
||||
- [x] M8-A9: secret-free diagnostics, private copied files, limits/deadlines and
|
||||
cleanup work on both success and failure; only test-owned resources are removed.
|
||||
- [x] M8-A10: integrated default and real-container gates pass; a clean repeated run
|
||||
reuses image layers while starting fresh mutable scenarios and produces the same
|
||||
behavioral outcomes. Independent review closes actionable isolation/coverage issues.
|
||||
|
||||
Executed integrated host and selected-daemon commands, from repository root;
|
||||
the exact Docker environment, image/driver commands, counts and durations are
|
||||
in [the M8.7 evidence](docs/evidence/milestone-8.md):
|
||||
|
||||
```sh
|
||||
cargo fmt --all -- --check
|
||||
cargo clippy --locked --all-targets -- -D warnings
|
||||
cargo test --locked
|
||||
cargo build --locked --release
|
||||
cargo test --locked --test testcontainers_wireguard -- --ignored --test-threads=1
|
||||
./target/release/wireguard-admin --help
|
||||
./target/release/wireguard-admin --version
|
||||
git diff --check
|
||||
```
|
||||
|
||||
The exact pinned image-build and in-container driver-build commands,
|
||||
prerequisites, and output artifact path are in [TESTING.md](docs/TESTING.md).
|
||||
Both were executed; the test-only musl driver compiled and ran in Alpine.
|
||||
Build setup and cached dependency access are distinct from the locked host
|
||||
test execution. No unapproved direct dependency was added.
|
||||
|
||||
Image identities, kernel/runtime/toolchain versions, target architecture,
|
||||
scenario names, outcomes, durations and counts are recorded in the evidence
|
||||
report. All required scenarios executed and passed; the ignored-test output
|
||||
explicitly reports 1/1 passing rather than treating a skipped test as success.
|
||||
Real systemd validation remains M9.
|
||||
|
||||
#### Progress
|
||||
|
||||
Current snapshot: 2026-10-25. This replaces the chronological execution notes;
|
||||
[the historical record](docs/history/milestone-8-before-workflow-cleanup.md)
|
||||
preserves previous attempts and their reported evidence.
|
||||
|
||||
| Task | State | Result / next action |
|
||||
| ------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| M8.1 | complete | Reviewed host/container contract. |
|
||||
| M8.2 | complete | Pinned Alpine recipe, package closure and readiness verified. |
|
||||
| M8.3 | complete | Reviewed IPv4 prerequisite probe passed on the selected daemon. |
|
||||
| M8.4 | complete | Reviewed in-container Application driver and real Rustix smoke passed. |
|
||||
| M8.5 traffic | complete | Copied first-delivery file drives real IPv4 traffic; exact IPv4 routes, handshakes and counter deltas verified; independent findings closed. |
|
||||
| M8.5 deletion | complete | Saved deletion preserves access until explicit fixture Apply; subsequent deleted-client traffic fails and retained-client traffic succeeds; independent finding closed. |
|
||||
| M8.5 restore | complete | Two password-free restores, unchanged runtime before Apply, renewed IPv4 traffic and pending-address release after verified Apply passed on the selected daemon. Independent code review found no implementation defect; the plan-status finding closed on re-review. |
|
||||
| M8.5 import/reissue | complete | M8.5-IMP-01 closed on independent re-review; focused tests and fingerprinted pinned musl build passed. Selected-daemon suite passed 1/1 in 82.06s with cleanup, including reissued-file IPv4 traffic. |
|
||||
| M8.5 backup failure | complete | M8.5-BF-R1 closed on independent re-review. Typed backup errors, unchanged saved/runtime state, no fixture apply, retained reservation and reader errors passed on a known-source selected-daemon run (1/1, 81.45s). |
|
||||
| M8.6 | complete | R1 documentation, R2 IPv6 plan-gate and R3 stale milestone summary findings each closed on independent re-review. No code defect was found. |
|
||||
| M8.7 | complete | Cached image/readiness/packages, pinned musl rebuild, host gates, two fresh selected-daemon full runs and the documented unfiltered opt-in command passed on stable source inputs. Final independent review closed all findings; coordinator accepted M8-A1–A10 for the scoped IPv4 Alpine work. |
|
||||
|
||||
#### Review and repair
|
||||
|
||||
| Finding / work item | State | Disposition / next evidence |
|
||||
| --- | --- | --- |
|
||||
| M8.1-R1; M8.2-R1/R2 | closed | Independent re-review closed documentation/image findings. |
|
||||
| M8.3-R1–R7 | closed | Timeout/transport/error/name fixes reviewed; revised IPv4 probe passed. |
|
||||
| M8.4-R1–R4 | closed | Driver protocol, path confinement, host transport and cleanup findings independently closed; real smoke passed. |
|
||||
| M8.5-R1/R2 | closed | Delivered bytes consumed in client namespace; exact IPv4 route assertions; independent re-review closed both. |
|
||||
| M8.5-R3 | closed | Negative ping requires completed transmitted/zero-received evidence; Docker execution errors cannot pass; independent re-review closed it. |
|
||||
| M8.5 restore phase failure | closed | Fixture expected only the removed client's IPv4 reservation; Application correctly retained both saved addresses. Exact-set expectation now derives all removed-client addresses; focused regression and selected-daemon pass. [Diagnostic record](docs/diagnostics/milestone-8.md). |
|
||||
| M8.5-RESTORE-DOC-1 | closed | Independent reviewer found stale restore status/handoff; coordinator updated the snapshot, and independent re-review closed it. No code defect found. |
|
||||
| M8.5-IMP-01 | closed | P2: the Alpine driver had omitted invalid-file byte preservation. Repair checks all three sources before claiming unchanged originals; focused regression and fingerprinted selected-daemon rerun passed, and independent re-review closed it. |
|
||||
| M8.5 failure phase | closed | Fixture misread `delete_client`'s bool as peer deletion; it actually reports vault-record removal and the legacy baseline has no record. Repair checks draft peer absence; focused regression and known-source selected-daemon run passed; independent review found no further issue with this check. |
|
||||
| M8.5-BF-R1 | closed | P2: Commit-failure assertion formerly accepted any error. Repair requires `Err(AppError::Backup(_))`; focused regression and known-source selected-daemon run passed, and independent re-review closed it. |
|
||||
| M8.6-R1 | closed | P2: TESTING.md and evidence report had stale M8.5 pending claims. Repairer recorded completed first-delivery transfer and fingerprinted backup-failure evidence; independent re-review closed it. |
|
||||
| M8.6-R2 | closed | P2: General plan gate required IPv6 prerequisites despite M8's explicit IPv4-only scope. Coordinator scoped prerequisite language to the suite and retained production dual-stack requirement as unverified; independent re-review closed it. |
|
||||
| M8.6-R3 | closed | P2: Milestone status summary still reported active M8.5 restore repair. Coordinator updated it to M8.1–M8.5 complete with M8.6/M8.7 open; independent re-review closed it. |
|
||||
| M8.7-R1 | closed | P2: Reviewer saw a prior plan snapshot while final evidence was being entered. Task/handoff rows and outcome now record passing repeated runs and R3 closure; independent re-review closed it. |
|
||||
| M8.7-R2 | closed | P3: Validation passage still described implemented and executed commands as planned, and snapshot date was stale. Coordinator corrected the passage and date; independent re-review closed it. |
|
||||
|
||||
Detailed closed-finding rationale and superseded attempts are in the historical
|
||||
record. New diagnostic attempts belong in `docs/diagnostics/`, not this table.
|
||||
|
||||
#### Evidence and handoff
|
||||
|
||||
Previously reported evidence, carried forward without rerunning during this
|
||||
2026-10-24 documentation cleanup:
|
||||
|
||||
| Scope | Result and limit |
|
||||
| --- | --- |
|
||||
| IPv4 prerequisite | Coordinator probe passed 1/1 (1.46s); isolated resources cleaned. |
|
||||
| M8.4 Application smoke | Coordinator musl rebuild and selected-daemon smoke passed 1/1 (4.05s); named resources absent afterward. |
|
||||
| M8.5 delivered-file traffic | Repaired real run passed 1/1 (14.23s); host support tests passed 21 with privileged test ignored; independent re-review closed R1/R2. |
|
||||
| M8.5 deletion | Repaired coordinator real run passed 1/1 (42.96s); host support tests passed 23 with privileged test ignored; cleanup verified; independent re-review closed R3. |
|
||||
| M8.5 restore | Worker reported fmt, focused/full locked tests, all-target Clippy, release build and diff check passing before the final reservation-helper edit; focused helper regression and pinned musl rebuild passed afterward. Coordinator exact selected-daemon run passed 1/1 (72.66s), with named resources absent. Independent review found no code issue; later integrated gates are recorded in the M8.7 row. |
|
||||
| M8.5 import/reissue | Worker reported fmt, Clippy and focused import tests after its final assertion edit; full locked tests and release build passed before it. After M8.5-IMP-01 repair, focused regressions and Clippy passed. Coordinator pinned musl build and selected-daemon run passed 1/1 (82.06s), with stable source fingerprint and named resources absent. [Reproducible evidence](docs/evidence/milestone-8.md). |
|
||||
| M8.5 backup failure | Worker reported fmt, Clippy, full locked tests/release before the final typed-error repair; focused regression, fmt and Clippy passed afterward. Coordinator pinned musl build and selected-daemon run passed 1/1 (81.45s), source-input SHA256 `b28dc6e4cb92aa6edf384d966ba5952a8d6d0efe4c22d6a804b67fb2c0297da2` stable before build/after run, driver SHA256 `ad45dc3f6b0987b075ac522e171c82c6651124c3d01c65c14df90595fe552815`, named resources absent. Independent re-review closed BF-R1. |
|
||||
| M8.7 integrated gates | On the same source fingerprint, `cargo fmt --all -- --check`, `cargo clippy --locked --all-targets -- -D warnings`, `cargo test --locked`, `cargo build --locked --release`, release help/version, and `git diff --check` exited 0. Cached Alpine image ID `sha256:f41cd6b848d8280d4d86bcaceea962e1b3e5a73e9496c6f9d7929470d0e874d5` passed readiness; 33 constrained packages recorded. Pinned musl rebuild produced the same driver SHA256. Exact selected-daemon scenario passed 1/1 twice (80.77s each); documented unfiltered `--ignored` command passed 1/1 (81.87s). Named containers/networks absent after each. [Reproducible evidence](docs/evidence/milestone-8.md); prerequisite failures in [diagnostics](docs/diagnostics/milestone-8.md). Final independent review closed M8.7-R1/R2 and found M8-A1–A10 supported. |
|
||||
|
||||
Exact earlier commands, environment/build identities and intermediate results
|
||||
remain in the historical record. For new evidence use the report format in
|
||||
[execution records](docs/EXECUTION_RECORDS.md), including the tested revision or
|
||||
working-tree identity. Earlier runs lack a complete source fingerprint; do not
|
||||
infer that they validate subsequent edits. Final gates must run on the integrated
|
||||
revision. Do not rerun unrelated gates merely to maintain this document.
|
||||
|
||||
Next action: Milestone 8 is accepted. Stop here; Milestone 9 remains pending and
|
||||
requires a disposable systemd VM before its real D-Bus acceptance work.
|
||||
|
||||
#### Decisions and discoveries
|
||||
|
||||
- The user excluded IPv6 capability and traffic testing on 2026-10-22;
|
||||
production dual-stack requirements are unchanged. Real IPv6 remains unverified.
|
||||
- Use the real bounded Rustix reader and test-only fixture Apply. Alpine cannot
|
||||
validate the private zbus/systemd adapter; real systemd acceptance remains M9.
|
||||
- Build the musl test driver in the pinned Alpine builder; the host lacks the
|
||||
musl prerequisites. Cached image/build layers may be reused; secret-bearing
|
||||
fixture state must be fresh. Build identities are preserved in the history.
|
||||
- Full fixture `wg setconf` resets learned peer state. Traffic assertions reconnect
|
||||
retained clients and require fresh observations; peer presence alone is not
|
||||
continuity evidence.
|
||||
|
||||
#### Outcome
|
||||
|
||||
M8 accepted for its user-scoped IPv4 Alpine Testcontainers work after independent
|
||||
review closed all actionable findings and the host and repeated real-container
|
||||
gates passed on one source fingerprint. M8-A1–A10 are satisfied within that
|
||||
scope. IPv6 capability and traffic were excluded by user direction; real
|
||||
systemd/D-Bus behavior remains unverified and belongs to M9.
|
||||
Milestone 9 remains pending.
|
||||
|
||||
### Milestone 9 — Real systemd acceptance and release readiness
|
||||
|
||||
@@ -2635,7 +2987,7 @@ Acceptance: real D-Bus job handling, separate restart verification, address rele
|
||||
|
||||
## Current progress and resume point
|
||||
|
||||
- Milestones 1–7 are accepted; milestones 8–9 remain pending.
|
||||
- Milestones 1–8 are accepted; milestone 9 remains pending.
|
||||
- The approved dependency list is in [DEPENDENCIES.md](docs/DEPENDENCIES.md); container testing methodology is in [TESTING.md](docs/TESTING.md).
|
||||
- Milestone 1 is expanded and the Rust environment is pinned.
|
||||
- Milestone 2 delivered a lossless in-memory WireGuard configuration editor, versioned metadata, and behavioral preservation tests.
|
||||
@@ -2646,8 +2998,17 @@ Acceptance: real D-Bus job handling, separate restart verification, address rele
|
||||
- M1–M6 integrated gates and independent reviews passed. No Alpine or VM results are claimed.
|
||||
- Milestone 7 delivered the native terminal workflow, safe startup/session projection, bounded single-owner worker, setup/import/draft/Commit/restart/delivery/backup/restore forms, synthetic PTY and workflow tests, and documentation. Independent R2 closed its list-status finding; all planned coordinator gates passed. Real WireGuard and systemd remain M8/M9.
|
||||
|
||||
- Milestone 8 delivered reviewed opt-in Alpine Testcontainers coverage for real IPv4 WireGuard peers, application lifecycle, saved/runtime separation, restoration, import/reissue, backup failures and the real Rustix reader. Host gates and three fresh real-container runs passed on one stable source fingerprint; M8-A1–A10 accepted. Real IPv6 behavior is unverified by user-authorized scope.
|
||||
- Next action: stop after M8. Milestone 9 remains pending for disposable-VM systemd/D-Bus acceptance; no production access, commit or deployment is authorized by M8 acceptance.
|
||||
|
||||
## Plan maintenance
|
||||
|
||||
Update progress, findings, decisions, blockers, and the next action after each meaningful execution/review cycle and before handing off or ending a session. Preserve acceptance evidence when summarizing old iterations. Append scope changes with their reason; update the specification only when the user actually authorizes a requirement change.
|
||||
Follow [Execution records and diagnostic workflow](docs/EXECUTION_RECORDS.md).
|
||||
Update the current snapshot in place after a task result, review disposition,
|
||||
blocker/scope change, acceptance, or handoff. Do not append command-by-command
|
||||
attempts or worker transcripts. Keep register, milestone outcome and resume point
|
||||
consistent. Preserve final evidence and scope-change reasons; archive superseded
|
||||
history with a link before removing it. Change the specification only with actual
|
||||
user authorization.
|
||||
|
||||
Planning reference: [OpenAI — Using PLANS.md for multi-hour problem solving](https://developers.openai.com/cookbook/articles/codex_exec_plans). The specific model roles, milestone numbering, and review policy above are project decisions requested by the user.
|
||||
|
||||
Reference in New Issue
Block a user