Files
vnidrop/crates/vnidrop/AGENTS.md
Hammed Abass ff8e046cf7 docs: rewrite AGENTS.md to agents.md / Codex style
Make agent instructions imperative and command-first, add nested
crates/vnidrop and shared guides, and keep compose-skill as the UI
source of truth with VniDrop-specific overrides.
2026-07-12 20:26:31 +02:00

4.0 KiB

AGENTS.md — crates/vnidrop (Rust core)

Nearest guide when editing under crates/vnidrop/. Root AGENTS.md still applies; this file wins for Rust-specific commands and conventions.


Purpose

This crate is the transfer backend exposed to Kotlin via UniFFI (VnidropCore). It owns Iroh, blobs, SQLite history, tickets, approval handshake, and file streaming.

Read CORE_FLOW.md before changing send/receive/export/cancel.


Commands (run from repo root)

Always prefer workspace commands so lockfile/fmt stay consistent:

cargo fmt --all
cargo fmt --all -- --check
cargo clippy --workspace --all-targets -- -D warnings
cargo test -p vnidrop
cargo test --workspace --all-targets

Focused integration suites:

cargo test -p vnidrop --test transfer
cargo test -p vnidrop --test approval
cargo test -p vnidrop --test lifecycle
cargo test -p vnidrop --test output_sink

Docs (CI uses -D warnings):

RUSTDOCFLAGS='-D warnings' cargo doc -p vnidrop --no-deps

Run cargo fmt --all after finishing Rust edits without asking.


Module layout

src/
  runtime/
    mod.rs        # CoreInner, startup recovery, emit helpers
    facade.rs     # UniFFI surface, block_on, cancel entry
    share.rs      # share / import
    receive.rs    # receive, download, export, OutputSinkFile
    lifecycle.rs  # cancel share, delete, status, access mode, shutdown
    provider.rs   # provider messages, per-peer transfer progress
  filesystem.rs   # collect sources, atomic publish, path rules
  repository.rs   # SQLite
  approval.rs / handshake.rs / ticket.rs / access_policy.rs / event_hub.rs
  api.rs          # UniFFI records/enums
  tests/          # crate-private unit tests
tests/            # public-API integration tests + support/

Do not reassemble a single huge runtime.rs. Prefer new focused modules if a file approaches ~800 LoC of non-test code.


Hard constraints

  1. Public API stability: UniFFI surface changes break Kotlin. Prefer additive changes; update shared Kotlin call sites in the same change when required.
  2. Streaming stays in Rust. Platform passes paths or FDs; core does not pull whole files into Kotlin.
  3. Android FDs are files only. SourceKind::FileDescriptor with is_directory=true must fail; directories are expanded on the platform side.
  4. Cancel: signal active-transfer oneshot synchronously before async DB work. Use existing take_active_transfer / facade cancel path. Do not reintroduce nested exclusive Runtime::block_on deadlocks.
  5. No lock across await: Clippy await_holding_lock fails CI.
  6. ReceiveOutputSink: after successful start_file, exactly one of finish_file or abort_file (see OutputSinkFile Drop).
  7. No-overwrite publish for path receives (temp + hard link / exclusive rename).
  8. Integration tests must use the public API + tests/support/ only.

Code style (Rust)

  • Clippy clean with -D warnings.
  • Prefer exhaustive match; avoid catch-all arms that hide new enum variants.
  • Prefer comparing whole objects in tests when practical.
  • Comment only non-obvious why (concurrency, durability, platform FS quirks).
  • Do not add one-off private helpers used once if inline is clearer.
  • Prefer private modules; export deliberately via lib.rs / UniFFI.

Testing

  • Unit / private: src/tests/ (see crate tests.rs paths).
  • Integration: tests/*.rs + tests/support/mod.rs (TestNode, MemoryOutputSink, CoreGuard, etc.).
  • Bug fixes need a regression test.
  • Prefer gates/latches over multi-second sleeps (see output_sink cancel test).
  • Failure tests: durable status and/or events when applicable.
  • Recovery tests: shut down core, reopen same data dir.

Details: tests/README.md.


PR / verify checklist for this crate

cargo fmt --all -- --check
cargo clippy --workspace --all-targets -- -D warnings
cargo test -p vnidrop

If you touched cancel, export, or sinks, also:

cargo test -p vnidrop --test output_sink