morphit/MORPHIT-BRAG-LIST.md

112 KiB
Raw Permalink Blame History

The Morphit Brag List

Why a peer-to-peer fiat ↔ Bitcoin / Monero / Blurt / USDT / USDC / DAI / Bitcoin Cash / Litecoin / Dash / Dogecoin / Zcash / Pirate Chain / Decred / Solana / Ethereum / Ripple marketplace that's actually non-custodial, actually no-KYC, and actually federated beats every centralized exchange and every fake "DEX" that calls itself decentralized.

A reference list of 300+ specific things Morphit does — privacy, security, decentralization, Monero-friendliness, anti-Sybil economics, operator independence — written for sharing, citing, and arguing with.

Keywords: peer-to-peer crypto exchange, P2P Bitcoin marketplace, P2P Monero marketplace, P2P Bitcoin Cash marketplace, P2P Litecoin marketplace, P2P Dash marketplace, P2P Dogecoin marketplace, no-KYC exchange, non-custodial DEX, federated marketplace, Blurt, USDT P2P, USDC P2P, DAI P2P, BCH P2P, LTC P2P, DASH P2P, DOGE P2P, ZEC P2P, ARRR P2P, Pirate Chain, DCR P2P, Decred, Politeia, hybrid PoW PoS, CoinShuffle++, SOL P2P, Solana, Proof-of-History, high-throughput PoS, ETH P2P, Ethereum, The Merge, EIP-681, EIP-55, post-Merge PoS, Blockscout, XRP P2P, Ripple, XRPL, XRP Ledger, Federated Byzantine Agreement, FBA, destination tag, UNL, Unique Node List, XRPL reserves, Xaman, Xumm, Crossmark, livenet.xrpl.org, Zcash, zk-SNARKs, shielded transactions, Sapling, Orchard, Unified Address, shielded-by-default, MakerDAO, Circle USDC, Tether USDT, PrivateSend, CashAddr, Litecoin bech32, Litecoin MWEB, Dash PrivateSend, Dogecoin merge-mined, Monero subaddress, amount jitter, view key privacy, AGPL crypto exchange, censorship-resistant trading, Tor onion service, I2P b32 service, Lokinet, Nostr, GrapheneOS, decentralized orderbook, on-chain reputation, end-to-end encrypted chat, on-chain chat ciphertext, STRIDE threat model, reproducible build, multi-explorer attestation, mempool.space, xmrchain.net, blockchair.com, sock-puppet detection, Sybil-resistant, privacy guides, kycnot.me


Table of Contents

  1. Free, fast, and friction-free
  2. Privacy by design (not by promise)
  3. Security and audits — receipts, not slogans
  4. Real decentralization, not the marketing kind
  5. Non-custodial, honestly
  6. For Monero users specifically
  7. For Bitcoin users specifically
  8. Reputation, trust, and chat that survives the platform
  9. Anti-spam and anti-Sybil (without surveillance)
  10. Open source and transparent (with receipts)
  11. Internationalization done right
  12. Pro-Monero culture, not just compatibility
  13. Honest comparisons (CEX, fake DEX, P2P)
  14. What Morphit deliberately does NOT do
  15. Reach: every device, every network
  16. Built-in tools — block explorer, activity stats, payment QR codes
  17. Trade anything — barter, cash, precious metals
  18. Operator setup — even your grandma can run a node

1. Free, fast, and friction-free

  1. Signup is free to the user. No credit card, no bank link, no fee, no deposit. The operator's relay account creates your account on-chain with a direct account_create op, paying the ~100 Blurt chain account-creation fee for you — so you join cost-free. (See ADR-0010 §4 for the key-custody rationale.)

  2. No KYC, no ID, no selfie, no proof of address, no nothing. You submit your cryptographic public keys and your desired username. That's the entire signup.

  3. No email required. No phone number or SMS. No identity verification. No ID, no selfie, no proof of address. No "verified human" check. That last bullet's not a joke — Morphit doesn't even check that you're a human; the rate limits and anti-spam are designed to make spam unprofitable rather than to gatekeep humanity.

  4. Listing fee is roughly $0.12 per order. A trade on a centralized exchange costs more in spread alone.

  5. Send a chat message to a stranger for ~$0.01. Welcome to a marketplace where contacting a counterparty costs less than a stamp. Spammer/solicitor filters are also built-in.

  6. Three-second blocks — and your own actions show up instantly. Blurt makes a block every three seconds, so your order is on chain in about three — and your own screen doesn't even wait for that: post an order and it's right there, marked "confirming" until the chain settles it. Strangers wait about a minute, on purpose: the public orderbook only lists orders that are irreversible and fee-paid, because we'd rather show someone nothing than an unpaid listing a reorg can erase. You get feedback in seconds and finality when the chain says so, and we tell you which one you're looking at (ADR-0051).

  7. No transaction-fee auctions. No gas wars. No priority-fee arms races. Listing fees are flat (with a Sybil-tier multiplier for spammers, see §9).

  8. First buy of Blurt is free. New users get a one-time waiver on their first listing fee, which puts real Blurt in their wallet so they can post and participate from day one.

  9. No deposits. Nothing to "fund" before trading. You hold your own coins; you trade when you want.

  10. No withdrawal fees. Because there's nothing to withdraw FROM. Trades settle peer-to-peer between you and the counterparty's wallets, not through an exchange custody account.

  11. Made for market makers and arbitrageurs. No maker or taker fee — only the flat ~$0.12 listing fee — and a spread price model (e.g. market ± 0.5%) that pins an order to the live market mid and re-prices itself as the world price moves. The orderbook is readable over read-only MCP tools and RSS, and orders are plain on-chain ops, so a bot needs no API key, no KYC, and no custody — the instance never even learns it's a bot.

  12. FAQ search answers Grandma's first questions. Queries like "how do I start", "how do I begin", "first time user", and "what is this" used to land on unrelated entries — pre-cp137 "how do I start" returned an order-editing FAQ at score 1.00. The synonym map now routes these grandma-shaped phrasings to the actual getting-started walkthrough, locked in by a coverage smoke with 14 sample queries.

  13. Lightweight pages even on slow connections. Every page does the minimum work to render, then loads more code only when the user action asks for it — chain-signing, hardware keys, profile cards, modals, the asset carousel. nginx serves the build's pre-compressed brotli and gzip artifacts (46× smaller than raw JS over the wire), and JSON API responses are gzipped too. Net effect: Sally on a remote mobile network downloads dramatically fewer bytes than on a typical exchange site, and the heavy code paths only load if she clicks something that needs them.

