Implement client configuration delivery and reissue lifecycle
This commit is contained in:
@@ -1823,9 +1823,401 @@ without a separate request.
|
||||
|
||||
### Milestone 6 — Client configuration delivery and reissue lifecycle
|
||||
|
||||
Generate full-tunnel IPv4/IPv6 configurations using settings and preserved existing parameters where applicable. Save a root-only plaintext file and optionally render a matching QR code. Enforce post-Commit initial delivery and per-client password-based reissue with session-scoped retry after file errors.
|
||||
Status: accepted (2026-10-21T21:50:26+03:00; independent integrated re-review closed findings and all scoped M6.7 gates passed).
|
||||
Prerequisites: milestones 1–5 accepted; pinned native Rust environment and
|
||||
compatible approved dependencies. Validation uses generated keys, synthetic
|
||||
saved stores and temporary output directories without root, a terminal, Docker,
|
||||
production inputs or any actual runtime/service call.
|
||||
|
||||
Acceptance: file/QR payloads agree; no delivery before Commit; output failure permits directory change/retry; successful initial delivery or session exit ends password-free eligibility; overwrite requires confirmation; unrelated plaintext imports cannot bypass authentication.
|
||||
#### Outcome and scope
|
||||
|
||||
Deliver testable application/library operations to create a new client with a
|
||||
session-held private key, Commit its encrypted record and server entry, save its
|
||||
plaintext WireGuard configuration after Commit, and optionally produce a QR code
|
||||
for the same delivery. Subsequent issuance requires a fresh password per selected
|
||||
client. Output errors permit changing the destination and retrying initial
|
||||
issuance during the current creation session without password entry.
|
||||
|
||||
Read SPEC.md New client parameters, Encrypted vault, Connection delivery,
|
||||
Importing existing clients and Operations and states; ADRs 0001–0003;
|
||||
VAULT_FORMAT.md, CONFIG_FORMAT.md, PERSISTENCE.md, RUNTIME.md, DEVELOPMENT.md,
|
||||
DEPENDENCIES.md, TESTING.md and the current Application/VaultBundle code.
|
||||
|
||||
Out of scope: TUI/password entry widgets, rendering live terminal screens,
|
||||
plaintext source-file fallback, automatic key rotation/reconciliation, adding
|
||||
connection settings, runtime mutation, automatic restart, actual phone/client
|
||||
import, Alpine harness and VM tests. Keep startup safely incomplete. Generation
|
||||
and saving an output file do not apply configuration to WireGuard.
|
||||
|
||||
#### Existing code and integration constraints
|
||||
|
||||
- `Application::add_client` currently accepts a prepared public `Client` and edits
|
||||
server/domain drafts. It does not generate or own a private key or authorize
|
||||
first delivery. Add a coordinated creation operation rather than treating any
|
||||
existing/imported public key as eligible for password-free output.
|
||||
- `WireGuardPrivateKey::generate`, `public_key`, and explicit Base64 exposure
|
||||
exist. `VaultBundle::encrypt_record` encrypts a new key using the recipient,
|
||||
while `retrieve_client_record` returns short-lived retained connection fields
|
||||
only after password-based decryption and authenticated conflict checks.
|
||||
- New-key records currently have no retained client parameters. Build their
|
||||
configuration from authoritative saved peer addresses and current saved
|
||||
application settings, not empty record defaults. Imported records can contain
|
||||
DNS/MTU/endpoint/routes/keepalive/PSK; preserve supported existing parameters
|
||||
rather than silently converting every imported client to a new default template.
|
||||
- `RetrievedClientRecord` exposes its key and optional preshared key explicitly
|
||||
and redacts Debug; do not turn it into a globally cached unlocked vault or add a
|
||||
password-free retrieval API to work around first-delivery state.
|
||||
- `Application::commit` saves staged document/vault/state only after backup and
|
||||
journaled installation succeeds. `delete_client`, `discard_draft`, restore,
|
||||
saved settings and restart choices can affect delivery eligibility. Integrate
|
||||
with these transitions without regressing M4/M5 or bypassing recovery-required
|
||||
handling. `Application::document()` is a draft; output must use committed bytes.
|
||||
- M5 observes public technical runtime fields and does not supply a trusted server
|
||||
private key for generation. Derive the server public key from the authoritative
|
||||
saved `[Interface] PrivateKey` through existing X25519 code, in a narrow secret
|
||||
boundary, or use an already validated authoritative derivation if available.
|
||||
Missing/ambiguous/invalid server identity blocks output rather than guessing or
|
||||
reading another file/interface. Never print or serialize the server private key.
|
||||
- Cargo already contains the key/crypto, file-safety and time dependencies.
|
||||
Approved `qrcode` may be added with minimal features (no image/SVG output needed).
|
||||
No decoder, image, CLI, TUI, random, hash or new helper crate is implicitly
|
||||
approved. Check official APIs/version compatibility before adding the crate.
|
||||
|
||||
#### Context and implementation steps
|
||||
|
||||
Run bounded tasks sequentially, one writer at a time. GPT-6-Sol/medium coordinates;
|
||||
GPT-6-Luna/high implements, independently reviews and repairs. Dispatch file
|
||||
ownership, prerequisite interfaces, acceptance IDs and actual required checks.
|
||||
Only the coordinator updates milestone acceptance and evidence in PLANS.md.
|
||||
|
||||
| Task | Owner | Files and deliverable |
|
||||
| --- | --- | --- |
|
||||
| M6.1 | implementer | `src/delivery.rs` and child modules as needed, library exports, `docs/DELIVERY.md`: secret-safe payload model and deterministic configuration generation |
|
||||
| M6.2 | implementer | `src/app.rs`, narrow delivery/domain integration: coordinated new-client creation and session-scoped first-issue state |
|
||||
| M6.3 | implementer | delivery/files module, existing safe filesystem helpers: file preparation, explicit overwrite confirmation, secure output and retry results |
|
||||
| M6.4 | implementer | delivery/QR module, Cargo files, app integration: optional matrix/text output bound to the same authorized payload/file action |
|
||||
| M6.5 | implementer | `tests/client_delivery.rs`, focused unit tests and README/DELIVERY guidance: full first-issue/reissue and failure lifecycle |
|
||||
| M6.6 | reviewer, repairer | Independent integrated review, bounded findings repair and re-review |
|
||||
| M6.7 | coordinator | Integrated validation, evidence ledger and scoped acceptance/handoff in PLANS.md |
|
||||
|
||||
M6.1 renders a deterministic standard WireGuard client file: `[Interface]` with
|
||||
client private key, saved addresses and DNS; `[Peer]` with server public key,
|
||||
endpoint and routes. New clients have IPv4/IPv6 and routes `0.0.0.0/0, ::/0`,
|
||||
using the configured template and authoritative saved host addresses. Define the
|
||||
client Address prefix policy explicitly, keeping host identity separate from
|
||||
server-side AllowedIPs; do not infer client addresses from the public endpoint.
|
||||
No new MTU, keepalive or PSK defaults are introduced.
|
||||
|
||||
For imported reissue, retain validated existing optional fields and IPv4-only
|
||||
shape where applicable. Never execute or copy hooks/unknown arbitrary directives
|
||||
from source configs. Validate decrypted fields again at rendering boundaries so
|
||||
newlines/control text cannot inject sections/directives. Compare retained identity
|
||||
and addresses/server binding with fresh saved authoritative values; a stale or
|
||||
mismatched record fails closed instead of silently regenerating a different
|
||||
connection. Respect authenticated reissue_blocked, missing server/file-only cases,
|
||||
and M2 unsupported projection without truncating routes to get a valid output.
|
||||
Document precedence between saved server state, application defaults for new
|
||||
clients, and retained imported fields; do not invent a conflict-resolution UI.
|
||||
|
||||
Keep plaintext payloads in explicitly exposed, short-lived zeroizing owners,
|
||||
redacted Debug/errors and no generic Serialize/Display. Raw source/client output
|
||||
is never an ordinary status object. Bound payload size. Passwords, encoded private
|
||||
keys and rendered files must not appear in logs, panic output, snapshots or test
|
||||
failure diagnostics. Document unavoidable encoding/QR-library copies honestly.
|
||||
|
||||
M6.2 coordinates address selection, key generation, server/client draft insertion,
|
||||
vault encryption and temporary first-issue tracking as one preparation. Use M1
|
||||
allocation/reservations and optional manual selection; reuse M2 edits and M3 key
|
||||
matching. Failure at any preparation step leaves prior draft and eligibility
|
||||
unchanged. Existing vault setup may require its initial password separately;
|
||||
creating additional clients in an existing vault does not request that password.
|
||||
|
||||
Define an internal lifecycle such as pending-draft, committed-awaiting-first-file,
|
||||
and issued/invalidated, keyed by PublicKey and actual creation/committed record
|
||||
context rather than alias, UI row, or historical public-key presence. Store no
|
||||
first-issue private key, password, or eligibility in settings, internal state,
|
||||
backup, vault plaintext fields or recovery journal. Session state is not recreated
|
||||
by reopen/restore/import. A failed/incomplete Commit cannot promote eligibility.
|
||||
Unrelated valid commits/renames must not accidentally authorize another key or
|
||||
consume an unused first issue; compare the relevant saved client/record context.
|
||||
|
||||
Discard/delete/restore/reopen/session end and any relevant key/record replacement
|
||||
invalidate stale pending material. Define transition timing so cancellation and
|
||||
failed backup/pre-install validation preserve unchanged work, while a successful
|
||||
replacement or unresolved partial persistence cannot retain unsafe output authority.
|
||||
A confirmed restart applying an unchanged saved client must not require a password
|
||||
merely because runtime state changes. Do not conflate access activation with the
|
||||
first-output permission. Successful saved deletion revokes output authorization
|
||||
immediately, even if the old runtime peer remains active until restart.
|
||||
|
||||
M6.3 prepares destination selection without writing, then requires explicit
|
||||
confirmation if a file exists. Never derive a path directly from an alias that
|
||||
may repeat or contain separators; use a safe suggested filename and explicit
|
||||
selected destination. Reject symlink/special-file destinations and unsafe ancestor
|
||||
traversal; do not overwrite internal application files, server config, vault,
|
||||
settings, journal or backups as a client output. Output goes only to the chosen
|
||||
location; no directory-wide chmod/deletion or source-file cleanup.
|
||||
|
||||
Use secure temporary/staged writes, mode 0600 from creation, complete flush/sync,
|
||||
atomic publication and parent sync as appropriate. New-file publication must not
|
||||
silently replace a file; overwrite requires a confirmed bounded action for that
|
||||
destination. Document behavior if failure follows publication (for example parent
|
||||
sync failure): the file may already exist and must be reported honestly, with
|
||||
explicit confirmation on retry, not claimed absent or automatically removed.
|
||||
|
||||
Output failure before confirmed success preserves retry eligibility for the same
|
||||
initial client in the current session, allowing a different directory. A normal
|
||||
plaintext file must be saved for every delivery action; QR-only success is not
|
||||
allowed. Success consumes initial eligibility and drops the cached private key.
|
||||
Later file/QR issuance for that client requires a fresh password. Password reissue
|
||||
is per action/client, not session-wide vault unlocking; wrong password, conflict
|
||||
or missing key has no source-file bypass. Retries may keep only bounded
|
||||
operation-local material, never a reusable unlocked identity across unrelated actions.
|
||||
|
||||
M6.4 generates an optional QR from the exact bytes saved in that delivery action,
|
||||
using qrcode's matrix/public rendering API without PNG/image features or external
|
||||
qrencode. Support a future terminal renderer through a matrix/controlled text
|
||||
representation with quiet zone and documented dimensions. Keep secret-bearing
|
||||
matrix/text out of Debug, snapshots and ordinary progress messages. Do not expose
|
||||
an unguarded second QR path that reconstructs private material from cached state.
|
||||
|
||||
One authorized action may include both file and QR; showing that same prepared
|
||||
QR does not require a second password. If QR encoding exceeds capacity or fails,
|
||||
the file can still be successfully delivered: report file success and QR failure
|
||||
separately, consume first-issue eligibility, and do not report a total failure
|
||||
that misleadingly permits another first file. A later new QR/delivery action then
|
||||
requires password authorization. A future TUI displays/clears the operation-local
|
||||
QR; terminal lifecycle implementation remains M7.
|
||||
|
||||
M6.5 covers complete library flows with private temporary stores and generated
|
||||
synthetic keys. Use fault-injected file writes and unit-tested authorization
|
||||
transitions, not privileged filesystem behavior. Assert file content through
|
||||
redacted comparisons/parsed public values and explicit key correspondence without
|
||||
printing secrets. Reuse M3 parsing for compatible generated files to demonstrate
|
||||
identity/server/routes semantics. File/QR equality should be guaranteed by a
|
||||
single payload source and tested at the encoding boundary; do not claim external
|
||||
QR decoding/real-device compatibility unless actually checked or add a decoder
|
||||
crate without approval.
|
||||
|
||||
#### Acceptance and validation
|
||||
|
||||
- [x] M6-A1: new clients yield valid full-tunnel dual-stack configurations using
|
||||
committed addresses/settings and a correctly derived server key; missing or
|
||||
ambiguous authoritative identity fails without guessing or exposing secrets.
|
||||
- [x] M6-A2: imported reissue preserves supported existing optional parameters
|
||||
and IPv4-only shape; stale identity/address/server bindings, authenticated
|
||||
conflict flags and unsupported data block unsafe delivery without truncation.
|
||||
- [x] M6-A3: coordinated creation stages a matching public client and encrypted
|
||||
key; failed preparation leaves prior drafts intact. No output is authorized
|
||||
before successful Commit or from an imported/existing key without a password.
|
||||
- [x] M6-A4: failed/incomplete Commit does not promote first issue; a successful
|
||||
Commit permits first output for the newly created client in that session.
|
||||
Draft discard/delete/restore/reopen and record replacement cannot restore or
|
||||
transfer stale eligibility; duplicate aliases remain independent by public key.
|
||||
- [x] M6-A5: failed file save supports same-session retry/new directory without
|
||||
password for initial issuance; success consumes eligibility. Reissue requires
|
||||
fresh per-client authorization with no cached identity/plaintext-file fallback.
|
||||
- [x] M6-A6: mandatory plaintext file creation uses 0600 from first write, safe
|
||||
paths, bounded payloads, explicit overwrite confirmation and honest partial-
|
||||
publication failure reporting; protected application/source files stay untouched.
|
||||
- [x] M6-A7: optional QR uses the exact same payload as the saved file; QR failure
|
||||
does not erase file success or grant another first issue. No independent QR-only
|
||||
bypass or retained cross-action secret cache exists.
|
||||
- [x] M6-A8: outputs warn when saved changes are not verified applied. Unavailable
|
||||
runtime is not silently treated as active; delivery never invokes service or
|
||||
WireGuard operations, releases reservations or changes apply history.
|
||||
- [x] M6-A9: rendering/input injection, wrong password, missing vault/record,
|
||||
duplicate/conflicting metadata, occupied/manual address failures, overwrite
|
||||
decline, symlink/special paths, and write/flush/publication/sync failures are tested.
|
||||
- [x] M6-A10: secret-bearing types, errors/Debug and tests do not disclose keys,
|
||||
passwords, configuration payloads or QR matrices; ephemeral material is never
|
||||
persisted in backup/journal/state and supported owned buffers clear on drop.
|
||||
- [x] M6-A11: M1–M5 regressions and integrated gates pass unprivileged with no real
|
||||
network, system bus, runtime, production paths or terminal required. Independent
|
||||
review closes actionable auth-lifecycle/rendering/output-safety findings.
|
||||
|
||||
Planned commands from the repository root after M6 targets and lockfile exist:
|
||||
|
||||
```sh
|
||||
cargo test --locked delivery
|
||||
cargo test --locked --test client_delivery
|
||||
cargo test --locked --test runtime_restart
|
||||
cargo test --locked --test commit_restore
|
||||
cargo test --locked --test vault_import
|
||||
cargo test --locked --test config_preservation
|
||||
cargo fmt --all -- --check
|
||||
cargo clippy --locked --all-targets -- -D warnings
|
||||
cargo test --locked
|
||||
cargo build --locked --release
|
||||
./target/release/wireguard-admin --help
|
||||
./target/release/wireguard-admin --version
|
||||
git diff --check
|
||||
```
|
||||
|
||||
Ensure focused filters run actual tests. Resolve approved qrcode and update
|
||||
Cargo.lock before locked checks; do not add Ratatui/Crossterm prematurely. Record
|
||||
commands, counts and exit results. All commands should exit zero; negative cases
|
||||
are passing assertions. No phone QR scan, real tunnel, terminal screenshot, Alpine
|
||||
or systemd result is required or claimed for this library/file-output milestone.
|
||||
|
||||
#### Progress
|
||||
|
||||
- [x] Description prepared against accepted M1–M5 code and current documents.
|
||||
- [x] 2026-10-20T23:12:02+03:00 execution preparation: verified active coordinator `gpt-6-sol`/`medium` in this session's latest turn context and project worker roles `gpt-6-luna`/`high`; confirmed M1–M5 accepted, read required specification, ADRs and supporting documents, and inspected the clean source baseline. The pre-existing expanded M6 plan edit in this worktree is preserved.
|
||||
- [x] M6.1 — implementer delivered bounded, zeroizing payload rendering in `src/delivery.rs`, library export and `docs/DELIVERY.md`, with new-client and authenticated-import paths. Independent R1 found an unchecked caller-supplied server identity; repairer moved derivation to the saved `[Interface] PrivateKey` boundary and added malformed/missing/ambiguous cases. Independent re-review closed M6.1-R1. Final focused `cargo test --locked delivery::tests` passed 7 tests; fmt, Clippy and diff checks passed. Fixture evidence only; no file/QR or host behavior claimed.
|
||||
- [x] M6.2 — implementer added transactional dual-stack creation and encrypted vault staging, plus session-only first-file state in `src/app.rs` and a narrow encrypted-record context accessor in `src/vault.rs`. Independent R1 identified duplicate live authorizations; repairer made issuance single-flight with explicit retry states, and re-review closed it. The same reviewer identified stale standalone plaintext after app mutation; second repair moved output behind an app-owned `deliver_first_issue` closure holding the mutable session borrow, and re-review closed it. Final `cargo test --locked app::tests::` passed 41 synthetic tests; fmt, Clippy and diff checks passed. M6.3 still must connect actual file results to these states.
|
||||
- [x] M6.3 — implementer added secure file-output adapter in `src/delivery/files.rs`, app first-issue bridge, narrow SavedStore protected-path accessor and documentation. Initial focused `cargo test --locked delivery` passed 16 and `cargo test --locked app` passed 47; fmt, Clippy and diff checks passed. Fresh independent review found two actionable findings (M6.3-R1/R2 below). Three targeted repair rounds and independent re-review closed both under the documented single-administrator threat model; final focused `cargo test --locked delivery` passed 20 and file-module tests passed 12; fmt, Clippy and diff checks passed. No production filesystem behavior is claimed.
|
||||
- [x] M6.4 — implementer added approved `qrcode` 0.14.1 with default features disabled, bounded/zeroizing operation-local matrix representation, file-first optional QR integration and focused tests. Initial `cargo test --locked delivery` passed 22 and `cargo test --locked app` passed 51; fmt, Clippy and diff checks passed. Independent R1 found a public QR-only encoder path; repairer made it crate-private with a compile-fail doctest, and independent re-review closed the finding. Final focused delivery (22) and doctests (2) passed. No phone scan or terminal rendering is claimed.
|
||||
- [x] M6.5 — implementer added fresh password-per-action reissue from installed vault bytes, validated authenticated key-only/imported provenance, a live-generation activation warning, five public synthetic lifecycle tests in `tests/client_delivery.rs`, and README/DELIVERY guidance. Initial focused integration (5), delivery (22), app (51) and partial-provenance regression (1) passed with fmt, Clippy and diff checks. Fresh independent review found first-issue outputs omitted the activation warning. Repairer added it to file-only, file+QR and definite-publication/bookkeeping-uncertain results; re-review found uncertain file publication still omitted it, so a second repair added warning to failed outcomes and injected file-only/QR uncertainty tests. Independent re-review closed the finding. At M6.5 closure, `cargo test --locked app::` passed 50 and `--test client_delivery` passed 5; fmt, Clippy and diff checks passed. Integrated gates ran later in M6.7.
|
||||
- [x] M6.6 — a fresh independent integrated reviewer inspected M6-A1–A11 and found three actionable issues: secret-bearing assertion diagnostics, optional imported server-key binding in the public renderer, and unreported temporary-file cleanup failure. Repairer fixed all three; independent re-review closed them with no new actionable issue. The reviewer found M6-A1–A10 supported by scoped synthetic evidence and left M6-A11 pending coordinator integrated gates.
|
||||
- [x] M6.7 — coordinator ran every planned command against the integrated revision, verified all exit zero and nonempty focused test filters, checked changed files and reviewer evidence, and accepted M6-A1–A11 for the explicitly scoped fixture/file-output milestone. No real WireGuard, systemd, terminal or phone scan is claimed.
|
||||
|
||||
#### Review and repair
|
||||
|
||||
M6.1-R1 (P2, `src/delivery.rs`): the initial renderers accepted a caller-supplied
|
||||
server public key without proving it came from the saved server configuration;
|
||||
the initial valid-looking test even used a different key. Repairer made both
|
||||
renderers derive it from exactly one valid saved `[Interface] PrivateKey`, reject
|
||||
missing/duplicate/malformed sources with a redacted error, and compare imported
|
||||
retained identity to that key. Synthetic regression tests passed (7 focused);
|
||||
the independent reviewer re-reviewed and closed the finding.
|
||||
|
||||
M6.2-R1 (P2, `src/app.rs`): two outstanding first-issue capabilities could
|
||||
both expose plaintext before either was consumed. Repairer made authorization
|
||||
single-flight/token-bound and added explicit pre-publication versus uncertain-
|
||||
publication retry handling. The independent reviewer closed this part after
|
||||
focused tests.
|
||||
|
||||
M6.2-R2 (P2, `src/app.rs`): invalidating a standalone token after deletion or
|
||||
replacement did not revoke a caller-held plaintext payload. Repairer removed
|
||||
that accessor and introduced an app-owned publication closure that validates
|
||||
saved peer/record context immediately before the file writer runs while holding
|
||||
`&mut Application`; stale deletion/replacement tests show the closure is not
|
||||
invoked. Independent re-review closed the finding. The real file adapter is
|
||||
still M6.3 work, not evidence from these synthetic closures.
|
||||
|
||||
M6.3-R1 (P2, `src/delivery/files.rs`): a confirmed overwrite rechecked the
|
||||
destination inode before `renameat`, but another entry could replace it between
|
||||
the check and publication and then be overwritten without confirmation. The
|
||||
independent reviewer supplied a deterministic `Checkpoint::Publish` substitution
|
||||
reproducer. Repairer changed confirmed replacement to atomic `RENAME_EXCHANGE`,
|
||||
checks the displaced inode and rolls back without deleting unexpected entries;
|
||||
rollback identity and parent sync failures report uncertainty. A later re-review
|
||||
found the normal-success temp-name unlink still vulnerable to a different local
|
||||
writer. Final repair requires a selected parent owned by root/current effective
|
||||
user without group/world write, checks existing ancestors, and uses an exclusive
|
||||
0600 temporary name with 128 bits of OS randomness. Independent re-review closed
|
||||
R1 under the single-administrator threat model. Same-privilege concurrent name
|
||||
changes remain explicitly outside scope; temporary 0600 output retained after a
|
||||
rollback is documented for manual cleanup rather than risking deletion of an
|
||||
unconfirmed entry.
|
||||
|
||||
M6.3-R2 (P2, `src/app.rs`): after a definite file publication, a fallible
|
||||
post-publication saved-state read/mark could return an undifferentiated app error,
|
||||
concealing that a plaintext file was already created. The independent reviewer
|
||||
requested an explicit published-but-bookkeeping-uncertain result and fault test.
|
||||
Repairer added `PublishedButBookkeepingUncertain` with definite file-success
|
||||
evidence and invalidated the session-held first-issue key on bookkeeping failure.
|
||||
The independent reviewer closed R2 after a synthetic post-publication saved-store
|
||||
failure test. No password-free retry is authorized by that result.
|
||||
|
||||
M6.4-R1 (P2, `src/delivery/qr.rs`): a public QR encoder allowed a library caller
|
||||
to render a payload and generate a QR without the mandatory file action.
|
||||
Repairer restricted the encoder and module to crate visibility, kept public
|
||||
output/error value types for the guarded app result, and added a compile-fail
|
||||
doctest. Independent re-review closed the finding after file-first and
|
||||
QR-failure tests. QR scanning and terminal rendering remain unverified/future.
|
||||
|
||||
M6.5-R1 (P2, `src/app.rs`): initial file-only and file-plus-QR delivery did
|
||||
not report whether the saved client had been verified active. Repairer bound an
|
||||
activation warning to the exact installed generation and the live verified
|
||||
saved/applied snapshot, never the historical timestamp. Re-review found the
|
||||
possibly-published parent-sync failure still lost the warning; second repair
|
||||
carried it in the failed outcome and tested uncertain publication for both
|
||||
variants with QR skipped. Independent re-review closed R1. All evidence is
|
||||
synthetic/fault-injected, not live VPN or device compatibility.
|
||||
|
||||
M6.6-R1 (P2, `src/app.rs` tests): `assert_eq!` on saved and rendered client
|
||||
configuration bytes could print a private key if a test failed. Repairer changed
|
||||
those to boolean assertions and audited related tests. Independent integrated
|
||||
re-review closed this secret-diagnostic finding.
|
||||
|
||||
M6.6-R2 (P2, `src/delivery.rs`/`src/vault.rs`): the public imported renderer
|
||||
accepted a missing saved-server binding from a mutable retrieved record.
|
||||
Repairer made retained fields private/read-only, required imported provenance and
|
||||
an exact present saved-server binding, and added missing/stale binding tests.
|
||||
Independent integrated re-review closed it.
|
||||
|
||||
M6.6-R3 (P2, `src/delivery/files.rs`/`src/app.rs`): ignored temp-file cleanup
|
||||
errors could leave a plaintext 0600 staging file while reporting an ordinary
|
||||
pre-publication failure. Repairer added a distinct `ManualCleanupRequired`
|
||||
result, retry gating until explicit cleanup acknowledgement, documentation and
|
||||
an injected cleanup-failure test confirming no selected-file publication.
|
||||
Independent integrated re-review closed it. The user may still need to inspect
|
||||
and remove a retained staging file; the application does not silently erase an
|
||||
uncertain entry.
|
||||
|
||||
All actionable M6 task-local and integrated review findings are closed after
|
||||
repair and independent re-review. The integrated reviewer found M6-A1–A10
|
||||
supported by synthetic/fault-injected evidence; M6-A11 then passed the
|
||||
coordinator's final integrated gates. No password check was weakened and no
|
||||
preservation test was disabled.
|
||||
|
||||
#### Evidence and handoff
|
||||
|
||||
Initial planning inspected current Application creation/Commit/discard/restart interfaces,
|
||||
VaultBundle key-only encryption and password-authorized retained fields, current
|
||||
Cargo dependencies, M5 acceptance record and runtime documentation, plus product
|
||||
specification/secret-storage ADR. M5 records scoped fixture acceptance and passing
|
||||
integrated gates with independent re-review; real kernel/systemd checks remain
|
||||
M8/M9. That planning-only turn did not rerun application tests, add crates/source, generate
|
||||
private keys/output/QR, dispatch agents or contact host runtime/services.
|
||||
|
||||
Final M6.7 validation on the integrated revision (all exit 0):
|
||||
`cargo test --locked delivery` (23 matching tests),
|
||||
`cargo test --locked --test client_delivery` (5),
|
||||
`cargo test --locked --test runtime_restart` (2),
|
||||
`cargo test --locked --test commit_restore` (9),
|
||||
`cargo test --locked --test vault_import` (5),
|
||||
`cargo test --locked --test config_preservation` (9),
|
||||
`cargo fmt --all -- --check`,
|
||||
`cargo clippy --locked --all-targets -- -D warnings`,
|
||||
`cargo test --locked` (205 library unit, 30 integration and two doctests passed;
|
||||
binary tests 0), `cargo build --locked --release`, release `--help` and
|
||||
`--version`, and `git diff --check`. Release `--help` correctly states the
|
||||
management interface is not implemented. Checks used synthetic keys,
|
||||
temporary stores/output directories and fake adapters without root, Docker,
|
||||
host WireGuard/system bus, production paths or a terminal. The approved
|
||||
`qrcode` 0.14.1 was added with default features disabled; no other direct
|
||||
dependency was introduced. No phone QR scan, live tunnel, Alpine test or
|
||||
disposable systemd VM result is claimed. Those validations remain future
|
||||
M7–M9 work, not passing M6 evidence.
|
||||
|
||||
Next action: stop after accepted M6. M7 may begin only on a separate request;
|
||||
do not create a Git commit or deploy.
|
||||
|
||||
#### Decisions and discoveries
|
||||
|
||||
New vault records contain a key but no template parameters, while imported
|
||||
records retain supported connection fields. Delivery needs an explicit provenance
|
||||
and precedence rule rather than assuming both are interchangeable. Creation must
|
||||
retain ephemeral private material separately from password-only vault retrieval;
|
||||
otherwise first delivery without a password is impossible. That ephemeral
|
||||
material cannot be persisted or reconstructed after session loss.
|
||||
|
||||
M5 applies saved state and M6 exports saved state; neither should call the other
|
||||
implicitly. File and QR are two representations of one authorized delivery action,
|
||||
with file success as the first-issue completion boundary. M7 supplies the terminal
|
||||
interaction around these library contracts.
|
||||
|
||||
#### Outcome
|
||||
|
||||
M6.1–M6.7 are complete. Accepted for the milestone's explicitly scoped
|
||||
synthetic/file-output checks after independent integrated review, repair,
|
||||
re-review and all planned coordinator gates. The TUI, phone compatibility,
|
||||
real WireGuard and actual systemd/D-Bus behavior are not claimed; M7–M9 own
|
||||
their later acceptance. No Git commit, deployment or production access occurred.
|
||||
Stop after M6; do not start M7 without a separate request.
|
||||
|
||||
### Milestone 7 — Complete terminal management workflow
|
||||
|
||||
@@ -1847,14 +2239,15 @@ Acceptance: real D-Bus job handling, separate restart verification, address rele
|
||||
|
||||
## Current progress and resume point
|
||||
|
||||
- Milestones 1–5 are accepted; milestones 6–9 remain pending.
|
||||
- Milestones 1–6 are accepted; milestones 7–9 remain 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.
|
||||
- Milestone 3 delivered secret-safe key handling, a versioned encrypted vault, caller-buffer reconciliation, and a bounded read-only source-directory import adapter.
|
||||
- Milestone 4 delivered versioned private backups, journaled saved-file Commit and recovery, previewed full restore, durable address reservations and historical verification bookkeeping, with independent R5 closure and coordinator gates.
|
||||
- Milestone 5 delivered public runtime observations and technical comparison, an approved-rustix bounded read-only netlink adapter, a zbus systemd job adapter, restart orchestration, and synthetic integration tests. Independent integrated review and repairs closed all actionable scoped findings; all planned gates passed. Real kernel/systemd validation remains deferred to M8/M9.
|
||||
- M1–M5 integrated gates and independent reviews passed. No Alpine or VM results are claimed.
|
||||
- Milestone 6 delivered session-bound creation/first-file authorization, saved-state rendering and password-per-action reissue, secure plaintext file output, optional same-payload QR, and synthetic lifecycle tests. Independent integrated review and repair closed all actionable findings; all planned gates passed. TUI and real-system validation remain M7–M9.
|
||||
- M1–M6 integrated gates and independent reviews passed. No Alpine or VM results are claimed.
|
||||
|
||||
## Plan maintenance
|
||||
|
||||
|
||||
Reference in New Issue
Block a user