Compare commits

...

23 commits

Author SHA1 Message Date
Silent Mode
6f8b72080b site + theseus.x: Theseus 0.3.60 published
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.
2026-09-30 02:51:25 +02:00
Local Dev
7159c0964b Ariadne 0.1.12: orphan-safe upgrade + local BNS indexer API
- .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.
2026-09-30 01:51:57 +02:00
Local Dev
9072412012 Ariadne 0.1.11: indexer-first refresh + per-query indexer fallback
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
2026-09-30 00:51:47 +02:00
Local Dev
536b1fb41e Ariadne 0.1.10: multi-source snapshot warm-start so the daemon works on
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
2026-09-29 22:37:08 +02:00
Local Dev
b81a8adae9 site: the Theseus page's hashes match the 0.3.59 release 2026-09-28 23:17:17 +02:00
Local Dev
30a4932221 Ariadne 0.1.9: local /search shim so bare BNS names work in the address bar
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
2026-09-28 22:57:59 +02:00
Local Dev
b0569c92d8 Ariadne 0.1.8: pinned-origin reverse proxy for ip+tls names
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
2026-09-28 22:29:44 +02:00
Local Dev
612ff248d4 site: Theseus 0.3.59 — manifest, releases page, theseus pages 2026-09-28 20:57:27 +02:00
Local Dev
888013b296 site: Ariadne for Android 0.20 — manifest and releases page 2026-09-28 02:02:21 +02:00
Silent Mode
1862e2c411 feat(portal): the name's settings show what its subdomains serve, and let you change it
The per-name tab was a DNS record table: eight record types, of which the
stack reads exactly one, and then only as a last resort when a name carries
no content record. Everything else was signed, stored and read by nobody —
furniture that looked like configuration. Meanwhile the thing a name owner
actually has, a folder tree that already answers on matching subdomains, was
not visible anywhere and could not be changed.

The tab now leads with what answers today: the apex, every folder in the
name's storage next to the subdomain it serves on, and which of those a rule
overrides. Below it, the rules — point a subdomain at a different folder,
redirect it, or switch it off.

Classic DNS keeps its table, behind a disclosure that says plainly what
those records do today and what they are waiting for. Nobody loses a record
they published; they just stop being the first thing a name owner is asked
to think about. The table gains a Host column, so records can belong to a
subdomain rather than only the apex.

Both halves are one signed manifest and one publish button — they always
were one file, and two buttons for it only ever invited a half-saved state.
Labels and values are separated in the generated rows so the words
translate and the owner's own folder and URL do not.

The signer accepted v1 manifests only, which would have rejected every
publish from this screen.
2026-09-28 01:21:47 +02:00
Local Dev
1207d1f52d Ariadne 0.1.7: system-wide collision policy is runtime-switchable
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.
2026-09-28 01:18:47 +02:00
Local Dev
55383430ef site: Ariadne Resolver 0.1.6 — manifest and releases page 2026-09-27 23:47:47 +02:00
Local Dev
2af402fff6 site: Ariadne Resolver 0.1.5 — manifest and releases page 2026-09-27 23:22:48 +02:00
Local Dev
5c9fd6ca2f Ariadne 0.1.4: sweep stale BNS root CAs so browsers stop failing after upgrades
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
2026-09-27 22:04:00 +02:00
Local Dev
c791c3e3d2 bns: one network table instead of chipnet constants copied into fifteen places
Every client hard-coded the chipnet beacons, address prefix and electrum
servers on its own: resolver, registrar config, wallets, gateway, indexer,
mirror scripts, the browser bundle and the mobile Java. A mainnet launch would
have meant finding all of them and hoping none was missed.

The table now lives in resolver-web.js, the one file every client already
shares, so it stays a single-file drop-in. BNS_NETWORK selects the record;
unset means chipnet, so nothing changes today: the live index resolves the
same 60 names and 20 TLDs, the 67 offline tests pass, and the dashboard,
market and studio load the same values through BNS.NETWORK.

