ZTORRENT-CORE // ENGINEERING REPORT

// module map · command surface · FFI exports · test status

Home Port Report Source
0.1.3version
35modules
96engine commands
343tests (301 Rust + 42 webui)
96.5%Transmission coverage
76.7%cross-client coverage

Module map

ModuleOwns
libThe Engine, the dotted command surface, Transmission-shaped torrent rows, engine events
model · storePersisted torrents, queue order, labels, per-torrent limits and seeding rules, per-file flags; atomic JSON writes
settingsTransmission’s session keys under their wire names, partial-merge semantics, effective speed limits
queueWhich torrents may run: download/seed slots, stalled detection, bandwidth-priority ordering, queue moves
seedingRatio and idle stop rules across the three Transmission modes (global / per torrent / unlimited)
schedulerTurtle-mode time windows, including overnight windows and the weekday bitfield
forecastThe horizon simulated slot by slot — the schedule resolved for each wall-clock moment, then queue::plan, allocation::split and seeding::should_stop called against a simulated snapshot, so a finish time accounts for the turtle window, the queue and the ratio limit that a bytes-left / current-speed ETA cannot see
category · rssCategories with save paths and their own limits, subcategory inheritance and auto-TMM (qBittorrent); RSS feeds with the auto-download rule engine, episode filters and a one-release-per-episode guard (qBittorrent / µTorrent / Deluge)
blocklist · watchdir · groupsP2P-plaintext / CIDR rules as merged sorted ranges; watch-dir polling that waits for a file’s size to settle; coloured auto-assign groups
verify · trackerThe engine’s own payload re-hash, and HTTP/UDP tracker announces with per-tracker seeders, leechers, interval and failure text
log · power · natpmpThe capped message log; the wake lock held while a torrent transfers (IOKit on macOS, SetThreadExecutionState on Windows); and NAT-PMP port mapping (RFC 6886) beside the wire layer's UPnP
bencode · metainfo · create · magnetSpan-preserving bencode, .torrent read/write, piece hashing, magnet parse/build
sessionThe wire boundary (a vendored librqbit fork): session options, add/pause/resume/remove, stats, peers, piece map, file order
rpc · rpcserverTransmission RPC method translation, and the HTTP listener that serves it: CSRF session id, Basic auth, wildcard whitelist, optional web root, optional TLS from a .p12 bundle or a PEM pair, and partial-file streaming over HTTP ranges so a player can start on a torrent that is still downloading
ffi · tauri_pluginThe C ABI (ztr_invoke) and the Tauri command/event bridge
viewsSaved views — named condition sets with and/or and their own sort order (rTorrent’s custom views)
prealloc · allocationSpace reserved before a download starts at Transmission’s three levels (off / fast-sparse / full via F_PREALLOCATE or fallocate); the weighted split of the global cap, where a torrent’s own limit caps its share and the remainder is redistributed (Tixati)
mailAn SMTP client (RFC 5321/4954/3207) — STARTTLS, implicit TLS or cleartext, AUTH PLAIN, dot-stuffing — that emails on download completion, with a test-message command
deadline · obligationCompletion-deadline admission control over forecast — feasible / repaired / infeasible with the settings changes that make a set of due dates hold; and seeding-obligation discharge, which projects each torrent’s ratio-or-time debt to a tracker forward to the moment it is paid
commands · errorThe sorted command list the GUI palette enumerates, drift-guarded by a test against Engine::invoke’s match arms; the error envelope every surface returns

Dependency footprint

CrateWhy
serde · serde_jsonThe JSON command surface and every persisted file
thiserror · dirsThe error envelope; platform data directories
sha1 · hexInfo-hashes and piece hashing (format layer, present in the pure build)
librqbit · tokio · url · anyhowThe wire half, behind the net feature: peers, HTTP/UDP trackers, DHT, magnet metadata, UPnP
tauriOptional, for hosts that mount the engine as app commands

Bencode, the metainfo reader/writer, magnet handling and the whole policy layer are written here rather than pulled in, which is why --no-default-features builds and tests with no sockets, no TLS and no async runtime.

FFI surface

ExportContract
ztr_initInitialize the process-global engine and wire its event sink; returns {"ok":true} or an error envelope
ztr_invokeOne command + JSON args → JSON result or {"error":{"tag","message"}}
ztr_commandsThe command list as JSON, so a host builds its menu from the ABI rather than a hardcoded copy
ztr_set_event_callbackInstall a C callback for engine events; the JSON pointer is valid for the call only
ztr_string_freeRelease any string this ABI returned

Test status

301 Rust tests pass on the default (net) build and 288 on --no-default-features — the difference is the wire modules’ own unit tests, including a listener that answers over a real loopback socket. The webui carries 42 headless tests (a DOM shim plus a recording engine bridge) that assert the scaffold, the boot command sequence, that every call goes through the ztr_invoke bridge, and that the view feeds the host shell without binding a global key. A drift guard reads Engine::invoke’s own source and fails if the published command list and the accepted commands disagree.

Known gaps

Nothing is missing outright any more. Six rows are partial, each for a stated reason: peer-connection encryption (MSE/PE) and BitTorrent v2 transfers are protocol work the wire layer has not done; a global peer cap does not exist there (it caps per torrent); the .part suffix needs a storage-layer rename the trait has no hook for; the disk-cache setting lost its home when the wire layer dropped its deferred-write buffer — the audit caught that stale claim and downgraded it; and sleep prevention on Linux needs a session-bus inhibitor. Every row is generated from a hand-assessed manifest and audited against the source, which is how that stale claim surfaced.