emulebb-rust is the active experimental Rust eD2K/Kad client in the eMuleBB
organization. It owns the Rust-forward /api/v1 contract, runs as a headless
daemon, and serves the embedded browser SPA WebUI from packaged static assets.
It keeps local client state plus indexing data in SQLite.
This is a Rust-native successor to the Windows eMuleBB MFC fork, not a line-by-line port or an MFC REST-contract mirror. Stock/community eMule peers are the primary wire-compatibility target. The separate maintained aMule client is a cross-platform source and offline-fixture reference in this workspace.
The repository began from earlier Kad and ED2K work, but it is intentionally a
local client product. The 0.1.0-beta.2 line does not expose a coordinator API.
Public beta:
rust-v0.1.0-beta.2is published for Windows, Linux, and macOS. The release decision and retained evidence are tracked in RUST-BUG-101 / issue 19.
Nightly beta channel: Automated builds from
mainare enabled. A scheduled run publishes a new prerelease only when the exact commit has passed normal CI and differs from the previous nightly. See Nightly beta builds for downloads, container tags, versioning, and generated changelog details.
Rust development uses the exact toolchain declared in rust-toolchain.toml.
Update that pin, the workspace rust-version, and CI together in a dedicated
toolchain commit after each stable Rust release has passed the full quality
gate; normal development must not float independently on stable.
The 0.1.0-beta.2 scope is eD2K/Kad protocol-operational parity: configured binding,
interoperability, search, sharing, transfers, uploads, queues, persistence,
local SQLite/FTS indexing, REST controller visibility, and embedded SPA WebUI
operation. Local API, UI, settings, diagnostics, and scheduling surfaces are
Rust-native async daemon design. Broadband-oriented async IO is the default
runtime model, not a compatibility toggle.
Active product docs, backlog, design notes, release scope, and the Rust OpenAPI
contract live in
EMULEBB_WORKSPACE_ROOT\repos\emulebb-tooling\docs\products\emulebb-rust.
The repo-local docs directory is only a pointer.
New contributors should start with CONTRIBUTING.md and the
public eMuleBB Roadmap. The beta
is published; new work should be scoped through the normal issue and validation
process rather than the former pre-release freeze.
emulebb-daemon: CLI, config, logging, and REST listener.emulebb-rest: Rust-native/api/v1routes, envelopes, and API-key auth plus the packaged browser WebUI static surface.webui: embedded Vite/Preact SPA WebUI packaged beside the daemon.emulebb-core: local app state, capabilities, searches, and transfer summaries.emulebb-index: SQLite + FTS5 local file index plus Kad harvest/store scheduling components.emulebb-kad-*: copied and renamed Kad protocol/runtime crates.
Indexing is a client capability, not a separate public API. It improves search results returned through the eMuleBB search resources.
The former native Slint client has been removed. The supported product shape is
the headless daemon plus its REST API and embedded SPA WebUI; release cleanup
still rejects stale emulebb-rust-ui artifacts from older build directories.
The Rust client is multi-platform by tiered proof: Windows, Linux, and macOS must stay compile/test viable where practical, while platform runtime claims require smoke or live evidence for that platform. Platform-specific behavior belongs behind narrow adapters.
The protocol surface is IPv4-only and stock-compatible for implemented eD2K and
Kad behavior. Historic or niche behavior may be omitted only when it is recorded
in policy/rust-client-omissions.toml, is not advertised on the wire, and does
not change the semantics of supported stock interactions.
Rust source is split by subsystem and responsibility, not by a mechanical line
limit. Substantial tests stay outside production modules; small white-box tests
may remain beside private helpers when proximity improves understanding. The
authoritative rules live in
EMULEBB_WORKSPACE_ROOT\repos\emulebb-tooling\docs\products\emulebb-rust\reference\CODE-QUALITY.md.
The policy checker reports maintainability signals as advisories while retaining
hard failures for objective protocol, omission, binding, and release-safety
violations. Normal CI also validates every GitHub Actions workflow with a pinned
actionlint revision so expression and context errors fail before release use.
Run the local policy guard before policy-sensitive protocol or architecture changes:
python tools\rust_quality_gate.py policyRun the build gate after code changes. It runs normal Cargo debug and release
builds for the daemon, builds the release diagnostics binary, and stages freshly
copied release executables under
%EMULEBB_WORKSPACE_OUTPUT_ROOT%\tools\emulebb-rust\bin. The browser WebUI is
staged beside the executable as webui.
python tools\rust_quality_gate.py buildRun the WebUI test gate after embedded SPA changes. It installs the locked npm
dependencies, runs Vitest unit tests, runs the stateful Playwright Chromium
suite, checks types, and verifies the production Vite build. The release
orchestrator stages all generated npm/test/build content below
EMULEBB_WORKSPACE_OUTPUT_ROOT:
Push-Location ..\emulebb-build
python -m emule_workspace test rust-webui
Pop-LocationUse --force-rebuild only when intentionally clearing Cargo state, for example
after a toolchain or native dependency investigation.
Compatibility proof for this line is local and deterministic first: Rust to Rust, stock-compatible eD2K/Kad interop witnesses, and REST conformance against the Rust OpenAPI contract. Public-network diagnostics may use a direct connection; VPN use is optional. An explicit interface bind is fail-closed, but the beta does not claim native VPN leak safety without separate platform proof.
Run the daemon directly or pass --profile <dir>. Without --profile, the
daemon creates a local-only profile under $XDG_CONFIG_HOME/emulebb-rust on
Linux (falling back to ~/.config/emulebb-rust), the platform application-data
directory on Windows, or ~/Library/Application Support/emulebb-rust on macOS.
It prints the generated WebUI API key on first launch. An explicit profile must
already contain emulebb-rust-settings.toml; its SQLite repository is
emulebb-rust-metadata.db. The TOML file is control-plane bootstrap only: REST
bindAddr is required there, while runtime/network settings live in the
database and are exposed through /api/v1/app/settings.
apiKey is also required. Startup rejects blank, known placeholder,
whitespace-padded, non-printable, and shorter-than-32-byte values. The implicit
first-run profile generates a 32-character random key and, on Unix, creates the
profile directory and bootstrap file with modes 0700 and 0600. Existing
Unix bootstrap files with group or other access are rejected with a chmod 600
remediation message because the file contains the REST credential.
The daemon serves plain HTTP. Keep direct listeners on loopback whenever possible. A non-loopback listener is intended for a container network or a trusted TLS reverse proxy and emits a startup warning; independently restrict host/firewall exposure. The WebUI keeps its API key in per-tab session storage, so closing the tab clears the browser copy.
GET /healthz is an unauthenticated operational readiness probe outside the
versioned /api/v1 contract. It returns an empty 204 only while the daemon is
running and 503 during graceful shutdown; it exposes no profile, peer,
network, or credential data. The OCI image uses this loopback-only probe for its
built-in healthcheck.
The beta settings contract has one owner for each upload scheduling input. The
following former ed2k.uploadQueue fields are no longer accepted; update saved
API payloads or profile automation to use their core equivalents:
| Removed field | Replacement |
|---|---|
ed2k.uploadQueue.activeSlots |
core.maxUploadSlots |
ed2k.uploadQueue.elasticPercent |
core.uploadSlotElasticPercent |
ed2k.uploadQueue.uploadLimitBytesPerSec |
core.uploadLimitKiBps |
ed2k.uploadQueue.elasticUnderfillBytesPerSec |
core.uploadClientDataRate |
ed2k.uploadQueue.waitingCapacity |
core.queueSize |
The two rate replacements use KiB/s, while the removed fields used bytes/s. Because this is a beta contract cleanup, stale fields are rejected as unknown rather than silently migrated. Fresh profiles use a 5-second drained/zero-rate grace and a 30-second accumulated slow-rate grace after a 30-second warm-up.
Regular daemon builds log INFO and above by default to the console, the
bounded GET /api/v1/logs buffer, and daily JSON Lines files under
<profile>/logs. The file logger retains the newest eight files. If its
directory cannot be created or opened, startup continues with console and REST
logging and reports a warning there.
Set RUST_LOG to change all three outputs together. Standard tracing filter
directives are supported, for example RUST_LOG=warn or
RUST_LOG=info,emulebb_core=debug. The REST buffer keeps the newest 2,000
entries and truncates individual rendered messages at 4 KiB; clearing the REST
buffer does not delete the retained files.
When an enabled server list or persisted Kad bootstrap file is empty, startup
downloads and validates the same trusted defaults used by eMuleBB MFC. Existing
server data and non-empty nodes.dat files are never replaced. An offline or
failed bootstrap does not prevent the daemon and WebUI from starting.
The daemon serves the browser WebUI from a webui directory beside
emulebb-rust.exe when that directory exists. Set [rest].webRootDir to an
explicit asset directory to override that default; relative override paths are
resolved from the profile directory. The WebUI is mounted at the REST origin
root: primary views use clean history paths such as /transfers and selected
search sessions use /searches/<id>, while production assets are served from
/assets. Reverse-proxy subpath mounting is not part of the current deployment
contract. Browser API calls use the existing X-API-Key header.
Harnesses may use operator-local inputs to create the profile directory and write those fixed files, but the Rust client itself only consumes the profile.
Report suspected vulnerabilities privately; do not place credentials, private
peer data, or exploit details in a public issue. Supported versions, the private
reporting link, and response expectations are in the security policy.
Committed CodeQL analysis covers the Rust daemon, browser WebUI, Python release
tooling, and GitHub Actions workflows on every main change and on a weekly
schedule using the extended security query suite.
The public release notes, changelog, and release scope are the version-specific operator and compatibility references.
The manual release workflow retains candidate
artifacts for Windows, Linux, and macOS on x64 and ARM64. Native ZIP,
DEB/AppImage, and app-in-DMG packages include the daemon and browser WebUI. It
also builds and smoke-tests a Linux amd64/arm64 OCI image without publishing it.
The container base is digest-pinned, and both variants must pass a scan for
fixable high or critical vulnerabilities. Per-platform SPDX JSON SBOMs, scan
reports, and their checksums are retained and attached to a published release.
An approved rust-v0.1.0-beta.2 tag is required to publish versioned GitHub
Release and GHCR assets; the workflow does not publish a latest image.
The scheduled nightly workflow runs daily at
02:17 UTC, with a 05:47 UTC fallback because GitHub schedules are best-effort.
It considers the latest main commit, verifies that the normal CI checks passed
for that exact SHA, and skips publishing when that commit already has a nightly,
so the fallback does not duplicate a successful publication. A manual run builds
candidates without publishing unless the operator explicitly enables its
publish input.
Published nightlies appear as prereleases on the GitHub Releases page. Each one has an immutable version and tag derived from the promoted beta, date, and source commit:
0.1.0-beta.2.nightly.YYYYMMDD.g<8-character-commit>
rust-v0.1.0-beta.2.nightly.YYYYMMDD.g<8-character-commit>
Nightlies use the same Windows, Linux, macOS, x64, ARM64, and
multi-architecture container matrix as a formal beta. Download the native
package for the target platform from its prerelease. Container users can pin
the immutable ghcr.io/emulebb/emulebb-rust:<version> tag or follow the moving
ghcr.io/emulebb/emulebb-rust:nightly tag. The workflow never publishes a
latest tag, and formal betas remain version-only.
The small changelog on each nightly is automatic. It groups commit subjects
since the previous successful nightly into Added, Fixed, Changed, and
Engineering, links every listed commit, and includes the full GitHub source
comparison. It also compares the current-only metadata schema with the previous
successful nightly and explicitly calls out when a fresh profile is required.
No separate nightly changelog needs manual maintenance. Clear commit subjects
therefore produce better release notes; see
CONTRIBUTING.md.
Verify downloads against the published SHA256SUMS; GitHub build-provenance
attestations are also published. The newest 14 nightly prereleases are retained,
so use an immutable version rather than the moving container tag when
reproducibility matters.
The image uses LinuxServer's s6 base and supports PUID/PGID, /config for
profile state, and /data/ed2k for completed downloads. It serves the WebUI
and REST API on port 4711. The optional
Gluetun Compose example uses
an independent tunnel and read-only operator credentials; it binds Rust P2P to
tun0 through EMULEBB_RUST_P2P_INTERFACE. It is not a requirement for direct
internet beta testing and does not alter an existing P2P Compose stack.
The emulebb-rust workspace is licensed under GPL-2.0-only. Third-party
components retain their own licenses; see THIRD-PARTY-LICENSES.md for the
dependency policy and required notices.