Skip to content

feat(wasm)!: support large-file downloads and disk streaming - #214

Merged
jacderida merged 15 commits into
mainfrom
feat/wasm-large-file-downloads
Oct 14, 2026
Merged

jacderida merged 15 commits into
mainfrom
feat/wasm-large-file-downloads

Conversation

@mickvandijke

@mickvandijke mickvandijke commented Oct 1, 2026 •

Copy link
Copy Markdown
Member

Files larger than 1 GB are currently rejected even when a browser reads them in bounded ranges. Removing that check alone would still leave 32-bit file offsets on wasm32. This change uses 64-bit file positions throughout browser reads, including the read-ahead from main, and adds BrowserFileReader.pipeTo() for public and private files, with backpressure, AbortSignal cancellation and writer cleanup.

Complete downloads fetch as on main: within the adaptive fetch limit (capped by concurrency), with missing records retried together in shared rounds. Each chunk is copied into its place in one JavaScript Uint8Array as it arrives. A complete download accepts an optional output-memory budget and an AbortSignal, and reports allocation failures with the streaming alternative. pipeTo fetches chunks concurrently, retries each on its own, and writes them in file order while holding at most 32 MiB of plaintext. Chunk positions, range lookup and per-chunk decryption come from self_encryption::DataMapIndex (WithAutonomi/self_encryption#447), which uses 64-bit positions on every platform and stops decompression at each chunk's declared size. Manifest validation accepts larger files and up to 262,144 chunks. The companion SDK and upload limits are outside this PR.

Before merge: publish self_encryption 0.36.2 from WithAutonomi/self_encryption#447 and remove the temporary [patch.crates-io] from the root Cargo.toml.

Linear issue

Closes V2-1398

Risk tier

  • T0 — docs / tooling / CI / pure UX-output. Repo CI only.
  • T1 — client-only, no network-facing behavior change. CI + prod compat smoke.
  • T2 — node/client logic with behavioral surface, no protocol/format/economics change. Dev testnet + ADR.
  • T3 — protocol / storage format / payments / routing. T2 evidence + adversarial testing.

Proposed for reviewer confirmation: client download buffering, offset validation and destination handling; no wire, node, storage-format or payment changes.

Compatibility

  • Wire: none; existing WebRTC requests and protocol verification are retained.
  • Storage: none; native DataMaps, ciphertext, per-chunk KDF and BLAKE3 verification are retained. Browser reads decrypt through self_encryption::DataMapIndex::decrypt_chunk, which uses the same KDF as self_encryption::decrypt_chunk and also rejects a chunk whose plaintext differs from its declared size, which encrypt never produces.
  • API: breaking for Rust browser consumers; existing JavaScript calls keep working, with the changes below.
    • Rust: PublicFileDescriptor.size changes from usize to u64, and affected WASM-export signatures change. Native data_download_range keeps its signature.
    • JavaScript: downloadPublicFile/downloadPrivateFile gain a trailing { maxMemoryBytes?, signal? } argument after concurrency and onProgress. pipeTo(writable, { start?, end?, signal?, onProgress? }) is additive. Progress text stays Downloaded chunk n/total. Sizes and offsets remain numbers but are validated as nonnegative safe integers: readRange rejects fractional, negative, missing or imprecise arguments that wasm-bindgen previously coerced (an omitted length used to read nothing, and 1.5 read from byte 1).
    • Behaviour: BrowserFileReader.close() releases the records its read-ahead holds and makes later calls fail, but no longer clears the client's shared chunk cache (bounded at 32 MiB, LRU). A DataMap whose range reads reject, such as one with non-contiguous indices, now fails at openPublicFile/openPrivateFile instead of opening with read-ahead off.

Semver impact

  • breaking
  • feature
  • fix

Breaking is proposed for Rust browser API consumers; existing JavaScript call forms remain supported.

Test evidence

  • Generated WASM: 221 tests passed. They include a complete 4,303,347,835-byte native-encrypted file streamed through pipeTo with a matching BLAKE3 and writes of at most 4 MiB, and fetching behind a blocked write stopping at the 32 MiB bound. They also cover AbortSignal cancellation of pipeTo and complete downloads (during retry waits, a stalled destination write and the destination's close), invalid pipeTo calls that leave the destination untouched (including a signal that is not an AbortSignal), writer, allocation and output errors, memory budgets, progress, public/private seeks across 4 GiB, and main's read-ahead suite.
  • Native: 819 ant-core library tests passed, including ranges, per-chunk retries, malformed maps and read-ahead windows past 4 GiB. The 64-bit index tests moved to self_encryption with DataMapIndex.
  • self_encryption#447: its tests, clippy (--all-targets --all-features) and fmt pass, and its Criterion decrypt benchmarks are unchanged against master.
  • cargo fmt --check, native clippy (--all-targets --all-features) and the wasm32 browser-wasm clippy, with and without test-utils, pass.
  • "Real Chromium and local nodes" passes in CI: the existing paid upload, recovery, download and pointer suites in real Chromium against seven nodes at the pinned revision.
  • Real-browser large file, run locally at fc215e6 (before the review fixes in 773ea5d; not re-run since) with Chromium 151 on macOS against seven nodes at the pinned revision: the 4,303,347,835-byte fixture plaintext was uploaded natively (1,032 records, 49 s) and landed on the fixture's address. The reader opened in 0.35 s and read across 4 GiB, and pipeTo wrote the whole file into the origin private file system (a real FileSystemWritableFileStream) in 100 s (147 s on an earlier run), with 1,028 progress calls, a matching BLAKE3, and the right stored size and bytes around 4 GiB and at the end. A complete download over a 64 MiB budget failed before any transfer and pointed to pipeTo. Chromium could not allocate one 4.3 GB buffer (RangeError: Array buffer allocation failed), so streaming is the only whole-file path at this size there. The file is one repeated byte and its records compress to about 67 KB, so this checks correctness, not network throughput. It is repeatable with the opt-in ant-core/browser-tests/large-file.mjs, which is not run in CI.
  • The WASM mock now copies an outgoing message before re-entering WASM; with a large record store, loading records could grow memory and detach it, intermittently failing GETs.
  • The WASM tests run in Node with mocked WebRTC hosts and real Rust protocol/crypto processing. Not done: the T1 production compatibility smoke, live-network runs, and Safari or Firefox. A browser-side upload of the same 1,032 records to the seven-node devnet did not complete (per-session request admission on the nodes, after which the client stops using the peers it lost); uploads are outside this PR, so the large-file run uploads natively.
  • Security Audit fails on newly published quinn-proto advisories (RUSTSEC-2026-0339 to 0342); this PR's Cargo.lock differs from main's only in self_encryption.
  • Test fixture and reproducible native generator: ant-core/wasm-tests/large-download.test.mjs and ant-core/examples/generate-browser-large-file.rs.

New dependency

None. self_encryption moves to 0.36.2 for DataMapIndex; until that is published, a temporary [patch.crates-io] pins WithAutonomi/self_encryption#447 at 869b2f94.

ADR

ADR-0004: large-file download destinations. The existing Proposed ADR is amended and remains Proposed.

Mitigation / rollback

Revert this PR and regenerate consuming WASM artifacts; self_encryption 0.36.2 is additive and can stay. Applications can keep using bounded readRange and set an explicit output-memory budget. Root-map/index memory, destination capacity and JavaScript's safe-integer range (just under 8 PiB) remain practical limits; disk output requires a caller-provided writable destination. Follow-ups: cancellation for native range reads, and bypassing the shared chunk cache when streaming.

🤖 Generated with Claude Code

@dirvine dirvine left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review — Hermes Agent

Verdict: No material blockers.

Verified against head 1bc1931:

64-bit positions. FileIndex.offsets is Vec<u64>; chunk_span and chunks_overlapping operate on u64 throughout. wasm32 truncation at 4 GiB is eliminated. readRange now validates inputs as nonnegative safe integers and rejects fractional/negative/imprecise arguments.

Memory bound. STREAM_BUFFER_BYTES = 32 MiB. ordered_pipeline admits items while outstanding + cost(next) <= budget; outstanding covers in-flight + fetched + being-written. A blocked write stops fetching at the bound. Test pipeline_writes_in_order_within_its_budget covers this.

KDF. Decryption delegates to self_encryption::decrypt_chunk(chunk, encrypted, &src_hashes, 0) with original indices and neighbouring source hashes — same canonical KDF as the native path.

Manifest validation. Chunk list capped at 262 144 entries (~1 TiB). Reconstructed size must match declared size. src_size == 0 rejected per chunk. MAX_SAFE_JS_INTEGER bounds file size for JS.

AbortSignal. Cancellation::run selects against the abort channel; an aborted operation is dropped without running again. AbortListener detaches its listener on Drop.

Writer cleanup. Writer releases its lock on Drop. On pipeTo failure, abort is called and the promise is spawned (not awaited) so a stalled write does not block the rejection.

Test evidence (reported by author, CI-confirmed): 212 WASM tests including a 4,303,347,835-byte file through pipeTo with matching BLAKE3; 765 native tests; fmt + clippy green.

Caveats (non-blocking)

  1. "Real Chromium and local nodes" CI job fails on every PR (Rust 1.99 / pinned node; fixed by #217). Pre-existing, not introduced here.
  2. Production compatibility smoke and real-browser/live-network runs not yet done (noted in PR body).
  3. Root-map/index memory still grows with chunk count — documented as a residual limit in the ADR.
  4. close() no longer clears the shared chunk cache — documented behaviour change; cache is bounded at 32 MiB LRU.

ADR

ADR-0004 amended (2026-10-01). Status remains Proposed. The new "Large-file download destinations" section accurately describes the implementation. Validate ADRs and immutable Accepted status CI check passes.

mickvandijke and others added 11 commits October 13, 2026 11:22
Complete downloads fetched one 4 MiB range at a time, ignoring the
requested concurrency and restarting retry rounds per range. Reads are
now chunk-aligned: a shared engine primitive fetches a set of chunks in
one deferred retry pass and hands each decrypted chunk on as it
completes. Complete downloads use one pass over the whole file and copy
chunks into the JS output out of order, hashing in file order. pipeTo
fetches 32 MiB windows of whole chunks, so no chunk is decrypted twice.

- Restore "Downloaded chunk n/total" progress used by startup probes.
- Abort the destination for every pipeTo failure, including invalid
  options and a closed reader; do not abort after the final write.
- Add an AbortSignal option for per-operation cancellation; closing a
  reader cancels in-flight fetches and retry waits at once and evicts
  only its own records from the shared cache.
- Take download and pipeTo options as objects (legacy positional
  download arguments still work) and reject unknown option names.
- Accept DataMaps whose chunks exceed this build's MAX_CHUNK_SIZE, and
  cap manifest chunk lists at 2^18 entries.
- Build the file index once per resolution, keep no hex chunk list in
  readers, and remove the unused progress plumbing and expected hash.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
self_encryption::decrypt_chunk decompresses without an output limit, so
a crafted public DataMap could make a one-byte read expand a record to
gigabytes and abort the WASM instance. Chunks are now decrypted with the
same KDF, pad, cipher and Brotli steps, stopping one byte past the
declared size, and DataMaps may declare chunks of at most 16 MiB. A test
pins the output to decrypt_chunk.

pipeTo replaces per-window retry passes with an ordered pipeline: chunks
are fetched concurrently and written in order, fetching continues during
writes up to a 32 MiB buffer, and each missing record retries on its own
schedule so waits overlap.

- Poll cancellation before the operation so a closed reader or aborted
  signal never lets a dropped read finish or refill the cache.
- Keep download options optional in the generated typings and restore
  `>>> 0` coercion for the legacy numeric concurrency argument.
- Accept an AbortSignal for complete downloads, covering resolution.
- Hash out-of-order chunks between event-loop turns, copy chunks into
  the output without an intermediate buffer, and pass settings as a
  struct.
- Evict a closed reader's records by visiting only cached entries.
- Share one MAX_SAFE_JS_INTEGER, rename the safe-integer helper, keep a
  single owner for the empty chunk list, and fix a stale doc comment.
- Make the backpressure and memory-budget tests able to fail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Nested DataMap records were still decrypted by self_encryption without
an output limit, so a crafted public file could exhaust WASM memory
while resolving. Resolution now decrypts each level through the bounded
per-chunk path, and browsers cap each decoded level at 64 MiB. The
16 MiB chunk cap applies to browser reads only, so native range reads
accept any chunk size again.

- Do not await the destination's abort, so a stalled write cannot keep
  pipeTo from rejecting; let an AbortSignal cancel while the destination
  closes, but not closing the reader once every byte is written.
- Count open readers per file: the last close evicts the file's content
  and DataMap records, looked up by address instead of scanning.
- Content records are authenticated by decryption and their plaintext
  hash, so the engine no longer hashes them a second time; the per-chunk
  fetch reuses the shared deferred retry rounds.
- Decrypt in place, and yield read-back hashing on a time budget.
- Correct the docs' decompression claims.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ction

Nested DataMap resolution reserved and zero-filled the full size a level
declared before fetching anything, so a crafted map declaring terabyte
chunks could exhaust a native client's memory. Each chunk is now kept
once decrypted and the level is joined after every chunk verifies, and
chunk decompression grows with its actual output.

Closing a reader no longer evicts records from the shared cache. The
per-file reader count missed readers dropped without close() and evicted
records still used by readers of the same content opened another way;
the cache is bounded at 32 MiB and its LRU policy now releases records.

- Return a complete download's own output error (such as a JS
  RangeError) instead of reporting it as an encryption error.
- Derive Deserialize for the download result.
- Correct the manifest cap and test README descriptions, and cover the
  legacy null concurrency argument.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Reject zero-size nested chunks and saturate the decompression bound,
  so a crafted usize::MAX size cannot overflow in debug builds.
- Stop re-hashing records the fetch layer verified: decryption
  authenticates content and nested records, and self_encryption matches
  whole-file records by content hash. Correct the comment that said
  otherwise.
- Decode nested DataMap levels straight from their chunks with
  DataMap's bincode options, instead of joining them into a second copy.
- Fetch a single pipeTo chunk through the shared chunk pass rather than
  a duplicate, and keep MIN_FILE_CHUNKS with the KDF that needs it.
- Narrow the README/ADR claim: the legacy decryptPublicFile binding
  still decompresses without a limit. Fix the data_download_range doc.
- Name the fixture generator's literals and close test readers in
  finally blocks.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Read-ahead from main planned its windows over a usize RecordLayout,
which wraps at 4 GiB on wasm32. It now shares the reader's FileIndex, so
windows, anchors and recent read ends use 64-bit positions, and the
reader moved to download.rs takes reads through it again: readRange
borrows records read-ahead holds and stops read-ahead when records fail
to decrypt, and closing or dropping the reader releases them.

openPublicFile/openPrivateFile keep their streaming option. A DataMap
whose range reads reject, such as one with non-contiguous indices, now
fails to open instead of opening with read-ahead off, because the
reader validates its index when it opens; the test from main is updated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A review for over-engineering found about a third of the branch was
machinery beyond the ticket. This removes it:

- Decrypt chunks with self_encryption::decrypt_chunk again and resolve
  nested DataMaps with main's resolver, dropping the bounded decryption
  copy, the bincode resolver, the browser chunk and nested-map caps, and
  the bincode, chacha20poly1305 and brotli-decompressor dependencies.
  Bounding crafted-record decompression is left to self_encryption.
- Run complete downloads and pipeTo through one ordered stream: buffered
  fetches handed to the writer over a one-slot channel, holding at most
  32 MiB. This replaces ordered_pipeline, OrderedHasher and its read-back.
- Restore downloadPublicFile(file, concurrency?, onProgress?) with a
  trailing { maxMemoryBytes?, signal? }, removing the dual-type argument,
  its ToUint32 emulation and the unknown-option checks.
- Cancel only through an AbortSignal; close() makes later calls fail.
- Validate pipeTo options before taking the writer, so invalid calls
  leave the destination untouched, as ReadableStream.pipeTo does.
- Keep data_download_range's u64 path internal and make the complete
  download a free function that registers no read-ahead.
- Restore main's record verification and retry helpers unchanged.

The WASM mock re-entered WASM before copying an outgoing message, so a
large record store could grow memory and detach it; copy it first.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The buffered(n) stream that replaced ordered_pipeline stopped polling its
fetches whenever a chunk waited for the writer, and sized its concurrency
from declared chunk sizes alone, so a map of tiny chunks could start
tens of thousands of fetches. Restore ordered_pipeline, which polls
fetches while a write is pending, follows the client's adaptive fetch
cap and counts the chunk being written against the 32 MiB budget.

- The backpressure test now delays GETs and requires new ones while the
  first write is blocked, so a stalled stream fails it.
- Document that an abort during the destination's close may come after
  the commit, parse reader options like the other options objects, and
  share the download progress format.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The backpressure test now requires exactly the 32 MiB buffer of chunks
to be fetched behind a blocked write, which the stalled buffered stream
missed (3 of 8), and fails instead of hanging if pipeTo ends before its
first write. A unit test checks that ordered_pipeline keeps no more than
its cap in flight. Docs note that a record waiting to retry keeps its
place under the cap, and that a download's concurrency also limits it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@mickvandijke
mickvandijke force-pushed the feat/wasm-large-file-downloads branch from 1bc1931 to 16cb3b6 Compare October 13, 2026 09:24
…mium

large-file.mjs uploads the large-file fixture's plaintext natively to the
local devnet, under a throwaway home so it stays out of the upload history,
and checks it lands on the fixture's address. Real Chromium then reads across
4 GiB and pipes the whole file into the origin private file system, checking
the hash, stored size and bytes, progress and the memory-budget error. Not run
in CI: it needs about 5 GB of disk and a release ant binary.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Range reads, read-ahead, pipeTo and complete downloads index the root
DataMap with self_encryption's DataMapIndex (0.36.2) instead of an
ant-core copy of its chunk-index and key-derivation contract. The index
uses 64-bit positions on every platform, checks each decrypted chunk
against the size and source hash the map declares, and stops
decompression at the declared size.

Complete downloads no longer run through pipeTo's in-order stream. They
fetch every chunk as a native complete download does, within the
adaptive fetch cap and the caller's concurrency, retrying missing
records together in deferred rounds, and copy each decrypted chunk
straight into its place in the output as it arrives. The stream's
32 MiB bound had capped them at about eight fetches, and its per-chunk
retries added the waits of each missing record one after another. The
file is hashed afterwards, and progress again counts chunks as they
land.

A complete download also checks its AbortSignal before allocating the
output. Signals and destinations use the typed web-sys AbortSignal and
WritableStream bindings, so an EventTarget that is not an AbortSignal is
rejected. Safe-integer validation uses Number.isSafeInteger, and the
large-file fixture generator addresses its DataMap record with
compute_address.

The workspace temporarily patches self_encryption until 0.36.2 is
published.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@dirvine dirvine left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hermes paired review — provisional; hold merge gates

Reviewed #214 at 773ea5dac9b7c68efcf1f9c0a73a298e9fa46d3c with WithAutonomi/self_encryption#447 at e8aa39ee1337c11f52628356d97fa86ac0d1007d.

Code verdict: No new blocking code defect found in the inspected changes. I traced 64-bit range positions through the browser reader and read-ahead, chunk-index and source-integrity checks, ordered streaming with backpressure, shared-round complete-download retries, and AbortSignal/writer cleanup. This is not a claim that every browser or destination supports a large in-memory allocation.

Pre-merge gate: Publish self_encryption 0.36.2 from the reviewed companion change; remove the root temporary [patch.crates-io]; regenerate Cargo.lock against the registry release; rerun the native and generated-WASM checks. The dependency requirement is already 0.36.2, but the current lockfile resolves it from the Git patch. The crates.io version endpoint returned HTTP 404 during this review. This gate is acknowledged in the PR body, not a newly discovered code bug.

Checks I ran: cargo test --locked -p ant-core --lib passed all 819 tests. cargo fmt --all -- --check passed. The production browser-WASM build with browser-wasm,test-utils succeeded; the generated-WASM Node suite passed all 221 tests. The companion's full release suite passed 97 tests, with 1 ignored.

CI is not fully green: Security Audit failed on five quinn-proto vulnerabilities. I read the job log and compared every Cargo.lock package block against main: only self_encryption changed; quinn-proto remains 0.11.15 on both base and head. This is inherited security debt, not introduced by this PR. It still needs resolution or an explicit authorised risk decision; do not describe the check as passing. At the last head check, Ubuntu E2E Tests and Ubuntu Merkle E2E were still in progress.

Evidence limit: I did not independently run browser-tests/large-file.mjs, the opt-in real-Chromium/local-node upload and disk-streaming check above 4 GiB. Generated-WASM tests are not proof of that full path. The companion SDK and upload limits also remain outside this PR's stated scope.

Review-team participation: 1/3 completed. Qwen 3.8 (qwen38-27b) completed an independent paired review and found no new code blocker. GLM 5.3 (huggingface, zai-org/GLM-5.3) failed with HTTP 402/no credits. DS4 (deepseek-v4-flash) timed out. An earlier oversized panel was stopped without completed local opinions. No substitution or full consensus is claimed. This neutral review does not approve, merge or waive any gate.

@dirvine dirvine left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean re-review — provisional, not an approval

Reviewed head 773ea5dac9b7c68efcf1f9c0a73a298e9fa46d3c against main / merge base 9a2b6353a88207dd4d6ed99a5158c370531a7e09 in a detached, clean worktree. The paired self_encryption #447 review used head e8aa39ee1337c11f52628356d97fa86ac0d1007d.

Source verdict: no blocking defect introduced by this diff was confirmed. This is a COMMENT, not an APPROVE, and is not a merge-ready verdict.

Actual review participation and dissent

GLM 5.3 via OpenRouter (z-ai/glm-5.3) and local Qwen 3.8 (qwen38-27b) each completed independent correctness and adversarial reviews. DS4 (deepseek-v4-flash) timed out in both roles, including both bounded retries. Participation is 2/3 models, 4/6 seats. Reconciliation answers are not extra votes; full consensus is unavailable.

Qwen retained a possible AbortListener lifetime caution, while its reconciled verdict was PASS with caution. GLM requested inspection of manifest handling for shrunk DataMaps. I checked those concerns against source and executable tests below. These checks do not count as another independent review seat.

Source adjudication

  • Prefetch failure/retry concern: a failed held record goes into read_chunks and retry_data_fetch; it does not permanently prevent the normal on-demand retries. The existing WASM recovery regression passed.
  • Shrunk-map metadata concern: src/browser.rs:169–193 resolves the original/root DataMap before constructing chunks. src/browser/manifest.rs:173–203 validates the original plaintext chunk sizes and their total. The native shrunk-map download/range-read regression passed. The reviewed metadata path does not confuse child-map byte counts with whole-file byte counts.
  • Chunk-index panic candidate: reviewed internal callers derive chunk indices from the validated index/range. I did not establish an out-of-bounds input reaching this code through those paths. Optional Rust API hardening is separate from a confirmed browser-path defect.
  • Cancellation lifetime caution: AbortListener::drop removes the DOM listener before dropping its Rust closure on the JS thread. I added and ran three review-only WASM tests, each repeated six times: completed download followed by abort; abort from progress; abort during fetch. All 18 lifecycle operations left no registered abort listener; all 3 tests passed. I could not reproduce the claimed dropped-closure problem. This is bounded evidence, not proof of every real-browser event schedule.

Verification I ran

  • cargo test --locked -p ant-core --lib: 819 passed, 0 failed.
  • Fresh wasm-pack build --target web --release --no-default-features --features browser-wasm,test-utils: passed.
  • All repository generated-WASM Node tests: 221 passed, 0 failed, 0 skipped.
  • Additional review-only cancellation checks: 3 passed, 0 failed; counted separately from the 221 repository tests.
  • cargo fmt --check: passed.
  • Latest head check: unchanged; 21 CI checks succeeded and Security Audit failed. There are no pending checks in that snapshot.

Outstanding integration gates

  1. Published dependency: the crates.io self_encryption/0.36.2 endpoint still returns 404. After #447 lands and that version is published, remove this PR's temporary root [patch.crates-io] override and regenerate/verify Cargo.lock against the published release. The present local/CI results use the pinned companion revision, not an independently available crates.io release.
  2. Security Audit: CI reports five vulnerabilities in quinn-proto 0.11.15: RUSTSEC-2026-0338, RUSTSEC-2026-0339, RUSTSEC-2026-0340, RUSTSEC-2026-0341 and RUSTSEC-2026-0342. The full quinn-proto lockfile entry is identical on the merge base and head, so these are inherited, not introduced here. They still need resolution through the normal security/merge process; this review does not waive the failed check. Audit output.
  3. Real-network evidence: I did not independently run a production-node compatibility smoke or a real-browser/live-node download-to-disk test above 4 GiB. Passing generated-WASM/mock transport tests do not establish those results.

No merge, dependency edit, deployment or release action was taken. This is Hermes's provisional technical assessment, posted through the authenticated GitHub account, not a human sign-off.

@jacderida
jacderida merged commit e3893cb into main Oct 14, 2026
18 of 19 checks passed
jacderida added a commit that referenced this pull request Oct 15, 2026
Brings in #214, #218, #227 and #181. Two things needed a hand:

- Cargo.toml: main removed its temporary self_encryption [patch.crates-io]
  entry when 0.36.2 was published; this branch's ant-protocol pin in the same
  section stays (rev 718f6068, unchanged).
- ant-core/src/data/error.rs: #218 added Error::duplicate(), an exhaustive
  match; arms for this branch's PointerFinal and PointerForked are added,
  cloning the message like every other String variant.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants