Updates releases-manifest.json, releases/index.html, theseus/index.html
and site-theseus-x/index.html for the 0.3.78 release — the one with
the Ariadne plug-in toggle fix for 0.2.0 Just-me installs, the
Settings Middle East crash fix, covenant-held name resolution and
Pithos 0.3.16.
- site/releases: 0.3.77 block above 0.3.76 with the Translator engine
radio, CF Bot Fight error page and Pithos 0.3.13 bundle, SHAs
ab4135a9… (installer) + a01ad6b8… (portable).
- site/theseus and site-theseus-x: bump the download card to 0.3.77 and
the fallback hashes to match. The theseus-x page already fetches the
live manifest; the fallback stays in sync for offline reads and the
Sia mirror.
- site/releases-manifest.json: 0.3.77 entry prepended for the main
manifest; the dl copy was scp'd and dl-latest.sh regenerated the
/latest/ redirects on the VPS.
Setup 9e5c4b6b…b7e9, portable b223eb14…5c49. Pithos opens at
pithos.sia/<user>/<drive>/<folder>, music keeps playing in background
tabs, a widened left panel no longer squeezes the page; bundles Pithos
0.3.10 and Aegis 0.31.0.
A parallel ship pass raced this one on the same version string: the
other session built 0.3.75 from 4bfef3a (Aegis 0.29.0) and scp'd its
binaries over mine. The first reconcile pass accepted the on-disk
hashes under the "both built from the same HEAD" assumption, but they
are different builds — mine includes d2ddee5 (Aegis 0.30.0) and the
master tip, theirs stops at 4bfef3a. The peer stood down, I re-scp'd
my binaries, and this commit pulls the manifest + the releases page +
theseus.x back to those hashes. The release notes already named
Aegis 0.30.0, which matches what the binaries actually bundle now.
Manifest, releases page, download pages and theseus.x fallback text all point at
0.3.61 with the new hashes. Silentmode.st serves static; silentmode.bch mirror
follows via the 5-min Sia sync.
Every subsystem is now individually switchable and reports its own state.
GET http://127.0.0.1/api/status returns:
- daemon: version, startedAt, uptimeSec, policy, permittedTlds, ports,
upstream, gateway
- index: size, nameCacheSize, warmStart {source, at, size}
- sources.snapshotHttps: enabled, urls, lastAttempt/Success/Status/Error,
winnerUrl, notModified count, refreshes count, ETags
- sources.electrumWss: enabled, lastAttempt/Success/Error, failStreak, refreshes
- sources.perQueryLookup: enabled, gateway, lastAttempt, hits/misses/errors
- sources.diskCache: enabled, path, exists, size, mtime
- sources.localApi: enabled, endpoints[]
- policyFile: path, exists
policy.json schema extended with a sources.<name>.enabled block, hot-reloaded
by the existing loadPolicyOverride() on the same 5-second tick as the
collision policy. Each refresh/lookup path guards on its flag, so an operator
can isolate any subsystem without a restart:
- snapshotHttps off -> daemon skips dl.silentmode.st/Sia polling
- electrumWss off -> daemon skips chipnet WSS refresh
- perQueryLookup off -> DNS handler misses fall straight through to forward
- diskCache off -> no write to and no read from bns-name-snapshot.json
- localApi off -> /api/* return 503 with a hint pointing at policy.json
Verified locally on port 18080: /api/status returned the full JSON with a
snapshot warm-start from dl.silentmode.st recorded in warmStart, ETag captured
in sources.snapshotHttps.etags, disk cache path/size/mtime populated.
Deployed dl.silentmode.st + Sia. sha256 a16d10759efede4412f4fdb52d59424bf56bbb258bb002ab930f4a5a5aef8a41.
The matching Theseus panel UI (source table with the toggles + a Copy-status
button that fetches /api/status) belongs in the Theseus release; not touched
here to avoid colliding with settings-preload.js work in flight from a
parallel session.
Manifest and download pages point at the new build. Silentmode.st serves
static; silentmode.bch mirror follows via the 5-min Sia sync; theseus.x's
fallback text and hashes match the 0.3.60 binaries so the page reads correctly
before the client-side manifest fetch overwrites them.
- .iss pre-install hook now also kills orphan node.exe from the Ariadne
install dir (foreground diagnostic runs, crashed processes not cleaned
up by the scheduled task), path-scoped so no other app is affected.
Fixes upgrades failing with "DeleteFile failed; code 5 -- Access is
denied" on runtime/node.exe -- seen on 0.1.11 install by a user who had
run the daemon manually per an earlier diagnostic.
- bnsd.js Express gateway now serves local BNS indexer endpoints:
/api/tlds -> {source, tlds: string[], count}
/api/name/:n -> full BNS entry (same shape as navigate.st/api/name/)
/api/registry -> {source, count, names[]} full index dump
CORS wide-open (matches operator behavior). Any app on the machine can
now query BNS locally with no navigate.st round-trip. Answers off the
daemMons in-memory index which already merges snapshot warm-start +
ETag polling + per-query indexer fallback + electrum WSS.
Verified locally: hello.bch resolves via /api/name; unknown gives 404;
/api/tlds returns the CA-constrained set (bch p2p bit deviant nav test
bcnr on this boxs current CA); /api/registry returns 61 names.
Deployed: dl.silentmode.st + Sia. sha256 b041652a330fefb4561da7ca14fa84ddf3b6085fda6eb62831cb08ea56ec602d.
The daemon now uses the operator's live BNS indexer as the primary source of
truth, not chipnet electrum. Two changes to the resolver pipeline:
1) Background refresh is HTTPS-first with ETag. Every 30 s the daemon polls
dl.silentmode.st/bns-name-index.json (and s3.silentmode.st:8600 as an
independent Sia mirror) sending If-None-Match; only reparses the array
when the operator republished, does zero work otherwise. Electrum WSS
stays as a same-tick secondary that runs when HTTPS turned nothing up,
so a daemon on a network that can reach chipnet but not the operator VPS
still converges. Both broken? Keep the last-good index from warm-start.
2) Per-query indexer fallback in the DNS handler. When the in-memory index
misses, the handler calls navigate.st/api/name/<host> directly with a
5-second timeout and a 30-second LRU cache. Names registered AFTER the
last snapshot poll but BEFORE the next one now answer immediately from
the live indexer instead of falling straight through to a forward and
returning NXDOMAIN. Cache is cleared on any successful full refresh so
a de-registered name doesn't stay resolvable.
Net effect: on the class of failure that motivated this (chipnet electrum
timing out on blockchain.scripthash.get_history, or port 50004 filtered by
the network), the daemon just works. The operator's HTTPS indexer -- which
every other client in the ecosystem (Theseus mobile, Aegis, sirius.x, the
gateway itself) already reads from -- is now Ariadne's Thread's primary
too. Trust model unchanged: the snapshot always came from the operator.
Verified locally with the built binary on port 15353:
bnsd index: warm-started from https://dl.silentmode.st/bns-name-index.json (61 names)
hello.bch -> 127.0.0.1 (snapshot hit)
game.x -> 127.0.0.1 (per-query /api/name fallback -- not in .bch-heavy snapshot)
coinspectrum.x -> 127.0.0.1 (per-query fallback)
ariadne.x -> 127.0.0.1 (per-query fallback)
notregisteredxyz.x -> NXDOMAIN (indexer confirms not registered, forwarded to upstream)
Deployed
- dl.silentmode.st/AriadneResolver-Setup-0.1.11.exe
- s3://bns/silentmode/dl/AriadneResolver-Setup-0.1.11.exe
- silentmode.st manifest advertises 0.1.11
- sha256 58ffb06424785973d2cd656e5122061ce10b53a8dcff55605c23b5699552ee75
WSS-blocked networks
Symptom on the other box (2026-09-29): task Running, port 53 bound by our
node, `Resolve-DnsName hello.bch -Server 127.0.0.1` times out. Cause: the
daemon's initial index build was a top-level `await buildIndex()` over
electrum WSS to chipnet (port 50004). Corporate/ISP networks that filter
outbound WSS let the await hang forever; the queries fell through to
`forward()` to upstream 1.1.1.1:53, which the same firewall also blocked,
so both legs died.
0.1.10 borrows Theseus's warmFromSnapshot pattern for the system-wide
daemon. On startup, in parallel with an 8 s deadline per source:
1. HTTPS snapshot from operator VPS https://dl.silentmode.st/bns-name-index.json
2. HTTPS snapshot from Sia mirror https://s3.silentmode.st:8600/bns/name-list.json
3. On-disk cache from a previous run C:\ProgramData\Ariadne\bns-name-snapshot.json
First non-empty result wins; on any HTTPS win the raw array is written to
the disk cache so the NEXT boot is instant even fully offline. dns.bind()
runs the moment warm-start completes, whether or not electrum was
reachable. Electrum WSS refresh continues in the background on the 30 s
timer and wins over the snapshot when it succeeds because it is strictly
newer.
Snapshot format is the pre-resolved array Android's Ariadne reader already
consumes (`[{name, category, records, txid, height, updatedTxid, owner?}]`),
so the operator maintains ONE artifact for both clients. Custom URLs go in
`ariadne.config.json`.snapshotUrls.
Verified on the dev box by running the built binary manually on port 15353:
bnsd index: warm-started from https://dl.silentmode.st/bns-name-index.json (61 names)
bnsd DNS: 127.0.0.1:15353 (policy=bcnr-first, upstream 1.1.1.1)
hello.bch -> 127.0.0.1
Disk cache written: 17,674 bytes.
Deployed
- dl.silentmode.st/AriadneResolver-Setup-0.1.10.exe
- s3://bns/silentmode/dl/AriadneResolver-Setup-0.1.10.exe
- silentmode.st manifest advertises 0.1.10
- sha256 29710c4011dfe058a252f94af221c02593e728e89cc7427e3e01eaa530f8e526
Chromium (Chrome + Edge) doesn't treat `foo.x` as a URL because `.x` isn't on
its known-TLD list -- it sends bare input to the default search engine. Only
way to intercept it without a browser extension is to make the default search
engine one that understands BNS.
The daemon now serves that. New route `app.get("/search")` before the catch-all
Express handler:
- `q` matches <label>.<permitted-tld> -> 301 https://q/ (any path preserved)
- q has whitespace, unknown TLD, IP, etc. -> 302 to `searchFallback`
(ariadne.config.json, defaults to https://duckduckgo.com/?q=)
- empty q -> 400
Permitted-TLD check reuses isPermittedHost() from lib/tlds.js -- same set the
CA is constrained to and the SNI callback gates leaf minting against, so
"routable, therefore a URL" stays one decision.
Users set their browser's default search engine to
`http://127.0.0.1/search?q=%s`. Everything decided locally, no navigate.st
round trip. Works offline. Works with the same offline BNS index the DNS side
uses. Fallback engine is per-user via config, not a locked-in default.
Verified on this box after upgrade:
"ariadne.x" -> 301 https://ariadne.x/
"game.x" -> 301 https://game.x/
"hello.bch" -> 301 https://hello.bch/
"ariadne.x/path" -> 301 https://ariadne.x/path
"Weather" -> 302 https://duckduckgo.com/?q=Weather
"bitcoin cash" -> 302 https://duckduckgo.com/?q=bitcoin%20cash
"unknown.zzz" -> 302 https://duckduckgo.com/?q=unknown.zzz
"" -> 400 bnsd search: q parameter is required
Deployed
- dl.silentmode.st/AriadneResolver-Setup-0.1.9.exe
- s3://bns/silentmode/dl/AriadneResolver-Setup-0.1.9.exe
- silentmode.st manifest advertises 0.1.9
- sha256 3b973e0ae584113ad776c756b16b895fd0dfb217a02bfae6376c5abb48f9a77c
Before 0.1.8, a BNS name with an on-chain `ip` record made the daemon return
the origin's public IP directly. Browsers then hit the origin's own HTTPS
server -- and if that origin's cert was not browser-trusted (which is the
whole point of the on-chain `tls` fingerprint pin next to the `ip` record),
every browser except Theseus rejected the site with ERR_CERT_AUTHORITY_INVALID
or SEC_ERROR_UNKNOWN_ISSUER. game.x and hephaestus.x both hit this. Theseus
was fine because its in-process resolver validates against the on-chain pin.
0.1.8 answers DNS with 127.0.0.1 whenever the name has BOTH `ip` and `tls`,
terminates the browser's TLS locally with our trusted leaf, and reverse-proxies
to the origin over HTTPS while validating the origin's SHA-256 fingerprint
against the on-chain pin. Same algorithm Theseus uses (main.js:pinnedHttpsGet,
cert.fingerprint256 lower-cased, colons stripped) so a site's `tls` record
means the same thing in-Theseus and system-wide.
Names with just `ip` (no pin) keep direct routing -- unchanged. Only opts in
when the owner has published a fingerprint pin, so nothing regresses for sites
that deliberately wanted direct IP routing.
Two subtle bugs found + fixed while landing this:
1. `agent: false` on the outbound https.request. With Node's default global
agent (keepAlive on), the second request onwards reuses the TLS socket
and `res.socket.getPeerCertificate(false)` comes back stripped of
fingerprint256 -- pin validation then reads "empty" and rejects with 526.
Fresh socket per request costs a handshake but is cheap next to the
pin-verify miss.
2. Removed `content-encoding` from the hop-by-hop strip list. Origin sends
gzip'd bytes; my proxy streams them unchanged. If we strip
content-encoding while forwarding compressed bytes, the browser treats the
gzip magic as text and renders garbage. content-encoding is end-to-end
per RFC 7230 -- keep it.
Verified on this box: game.x, hephaestus.x, theseus.x, sirius.x,
coinspectrum.x, hello.bch all load HTTPS 200 in strict IWR and Chromium; DNS
answers 127.0.0.1 for game.x + hephaestus.x (was their origin IP before),
still their origin IP for names without a tls pin.
Deployed
- dl.silentmode.st/AriadneResolver-Setup-0.1.8.exe
- s3://bns/silentmode/dl/AriadneResolver-Setup-0.1.8.exe
- silentmode.st manifest advertises 0.1.8
- sha256 47450ad4555beb04fe3b90ae5f658dc2932061d011ada9a2fb507471e2f0a0cb
Feature. The daemon now hot-reloads C:\ProgramData\Ariadne\policy.json every
5 s (fs.stat mtime check, only opens the file when it actually changed) and
flips its DNS collision policy between bcnr-first and icann-first in place.
Every browser on the machine follows within seconds -- no daemon restart,
no reinstall, no UAC. The next Ariadne panel in Theseus will edit this file
directly; a text editor works too.
install.ps1 seeds the file with the current -Policy default on FIRST install
only (an upgrade never clobbers a user's later flip) and grants BUILTIN\Users
Modify on it so an unprivileged app can rewrite it. Invalid values keep the
last good policy (logged). File deleted -> daemon falls back to the CLI
policy the scheduled task was registered with.
Also fixes an intermittent "config unreadable" on daemon startup when
ariadne.config.json had a UTF-8 BOM -- same class of PS-writes-BOM bug 0.1.6
fixed in the TLD-sync path, this time in bnsd.js's own config loader.
Verified live on this box with a second daemon running on port 15353:
bnsd policy: bcnr-first -> icann-first (from C:\ProgramData\Ariadne\policy.json)
bnsd policy: icann-first -> bcnr-first (from C:\ProgramData\Ariadne\policy.json)
bnsd policy: ... has invalid policy 'cash-first' -- keeping bcnr-first
ACL check: BUILTIN\Users has Modify on policy.json, non-elevated write succeeds.
Deployed
- dl.silentmode.st/AriadneResolver-Setup-0.1.7.exe
- s3://bns/silentmode/dl/AriadneResolver-Setup-0.1.7.exe
- silentmode.st manifest advertises 0.1.7
- sha256 742f8005c2dfb47929287c009cddf7738f0d12bd56fb8f8a837df3e9b435f47f
Theseus UI wiring for this file NOT touched -- settings-preload.js has 31
lines of uncommitted work from another session; a Theseus panel selector
belongs in that session's next commit so it doesn't collide.
Symptom: on any machine that had been through a series of installs, one or
more older "BNS Local Root CA" certs from earlier builds could accumulate in
LocalMachine\Root -- an unconstrained root from before 2026-07, or a rotated
one -- and every install added the current constrained root ALONGSIDE the
stale ones. Two certs with the same Subject-DN defeat browser chain-builders:
Chromium/Edge/Firefox pick one candidate and refuse to try the others, so
every .bch site failed with ERR_CERT_AUTHORITY_INVALID / SEC_ERROR_BAD_SIGNATURE
in every browser EXCEPT Theseus (which trusts the on-chain tls fingerprint
directly, not the machine store).
Reproduced on the dev box: two BNS Local Root CAs present (thumbprints
EB5DBE98... constrained + 23538FD7... unconstrained), DNS answered correctly,
strict Invoke-WebRequest to https://coinspectrum.bch/ failed. Removing the
stale one and re-running the chain-build restored HTTPS 200.
Fix (install.ps1):
- Before Add(imported), enumerate the store and $store.Remove() every
"BNS Local Root CA" whose thumbprint differs from the one we're about
to trust. Post-condition: exactly one BNS root remains after install.
Fix (uninstall.ps1):
- Switched from `Get-ChildItem Cert:\LocalMachine\Root` to X509Store direct.
The Cert: PSDrive is not always loaded in Inno's [UninstallRun] -NoProfile
context, so uninstall could silently leave the CA behind on the store side
even while it removed everything else.
Verified end-to-end on this box: 0.1.4 upgrade over 0.1.3 finished cleanly,
BNS Resolver Daemon Running, 127.0.0.1:53 open, exactly one BNS Local Root
CA in the machine store, strict HTTPS to https://coinspectrum.bch/ returned
200 (506,997 bytes) with X509Chain.Build ok=true leaf -> BNS root.
Deployed
- dl.silentmode.st/AriadneResolver-Setup-0.1.4.exe
- s3://bns/silentmode/dl/AriadneResolver-Setup-0.1.4.exe
- silentmode.st manifest advertises 0.1.4
- sha256 30ed5e3bb6d6da5325f854c97976410b4fc63067ed52c810a55e9d2e1bdc4e17
Canonical silentmode.st URLs no longer carry a trailing slash (/tools, not
/tools/). nginx (tracked now in VPS/SilentMode/silentmode-st.nginx) 301s
the old form and serves <dir>/index.html; sub-sites deployed from other
repos with relative asset paths (deviant, sirius-x, theseus-x, hephaestus.x,
fly.x, code) keep their directory URLs. Every page's internal links are
now site-root-relative, which resolves correctly both at /x on nginx and
under the BNS gateway's injected <base href="/bns/silentmode.bch/"> — the
old ../x/ links were already broken on the gateway route.
/theseus becomes the Silent Mode-headered Theseus page (what it is, what's
inside, Windows + Android downloads with manifest hashes, verify), linking
out to the sovereign theseus.x whose VPS mirror moves to /theseus-x/, the
same split as /sirius vs /sirius-x/. /tools is repurposed as the overview:
every site, the on-chain twins, the other clients (relay, Firefox, the
standalone Ariadne Resolver) and the machine endpoints. The old tools page
carried stale APK and resolver hashes; the new pages use the manifest's,
verified against the files on dl.silentmode.st.
scripts/serve-site.mjs mirrors the nginx rules for local preview.
Until now only the gateway, Theseus and the desktop reader applied the
TLD co-sign rule; phones and the Windows resolver still admitted every
registration under a cosign or hidden TLD, so the network disagreed
about which names exist. Both shipped builds now carry the rule.
Android 0.19: the JSON helpers in the new TLD-map code used throwing
getters inside methods that do not declare the checked exception, which
javac rejected under the real build (the earlier compile check ran
without -bootclasspath and stopped at the aapt R errors first). Switched
to the non-throwing opt* forms. Release-signed with the existing key.
Resolver 0.1.3: no source change beyond the resolver library already
committed; the installer picks up the source tree, so this is a version
bump and a rebuild.
Manifest, releases page, tools page and theseus page point at the new
files; dl.silentmode.st/latest redirects regenerated.
Direct answers to the three complaints in one release.
"Doesn't load any results even if I type a keyword" — navigateTo used to
always append .bch to any bare label. So "bitcoin" became
https://bitcoin.bch/ and NXDOMAINed. Now: input with a space, or bare
label with no dot, routes to the user's chosen search engine. Input with
a dot (hello.bch, example.com) stays a URL. Matches Chrome/Firefox
omnibox behaviour exactly.
"Has no check for updates in settings" — new Updates section shows the
installed version + signing-cert SHA-256, with a "Check for updates now"
button that manually polls dl.silentmode.st and toasts the result. If a
newer version exists, the standard silent-prefetch → green-chip → tap-to
-install flow (unchanged from 0.15) kicks in.
"Looks poor compared to a regular browser" — Settings gains three more
sections beyond Resolution / Ariadne's Thread / Maintenance:
- Search: segmented picker for DuckDuckGo (default), Startpage, Brave
Search, Google, Kagi. Persists via SharedPreferences.
- Updates: version + cert + manual check.
- Privacy: "Clear browsing data" — cookies (CookieManager), form data,
cache, per-tab history, all in one tap. Bookmarks + tabs preserved.
- About: silentmode.st/theseus + theseus.x links, brand credit.
serveSettingsPage() signature grew to take (indexerOn, searchKey,
currentVersion) so it can render the current selection + version. Added
searchEngineSegment() helper for the picker layout.
Release: ariadne-v0.17.apk sha256
8a655081782ecc17a50a7fcd67c28625ccb0c905cf6b583bdd703a128b2b9b10
Deployed to dl.silentmode.st + silentmode.bch (Sia mirror). Site pages
bumped: silentmode.st/tools + /releases + /theseus + theseus.x.
Users on 0.15 reported "Ariadne can't open many websites" and "start page
is full of dead links". Two independent stale-data issues, both fixed.
Start page — replaces the featured-hero + beacon-fallback grid with the
same nine curated cards navigate.st serves (hello.bch, siatest.bch,
SilentMode.X, Theseus.X, Sirius.X, Hephaestus.X, Prometheus.X, Helios.X,
Hermes.X). No more auto-iteration over every registered name on the
beacon — which is what was surfacing smtest-dc5563.bch, uitest-e20579.p2p,
qrtest-e21970.nav etc. Added product-role badges (infrastructure /
navigator / registrar / code-host / app-store / search / messaging) with
the same acid/blue/purple/green/gold/pink vocabulary Theseus uses.
Bundled snapshot at app/assets/bns-index.json regenerated from the live
chain via the resolver-web.js buildIndex path. Up from 44 entries to 54,
now including all 13 .x names (was 6 — silentmode.x, theseus.x,
hephaestus.x, prometheus.x, helios.x, hermes.x etc. were entirely
missing). So cold-start resolution finds the .x brands without waiting
for a network trip.
Also regenerated dl.silentmode.st/bns-name-index.json — same 54-entry
JSON. That file hadn't been rebuilt since 2026-08-30 and is what every
client's CDN pull path reads on cold start (mobile, extension, resolver).
There's no timer that regenerates it; scratchpad/build-snapshot.mjs is
the reproducible one-shot: node build-snapshot.mjs <cdn-path>.
Sites updated in the same commit (all four surfaces need to advertise the
same version — silentmode.st/tools + /releases + /theseus + theseus.x
were still linking 0.15). APK also mirrored to bns/silentmode/ so
silentmode.bch/ariadne-v0.16.apk serves the same bytes.
Release: ariadne-v0.16.apk sha256
fa58aa7642319faaa6b23f0f0a46c0adad2ce1f3c5957f4d527ac09241b76574
Old links pointed users at ariadne-v0.11.apk from three separate pages
while the in-app auto-updater was already pulling 0.15. New downloaders
got 4 versions behind.
- site-theseus-x/index.html — v0.11 → v0.15, hash updated, meta noting
in-app auto-update. Sia-uploaded to bns/theseus/ so theseus.x reflects
it now.
- site/releases/index.html — bumps the Ariadne row from 0.11 to 0.15
with the new hash and a release note covering the DOWNLOADING/READY/
RETRY chip states shipped in 0.15.
- site/tools/index.html — same v0.11 → v0.15 bump. Also retitled from
"Theseus — Silent Mode" / "Theseus — the browsers" to "Tools — Silent
Mode" / "Silent Mode tools" because the page actually lists every
client (Theseus Win + Android, Ariadne extension, navigate.st relay,
Ariadne standalone Windows resolver) — a tools directory, not a
Theseus-dedicated page. Intro now points at /theseus/ for the
dedicated Theseus landing.
- site/theseus/ NEW — clearnet mirror of theseus.x. Same page, retitled
"Theseus Navigator — Silent Mode" with canonical URL pointing at
silentmode.st/theseus/. Users on the resolver reach theseus.x for the
same content trustlessly; the /theseus/ path is the always-reachable
fallback with a real cert. Also pushes the APK itself to
bns/silentmode/ so silentmode.bch/ariadne-v0.15.apk works too
(dl.silentmode.st and silentmode.bch now serve the same bytes with
identical SHA-256).