2. Privacy by design (not by promise)

  1. No cookies. No analytics. No logging. The footer says it because it's true, not because the lawyers wrote it.

  2. We do not get, store, log, transmit, or otherwise touch your IP address. Period. Zero. The relay extracts the client IP only as a rate-limit bucket key in memory; it's never written to disk, never logged, never sent anywhere, and the in-memory entry is discarded as soon as the rate-limit window passes. The source code (apps/relay/src/middleware/ip.ts) carries this as a binding contract — adding IP logging would require a security advisory and an ADR.

  3. Your broadcasts go through your operator's node, not a stranger's. Posting an order, sending a chat, or editing your profile is signed on your device and relayed to the chain by the same-origin indexer — so your IP and your exact on-chain action aren't handed to a third-party Blurt RPC operator you didn't choose, and your keys never leave your device (only the signed message is forwarded). The read side already worked this way; if your operator's node is briefly unreachable the browser falls back to a public RPC node so the broadcast still lands.

  4. We encourage VPN, Tor, Lokinet, and I2P access. Anything that hides your IP from the server you're talking to is a good idea. Our anti-abuse defenses are deliberately designed not to punish privacy-conscious users — rate limits are coarse, easy to evade with a VPN rotation, and we accept more abuse rather than make privacy-conscious users feel unwelcome. The Tor .onion, I2P b32, and Lokinet endpoints are first-class citizens, not afterthoughts — every instance now generates and serves a Tor .onion automatically, advertised via an Onion-Location header so Tor Browser offers it.

  5. No central key store. Your Blurt private keys never leave your device. There's no key database for anyone — including a future-bankrupt operator — to leak.

  6. No session cookies. No login state on the server. No session hijacking class of vulnerability because there are no sessions.

  7. No password reset emails. Because there are no passwords stored. You hold your own keys; the project can't forget what it never knew.

  8. End-to-end encrypted (E2EE) chat. Buyer-seller conversations are encrypted on your device, then stored on the public chain as ciphertext. Not even the indexer can decrypt them.

  9. End-to-end encrypted (E2EE) chat uses per-message ECIES (X25519 + ChaCha20-Poly1305-IETF, libsodium primitives). Each outbound message generates a fresh sender ephemeral key that's wiped after one use — that gives you sender-side forward secrecy: even if your posting key leaks later, an attacker cannot decrypt messages YOU sent in the past. We're honest about the tradeoff: the receiver's long-term chat key is stable until you rotate your posting key, so we don't claim per-message receiver-side forward secrecy. Full design + tradeoff rationale in docs/adr/0015-chat-crypto.md and the forward_secrecy FAQ entry.

  10. Deliberately NO Double Ratchet — and we'll defend the choice. We evaluated the Signal-style Double Ratchet against Morphit's actual threat model and rejected it: the realistic compromise (your Blurt posting key leaks) lets the attacker re-derive every chat key you've ever held anyway, defeating forward secrecy regardless of how clever the ratchet is — and shipping the full protocol means a ~2 MB WASM crypto bundle that doubles first-load size on slow connections. Instead we ship per-message ECIES with sender-ephemeral keys wiped after one use, chain-anchored TOFU pinning that detects any peer key swap, and opt-in out-of-band fingerprint comparison. See docs/adr/0015-chat-crypto.md for the full tradeoff rationale.

  11. Opt-in out-of-band fingerprint verification ("Verify peer"). For users who want belt-and-suspenders MITM protection beyond the chain-anchored TOFU pin, the conversation menu has a "Verify peer" item that computes an 8-word fingerprint from your chat keys, derived locally with the PGP word list (deliberately NOT BIP39 — we don't want users mistaking it for a seed phrase). Compare with your counterparty by voice call or in person. Hidden by default; power users get "safety numbers" protection without imposing the friction on everyone.

  12. Private E2EE chat history is permanent and verifiable. Stored on chain forever, signed, timestamped. The immutability matters for posterity (your trade record can never be deleted by a bankrupt operator), for legal recourse (an unredactable contemporaneous record is courtroom-grade), and for reputation integrity (counterparties can't quietly delete inconvenient threads to manipulate their feedback story).

  13. No Cloudflare. The project deliberately rejects Cloudflare and similar centralized reverse-proxy services that intercept all user traffic at TLS termination.

  14. No Google Analytics, no Facebook Pixel, no Hotjar, no LogRocket. No third-party trackers, full stop.

  15. No third-party CDN for fonts or scripts. Everything self-hosted; your browser doesn't phone home to Google Fonts when you load a page.

  16. The frontend has a strict Content-Security-Policy. No external scripts, no inline event handlers, no eval, no dynamic code paths.

  17. The relay only speaks to pre-configured Blurt RPC endpoints. No SSRF. No "fetch a URL the user supplies" code paths.

  18. Scans your text for accidental private-key disclosure. When you type into a chat or feedback box, Morphit scans the text for WIF keys, 64-character hex, and 12/24-word seed phrases. If detected, it warns you in red — and if you ignore the warning, it truncates the key client-side before the message leaves your device. Keep your private keys private!

  19. Profile fields don't require real names. Use a handle, use anything — profiles are decoration over a cryptographic key "identity". Be as anonymous as you want to be.

  20. Sharing your public address goes through a privacy-aware modal. Not just a copy-paste field — a flow that asks about subaddress preferences (XMR), amount-jitter (applied to every supported asset — BTC/BCH/LTC/DASH/DOGE/ZEC/ARRR/DCR/BLURT/SOL/ETH/XRP/XMR plus the stablecoins USDT/USDC/DAI; even XMR with its on-chain hidden amounts gets jitter because chat-shared amounts and centralized off-ramps both reveal the figure, and that's a separate linkability threat from the issuer-freeze concern the stablecoins already carry), client-side address-reuse detection (warns when you're about to share an address you've shared from this device before), and optional PayJoin (BIP-78) endpoint for BTC. Untraceability is the mission.

  21. Amount-jitter on every transparent chain. Default ON. Adds a small random extra (≤999 satoshis for UTXO chains, ≤99 milliblurt for Blurt) so the "exact 0.00513924 BTC" giveaway becomes "approximately 0.00513924 BTC with a small random tail your buyer absorbs." Trivial cost; significant chain-analysis defeat.

  22. Client-side address-reuse warning. When you paste or type a receive address you've previously shared from this device, the address-share modal surfaces an amber chip with the date of the prior share (and previous order permlink, if available). Pure localStorage — never transmitted to any Morphit server. Per-device limit: 200 entries (rolling buffer).

  23. PayJoin (BIP-78) support for BTC. The address-share modal has an optional PayJoin endpoint field on the BTC tab. When the seller's wallet supports BIP-78 and pastes its endpoint URL there, Morphit relays it as the pj= parameter in the bitcoin: URI — buyer wallets that support PayJoin negotiate a cooperative transaction that breaks the common-input-ownership heuristic chain-analysis depends on. Wallets without PayJoin support ignore the parameter and fall back to a normal payment: zero footgun.

  24. Per-asset privacy guide pages. /privacy (index) lists every Morphit-tradable asset with a one-line privacy summary, linking to per-asset deep-dives at /privacy/{asset}. Each guide covers fresh-address advice (asset-specific), opt-in privacy tech (MWEB for LTC, CashFusion for BCH, PrivateSend for DASH, CoinJoin + PayJoin for BTC), universal practices (Tor broadcast, coin control, avoiding KYC touchpoints), what NOT to do, and asset-specific caveats. Registry-driven — the next asset Morphit adds gets a guide automatically by populating one struct field.

  25. No wallet recommendations. Even reputable wallets have been compromised or have had hidden flaws. The privacy guides describe protocol standards (MWEB, CashFusion, CoinJoin, PayJoin) by name and capability so users can find their own wallet — but Morphit deliberately does not endorse, recommend, or list specific wallet software. Your wallet, your responsibility.

  26. Seed-phrase sign-in has a clear "remember me?" step. Pasting a 12-word seed phrase on a new device used to be a one-way trip to the trading screen — but the session ended when the tab closed, forcing the user to re-paste the seed next visit. Now after a successful seed import, Morphit asks "Automatically remember me on this device? (assuming nobody else uses it)" with the checkbox UNCHECKED by default — privacy-positive on public computers, one click + a password to persist on personal ones.

  27. There is no master password — the concept doesn't exist in the code. Morphit never creates, asks for, or derives a Blurt master password: every action is signed with the exact key it needs (posting or Active) and nothing else. This isn't a promise you take on faith — the key-derivation primitive that could have turned one password into every role's key (owner included) was deleted outright, and scripts/no-master-password-in-fee-flows-smoke.ts fails the build if the term or the capability ever reappears anywhere in the app.

3. Security and audits — receipts, not slogans

  1. Several thousand self-checking smoke scenarios across ~280 runners ship with the source code. Run them yourself: bash scripts/run-smokes.sh (and triple-pulse it for flake filtering). They cover the indexer, relay, ops CLI, frontend bus, payments, federation probe, fee verification, chat encryption, and more.

  2. A running audit document (docs/AUDIT-2026-05.md) — currently 20,000+ lines across 60+ numbered parts, organized by date and subsystem, listing every security review pass, every finding, every severity rating, every fix or accepted-risk rationale. Public, in the repo, anyone can read it. Plus per-batch audit files in docs/audit/ (Batch I YubiKey unlock, Batch J release trust anchor, Batch K block explorer, Batch L payment methods).

  3. STRIDE threat-model methodology applied per audit pass: Spoofing, Tampering, Repudiation, Information Disclosure, Denial of Service, Elevation of Privilege — a matrix run over every changed subsystem, with attack trees built from the most attractive entry points.

  4. Adversarial red-team narratives. The audit doc names hypothetical attackers (a doxxing journalist, a federated phisher, a sanctions evader, a reputation-launderer) and walks through what each would actually do to the system. Defenses are designed against the playbook, not against generic "bad actors."

  5. AUTOMATION-AUDIT.md — separate document covering the build pipeline, dependency hygiene, and supply-chain attack surface.

  6. REVISIT-LIST.md — public list of every accepted-risk item or deferred fix, with full context. Nothing falls through the cracks; nothing is hidden in a private bug tracker.

  7. AUDIT-FINDINGS.md — historical findings catalog, severity-tracked.

  8. PHASE-F-AUDIT.md, PHASE-G-PREP-AUDIT.md — phase-specific deep-dive audit reports.

  9. Threat-model assumes the attacker has read every line of code. The codebase is AGPL-3.0; this assumption is realistic, and designing for it is what makes the system actually safe.

  10. Reproducible builds. Every release tarball can be rebuilt byte-for-byte from its tagged commit. The build script publishes a verify.json containing per-file SHA-256 hashes; the same manifest is recorded on the Blurt chain via a morphit_release_v1 op.

  11. On-chain release attestation. Every Morphit release's bundle hashes are broadcast to the Blurt blockchain. Your browser can verify that the page you're loading matches the manifest the project published — independent of the operator's word.

  12. Two independent verification paths: (a) the GPG-signed release tag (git verify-tag), (b) on-chain hash manifest on the running bundle. If either is wrong, escalate; if both match, trust.

  13. Every release is hashed + tag-signed by CI. The release pipeline (.forgejo/workflows/release.yml) builds each release tarball, publishes its SHA-256, and refuses to publish unless the git tag is GPG-signed by a maintainer key committed under .forgejo/release-signers/. A downloaded source can be checked against a published hash and an authenticated tag.

  14. Verify your download against the blockchain, not against us. Every release's source-tarball SHA-256 and GPG signing-key fingerprint are anchored on the Blurt chain in the morphit_release_v1 op, alongside the mirror list — so you can prove a copy is the genuine, unmodified release without trusting the host you fetched it from. Clone any mirror and git verify-tag checks the signed tag; download the release bundle and scripts/verify-download.mjs cross-checks it against the on-chain record. Step-by-step: docs/VERIFY-YOUR-DOWNLOAD.md.

  15. No PHP, no WordPress, no XML-RPC, no OAuth, no Express middleware sprawl. Whole vulnerability classes that plague other platforms simply don't apply here.

  16. No eval, no Function(), no dynamic-code paths anywhere. The CSP enforces this; the codebase is clean.

  17. Strict CORS allowlists on every API endpoint. No promiscuous Access-Control-Allow-Origin: *.

  18. 64 KiB request body cap on every endpoint. No "send us a 500 MB JSON and watch our server fall over" attacks.

  19. Per-IP rate limiting at the indexer's middleware layer: 120 req/min for list endpoints, 600 req/min for single-record lookups, both operator-tunable. The IP is used as an in-memory bucket key only — never logged, never persisted.

  20. Schema-validated request bodies via Zod with bounded field lengths. Malformed input never reaches handler code.

  21. No SQL string concatenation. All queries are parameterized; SQL injection isn't a thing here.

  22. Constant-time comparisons for invite tokens and HMAC verification, to defeat timing oracles.

  23. Signed, short-lived (10-minute) invite tokens. A cryptographic hash of the requesting IP is included inside the signed token to prevent trivial cross-IP replay — but the IP itself is never logged or persisted; only the hash exists, only inside the token, only for the 10-minute TTL. After that the hash is gone with the token.

  24. Altcha proof-of-work challenge on the Nth invite per user per day. Frictionless for honest users, expensive at scale for spammers.

  25. Global daily ceiling on signups, configurable per operator. Caps worst-case Sybil drain regardless of how many IPs an attacker controls.

  26. Operator-balance scanner alerts when the relay's Blurt balance approaches zero, so the operator can refill if desired before signups stall.

  27. Federation probe auto-discovers other Morphit instances and tracks their health (good / quiet / stale / unreachable / mismatch / never).

  28. YubiKey unlock support for the local key vault on supported browsers (ADR-0017).

  29. Optional secp256k1 key isolation via local hardware token; private keys never enter the page's JavaScript heap when this mode is on.

  30. Matrix-only security disclosure channel at @agorise:matrix.org — end-to-end encrypted (E2EE) by default, no email-in-cleartext disclosure path.

  31. Operator kill-switch for compromise scenarios. A relay-side flag operators can flip if their instance is breached or hijacked — disables signups, blocks fee writes, and surfaces a banner instructing users to switch to a different Morphit instance. Combined with the federation probe (every instance discovers others automatically), a compromised operator can stop the bleeding while users keep trading on any other node within seconds. Code lives at apps/relay/src/policy/killSwitch.ts; runbook at docs/BETA-INCIDENT-RUNBOOK.md.

  32. Push subscriptions are proof-of-ownership protected. Only the holder of your posting key can subscribe a device to receive your push notifications — the relay verifies a Blurt-account-keyed signature on the subscription op before storing it. So even if someone steals your push subscription endpoint URL, they can't subscribe their own device to your notifications. Same trust anchor as the rest of Morphit: your posting key.

  33. The brag list audits its own honesty. A CI smoke walks MORPHIT-BRAG-LIST.md and asserts four invariants: the trailer count matches the actual number of entries, the trailer "Last updated" date is at least as fresh as the newest date cited in any entry, the ADR-range claim matches the actual range of ADRs on disk, and no two entries share a number. cp75 surfaced six prior numbering collisions (155, 156, 236239) and an 11-entry trailer-count drift; all renumbered to 294299 and the trailer corrected to 301. Future drift fails CI instead of accumulating.

  34. Test flakes get root-caused, not papered over. When a relay test failed intermittently across the cp74 battery, the prior diagnosis blamed an "rpc timeout" — but the test's mock had no real timeout to bump. cp76 traced the actual flake to apps/relay/test/killSwitch.test.ts using a 1.5s real-time wait on a 1s polling interval, then replaced it with vi.useFakeTimers() for deterministic timing. A CI smoke now bans real-time setTimeout waits over 10 ms in any test file across 90 test files, so the next variant of the class fails the build instead of leaking through.

  35. Logger redacts secret-named fields by default. The indexer's structured logger walks every context object before emit and replaces values whose key name matches a secret-suffix pattern (env-var styles like *_KEY/*_PASSWORD/*_TOKEN, camelCase suffixes like apiKey/userPassword/authToken, compounds like privateKey/seedPhrase) with [REDACTED] — recursively into nested objects, non-mutating to the caller's. Public-identifier keys (publicKey, pubkey, *_PUBLIC_KEY) are explicitly exempt and innocent words like monkey aren't false-flagged thanks to last-word tokenization. 20 unit tests in apps/indexer/test/log.test.ts lock the matcher behavior.

  36. Backup script honors every Ansible-set env var. Pre-cp131 ops/backup/morphit-backup.sh ignored AGE_RECIPIENT, REMOTE_DESTINATION, SSH_KEY, DB_HOST, DB_PORT — operators who set the encryption recipient got plaintext SQL dumps in their off-site backups, with §37.12 of OPERATIONS.md promising encryption that didn't exist. The cp131 rewrite consumes all five vars, age-encrypts when AGE_RECIPIENT is set, rsync-pushes to REMOTE_DESTINATION, and refuses to run when any value matches a placeholder denylist. A widened ansible-env-var-consumer-smoke (122 scenarios, was 79) now structurally compares every consumer to every Ansible-set var so the class can't recur.

  37. Push unsubscribe is signed AND ACTION-bound. Pre-cp131 /v1/push/unsubscribe accepted {account, endpoint} with no signature or rate limit, leaving DB-leaked endpoint lists weaponizable as a federation-wide notifications DoS. cp131 MED-009 mirrors the cp14 subscribe-side signature gate onto unsubscribe with the ACTION keyword folded into the canonical signed message — a captured subscribe-signature CANNOT replay as an unsubscribe (or vice-versa). The cross-action replay defense is mathematically verified by 5 scenarios in canonical-message-cross-check-smoke.ts plus 9 wiring sentinels in web-push-wiring-smoke.ts.

  38. The headline FAQ enumerates every tradable asset. The what_is_morphit answer — the first explanation a new user reads — was stale through cp124+ asset additions, listing only 10 of 16 supported assets. cp131 DEEP-001 fixed it across all 10 locales preserving each locale's conjunction style. A new what-is-morphit-asset-enum-smoke (170 scenarios — 17 assets × 10 locales with native-script aliases for Chinese variants) now pins the enumeration; tamper-tested by removing "Ethereum," from en.json → caught.

  39. Optional TOTP-based 2FA — never required, never nagged. Users who want a second factor after their password can enroll a TOTP secret at Settings → Two-factor authentication and scan it into Aegis, 2FAS, or Ente Auth — open-source apps Morphit recommends by name. The enrollment page surfaces the honest threat model: this is a session gate against shoulder-surfing and casual local malware, NOT cryptographic strength against an attacker with both your keystore AND your password. Users who never enroll see no prompt or nag; code lives in apps/web/src/lib/auth/totp.ts with 38 RFC 6238 vectors passing, and ADR-0043 documents the design rationale.

4. Real decentralization, not the marketing kind

  1. Federated orderbook over a public blockchain. Orders live on the public chain. Any operator running a Morphit indexer sees the same orderbook in real-time, and a buyer on one instance sees orders posted through any other instance — each operator's frontend is its own brand and URL, but the data layer is shared. Multiple indexers cross-verify each other.

  2. No central server to attack. Take down a Morphit website and the federation continues; a buyer just opens another operator's URL.

  3. No central database to subpoena. The orderbook isn't IN a database; it's ON the public blockchain. Subpoenas aren't a useful attack here.

  4. No single point of failure. Operators come and go; the chain is permanent.

  5. Both indexer and relay pick the fastest healthy Blurt RPC node automatically, and explorer verification doesn't hang on a slow one. Each operator configures lists of public Blurt RPC nodes (chain reads) plus BTC and XMR block explorers (fee verification). The shared endpoint pool tracks rolling-average latency, prefers the fastest known good one, and rotates with an exponential cooldown so flapping nodes don't get hammered. For fee verification, the indexer returns the moment explorers agree on the amount — slow or dead explorers no longer gate completion, so releases that previously hung for 5 seconds now land in milliseconds.

  6. Federation directory built into every instance. Visit /instances on any Morphit URL and see a list of every other known instance, their alt-network addresses, and their health status.

  7. Reachable over Tor. Onion services are first-class; instances commonly publish a .onion address alongside their public hostname.

  8. Reachable over I2P. Instance directory tracks .b32.i2p addresses; the federation probe tries them.

  9. Reachable over Lokinet. Same for .loki addresses. Different threat model than Tor; sometimes faster; an option, not the only path.

  10. Reachable over Nostr. Operators can publish their pubkey as an alt-network channel for users who prefer that ecosystem.

  11. No registrar, no domain auth, no DNS dependency required. A Morphit instance can run on morphit.local, on .onion only, on .loki only — DNS is a convenience, not a requirement.

  12. Anyone can run a node. Pick a domain (or skip the domain), clone the repo, run the setup script, broadcast a morphit_operator_register_v1 op. You're in the federation. No application, no permission, no central listing.

  13. Operators earn 90% of every Blurt-paid listing fee on their instance, paid in Blurt directly to their payout address — the other 10% goes to the project treasury (@morphit-fees). BTC/XMR-paid listings fund the project treasury 100% — those don't generate operator revenue — but the Blurt-paid path is 50% cheaper for users (deliberate incentive), so most listings naturally choose Blurt, where operator revenue lives. Real revenue stream for serious operators on a $5-10/month VPS. No project skim on the operator's Blurt share.

  14. Operator instances are self-branded. acme.example.com running Morphit looks like Acme Corp's marketplace, not like a generic affiliate page.

  15. Run on a Raspberry Pi. Hardware requirements: 2 cores, 2 GB RAM, 20 GB SSD, 1 Mbit/s. A Pi 4 with a USB-3 SSD is sufficient for a community instance.

  16. Run on a spare laptop. Closed-lid on a shelf with wired Ethernet works great. The laptop battery doubles as a UPS.

  17. Run on a $5/month VPS, or $0/month at home on residential internet with Dynamic DNS. No static IP required; many operators host from home.

  18. No Blurt witness or full chain node required. The indexer talks to public Blurt RPC endpoints over HTTPS.

  19. Indexer cross-verifies via multiple Blurt RPCs. No single chain provider is a trust anchor.

  20. Self-sovereign Blurt pricing from on-platform trade data (opt-in). Operators can flip on a price source that derives Blurt/USD from real verified-fee trades happening on Morphit instead of leaning on outside price feeds. Survives any external feed shutting down: tiered anchors prefer direct Blurt-vs-USD orders, fall back to Blurt-vs-stablecoin orders with cross-stablecoin depeg detection, then combine both pools when each alone is thin. Same Sybil filters as reputation; one-vote-per-trader medians; manipulation defenses at every layer.

  21. Publicly verifiable price receipt. Fetch GET /v1/price/morphit-native/receipt and you get exactly which on-platform traders contributed to the current native price, which tier was used, the live cross-stablecoin depeg report, the plausibility envelope settings, and a loud NOT-AN-ORACLE warning. Anyone can audit; nothing about price derivation is opaque.

  22. Operator-configurable price denomination. The "~$0.12" subtext next to listing-fee Blurt amounts isn't hardcoded to USD — operators pick their instance's display unit (USD, EUR, GBP, JPY, BRL, CNY, INR, RUB, AED, XDR for the IMF basket, XAU for gold ounces, or any 3-8 character ticker their market uses). Works today for non-USD-native markets, hedges against future scenarios where USD's reserve-currency role erodes. One env var, no code change; listing-fee API returns a denomination_fiat field so frontends know which unit they're rendering.

  23. Cross-instance peer-disagreement detector (Defense F). Opt-in monitor that periodically queries peer Morphit instances' price-receipt endpoint, computes the federation median, and alerts on sustained 25%+ disagreement vs your own derived price. Catches the case where YOUR indexer is the one being manipulated — pressured operator, captured server, geographic isolation — rather than the trader-level manipulation the cp127 sybil filters address. Uses median (not mean) so a single bad peer can't swing the result, requires ≥3 peers minimum, and filters by same-denomination so EUR-vs-USD instances aren't compared apples-to-oranges (which closes the last open item from cp127's 8-defense black-hat table).

  24. Multi-asset self-sovereign pricing. The cp127 morphit_native price source (Blurt/USD derived from on-platform trade data) extends to BTC and XMR in cp130 — each asset has its own composite chain: an outlier-rejected median across many independent external feeds (Coingecko, CoinPaprika, CryptoCompare, plus exchanges like Kraken/Binance/Coinbase/OKX/Bybit where listed) → morphit_native → static floor. Any feed that's down, rate-limiting us, or wrong is dropped from the median, so no single provider can move the published price. The receipt endpoint /v1/price/morphit-native/receipt?asset=BTC returns a real BTC/USD derivation operators can inspect.

  25. Wallet developers can embed Morphit's orderbook directly inside their wallet UI — the same kind of integration Mycelium famously did with LocalBitcoins years ago. Morphit publishes a stable public REST + SSE API (/v1/openapi.json on any instance) covering the orderbook, profiles, feedback, and chat — federation-aware, so the wallet can point at any operator's instance or a self-hosted one. Any wallet supporting Morphit's 16 tradable assets can offer peer-to-peer trading without making users leave it. AGPL-3.0 like the rest of the project; integrators ship under their own license.

  26. AI agents can browse the orderbook natively (morphit-mcp). Ship a Model Context Protocol server (npm + Docker) so Claude Desktop, Cline, Cursor, Continue, Windsurf, Zed, and local-LLM stacks query Morphit directly. Read-only over two transports — stdio for local agents, plus a hardened loopback-bound Streamable-HTTP service (DNS-rebinding allowlists, rate limit, body cap, fail-closed bind) installed and kept running by default — deeplinking back to the web UI for key-signing so keys never enter the AI surface. Federation-wide discovery: the wizard defaults MCP on and /v1/instance.mcp_url advertises the live <origin>/mcp endpoint, growing the AI-discoverable surface with every operator (AGPL-3.0, apps/mcp-server/).

5. Non-custodial, honestly

  1. Morphit never holds your funds. Period. There's no exchange wallet, no custodial pool, no deposit account. You trade peer-to-peer; the operator's relay never sees your private keys or your counterparty's funds.

  2. No escrow account. No "we hold while the trade settles" pattern. Settlement is direct.

  3. No custody fees. Because no custody.

  4. No "frozen account" mechanism. Thanks to the public blockchain, demonetization, censorship and user bans are impossible.

  5. No exchange-side hot wallet to be hacked. Because no exchange-side wallet.

  6. No insolvency risk. A bankrupt Morphit operator can't owe you BTC because they never had your BTC.

  7. No FTX failure mode. No SBF holds the keys. There are no shared keys. There is no shared cold storage.

  8. The trade itself never appears on Morphit's books. Your bank transfer goes from your bank to the seller's bank. The XMR moves directly from seller's wallet to buyer's wallet. Morphit cannot see, log, or intervene.

  9. You can audit the on-chain receipts. Every fee paid, every listing posted, every feedback signed — provable on the public blockchain, no Morphit cooperation required.

  10. Your Active key is asked for, used, and forgotten. Sign in with an existing Blurt account and Morphit asks for that key only when a trade needs it. By default it signs once, then is wiped from memory. Keeping it on the device is a choice you make in words, with the safe option preselected.

  11. Morphit refuses your Owner key. Paste it and the app names it and declines to use it. The same refusal applies when a pre-fork master password turns out to derive Owner rather than Active. The most dangerous key you own is the one Morphit works hardest never to touch.

  12. An encrypted Keyfile for accounts that never had one. Choose to keep your Active key here and your Keyfile holds both Posting and Active, encrypted with your password, labelled honestly as holding neither Owner nor Memo. Imported accounts get no 12-word phrase: a seed derives keys and cannot be built backwards from keys you already had.

6. For Monero users specifically

  1. Monero is a first-class asset, not an afterthought. Listed alongside Bitcoin and Blurt as the three core trading assets. Treated as a peer, not a curiosity.

  2. Morphit won't accept your view key. Ever. For any reason. The Monero verification flow is explicitly designed to NOT require it.

  3. Morphit never proxies your XMR transactions. They move directly between the parties' wallets; Morphit doesn't even broadcast for you. The public Blurt order doesn't leak the asset either: permlinks are opaque random tokens (order-…, not sell-xmr-usd-…), so "xmr" never appears in URLs, RSS feeds, or block explorers, and the expiry is floored to the day to hide your exact posting time. An XMR TxID touches Blurt only for an optional listing fee you can skip by paying in Blurt — the default, at half the price; the other privacy coins (Zcash, Pirate Chain, Dash, Decred) can't pay fees at all, so their TxIDs never touch Blurt.

  4. Amount randomization (jitter) defeats correlation attacks. When you share your XMR address, Morphit can append cryptographic-RNG randomness to the trailing 6 decimals of the amount — up to ~0.000001 XMR (1 microXMR ≈ $0.0002 trivial cost) — so two "0.5 XMR" trades produce distinct on-chain amounts. Defeats the well-known view-key amount-correlation attack.

  5. Jitter uses crypto.getRandomValues, not Math.random. Predictable PRNG would let observers correlate jitters across one user's trades. Morphit uses cryptographic-quality randomness.

  6. Jitter is asymmetric — round UP only. Never underpays the seller. Verifier compares observed amount vs expected; underpayment fails. Costs the buyer at most 0.000001 XMR per trade.

  7. Subaddress nudge. When you try to share a standard Monero address (starts with 4), Morphit gently suggests using a subaddress (starts with 8) instead. Standard addresses link every received payment to the same view key; "Stealth" subaddresses break that linkage. Not paternalistic — it's a soft nudge with a brief explanation.

  8. Multi-explorer attestation for XMR proofs — five independent explorers by default. When verifying that a Monero payment landed, Morphit queries five Monero block explorers in parallel (xmrchain.net, localmonero.co/blocks, monerohash.com/explorer, exploremonero.com, moneroexplorer.org — all running the same onion-monero-blockchain-explorer reference codebase, but operated by independent parties) and rejects when responding explorers disagree on the proven amount. Operator-configurable to any compatible list, including self-hosted instances for maximum independence (see OPERATIONS.md §40.4). No single explorer can lie about a verification undetected.

  9. The "I sent the funds" flow includes XMR-specific tooling. TxID copy-paste, view-key-handling explanations, integrated subaddress hints — Monero-aware throughout, not just "another asset on the dropdown."

  10. Monero-specific FAQ entries in 10 locales explaining: how to find a TxID in GUI / Cake Wallet / Feather / monero-wallet-cli, why subaddresses matter, why Morphit won't accept your view key, how amount jitter protects you, and what the limits are.

  11. No "show us your wallet balance" prompt. Ever. Other platforms ask. Morphit doesn't.

  12. No KYC trigger thresholds for Monero trades. No "trades over $X require ID." No KYC at all, ever, regardless of trade size.

  13. Onion-only access works for Monero traders. Several operators run .onion-only instances; you can trade XMR without your IP ever touching the clear net.

  14. Per-asset payment-method registry. Operators can list which payment rails they support per asset, with operator-specific notes — reduces wasted DM exchanges asking "do you take Cash App for XMR?"

7. For Bitcoin users specifically

  1. Multi-explorer Bitcoin verification. Morphit cross-checks Bitcoin payments against multiple explorers (Blockstream, mempool.space by default, operator-configurable) — no single explorer is a trust anchor.

  2. Bitcoin support is genuine. Not a "we technically allow BTC" afterthought. The fee verifier, the explorer URL builder, the asset registry, the FAQ — all treat BTC as a primary asset.

  3. Lightning support is on the roadmap. Currently on-chain BTC; Lightning integration is a tracked roadmap item, honestly disclosed rather than overpromised as already-shipped.

  4. No "Bitcoin only" tribalism. Morphit serves BTC users without sneering at Monero users (and vice versa). The two communities trade with each other; the platform reflects that.

8. Reputation, trust, and chat that survives the platform

  1. Star ratings on chain, signed by both parties, immutable. Every feedback row is a Blurt morphit_feedback_v1 op signed by the reviewer. Edit-proof, delete-proof, fake-proof.

  2. Reputation can't be faked. Your displayed star average is computed only from on-chain feedback rows whose reviewer signed the op AND whose feedback is tethered to a real on-chain order (not free-form). Self-signing isn't possible — the chain rejects ops without a valid signature from the reviewer's posting key — and the indexer further excludes (reviewer, subject) pairs flagged in suspicious_reciprocity (sock-puppet pattern) or related_accounts (linked-account heuristics). What's left, averaged and rounded to 2 decimals, is what the world sees.

  3. Recent feedback weighs more than ancient feedback. Your published rating uses a 365-day exponential half-life — today's review counts 1.0×, a year-old review 0.5×, two-year-old 0.25×. A trader who turned bad can't dilute recent 1-stars with stale 5-stars; raw count stays visible separately so historical context isn't lost. Displayed to 2-decimal precision (4.74, not 4.7).

  4. Public verifiable reputation receipt. Fetch GET /v1/accounts/<account>/reputation-receipt and you get every feedback row about that account (included AND excluded, with the reason for each exclusion), the decay weight applied to each row, and the formula used. Any reader with chain access can independently re-derive the published score — reputation is verify-against-chain, not trust-the-indexer.

  5. Positive feedback builds your reputation. Every counterparty who rates you 4 or 5 stars after a real on-chain trade lifts your average. Keep in mind: if you want people to trade with you, your reputation is everything. New accounts show up with an is_new_trader flag (fewer than 4 ratings) — and counterparties may be wary of trading with someone whose reputation has yet to be established.

  6. Sock-puppet detection. The indexer runs a suspicious_reciprocity heuristic that flags pairs who exclusively review each other. Suppressed feedback is excluded from the headline rating but visible in the raw history.

  7. Diversification-resistant concentration detector. Catches reviewers who concentrate ≥80% of their reviews on a single high-star target over a 30-day window — including the smart attacker who reviewed a few throwaway third parties to evade the older sock-puppet detector's stricter mutual-only rule. Flagged feedback is excluded from the published rating but remains visible in raw history.

  8. Verified-chat badges. Feedback rows get a "verified chat" badge if the reviewer-subject pair had a real-looking on-chain conversation BEFORE the review: at least 2 messages from each side (bidirectional, not one-shot), at least 15 minutes between first and last message, and the pair isn't flagged in suspicious-reciprocity. Defeats the "fake-trade-fake-review" pattern by requiring evidence of actual interaction.

  9. Side-of-trade breakdown + dormancy signal. Your profile shows separate weighted ratings for buyer-side and seller-side trades — a trader great as buyer but careless as seller is visible to readers. A "Last traded: N ago" chip surfaces freshness (verified-fee order posted OR feedback received) so readers see if an account is dormant without changing the numeric score.

  10. Feedback responses are themselves on-chain. When you reply to feedback you received, the response is signed and attached. No "edit out the bad review" pattern.

  11. Engagement counter shows how many distinct accounts messaged the order owner about a specific order in the last 24 hours. Tells you if an order is alive or stale.

  12. Loyalty milestones delegate progressively more BP (10/50/200/1000, totaling 1,260 BP) as you accumulate cumulative Blurt-fee spend. Real reward for sustained good-faith trading.

  13. Welcome bonus on first completed trade: 10 Blurt liquid + 10 Blurt Power (BP). BP is your own vested, staked Blurt — not a delegation, not borrowed. You own it. Staking earns you curation rewards, empowers your upvotes, and earns you ~2% interest (APR).

  14. First-fee welcome BP delegates 1 BP on your first Blurt-paid listing fee, separate from the welcome bonus. Small symbolic stake giving you a foot in the broader Blurt ecosystem.

  15. Reputation can't be migrated to a competitor's silo. It's on a public chain. Your reputation is yours, portable across every Morphit instance. If you want to start using a different operator's frontend, your reputation comes with you.

  16. A built-in notifications system with inbox. Three ambient channels (browser tab title prefix, favicon dot, PWA app-icon badge) never interrupt; three opt-in interactive channels (OS notifications, audio chime, mobile vibration) ask permission at the point of relevance instead of on page-load — roughly 3× the grant rate. Web Push delivers notifications even when the Morphit tab is closed or the phone is locked, using operator-generated VAPID keys (no external service). Settings → Notifications has the full toggle panel; the inbox is at /notifications with mark-read, dismiss, and per-channel preferences.

  17. A poster's cryptographic identity is shown, not just their name. Each order-detail page prints the poster's truncated public posting key directly under their display name — the durable on-chain identity that a mutable display name can't spoof. A would-be impersonator who picks a look-alike name is exposed at a glance, and any later fraud claim has a concrete on-chain key to point to.

9. Anti-spam and anti-Sybil (without surveillance)

  1. Listing fees rise with abuse. Sybil-tier multiplier scales: 4th order in 24h = 1×, 5th = 2×, 6th = 4×, 7th+ = 8×. Honest traders pay $0.12; spammers pay rapidly-growing tolls.

  2. Cold-message fees discourage drive-by spam. First-time DM to someone you've never traded with costs ~$0.01 in Blurt, escalating with abuse history.

  3. Featured-slot bidding is auctioned, with anti-snipe protections and outbid alerts. Top-of-orderbook placement requires outbidding, but minimum-hours floors prevent micro-bid sniping, bids go to the operator (no project skim), and a soft-close rule extends the deadline of any expiring top-5 bid when a new bidder triggers it in the last 5 minutes (capped at 6 extensions / 30 min). Bidders see their own recent bids inline with the bid form (status chips: Visible / Outranked / Expired / Order ended), so they know what to pay before pressing submit. When a new bid outranks yours, the displaced bidder gets a push notification with one-tap re-bid.

  4. Account creation costs the operator 100 Blurt per signup. That's a real economic gate. Sybil farms attacking a Morphit instance must convince the operator's relay to spend real money on each puppet account, which the operator's daily-ceiling defenses cap.

  5. Per-IP signup spacing. Multiple invite-token issuance from the same IP triggers an Altcha PoW challenge.

  6. /v1/health short-circuits signups when the relay is low on funds. Drains stop before they become unbounded.

  7. Drainer has defense-in-depth. Per-row caps (N Blurt max amount per queued transfer), savepoint isolation per op, idempotency guards.

  8. No invite is "verified by SMS / phone." No carrier surveillance. The invite system uses cryptographic proof-of-work, not telecom data.

  9. No CAPTCHA from a third party. Altcha is self-hosted, doesn't phone home, doesn't track.

10. Open source and transparent (with receipts)

  1. AGPL-3.0 licensed. Every operator who modifies Morphit and runs it as a service must publish their modifications. The license is the strongest copyleft in common use; it's chosen deliberately to keep forks honest.

  2. Source code at git.agorise.net/agorise/morphit. Self-hosted Forgejo (Git forge), not GitHub. The project's own infrastructure is decentralized too.

  3. 50 ADRs (Architectural Decision Records) in docs/adr/, numbered 00010051 (0016 retracted), each recording a design choice with its alternatives and tradeoff. Topics span key custody (0010), chat reputation + crypto (0014, 0015), YubiKey unlock (0017), release trust anchor (0019), QR pairing (0022), one ADR per tradable-asset addition (00230036), cash-by-mail (0037), reputation hardening (0038), self-sovereign pricing (00390042), opt-in TOTP 2FA (0043), AI-agent integration via MCP (0044), shared network-defense primitives (0045), Blurt signing off elliptic (0046), Tor-onion + host-hardening by default (0047), sub-6s chat delivery (0048), payment-proof reputation deferred to protect transaction privacy (0049), and provenance-is-not-capability (0050).

  4. 49 design and operations documents in docs/. Architecture, operations runbook, security model, fees-and-rewards reference, threat model, metadata-leak catalog, integration test design, automation audit — all public.

  5. PHASE-3a-DESIGN.md, PHASE-3b-DESIGN.md, PHASE-5-PLAN.md — phase-by-phase honest planning documents. What we're building, when, and what we're explicitly deferring.

  6. GRANDMA-FRIENDLY-INVESTIGATION.md. A document specifically about UX accessibility for non-technical users, treating "can a non-crypto-native person actually use this" as a first-order engineering concern.

  7. METADATA-LEAK-CATALOG.md. A full inventory of every place metadata could leak — and what we do or don't do about each. Honest disclosure of where we're imperfect.

  8. OPERATOR-TRUST-DESIGN.md. Explicit threat model treating operators as untrusted by default. Users can verify what an operator is actually serving against the on-chain manifest.

  9. OPERATIONS.md — full ongoing runbook for operators (40-plus sections). Covers backups, RPC management, signup-drain defenses, fee-recipient accounts, release signing, and more.

  10. API.md — a public, documented HTTP API contract. Stable shape, stable URLs, free, read-only — designed for block explorers, federation aggregators, third-party clients, academic research.

  11. FEES-AND-REWARDS.md. Single-source-of-truth document for every monetary flow in Morphit, with line-number references back to the source code that defines each figure. Don't trust marketing — verify against the code.

  12. CHANGELOG kept in releases on Forgejo. Every release notes what changed, what bugs were fixed, what's deprecated.

  13. No proprietary modules — and zero code obfuscation. Nothing is closed "for security reasons," and nothing is obfuscated: the frontend is minified only for size, never to hide logic. Every byte of the running system is published AGPL source you can read and audit — no V8 bytecode, no opaque packed archives.

  14. No telemetry. Not even crash reporting. The codebase doesn't phone home.

  15. No dependency on a single vendor. Postgres, Node.js, nginx — all standard, all open-source, all easily replaceable.

  16. One-click media kit at /morphit-mediakit.zip. A pre-built bundle with the current claims list and brand logos (mark + wordmark, both SVG) — served from every instance, not gated behind asking the project for assets. Press, integrators, and the community can grab everything they need to write about Morphit, integrate with it, or talk about it on a podcast without a back-and-forth permission dance. The bundle is regenerated and re-committed every time its source files change; a CI smoke fails the build if it goes stale.

  17. Signed-tag release pipeline with one-command operator upgrade. Every release tag is GPG-signed by an authorized release-signer (public keys live in .forgejo/release-signers/ so anyone can verify); CI runs git verify-tag before building the tarball, and morphit-ops upgrade re-verifies on the operator's side before extracting, with automatic rollback on failure. A morphit-release-monitor systemd sidecar polls Forgejo every 6 hours and DMs the operator via matrix-bot when a new release is available — no mailing list to subscribe to, no manual repo-checking needed. Full operator guide at docs/UPGRADING.md.

  18. Live-updated comparison image hosted at a stable URL. Blog posts, fediverse threads, and external sites can hot-link https://morphit.io/morphit-comparison.png — a 2400-pixel-wide feature-by-feature table comparing Morphit to Bisq, Haveno/RetoSwap, OpenMonero, and BasicSwap across 136 verified data points. The image regenerates from scripts/comparison-image/build_comparison.py every time the brag list or competitor facts change; a CI smoke (comparison-image-freshness-smoke) fails if the PNG goes stale. Every claim is traceable to either Morphit's source code or the competitor's public docs; corrections welcome via Matrix #agorise:matrix.org.

11. Internationalization done right

  1. 10 locales shipped at v0. English, Spanish, French, German, Italian, Polish, Russian, Persian/Farsi, Mandarin (Simplified), Cantonese (Traditional). Many platforms ship English-only and consider it "worldwide."

  2. Right-to-left support for Persian. Layout flips, numerals localize (Persian uses ۱۰ not 10), text flow respects RTL conventions.

  3. Persian numerals tracked separately. The fee-reward smoke specifically validates Persian-numeral consistency, because "10 Blurt" and "۱۰ Blurt" don't share regex patterns.

  4. No US-centric defaults assumed. Currency display, date formatting, payment method names — locale-aware.

  5. Translation isn't an afterthought. Each locale has full FAQ entries (often 100+ entries), full UI strings, full error messages.

  6. Native-speaker QA pending across non-English locales. The team is honest about which locales were originally digital-translator-assisted and ensuring native-speaker review as a real backlog item, not pretending all 10 locales are equally polished.

  7. Native ES/FR/DE translations for every per-asset surface. Across all 16 tradable cryptocurrencies, the per-asset FAQ entry (what_is_<asset>), the post-order asset-explainer tooltip, the address-format error, the address placeholder, the pill-title in chat, and the cheat-sheet section — every one of these has actual Spanish, French, and German translation pairs, not silent EN-fallback. 93 translation pairs added in cp54+cp55, with a registry-based policy-gate smoke that prevents future per-asset surfaces from skipping native-locale closure.

  8. Memory #29 native-locale policy is mechanically enforced. A per-asset-key-family-native-locale-floor-smoke walks a registry of per-asset key families × 3 native locales (es/fr/de) × 16 tickers = 240 field-checks per CI run, refusing any value that's byte-identical to the EN baseline. EN-fallback smuggled into a native locale fails the build; new per-asset key families are one-line additions to the registry.

  9. Long-form FAQ + privacy-guide content translated to all 10 languages — mechanically enforced. Memory #29 originally permitted EN-fallback for 6 community-translation backlog locales (it/pl/ru/fa/zh-CN/zh-HK); 13 batches across cp76-cp80 closed that backlog by translating every key with EN length ≥ 200 chars across all 6 locales. A cp80 smoke walks 293 long-form keys × 6 backlog locales = 1,758 translation pairs per CI run, refusing any byte-identical to EN. Future long-form content additions can't ship with English-only in the backlog locales.

  10. Every new asset ships its per-asset prose in all 10 locales — mechanically enforced. When a ticker is added to packages/asset-registry, five mandatory i18n families must appear across every locale: the post-order asset explainer, the cheat-sheet entry, and three privacy-guide keys (one-line summary, intro body, and HTML meta description). A cp75 smoke walks the registry × families × locales = 800 key checks per CI run and fails if any one is missing; optional families like "caveats" (where some assets correctly have nothing to caveat) stay opt-in by design. New tickers can't slip through with prose in English only.

12. Pro-Monero culture, not just compatibility

  1. No Monero "lite" client logic. Morphit does NOT try to interpret your Monero wallet. It's a coordination layer; your wallet is your wallet.

  2. Five independent Monero block explorers in the default config (xmrchain.net, localmonero.co/blocks, monerohash.com/explorer, exploremonero.com, moneroexplorer.org) — operator-configurable to any list of compatible explorers, including self-hosted instances.

  3. Trade verification logic is per-asset. Bitcoin uses one path (multi-explorer cross-check on UTXO confirmation), Monero uses another (TxID + amount-match against the recipient's expected, no view key required) — designed for each chain's actual privacy model.

  4. Privacy-respecting default for the XMR jitter toggle: ON. A user has to deliberately turn jitter OFF if they want to send a round amount. Default is the privacy-preserving choice.

  5. Monero loadout in the asset registry includes piconero precision (12 decimals). No truncation, no awkward display.

  6. No "Monero is risky / for criminals" UI text. Anywhere. We trade XMR; we don't apologize for it.

  7. No Chainalysis, no on-chain analytics integration, no third-party "compliance" tooling. Designs treat that as a leak surface, not a feature.

  8. Acknowledges privacy is a journey. The METADATA-LEAK-CATALOG documents what we DON'T solve (e.g., the operator can see (but not log) an IP fetched a specific order list — solved by Tor users, not by Morphit alone). Honesty over PR.

  9. Documented in plain English: "Morphit cannot see this." Throughout the chat-trade flow, the UI explicitly tells users which actions Morphit observes and which it doesn't. No false claims of total privacy where partial privacy is the truth.

  10. Pro-Monero stance in the welcome bonus. New users with their first XMR trade get the same welcome bonus (10 Blurt liquid + 10 Blurt Power) as Blurt-fee payers, no second-class treatment.

13. Honest comparisons (CEX, fake DEX, P2P)

vs. centralized exchanges (Binance, Coinbase, Kraken, etc.)

  1. No KYC. They require government ID; Morphit asks for nothing.

  2. No deposits. They custody your coins; Morphit never touches them.

  3. No frozen accounts. They can freeze you; Morphit literally lacks the database table to track an account-freeze flag.

  4. No insolvency risk. No exchange to go bankrupt. No custodial pool to lose. No "the bridge got hacked" headline applies to Morphit because there is no bridge — the relay never touches your funds.

  5. A smart contract custody escrow is still custody. Funds sit in code controlled by someone (multisig, governance, admin keys). Morphit's funds NEVER sit anywhere — they go directly between the two parties.

  6. Morphit doesn't have admin keys. Not in a multisig, not in a timelock, not anywhere.

  7. Smart contract bugs have rug-pulled billions. Morphit's "smart contract" is the Blurt chain — a public ledger maintained by an independent nodes network that nobody can control.

  8. A "decentralized" exchange that depends on AWS isn't decentralized. Morphit operators run on Pi 4s, mini-PCs, spare laptops, residential connections, and .onion services.

vs. LocalBitcoins / Hodl Hodl / LocalCryptos / Bisq / Haveno / OM

  1. LocalBitcoins shut down. Single-operator failure killed the platform. Morphit is federated; no single shutdown can do this.

  2. Hodl Hodl uses on-chain Bitcoin escrow. That's better than CEX custody but still escrow. Morphit is fully no-escrow.

  3. Bisq has been hacked twice, user funds stolen. They require you to run their desktop app, a Tor node, and provide them with collateral. Morphit runs in any browser, requires no collateral, and let's the user choose options like Tor, i2p, Lokinet, etc.

  4. Haveno/RetoSwap is Monero-only, non-PWA, not Grandma-friendly. Morphit handles 16 tradable assets, ships as a PWA (no install on iOS, two taps on Android), and is built so non-crypto-native users can trade without reading 40 pages of docs. The Haveno/RetoSwap project does important work for Monero-only; Morphit complements it by being broader and easier.

  5. Haveno's 2-of-3 multisig escrow was exploited on May 20, 2026 for ~$2.7M. A forged out-of-order arbitrator ACK message caused the Haveno client to update the arbitrator's node address mid-trade, letting attackers create a compromised multisig wallet before user funds were deposited; RetoSwap halted trading the same day (min client version raised to 2.0.0). Morphit's design has no arbitrator role, no multisig escrow, and no central coordination message Haveno's exploit relied on — so this attack class doesn't apply to our threat model. The tradeoff is real and stated honestly elsewhere on this list: Morphit users carry full self-custody and lean on signed on-chain reputation rather than an arbitrator's safety net.

  6. OpenMonero (LocalMonero clone) lost user funds twice in 12 months. June 6, 2025: a ufw and wallet-rpc misconfiguration drained 77.85 XMR ($25,225) from the platform's custodial internal wallet; refunds are still being paid out of trading fees over a year later, vendors first. May 21, 2026: a second exploit drained 40 XMR ($16,120) and the alert prompted OpenMonero to halt all payments one day after Haveno's $2.7M exploit. Morphit has no custodial wallet to drain — your XMR never sits on a Morphit server, so this entire attack class has nothing to steal.

  7. Some P2P platforms have admin "dispute resolution" that overrides users. Morphit has no admin role; chat history is the dispute record, and it's signed and immutable.

14. What Morphit deliberately does NOT do

  1. No token sale. No ICO. No IDO. No airdrops to manipulate "user count." There's no MORPHIT coin.

  2. No "premine." The project earns by listing fees on its own instance, same as any other operator.

  3. No "governance token." No proposals you don't care about; no votes you can't participate in.

  4. No "DAO." Architectural decisions are made by the contributors; documented in ADRs; criticizable by anyone via the public issue tracker.

  5. No marketing partnerships with CEXes. No referral codes. No yield-aggregator integrations.

  6. No "Pro" tier with extra features for paying customers. The free Morphit IS Morphit.

  7. No "premium" customer support. There's no standard support either — if you need help, ask on the operator's Matrix channel or read the FAQ. Honest.

  8. No NFT integration. No "trade BTC for an ape JPEG."

  9. No leverage. No margin. No futures. No options. Morphit is a spot fiat-crypto marketplace, full stop. Defi degens look elsewhere.

  10. No "AI assistant" trying to sell you a trade. Just an orderbook.

  11. No app-store gatekeepers. Morphit is a PWA — installs on Android via "Add to Home Screen," installs on iOS via Safari Share → Add to Home Screen. Apple App Store would reject a non-KYC P2P crypto app; we don't pretend otherwise.

15. Reach: every device, every network

  1. Progressive Web App — installable as a standalone app on Android and iOS without going through Google Play or the Apple App Store.

  2. Service worker caches assets locally — partial offline capability for previously-loaded pages and static content.

  3. Works in Tor Browser at maximum security level. Service worker gracefully falls back to normal caching when service workers are disabled.

  4. No install required to browse. Morphit runs in any modern browser — desktop, laptop, phone, or tablet — with nothing to download; installing the PWA is optional, for an app icon and an offline shell.

  5. Runs on modest hardware. The PWA is small and dependency-light, so it loads on older phones and slow connections — no flagship device required.

  6. GrapheneOS callout as the recommended privacy-first Android. No Google relationship required.

  7. iPhone PWA install instructions in the /download page, in plain English, in 10 languages.

  8. No native Apple Store app planned. Apple's guidelines forbid non-KYC P2P crypto apps; Morphit doesn't pretend otherwise. The PWA path is the lasting answer.

  9. Operator section on the /download page shows the run-your-own-node path: source code, releases, setup walkthrough, supported systems, federation directory.

  10. RSS feeds for the orderbook — real-time updates in your existing RSS reader. Asset-filtered, account-filtered, full-orderbook variants.

  11. SSE streams for the orderbook — live deltas without polling.

  12. no-js graceful degradation. The footer link advertises that the static parts of Morphit work without JavaScript, for users on Tor's max-security level or otherwise locked-down browsers.

  13. Public, free, documented HTTP API. Anyone can build a block explorer, an aggregator, a CLI client, a price feed, a federation health monitor — without asking permission.

  14. API self-hosting recommended at scale. If you're building something high-volume on the API, the recommended path is to run your own indexer ($5/month VPS) — no negotiation, no allowlist, no rate limits.

  15. Federation health visible to everyone. /instances shows every known instance and its probe status. Aggregators and end users alike can monitor the federation in real time.

  16. Reachable at a .eth name, no DNS required. Every operator can advertise an ENS name — ours is morphit.eth — and ENS-aware browsers like Brave and the MetaMask browser resolve it straight to the site, with no dependency on the DNS system or any single registrar. We link the bare name, not an eth.limo-style gateway, so there's no centralized resolver sitting in the path. If morphit.io were ever seized at the DNS level, the .eth name would still point the way in.

16. Built-in tools — block explorer, activity stats, payment QR codes

  1. Built-in block explorer at /explorer. Search by Blurt account name, transaction ID, or block number — Morphit ships its own explorer so you don't have to trust a third-party block-explorer site (which sees your IP and search history). The explorer is served by the same indexer that powers the orderbook; same trust model, same operator, no extra service to inspect.

  2. Trading-activity dashboard at /explorer/activity. Daily fee revenue, top-5 trading pairs, federation-wide order volume — all derived from public chain data, no analytics scripts. Useful for traders deciding which assets are liquid, and for operators showing prospective traders what the marketplace looks like at scale. Same data the project uses internally; nothing hidden.

  3. Cross-chain explorer links inside chat with alternatives. When a counterparty sends a Bitcoin txid, the chat bubble auto-routes to mempool.space (or the operator's configured explorer); Monero to xmrchain.net; Blurt to the in-app /explorer. A small "+N more ▾" next to the link reveals bundled alternatives — mempool.observer and blockstream.info for BTC, localmonero.co and moneroblocks.info for XMR, similar choices for the other chains — for users who don't trust or can't reach the primary. Grandma's default click is unchanged; the dropdown is opt-in progressive disclosure.

  4. Display-payment QR codes for receiving addresses. Share a receive address through the trade flow and Morphit can render it as a QR code on screen, using the right URI scheme per asset (BIP-21 for Bitcoin-family, official Monero URI, ZIP-321 for Zcash, Solana Pay, EIP-681 for EVM, XRPL URI, and more). The buyer scans with their mobile wallet's camera. Works on .onion instances, works in Tor Browser, works without any third-party QR-image service — the QR library is lazy-loaded so users who never tap "Show QR" don't pay the bytes.

  5. Live Blurt staking APR display in the balance card. Computed locally from chain DGP — no third-party endpoint, no CoinGecko, no fee-feed dependency. (Current chain inflation is 7.6% as of 2026-05-03; ~75% of new emission goes to BP holders pro-rata, so the real APR per staked BP unit varies with the vesting pool size.)

17. Trade anything — barter, cash, precious metals

  1. Curated registry of 40+ payment methods organized by category: crypto (BTC ↔ XMR, etc.), bank rails (Zelle, Interac e-Transfer, SPEI, Oxxo Pay, SEPA), in-person, and operator-defined extras. Pickers fuzzy-match on the canonical 40-entry list to avoid the "did you mean Cash App or CashApp or Venmo or PayPal" dropdown soup.

  2. BRICS Pay supported as a first-class payment method. The BRICS+ cross-border payment rail (live in pilot in Russia 2026; rolling out to India/Brazil/China/South Africa/Indonesia/Saudi Arabia through 2026 Q4) is in the registry alongside PayPal, Alipay, and other consumer rails. Connects national payment systems (Pix, UPI, UnionPay, PayShap, SPFS, CIPS) without going through SWIFT. Users in any BRICS+ jurisdiction can pick it from the same dropdown they pick any other rail; the federation doesn't gatekeep which rails operators or traders use.

  3. Barter for goods is a first-class payment method. Trade crypto for a used bicycle, a vintage typewriter, or a haircut — the chat flow has "Goods or services" as a payment method alongside cash and bank transfer. Photos can be attached (chain-stored, signed). The seller and buyer negotiate; Morphit just provides the orderbook + chat + escrow-free settlement on the asset side.

  4. Cash + precious metals (gold/silver coins/bars) also covered as in-person methods. Meet up, exchange, leave on-chain feedback. Morphit's role ends at "facilitating the introduction"; the actual exchange is between two humans.

  5. Cash by mail is its own payment method, with structured proof-of-shipment. Distinct from "Cash in person" because the operational reality is different: you mail an envelope of paper currency to your counterparty across town or across the world. The chat composer has dedicated "Share mailing address" and "Record shipment" buttons that build structured payloads — recipient sees a 📬 address pill (copy-formatted button) and a 📦 shipped-via pill with a clickable "Track package" link. Both pills stay in end-to-end-encrypted chat only — never written to the indexer, never on-chain, never federation-readable.

  6. Top 20 worldwide carriers bundled with clickable tracking links. The Record-Shipment modal includes a curated dropdown — USPS, UPS, FedEx, DHL Express, Royal Mail, La Poste, Deutsche Post, Poste Italiane, Correos, Poczta Polska, Pochta Rossii, China Post EMS, Hongkong Post, Japan Post, Australia Post, Canada Post, India Post, Iran Post, SF Express, Aramex — covering every supported locale's primary postal service. An "Other (specify carrier)" escape hatch lets users type any carrier name + tracking URL when their service isn't bundled. Tracking number is optional (not required) so users who chose untracked mail can still record the shipment.

  7. Operator-defined payment methods. Per-instance, an operator can add region-specific payment rails their community uses (a local fintech app, a national bank-transfer system) without forking the codebase — the registry is operator-extensible.

  8. Orderbook filters every tradable asset, automatically. The /orderbook page's asset dropdown is wired to the canonical ASSET_TICKERS registry, so any new asset that becomes tradable appears as a filter option the same moment the rest of the app learns about it — no separate "remember to update the filter" step. A asset-select-coverage-smoke enforces this structurally by failing CI on any future <select> that hardcodes a partial ticker list.

18. Operator setup — even your grandma can run a node

  1. Beautiful CLI setup wizard. The wizard walks new operators through everything: pre-flight system check, ELI5-friendly prompts for the basics (instance name, accounts, networks), review-and-confirm screen, write the config. End-to-end in about 15 minutes. It also generates a Tor .onion for you in the background (no waiting, no key-grinding) and hand-holds you through server hardening — SSH lockdown, firewall + fail2ban, automatic security updates, kernel hardening, and intrusion detection — as a short run of one-keystroke "yes" confirmations; the shipped Ansible role applies all of it by default.

  2. Browser setup-wizard for live config tweaks. Once your instance is up, visit /admin/setup-wizard on your domain to toggle which assets you list and to add or remove per-instance payment methods. The page emits the exact env-var line or CLI command — paste into morphit.config.env (then restart the indexer) or into your terminal (no restart). Read-only by design — never mutates your server, no auth-gating attack surface to maintain; full operator UX walkthrough in docs/RUN-A-MORPHIT-NODE.md.

  3. The system check tells you what's wrong, not just "ERROR". Pre-flight verifies CPU, RAM, free disk, OS family, and network reachability — and if any check fails, you get a specific human-readable explanation of what to do next.

  4. One-command deployment. Once the config is written, a single command brings up the indexer, relay, and database in one shot.

  5. Federation registration is one CLI broadcast. After setup, a single chain op puts you in the federation directory worldwide — you show up on every other Morphit instance's /instances page within seconds.

  6. Operational runbook with concrete cron snippets. OPERATIONS.md ships copy-pasteable cron snippets for the operational tasks that should be automated (TLS certificate renewal monitoring, nightly database backups). Set up once, the runbook walks you through verifying each.

  7. Sign in to a strange computer by scanning a QR with your phone. Posting key never leaves the phone. Your phone shows a confirmation card with the website name so you can spot phishing like morph1t.io before tapping "Yes, that was me." See docs/adr/0022-desktop-qr-pairing.md for the full protocol and threat model.

  8. Adding new tradable assets is usually a single day's work. The canonical asset list lives in one package (packages/asset-registry/); add an entry with the right flags (tradable, can-pay-fees, supported-networks), drop a logo, add per-asset translations, register the explorer URL templates. Pre-2026 the same change required edits at 32 separate sites; now it's contained. Currently shipped: 16 tradable assets (BTC, XMR, BLURT, USDT/USDC/DAI (multi-network EVM stablecoins), BCH, LTC, DASH, DOGE (UTXO chains), ZEC, ARRR (shielded chains), DCR (hybrid PoW/PoS), SOL, ETH, XRP), plus barter (goods/services) as a distinct trade type that rides on top of those coins.

  9. Adding a new language is a single-array edit. Drop a translation JSON, add the locale code to the supported array. The framework knows the difference between "shipped" and "in progress" — work-in-progress translations don't appear in the language switcher until they're done. Translator workflow is documented for native-speaker contributors.

  10. Witness fee alerts carry actionable delta information. When Blurt's chain account-creation fee changes (the cost an operator's relay pays for each signup), the operator gets an alert with the old value, the new value, the percentage change, and the direction — not just "fee changed."

  11. Build from source, with reproducibility as a project goal. Operators can build the frontend locally and verify the bytes match what the project published; the build emits a SHA-256 manifest of every served file, recorded on chain. No privileged build pipeline — every operator builds the same source.

  12. Operators publish two I2P addresses, both render. Operators with both a long-form .b32.i2p (always-resolvable) AND a human-readable .i2p alias can publish both. The footer renders both as separate chips; the directory shows both for every operator that publishes them. Backwards-compatible with single-address operators.

  13. Discretionary bug bounty program. Find a real security bug — privacy leak, signup-drain vulnerability, cryptographic flaw — disclose responsibly via @agorise:matrix.org, and the operator may compensate you in BTC, XMR, or Blurt at their discretion. No formal program scope, no rigid payout grid — the operator decides based on severity, novelty, and demonstrability. Honest framing: this isn't HackerOne, it's a thanks-with-money for genuinely good security research.

  14. Weekly automated warrant canary. Every week the operator regenerates a PGP-signed statement at /canary.txt ("no NSL, FISA order, gag order, or backdoor demand") carrying live freshness proofs — the current Blurt and Bitcoin chain heads and a fresh news headline — so it can't be replayed from an old copy. If it stops updating for two weeks, the frontend flags the silence to users: an operator under a gag order can stop publishing instead of being forced to lie. Federated instances run their own, so coordinated suppression shows up as simultaneous silence.

  15. PGP keys link in the footer for canary verification. Operators publish their release-signing keys as a downloadable .asc file. Anyone can import and verify operator-signed canaries and releases. Footer link translated to all 10 locales.

  16. Server hardening below the application layer is documented in copy-pasteable detail. SSH, unattended security upgrades, kernel hardening, filesystem mount hardening, systemd unit isolation, Postgres SCRAM-SHA-256, encrypted backups, outbound egress allowlist, alerting — operators can apply as much or as little as fits their threat model. Recommended baseline highlighted explicitly.

  17. High-value account names get extra friction. Short names, obvious brand names, common dictionary words, and enumeration patterns get classified at signup time and handled per the operator's policy. Three policy modes (strict / moderate / off) — operator's call. Legitimate year-suffix names (bob-1990, crypto-noob-2026) explicitly pass.

  18. Sequential signup pattern detection. Patterns like account001 / account002 / account003 get caught at signup time — operator-tunable, per-IP-bucket isolation so an attacker controlling multiple ranges still hits the threshold separately on each.

  19. Trusted-proxy IP allowlist with CIDR support. Operators running behind a reverse proxy (BunkerWeb in Docker, multi-host nginx, etc.) can correctly preserve client IPs for rate limiting. Without this, a Dockerized reverse proxy would funnel every client through a single rate-limit bucket — one abuser exhausting the daily cap for everyone.

  20. Turnkey BunkerWeb deployment with cross-reference parity enforcement. The morphit repo ships a tested BunkerWeb config at ops/bunkerweb/ — docker-compose + env template with OWASP CRS paranoia 3, anti-Referer: none on the invite endpoint, real-IP forwarding wired correctly, and a pinned 172.20.0.0/16 Docker network CIDR. A CI smoke (cp61-O14) enforces that the Ansible default for MORPHIT_RELAY_TRUSTED_PROXY_IPS matches this CIDR — getting them out of sync (the cp61-D1 bug, fixed at cp61) silently breaks per-IP rate limiting. Operators copy + edit two values + docker compose up -d and have a WAF-fronted instance.

  21. Cross-document value-invariant CI gate, registry-driven. When one value lives in multiple files (DB name, port, account, network name, CIDR) and one file drifts, the deploy breaks silently. The cp66 smoke generalizes cp61-O14 into a registry of invariants — each with a single source-of-truth file and a list of consumer files that must agree. Eleven ship at launch (postgres DB name, postgres user, postgres port, treasury fee-recipient default, indexer and relay BunkerWeb bind ports, bunkerweb_net network name, relay and indexer bare-metal listen-port defaults, matrix-bot healthcheck port, BunkerWeb network CIDR); adding new ones is data, not new runner code, and every drift is mutation-tested.

  22. Operator-doc section length is bounded by CI. OPERATIONS.md, RUN-A-MORPHIT-NODE.md, PRE-LAUNCH-CHECKLIST.md and ADRs are detailed by design, but a section that grows past its per-doc threshold becomes a small book inside a larger book — search context balloons, readers lose place, edits get scary. The cp69 smoke flags newly-outsize sections so they get split into sub-runbooks instead of growing forever. Existing oversize sections are allow-listed with a documented plan to split.

  23. Ansible playbook idempotency is enforced by CI. The README promises "re-running the playbook is a no-op when the system is in the desired state." Tasks using command:, shell:, or raw: execute arbitrary processes — Ansible can't tell whether they changed state, so they need an explicit guard (creates:, removes:, changed_when:, when:, check_mode:). The cp69 smoke walks every ansible task; an unguarded action surfaces in CI so the playbook stays trustworthy.

  24. Unit-test pass count is locked by CI. The cp71 vitest-must-pass smoke runs vitest --run per workspace (indexer, relay, web — 1,344 tests across 3 workspaces) and asserts the pass count meets a baseline. Test-rot — handlers evolving without their tests being updated — used to go undetected for months. Now a drift incident surfaces immediately as a smoke failure, so handlers and their tests stay in lock-step.

  25. Untrusted-input parseInt is forbidden without a strict pre-check. parseInt('999000abc', 10) = 999000 silently accepts trailing garbage. When the input is operator-controlled or user-controlled (HTTP headers, query params, env vars), the partial parse can let malformed values past the validity check. The cp71 smoke greps the codebase for parseInt/parseFloat on plausibly-untrusted inputs and requires each to be preceded by /^\d+$/.test(s) or document-able as trusted in the allow-list.

  26. Every fetch() has a timeout. Without an AbortController + setTimeout, a slow or hung remote endpoint blocks the calling code indefinitely — a UI in 'loading' forever, an ops-cli command that never exits. The cp71 smoke walks all .ts and .svelte source and verifies every fetch() call has a signal: from an AbortController nearby (or is allow-listed as a browser-managed exception). 14 unbounded fetches were caught and converted to use a centralized fetchWithTimeout helper at cp71 ship time.

  27. Every route's SEO metadata is locale-complete. When a new route is added to apps/web/src/lib/seo/routes.ts, the matching seo.<key>.title and seo.<key>.description must exist in all 10 locales — or the route ships with empty meta tags in the locales that forgot. The cp74 smoke walks the route registry against every locale JSON and fails CI if any pair is missing. This caught cp73-D11 (missing seo.privacy_index in 10 locales) statically, so future routes can't slip through with English-only SEO.

  28. Squatter defense operator playbook. A tactical runbook for operators concerned about name-squatting: env config, log monitoring, attacker-pattern recognition, weekly audit procedure, active-attack incident response, network-layer defenses, and a "diamond-hardened" preset for operators willing to accept moderately higher friction for maximum resistance.

  29. Comprehensive threat model with documented attack scenarios. Every credible attacker behavior across the four primary attack surfaces (frontend, indexer, relay, Blurt chain) is enumerated as a STRIDE row, with the existing in-code mitigation named and cross-referenced. Residual risks stated honestly; open gaps flagged. Regenerated when meaningful new attack surface ships.

  30. Operator alerts to a private Matrix DM with three-tier routing. A turnkey sidecar (apps/matrix-bot/) tails journalctl, classifies indexer + relay events into CRITICAL (immediate DM, no rate limit), WARN (1/hour per category), and INFO (daily 09:00 UTC digest, skipped on quiet days), and DMs the operator's private MXID end-to-end-encrypted. Branded TypeScript types prevent confusing the private MXID (@user:server) with a public room alias (#room:server) at compile time — security disclosures never accidentally route to a public channel. Comma-separate multiple MXIDs in MORPHIT_MATRIX_BOT_ALERT_MXID for vacation coverage.

  31. Resource alerts that read like advice, not alarms. A POSIX-sh sidecar polls disk, memory, swap, CPU, and swap-thrashing every 5 minutes; alerts go through the matrix-bot in three tiers with ELI5 advice and the exact debug command ("free space NOW: sudo journalctl --vacuum-time=7d, sudo apt clean"). Sidecars exit silently on hosts without the things they monitor — safe to enable defensively across operator instances.

  32. Kernel-log monitoring catches what the resource monitor can't. A separate sidecar scans the kernel ring buffer every 5 minutes for OOM-killer activations (with the victim process name and PID), kernel oopses and panics, hardware errors (MCE / EDAC / ATA), and morphit-service segfaults. The resource monitor sees memory pressure building; the kernel-log monitor sees what got killed when it broke. Cursor-based state means successive runs don't re-alert on old events.

  33. Disk health and RAID monitored before silent data loss. SMART self-tests every 6 hours alert on imminent drive failure, reallocated/pending sectors, and high temperature with the exact smartctl -a /dev/X command to investigate. Linux software RAID (/proc/mdstat) is checked every 15 minutes for degraded or failed arrays. Sidecars exit silently on hosts without SMART/RAID — safe to enable defensively.

  34. The "alerting is silently failing" detector — and the silent TLS-renewal-failing detector too. Most monitoring stacks miss two killer patterns: email alerting that broke silently (smarthost credentials rotated, TLS cert expired) and certbot renewals that stopped working months ago. Morphit's postfix-queue monitor alerts via the matrix-bot when mail queue depth or oldest-message age cross thresholds — alert still arrives when email is dead. The certbot monitor correlates cert expiry against the last successful renewal in letsencrypt.log and fires renewal_stalled long before the cert actually expires.

  35. OS health surfaced through the same channel as everything else. Pending security updates (apt list --upgradable parsed for the -security suffix), systemd units in failed state (caught by the systemd-monitor since failed-to-start units emit no journal output journalctl-based alerting can route), journal disk growing toward gigabytes (catches "journal silently grew to 8 GB over six months"), and a daily trivy Docker-image CVE rescan against running containers — all DMed with the exact remediation command. Operators don't have to read every CVE advisory or check the motd.

  36. Docker Compose service health, including the silent-unhealthy state. docker compose ps --format json is polled every 5 minutes; service_unhealthy fires when the container is running but its declared health-check is failing — the silent-degradation state most operators miss because docker ps still shows "up." Restart-loop detection covers services whose restart: always policy is masking a real bug.

  37. One-command Ansible deployment. Fill in group_vars/all.yml (8 mandatory values: domain, operator account, posting key file, db creds, alert MXID), run ansible-playbook playbook.yml, and 25 minutes later you have a fully-configured Morphit instance with BunkerWeb WAF, systemd services, postgres, certbot TLS, matrix-bot alerts, and host monitoring. Idempotent — re-runs only change what drifted. The full playbook source is ops/ansible/.

  38. Native-language translations across every locale, not English fallbacks. A systematic audit and translator pass closed real translation gaps — strings that had been silently shipping in English because earlier translator passes missed them. Now backed by a regression smoke that flags any same-as-English value outside a documented allow-list, so future translator drift fails CI rather than user-report time.

  39. Plain-language /glossary route. "Trade-only," "trust score," "orderbook," "escrow-free," "federation" — defined in plain English with a one-sentence example each, not crypto-jargon. No need to keep a browser tab on Wikipedia open while learning Morphit. Linked from every page footer.

  40. In-context glossary tooltips. A <Term> component surfaces glossary definitions on hover or tap, with a dotted-underline cue on first appearance per route. Restrained by design — callers opt-in word by word rather than auto-detecting across rendered text. Power users get the protection; everyone else sees clean reading flow.

  41. Onboarding copy softened — same custody truth, less doom-laden framing. The seed-phrase confirmation reads as a commitment to action ("I'll keep these 12 words safe — I know they're the only way back into my account") rather than a legal disclaimer ("I understand losing this means everything is gone"). Same fact, friendlier voice, in all 10 locales.

  42. "Your fee-rejected order silently vanished" cliff closed. When the relay rejects your listing fee for any reason (wrong amount, wrong fee_method, low operator balance, wrong recipient), you get a chat message explaining exactly which validation step failed and the corrective action. No more "I posted my order three hours ago and it never appeared" mystery.

  43. Chat composer surfaces a soft proofread reminder before accidentally-public chat goes out. When you're typing what looks like a private message ("my address is...", "my real name is...", "my bank account is...") into a public chat channel, Morphit shows a soft amber banner: "This channel is public. Did you mean to DM?" One tap to keep typing, one tap to switch to DM. Doesn't block; just nudges.

  44. Printable seed-phrase backup card. One click in the onboarding flow prints a paper-friendly backup card via the browser's native print dialog — no PDF library, no server round trip, no third-party dependency. Seed phrase never leaves the device. Pick paper or save-as-PDF; the rest of the page is hidden during print.

  45. First-post starter pack. First-time posters see a green-tinted card with three safe-default tips (start small, 7-day expiry, pick payment methods you actually accept) and a deep link to the trade-walkthrough FAQ. Self-hides once the user has any prior posting experience. Privacy posture: client-side only.

  46. Centralized locale-aware number/date formatters. Currency, percent, Blurt amount, count, and date helpers all read the active locale. A German user sees "1.234,56" where a US user sees "1,234.56" — no ad-hoc .toFixed() calls drifting across the codebase.

  47. Printable one-page cheat-sheet at /cheat-sheet. A landscape A4 / US Letter sheet with the trade flow on the left, the chat-paste safety rules in the middle, and the per-asset quick-reference table on the right. Fold and put it on your desk; hand it to the grandma you're onboarding. Print-friendly CSS strips colors and reformats for a single black-and-white page.

  48. Identity-label policy enforced consistently. Every place a user account name appears in the UI renders with its identicon, so brand-new Blurt accounts are visually distinguishable. Spoofing attempts like @morph1t vs @morphit are visually obvious, not just textually different. Backed by a regression smoke catching future raw-render drift at CI time.

  49. Onboarding back-button on the review stage that wipes the just-generated seed before returning to the path picker. A confirmation modal warns the user they're discarding the 12 words; on confirm, the seed is wiped from memory and the form state resets. Three "discard the unsaved identity" code paths now use the same wipe pattern.

  50. /post remembers your fiat currency and region across sessions. Stored in your browser, never sent to any server, never on chain. Clear the preference any time from /settings. A "Preferences" section lets you review what's saved.

  51. Route-transition focus management for screen-reader users. Navigating from page to page moves focus to the main region on every real route change. Screen readers announce the page change; sighted users see no visual disruption. Heading hierarchy is audited and codified as a regression smoke so future drift fails CI.

  52. Static-source color-contrast smoke. Every text/background color pairing across the frontend is checked against WCAG AA at the source level — 161 pairs across 96 Svelte files, zero below threshold.

  53. Treasury chain-pin closes a real fork-attack vector. BTC/XMR fee addresses are signed by @morphit on chain via the existing release trust anchor. Every federated indexer prefers the chain-pinned address over its own configured value. A hostile fork can only divert fees on its own instance — every other federated indexer marks those orders unverified, and the divergence is itself a defection signal anyone scraping multiple instances can detect.

  54. No Morphit instance — not even canonical morphit.io — holds any user's funds. Every trade settles peer-to-peer between the two parties' wallets. The operator runs an orderbook + chat relay + fee-collection account, not a custodial pool. If morphit.io shut down tomorrow, every order still settles via any other federated instance — your funds were never on morphit.io to begin with.

  55. Per-operator chat-link external explorer URLs. When a counterparty sends a BTC or XMR transaction ID in chat, Morphit renders it as a clickable link that opens the transaction in an external block explorer. Operators who self-host their own explorers can override per-instance; everyone else inherits the bundled defaults. The override is per-operator (not per-user) — a user who wants different behavior chooses a different Morphit instance.

  56. Multi-explorer quorum gate on fee verifiers. Operators can require N-of-M explorer agreement before accepting a fee verdict. Below the threshold, the verifier marks the order pending-external rather than accepting a degraded single-source result. Default is 1 (back-compat with smaller instances); operators with the full 5-explorer default list can set the threshold to 2 or 3 for genuine multi-source cross-check.

  57. Setup wizard configures explorer URLs with live health probes. Each URL gets a ✓ / ⚠ / ✗ status indicator with latency on screen. Probes hit each explorer's standard health endpoint — no real transaction IDs or addresses sent. Non-blocking: operators can configure URLs that fail probes (might be configuring an explorer not yet online, or running offline).

  58. Per-operator listing fee USD target with live price recompute. The operator picks a USD target (default $0.25), the wizard fetches live BTC/USD and XMR/USD prices, computes equivalent amounts, displays them, and asks for accept-or-override. Same step is reachable from the maintenance menu for ongoing tuning.

  59. Pre-launch + day-zero + week-one runbooks: three distinct documents, one continuous operator experience. Pre-launch checklist → launch-day rehearsal + T-zero procedure + first-hour monitoring + rollback plan → week-one monitoring rolled up daily and weekly. Each doc has clear handoff to the next. Community operators get a wizard that configures the node and runbooks that tell them what to do with it.

  60. Federation cost attribution: each operator's relay pays only for ops that route through their own instance. Before this fix, every federated indexer would have queued payouts on every op it saw — multiplying treasury spend by the federation count. Now each operator only pays the welcome bonus, refills, and loyalty BP for ops that name their instance tag. The operator getting the 90% fee reward is also the operator obligated for the consequences.

  61. Reputation attack-surface audit closed two real gaps. Untethered "free" feedback citations are now rejected (fake-feedback targets require a real listing fee payment). Coordinated low-rating pile-on detection catches Sybil clusters depressing a real trader's reputation, with strict false-positive guards so a legitimate user reviewing multiple counterparties is never flagged. Flagged reviews stay visible on the subject's profile list but don't drive the numeric rating.

  62. QR-pair real sign-in: read-only desktop session. Pairing your phone establishes a read-only session on the desktop — posting key stays on the phone, all writes route through the phone for signing. WhatsApp-Web mental model — phone is the source of truth, desktop is a window. A clear banner keeps you aware of session shape; "use your phone to sign this" affordances appear on every write surface (post an order, send a chat, leave feedback).

  63. Paired-readonly affordance gap sweep. Every write call site explains why you need your phone, with deep links that preserve context (which order to edit, which peer to message). No more silent disappearances or misleading "session locked, unlock to continue" CTAs that paired users can't satisfy.

  64. Price-model picker on /post/edit. Change your spread or flat price without cancelling and re-listing. Loses no engagement metrics, no fee status, no prior view counts. Defensively handles legacy and unknown shapes — never silently drops user intent.

  65. Persona walk-throughs as standing engineering discipline. Three personas run end-to-end at the top of every major session: Bob (existing Blurt user), Sally (never owned crypto), Sally-as-operator (sets up her own node from any of the operator docs). Findings get fixed inline; locale parity across 10 languages holds throughout. Catches UX gaps no backlog list catches.

  66. Operator-doc audit pinned by regression smokes. Every CLI command, every environment variable, every API field path, every install location named in the operator docs is sentinel-grep checked against the real code. When the docs and the code disagree, CI fails loudly before the operator copy-pastes from a doc that lies.

  67. USDT (Tether) peer-to-peer across four networks. Trade USDT on Ethereum (ERC-20), Tron (TRC-20), Solana (SPL), or BNB Smart Chain (BEP-20) — peer to peer, non-custodial, no KYC. The most-traded stablecoin in the world, with the price stability active traders rely on. Trade-only on Morphit (listing fees stay Blurt/BTC/XMR per the frozen fee enum); operators can disable USDT on their instance with one env var if they prefer to specialize.

  68. No default USDT network — every USDT trade is an explicit network commit. Cross-network sends are unrecoverable (USDT-ERC20 to a TRC-20 address loses the funds, period). Morphit's UI refuses to let the user default into that mistake: every USDT trade picks the network deliberately, every USDT address shared in chat carries a bold per-network header and a permanent per-message reminder of which chain it's for, and the post-order form won't submit until the network is chosen. Friction by design — the right kind of friction.

  69. Arbitrage between Morphit and exchanges is built for, not built against. Morphit's listing fee is a fraction of a dollar; no taker fee, no withdrawal fee, no withdrawal limit. The price-model picker lets a trader run a thin-spread arbitrage strategy on their own listings (set spread: 0.5% and let the orderbook fill at-or-above CoinGecko mid). As liquidity grows, arbitrageurs pull the P2P prices into line with the worldwide market — good for everyone.

  70. Each instance's asset policy is visible up front. Open /about-this-instance on any Morphit and you see which assets that operator accepts at a glance — green for "accepts everything," amber for "accepts most," red for "tight policy." No surprises after you've already posted an order.

  71. No flash of English content for non-English speakers. Every page is prerendered per locale — /de/orderbook ships German bytes, /fa/orderbook ships Persian, /zh-HK/orderbook ships Traditional Chinese. No layout flicker, no client-side translation reload — what you see is what you get from the first byte.

  72. Bitcoin Cash (BCH) peer-to-peer. Trade BCH on Morphit — bigger blocks and lower fees than BTC, transparent and decentralized with no issuer who can freeze addresses. Single mainnet, single CashAddr address format, no bridges. Trade-only on Morphit (listing fees stay Blurt/BTC/XMR per the frozen fee enum).

  73. Setup wizard handles trade-only-asset opt-out — no manual env editing. Step 13 of morphit-ops init walks operators through each tradable asset and asks per-ticker whether to disable. Picks emit the right MORPHIT_INDEXER_DISABLED_ASSETS= line automatically. Grandma-friendly: zero shell editing for the most common operator-stance decision.

  74. Litecoin (LTC) peer-to-peer. Trade LTC on Morphit — fast 2.5-minute blocks, low transaction fees, transparent and decentralized like Bitcoin with no central issuer. Three address formats accepted (legacy L, P2SH M/3, bech32 ltc1). Trade-only on Morphit (listing fees stay Blurt/BTC/XMR).

  75. Dash (DASH) peer-to-peer. Trade DASH on Morphit — fast-confirmation Bitcoin-family chain with optional InstantSend (sub-second confirmations) and opt-in PrivateSend mixing via masternodes. Two address formats accepted (X legacy, 7 P2SH). Trade-only on Morphit (listing fees stay Blurt/BTC/XMR).

  76. USD Coin (USDC) peer-to-peer across four networks. Trade USDC on Ethereum, Solana, Base, or Polygon — peer to peer, non-custodial, no KYC. Pick whichever network you and your counterparty both support; Morphit's network picker locks it in at post time so a cross-network send can't accidentally lose your funds. Honest disclosure: Circle (the issuer) can freeze any USDC address on demand — exactly why Morphit ships USDC as trade-only and never pays its own listing fees in it.

  77. Dai (DAI) peer-to-peer across four networks — the meaningfully-decentralized stablecoin. Trade DAI on Ethereum, Polygon, Base, or Arbitrum — peer to peer, non-custodial, no KYC. Unlike USDT and USDC, DAI is not issued by a corporate entity — it's governed by MKR token-holders through on-chain votes, with no admin-freeze function on the token contract itself. Honest nuance: MakerDAO's Peg Stability Module holds USDC as collateral, so Circle's freeze power indirectly affects DAI redeemability — meaningful-but-not-perfect decentralization.

  78. Dogecoin (DOGE) peer-to-peer. Trade DOGE peer to peer — non-custodial, no KYC. Fair-launched in 2013 with no premine after the first year, merge-mined with Litecoin since 2014 so DOGE inherits LTC's hashrate-security. Transparent base layer; wallet-side address rotation is the privacy lever — trade-only on Morphit.

  79. Zcash (ZEC) peer-to-peer with per-address privacy choice. Trade ZEC peer to peer — non-custodial, no KYC. Two address families coexist on the same chain: transparent (t1/t3, publicly-visible like Bitcoin legacy) and shielded (zs1 Sapling, u1 Unified Address) that hide sender, recipient, and amount via zk-SNARKs. Pick the address type that fits each trade's privacy posture — trade-only on Morphit.

  80. Pirate Chain (ARRR) peer-to-peer with chain-level shielded transactions. Trade ARRR peer to peer — non-custodial, no KYC. Pirate Chain runs only the Sapling zk-SNARK shielded pool, so every transfer hides sender, recipient, and amount by construction (no transparent address option at all). Single address format (zs1 Sapling), trade-only on Morphit.

  81. Decred (DCR) peer-to-peer with hybrid PoW/PoS consensus and on-chain governance. Trade DCR peer to peer — non-custodial, no KYC. Every block is mined by PoW miners AND voted on by 5 PoS ticket-holders, so neither group alone can change protocol rules. On-chain governance via Politeia lets stakeholders propose, debate, and ratify changes — trade-only on Morphit.

  82. Solana (SOL) peer-to-peer with delegated Proof-of-Stake and high-throughput PoH sequencing. Trade SOL peer to peer — non-custodial, no KYC, no central freeze authority. Solana addresses look identical to USDT/USDC SPL token-account addresses, so the asset field on each order disambiguates — Morphit shows you which asset you're sending. Trade-only on Morphit.

  83. Ethereum (ETH) peer-to-peer with post-Merge Proof-of-Stake. Trade ETH peer to peer — non-custodial, no KYC, no central freeze authority. EVM addresses look identical across ETH/USDT-ERC20/USDC-ERC20/DAI-ERC20/Base/Polygon/Arbitrum, so Morphit's asset + network fields disambiguate (and ENS names aren't resolved — no centralized RPC dependency). Trade-only on Morphit.

  84. Ripple (XRP) peer-to-peer with Federated Byzantine Agreement consensus. Trade XRP peer to peer — non-custodial, no KYC. Native XRP cannot be frozen by any central authority (only IOU-token variants on XRPL can; native XRP cannot), and Morphit's post-flow surfaces the two XRPL gotchas — destination tags (required when sending to exchange-hosted addresses) and the 1-XRP base reserve (first receive needs ≥1 XRP). Trade-only on Morphit.

  85. Moderate your own instance without becoming a censor. An operator can review the abuse signals the indexer already collects — reciprocity rings and likely-same-person accounts — and hide a troublesome account's listings from their own instance. A block is instance-local: it broadcasts nothing to the chain, touches no funds or keys, is fully reversible, and has zero effect on any other Morphit instance. The blocked person stays fully visible on every other instance and sees a plain-English banner saying exactly that — no single operator can erase anyone from the federation.

  86. Check your Blurt RPC health before you rely on it — and one dead node never freezes your instance. morphit-ops doctor and the setup wizard probe every configured RPC endpoint with a real chain query — not just DNS — and report which are reachable before you depend on them; /v1/health shows how many are healthy at a glance. The indexer now ships the same vetted default node list the relay always had, so a missing or stale config falls back to working nodes instead of stalling — and a dead, rate-limited, or flapping node is routed around automatically.

  87. Runs across the whole Debian/Ubuntu family — including hardened, lightweight servers. The setup pre-flight (apps/ops-cli/src/init/systemCheck.ts) green-lights Ubuntu 24.04/26.04 LTS and Debian 12+ as first-class bases and recognizes popular derivatives automatically from their base codename — Linux Mint, Pop!_OS, Zorin OS, KDE neon, and elementary OS. Debian-minimal and hardened-Debian distros like Kicksecure make excellent lean, security-focused nodes: the one-command Ansible installer targets the Ubuntu 24.04 'noble' family, while Debian and Kicksecure install via the documented manual steps, and the recognition is locked by apps/ops-cli/scripts/system-check-os-smoke.ts.

  88. Save any chat as a locked, court-ready PDF anchored to the blockchain. Export a conversation to a tamper-resistant PDF: it's locked against editing, and every message cites its Blurt transaction ID as a "Blockchain proof" anyone can re-verify on a public block explorer. A plain-language explainer walks a judge or jury through confirming each line against the immutable chain — the document's integrity comes from the blockchain, not from trusting the file. It's generated entirely in your browser from the already-decrypted messages, and the PDF engine is only fetched the moment you export, so it costs nothing until you need it.

  89. A reputation score that shows its work — and can't be bought with volume. Alongside the raw trade count, each trader gets a 05 composite reputation score: their time-decayed rating, shrunk toward neutral so a single glowing (possibly fake) review can't spike a newcomer, plus a bounded track-record bonus that applies only when the rating is already above neutral. A high-volume scammer stays low; sustained good behaviour is rewarded. The reputation-receipt endpoint returns the full factor breakdown so anyone can re-derive the number from the raw feedback rows.

  90. Every timestamp is 24-hour UTC, to the second. Dates and times sitewide — pages, PDFs, and exports — render as "30 June, 2026 @ 16:45:18 UTC": day-first, the month translated into your language, 24-hour clock, a literal UTC suffix, and seconds. Unambiguous across time zones and locales, and precise enough to line up with an on-chain transaction if a record ever has to hold up in a dispute.

How to verify any of the above

Every claim in this document is verifiable. The repository is at git.agorise.net/agorise/morphit. Specific anchors:

  • Smoke suite: bash scripts/run-smokes.sh — runs several thousand self-checks across ~280 runners, triple-pulse stable
  • Audit log: docs/AUDIT-2026-05.md
  • Architecture decisions: docs/adr/0001-*.md through docs/adr/0051-*.md (50 ADRs; 0016 was retracted and the number isn't reused)
  • Fees and rewards: docs/FEES-AND-REWARDS.md (line-cited to source)
  • Public API: docs/API.md
  • Operator runbook: docs/OPERATIONS.md
  • Security disclosure: docs/SECURITY.md (Matrix-only)
  • Frontend integrity: every page's served bundle hashes against the on-chain morphit_release_v1 op
  • License: LICENSE (AGPL-3.0)

Don't trust this list. Verify it. That's the whole point.


344 specific selling points. None of them invented. All of them shipped, documented, or honestly disclosed as backlog. If you find one that isn't accurate, open an issue at git.agorise.net/agorise/morphit and we'll either fix the claim or fix the code. Last updated: 24 July, 2026.