fix(attachments): mirror outbox layout in peat-cli + test inbox sinks (#173) + docs/version-minimums#175
Conversation
… + version minimums
The example README described delivered files landing at
inbox/{distribution_id}/{filename}. As of v0.4.8 (#173) the inbox mirrors
the sender's outbox layout instead (outbox/sub/f -> inbox/sub/f, original
name, latest-wins), with an unsafe-name fallback to {distribution_id}.bin
at the inbox root. Validated end-to-end across two arm64 hosts, both directions.
- README: rewrite the three stale {distribution_id} path claims; add a
per-feature version-minimums table (PRD-006 v0.2.0, reliable delivery
v0.3.0, derive-id v0.4.4, outbox-watch v0.4.5, mirrored layout v0.4.8).
- Bump all three example compose pins v0.4.5 -> v0.4.8 so they exhibit the
documented layout and match the validated run.
Does NOT touch the peat-cli InboxSink / e2e TestInboxSink / main.rs doc
comment, which still describe+implement the old layout (tracked separately).
peat-bot
left a comment
There was a problem hiding this comment.
Peat QA Review (SHA: 51c5e1d)
Docs-only PR: rewrites examples/compose/attachments/README.md to reflect the v0.4.8 mirrored-outbox inbox layout (#173), adds a per-feature version-minimums table, and bumps the three example compose pins from v0.4.5 → v0.4.8. No proto, Rust, Cargo.toml, chart, or zarf.yaml changes.
Doc claims cross-checked against the diff that landed in #173: the "mirrors the sender's outbox layout" wording, the unsafe-path fallback to {distribution_id}.bin at the inbox root, and the v0.4.5 hands-off-watcher / v0.4.4 deterministic-identity minimums all match what is actually in tree. Author reports end-to-end validation on two arm64 Raspberry Pis (bidirectional, sha256-identical) in the PR body.
The PR explicitly carves out the peat-cli InboxSink / TestInboxSink / --attachment-inbox doc divergence as a tracked follow-up. That's the right call for a docs-only change in this repo — those paths live in a sibling crate and require a code + regression-test change, not a README edit.
No findings.
…x layout (#173) #173 changed the production FilesystemInboxSink to write delivered blobs at {inbox}/{relative_path} (mirroring the sender's outbox layout), but the peat-cli InboxSink and the e2e TestInboxSink still nested every delivery under {inbox}/{distribution_id}/{filename}. A peat-cli receiver and a peat-node receiver therefore disagreed on where files land. Bring both sinks into lockstep with production: - peat-cli InboxSink: resolve a sanitised inbox-relative path (subdirs preserved, absolute/.. rejected -> {distribution_id}.bin fallback), create nested parents, add the post-write size-validation guard. - e2e TestInboxSink: same path resolution + already_delivered keyed on the mirrored path. - Update the two e2e scenarios to assert the mirrored path and that no {distribution_id}/ dir is created. - Fix stale doc comments: attach.rs module + watch help, main.rs --attachment-inbox. Regression tests (peat-cli lib): deliver_mirrors_relative_path_not_distribution_id_dir, deliver_traversal_name_falls_back_inside_inbox, deliver_size_mismatch_bails_without_publishing, plus inbox_relpath_* unit coverage. Adds chrono as a dev-dependency for the DistributionDocument fixture. Verified: fmt, clippy -D warnings, cargo test --workspace (the two real-iroh attach e2e scenarios now assert the mirrored layout end-to-end).
peat-bot
left a comment
There was a problem hiding this comment.
Peat QA Review (SHA: ebf898b)
Incremental review since 51c5e1d.
Delta converts the prior docs-only PR into a fix+docs PR: peat-cli's InboxSink and the e2e TestInboxSink are brought into lockstep with the production FilesystemInboxSink (post-#173 mirrored-outbox layout). The two stale sinks previously wrote deliveries under {inbox}/{distribution_id}/{filename}, which disagreed with the production sink that #173 moved to {inbox}/{relative_path} — a peat-cli receiver and a peat-node receiver therefore landed the same blob in different places. This PR closes that gap.
Sanity checks against the peat-node review criteria:
- No proto / Connect RPC /
PeatSidecarsurface changes. - No
src/crypto.rs,chart/peat-node/,zarf.yaml,src/watcher.rs, orpeat-meshpin changes. src/main.rschange is a--attachment-inboxdoc-comment correction only.- New dep is
chrono = "0.4"as a peat-cli dev-dependency (Cargo.lock shows it added under the peat-cli entry). Not a new runtime — used only to build aDistributionDocument { started_at: DateTime<Utc>, .. }fixture for the new unit tests. - Path-traversal guard (
inbox_relpath) is whitelist-based viastd::path::Component: onlyNormalaccepted,CurDirignored, everything else (absolute,.., Windows prefix) rejected → caller falls back to{distribution_id}.binat the inbox root. Tested with../../etc/passwd,/etc/passwd, anda/../../b. - Post-write size validation in
InboxSink::deliverremoves the partial and bails on mismatch — iroh content-verifies the blob on fetch, so a size match confirms a complete local write. Unit-tested bydeliver_size_mismatch_bails_without_publishing. - E2E coverage: both real-iroh attach scenarios (
attach_send_delivers_file_to_peer_inbox,attach_watch_receives_file_from_peer) now poll the mirrored target path and explicitly assert no{distribution_id}/directory is created. - PR reports
cargo fmt --check,cargo clippy --workspace --all-targets -- -D warnings, andcargo test --workspaceall green, plus two-rPi end-to-end byte-identical validation.
Prior review at 51c5e1d had no findings — nothing to re-verify.
No findings.
What
Brings the peat-cli and e2e test inbox sinks into lockstep with the production
FilesystemInboxSink, and corrects the example docs — all around the v0.4.8 (#173) inbox-layout change.#173 changed the production sink to write delivered blobs at
{inbox}/{relative_path}(mirroring the sender's outbox layout), but two other sinks in this repo were never updated and still nested every delivery under{inbox}/{distribution_id}/{filename}. Apeat-clireceiver and apeat-nodereceiver therefore disagreed on where files land.Code fix
crates/peat-cli/src/cli/attach.rs(InboxSink): resolve a sanitised inbox-relative path (subdirs preserved; absolute/..rejected →{distribution_id}.binfallback), create nested parents, and add the post-write size-validation guard — faithfully mirroring production.crates/peat-cli/tests/e2e/topology.rs(TestInboxSink): same path resolution;already_deliveredkeyed on the mirrored path.crates/peat-cli/tests/e2e/scenarios.rs: both attachment scenarios now assert the mirrored path and that no{distribution_id}/directory is created.attach.rsmodule +watchhelp,src/main.rs--attachment-inbox.Regression tests
New peat-cli lib tests:
deliver_mirrors_relative_path_not_distribution_id_dir,deliver_traversal_name_falls_back_inside_inbox,deliver_size_mismatch_bails_without_publishing, plusinbox_relpath_*unit coverage. Addschronoas a dev-dependency for theDistributionDocumentfixture.Docs
{distribution_id}path claims; add an "Attachment feature version minimums" table (PRD-006 v0.2.0, reliable delivery v0.3.0,derive-idv0.4.4, outbox-watch v0.4.5, mirrored layout v0.4.8).Verification
cargo fmt --check✓ ·cargo clippy --workspace --all-targets -- -D warnings✓cargo test --workspace✓ — incl. the two real-iroh attach e2e scenarios (attach_send_delivers_file_to_peer_inbox,attach_watch_receives_file_from_peer) now asserting the mirrored layout over the wire, and the 122 peat-node lib tests. (One unrelated sync-subprocess test flaked under full-parallel load and passes in isolation.)