ADR-013 — Miner distribution policy: standalone, never bundled, never in a browser
- Status: Accepted
- Date: 2026-10-10
- Related: ADR-006 (founder-mining disclosure; both miners released
publicly with no hidden speed edge), audit 2026-09-22 finding B2 (checksum drift), audit 2026-10-03 (supply chain is the real risk; moonbite-wallet.exe tracked next to the miner), infra audit 2026-10-09 L5 (release authenticity integrity-only), deploy/RELEASE-SIGNING.md.
Context
MoonBite is a CPU-mined proof-of-work coin. Its miner is the full node (moonbited) driven by a small script that calls generatetoaddress over loopback RPC. The wallet is a separate program that handles keys and never mines. Both are distributed as downloads from moonbite.org and GitHub Releases.
Three pressures act on how these are packaged:
1. User trust. A download that quietly installs a miner next to a wallet, or a wallet that turns out to use the CPU, is indistinguishable from cryptojacking malware. The project's credibility rests on the miner being something the user explicitly chose, started and can see running. 2. Antivirus heuristics. A RandomX miner is, behaviourally, what AV engines are tuned to catch: a JIT writing and executing memory, several gigabytes of RAM, every core saturated for hours, from an unsigned binary almost no one has seen. Every additional suspicious trait (packer, self-extraction to %TEMP%, auto-start, downloading code) compounds the score. 3. Pseudonymity. The project is run under a pseudonym with no legal entity. Authenticode OV/EV certificates and Apple Developer ID notarization require a verified legal identity. That path is closed until an entity exists, so provenance has to come from somewhere else.
Until this ADR, release/miner/ in the repository held moonbite-wallet.exe next to moonbited.exe, the PyInstaller spec for the desktop wallet used UPX and the build docs recommended --onefile, and the Windows launcher invoked PowerShell with -ExecutionPolicy Bypass.
Survey: is there any browser mining?
static/ and templates/ were searched for WebAssembly, .wasm, new Worker, importScripts, SharedArrayBuffer, hashcash, cryptonight and coinhive. There are no matches. static/mining-god.js draws a particle field and a sparkline from a synthetic, Math.random-jittered "hashrate"; it performs no hashing and talks to no node. The only RandomX strings in templates/ are prose describing the algorithm. The site-side /api/mining/* endpoints and the /start page are a demo surface, and release/miner/README.md already says so. Conclusion: no browser mining exists anywhere in the web app, and this ADR forbids adding any.
Decision
1. The miner is never bundled with the wallet, and the wallet never carries a miner. Two archives per platform, from two source directories:
| Archive | Contents | Source |
|---|---|---|
moonbite-miner-<os>-<arch>.{zip,tar.gz} | moonbited, moonbite-cli, mine.ps1/Mine-MoonBite.bat or mine.sh, README.md, ANTIVIRUS.md | release/miner/ |
moonbite-wallet-<os>-<arch>.{zip,tar.gz} | the wallet app, README.md | release/wallet/ |
deploy/miner/build-windows-bundle.py refuses to build an archive whose member list crosses the line. moonbite-wallet.exe moves from release/miner/ to release/wallet/. 2. The miner never runs in a browser. No WebAssembly, Web Worker or server-side mining-on-behalf-of-the-user is ever added to the site. Any visual on the site that resembles mining is labelled a demo and performs no proof-of-work. Real mining is a native node process the user starts. 3. Standalone download, started by the user, running only while the user keeps it running. No installer, no auto-start entry, scheduled task, service, cron job or login item is created by anything in a user download. Operator tooling that does install persistence on seed/explorer hosts (install-autostart.sh) is gated behind an explicit --i-am-the-operator flag and root, and is not shipped to users. 4. No runtime packers and no self-extraction. upx=False in every PyInstaller spec; one-directory builds, never --onefile; no obfuscation, no bytecode cipher. The node binaries are plain mingw/gcc output, stripped of debug symbols only. 5. No self-update and no downloading. The miner scripts and the Python miner never fetch, write or execute code. Updates are a new release the user downloads and verifies. 6. No privilege and no security-setting changes. The scripts never request administrator or root rights, never add Defender exclusions and never override the PowerShell execution policy. The .bat wrapper calls powershell -NoProfile -File mine.ps1 and, if the policy blocks it, explains the user-scope Set-ExecutionPolicy -Scope CurrentUser RemoteSigned plus Unblock-File so the choice is the user's. 7. Every launcher prints the SHA-256 of the binaries it is about to run and points at the published SHA256SUMS.txt. 8. A full Windows version resource (CompanyName "MoonBite Labs", FileDescription, ProductName, FileVersion matching the release tag) is embedded in PyInstaller builds via windows-version-info.txt. 9. Signed where identity allows; attested and reproducible everywhere.
SHA256SUMS.txtfor every archive and every executable inside it,
generated by the build from the artifacts, never hand-typed; verified in CI by deploy/verify-release-checksums.py.
- A minisign signature over the manifest with the key in
deploy/moonbite-release.pub (key ceremony per deploy/RELEASE-SIGNING.md).
- GitHub build-provenance attestations (Sigstore) for CI-built archives,
verifiable with gh attestation verify.
- Deterministic archives (fixed member order, fixed timestamps, fixed
compression) and documented build inputs so a third party can rebuild and compare.
- Authenticode and Apple notarization are adopted the day a legal entity
exists to hold the certificate. Until then codesign_identity=None and skip_notarization=True are stated in the spec rather than faked with a self-signed certificate, which buys nothing with SmartScreen and looks like evasion. 10. AV vendor submissions each release. Every new executable is submitted to the major vendors' false-positive portals as part of the release checklist, and users are given the same list in release/miner/ANTIVIRUS.md together with the reasons a legitimate RandomX miner trips heuristics.
Amendment 2026-10-15: the launcher bypasses the execution policy for itself
Item 6 is changed for Mine-MoonBite.bat only, by the owner's decision. Most Windows 11 PCs ship with the Restricted execution policy, which blocks every script, signed or not, and downloaded scripts also carry the "from the internet" mark. In practice the double-click launcher failed for nearly every new miner, who then had to type policy commands first. Signing does not solve it (a signed script is still blocked under Restricted), and the signing routes open to a pseudonymous project are uncertain (SignPath Foundation, applied for separately).
The launcher now runs powershell -NoProfile -ExecutionPolicy Bypass -File mine.ps1. The bypass is scoped to that one process and that one script next to the launcher; no policy, registry key or other setting changes, and the scripts still never request administrator rights or touch Defender. The cost named in the rationale below stands: antivirus engines score this line, so the launcher may be flagged more often. ANTIVIRUS.md and the per-release AV submissions remain the mitigation. Running mine.ps1 directly still obeys the user's policy.
Rationale
- Separation is the only way to make "we did not put a miner on your
machine" provable: a user who downloaded the wallet can open the archive and see that no node binary is present. Bundling for convenience would save one download and cost the project its clearest honesty signal.
- Browser mining is either theatre (a page cannot run RandomX at a useful
rate) or abuse (using visitors' CPUs). Neither is acceptable for a coin whose premise is that the user's own machine mines for the user.
- Each AV-hygiene item removes a trait that the engines score, so the only
remaining signal is the one the miner cannot avoid: it is a miner. That residual is addressed by documentation and vendor submissions, not by asking users to lower their defences.
-ExecutionPolicy Bypassis the most common line in malicious batch
droppers. Even though the policy is not a security boundary, shipping the bypass trains users to accept it and gives engines a reason to flag the wrapper.
- The pseudonymity constraint is real and is stated rather than worked
around. Checksums prove integrity, minisign proves the manifest came from the project key, attestations prove which commit and workflow produced the file, and reproducibility lets anyone check that the commit produces the file. Together they are stronger provenance than an OV certificate bought by a shell company; what they do not buy is SmartScreen reputation, and the user-facing documents say so plainly.
Consequences
- Two download buttons and two archives per platform;
web_app.py's
_MINER_BUNDLES["wallet"] currently serves a bare moonbite-wallet.exe and should move to the moonbite-wallet-windows-x86_64.zip name when the web route owner next touches it.
- Desktop-wallet builds are larger (no UPX, one directory). Acceptable.
- Users on a default Windows execution policy see one explanatory message the
first time instead of a silent bypass; the README documents the two user-scope commands.
- Release checklist grows: build both archives, regenerate and sign
SHA256SUMS.txt, confirm attestations, submit executables to AV portals, bump windows-version-info.txt with the tag.
install-autostart.shnow exits with an explanation unless invoked with
--i-am-the-operator as root.
- Any future proposal to embed mining in the wallet, the site or a browser
extension requires superseding this ADR, not amending it.