-
Morphit v1.21.16
StableAll checks were successfulmorphit-ci / Supply-chain audit gate (every advisory triaged, none fixable in range) (push) Successful in 40smorphit-ci / TypeScript typecheck (sweep all workspaces) (push) Successful in 1m16smorphit-ci / apps/web svelte-check (svelte-kit sync + svelte-aware tsc) (push) Successful in 55smorphit-ci / Integration tests (real Postgres 16) (push) Successful in 6m23smorphit-ci / ansible-lint (playbook quality gate) (push) Successful in 49smorphit-ci / Smoke suite (run-smokes.sh, pulses 1–2 of 3) (push) Successful in 1h4m28smorphit-ci / Smoke suite (run-smokes.sh, pulse 3 of 3) (push) Successful in 32m0smorphit-release / Build + publish release tarball (push) Successful in 44m33sreleased this
2026-10-26 14:48:38 +00:00 | 0 commits to main since this releaseMorphit v1.21.16
The chat's buttons say what they do, and name the coin. The button at the bottom of a trade chat used to
read "Pay now" or "Share crypto address" whatever the trade was. Now it names the coin the order is about:- If you are the one who sends the coin, it reads Send BLURT, Send XMR, Send BTC and so on.
- If you are the one who receives it, it reads Share your XMR address (or BTC, LTC…), and for BLURT, which
arrives at an account rather than an address, Share your Blurt account. - A goods-and-services order that accepts one coin names that coin too, and when that coin is BLURT, "Send BLURT"
sends it from the app like on a BLURT order (before, it asked you to paste a transaction id). One that accepts
several coins keeps "Pay now" and "Share crypto address", since the coin is chosen in the next step.
The "Share your … address" window now offers only the order's coin, so you cannot share an address for a
different coin by mistake. The BLURT button on a shared Blurt account in the conversation reads "Send BLURT" as
well.The chat's subject line reads from your side. Both people used to see the same "RE: I'm buying …" at the top of
the chat, which on the other side read as if they were the buyer. Now the person who posted the order sees
"Regarding my order: I'm buying at least 25 BRL of BLURT with XMR or BTC", and the other person sees "Regarding
@alice's order: Buying at least 25 BRL of BLURT with XMR or BTC". The inbox shows each order the same way:
yours as "I'm buying …", the other person's as "Buying …". A chat saved as a PDF heads the order's messages with
the same line.The buttons fit a phone. On a phone the buttons at the bottom of a chat are full width, one under the other,
and tall enough to tap comfortably; the order's title gets its own line under "Regarding …". On a wider screen
they sit side by side as before.The help pages and their translations use the new button names.
For node operators: stopping a snapshot download always says so. When a snapshot download (fast-sync) was
stopped with Ctrl+C, a closed terminal orkillon the whole process, it could, depending on timing, report "every
source failed" and try the next source instead of stopping with "Nothing was changed". It now always stops.Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
-
Morphit v1.21.15
StableAll checks were successfulmorphit-ci / Supply-chain audit gate (every advisory triaged, none fixable in range) (push) Successful in 44smorphit-ci / TypeScript typecheck (sweep all workspaces) (push) Successful in 1m20smorphit-ci / apps/web svelte-check (svelte-kit sync + svelte-aware tsc) (push) Successful in 50smorphit-ci / Integration tests (real Postgres 16) (push) Successful in 6m41smorphit-ci / ansible-lint (playbook quality gate) (push) Successful in 47smorphit-ci / Smoke suite (run-smokes.sh, pulses 1–2 of 3) (push) Successful in 1h7m54smorphit-ci / Smoke suite (run-smokes.sh, pulse 3 of 3) (push) Successful in 39m32smorphit-release / Build + publish release tarball (push) Successful in 52m48sreleased this
2026-10-24 18:04:50 +00:00 | 1 commits to main since this releaseMorphit v1.21.15
On a Tor or I2P site, every explorer link stays on Tor or I2P. A payment's "view on explorer" link used to
open a clearnet block explorer (mempool.space, Blockchair, etherscan…) even when you were using the site's
.onionor.i2paddress — one click and you left the hidden network. Now a page opened on a.onion,.i2p
or.lokiaddress links only to explorers that are Tor or I2P services themselves:- Bitcoin: mempool.space, Blockstream, mempool.emzy.de, Foundation and Cake Wallet onions, then Blockchair
and 3xpl; on an I2P site, RunBTC's I2P explorer first. - Monero: xmr.mx and P2Pool.io's explorer, then Blockchair and 3xpl; on an I2P site, xmr.mx's and
moneroexamples' I2P explorers first. - Bitcoin Cash, Litecoin, Dash, Dogecoin, Zcash, Solana, Ethereum, XRP and every token network (USDT, USDC,
DAI on Ethereum, Tron, Solana, BNB Chain, Base, Polygon and Arbitrum): Blockchair's and 3xpl's onions. - Decred and Pirate Chain have no working Tor or I2P explorer, so a hidden site shows no link for them; the
transaction id stays on the page to copy. The "check on blocks.blurtwallet.com" link is not shown there either.
Every address was opened in Tor Browser or an I2P browser before it went in. The clearnet site is unchanged.
Two fixes ride along on the links: a Solana transaction's link keeps its signature exactly as written
(letter case matters there), and an Ethereum one always gets its0x.The warrant canary keeps working when clearnet explorers and nodes do not. Its Blurt and Bitcoin block
heights and its news headline now come from onion (and I2P) sources when every clearnet one fails — asked all
at once — and a Tor-only server asks them first. They are reached only through the server's Tor proxy or i2pd,
never directly. Two hidden explorers must agree on the Bitcoin head before it is signed, so one lying explorer
cannot choose it.What the canary signs is checked first. A Blurt head must be a real block id that carries its own height, a
Bitcoin hash must show its proof of work, every answer is read up to 64 KB, and the news headline becomes one
line of plain ASCII (at most 200 characters) that is filled in literally. Before, a headline with an&(say
"Q&A") came out as a broken placeholder that the canary check then rejected, and a headline could carry text
that looked like part of the signature block.More hidden data sources. Bitcoin fee checks also ask mempool.foundation.xyz's onion and RunBTC's I2P
explorer; Monero fee checks also ask xmr.mx's I2P explorer. (Cake Wallet's onion timed out and xmr.mx's onion
answers only behind a captcha, so neither is a data source; both stay as links.)"No such payment" only when an explorer says so. A source that answers with a captcha or an error page —
even with HTTP 404 — counts as a malformed answer, not as "no such payment": only an explorer's own "not found"
does (Bitcoin: Esplora'sTransaction not found; Monero: the explorer's JSON error). Before, any 404 counted,
so explorers whose API was off or blocked could, together, reject a fee that was paid.When clearnet does not answer, the hidden network is tried (on servers that still use clearnet):
- Upgrades: if the code host and every mirror are unreachable, and @morphit's signed record names a newer
release, the upgrade fetches it from the other Morphit instances over Tor/I2P, checked against that record, as
a zero-clearnet server always does. A newer release you dropped in the offline folder still comes first;
--check-onlyand--jsonnever fetch. - Clock: a new timer (
morphit-clock-fallback.timer) checks every 6 hours whether NTP keeps the clock;
if it cannot (UDP blocked, pools unreachable), the clock is set from onion time sources over Tor, only when at
least three agree it is more than 30 seconds off. While NTP works it does nothing. Only one time check runs at
a time, and a server switched to Tor-only has this timer removed (its own replaces it). - Prices (BLURT, BTC, XMR): if every clearnet price source is down, the median of other instances' prices
comes before this server's own trades alone — only in USD, and only where the chain-pinned fee bounds it; where
that bound cannot be read, the federation's price is not used at all, so sybil instances cannot set it. A peer
whose web address does not answer is asked on its Tor or I2P address; a peer registered under a hidden name is
reached only through Tor or I2P, never through this server's DNS. Every server now samples the other instances'
prices (every 30 minutes);MORPHIT_INDEXER_PEER_PRICE_MONITOR_ENABLEDstill decides whether a clearnet server
alerts on disagreement.
For operators
- Upgrade every instance (
sudo morphit-ops, option 2). No database change. The upgrade adds the new
hidden fee sources to a fee-source list the wizard wrote, once (a source you remove later stays removed), and
installs the clock fallback on a server that keeps clearnet NTP. - Your explorer overrides (
MORPHIT_FRONTEND_*_CHAT_LINK_URL) apply on the pages that can open them: a
clearnet explorer on your clearnet site, a Tor onion on your.onion/.lokiaddresses, an I2P or Tor one on
your.i2paddress; otherwise the built-in list is used.
An override may now use plainhttp://for a Tor v3.onionor an.i2phost (the wizard, the indexer and
the browser all accept it); everything else must still behttps://. The wizard never checks such an address
from the server, and none of its checks follows a redirect to one. See OPERATIONS, "Explorer links on a hidden
site". - The canary reads
MORPHIT_CANARY_TOR_SOCKS(default127.0.0.1:9050) and the new
MORPHIT_CANARY_I2P_HTTP_PROXY(default127.0.0.1:4444) for those hidden sources, and the new
MORPHIT_CANARY_ONION_NEWS_RSS(space-separated.onionfeeds; default the BBC's) and
MORPHIT_CANARY_ONION_NEWS_WAIT(seconds they get, default 60) for the news line. Pinning
MORPHIT_CANARY_BTC_EXPLORERasks that explorer only. On a clearnet box without Tor the hidden sources fail at
once and change nothing. MORPHIT_HIDDEN_RPC_TIMEOUT_MSthat is not a positive number now falls back to 60 seconds; before, it made
every Tor/I2P call time out at once.- Dependencies: body-parser, qs, iconv-lite, fast-uri and undici updated within their versions for new advisories. A new zod
advisory (memory use on an unbounded list) does not reach Morphit: every list it checks from outside input has
a size limit, and the one that had none (a broadcast'sextensions) now has one.
Downloads
-
Source code (ZIP)
2 downloads
-
Source code (TAR.GZ)
1 download
- Bitcoin: mempool.space, Blockstream, mempool.emzy.de, Foundation and Cake Wallet onions, then Blockchair
-
Morphit v1.21.14
StableAll checks were successfulmorphit-ci / Supply-chain audit gate (every advisory triaged, none fixable in range) (push) Successful in 42smorphit-ci / TypeScript typecheck (sweep all workspaces) (push) Successful in 1m29smorphit-ci / apps/web svelte-check (svelte-kit sync + svelte-aware tsc) (push) Successful in 1m7smorphit-ci / Integration tests (real Postgres 16) (push) Successful in 6m38smorphit-ci / ansible-lint (playbook quality gate) (push) Successful in 45smorphit-ci / Smoke suite (run-smokes.sh, pulses 1–2 of 3) (push) Successful in 1h7m53smorphit-ci / Smoke suite (run-smokes.sh, pulse 3 of 3) (push) Successful in 38m5smorphit-release / Build + publish release tarball (push) Successful in 47m58sreleased this
2026-10-23 03:53:17 +00:00 | 4 commits to main since this releaseMorphit v1.21.14
Chat is fast again. Two people on morphit.io saw every message about a minute late. The server had each
message within a second; BunkerWeb, which buffers what it relays, held the live chat stream until later traffic
pushed it out. The indexer marks every live stream "do not buffer", but the frontend container in front of it
dropped that mark (nginx never passes it on by itself), so BunkerWeb never saw it. The frontend now passes it
on, and a message reaches the other person's browser in under a second. Tor and I2P visitors, who do not go
through BunkerWeb, were not affected by this part.A full audit of chat and the inbox followed, measured end to end on a private Tor network with three instances
(clearnet, clearnet with an onion, and Tor-only): every combination of sender and recipient arrived in under four
seconds, a paid first message in about one, and a message still arrived in under four seconds with a peer's
onion down. Messages from accounts this server had never stored a key for (most accounts older than Morphit)
used to wait for the chain too; they are now checked at once.No more "Sender not verified" or "Not sent: these are not keys you have checked" on a first chat. Chat now
uses one key per account, its posting key, so a conversation never starts with a key warning. Messages from
older versions stay readable, with a calm grey note.Your browser now talks to this site only. The once-a-day release check used to ask public Blurt RPC nodes
directly from your browser, so those nodes saw your IP address, even on a Tor or I2P site. It now asks this site,
which answers only with what two Blurt RPC operators agree on; your browser still checks the release's signature
itself, so a site cannot fake a release. Every page's Content-Security-Policy now lets the browser connect to
this site and nothing else (connect-src 'self'). See the FAQ "Does anything see or leak my IP address?".Chat and inbox
- Every message is pushed to every instance at once, one push per sender. People writing to users of the
same instance at the same moment no longer wait in line behind each other. Each push still travels on its
own fresh Tor circuit; a peer whose onion does not answer within two seconds is also tried at its web
address through Tor. - A paid first message reaches the inbox in about a second, also when the message arrives before its fee.
- Blocking someone takes effect at once, not when the block reaches a final block.
- A message from someone you blocked, or a first message that never reaches the chain, sends no notice.
- Trade buttons only for the trade they belong to. "Pay now" and "Mark sent" act only on this
conversation's own order, and only on what its two parties said. - Fewer connections per tab (three at most), so sending and reading never wait behind live streams on Tor
and I2P; live streams come back by themselves after an error. - One live inbox stream per browser, not one per tab. One tab keeps it and passes its news to your other tabs;
when that tab closes, another takes over and catches up. On Tor and I2P, where a browser allows only a few
connections per site, ten open tabs no longer use them all up. - Two orders with the same name are two trades. Two people can each post an order whose link name is the
same; a payment or an address on one of them no longer shows on the other, in chat, the inbox or My orders. - "Leave feedback" in the inbox only on the card of the person you traded with, not on every card about the
same order. - Ready for messages bound to their order and time. This version reads a new message format that cannot be
shown under another order than the one it was sent about, or more than a few minutes away from when it was
sent. It still sends the current format; the next version sends the new one, once every instance can read it. - The composer is free again at once after you press Send, a failed send says so, and drafts are kept per
conversation. - Live chat needs a ticket signed by your posting key. Before, anyone could watch an account's chat streams
on every instance and tell from which one showed a message first which instance that account uses. The browser
signs the ticket for you, for seven days at a time, so a device whose clock is hours or days off still gets live
chat; a paired desktop's ticket lasts as long as the pairing. (The person you are writing with can still tell,
by timing; see the leak catalogue.) - Chat records on the chain (messages, read receipts, folders, blocks, fees) are applied once two RPC operators
serve the same block. If your instance can reach only one operator for ten minutes, chat blocks are applied on
that operator's word until two answer again — so a hostile node can write chat history only while it is the
only one your instance reaches. - The safety number now checks your own half. Verify peer compares the keys this site lists for your account
with the key you signed in with: if yours is missing it shows no number, and any other key listed for you is
named above the number (messages to you are encrypted to it too). Before, a site serving both of you could add
a key of its own to your account, and both of you still saw the same number. - Signing out keeps what you have checked. The keys you have pinned for your partners are sealed under your
own key at Sign Out and come back when you sign in again, as the docs said they did. Before, every partner was a
first contact again after a sign-out. - A message you read stays read. Reading a message the moment it arrived, then leaving, no longer lights the
thread up again a few seconds later when its copy reaches the chain. - After you accept a partner's new key, their earlier messages show the calm grey note, not a request to compare
the number you have just compared. - One busy sender cannot crowd out the others on the way to another instance; a slow onion is no longer cut
off by a refusal from the same instance's web address; a notification whose first try hit a database hiccup is
sent on the next pass, not five minutes later.
For operators
- Upgrade every instance (
sudo morphit-ops, option 2). The upgrade rebuilds the frontend container, which
carries the stream fix above, and replaces the page Content-Security-Policy (BunkerWeb, the frontend
container, or the bare-metal nginx site) with this release's, in which visitors' browsers connect to this site
only. A policy you wrote yourself is left alone and reported. - New endpoint:
POST /v1/chain/agreed. It answers only the release check's two reads (@morphit's newest
release record, and that release's transaction from the block a checked history named), and only with what two
RPC operators of your pool agree on; it says 502 when they do not, and logschain_agreed_no_quorumat most
every ten minutes. One read serves every visitor and is kept a minute (a block ten, a failure 30 s), so a
flood costs your pool nothing more. Two reachable RPC operators are needed for the release banner. - A browser from before this version gets no live chat from an upgraded instance until it reloads (the
streams need a ticket). - Instances older than v1.21.13 cannot read chat from this version (every message is now sent the
posting-key way, which v1.21.13 introduced), and cannot write to accounts created from now on. Upgrade them. - Fan-out to other instances is Tor-only: every installer configuration runs Tor and publishes an onion.
- The head tailer polls every second by default (
MORPHIT_INDEXER_FASTPATH_INTERVAL_MS, now 1000). - New limits, all in OPERATIONS §24 and ADR-0052: stream tickets (new tickets checked at 100 a second for members whose key the instance holds, 40 for
others; their chain reads have their own ceiling), hidden-service streams (1,500, of which 1,000 without a ticket; 12 per account),
pushes in flight (8 per peer, 96 in all), relay push passes (4 at once). - When only one RPC operator answers, a block with chat or inbox ops waits up to 10 minutes once per outage,
then such blocks are applied on that operator's word (chat_block_single_source_after_waitin the log) until
two operators answer again; the pool is asked again once a minute. If you see that line, check that your RPC
operators are reachable. Blocks with a release, RPC-directory or BTC-order op still wait for two operators.
The second operator's copy of each chat block is fetched ahead, eight at a time, so catching up stays fast. - A refused live-chat stream answers 403 (not 401, which BunkerWeb's bad-behaviour ban counts: many visitors
behind one address would otherwise get it banned for an hour). A stream whose visitor leaves while its ticket
is checked no longer keeps its slot. - The sign-in pairing wait (
/v1/login-pairing/<id>/wait) is relayed unbuffered too. - A desktop paired before this version gets live chat back after pairing again; until then it still updates
every few seconds.
Also in this version: password fields
The settings page no longer stays blurred. Opening Settings from the avatar menu in Firefox left the whole
page grey and blurred until the next click. The browser's password manager had written the saved user name
(for example "morphit") into the "Also show orders in" language field as the page loaded; that opened the
field's list, and the open list blurs the page behind it.The same mistake happened elsewhere, found while fixing it and seen in Firefox: the saved user name went into
the memo of a BLURT transfer (a memo is public on chain) and into the amount to power up, and the saved
Morphit password went into the Active key box of "unlock with your Active key".Upgrading:
sudo morphit-ops upgradeon every server. No database change.What changed
- Every Morphit password field is a form of its own, with your account name as its user name (hidden,
read-only). Firefox's password manager now keeps to that form: it never writes into another field of the page,
and it offers the password saved for the account you are signed in with — not the password of another account
saved in the same browser. This covers Settings (change password, hardware key), sending BLURT, power up/down,
paying in chat, the chat fee, featuring an order, posting an order, backing up keys, sign-in, two-factor
setup, creating an account and importing one. - A box for a key (an Active key, a secret) starts read-only and becomes writable the moment you touch it or
move to it with the keyboard. Firefox does not fill a saved password into a read-only field. Pasting and typing
work as before. - A search-and-pick field (language, currency, payment method) opens its list only for your own typing. If a
browser or an extension writes into it, the text is cleared and nothing opens. - A new password set in Settings, or while importing an account with its posting key, is now offered for saving
under your account name.
Good to know
- If Firefox saved your Morphit password without your account name, it no longer fills it into these boxes.
Type it once; Firefox offers to save it under your account name. - Firefox still offers to save anything typed into a box that shows dots — the key icon in the address bar —
including an Active key typed into "unlock with your Active key". Websites cannot switch that off. For a key,
choose "Not now" ("Never save" would also stop it saving your Morphit password): Morphit uses the key once and
forgets it, and it should not sit in a password list.
For operators and contributors
- A new check runs with the other smoke tests (
password-field-scope-smoke): every password field in the web
app must be a Morphit-password field inside<PasswordScope>(or a<form>with a<LoginNameField>right
before it), or a key field that starts read-only and unlocks on touch or focus. - Another new smoke (
ops-harness-anchors-smoke) runs every mutation harness inops/testwith its slow test
runs skipped, and fails when a planted bug no longer lands on the code it names. 37 of them had stopped
landing (the code had moved), so the bugs they stood for were guarded by nothing; all are re-anchored (or
retired with the reason, where the code they named no longer exists). Nine more landed but were no longer
caught: seven are caught again, and two are retired because they change nothing on any path that still exists. - The smoke runners keep a failing smoke's whole output (
MORPHIT_SMOKE_FAIL_DIR, default the temp folder) and
print where. A test in one workspace no longer imports another workspace's source
(noWebSourceImports.test.ts): the web app's needs a generated folder that a fresh checkout lacks. - Dependencies: sanitize-html 2.18.0 → 2.18.1 (used by the Matrix bot; GHSA-c9rx-x947-fp3h, unbounded recursion);
dompurify 3.4.16 → 3.4.17 (used by the PDF export library; GHSA-cg2g-xh64-v4q7, GHSA-mrv2-3pqr-j5jr,
GHSA-c6gr-qvv4-5v3f); ip-address 10.7.2 → 10.7.4 (used by the MCP server's rate limiter; GHSA-rxp7-6hxx-x8q5).
A new Vite advisory (GHSA-rq7h-c2jc-7f22,server.fs.allow) concerns only the Vite dev server, which no node
runs; triaged inscripts/audit-allowlist.json(the fix is in Vite 6, a major upgrade).
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Every message is pushed to every instance at once, one push per sender. People writing to users of the
-
Morphit v1.21.13
StableAll checks were successfulmorphit-ci / Supply-chain audit gate (every advisory triaged, none fixable in range) (push) Successful in 39smorphit-ci / TypeScript typecheck (sweep all workspaces) (push) Successful in 1m13smorphit-ci / apps/web svelte-check (svelte-kit sync + svelte-aware tsc) (push) Successful in 54smorphit-ci / Integration tests (real Postgres 16) (push) Successful in 5m56smorphit-ci / ansible-lint (playbook quality gate) (push) Successful in 47smorphit-ci / Smoke suite (run-smokes.sh, pulses 1–2 of 3) (push) Successful in 59m40smorphit-ci / Smoke suite (run-smokes.sh, pulse 3 of 3) (push) Successful in 30m26smorphit-release / Build + publish release tarball (push) Successful in 46m6sreleased this
2026-10-21 01:01:41 +00:00 | 5 commits to main since this releaseMorphit v1.21.13
Chat reaches anyone, including someone who has never opened chat. A buyer pressed "Message" on a new
member's order. They got a red "This recipient hasn't opened Morphit chat yet", nothing was stored for the
recipient, and the message was gone after leaving the chat and coming back.The cause was not that member: every message was encrypted to a key the recipient had to publish on chain
first. The app published it silently, from the recipient's own BLURT, the first time they opened chat, and a
member with no BLURT left could never be reached at all. Messages to an account without that key now go to
its posting keys, which every Blurt account has on chain from the moment it exists. The message goes on
chain at once, the recipient is notified as usual, and they read it whenever they sign in. The sender pays
the network fee; the recipient needs no BLURT to receive or read it. Replying is sending: the replier pays the
fee for their reply.New accounts now start with 4 BLURT instead of 2, enough to fill in the whole profile, post a first order
and send a few messages (details below).Upgrading:
sudo morphit-ops upgradeon every server. No database change. Upgrade every instance,
including federated ones you chat with. A version older than this one:- cannot open a message sent in the new format. It shows "This message couldn't be decrypted on this
device. It may be damaged…" — the message is fine; that version cannot read it; - cannot send to a member who never opened chat (it still says "This recipient hasn't opened Morphit chat
yet").
New members never publish a chat key, so everything they send is in the new format, to everyone. Every
instance must run v1.21.1 or later before 2026-11-01 00:00 UTC.Chat to someone who never opened it
- What happened. Each message was encrypted to the recipient's published chat key, a key made from their
posting key and put on chain by the app the first time they opened chat, paid from their own BLURT. Until
then nobody could write to them, and their replies could not be proved on the other side. - Now. When the chat-key format can't be used, the message is encrypted to the recipient's posting keys,
read from their account on chain. One random key encrypts the message; it is sealed separately for each of
the recipient's posting keys that can sign on its own (up to three — whichever one their session holds
opens it), and once more for your own copy. Each seal uses the same construction as before (a fresh
one-time key for every message, mixed with both parties' keys, then ChaCha20-Poly1305), and each is tied to
this exact message, so nobody holding one of those keys can reuse it to write something else in your name.
Only the recipient can open it, and it proves who sent it. - Pairs that already chatted keep their format. When your published chat key is current and the other
person has one, nothing changes. - No fee for opening chat. Opening chat no longer broadcasts anything. A key published earlier is still
re-published after its owner changes their posting key (a small network fee), so people writing to them
keep reaching the right key. - Never moved off keys you checked.
- The posting keys first seen for someone are pinned on your device, as a set. A key removed from their
account narrows the pin. A key ADDED stops sending with "this person's account has a key it didn't have
when you last wrote to them" until you compare the new safety number and accept it. Accepting a changed
posting key never accepts a changed chat key, and the reverse. - If your server suddenly says that someone whose chat key you pinned has none, sending stops ("a key
recorded on the blockchain can't disappear"); it is not moved to their posting keys. - Someone whose chat key you already trust gets no posting keys on first use: sending to them in the new
format stops with "these are not keys you have checked" until you compare the safety number in Verify
peer and accept, and their messages in the new format read "Sender not verified" until then. - If your server can't say whether your own chat key is published, sending stops with "try again"; nothing
is guessed. Once your key has been seen published on this device, a later "none" from a server changes
nothing. - A message made with a key that isn't pinned reads "Sender not verified" and never moves a trade.
- The pins and that record are encrypted when you lock and removed when you sign out, as before.
- The posting keys first seen for someone are pinned on your device, as a set. A key removed from their
- Safety number. Verify peer uses the same rule as sending, so both sides compare numbers made from the
same keys — every posting key of each account, in any order. Opening it pins no posting keys: "The numbers
match — use these keys" (or "accept" for a changed set) pins exactly the keys whose number you compared.
(A chat key is still remembered the first time the panel or a message looks it up, as before.) It now says plainly when an account doesn't exist, when it has no
posting key of its own, when the chain couldn't be reached, and when your own key on chain is an old one
(the other person may see a different number until it is replaced). - Accounts with no posting key of their own (managed by other accounts) are named as such, instead of "no
account by this name". A message made for another posting key of your account (an account can list
several, and only one is in your session) says so, instead of "may be damaged". - Answering in the same format. When someone writes to you in the new format although you hold their
chat key — their own published key is out of date, for example — your replies go in the new format too, so
they can read them. Messages already sent in the older format to a key that has since gone out of date
stay unreadable until its owner opens chat with enough BLURT to re-publish it (a small fee). - Settled with someone else. The automatic "this order was settled with someone else" note follows the
same rules and pins, and reaches every posting key of people who never published a chat key.
Chat stays fast
- The keys a first message needs are looked up side by side as the conversation opens, while you type, so
the first Send waits on nothing (on Tor/I2P each lookup is a slow round trip). - A person without a chat key is looked up once per conversation, not once per message; a failed lookup is
asked again after 30 seconds (or at once on Retry), so a long history costs one lookup, not one per message.
Opening a conversation no longer asks the server for the same key twice. - A long history is opened a few messages at a time, so the page stays responsive while it fills.
- A message from someone whose keys are pinned opens with no lookup at all. On a server CPU the first message
from a person takes about 6 ms of crypto to open, later ones about 3 ms (they reuse part of the work);
sending takes about 11 ms. - The account-keys lookup now has a deadline (15 s, longer through Tor/I2P), so a server that stalls can't
hold a send open forever. - A long message costs less in the new format than before: your own copy is a 48-byte key, not a second copy
of the text.
A message that could not be sent stays in the chat
- A message that failed before the network took it lived only on the open chat page: leaving and coming back
showed nothing where it had been. It now stays in the conversation, marked failed, with the reason and
Retry, until it is sent. - Like your other unsent words, it is kept in memory only, never on disk. It is forgotten when you lock or
sign out, and not kept at all in "destroy after you leave this chat" mode — including when you switch to
that mode after the send failed.
Out of BLURT, in chat too
- v1.21.12 said the out-of-funds message showed on every screen that writes to the chain. In chat it did not:
a send refused for lack of BLURT showed the chain's own text ("Assert Exception: acnt.balance >= fee …").
A failed chat send now reads like every other screen: "Broadcast rejected due to insufficient funds. Buy
BLURT to save more data to the chain.", and the other refusals (clock off, wrong key, too large, the
server unreachable) say what to do. - A message to an account that does not exist on the chain says so instead of failing without a reason.
New accounts start with 4 BLURT
Blurt takes a fee for every operation from the sender's liquid BLURT: 0.050 per operation plus 0.200 per
1,024 bytes of the signed transaction. Every Save on the settings page is its own operation. Measured with the
real builders:Operation Fee (BLURT) Display name 0.084 Short bio (128 characters) 0.111 Website, streaming or Nostr link about 0.09–0.10 each (0.187 at the 512-character limit) Preferred languages 0.090 Avatar about 0.89 for 4 KB, 1.29 at the 6 KB limit Settings sync (one per batch of changes) 0.223 First order about 0.18 Chat message about 0.20 (short), 0.31 (500 characters) 2 BLURT ran out after an avatar, one order and a few saves; the next field was refused. 4 BLURT pays for every
profile field once (avatar at the limit), two settings saves, the first order and about seven short
messages. It adds 2 BLURT to the ~100 BLURT the chain already charges for each new account (~104 per signup;
about 2,100 BLURT still covers the first 20). The relay now needs the account fee plus 5 BLURT on hand before
it starts a signup.OpenMonero: what it still owes
The FAQ ("How is Morphit different from OpenMonero?"), the brag list and the media kit now give its full
record: about 77.85 XMR drained in June 2025; an exploit alert in May 2026; about 200 XMR taken in June 2026
and about 112 XMR in July 2026 (122 in his later count; 399 XMR across the three drains, by his own count); and on 20
October 2026 its operator told his community that 150–200 XMR of refunds are still pending, owed to four
vendors, and that he needs more fees to pay them back. An unverified "~40 XMR" figure for May 2026 was
removed.Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- cannot open a message sent in the new format. It shows "This message couldn't be decrypted on this
-
Morphit v1.21.12
StableAll checks were successfulmorphit-ci / Supply-chain audit gate (every advisory triaged, none fixable in range) (push) Successful in 40smorphit-ci / TypeScript typecheck (sweep all workspaces) (push) Successful in 1m13smorphit-ci / apps/web svelte-check (svelte-kit sync + svelte-aware tsc) (push) Successful in 50smorphit-ci / Integration tests (real Postgres 16) (push) Successful in 6m4smorphit-ci / ansible-lint (playbook quality gate) (push) Successful in 45smorphit-ci / Smoke suite (run-smokes.sh, pulses 1–2 of 3) (push) Successful in 1h0m23smorphit-ci / Smoke suite (run-smokes.sh, pulse 3 of 3) (push) Successful in 30m15smorphit-release / Build + publish release tarball (push) Successful in 42m51sreleased this
2026-10-20 03:49:00 +00:00 | 7 commits to main since this releaseMorphit v1.21.12
Chat, profile saves and every other error the app reads work again on BunkerWeb sites. BunkerWeb,
on its default settings, replaced every error answer from the site with its own web page. The app
reads those answers for their reason. On morphit.io, a message to a new member failed with
"Malformed response from indexer (status 404)", and a short-bio save showed "the chain rejected the
transaction" without saying why. Worse, the app never published a new member's chat key, so nobody
could write to anyone who joined after BunkerWeb went in. The upgrade turns that replacing off and proves
it on the running site. And when an account is short of BLURT, the app now says so on every screen that
writes to the chain: "Broadcast rejected due to insufficient funds. Buy BLURT to save more data to
the chain."Also fixed: members whose name ends like a file (
bob.old,ann.git,max.svg) got the web server's
404 page for their chat key and their pages. And on BunkerWeb sites the upgrade did not set up, normal
browsing could ban a visitor for a day.This release includes everything in v1.21.11 (see its notes): the download page about Morphit,
the barter chat buttons, andwww.<domain>on BunkerWeb sites.Upgrading:
sudo morphit-ops upgradeon every server. No database change. On a BunkerWeb site the
upgrade changes a few lines ofbunkerweb.env, recreates BunkerWeb's services so they read them, and
checks the result on the running site. The frontend container is rebuilt from this release, and a
bare-metal nginx site's own file is updated. Members who joined while answers were replaced get their
chat key published the next time they open a chat. Publishing it costs the usual small fee, so an
account with no BLURT left needs some first. Thewwwnote in v1.21.11 applies when you upgrade from
v1.21.10 or earlier. Every instance must run v1.21.1 or later before 2026-11-01 00:00 UTC.BunkerWeb replaced the site's error answers
- What happened. BunkerWeb's
REVERSE_PROXY_INTERCEPT_ERRORSisyesby default. It swaps every
400, 401, 403, 404, 405, 413, 429 and 500–504 answer from the site for BunkerWeb's own HTML error
page. Morphit's indexer and relay answer refusals as JSON with a reason, and the app acts on that
reason.- Seen on morphit.io (v1.21.10): asked directly, the indexer answered a missing chat key correctly
(404, "no chat identity for @…"); through BunkerWeb, the same request got its HTML page. - None of Morphit's code had changed: every BunkerWeb site has had this since BunkerWeb went in.
- The bio save was a real refusal by the chain. The account had 0.076 BLURT left, and the save
costs about 0.11 (see below).
- Seen on morphit.io (v1.21.10): asked directly, the indexer answered a missing chat key correctly
- What it broke, everywhere the app reads an error answer:
- Chat.
- Opening a chat for the first time looks up your own chat key, and "not found" is the signal to
publish it. With BunkerWeb's page instead, the app could not tell, so it never published the key.
Nobody could write to a member who joined after BunkerWeb went in. - A message to such a member showed "Malformed response from indexer (status 404)" instead of
"they have not set up chat yet".
- Opening a chat for the first time looks up your own chat key, and "not found" is the signal to
- Profile. A member with no profile yet could not save a display name, bio, website or links
from Settings: the page read "no profile yet" as a failed load and kept saving off. (An avatar
could still be saved, and that created the profile.) - Every chain write (chat, profile, listings, feedback, sending, paying):
- The chain's reason for a refusal was lost, so the user never saw "not enough BLURT", "your
device's clock is off", "wrong key" or "too large". - The broadcast service's "this is already on the network, do not send it again" warning was lost
too, inviting a second payment.
- The chain's reason for a refusal was lost, so the user never saw "not enough BLURT", "your
- Listings.
- A listing just posted showed "failed to load" instead of "still posting", and the edit page
skipped its wait for the indexer. - A gone listing read "load failed" instead of "not found", and the feature-bid form's "listing
not found" never showed.
- A listing just posted showed "failed to load" instead of "still posting", and the edit page
- Sign-up.
- Every relay refusal became "the chain rejected…": signups paused, the daily limit reached (and
its voucher steps), "try again in N minutes", a name already taken. - After a sign-up whose result was unknown, the safe retry of your own name was lost.
- Every relay refusal became "the chain rejected…": signups paused, the daily limit reached (and
- Elsewhere. Compare-orderbook reasons, the login QR "not in the directory" screen, push and
email notification setup errors, and the explorer's "history is busy, retrying" wait.
- Chat.
- Now.
REVERSE_PROXY_INTERCEPT_ERRORS=no: the site's own answers reach the browser unchanged, with
their status and reason. BunkerWeb's own answers (a firewall block, a request limit) keep its pages.- New installs set it (the Ansible template and
bunkerweb.env.example). - On installed boxes,
morphit-ops upgrade:- sets it, and turns off every copy of the line (an operator's own
yestoo: the app cannot work
with it); - recreates BunkerWeb's services (a plain restart keeps a container's old settings);
- checks a chat key that cannot exist: it must come back as the indexer's own JSON answer, not
BunkerWeb's page; - if the page still comes back, recreates them once more (not while BunkerWeb is still loading)
and checks again; - failing that, gives the exact command to run. When BunkerWeb's Compose service sets the
setting itself, it says where.
- sets it, and turns off every copy of the line (an operator's own
- New installs set it (the Ansible template and
- When a page comes back anyway (a firewall in front of the site, or a box not upgraded yet), the app
says who answered instead of "Malformed response":- "Your Morphit server's web firewall answered with its own page instead of the indexer's reply
(status 404), so the reason was lost…" - "…could not reach its indexer (status 502)…"
- "…is limiting requests right now (status 429)…"
- A chain refusal whose reason was replaced says that the reason was replaced.
- "Your Morphit server's web firewall answered with its own page instead of the indexer's reply
Account names that end like a file
- What happened. A Blurt name can end in
.old,.git,.bak,.svgand the like (each part of
a name is 3 or more characters). The web server's rule that hides leftover files (.env,.sql,
.bak…) and its rule for SVG images matched every address. That included the API and the app's
pages:/v1/chat-identity/bob.oldgot the web server's own 404 page, so that member's chat key was
never published./en/@bob.old(the profile) and/en/chat/max.svg(the chat) answered 404 instead of the app.
- Now. The API (
/v1/,/relay/) is never matched by those rules. Under a language path, every
such address is a page of the app, never a file. A leftover file elsewhere is still never served:
missing or not, the answer is the same 404. - Where.
- BunkerWeb sites: the frontend container's nginx. The upgrade reads its running config and
rebuilds it from this release when it has the old rules. - Bare-metal nginx sites: the upgrade rewrites the two rules in the site's own
web.confcopy,
tests it withnginx -t, reloads, and checks what nginx loaded. - Checked on a real nginx 1.24 with both shipped configs, and with v1.21.11's
web.confafter the
upgrade's rewrite.
- BunkerWeb sites: the frontend container's nginx. The upgrade reads its running config and
Bans on BunkerWeb sites
- Morphit counts only 401, 405 and 444 towards BunkerWeb's bad-behavior bans, at 50 a minute, banning
for an hour (the install template).- A 404 is a member with no chat key or profile yet, or the app checking for a file; a 403 is
BunkerWeb's own answer to a banned visitor; a 429 is a short burst. - Earlier upgrades only took 400 out of BunkerWeb's default list. A box without the template's lines
therefore kept counting 403, 404 and 429, at BunkerWeb's 10 a minute with a ban of a day. - Ordinary browsing could ban a real visitor for a day.
- A 404 is a member with no chat key or profile yet, or the app checking for a file; a 403 is
- Now. The upgrade sets Morphit's list where BunkerWeb's default or the earlier upgrade's list is in
force (an operator's own list only loses 400). It sets the threshold, window and ban time where they
are missing.
Out of BLURT
- Blurt charges every transaction a fee from the account's liquid BLURT: 0.050 BLURT per operation plus
0.200 BLURT per KB of the whole signed transaction. These are the witnesses' current settings, as the
chain reported them on 2026-10-19.- A short-bio save costs about 0.11 BLURT.
- The avatar in this report (5.8 KB on chain) cost about 1.2 BLURT.
- When the balance cannot cover the fee (or a payment), the chain refuses with "Account does not have
sufficient funds…". - That refusal now reads "Broadcast rejected due to insufficient funds. Buy BLURT to save more data
to the chain." in all 10 languages. It shows on every screen that writes to the chain: settings,
chat, feedback, posting and editing a listing, featuring a listing, sending, powering up and down,
and paying in a chat.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- What happened. BunkerWeb's
-
Morphit v1.21.11
StableAll checks were successfulmorphit-ci / Supply-chain audit gate (every advisory triaged, none fixable in range) (push) Successful in 41smorphit-ci / TypeScript typecheck (sweep all workspaces) (push) Successful in 1m10smorphit-ci / apps/web svelte-check (svelte-kit sync + svelte-aware tsc) (push) Successful in 46smorphit-ci / Integration tests (real Postgres 16) (push) Successful in 5m48smorphit-ci / ansible-lint (playbook quality gate) (push) Successful in 48smorphit-ci / Smoke suite (run-smokes.sh, pulses 1–2 of 3) (push) Successful in 59m35smorphit-ci / Smoke suite (run-smokes.sh, pulse 3 of 3) (push) Successful in 32m4smorphit-release / Build + publish release tarball (push) Successful in 42m50sreleased this
2026-10-19 22:59:13 +00:00 | 8 commits to main since this releaseMorphit v1.21.11
The download page is about Morphit, on every site. On a branded site it said "Get Vigilante
Trading" and invited visitors to "install a Vigilante Trading instance … or run your own node", as if
the site were the software. Its heading, browser-tab title and the title of a shared link now read
"Download Morphit", with no site name, and the introduction says the site runs on open source software called
Morphit, which anyone can use to run their own site and be listed in the Federation directory. Also:
in a chat about a goods or services (barter) listing, "Pay now" now shows to the person who pays and
"Share crypto address" to the one who is paid — it was the other way round — and the mailing-address
and shipment buttons appear. And on a BunkerWeb site with a domain of its own,www.<domain>now
works and is secure: it goes tohttps://<domain>instead of BunkerWeb's "403 Forbidden" page.Upgrading:
sudo morphit-ops upgradeon every server. No database change. On a BunkerWeb site
whose address is a domain of its own (vigilante.trading, morphit.io — not a subdomain such as
morphit.timeapp.foundation) and whosewwwrecord points at the server, the upgrade addswwwto
BunkerWeb's settings and to the Let's Encrypt certificate (see below; BunkerWeb's services restart for
the settings, then again for the certificate). Check
the record first, on any computer:getent ahosts www.<domain>should list the same addresses as
getent ahosts <domain>; if not, add a CNAME recordwww→<domain>at your DNS provider.
Every instance must run v1.21.1 or later before 2026-11-01 00:00 UTC.Download page
- Title: "Download Morphit" (it was "Get your site"), the same on every site — the heading, the
browser tab and the title of a shared link, in all 10 languages. No site name follows it: a branded
site added none already, and an unbranded site no longer adds its name ("— your site") on this
page; every other page keeps its title as before. - Description (search results and shared links): it said "Install your site as an app", which
the page no longer covers. It now says Morphit is the free, open source software the site runs on,
which anyone can use to run their own site, and that its code is mirrored and verifiable. - Introduction: "This website runs on open source software called Morphit. It enables anyone to
run their own Morphit-powered website like this one and get auto-listed in the Federation directory
so you can start earning from it." — "run their own" opens the run-a-node page, "the Federation
directory" the instances page. - Source code: the canonical repository "lives on the Agorise server" (it said "our own Forgejo
server").
Chat about a barter listing
- The right button for the right person. A barter listing says what happens to the goods ("I'm
selling bananas for XMR"), so its crypto runs the other way: the goods buyer pays, the goods seller
is paid. The chat read the listing as a crypto order and offered the goods seller "Pay now" and the
goods buyer "Share crypto address". It now turns the direction round for barter listings only — the
rule the orderbook already used — on whichever side of the chat you are. - Mailing address and shipment. "Share mailing address" (for the one who pays) and "Record
shipment" (for the one who is paid and sends the goods) appear in a barter chat. They showed only
when a listing named a payment method that is posted (metals, cash by mail, barter goods), and a
barter listing names only the coins it accepts, so they never appeared there. - Contributed by another developer, with tests; crypto orders behave exactly as before.
www.(your domain) on BunkerWeb sites
- What happened.
http://www.vigilante.tradingshowed BunkerWeb's "403 Forbidden" page. The
wwwrecord pointed at the server, but BunkerWeb serves only the names in itsSERVER_NAME
setting, which held the domain alone, and turns every other name away. The certificate named the
domain alone too, sohttps://www…could not be secure either. - Now. BunkerWeb answers for
www.<domain>and sends every request for it, on http and https, to
https://<domain>with the same page (one redirect), and the Let's Encrypt certificate names both.
Renewals checkwwwthrough that redirect, the way they check the domain. - Which sites. A domain of its own: two parts (
example.com) or a country's three
(example.com.mx,example.co.uk). Never a subdomain (morphit.timeapp.foundation,
trade.example.org), an address that already starts withwww., or an onion or I2P address. - New installs set it up. They ask Let's Encrypt for the domain's certificate, then add
wwwto
it; whilewwwdoes not point at the server yet, only that addition is refused (the domain's own
requests stay under Let's Encrypt's limit of five failed checks an hour). - The upgrade looks up where
wwwpoints, asking DNS servers directly (systemd-resolved's own
upstream servers when it runs, so not this server's hosts file). When it points at the server, it
addswwwtoSERVER_NAMEand the redirect rule tobunkerweb.env(a copy of the old file is
kept next to it), recreates BunkerWeb's services (a plain restart keeps a container's old settings),
and checks on the server thatwwwanswers with the redirect. It then proves Let's Encrypt can
checkwww(a test file in the web build must come back throughhttp://www…), asks for the
certificate withwwwadded, reads it back, and checks thathttps://www…passes a certificate
check. The certificate keeps what the operator set for it (its own deploy hook, preferred chain,
key reuse; not OCSP Must-Staple, which Let's Encrypt no longer issues — the upgrade says so). When BunkerWeb refuses the settings or the site stops answering, the old
file goes back. A settings file that already nameswwwwhile the running BunkerWeb does not (a
fresh install, or an upgrade that could not recreate it) is loaded by recreating BunkerWeb's
services — once per version of the file. When BunkerWeb's Compose service setsSERVER_NAME
itself, or does not readbunkerweb.env, the file is left alone and the upgrade names what to
change instead. Whenwwwhas no record, the upgrade says which record to add; when it points
elsewhere, it says where. A certificate that nameswwwafter its record is gone is issued again
without it, so renewals keep working. All of it runs in the background part of the upgrade and
stops in time: a step that would not finish before that run's time limit is left for the next
upgrade, so BunkerWeb is never stopped half-way (when that background part cannot be started on a
server, the upgrade says thatwwwwaits for it). - Installer.
morphit-ops bunkerwebreads the domain from aSERVER_NAMEthat also lists
www, keepswwwwhen the domain stays the same, and moves the certificate paths with a new
domain. - Onion-Location header (corrected comment). The install template claimed the header kept the
page a visitor is on. It never did: BunkerWeb sends the header exactly as written, and Docker
Compose dropped the$request_uriit ended with. The header names the onion (as it always did in
practice), and the page's ownonion-locationtag keeps carrying the page for Tor Browser.
Build tooling
- postcss-selector-parser 6.1.5, published today as the fix for the 6.x line of a CPU-exhaustion
advisory (GHSA-rj75-hqrm-r3gf). It is used only while the frontend's CSS is built and linted, never
on a node. The advisory database still lists it until it names 6.1.5 as patched, so it stays in
the project's reviewed list until then.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- Title: "Download Morphit" (it was "Get your site"), the same on every site — the heading, the
-
Morphit v1.21.10
StableAll checks were successfulmorphit-ci / Supply-chain audit gate (every advisory triaged, none fixable in range) (push) Successful in 40smorphit-ci / TypeScript typecheck (sweep all workspaces) (push) Successful in 1m15smorphit-ci / apps/web svelte-check (svelte-kit sync + svelte-aware tsc) (push) Successful in 53smorphit-ci / Integration tests (real Postgres 16) (push) Successful in 6m11smorphit-ci / ansible-lint (playbook quality gate) (push) Successful in 45smorphit-ci / Smoke suite (run-smokes.sh, pulses 1–2 of 3) (push) Successful in 59m34smorphit-ci / Smoke suite (run-smokes.sh, pulse 3 of 3) (push) Successful in 30m25smorphit-release / Build + publish release tarball (push) Successful in 42m26sreleased this
2026-10-18 05:18:42 +00:00 | 10 commits to main since this releaseMorphit v1.21.10
Setting up offline notifications, made to work for a real operator.
sudo morphit-ops offline-notifycan now make your site's XMPP account on a free public server (og.im, openim.nl or
jabber.de, asked live), with every answer checked before anything is sent. The Matrix step explains
that the account must already exist and says exactly why a sign-in was refused. A Matrix test
invitation can now be accepted, and the email step is written in plain words. Also: a contact link,
name or address changed withmorphit-ops editnow reaches your card on the Instances page,
including on servers installed before v1.12.20.Upgrading:
sudo morphit-ops upgradeon every server. No database change. The upgrade removes
the install-time copies of your site's name, tagline, contact link and addresses that an older
install still has in/etc/morphit/indexer.env, wheremorphit.config.envsets them too, and
restarts the indexer if that changes anything (see below). Every instance must run v1.21.1 or
later before 2026-11-01 00:00 UTC.Your card on the Instances page shows what you set
- What happened. An operator changed the site's contact from a Matrix room to an email address.
The Operators page (the on-chain registration) showed the email at once; the site's card on other
instances' Instances pages kept "Contact via Matrix". The card is copied from the site's own
indexer, which still had the old value. - Old copies in a file read last. The indexer reads
/opt/morphit/morphit.env, then
morphit.config.env, then/etc/morphit/indexer.env— the last one wins. A server installed
before v1.12.20 still has its install-time name, tagline and contact link inindexer.env, and the
Ansible files carry the operator tag and the Blurt node lists, so an edit was written, the service
restarted, and nothing changed. Nowmorphit-ops editandmorphit-ops alt-addressremove an old
copy of every setting they just saved fromindexer.envandrelay.env(a copy of the file is kept
next to it,….bak-<number>), restart, and then read the running services' settings and say
whether they have the new values. A Blurt node list there that keeps the server off public nodes
(empty, or hidden.onion/.i2pnodes only) is kept, and named. Each upgrade does the same for the
name, tagline, contact link and addresses wherevermorphit.config.envalso sets them. - The relay is restarted too when the site's name, origin, Tor/I2P/Lokinet address or its own
Blurt node list changes: its offline notes carry the name and the addresses, and it used to keep the
old ones until its next restart (even an onion just replaced). - At once after a restart. The indexer refreshes your own card at the first check after it starts,
instead of when it next falls due. - Other servers' cards. A card for another instance changes when that instance's own indexer
answers with the new value (each instance asks every 10 minutes), so that instance needs this fix
(or a restart of its indexer) too.
Offline notifications: setting up the accounts
- XMPP: a new account in a few answers. Choose Make a new one: the wizard asks og.im, openim.nl
and jabber.de (or a server you name) whether they take new accounts right now and offers only those
that do. It checks the name (2–32 of a–z, 0–9,._-) and the password (12–128 characters, not
containing the name, three kinds of characters or 20 and more, plain characters, typed twice) before
anything is sent, or makes a strong 24-character one if you just press Enter. A server that wants a
picture check shows a web page and you type what it shows (within about half a minute; a late answer
gets a new picture). A refusal shows the server's own reason. Then it turns the account's message
archive off (and reads the setting back), sends you a test note and saves. With no test address it
offers to save the new account untested; a new account you choose not to save stays on its server,
and the wizard says so. Use an account that already exists finds the server from the domain's DNS
records. On a zero-clearnet site only.onionservers, and no DNS lookups. It never logs in or
registers without encryption. - Matrix. The step now says the account must already exist (the wizard signs in; it does not make
one) and how to make one on matrix.org. A refused sign-in says why: wrong username or password, no
such account yet, too many attempts, no password sign-in, not a homeserver, unreachable. An address
whose/.well-knownnames another (matrix.org → matrix-client.matrix.org) is signed in at, and saved
as, that one. A homeserver that answers the sign-in with a redirect is refused, so the password is
never sent on to another address. - The Matrix test invitation can be accepted. The bot used to leave the test chat at once, so the
invitation could not be accepted ("the person who invited you has already left"). It now waits until
you have joined, up to about a minute and a half, and the wizard says so; it always finishes within
the wizard's time limit. - Email. The step explains in plain words that no mail server runs on your server: notes go out
through a mailbox at a provider, and it names the four answers to have ready.
Relay hardening (found in the review)
- XMPP replies are read in one pass. The relay read a server's replies with patterns that could
take minutes on crafted input, and a hostile XMPP server could have stalled the whole relay. Replies
are now split into elements by a scanner that looks at each character once. - Passwords as servers keep them. The relay now logs in with the password prepared the standard way
(SASLprep): an account whose password has a no-break space, a ligature or an accent typed as a
separate mark could not be logged in to before. - Zero-clearnet read the way the indexer reads it. Every check that decides from
/etc/morphit/indexer.envwhether a server is zero-clearnet (morphit-ops, first-online, the IPFS
setup, the snapshot pinning) now readsMORPHIT_INDEXER_RPC_ENDPOINTSas bash does: an empty list
written with a comment after it (…= # tor-only), quoted, or withexportis empty, and the last
line wins. Before, such a line read as clearnet: first-online could ask public RPC nodes and IPFS
could join the public network from the server's own address. - CI: the third run of the smoke suite is now its own job, started after the first two: a run of
the suite had grown to about 32 minutes, and three in one job no longer fit its 90-minute limit. - Smaller: a malformed name refused by the server asks for another name; a registration form that also
needs an email address is reported as such; a character split across two network packets is no
longer garbled; a server repeating the password in a refusal no longer puts it on the screen; Ctrl+C
at the picture question stops the wizard like any other prompt; the relay tool ending during a
question no longer leaves a second prompt or a spinner behind.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
3 downloads
- What happened. An operator changed the site's contact from a Matrix room to an email address.
-
Morphit v1.21.9
StableAll checks were successfulmorphit-ci / Supply-chain audit gate (every advisory triaged, none fixable in range) (push) Successful in 48smorphit-ci / TypeScript typecheck (sweep all workspaces) (push) Successful in 1m9smorphit-ci / apps/web svelte-check (svelte-kit sync + svelte-aware tsc) (push) Successful in 48smorphit-ci / Integration tests (real Postgres 16) (push) Successful in 5m47smorphit-ci / ansible-lint (playbook quality gate) (push) Successful in 45smorphit-ci / Smoke suite (run-smokes.sh, triple-pulse) (push) Successful in 1h24m30smorphit-release / Build + publish release tarball (push) Successful in 40m14sreleased this
2026-10-17 01:46:07 +00:00 | 12 commits to main since this releaseMorphit v1.21.9
Offline notifications. A user can now ask for a short note on an app she already uses — Matrix,
Session, XMPP, Telegram or email — when someone sends her a chat message while she is away. The note
says only "Someone just sent you a chat message on your site", with a link that opens that
conversation for her alone; never who wrote or what. It is off until she turns it on, on the apps you
choose to offer, and her address is kept encrypted under a key outside the database, never shown to
anyone and left out of backups. Also: script files no longer fail to load with "429 Too Many
Requests" behind BunkerWeb, and a small fix that lets the W3C validator accept every page.Upgrading:
sudo morphit-ops upgradeon every server. One database change (migration v69, seven
new tables, all local: never published in snapshots, never in backups), applied by the upgrade.
Offline notifications stay off until you set up at least one app with
sudo morphit-ops offline-notify(also in thesudo morphit-opsmenu); see
OPERATIONS.md §54. The 429 fix reaches BunkerWeb boxes on this upgrade (see
below). Every instance must run v1.21.1 or later before 2026-11-01 00:00 UTC.Offline notifications
- For your users. Settings → Offline Notifications: she picks an app you offer, types her
address, and confirms it with a code sent there (Telegram the other way round: she sends your bot a
code, and a button does it for her). From then on, a chat message that reaches her while she is away
earns her a note there, in her language: "Someone just sent you a chat message on Vigilante Trading.
Open it here to read it and reply: …". She can change an address (the old one keeps working until
the new one is confirmed — cancel, a code that never arrives, expires or is typed wrong five times
gives her the old one back, and it keeps getting her notes meanwhile), turn one app off, or delete
every address at once. - When a note goes. A random 10 to 60 minutes after the message, and only on a quarter hour
(:00, :15, :30, :45 UTC) — the same moments for everyone — so a note's arrival does not point at one
message on the public chain. None while she has the site open (her browser tells the relay once a
minute, kept in memory only), none once she has read the conversation or replied, one per
conversation until she looks, at most one a day from someone she has never written to, none from
someone she has blocked since, at most 20 a day. A note that reached none of her apps is tried again
twice, and does not count as one she was given. - How her address is kept. Sealed with AES-256-GCM under a key in the relay's own state folder
(/var/lib/morphit-relay/offline-notify.key), never in the database, and padded to one size, so a
copy of the database opens none of them. Nothing sends an address back to a browser, not even to
her: once saved, the card shows only "On". It is never in a log, a backup or a snapshot. A relay
that finds its key missing or replaced turns notices off rather than make a new key over the saved
addresses; Start over in the wizard (offered only then) deletes them and makes a new one. - Signed, once, for your site. Every request is signed with her posting key — the key as two of
your RPC operators agree it is, and one that signs for her on its own — for your relay only, and
each signature works once, within five minutes. A link in a note opens the conversation only for
her account. - Not a spam cannon. At most 6 codes a day per user, 3 of them to one address, and 5 a day to one
address whoever asks. Past those 5 the card still says the code was sent (nothing is), and every
"send me a code" is answered eight seconds after it arrived whatever happened, so neither the answer
nor its timing tells anyone whether an address was used today. On a hidden site every visitor
reaches your relay from the same address, so only failed requests that cost the relay something
count against an address's limit, and a user whose key was seen within a day is still let through
(within a small shared budget per second) while that address is being flooded. - Honest about the apps in between. Apart from Session (end-to-end encrypted), the servers that
carry a note can read it: they learn that she uses your site and when a note came — never who wrote
or what. And to deliver anything, her address goes to the provider of the account your notes come
from. The card and a new FAQ answer ("How do offline notifications work, and how is my address
kept private?") say so plainly, and "What data does it collect about me?" now lists the address she
gives for them. - Matrix rooms are left. The bot leaves and forgets every chat no saved address holds any more —
a removed or changed address, a code nobody confirmed, a first message that failed — retrying for
about two days when your homeserver does not answer. - Setting it up.
sudo morphit-ops offline-notifyasks for the account your site sends from for
each app, tests it (a real note to an address you type, or for Telegram the token checked with
Telegram), saves it to/etc/morphit/relay-notify.env(root:morphit-relay 0640; the wizard
changes only its own lines), restarts the relay and checks the app is offered. Turn an app off
deletes every address saved for it first. On a Tor-only site only.onionservers can be used, and
Telegram and Session are not offered. - What your WAF records. BunkerWeb's ModSecurity rule for the relay's paths now turns ModSecurity's
rules off there and, belt and braces, its audit log and request-body reading too, so the WAF never
records what she typed (the upgrade brings the older rule up to date).
Script files no longer fail with 429 behind BunkerWeb
- What happened. Some visitors' browsers logged "Failed to fetch dynamically imported module" on
first visit: BunkerWeb's own catch-all request limit (2 per second, counted per visitor and per
file) answered 429 when the browser fetched the same script file three times within a second (the
page, the offline cache, the tamper check). - Now. The site's own files are not limited; the 2-per-second limit stays only on IPFS, RSS and
MCP. BunkerWeb also allows 256 parallel streams per connection (it allowed 100, fewer than nginx's
128). The upgrade fixes boxes that still have BunkerWeb's defaults (your own values are kept),
recreates BunkerWeb and checks the home page three times in a second; if it still gets a 429 it
tries once more, then tells you the command to run. Bare-metal nginx's connection limit per visitor
is raised from 40 to 256 likewise.
Smaller changes
- The no-JavaScript style moved from the page body into its head, where the W3C validator accepts it;
pages look and behave the same with and without JavaScript. - The FAQ search finds "notify me by email" and similar questions (new words: notify, notified,
writes; filler words by, me, am, at).
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
4 downloads
- For your users. Settings → Offline Notifications: she picks an app you offer, types her
-
Morphit v1.21.8
StableAll checks were successfulmorphit-ci / Supply-chain audit gate (every advisory triaged, none fixable in range) (push) Successful in 42smorphit-ci / TypeScript typecheck (sweep all workspaces) (push) Successful in 1m9smorphit-ci / apps/web svelte-check (svelte-kit sync + svelte-aware tsc) (push) Successful in 53smorphit-ci / Integration tests (real Postgres 16) (push) Successful in 5m43smorphit-ci / ansible-lint (playbook quality gate) (push) Successful in 48smorphit-ci / Smoke suite (run-smokes.sh, triple-pulse) (push) Successful in 1h26m49smorphit-release / Build + publish release tarball (push) Successful in 39m35sreleased this
2026-10-15 04:09:33 +00:00 | 13 commits to main since this releaseMorphit v1.21.8
A branded site never shows Morphit's logo or colours, not even for an instant on a first visit. The
Operators page shows, for every operator, how many orders came through its site and what it has
earned since it started. The thin bright edge a main button lights on hover shows again on sites with
bright (gold) buttons, an upgrade puts back a warrant canary signed on another computer, and Morphit
works with hidden-rpc v1.3.0's built-in snapshot mirror. Plus a Morphit entry in the glossary and the
requested wording changes on the homepage, the privacy pages and the FAQ.Upgrading:
sudo morphit-ops upgradeon every server. One database change (migration v68, three new
tables), applied by the upgrade. After it, the indexer fills in the operator earnings from fee
payments it indexed before by reading them from the chain again, in the background; the Operators
page's earnings can be short until it finishes (it reads 25 blocks with fee payments every 10 seconds;
fee_legs_backfill_passin the indexer log).
Like every change to the upgrade, the canary fix starts with the upgrade AFTER the one that installs
it: this upgrade still clears a canary signed on another computer, so re-sign it once more afterwards,
on that computer (bash ~/.morphit/update-canary.sh). Every instance must run v1.21.1 or later
before 2026-11-01 00:00 UTC.A branded site never shows Morphit's look
- What happened. Opening some pages of a branded site for the first time — an order, a chat, a
profile: the pages the app draws in the browser — showed Morphit's logo and colours for a moment
before the site's own. Those pages start from one shared page that branding does not rewrite, and
learned the site's name and colours from/brand/brand.json, which arrives after the first paint.
And a browser that had visited the site before it was branded kept showing the old Morphit logo
until a refresh, because the stored copy was shown first and the new one fetched in the background. - Now. Every page links a small stylesheet,
/brand/theme.css, in its head; the browser paints
nothing until it has it. Branding writes the site's colours into it, and its name, so every page —
prerendered or drawn in the browser — has the site's look from its very first frame, with no wait
forbrand.json. On an unbranded site the file sets nothing. The logo, icons,theme.cssand
brand.jsonare now always asked of the server first, so a visitor who saw the site before it was
branded, or before a change, gets the new look on the very next page, without a refresh. The
browser's stored copy is used only when the server cannot be reached at all (offline, or the
connection drops) — since it may be from before the site was branded, it is never handed out
because the server is slow, nor in place of an error (a 404 or 503, or a server that has not
answered within 30 seconds (45 on a .onion, .i2p or .loki address): the logo is then missing rather than
possibly Morphit's). Only
theme.csskeeps its stored copy over an error, since without it the page would show Morphit's
look anyway. Wheretheme.cssnames the site,brand.jsonis no longer read at all, so a copy
stored before a re-brand cannot paint the old colours back. (A page now waits for that small
file, as it already waits for the page itself.) - Until the new service worker takes over. A returning visitor's browser keeps running the old
service worker until the visitor accepts the update or closes every tab of the site, and that
worker handed out its stored logo first. The pages now ask for the logo as
/brand/site-logo.svg?fresh=1(and the footer's likewise), which the old worker, too, always
fetches from the server — so those pages show the site's logo as well. - The browser's own colour. A phone's address bar (
theme-color) took Morphit's green until
brand.jsonarrived; it now takes the site's colour fromtheme.css, before the page renders. - Also branded: the minimal page an operator can serve under heavy load (
degraded.html) now
linkstheme.cssand takes the site's colours (background, panel, text and accent), and the
banner that offers to install the site as an app is tinted in the site's colour instead of
Morphit's green (on an unbranded site, a shade different from before). - Nothing to do: the upgrade re-applies your branding, which writes the new file. A site branded
before this release keeps working the old way until then.
Branding
- The hover edge on bright buttons. The 1px edge a main button (Start, top right, and the other
solid-colour buttons) lights on hover was drawn in the accent colour. On a theme with bright buttons
the accent colour is the button's own colour, so the edge never showed — on Vigilante Trading's gold
buttons (champagne-gold) it was gold on gold. It now has a colour of its own: on bright buttons the
theme's lightest colour, lifted until it stands out (a pale gold,#fff9e8, onchampagne-gold); on
deep buttons the accent colour, as before. With some colours of your own a deep button sat right on
the accent colour too (1.01:1); the edge is lifted lighter there as well. In every theme the edge, as
drawn (at 90% opacity over the button), is at least 1.8:1 from the button — lighter than it, or, on a
button so light that not even white stands out from it (Morphit's emerald, yellows, cyans, white), a
darker shade of it. (Many buttons
inside dialogs, chat and settings also brighten by 10% on hover, edge included; there it stands out
a little less — about 1.6:1 onchampagne-gold, where it used to be invisible.) An unthemed site
paints exactly as before (Morphit's emerald edge).
Nothing to do: the upgrade re-applies your branding — on a branded site its output shows
"✓ Applied your branding (…) to the live frontend." near the end. If, after the upgrade, the edge
still shows the old colour on your buttons (whatever the upgrade printed — an upgrade whose last
step ran out of time can leave the old look), runsudo morphit-ops branding applyon that server. - Branding stopped half-way. The server sends the pre-compressed copies of a page (
.gz,.br)
to most browsers. If applying the branding stopped half-way (a full disk, a power cut) after the
page was rewritten but before its compressed copies were, the next run saw the page already
branded and skipped it — and browsers kept getting the old compressed copy. Branding now writes
the compressed copies before the page and checks them too before skipping a file, and a reset puts
back every original, compressed copies included, even after a run that stopped half-way.
Operators page: orders and earnings for every operator
- What was wrong. The page promised each operator's orders and earnings, but showed them only on
the operator's own site, only for BLURT listing fees, and only from the version that started
counting them — so nearly every operator showed nothing, everywhere. - Now every operator has both figures, since it started, and the list is ordered by orders,
then earnings:- Orders — orders posted through its site (carrying its operator tag) whose fee this site holds
as paid (verified, or verified by attestation): paid in BLURT, BTC or XMR, or a free first buy,
whatever the order's status now. This is each site's own count: a site that does not list an
asset has none of its orders, and BTC and XMR payments are confirmed by each site's own
explorers, so sites can differ a little. - Earned — the BLURT that reached its fees account in Morphit fee payments: listing fees,
first-contact fees and featured-slot bids. Computed from the chain alone, so it is the same on
every Morphit site, whatever assets or settings each has. It follows the money: each payment is credited to the
operator whose registered fees account received it, as registered when it was paid (a payment
from before an operator first registered its fees account counts for the first account it
registers, if the payment names that operator). The 10% that goes to the Morphit treasury is
nobody's earnings, and neither is a fee paid from an operator's fees account itself (it cannot
pay itself, so that fee goes wholly to the treasury; BLURT a fees account sends itself never
counts). A payment counts only when the treasury
got its tenth — the check every fee already passes — so BLURT sent round in a circle cannot
inflate the figure for free, and registering someone else's account claims nothing paid into it
before. A featured-slot bid is credited by the tag of the order it features, as that order's own
op on the chain carries it. BTC and XMR fees go entirely to the treasury, so they add orders, not earnings. For an operator whose fees account is the Morphit treasury (morphit.io, or a site that
left its fees account blank) the page says "Paid to the Morphit treasury" under the figure.
- Orders — orders posted through its site (carrying its operator tag) whose fee this site holds
- The indexer now records every fee payment with the transfers that paid it (two new tables,
fee_paymentsandfee_payment_legs, carried in snapshots). Payments indexed before this version
are filled in after the upgrade from the chain: each original transaction is fetched again through
the node's own RPC pool and checked against its id before anything is recorded; a block that
cannot be fetched is set aside and tried again every 10 minutes. At most 16 transfers are recorded
per fee payment (a fee has at most two), so a crafted transaction cannot make the count expensive. - The figures are computed in the background into a third small table,
operator_stats(local, not
in snapshots): within a minute of a new fee payment and at least every 10 minutes, so the page
never waits on the count./v1/operatorsaddsfee_account, andstatsfor every operator
counted (an operator registered since the last count has none until the next one, and every
operator has none until the first count after the upgrade, which waits until the node has caught
up with the chain).
Pages and wording
- Glossary: a "Morphit" entry — the open source software that runs this site and many others,
each run by its own operator, developed by the Dev Team at Agorise; every site reads the same
Blurt blockchain, so your account works on all of them, and the software never holds your coins
or your keys. - Homepage: the first sentence ("Anonymously trade cryptocurrencies, fiat, goods, services and
more") is 10% smaller at every screen size, and the logo above it sits a little higher. - Privacy & terms: "We go further than encouraging privacy" links to the privacy page.
- Privacy page: "the next asset we add will get a guide automatically", and the large heading
at the top (and on each asset's guide) is drawn in the site's own colours, like the other pages'
headings, instead of plain white. - FAQ: every edit requested, in all ten languages — "Who runs Morphit?", the comparisons with
LocalBitcoins/LocalMonero, BasicSwap and Bisq/Haveno, the fees, Blurt and BP answers, the chat and
privacy answers (with the @-name examples), the operator answers — and two more "Related" links:
"How do I sell crypto?" → "What are the fees?", and "How does the chat inbox work?" → "If I block
someone, will they know?". "encrypted chat chat" in the request was written "encrypted chat". - The bookmark tip on the Instances page names ENS addresses too, in every language.
- Translations: a round of fixes found by a native-language review (Spanish, French, Italian,
German, Polish, Russian, Persian and both Chinese) — grammar, a wrong word or two, terms that must
stay in English; the FAQ question about the Blurt-blog checkbox now quotes the checkbox as it
reads (French, German, Polish, Russian, Persian, Chinese). In Persian, an @-name, a Matrix
address (@agorise:matrix.org) and a /@name path in the middle of a sentence now read left to
right instead of being reordered by the right-to-left text around them. - Narrow phones. On a 320 px screen the menu row under the header, in Russian, German, Polish,
Spanish and Italian, pushed its last link (Help) off the screen, and in French the header's Start
button (also at 768 px, a tablet, in French and Russian); all now fit, and no label is cut in the
middle of a word. A long FAQ question and the
Instances page's filter menu no longer push past the screen's edge either. The Operators page
keeps long operator tags inside the screen and writes its numbers the page language's way
(1,234 in English, 1.234 in German), not the browser's. - Without JavaScript the notice says "This site works without JavaScript — partly." and "This
site never sees your keys." On a branded site, the pages the app draws in the browser (an order, a
chat, a profile) said "Morphit" there.
Hidden RPC nodes (hidden-rpc v1.3.0)
- hidden-rpc v1.3.0 puts a small gateway in front of blurtd on every hidden RPC node, which serves
the indexer snapshot (checked against@morphit's signed SHA-256) and passes JSON-RPC through.
Checked against Morphit's own code before this release:fast-syncdownloads and accepts the
snapshot from it, the snapshot mirror imports and pins it, and single and batch JSON-RPC calls
reach blurtd byte for byte. Nothing changes in Morphit's code; the docs now say that nodes on
hidden-rpc v1.3.0 or later serve the snapshot (OPERATIONS.md, HIDDEN-RPC-SNAPSHOT-MIRROR.md).
Warrant canary
- An upgrade puts your canary back. An upgrade installs a fresh served folder, which has no
canary.txtorpgp_keys.asc. A canary signed on the same server was signed anew by the upgrade,
but one signed on another computer (the recommended set-up for a VPS) stayed missing until you re-ran
bash ~/.morphit/update-canary.shthere — a canary that disappears reads as one that tripped. The
upgrade now puts the canary served before it and its public key back, the same bytes (so the
signature still checks), and says until when the canary is valid; its "Valid through" date still runs
out on its own, so a canary you stop signing still goes stale as before. The upgrade's last lines ask
you to re-sign when it could not put the canary back (and says why), when the canary it put back runs
out within 5 days (or has, or has no readable date), or to publish the public key again when the key
could not be put back — each with the command for where the canary is signed; otherwise there is
nothing to do. Where the canary is signed on the server itself and the upgrade can run its refresh
(its timer, or the uploader's refresh script), it is signed anew there, replacing the one put back. - It copies only what a canary is. The upgrade runs as root and reads a folder your canary upload can
write, so a file is copied only when it is a regular file with one name (checked again after it
is read, so a second name made in the meantime is caught too), reached with no link anywhere
inside the old install (so nothing planted there — a link, or a second name for another file — can make the
upgrade copy out a file only root can read), of a canary's or a key's size, and, as a whole, a signed
Morphit canary or PGP public key blocks. Anything else is left behind, and the upgrade says so.
Tests (maintainer)
apps/indexer/test/integration/operator-earnings-v1218.test.ts(real dispatcher, handlers,
Postgres and/v1/operatorsroute): every operator's orders and earnings from listing,
first-contact and featured-slot fees; the treasury leg of a split fee and a fee paid from a fees
account itself credit nobody; BLURT sent to a fees account without the treasury's tenth (1,000,000
BLURT with a refused op, or 9% to the treasury) credits nobody; an operator that registers, later,
an account others were paid in claims none of it (also at the boundary block); an operator that
changes its fees account, twice in one block, is credited by the account in force at each
payment's block; a treasury-account operator is credited only for whole fees that name it; an
operator that registers its fees account after a payment is credited for it; a second operator
registering the same account later is not; an underpaid order counts no order but its BLURT; a
decoy transfer is ignored; every fee op is recorded, even one refused before any handler; the
back-fill reproduces the same figures from the chain, runs in the background (the indexer goes on
while its block fetches are out), fetches nothing once done, and records nothing for a transaction
served altered (the rest of its block is recorded). Seen failing on v1.21.7's code, and with each
rule removed or loosened in turn (the treasury's tenth, the whole-fee treasury rule, the
named-operator preference, the first-registration preference, the legacy grace and its naming
condition, each end of the as-of-block interval); the back-fill test failed while a pass still
held the indexer.- The same test file, after the deep review: two nodes with different settings (another fees
account, BTC not listed) compute the same earnings; orders whose fee was verified by attestation
count; a fee op with 20 transfers records 16; a NUL character in a memo or payload is recorded
the same way live and by the back-fill; a featured-slot bid takes the tag from the featured order's own op, not from this
node's orders table; a back-fill whose RPC fails for a while sets those blocks aside and fills
them in once the RPC answers; and the real poller loop back-fills and computes the figures on its
own. Each seen failing with its rule removed (mutation runs: the feature tag, the payload tag, the
leg cap, the signer check, the payload cleaning, attested orders, the retry, the set-aside
handling, the named-operator preference, each of the poller's two calls). api-response-shape-smoke(matrix-bot):/v1/operatorsentries withfee_accountandstats,
and the shapes that must be refused. Seen failing.apps/web/src/lib/brand/brandCss.test.ts: the site name survives the trip throughtheme.cssfor
every usable name (accents, Hebrew, Chinese, punctuation), as one CSS identifier that nothing can
break out of; anything else names no site; a page the app draws in the browser has the name before
anything renders, withoutbrand.json; a stylesheet that names no site falls back tobrand.json;
a prerendered page keeps its stamped name. Seen failing before the change. Also: the address
bar's colour comes fromtheme.csswhilebrand.jsonnever answers, and from a stylesheet that
arrives late; a name hidden inside a longer value is not read as one.apps/web/src/lib/net/serviceWorkerBrand.test.ts: the service worker's whole answer to a brand
request, with real requests and a cache that matches as the browser's does — a logo stored before
the branding is never handed out while the server answers, nor in place of an error; offline the
stored copy is used; a?fresh=1read never gets it; the logo URLs the pages use carry
?fresh=1. Each check seen failing (six mutations).apps/web/src/lib/net/brandResponse.test.ts: the service worker answers brand files from the
network first, keeps its copy for offline use only, and waits for a slow server rather than hand
out a copy that may predate the branding. Seen failing with the old stale-while-revalidate order.apps/ops-cli/test/branding.test.ts: branding writestheme.css(and its gzip copy) with the name
and the colours, and a colour theme alone writes it too. Seen failing before the change. A full
disk (injected) while writing a page's.gz, while saving its original.gz, and a page an older
version left with its old.gz: the next apply finishes the job (and, after the failure while
saving the originals, a reset restores every byte). Seen failing with the old skip check.theme-tokens-smokeTT-10: the shippedtheme.csssets nothing, andapp.htmllinks it
render-blocking, before any script.- The service worker is now type-checked (
tsconfig.sw.json, innpm run check, the workspace
typecheck smoke and CI):svelte-checkskipped it and the build only warned. - Checked in Chromium, frame by frame: on a
champagne-goldbuild, a brand-new browser opening a
profile, the orders page and the glossary, and a browser that had the unbranded site (and its
service worker) before it was branded, paint the branded background and logo from the first frame
and never Morphit's — also with every/brand/*answer held back 1.5 s and 3 s. (The same check on
an unbranded build finds Morphit's logo in the header, so it would see it.) A first try that
served the stored copy after a 2 s deadline showed the old Morphit logo for a whole page with 3 s
answers; that deadline was dropped. theme-tokens-smokeTT-9: reads the hover rule and the button's face from the CSS (the sources, and
the built frontend when present), resolves both to theme tokens, takes the rule's own opacity, and
checks that the edge as painted stands out from the face (1.8:1) in every preset with deep and bright
buttons, on white and near-white bright buttons, and in 200 random themes the engine accepts. Seen failing with the hover
painted in brand-primary (the shipped bug:champagne-gold/bright1.00:1), with the old deep-button
rule (1.01:1), with a white bright button (1.00:1), with the contrast measured on the opaque colour
(1.72:1 as painted) and with the rule's opacity lowered to 0.5.apps/ops-cli/test/theme.test.ts: the edge token, deep and bright, on 240 random themes and on white
and near-white bright buttons.apps/ops-cli/test/canaryCarry.test.ts: the canary put back byte for byte (also with bytes that are
not UTF-8, and with CRLF line ends and armor headers as gpg writes them); a link in the file's name or
in a folder above it, a hard link, a FIFO, an oversized file, contents that only start like a canary
or a key, a crafted key file of 4 million lines and a file already in the new folder are not copied
(and never make it throw); a failed write leaves nothing behind; the last lines' words for a canary
that runs out soon, has run out, has no date, or lost its key; a second name made for the file
while it is read; a canary uploaded with a strict umask is still readable by the web server; a
canary without its marker or with an odd armor line is refused. Each check seen failing with its
protection removed.upgrade-frontend-deploy-smoke: the upgrade puts the canary back before it hands the served folder to
the canary uploader, and does not then call the canary cleared.- Reviewed three times by a separate reviewer attacking the change and then each round of fixes, with
real gpg output, a real bind mount and Chromium's own pixels; every finding fixed and guarded, except
the dimmer edge on buttons that brighten on hover, where the wording now says what holds. - Then a deep review of the whole release by eight separate reviewers (indexer, web and service
worker in Chromium, ops-cli, security, the release checklist, and three translation reviewers),
and a second round of two reviewers attacking the fixes, whose findings were fixed in turn:- earnings: a featured-slot bid is credited by its order's own op, not an earlier malformed one
or a later repeat with the same name; BLURT a fees account sends itself counts for nobody; a
block set aside gets its three tries again after its time aside; the figures are counted
without holding the indexing loop;operator_statsnever leaves the node in a snapshot
(snapshot-trust). Each seen failing. - branding: a full disk while saving a page's original, or its
.br, then the next apply and a
reset; a page left with a new.gzbut its old.br; a full disk as the page itself is
written (its compressed copies are already branded). Each seen failing. - canary: whether the last lines call the canary cleared, over every case; a canary with
something before its signed message is not copied. Each seen failing. - web: the logo URLs the components actually render carry
?fresh=1
(MorphitLogoBling.test.ts); a storedbrand.jsonis not handed out over an error; a server
that never answers gets the worker's 504 for a logo, whiletheme.csskeeps its stored copy;
colours fromtheme.cssare never painted over by an olderbrand.json, and a late
stylesheet sets the toolbar colour; the Operators page's numbers follow the page language
(i18n-formatters-smoke); Persian Matrix addresses and /@paths (rtl-handle-and-footer-tasks-smoke).
Each seen failing. - Two tests no longer depend on the machine they run on: the canary tests point every upgrade
state file into their own folder, and the relay heal test's self-heal records its web heal
there too (it wrote/var/lib/morphit-ops/web-heal.jsonon the test machine). The fake
dockerinbunkerwebWafIdentify.test.tswrites its state atomically: twodocker inspect
calls at once could read it half-written and fail the test now and then (also on v1.21.7). mediakit-freshness-smokechecks the kit's README colours againsttheme.cssitself, and no
longer calls the kit stale whentheme.csschanged without changing those colours (git
keeps a byte-identical rebuilt zip at its older commit time; this failed the first v1.21.8
release run).eli5-release.sh --recutprints the ceremony for a tag whose release run
failed: BLOCK 2 moves the tag.- Checked in Chromium on a fresh build, branded and unbranded: no horizontal overflow at 320,
360, 375 and 768 px in all ten languages on the home, FAQ, Instances, Operators, orderbook,
glossary and privacy pages (none at 800, 900 and 1024 px on the home page either), and no menu
label cut mid-word from 320 to 600 px.
- earnings: a featured-slot bid is credited by its order's own op, not an earlier malformed one
rtl-handle-and-footer-tasks-smoke: an @-name in Persian text is kept left to right, and an
e-mail address, a link or acodespan is not touched; other languages get no invisible marks.
Seen failing.- TT-9 reads the edge's opacity only from
rgb(var(--…) / <number>); any other way of writing it
fails the check instead of counting as fully opaque. - Checked in Chromium: hovering Start on a
champagne-goldbuild draws#fff9e8at 90% on the
#d6b26aface (was#d6b26a); the unthemed build still draws#00da69; a build branded by v1.21.7's
code and then by this release's (the upgrade's order) ends with the pale-gold edge. Compiled-CSS
comparison with v1.21.7: 1511 rules each, every one paints the same values.
Downloads
-
Source code (ZIP)
0 downloads
-
Source code (TAR.GZ)
0 downloads
- What happened. Opening some pages of a branded site for the first time — an order, a chat, a
-
Morphit v1.21.7
StableAll checks were successfulmorphit-ci / Supply-chain audit gate (every advisory triaged, none fixable in range) (push) Successful in 44smorphit-ci / TypeScript typecheck (sweep all workspaces) (push) Successful in 1m16smorphit-ci / apps/web svelte-check (svelte-kit sync + svelte-aware tsc) (push) Successful in 47smorphit-ci / Integration tests (real Postgres 16) (push) Successful in 5m33smorphit-ci / ansible-lint (playbook quality gate) (push) Successful in 45smorphit-ci / Smoke suite (run-smokes.sh, triple-pulse) (push) Successful in 1h20m54smorphit-release / Build + publish release tarball (push) Successful in 39m48sreleased this
2026-10-13 19:43:53 +00:00 | 15 commits to main since this releaseMorphit v1.21.7
A fresh server goes from the guided install to a live, listed node without hand work: it fast-syncs,
sets up its warrant canary where you choose, lists itself when you say yes, and offers branding — and Ctrl+C at any point
says what stopped and what is left. The SSH safety net after an install no longer empties the firewall,
the hardening step no longer opens SSH wider than you had it, fast-sync checks every snapshot before
unpacking it and never serves a database that did not pass its checks, and the stats page's RPC card
measures the Blurt nodes only while someone is reading it.Upgrading:
sudo morphit-ops upgradeon every server. No database change. Like every change to the
upgrade, the new behaviour starts with the upgrade AFTER the one that installs it. Every instance must
run v1.21.1 or later before 2026-11-01 00:00 UTC. On a server installed with v1.21.6 or earlier whose
SSH question went unanswered, runsudo morphit-ops healthafter upgrading: it says whether the
firewall still lets SSH in (docs/UPGRADING.md, Troubleshooting).Installing a node
- Run a node, step 6, now has the exact commands: connect over SSH, update and restart the machine
(with a three-minute wait and the reconnect), starttmux, download the offline release into
~/morphit(or the normal one on an ARM machine), check it, unpack it, and run the installer. The old
text pointed at a download-page anchor that did not exist. The README's install step links the same
commands. - Ctrl+C during the guided install now says that you stopped it, and the exact command to start
again (cd <your folder> && sudo bash morphit-setup.sh), instead of "The install hit an unexpected
problem" and a support address — also at a check under the spinner while the questions are asked (it
used to end without a word there), and while Ansible is being installed; the file holding the database
password is always removed. Every other install failure names that command too. Once the
install itself has finished, Ctrl+C in one of the steps after it (fast-sync, the canary, the listing,
branding) stops only that step; Ctrl+C at a question or a wait ends the wizard with a list of what was
left and how to do each part later — the installed node is not called a failed install. - The "save your database password" screen says how to copy without stopping the installer
(Ctrl+Shift+C; Cmd+C on a Mac). - The guided install remembers your answers. Stopped part-way (Ctrl+C, a dropped connection, a failed
install), the next run shows what you entered and offers to reuse it, so you don't answer everything
again. Asked again every time, because they are never written to disk: your relay account's active key,
the alerts step (it holds a bot token) and, at home, the dynamic-DNS update URL. The database password is
new on every run, and after any earlier run or install on the box the save screen says so. The saved answers are deleted once the install succeeds, or
when you choose to start fresh. ("Configure only" already did this; the guide said the guided install did
too, and it did not.) docs/VERIFY-YOUR-DOWNLOAD.mdnames the offline bundle by its real file name,
morphit-vX.Y.Z-offline.tar.gz.- Inside tmux, the guided install ends by saying so and how to leave: type
exit, or Ctrl+B then D to
keep it running (tmux attachto come back). It doesn't close tmux itself: that would wipe the summary
you still need to read. - Encrypted backups: the key file's place is spelled out. The wizard used to say
age-keygen -o morphit-backup-key.txt, which saves the key in whatever folder the terminal is in, and
never said where. It now gives a fixed path in the home folder, named for the instance
(age-keygen -o ~/morphit-backup-key-<your domain>.txt), says where that is (/home/<you>/…,
/Users/<you>/…on a Mac), and to keep it in your password manager. Keys for several nodes no longer
overwrite each other.
The SSH safety net after the install
- An unanswered "a NEW SSH login still works?" no longer empties the firewall. When that question went
unanswered (at the end of a long install, nobody is watching), the safety revert put back the firewall
rules from before the install. On a fresh VPS that is no rules at all with the firewall still on: SSH
itself was no longer allowed (only the open session survived), and the rules the install added for the
web containers were gone, so every/v1call from the site hung and other instances listed the node as
"Clearnet blocked". The revert now only puts SSH's own settings back, and keeps the SSH port open to
everyone only when it was open to everyone before; a port that only some addresses or a VPN
could reach keeps those rules and is not widened, and one that was closed (SSH over Tor only, say) stays
closed. It re-asserts Docker and never touches the firewall's other rules. The install's hardened SSH
settings are kept, andmorphit-ops healthgives the one command that puts them back once you have
checked your key login (sudo bash /var/lib/morphit-root/reharden-ssh.sh: it puts them back only if
sshdaccepts them, and otherwise leaves SSH exactly as it is; if SSH then fails to start with them,
it puts the old ones back, starts SSH again and says which settings it runs now). - The hardening step no longer opens SSH to the whole internet on a box with its own firewall. It
always ranufw allow 22andufw limit 22: on a server whose firewall was already on with your own SSH
rules (an office address, a VPN, SSH over Tor only) that opened SSH to everyone, and on a server whose SSH
listens on another port (2222) the firewall it switched on locked you out. It now sets SSH rules only when
the firewall was off (or let everything in) before it, on the port(s) SSH really listens on — read from
where it listens (ListenAddress 0.0.0.0:2222is port 2222, thoughsshd -Tstill says "port 22"), and
none at all when SSH listens on this box only (SSH over Tor). morphit-ops healthwarns when the firewall lets no one in on SSH, with the command that does
(sudo ufw limit 22/tcp). On a fresh VPS installed with v1.21.6 or earlier, an unanswered SSH question
left exactly that: the next login failed.docs/UPGRADING.mdexplains it.- The question now waits 10 minutes (was 2), rings the terminal bell, and asks again on a bare Enter
(Enter alone is not "no"). Answering "no" puts the SSH settings back at once. Ctrl+C at the question
leaves the safety net armed and shows the command that cancels it. After "no" it waits (spinner) for the
revert to finish before saying it did — it used to say "did not report back" while it was still
running. A box with no SSH server gets no safety net (nothing to put back). If the revert does run,
morphit-ops healthsays so ("SSH safety revert ran …") with how to check and re-apply the SSH
hardening; the notice goes once the hardened settings are back, or after a later confirmed install. - The upgrade restores the web containers' firewall rules (relay 8080, indexer 8081, IPFS gateway
8082, MCP 8124 from thebunkerweb_netsubnet) where they are missing, on the install's own layout only,
and checks they took. It reads the subnet's IPv4 range even on a dual-stack network, and only ever a
private range.
Listing your instance
- "List this instance?" → yes now lists it. Two faults together kept a fresh VPS off
/instances:- The wizard registered on the spot only if every row of the review was ✓. On a fresh VPS some rows
never are at that point (the PGP contact key and the canary are signed later on your own computer;
i2pd takes minutes), so it always deferred. It now registers right away when the node is ready to be
listed: the chain is reachable and the database, relay, indexer and website are up, with the relay
funded. - Deferring flipped a switch for the background finisher (morphit-first-online), which had already done
its other jobs during the install and switched its own timer off, so nothing ever read the switch.
Deferring now also starts the finisher again; it retries every 5 minutes. A registration that goes
through on the spot no longer leaves a second one queued.
- The wizard registered on the spot only if every row of the review was ✓. On a fresh VPS some rows
- Declining at
register's own "Publish this registration?" question is no longer reported as listed.
registerexits with its own code (5) then, so the wizard says "Not listed" andeditsays "Not
published", where both used to report success. Ctrl+C at that question counts as declining too, and is
not queued for the background finisher. Having just said yes to "List this instance?", the wizard's own
registerquestion defaults to yes. - A Tor-only node whose
.onionis not in its settings yet is never registered as a barehttps://;
it is queued, and listed once the settings carry the onion.register(by hand or queued) now uses
http://<onion>when the origin setting is empty and the onion is set, so the menu's "Set up a Tor /
Lokinet / I2P address" is enough to list such a node. - The canary setup is never told the instance URL is a bare
https://(a Tor-only node before its
onion is saved); it then finds the URL itself, onion included. - Why a peer probe failed is now in the indexer's log (
peer_probe_failed, with the peer and the
reason), once per change. It was only in the database, so a new instance shown as "Clearnet blocked"
had nothing to read. Text a peer chose (its error, its relay account, its treasury address) is cut short
in the log, so a hostile peer cannot write huge log lines, and control characters are removed (a NUL in
a peer's answer made the reason unstorable, so it was logged again on every probe). - A registration marker from an earlier install on the same box no longer makes the queued listing
think it is already done. - When the finisher cannot list the node, its log says why: what
registersaid (its ✗ lines and its
last lines) is injournalctl -t morphit-first-online, instead of a generic list of possible causes,
with terminal control characters and bytes that are not text removed, each line cut to 300 bytes. A
✗ line is kept even when the output holds such bytes.
Fast-sync
- The guided install offers fast-sync (default yes), right after installing: the newest signed
federation snapshot instead of a full replay from genesis. Only "Configure only" offered it, so a fresh
VPS started millions of blocks behind. The indexer is started again (unless the restore left the
database unusable, see below), and the step waits until it is connected before the review. - Fast-sync fetches the snapshot through the node's own IPFS (on a node in the public IPFS network —
never a Tor/I2P-only one), before the public gateways, which rate-limit (429). The node's own gateway
serves only what it already holds. - The "127.0.0.1" source was the relay. The default source list included
http://127.0.0.1:8080—
kubo's stock gateway port, which on a Morphit node is the relay — so it always answered 404. The node's
own IPFS gateway is now read from its IPFS configuration (it is on 8082). - The hidden Blurt RPC nodes are asked for the snapshot too, at
/ipfs/<cid>on their own
.onion/.b32.i2pand port: they are the one set of hidden addresses a brand-new Tor/I2P-only node always
knows. One that does not mirror answers 404. What they serve, and a ready script for their operators:
docs/HIDDEN-RPC-SNAPSHOT-MIRROR.md. The snapshot mirror on every Morphit node asks them too. - Re-installing over a box that already ran a node, the wizard's fast-sync defaults to no and says
that a restore replaces that node's own data (pending payouts, push subscriptions, moderation). Offline,
it is not offered (it could only fail). - The chain check after a restore shows a turning spinner with the time taken and how far it is
("block 12 of 41"), and the RPC library's "Didn't failover…" notes are gone from fast-sync's output.
It used to sit for minutes with nothing moving. - No more double "Start the indexer" after fast-sync when fast-sync (or the wizard) starts it itself.
- The first-online job never starts a stopped indexer or relay (
try-restart): one may be stopped for
a restore. - A failed fast-sync starts the indexer again. It stopped the indexer, and only a success started it
again, so a failed download left the node's indexer stopped. Ctrl+C during the restore now stops only
the restore:morphit-ops(and its launcher) stay up long enough to start the indexer again. Before, on
an installed node the whole command died on Ctrl+C and left the indexer stopped. A closed terminal
(a dropped SSH session) no longer ends it before it has started the indexer again either. Ctrl+C, a
closed terminal or a stop before the restore begins stops at once and leaves nothing in/tmp. - A hidden snapshot source can no longer redirect the download (it could have pointed a Tor/I2P-only
node at a clearnet address through its proxy). A source that stalls is dropped: after two minutes for
a clearnet source or a hidden RPC node, ten for a hidden snapshot mirror (an I2P tunnel can take minutes
before the first byte), five for the node's own IPFS (with a turning spinner while it waits). - A snapshot is checked before it is unpacked. A download larger than the signed record says is cut
off at that size, one of the wrong size or hash is refused and the next source is tried, and the archive
is read by fast-sync itself: only the two files a snapshot holds, never a link or a path outside its
folder, and never much more than the signed size (a full disk is a refused source like any other). - A restore that replaced the database but could not finish is reported as such (exit code 4: the
check after the restore failed, the tidy-up failed, or Ctrl+C after the database was replaced). The
indexer is left stopped, with what to do: run fast-sync again, or wait for the next snapshot (published
daily). The guided install does not then list the node, and does not call it "running". A Ctrl+C during
the check on a busy server used to end the restore so abruptly that fast-sync read it as "nothing
changed" and started the indexer on the unchecked database; fast-sync now knows the restore had begun
even when it is killed outright. - While the wizard restores the snapshot, the first-online job is paused, so it cannot restart Tor or
i2pd under a download going over them. - The wizard waits up to a minute for the chain connection before deciding whether to offer fast-sync,
instead of one early look.
Backups and health
- Encrypted backups count as backups. With an age key, dumps are
….sql.gz.age;morphit-ops health
looked only for….sql.gzand showed "Backups ✗ missing — no dump has ever been written" on every node
with encrypted backups. The install's own wait for the first backup had the same fault, so it retried
for five minutes on every encrypted install. Half-written dumps (.partial) still never count. printf: I/O erroris gone from every backup's log. The "is the schema migrated yet?" check stopped
reading early, and under systemd that madeprintffail on the rest of a large schema. Harmless, but it
read like a failure.morphit-ops healthhas an Addresses section (a Tor-only node's onion origin is not shown as
"Clearnet"; a daemon still starting shows?, not ✗; run without sudo, it says the settings need root
instead of calling every address "none yet"): your clearnet origin as set, and your.onionand
.b32.i2p, each with ✓ when the service behind it runs (✗ when it does not, ○ never created). The Tor
check follows the Tor service that really runs (tor@defaulton Debian and Ubuntu), in health and in
the install review. The release-sharing line is
in plain words ("This node keeps a copy of the Morphit release for other nodes to download…"), and the
canary line says how to set one up, here or on your own computer.- The install review shows the
.b32.i2ptoo, and marks the.onion/.b32.i2p✓ only when they are
also in your settings (what the node advertises), not just created. morphit-ops healthshows your addresses. It never loaded the instance's settings, so it
printed no "Reachable at" rows and "No hidden address yet" on nodes whose.onionand.b32.i2pwere
configured and serving.
Warrant canary
- The guided install asks where a VPS's warrant canary is signed: here on the server, automatically
every week (the same turnkey setupupgradeoffers), on your own computer (the key never sits on the
server), or later. It used to be offered on home installs only, so a VPS ended with no canary and no
/pgp_keys.asc. Its first publish waits for the weekly timer only when the chain cannot be reached at
install time (it used to wait whenever the offline bundle was used, which the guide now uses on every
x86 VPS). morphit-ops health's canary hint gives the right command for where the canary is signed: the
server's own refresh script when it is signed here.
Branding
- The setup wizard offers branding (optional) just before its final review: the same guided setup as
sudo morphit-ops branding setup. - Branding setup first says exactly what it needs: three SVG files —
logo.svg(header, 32 px tall;
homepage, 44–96 px tall; any width),logo-footer.svg(footer, 40 px tall; optional) andicon.svg
(a square symbol that reads at 16 × 16 px) — each at most 2 MB with aviewBox, nothing loaded from
elsewhere, how to copy them to the server, and that they are saved under those names. - Colours from one colour, or from your logo. Answer the colour question with just your main colour
(#d4a017) orlogo, and the rest is worked out: a gradient from a lighter tint to a deeper shade (or
the logo's two main colours), a near-black page background with a trace of that colour, bright or deep
buttons to suit, everything checked for readability. Setup shows the result and asks before using it.
Two or three colours and the presets work as before, except that two or three colours now replace the
whole theme (an earlier preset's middle stop or button style is no longer left over). - Colours are read from any logo, quickly. A large logo kept the colour suggestion busy for minutes
(9 for a 2 MB file); it now takes a moment whatever the size. Colours written as names (navy),hsl()
or 4/8-digit hex are now read too, where such a logo was called "no colour". edit's "publish the change?" hints saysudo, Ctrl+C there is reported as not published, and
having said yes,register's own question defaults to yes (Enter, Enter used to mean "not published").
The stats page's RPC card
- The card stops when nobody is there. It re-read the figures every 10 s for as long as the tab was
visible, even a tab left open on a second screen for days. It now pauses after 3 minutes without mouse,
touch, keyboard or scroll input (and while the tab is hidden, as before), says "Paused while you're
away", and reads again the moment there is input. - The indexer measures the nodes only while someone reads the card. It measured every published Blurt
node every 20 s from boot, forever, page open or not: about one request a second from every instance,
Tor and I2P circuits included. It now measures nothing until the card is read and stops a minute after
the last read; the first read after a quiet spell measures at once, and when the figures it gets are
more than a minute old (first load, back from a pause, back to the tab) the card reads again 3 s later
so old figures don't stay on screen. - No number of open pages, clicks or scripted requests makes an instance contact a node more often.
The refresh (?probe=1, open to anyone) re-measured every node every 5 s for as long as someone kept
asking — a single script could make an instance contact all ~20 nodes four times as often as the
schedule. A refresh now re-measures only nodes not measured in the last 10 s, and waits for a
measurement already running instead of starting another: each node is measured at most once per 10 s
(a measurement that misses retries once), whatever the load. A refresh answers within 8 s even when a
hidden node never does: that node keeps its previous figure, with how long ago it was measured (or shows
as not measured yet). - The card has its own request limit, so a flood of it can no longer use up an address's limit for
the other public reads (sending a transaction, say). The directory reads behind it are shared between
requests arriving together. morphit-ops healthmeasures fresh (it asks for a refresh), and a node whose figure is over two
minutes old shows as "being measured" with no latency, instead of an old number.
Downloads
-
Source code (ZIP)
1 download
-
Source code (TAR.GZ)
1 download
- Run a node, step 6, now has the exact commands: connect over SSH, update and restart the machine