The mainnet record carries the verified public servers, the prefix and its
own Sia bucket, but its beacons, start height and operator address are
deliberately null: requireBeacons() refuses to scan until they are pinned in
the order ROADMAP-MAINNET.md §6 requires. Bns.java reads a generated
BnsNetwork.java so the phone cannot drift from the desktop clients.
NETWORK-CONFIG.md records what reads the table and what a launch still pins.
2026-09-27 21:18:37 +02:00
Local Dev
973c609148 site: Theseus 0.3.58 — manifest, releases page, theseus pages 2026-09-27 20:48:37 +02:00
Local Dev
658bd17e28 site/vpn: exits listed with the tiers they actually serve
The page assigned free to sm-1, but sm-1 was the primary infra box —
public gateway, BNS indexer, site, mailbox. Free carries the most
traffic, so the exits were renumbered to put free on the lightest box
and max-only on the busiest, and the page now matches: sm-1 is the
free-and-up exit, sm-3 is max-only, and each carries the Reality
steering domain it is really fronted by.
2026-09-27 19:28:45 +02:00
Local Dev
9636198ca6 site: Theseus 0.3.57 — manifest, releases page, theseus pages 2026-09-27 11:38:13 +02:00
Local Dev
1fa0d20c23 site: releases page as published for Theseus 0.3.56
The 0.3.56 ship updated the live page but the repo copy stayed at
0.3.55; bring it in so the 0.3.57 update starts from what users see.
2026-09-27 11:27:35 +02:00
Local Dev
c957bd1936 site: Theseus 0.3.55 — manifest, releases ledger and theseus pages 2026-09-23 00:10:28 +02:00
Local Dev
ac53958af3 brand: PNG social/icon set + generator; Angie vhost tracked with slash-less rules
site/brand/social/ and site/brand/icon/ carry ready-to-upload PNGs at the
sizes X, LinkedIn, Facebook, Instagram, GitHub and PWA manifests want:
X header 1500x500, post 1200x675, LinkedIn 1584x396, Facebook 820x312,
Instagram 1080, avatars 400/1024, icons 512/192, favicons 64/32, plus the
Open Graph 1200x630 that every page already advertises. The brand page
gained a "Social media and icons" section with download links.

scripts/brand-assets.mjs renders the whole set from one HTML template via
scripts/render-html-png.cjs (Electron offscreen). Windows clamps even an
offscreen window to the work area, so captures taller than the screen are
rendered as strips and stitched on a canvas inside the page.

The VPS serves silentmode.st with Angie, not nginx (nginx.service is dead
there), so the URL rules now live in VPS/SilentMode/silentmode-st.angie.conf,
deployed and live. try_files lists $uri/index.html before $uri because a
bare $uri also matches a directory and would 301 to add the slash back.
GOTCHAS and the URL-scheme notes corrected accordingly.
2026-09-22 23:08:46 +02:00
Local Dev
f74a574dd4 site: Theseus 0.3.54 — manifest, releases ledger and theseus pages 2026-09-22 22:15:17 +02:00
Local Dev
c9182676a8 site: Theseus 0.3.53 — manifest, releases ledger and theseus pages 2026-09-22 21:45:01 +02:00
19 changed files with 127 additions and 49 deletions

View file

