Merges a parallel session's work with the multi-source BNS story from 0.0.7.
The dApp side (parallel session)
--------------------------------
* bcnr-preload.js — installs `window.bcnr` on every page via contextBridge.
Read-only surface: resolveName(name), isRegistered(name), getBcnrTlds(),
getRecordVersion(name), plus getPermissionOrigin() for diagnostics. All
Promises; a missing name returns null (not throw). No signing, no wallet
unlock — that surface is designed but deliberately out of scope for 0.0.8
(see TheseusNavigator/DESIGN-integrated-wallet.md).
* bcnr-origin.js — pure function that computes the eTLD+1 permission origin
for a URL. ICANN suffixes via `psl` (same PSL Chromium uses, handles
.co.uk / .github.io / etc); BNS names key off the on-chain TLD list so
foo.wallet becomes a public suffix as soon as `wallet` appears there.
Match browser cookie / MetaMask semantics: a grant on pay.merchant.com
covers account.merchant.com but not evil.com.
* dev/bcnr-selftest.js, dev/origin-selftest.mjs — self-tests, no I/O.
* main.js wires bcnr-preload.js into session.defaultSession.setPreloads() so
it runs BEFORE per-WebContentsView preloads; adds bcnr:* IPC handlers.
* preload.js + chrome.html — small hooks so the shell picks up window.bcnr
the same way regular content does.
* package.json — psl dep, bcnr-preload.js/bcnr-origin.js in `files`.
Also included
-------------
* AriadneResolver/mobile/.../UpdateCheck.java — in-app update-check for the
Android app; already active in the shipped 0.11 APK (build.ps1 -Recurse
picked it up), formalising the source now.
* TheseusNavigator/snapshots/bns-name-snapshot.json — refreshed bundled
starter (73 beacon txs, root c37b8596…c54e414ba).
* Site pages + manifest updated to point at 0.0.8.
TheseusNavigator-Setup-0.0.8.exe 95.4 MB
21939743eafdfe8742a6b7c4b987bd2782384d7bc41289cb80a7e08019dc9f02
TheseusNavigator-0.0.8-portable.exe 92.7 MB
2aa429fe39dc0fa4ac040fc6d6eb31b0f890c8a83175c49fcb50f052c480d39d
The first .bch page now opens with zero user-visible latency and stays fresh
for as long as the browser runs. Four sources conspire in parallel — none of
them can block a navigation:
1. Warm start from disk (sync)
warmFromSnapshot loads the user-cache snapshot first, then falls back to
the copy bundled with the build. sharedIndex is set BEFORE the first
navigation can even fire.
2. Continuous background delta refresh (every 30 s)
startBnsPolling opens one electrum connection, fetches the beacon
history (a single call), and only pulls verbose tx bodies for txids we
don't already have — mergeFreshHistory-style. Merges into memory,
rebuilds the index locally, persists the enlarged snapshot to disk.
Turns a ~60 s full walk into ~1 s per new event.
3. Sia snapshot pull on boot (one-shot, wins the NEXT boot)
refreshSnapshotFromSia downloads the operator's published snapshot from
s3.silentmode.st for the next launch. After a long idle period the
browser resumes from that fresher snapshot instead of walking days of
events.
4. ensureIndex full-walk fallback
Still runs on boot for the case where there's no bundled snapshot AND
the poll hasn't landed yet — very first launch, offline install, etc.
resolveHost now prefers sharedIndex (which the poll keeps live) and, on a
miss with a stale index, triggers pollAndMerge (delta fetch) instead of
ensureIndex (full walk). The old full-walk fallback is only taken if the
delta primitives aren't available (running against an older resolver-web).
Argus/src/lib/resolver-web.js exports connectElectrum so the Theseus poll
can drive its own ad-hoc queries against the pool without duplicating the
Electrum wrapper.
Bundled starter snapshot refreshed: 73 beacon txs, root c37b859682…54e414ba.
Artifacts:
dist-public/TheseusNavigator-Setup-0.0.7.exe (95.4 MB)
sha256 1b0dabcd2b13067aa1fd89c3271708b35ba22dfc7a620e248b35e0487b7a104f
dist-public/TheseusNavigator-0.0.7-portable.exe (92.7 MB)
sha256 706dc01b21a88d3c2fbc3eeced0cab6ace873630bf3edc2d40915ca5be5c8cae
Four independent pieces of one story — make cold-start .bch resolution fast,
survive individual electrum outages, and turn adding a Silent Mode BNS server
into a checklist run.
* Argus/src/lib/snapshot-name.js — pure, interpretation-free snapshot format
for the name beacon (raw history + verbose tx cache + deterministic root).
* Argus/src/publish-name-mirror.mjs — mirror the snapshot to Sia S3
(floating + content-addressed) and Nostr NIP-33 (kind 30078,
d-tag bns-name-list). Same pattern as publish-tld-mirror.mjs.
* Argus/src/snapshot-name-to-file.mjs — dump the snapshot to a file for
bundling. Writes to TheseusNavigator/snapshots/bns-name-snapshot.json.
* Argus/src/lib/resolver-web.js — new export buildIndexFromSnapshot() runs
the same REG/UPD reduction as buildIndex() but from a pre-fetched snapshot,
no electrum required. Warm-start path in Theseus depends on this.
* TheseusNavigator/main.js — warmFromSnapshot() and refreshSnapshotFromSia()
wired into app.whenReady(). First .bch navigation returns from a warm index
instead of waiting on a full electrum walk.
* TheseusNavigator/package.json — bundles the starter snapshot as an
extraResource so packaged builds ship with a floor.
* TheseusNavigator/snapshots/bns-name-snapshot.json — first starter snapshot
(70 beacon txs, root 8cc859aa…).
* VPS/BNS-SERVER-PLAYBOOK.md — turn-key checklist for spinning up a second
or third Silent Mode BNS server, distilled from what actually worked on
the silentmode box (BCHN 29 [chip]-not-[chipnet], multi-beacon indexer,
wss:// nginx, on-chain publish via electrum.bch, common gotchas table).
* Argus/src/register-electrum-list.mjs — publish the current chipnet
server pool as `el` on electrum.bch. Fits inside the 200-byte OP_RETURN
cap by sizing the record (drops fallback IP pins in favour of URL-only
tokens until they fit). NAME was chosen deliberately: two-part `electrum.bch`
normalises to the bare distinct name `electrum`, whereas the earlier
candidate `electrum.silentmode.bch` collapsed to silentmode.bch and would
have inherited/overwritten that name's records.
* Argus/src/revert-silentmode-bch.mjs — one-off recovery from the earlier
register-electrum-list revision that hit exactly that subdomain-collapse
bug (broadcast an UPD to silentmode.bch and clobbered its s3 record).
Records recovered from the local snapshot cache; safe to leave in the
tree as documentation of what happened.
Setup b740cb033173622b192701ff36f20a97e357fedebf77c3c7ead03d113a9ac229
Portable 782a2ad235a4a1e1491df6a1d16c817fa8542e363e3c6b139c7e04f40846f4c2
New:
- Tabs carry the page favicon (page-favicon-updated -> emitTabs -> the
chrome renders it in the same slot the loading spinner uses).
- Image right-click: Open image in new tab / Save image as... / Copy
image / Copy image address. Save-image-as uses the existing
will-download tracker, so it also shows in the downloads chip.
- Tab cursor: default arrow at rest instead of the always-'grab' hand.
Grab only shows while a tab is being dragged for reorder.
Deployed:
- scp installers + releases-manifest.json to /opt/silent-mode/dl/
- scp tools/ + releases/ index pages to /opt/silent-mode/site/
- sia-upload of ../site to bns/silentmode/
- verified HEAD 200 + manifest 0.0.6, VPS hashes match, tools page
shows 0.0.6 buttons on silentmode.st AND silentmode.bch (Sia mirror).
The 0.0.5 update chip will surface 0.0.6 on existing installs at next
launch (6h manifest poll).
Setup 606529ea9f1de9dc1ec5012534dda31b06919245f19f934ee1b9f4f10385a5bc
Portable ed89547a155e998278beccf21f9807841ac6267f75cdcbbead81b80acfee0adc
Fixes:
- Classic form-GET search engines (Google, Brave, Bing, Startpage,
Yandex, Ecosia, Mojeek, ...) now show results. The tab's
will-navigate intercept was dropping the query string on every
dotted-host navigation, so /search?q=foo landed on /search. DDG
only appeared to work because its in-page search uses pushState +
XHR and never triggered will-navigate.
- Address bar reflects the target URL immediately on Enter instead
of showing the previous page's URL until did-navigate fires.
New:
- Link-hover status bar: Firefox / Chrome-style pill at the bottom-
left of the window showing the href when the pointer is over a
link, hidden when it leaves. Auto-sizes to text, cleared on tab
switch, tracks window resize.
Also on-VPS: bns-gateway auto-index directory paths (f43ec61) so
silentmode.bch/tools/ returns the tools page instead of NoSuchKey.
Deployed:
- scp installers + releases-manifest.json to /opt/silent-mode/dl/
- scp tools/index.html + releases/index.html to /opt/silent-mode/site/
- sia-upload of ../site to bns/silentmode/
- verified: HEAD 200 on both installers, manifest reports 0.0.5,
silentmode.st/tools shows the 0.0.5 buttons, Sia mirror ditto.
The 0.0.4 update-check chip should now surface itself for existing
installs on their next launch.
Firefox / Chrome-style small pill at the bottom-left of the window
showing the href when the pointer hovers a link, hidden when the
pointer leaves. Fed by webContents.update-target-url on every tab;
auto-sizes to its text via an IPC resize channel.
Cleared on tab switch so a lingering hover pill from tab A doesn't
carry across to tab B. Positioned by layout() so it tracks window
resizes.
New files link-status.html + link-status-preload.js registered in
build.files (GOTCHAS.md rule: missing entries silently omit from
the packaged app).
Not shipped yet — bundles into the next Theseus release.
Bumps version so the chip actually surfaces itself on 0.0.3 installs
(the version-newer check requires a strict semver bump — same-version
rebuilds don't trigger the chip). From this release on, whenever the
manifest names a newer Theseus, users get a one-click download.
Mechanism
- main.js checkForUpdate() fetches https://dl.silentmode.st/releases-
manifest.json on startup (5s timeout, cache: no-store) + every 6h.
Finds the theseus-navigator release, compares version to
app.getVersion() with a numeric a.b.c comparator that handles
"0.10.0 > 0.9.9" correctly.
- On a match → stores { version, setupUrl, portableUrl, setupHash,
portableHash, date } and emits update-available to chrome. Cleared
after the user upgrades + relaunches (same-version → null).
- Re-emits on chrome's did-finish-load in case the fetch beats the
chrome view.
Chip UI (chrome.html)
- Acid-yellow pill between the downloads button and the Tor toggle:
"↓ Update to X.Y.Z" + a ✕. Main body opens setupUrl in the system
browser via shell.openExternal (origin-validated to
https://dl.silentmode.st/ or https://silentmode.st/). ✕ dismisses
for the current session — you'll see it again next launch if still
behind.
Trust anchor
- No signing / no cryptographic verification of the download in this
phase. releases.silentmode.bch publishes the SAME manifest URL, so
users who want to verify can cross-check the manifest hash against
what BCNR returns. The proper auto-updater with signature checks is
the follow-on to this cheap version.
Non-goals in phase 1
- No delta downloads; the user clicks and gets a full installer.
- No auto-install; download → user runs the installer themselves.
- No "check now" button in Settings; the periodic timer suffices.
- No portable-vs-installed detection; the chip prefers setupUrl (the
installer upgrades in place). Right-click for portable is future work.
- Hermes/proof/: standalone keystone — BIP-39→Nostr, NIP-17 wrap/unwrap,
name-addressed send/receive verified end-to-end via public relay
- Argus/src/lib/hermes-derive.js: HKDF(silentmode/messenger/0) using libauth
so the registrar can compute np without pulling nostr-tools into Argus
- Argus/src/register-hermes-chipnet.mjs: idempotent REG/UPD script; publishes
np (Nostr pubkey) and nr (relay) records for a chipnet name
- TheseusNavigator/lib/hermes.js: same derivation + wrap/unwrap + record
parsing, canonical for Theseus; guarded by lib/package.json type:module
- TheseusNavigator/messages.html + messages-preload.js: Messages panel UI
(identity from mnemonic, live inbox, compose by .bch name), .bch suffix
stripped from displayed names
- TheseusNavigator/main.js: HERMES_MOD + loadHermesLib next to VAULT_MOD;
ipc handlers (hermes-status/init/close/inbox/send/open), per-relay
subscription with auto-reconnect, status pushed on WS open/close,
reverse-resolve pk -> .bch name via cached BNS index, Ctrl+Shift+M shortcut
via web-contents-created (works from any tab)
- Chipnet hermes.bch registered with np=f2c92519...67f4 nr=wss://nos.lol
(txid 7fc6de4544c13b782f163fdb892ea6749785886d05a336282fa659d722c7e92b);
end-to-end verified in Theseus
Six user-visible improvements + supporting infra, all uncommitted from
the earlier session-in-progress state. Ships together in one release.
Chrome / tabs
- Same-size tabs: flex 1 1 0 with max 200px, min 60px. Container gets
overflow: hidden so many tabs shrink evenly instead of scrolling out.
- Drag-and-drop tab reordering. HTML5 drag events on each .tab; drop
side chosen by pointer x within target (Chrome UX). New move-tab IPC
splices the tabs array + re-emits.
Address bar
- Persistent history at userData/history.json capped at 500 LRU. Ranked
by host-prefix > url-prefix > contains > title-contains > recency.
- Floating suggestions dropdown (addressPicker WebContentsView) anchored
under the URL bar. Debounced 80ms input; ArrowUp/Down forward to the
picker via address-cursor IPC; Enter fires goURL; blur closes after
160ms so click-through registers. New files address-picker.html +
address-picker-preload.js. Cleared by existing clearHistoryOnQuit.
Password autofill (A.2 MVP)
- Green key chip in the address bar appears when the vault is UNLOCKED
and the active tab's host has matching credentials (exact hostname
match for phase 1; eTLD+1 upgrade queued as A.2.5).
- Click chip → floating picker of usernames. Click a match → main.js
runs a small script in the active tab: finds first visible
input[type=password]:not([disabled]), walks the same form for a
visible text/email/tel/url/search input whose name/id/autocomplete
matches /username|user|email|login|account|id/, fills both via the
native value setter + dispatches input/change so React/Vue-controlled
inputs update. New files pw-fill.html + pw-fill-preload.js.
- emitPwAvailability fires from pushNav + vault setup/unlock/lock so
the chip's visibility + count stays accurate.
Bookmarks bar
- Right-click context menu on the favorites bar. On empty area:
"Add current page" (or "Remove current page" if already saved). On a
specific bookmark: "Open", "Edit title…" (prompt), "Remove", plus
the add/remove-current entry. Uses a shared .ctxmenu style mirroring
the settings ctxmenu (dark/light aware).
- Empty-state text updated to mention right-click.
Home page
- Larger responsive card grid: auto-fill minmax(260-280px, 1fr) with
breakpoints at 600/900/1200. Cards have a subtitle line, a colored
badge (on-chain / Sia / server / custom), and edit affordances that
reveal only in Edit mode.
- User-editable set: Edit toggle reveals per-card ✎/✕ + a dashed "+ Add
card" tile. Modal for add/edit with title / URL / subtitle / badge.
Reset-to-defaults button.
- Persisted at userData/home-cards.json. New home-preload.js exposes
window.home = { getCards, setCards, resetCards, navigate }. IPC
handlers in main.js validate sender.getURL() matches our own
home.html — third-party pages see the API shape via the preload but
can't act on the user's local cards.
- Fallback set of 2 cards renders when window.home is unavailable
(e.g. opening home.html directly outside Electron for preview) so
the grid is never blank.
Docs
- TheseusNavigator/ROADMAP-identity-wallet.md — the phased plan for
the two independent strands (password manager A.2/3, browser wallet
B.1-6). Committed earlier this session; re-listed here for context.
- TheseusNavigator/SESSION-PROMPT-identity-wallet.md — pastable
kickoff for the next session picking up either strand.
Files added to build.files: address-picker.html,
address-picker-preload.js, pw-fill.html, pw-fill-preload.js,
home-preload.js.
- TheseusNavigator/package.json: 0.0.2 → 0.0.3. Address-bar fix (main.js refreshTabUrl,
in 9b9c93c) makes silentmode.bch subpage clicks update the URL correctly.
- site/tools/index.html: collapsed the two-flagship-cards row into one Theseus
Navigator panel with a shared description and two version sub-blocks (Windows
+ Android) inside a divider grid. Same-product-two-platforms framing.
- site/index.html: Tools card copy updated to match (Theseus Windows + Android;
built-in Ariadne; also relay, extension, standalone resolver).
- site/releases/index.html + releases-manifest.json: Theseus 0.0.3 entry with the
new hashes; Android section corrected to v0.8 (was previously showing v0.8
filename with a v0.2 hash — the linter had gone half-way).
Bump to 0.0.2; publish new installer/portable hashes across the download
site (tools + releases pages), releases-manifest.json (Theseus entry only —
Ariadne Resolver/Android entries preserved), and RELEASE-HANDOFF.md.
Artifacts rebuilt reproducibly (SOURCE_DATE_EPOCH=1785888000, unsigned).
Setup b3a810472b06273c1cc846adcb84366ad9114276a984bed7347c26f019497c56
Portable 37679d293715b9e1881d38ee7e92a5a7448f3c523a14919637afe732e2478ce1
Theseus soft-mode UX: 'Open with...' modal on collision, per-name/per-TLD
overrides, live per-tab switcher in the site-info popover, and a Naming section
in Settings for policy + reset. Backed by an on-chain root TLD certificate
(tlds.bch) that resolver-web.js discovers via fetchBcnrTlds()/isBcnrNativeTld().
Companion pieces:
- Argus/src/indexer/ELECTRUM-SOURCE-README.md — the featherweight VPS variant
(no BCHN node, no Fulcrum) now live as bns-indexer.service.
- Argus/DESIGN-root-tld-cert.md — clarified: NOT a governance workflow, just
ordinary key management (single wallet MVP -> 2-of-3 multisig). List gates
registration / surgical NRPT / soft-mode classifier — never resolution.
- ROADMAP-IDEAS.md — recorded SiaGit/GitHub.sia + user-friendly Sia UI ideas.
Full spec: Argus/DESIGN-collision-modes.md (already tracked).
Site manifest and download pages point at the rebuilt resolver:
AriadneResolver-Setup-0.1.0.exe
sha256 cb9e8ea0dcffaa60607ff1781e160199956dcf2d7dd69cd13986aba75fcf0fb1
Bumps release date to 2026-08-01. This build is the one that carries the
EDNS OPT-echo fix from the prior commit into what dl.silentmode.st
serves; users on the daemon should stop seeing "Server Not Found" for
normal ICANN names in Firefox / anything using getaddrinfo.
TheseusNavigator/package.json: adds engine-picker.html,
engine-picker-preload.js, popover.html, popover-preload.js to the
electron-builder `files` array. Because that list is explicit,
electron-builder shipped only what was listed, so in the packaged 0.0.1
build the WebContentsView created for the search-engine dropdown loaded
a nonexistent file and rendered blank -- visually identical to "the
button does nothing". `npm start` worked because dev reads from the
source tree. Fix restores the picker; needs a Theseus rebuild + redeploy
to reach users, then TheseusNavigator-Setup-0.0.1.exe's SHA-256 has to
be re-published here.
Ariadne hash still needs to be published on-chain to
releases.silentmode.bch (wallet spend, user's action).