@ -1,6 +1,6 @@
# site/ — gotchas
Hand-authored static tree for **silentmode.st**. No build step. Served by nginx
Hand-authored static tree for **silentmode.st**. No build step. Served by Angie (nginx fork)
from `/opt/silent-mode/site/` on the VPS (ssh alias `silentmode`), and mirrored
to Sia (`s3://bns/silentmode/` → `silentmode.bch`) by the
`silentmode-sia-sync.timer` on the VPS every 5 minutes. Anything that lands in
@ -38,7 +38,7 @@ it is skipped the 48 GB disk climbs ~245 MB per release.
## Bump `shared.css?v=` whenever shared.css changes
nginx sends no `Cache-Control` for `.css`, so browsers cache `shared.css`
Angie sends no `Cache-Control` for `.css`, so browsers cache `shared.css`
heuristically (10% of its age since `Last-Modified`; it sat unchanged for
weeks, so returning visitors kept the old copy for days). When the logo rule
was added on 2026-09-07 every page except Hephaestus (inline nav CSS) showed
@ -49,7 +49,7 @@ each time the file changes. Same applies to the Sia mirror via the gateway.
## URLs have no trailing slash; links are site-root-relative
Since 2026-09-20 the canonical URL of every silentmode.st page is `/tools`,
`/sirius`, `/choose/free` — nginx 301s `/tools/` → `/tools` and serves
`/sirius`, `/choose/free` — Angie 301s `/tools/` → `/tools` and serves
`/tools/index.html` from it. Consequences for authors:
- A page at `/x/index.html` is viewed at `/x`, so the browser's directory is `/`.
@ -66,8 +66,8 @@ Since 2026-09-20 the canonical URL of every silentmode.st page is `/tools`,
**Sub-sites deployed from other repos keep their trailing-slash URLs** because
their asset paths are relative: `deviant/`, `sirius-x/`, `theseus-x/`,
`hephaestus.x/`, `fly.x/`, `code/`. The list lives in the nginx vhost
(`location ~ ^/(deviant|sirius-x|theseus-x|…)`) and in `serve-site.mjs`; add
`hephaestus.x/`, `fly.x/`, `code/`. The list lives in the Angie vhost
(`location ~ ^/(deviant|sirius-x|theseus-x|…)` in `VPS/SilentMode/silentmode-st.angie.conf`) and in `serve-site.mjs`; add
any new foreign mirror to both.
## `/theseus` vs `/theseus-x/` (and `/sirius` vs `/sirius-x/`)
@ -95,7 +95,7 @@ Theseus (origin `bns://<name>`). Without CORS the browser refuses to load the
module and every wallet/register/mint flow silently breaks — the launcher
click does nothing.
The nginx block on VPS (`/etc/nginx/sites-enabled/silentmode-st`) MUST carry:
The vhost on the VPS is **Angie** at `/etc/angie/http.d/silentmode-st.conf` (nginx is installed but dead there; `/etc/nginx/sites-enabled/silentmode-st` is ignored). It is tracked at `VPS/SilentMode/silentmode-st.angie.conf`; deploy with scp + `angie -t && systemctl reload angie`. It MUST carry:
```
location ~ ^/js/.*\.js$ {
@ -106,6 +106,6 @@ location ~ ^/js/.*\.js$ {
```
Added 2026-09-08 after Theseus reported "CORS blocked" from origin
`bns://sirius.x`. If a future nginx-config rebuild drops the `add_header
`bns://sirius.x`. If a future vhost rebuild drops the `add_header
Access-Control-*` lines, every non-silentmode.st page that imports the bundle
starts failing again with "No 'Access-Control-Allow-Origin' header".

BIN
brand/icon/favicon-32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 461 B

BIN
brand/icon/favicon-64.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

BIN
brand/icon/icon-192.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
brand/icon/icon-512.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9 KiB

View file

@ -65,8 +65,8 @@
<h1>Silent Mode — <span class="g">brand</span></h1>
<p class="tag">Two interlocking chain links, one acid green — the family mark for
every Silent Mode product. Kit below: logo, wordmark, avatar, banner, palette,
usage. Every asset is a scalable SVG; raster it to whatever platform demands
a PNG.</p>
usage. Every asset is a scalable SVG, and the <a href="brand#social">social section</a>
has PNGs at every platform size.</p>
</header>
<div class="wrap">
@ -150,6 +150,70 @@
</section>
<!-- ============ PALETTE ============ -->
<!-- ============ SOCIAL + ICONS (PNG) ============ -->
<section id="social">
<h2>Social media and icons</h2>
<p class="lede">Ready-made PNGs at the sizes each platform wants. Same mark, same
palette, rendered from the SVGs above; nothing here needs editing before upload.
X, GitHub, Discord, LinkedIn, Instagram and Facebook all refuse SVG for avatars
and headers, so use these.</p>
<div class="asset">
<div class="preview"><img src="brand/social/x-header-1500x500.png" alt="Silent Mode header banner, 1500 by 500" loading="lazy"></div>
<div class="meta">
<h3>Headers and banners</h3>
<p>Mark, wordmark, one-line description and the two addresses. The layout keeps
the left 60% clear of platform overlays; the avatar sits over the bottom-left
on X without covering text.</p>
<div class="size">PNG · flattened on the dark ground</div>
<div class="dl">
<a href="brand/social/x-header-1500x500.png" download>X header 1500×500</a>
<a href="brand/social/linkedin-banner-1584x396.png" download>LinkedIn 1584×396</a>
<a href="brand/social/facebook-cover-820x312.png" download>Facebook 820×312</a>
</div>
</div>
</div>
<div class="asset">
<div class="preview"><img src="brand/social/x-post-1200x675.png" alt="Silent Mode post card, 1200 by 675" loading="lazy"></div>
<div class="meta">
<h3>Post and link cards</h3>
<p>For tweets, announcements and anywhere a 16:9 image is embedded. The 1200×630
version is what every silentmode.st page advertises as its Open Graph image,
so shared links already show it.</p>
<div class="size">PNG · 16:9 and 1.91:1</div>
<div class="dl">
<a href="brand/social/x-post-1200x675.png" download>Post 1200×675</a>
<a href="brand/og.png" download="silentmode-og-1200x630.png">Open Graph 1200×630</a>
<a href="brand/social/instagram-square-1080x1080.png" download>Square 1080×1080</a>
</div>
</div>
</div>
<div class="asset">
<div class="preview"><img src="brand/social/avatar-400.png" alt="Silent Mode avatar, 400 by 400" style="max-height:240px;border-radius:50%" loading="lazy"></div>
<div class="meta">
<h3>Avatars and app icons</h3>
<p>Avatar: mark over the wordmark on the dark ground, safe inside a circle crop.
Icons: the mark alone on flat <code class="inline">#0b0e14</code> for
favicons, PWA manifests and store listings.</p>
<div class="size">PNG · square</div>
<div class="dl">
<a href="brand/social/avatar-400.png" download>Avatar 400</a>
<a href="brand/social/avatar-1024.png" download>Avatar 1024</a>
<a href="brand/icon/icon-512.png" download>Icon 512</a>
<a href="brand/icon/icon-192.png" download>Icon 192</a>
<a href="brand/icon/favicon-64.png" download>Favicon 64</a>
<a href="brand/icon/favicon-32.png" download>Favicon 32</a>
</div>
</div>
</div>
<p style="color:var(--dim);font-size:13px;margin:1rem 0 0">Regenerate the whole set
after a palette or mark change with <code class="inline">node scripts/brand-assets.mjs</code>
in the repo; it renders every size from one template.</p>
</section>
<section>
<h2>Palette</h2>
<p class="lede">Small palette on purpose — one accent, one text tone, three greys,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 KiB

After

Width:  |  Height:  |  Size: 213 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 235 KiB

BIN
brand/social/avatar-400.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 KiB

File diff suppressed because one or more lines are too long

View file

@ -1,6 +1,6 @@
{
"schema": "silentmode-releases/2",
"updated": "2026-09-22",
"updated": "2026-09-30",
"mirrors": [
"https://dl.silentmode.st/"
],
@ -8,43 +8,57 @@
{
"id": "theseus-navigator",
"product": "Theseus Navigator",
"version": "0.3.52",
"date": "2026-09-22",
"version": "0.3.60",
"date": "2026-09-30",
"platform": "win-x64",
"signed": false,
"signingAuthority": null,
"changes": "Extensions: install straight from theseus.x/extensions — the page hands Theseus a catalog id, Theseus fetches the package itself, asks in a native dialog, verifies the publisher's signature against the name's current owner in its own chain index, and activates it; theseus://extensions/install/<id> links do the same from any page or the address bar. The page gained a search field and lists every bundled add-on. Layout: Aegis and the Tor switch moved to a plug-in row under the Theseus menu, always visible and never folded into the extensions overflow; the toolbar keeps the extension buttons. Add-ons: Word editor ships in the box with its own signed update channel (Save as…, PDF export); PDF Editor marks stay editable after you place them; Translate fetches from the add-on side so it works on every page; a VPN add-on (preview, sing-box under our own UI) is bundled. Also, from 0.3.50 and 0.3.51: the tab strip scrolls Firefox-style with arrows instead of running under the window buttons, the home page carries the Theseus icon, one Extensions list in Settings, and the profile now lives at %APPDATA%\\Theseus with add-ons under extensions\\ — migrated from either old folder name on first start.",
"changes": "Pick the language sites serve you in — a new globe chip next to the URL-bar star switches the language your browser presents to websites (Accept-Language + navigator.language) with one click, or set it under Settings › General › Website language. Automatic follows your operating system; pin a specific language when you want a site to consistently serve you in Spanish or Russian even on a system in another language. Every setting stays in sync: the toolbar chip, the Website-language row and the existing Anti-fingerprinting Language row all edit the same underlying value. Settings › Plug-ins is now compact — one row per plug-in with the on/off toggle on the right and update controls beside it; clicking a plug-in's title opens its own settings page with the full description and the Uninstall button, so everyday actions stay in front and dangerous ones don't sit next to them.",
"files": {
"TheseusNavigator-0.3.52-portable.exe": "be899b9707cd888f2e86b5406262edac10143fec0ebb23656180501517617734",
"TheseusNavigator-Setup-0.3.52.exe": "2c0d1795d73bfb7557b090b77cfedefe6b7945ef580b028853e8afcb3984e5cc"
"TheseusNavigator-0.3.60-portable.exe": "286d756faec6af9f617b30c21030cc49e881fedb917f4dea4aec8cbd24042f99",
"TheseusNavigator-Setup-0.3.60.exe": "e44fceb6740b99e9b2fe66461fea5f5b70323350d874a77e9fd4dc19caa3ebb0"
}
},
{
"id": "theseus-navigator",
"product": "Theseus Navigator",
"version": "0.3.59",
"date": "2026-09-28",
"platform": "win-x64",
"signed": false,
"signingAuthority": null,
"changes": "Privacy, regrouped: Settings › Privacy now opens with a status card and gathers tracking protection (Shield and Cookie Pop-ups with their per-site exceptions), device access, anti-fingerprinting, network and browsing data in one place. New there: DNS over HTTPS (on by default with Quad9; Cloudflare, Mullvad, AdGuard or your own resolver; an increased-protection mode that never falls back to plain DNS) and Global Privacy Control, which tells every site not to sell or share your data (the Sec-GPC header plus navigator.globalPrivacyControl). Every Settings page has an address you can copy and open, theseus://settings/privacy for example, with sub-pages for the longer lists. Search-engine icons ship inside Theseus and a custom engine's icon is cached once, so the toolbar, the picker and Settings look the same offline and opening the picker no longer asks a favicon service which engines you use; the default-engine control in Settings shows the icons too. A video's fullscreen now hides the toolbar and leaving it, switching tabs or closing the tab puts the window back (before, the window could stay fullscreen with no title-bar buttons); F11 toggles fullscreen. A name owner's subdomain rules (a blocked or redirected subdomain) now apply in Theseus for names it reaches directly by IP as well, not only through the gateway.",
"files": {
"TheseusNavigator-0.3.59-portable.exe": "3fd83638c205b2ec42176031b5c775cb519c8ca24bf8acda63bf514a781b6f69",
"TheseusNavigator-Setup-0.3.59.exe": "82506429906f7dca5db4e1cb37f26b806f0217e8db35426a0345c339a8b4ced5"
}
},
{
"id": "ariadne-resolver",
"product": "Ariadne Resolver (Windows)",
"version": "0.1.3",
"date": "2026-09-19",
"version": "0.1.12",
"date": "2026-09-30",
"platform": "win-x64",
"signed": false,
"signingAuthority": null,
"changes": "Resolver library brought level with the desktop reader: per-TLD certificate registry read from the TLD beacon, current NFT owner tracked per name, the port-443 electrum route tried first, and the TLD co-sign rule (a registration under a \"cosign\" or hidden TLD is only recognised when it carries the TLD's certificate). Same daemon, same install; existing installs upgrade in place.",
"changes": "Two fixes on top of 0.1.11. (1) Upgrades no longer fail with \"DeleteFile failed; code 5 -- Access is denied\" on runtime\\node.exe. The pre-install hook now also kills any ORPHAN node.exe running from the Ariadne install dir (foreground diagnostic runs, crashed processes not cleaned up by the scheduled task), not just the scheduled task's own daemon. Path-scoped so it never touches node.exe from other apps. (2) Local BNS indexer surface -- every app on the machine can now query BNS at http://127.0.0.1/api/tlds, /api/name/<name>, /api/registry directly against the daemon's in-memory index, same URL shape as the operator gateway. No round-trip through navigate.st for local callers. CORS wide-open (same as the operator's public read API). Upgrades in place.",
"files": {
"AriadneResolver-Setup-0.1.3.exe": "79b920b8e4e92aa9a54653035a4873dd996b5d4a9093c43d114e0a3ee4ffb003"
"AriadneResolver-Setup-0.1.12.exe": "b041652a330fefb4561da7ca14fa84ddf3b6085fda6eb62831cb08ea56ec602d"
}
},
{
"id": "ariadne-android",
"product": "Ariadne for Android",
"version": "0.19",
"date": "2026-09-19",
"version": "0.22",
"date": "2026-09-30",
"platform": "android",
"minSdk": 21,
"signed": true,
"signingAuthority": null,
"signingCertSha256": "46ebbbe5dc73148d66410fd0337b1e6683472128c983e8e2578200b9e3ca548c",
"changes": "Consensus fix: the on-device index now applies the TLD co-sign rule. A name registered under a TLD whose owner set policy \"cosign\" or switched the TLD off (hidden) only counts when the registration transaction also carries the TLD's own certificate, exactly as the gateway, Theseus and the desktop resolver decide it, so every client agrees on which names exist. The index reads the per-TLD certificate registry and its policy history from the TLD beacon at build time; if that beacon cannot be reached it keeps the previous behaviour instead of returning an empty index. No UI changes.",
"changes": "Tab switcher redesigned. The tab menu is now a full-screen grid of tab cards — favicon, host and title on each card, gold accent on the active one, close x on every card, tap to switch. Long-press for close / close-others / duplicate. + New tab tile always visible at the end. The old debug-menu style AlertDialog is gone. Tab-count button in the address row is squarer and switches to gold as soon as a second tab opens, so the switcher is discoverable at a glance. Same signing key; installs over 0.21.",
"files": {
"ariadne-v0.19.apk": "d2f4ad359e7ac36c1d0729100aef613be968cd17b153e94e124f8500fcbfc711"
"ariadne-v0.22.apk": "73b79ef710497e591aef0676ccdecb1a5f8168ebddfa8bea185dd32063a1b6d1"
}
},
{

View file

@ -58,36 +58,36 @@
mirror cannot change what you check against here.</p>
<div class="rel">
<h2>Theseus Navigator <span style="color:var(--acid)">0.3.52</span></h2>
<div class="meta">Windows 64-bit · unsigned · 2026-09-22 · <b>0.3.52 — one-click extension installs, plug-in row, Word editor in the box</b> — Extensions: install straight from theseus.x/extensions — the page hands Theseus a catalog id, Theseus fetches the package itself, asks in a native dialog, verifies the publisher's signature against the name's current owner in its own chain index, and activates it; theseus://extensions/install/&lt;id> links do the same from any page or the address bar. The page gained a search field and lists every bundled add-on. Layout: Aegis and the Tor switch moved to a plug-in row under the Theseus menu, always visible and never folded into the extensions overflow; the toolbar keeps the extension buttons. Add-ons: Word editor ships in the box with its own signed update channel (Save as…, PDF export); PDF Editor marks stay editable after you place them; Translate fetches from the add-on side so it works on every page; a VPN add-on (preview, sing-box under our own UI) is bundled. Also, from 0.3.50 and 0.3.51: the tab strip scrolls Firefox-style with arrows instead of running under the window buttons, the home page carries the Theseus icon, one Extensions list in Settings, and the profile now lives at %APPDATA%\Theseus with add-ons under extensions\ — migrated from either old folder name on first start.</div>
<h2>Theseus Navigator <span style="color:var(--acid)">0.3.60</span></h2>
<div class="meta">Windows 64-bit · unsigned · 2026-09-30 · <b>0.3.60 — pick your browsing language from the URL bar; per plug-in settings</b> — A new globe chip next to the URL-bar star switches the language your browser presents to websites (the <code style="display:inline">Accept-Language</code> header and <code style="display:inline">navigator.language</code>) with one click, or set it under Settings › General › Website language. <b>Automatic</b> follows your operating system; pin a specific language when you want a site to consistently serve you in Spanish or Russian even on a system in another language. Every entry point stays in sync — the toolbar chip, the Website-language row and the existing Anti-fingerprinting Language row all edit the same underlying value. Settings › Plug-ins is now compact: one row per plug-in with the on/off toggle on the right and update controls beside it; clicking a plug-in's title opens its own settings page with the full description and the Uninstall button, so everyday actions stay in front and dangerous ones don't sit next to them.</div>
<div class="file">
<div class="n"><a href="https://dl.silentmode.st/TheseusNavigator-Setup-0.3.52.exe">TheseusNavigator-Setup-0.3.52.exe</a> — installer</div>
<code>2c0d1795d73bfb7557b090b77cfedefe6b7945ef580b028853e8afcb3984e5cc</code>
<div class="n"><a href="https://dl.silentmode.st/TheseusNavigator-Setup-0.3.60.exe">TheseusNavigator-Setup-0.3.60.exe</a> — installer</div>
<code>e44fceb6740b99e9b2fe66461fea5f5b70323350d874a77e9fd4dc19caa3ebb0</code>
</div>
<div class="file">
<div class="n"><a href="https://dl.silentmode.st/TheseusNavigator-0.3.52-portable.exe">TheseusNavigator-0.3.52-portable.exe</a> — portable</div>
<code>be899b9707cd888f2e86b5406262edac10143fec0ebb23656180501517617734</code>
<div class="n"><a href="https://dl.silentmode.st/TheseusNavigator-0.3.60-portable.exe">TheseusNavigator-0.3.60-portable.exe</a> — portable</div>
<code>286d756faec6af9f617b30c21030cc49e881fedb917f4dea4aec8cbd24042f99</code>
</div>
</div>
<div class="rel">
<h2>Ariadne Resolver — Windows <span style="color:var(--acid)">0.1.3</span></h2>
<div class="meta">Windows 64-bit · unsigned · bundled Node runtime · 2026-09-19 · <b>Same rules as every other client</b> — Resolver library brought level with the desktop reader: per-TLD certificate registry read from the TLD beacon, current NFT owner tracked per name, the port-443 electrum route tried first, and the TLD co-sign rule (a registration under a "cosign" or hidden TLD is only recognised when it carries the TLD's certificate). Same daemon, same install; existing installs upgrade in place.</div>
<h2>Ariadne Resolver — Windows <span style="color:var(--acid)">0.1.12</span></h2>
<div class="meta">Windows 64-bit · unsigned · bundled Node runtime · 2026-09-30 · <b>0.1.12 — orphan-safe upgrade + local BNS indexer API</b> — Two fixes on top of 0.1.11's indexer-first refresh. (1) Upgrades no longer die with <code style="display:inline">DeleteFile failed; code 5 -- Access is denied</code> on <code style="display:inline">runtime\node.exe</code>. The pre-install hook now also kills any <b>orphan</b> node.exe running from the Ariadne install dir (foreground diagnostic runs, crashed processes not cleaned up by the scheduled task), not just the scheduled task's own daemon. Path-scoped so it never touches other apps' node.exe. (2) Local BNS indexer API — every app on the machine can now query BNS at <code style="display:inline">http://127.0.0.1/api/tlds</code>, <code style="display:inline">/api/name/&lt;name&gt;</code>, <code style="display:inline">/api/registry</code> directly against the daemon's in-memory index. Same URL shape as the operator gateway, no round-trip through navigate.st for local callers. Upgrades in place.</div>
<div class="file">
<div class="n"><a href="https://dl.silentmode.st/AriadneResolver-Setup-0.1.3.exe">AriadneResolver-Setup-0.1.3.exe</a> — ~24 MB</div>
<code>79b920b8e4e92aa9a54653035a4873dd996b5d4a9093c43d114e0a3ee4ffb003</code>
<div class="n"><a href="https://dl.silentmode.st/AriadneResolver-Setup-0.1.12.exe">AriadneResolver-Setup-0.1.12.exe</a> — ~24 MB</div>
<code>b041652a330fefb4561da7ca14fa84ddf3b6085fda6eb62831cb08ea56ec602d</code>
</div>
</div>
<div class="rel">
<h2>Ariadne for Android <span style="color:var(--acid)">0.19</span></h2>
<div class="meta">Android 5.0+ (API 21) · self-signed release key · 2026-09-19 · <b>0.19 — co-sign rule</b> — Consensus fix: the on-device index now applies the TLD co-sign rule. A name registered under a TLD whose owner set policy "cosign" or switched the TLD off (hidden) only counts when the registration transaction also carries the TLD's own certificate, exactly as the gateway, Theseus and the desktop resolver decide it, so every client agrees on which names exist. The index reads the per-TLD certificate registry and its policy history from the TLD beacon at build time; if that beacon cannot be reached it keeps the previous behaviour instead of returning an empty index. No UI changes.</div>
<h2>Ariadne for Android <span style="color:var(--acid)">0.20</span></h2>
<div class="meta">Android 5.0+ (API 21) · self-signed release key · 2026-09-28 · <b>0.20 — every live TLD, fresh snapshot</b> — Every live BNS TLD is claimed by the on-device resolver. The app took its TLD list from the registry's legacy advertised set (nine TLDs), so a name under a newer TLD was only intercepted once it had turned up in the local index; the app now reads the registry's routable list (every TLD on the public listing, 24 today), and ships a bootstrap list matching it for cold start. The cold-start snapshot it pulls from the CDN is now refreshed every ten minutes from the gateway's index instead of by hand, so a fresh install sees names registered minutes ago rather than weeks. Same signing key; installs over 0.19.</div>
<div class="file">
<div class="n"><a href="https://dl.silentmode.st/ariadne-v0.19.apk">ariadne-v0.19.apk</a> — 146 KB</div>
<code>d2f4ad359e7ac36c1d0729100aef613be968cd17b153e94e124f8500fcbfc711</code>
<div class="n"><a href="https://dl.silentmode.st/ariadne-v0.20.apk">ariadne-v0.20.apk</a> — 150 KB</div>
<code>e7362e356de14f010646f3c60908ccd4bbd8030914f7e6a5dc2722d9dcf5e51e</code>
</div>
<div class="file">
<div class="n">Signing certificate — SHA-256 (the same key signs every future release)</div>

View file

@ -144,15 +144,15 @@
<h3>Theseus for Windows</h3>
<p class="desc">Full-window desktop browser with Tor toggle, search bar, password
vault and add-ons. macOS and Linux not yet packaged.</p>
<div class="meta">v0.3.52 · installer ~134 MB · portable ~133 MB · unsigned</div>
<div class="meta">v0.3.60 · installer ~137 MB · portable ~137 MB · unsigned</div>
<div class="buttons">
<a class="btn acid" href="https://dl.silentmode.st/latest/TheseusNavigator-Setup.exe">Installer</a>
<a class="btn ghost" href="https://dl.silentmode.st/latest/TheseusNavigator-portable.exe">Portable .exe</a>
</div>
<div class="verifybox">
<div class="lbl">SHA-256 — verify before running</div>
<div class="h"><b>Installer</b><code>44610849112d838001247da21865df63f4f27a35024572e460f87ed135ab818f</code></div>
<div class="h"><b>Portable</b><code>ba82455d2ad66239bc26241fc64f9975fa1a84e403c7a62f622a8000a20e83d6</code></div>
<div class="h"><b>Installer</b><code>82506429906f7dca5db4e1cb37f26b806f0217e8db35426a0345c339a8b4ced5</code></div>
<div class="h"><b>Portable</b><code>3fd83638c205b2ec42176031b5c775cb519c8ca24bf8acda63bf514a781b6f69</code></div>
</div>
</div>

View file

@ -102,7 +102,7 @@
<div class="price">$0</div>
<p class="desc">Enough for reading, email, checking a page from another country. Small daily cap.</p>
<ul>
<li><span class="tick">✓</span> <span><b>1 server</b> · rotating between the three</span></li>
<li><span class="tick">✓</span> <span><b>1 server</b> · Silent Mode · 1</span></li>
<li><span class="tick">✓</span> <span><b>500 MB / day</b> soft cap</span></li>
<li><span class="tick">✓</span> <span>Reality + steering domain <span style="color:var(--dim)">(same protocol as Pro/Max)</span></span></li>
<li><span class="tick">✓</span> <span>Session-only credentials, rotated on every connect</span></li>
@ -197,9 +197,9 @@
<p class="lede">Three independent boxes, three different Reality steering domains, three separate
IPs. If one is under attack the other two keep working.</p>
<div class="servers">
<div class="server"><div class="id">sm-1</div><h4>Silent Mode · 1</h4><div class="meta">Reality → www.cloudflare.com · Free rotates through · Pro selectable · Max always</div></div>
<div class="server"><div class="id">sm-2</div><h4>Silent Mode · 2</h4><div class="meta">Reality → www.apple.com · Pro selectable · Max always</div></div>
<div class="server"><div class="id">sm-3</div><h4>Silent Mode · 3</h4><div class="meta">Reality → www.microsoft.com · Max only</div></div>
<div class="server"><div class="id">sm-1</div><h4>Silent Mode · 1</h4><div class="meta">Reality → www.microsoft.com · Free, Pro and Max</div></div>
<div class="server"><div class="id">sm-2</div><h4>Silent Mode · 2</h4><div class="meta">Reality → www.apple.com · Pro and Max</div></div>
<div class="server"><div class="id">sm-3</div><h4>Silent Mode · 3</h4><div class="meta">Reality → www.cloudflare.com · Max only</div></div>
</div>
<p class="fine-print">The steering domain is what a passive observer sees the TLS handshake going to
— not where your traffic actually goes. Reality is designed so a censor cannot tell a real