2026-07-29 13:54:34 +02:00
|
|
|
{
|
|
|
|
|
"name": "theseus-navigator",
|
2026-10-06 00:00:15 +02:00
|
|
|
"version": "0.3.83",
|
2026-09-29 00:18:00 +02:00
|
|
|
"license": "MPL-2.0",
|
2026-07-29 13:54:34 +02:00
|
|
|
"description": "Theseus Navigator — a browser that follows the thread. By Silent Mode, a Deviant project.",
|
|
|
|
|
"author": "Silent Mode",
|
|
|
|
|
"main": "main.js",
|
|
|
|
|
"type": "commonjs",
|
|
|
|
|
"scripts": {
|
|
|
|
|
"start": "electron .",
|
|
|
|
|
"resolve-test": "node resolve-test.mjs",
|
|
|
|
|
"dist": "electron-builder --win nsis portable"
|
|
|
|
|
},
|
|
|
|
|
"dependencies": {
|
0.3.38: brand-green scrollbars everywhere + captureTab widens the viewport when sidebar shrinks the tab
Two changes shipped together (main.js touched by both this session and a
parallel session in different regions):
Scrollbars — from the "empty white space should be grey, thumb should
be Bitcoin Cash green" ask:
* new SCROLLBAR_CSS constant + styleScrollbars(wc) helper injects the
theme on every dom-ready
* thumb #0AC18E (BCH primary), track rgba(120,130,150,0.18) subtle
neutral grey so it works on both dark and light surfaces without
hardcoding either; 6px radius, 2px inset via background-clip:padding-box
* modern scrollbar-color on <html> for Chromium 121+; ::-webkit- rules
with !important as the fallback / override for sites that theme
their own scrollbars — scrollbar-width intentionally left alone so
a page that hides scrollbars entirely keeps that behaviour
* hooked into every wc we own: createTab, chrome, popover, enginePicker,
downloadsPop, addressPicker, pwFillPop, linkStatus, sidebar (so every
add-on panel like Aegis picks it up), approvalPop
* fires once immediately if the wc is already past dom-ready when we
attach — fixed views load fast during startup, we'd otherwise miss
captureTab full-page — from the parallel session's screenshot work:
* before Page.captureScreenshot with captureBeyondViewport we now
override Emulation.setDeviceMetricsOverride to the window's full
content width so an open sidebar (or other on-screen chrome that
narrowed the tab view) doesn't clip the shot — capture comes back at
the page's natural full width, not the visible width
* attach the debugger for the call if it isn't attached, detach on
return; clear the metrics override in finally so the tab returns to
its normal layout regardless of success
2026-09-09 00:42:38 +02:00
|
|
|
"@bch-wc2/interfaces": "^0.0.16",
|
|
|
|
|
"@bitauth/libauth": "^3.1.0-next.8",
|
Ship Theseus 0.3.18 b751b5de (add-on updates land + signed endpoint + tab-flash + screenshot fix + Ariadne installer)
Setup b751b5deea997bb7e0e894104dcb7411358728987196cb610f316edacaf9be54
Portable 8a258f29c62a03b745e93ea0265285e6d5df38d4f25cdbdadc20b4d2a54b97d7
Five theseus fixes since 0.3.16:
e90062a - Bundled add-on updates now actually land. seedBundledAddons()
previously copied a bundled add-on only when its target folder was
missing, so the 0.3.14 screenshot editor never reached machines that
already had an older screenshot/ folder from a previous run — Theseus
quietly kept using the stale copy. The seeder now compares bundled and
on-disk addon.json versions and reseeds with a timestamped backup
under <userData>/addons-backups/<id>-<oldver>-<timestamp>/.
ecfd481 + 6117429 - Signed add-on update endpoint, à la Firefox XPI.
An add-on can now advertise an updateURL in its addon.json and be
republished at any time without waiting for a Theseus release. The
client fetches, verifies an Ed25519 signature over
"silentmode.addon-update-v1|<id>|<version>|<tarball-sha256>",
downloads the tarball, verifies the hash, and stages the new copy
under <userData>/addons-updates-staged/ for promotion on next launch.
Dormant in this build — the shipped addon-update-pubkeys.js is empty,
so checkAndStageUpdates() short-circuits and makes no outbound
requests; the feature activates when an operator ceremonies a key in
and ships a follow-up release with the pubkey baked in. Operator
tooling in scripts/generate-update-keypair.mjs and
scripts/sign-addon-update.mjs; full brief in docs/ADDON-UPDATES.md.
End-to-end verified against a local HTTP server: sign, serve, fetch,
verify, download, extract, stage, promote, backup — plus signature
tamper, wrong pubkey, sha256 tamper, and empty-pubkey short-circuit
all rejected as expected. 15/15 checks pass.
bfe5132 - Tab-switch flash is gone. Two independent causes: (a) tab
views were created without an explicit background color, so the first
frame after setVisible(true) showed whatever was underneath the view
until the page painted; a solid theme-tracking ground fills the gap.
(b) setActive iterated tabs in list order, so if the outgoing tab
came before the incoming in the array, the loop hid the outgoing
first and left one frame where no tab was visible; the incoming is
now shown before any hides.
a5a667d - Screenshot toolbar-menu captures no longer come out blank.
The click handler dispatched capture synchronously while the native
Menu.popup window was still on top, marking the tab view occluded and
letting WebContents.capturePage() snapshot a stale/empty compositor
frame at the correct dimensions (which the existing 0x0 retry
couldn't detect). Dispatch now runs from the popup's close callback
after a 120ms settle so the parent window is foreground and the
compositor is live at capture time.
a5a667d also - Ariadne — Install / Update / Uninstall alongside Turn
on / off. The Ariadne toggle card in Settings > Registries grows
three lifecycle actions. Install and Update run the bundled
AriadneResolver-Setup-<ver>.exe silently and elevated (/VERYSILENT
/SUPPRESSMSGBOXES /NORESTART — one UAC prompt, no wizard); Update is
only visible when the bundled version is newer than what's installed.
Uninstall reads Inno's QuietUninstallString from HKLM registry and
runs it elevated. Status surfaces installed version + bundled version
so the user can see what's on disk vs what would land next; buttons
disable during work and refresh after both success and failure so the
UI never lies.
Deployed. Verified LIVE 0.3.18.
2026-09-07 23:50:52 +02:00
|
|
|
"@bitcoinerlab/secp256k1": "^1.2.0",
|
2026-09-27 19:55:43 +02:00
|
|
|
"@duckduckgo/autoconsent": "^16.42.0",
|
2026-09-27 19:43:14 +02:00
|
|
|
"@ghostery/adblocker": "^2.18.2",
|
2026-09-06 02:57:11 +02:00
|
|
|
"@noble/curves": "^2.0.1",
|
|
|
|
|
"@noble/hashes": "^2.0.1",
|
|
|
|
|
"@scure/bip32": "^2.0.1",
|
0.3.38: brand-green scrollbars everywhere + captureTab widens the viewport when sidebar shrinks the tab
Two changes shipped together (main.js touched by both this session and a
parallel session in different regions):
Scrollbars — from the "empty white space should be grey, thumb should
be Bitcoin Cash green" ask:
* new SCROLLBAR_CSS constant + styleScrollbars(wc) helper injects the
theme on every dom-ready
* thumb #0AC18E (BCH primary), track rgba(120,130,150,0.18) subtle
neutral grey so it works on both dark and light surfaces without
hardcoding either; 6px radius, 2px inset via background-clip:padding-box
* modern scrollbar-color on <html> for Chromium 121+; ::-webkit- rules
with !important as the fallback / override for sites that theme
their own scrollbars — scrollbar-width intentionally left alone so
a page that hides scrollbars entirely keeps that behaviour
* hooked into every wc we own: createTab, chrome, popover, enginePicker,
downloadsPop, addressPicker, pwFillPop, linkStatus, sidebar (so every
add-on panel like Aegis picks it up), approvalPop
* fires once immediately if the wc is already past dom-ready when we
attach — fixed views load fast during startup, we'd otherwise miss
captureTab full-page — from the parallel session's screenshot work:
* before Page.captureScreenshot with captureBeyondViewport we now
override Emulation.setDeviceMetricsOverride to the window's full
content width so an open sidebar (or other on-screen chrome that
narrowed the tab view) doesn't clip the shot — capture comes back at
the page's natural full width, not the visible width
* attach the debugger for the call if it isn't attached, detach on
return; clear the metrics override in finally so the tab returns to
its normal layout regardless of success
2026-09-09 00:42:38 +02:00
|
|
|
"@wizardconnect/core": "^0.2.4",
|
|
|
|
|
"@wizardconnect/wallet": "^0.2.3",
|
Ship Theseus 0.3.18 b751b5de (add-on updates land + signed endpoint + tab-flash + screenshot fix + Ariadne installer)
Setup b751b5deea997bb7e0e894104dcb7411358728987196cb610f316edacaf9be54
Portable 8a258f29c62a03b745e93ea0265285e6d5df38d4f25cdbdadc20b4d2a54b97d7
Five theseus fixes since 0.3.16:
e90062a - Bundled add-on updates now actually land. seedBundledAddons()
previously copied a bundled add-on only when its target folder was
missing, so the 0.3.14 screenshot editor never reached machines that
already had an older screenshot/ folder from a previous run — Theseus
quietly kept using the stale copy. The seeder now compares bundled and
on-disk addon.json versions and reseeds with a timestamped backup
under <userData>/addons-backups/<id>-<oldver>-<timestamp>/.
ecfd481 + 6117429 - Signed add-on update endpoint, à la Firefox XPI.
An add-on can now advertise an updateURL in its addon.json and be
republished at any time without waiting for a Theseus release. The
client fetches, verifies an Ed25519 signature over
"silentmode.addon-update-v1|<id>|<version>|<tarball-sha256>",
downloads the tarball, verifies the hash, and stages the new copy
under <userData>/addons-updates-staged/ for promotion on next launch.
Dormant in this build — the shipped addon-update-pubkeys.js is empty,
so checkAndStageUpdates() short-circuits and makes no outbound
requests; the feature activates when an operator ceremonies a key in
and ships a follow-up release with the pubkey baked in. Operator
tooling in scripts/generate-update-keypair.mjs and
scripts/sign-addon-update.mjs; full brief in docs/ADDON-UPDATES.md.
End-to-end verified against a local HTTP server: sign, serve, fetch,
verify, download, extract, stage, promote, backup — plus signature
tamper, wrong pubkey, sha256 tamper, and empty-pubkey short-circuit
all rejected as expected. 15/15 checks pass.
bfe5132 - Tab-switch flash is gone. Two independent causes: (a) tab
views were created without an explicit background color, so the first
frame after setVisible(true) showed whatever was underneath the view
until the page painted; a solid theme-tracking ground fills the gap.
(b) setActive iterated tabs in list order, so if the outgoing tab
came before the incoming in the array, the loop hid the outgoing
first and left one frame where no tab was visible; the incoming is
now shown before any hides.
a5a667d - Screenshot toolbar-menu captures no longer come out blank.
The click handler dispatched capture synchronously while the native
Menu.popup window was still on top, marking the tab view occluded and
letting WebContents.capturePage() snapshot a stale/empty compositor
frame at the correct dimensions (which the existing 0x0 retry
couldn't detect). Dispatch now runs from the popup's close callback
after a 120ms settle so the parent window is foreground and the
compositor is live at capture time.
a5a667d also - Ariadne — Install / Update / Uninstall alongside Turn
on / off. The Ariadne toggle card in Settings > Registries grows
three lifecycle actions. Install and Update run the bundled
AriadneResolver-Setup-<ver>.exe silently and elevated (/VERYSILENT
/SUPPRESSMSGBOXES /NORESTART — one UAC prompt, no wizard); Update is
only visible when the bundled version is newer than what's installed.
Uninstall reads Inno's QuietUninstallString from HKLM registry and
runs it elevated. Status surfaces installed version + bundled version
so the user can see what's on disk vs what would land next; buttons
disable during work and refresh after both success and failure so the
UI never lies.
Deployed. Verified LIVE 0.3.18.
2026-09-07 23:50:52 +02:00
|
|
|
"bip32": "^4.0.0",
|
|
|
|
|
"bip39": "^3.1.0",
|
|
|
|
|
"bitcoinjs-lib": "^6.1.7",
|
|
|
|
|
"ecpair": "^2.1.0",
|
0.3.38: brand-green scrollbars everywhere + captureTab widens the viewport when sidebar shrinks the tab
Two changes shipped together (main.js touched by both this session and a
parallel session in different regions):
Scrollbars — from the "empty white space should be grey, thumb should
be Bitcoin Cash green" ask:
* new SCROLLBAR_CSS constant + styleScrollbars(wc) helper injects the
theme on every dom-ready
* thumb #0AC18E (BCH primary), track rgba(120,130,150,0.18) subtle
neutral grey so it works on both dark and light surfaces without
hardcoding either; 6px radius, 2px inset via background-clip:padding-box
* modern scrollbar-color on <html> for Chromium 121+; ::-webkit- rules
with !important as the fallback / override for sites that theme
their own scrollbars — scrollbar-width intentionally left alone so
a page that hides scrollbars entirely keeps that behaviour
* hooked into every wc we own: createTab, chrome, popover, enginePicker,
downloadsPop, addressPicker, pwFillPop, linkStatus, sidebar (so every
add-on panel like Aegis picks it up), approvalPop
* fires once immediately if the wc is already past dom-ready when we
attach — fixed views load fast during startup, we'd otherwise miss
captureTab full-page — from the parallel session's screenshot work:
* before Page.captureScreenshot with captureBeyondViewport we now
override Emulation.setDeviceMetricsOverride to the window's full
content width so an open sidebar (or other on-screen chrome that
narrowed the tab view) doesn't clip the shot — capture comes back at
the page's natural full width, not the visible width
* attach the debugger for the call if it isn't attached, detach on
return; clear the metrics override in finally so the tab returns to
its normal layout regardless of success
2026-09-09 00:42:38 +02:00
|
|
|
"eventemitter3": "^5.0.1",
|
2026-07-29 13:54:34 +02:00
|
|
|
"fetch-socks": "^1.3.3",
|
0.3.38: brand-green scrollbars everywhere + captureTab widens the viewport when sidebar shrinks the tab
Two changes shipped together (main.js touched by both this session and a
parallel session in different regions):
Scrollbars — from the "empty white space should be grey, thumb should
be Bitcoin Cash green" ask:
* new SCROLLBAR_CSS constant + styleScrollbars(wc) helper injects the
theme on every dom-ready
* thumb #0AC18E (BCH primary), track rgba(120,130,150,0.18) subtle
neutral grey so it works on both dark and light surfaces without
hardcoding either; 6px radius, 2px inset via background-clip:padding-box
* modern scrollbar-color on <html> for Chromium 121+; ::-webkit- rules
with !important as the fallback / override for sites that theme
their own scrollbars — scrollbar-width intentionally left alone so
a page that hides scrollbars entirely keeps that behaviour
* hooked into every wc we own: createTab, chrome, popover, enginePicker,
downloadsPop, addressPicker, pwFillPop, linkStatus, sidebar (so every
add-on panel like Aegis picks it up), approvalPop
* fires once immediately if the wc is already past dom-ready when we
attach — fixed views load fast during startup, we'd otherwise miss
captureTab full-page — from the parallel session's screenshot work:
* before Page.captureScreenshot with captureBeyondViewport we now
override Emulation.setDeviceMetricsOverride to the window's full
content width so an open sidebar (or other on-screen chrome that
narrowed the tab view) doesn't clip the shot — capture comes back at
the page's natural full width, not the visible width
* attach the debugger for the call if it isn't attached, detach on
return; clear the metrics override in finally so the tab returns to
its normal layout regardless of success
2026-09-09 00:42:38 +02:00
|
|
|
"isomorphic-ws": "^5.0.0",
|
|
|
|
|
"lossless-json": "^4.0.2",
|
Hermes: wire NIP-17 messaging into Theseus, provision chipnet hermes.bch
- 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
2026-08-18 20:14:43 +02:00
|
|
|
"nostr-tools": "^2.10.4",
|
Ship Theseus 0.0.8: window.bcnr dApp API + eTLD+1 permission origins
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
2026-08-31 01:38:55 +02:00
|
|
|
"psl": "^1.15.0",
|
2026-07-29 13:54:34 +02:00
|
|
|
"socks-proxy-agent": "^10.1.0",
|
|
|
|
|
"ws": "^8.18.0"
|
|
|
|
|
},
|
|
|
|
|
"devDependencies": {
|
2026-09-20 14:19:20 +02:00
|
|
|
"electron": "^44.4.3",
|
2026-07-29 13:54:34 +02:00
|
|
|
"electron-builder": "^25.1.8"
|
|
|
|
|
},
|
|
|
|
|
"build": {
|
|
|
|
|
"appId": "st.silentmode.theseus",
|
|
|
|
|
"productName": "Theseus Navigator",
|
|
|
|
|
"artifactName": "TheseusNavigator-${version}-${arch}.${ext}",
|
2026-10-02 22:15:14 +02:00
|
|
|
"extraMetadata": {
|
|
|
|
|
"description": "Theseus Navigator"
|
|
|
|
|
},
|
Ship Theseus 0.0.8: window.bcnr dApp API + eTLD+1 permission origins
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
2026-08-31 01:38:55 +02:00
|
|
|
"directories": {
|
|
|
|
|
"output": "dist-public"
|
|
|
|
|
},
|
2026-07-29 13:54:34 +02:00
|
|
|
"asar": true,
|
|
|
|
|
"files": [
|
2026-09-29 00:18:00 +02:00
|
|
|
"THIRD-PARTY-NOTICES.md",
|
|
|
|
|
"LICENSE",
|
2026-07-29 13:54:34 +02:00
|
|
|
"main.js",
|
Theseus: BNS index in its own process; a name never waits for the download
The snapshot parse, index builds, electrum sync and snapshot refresh ran on
the browser's main thread at launch. They now run in bns-indexer.js, a
utilityProcess, in two phases: the local snapshot first (no network), then
— once the first page has loaded — the published snapshot (one download)
and the electrum poll. Main keeps a mirror of the name map for its
synchronous lookups; tabs no longer wait for the index to restore.
With no local index yet, a name under a known BCNR TLD gets one lookup of
just that name on the gateway and opens; the full snapshot and the electrum
check follow in the background, and every quick answer is compared with the
verified index when it lands (a mismatch reloads the affected tabs). Plain
web hosts are never sent to the gateway, and the extension-publisher check
only accepts verified data.
DESIGN-bns-indexer-service.md: Ariadne's Thread as the owner of the one
shared indexer (scope x mode, launch at start, power, and a resolver that
never depends on the indexer).
2026-10-03 13:08:28 +02:00
|
|
|
"bns-indexer.js",
|
2026-07-29 13:54:34 +02:00
|
|
|
"preload.js",
|
|
|
|
|
"chrome.html",
|
|
|
|
|
"home.html",
|
|
|
|
|
"settings.html",
|
|
|
|
|
"settings-preload.js",
|
2026-08-02 01:19:34 +02:00
|
|
|
"popover.html",
|
|
|
|
|
"popover-preload.js",
|
|
|
|
|
"engine-picker.html",
|
|
|
|
|
"engine-picker-preload.js",
|
Theseus: language picker is a floating overlay now, not a native menu
The globe-chip menu was a native Electron menu — square corners, system
font, no theming beyond the OS's own context-menu paint. Replaces it with
a floating overlay WebContentsView (lang-picker.html + preload),
following the same pattern the engine picker and the popover already
use: rounded 12px surface, acid-tint accents on the current pin, soft
shadow, dark + light scheme, flush under the chip's bottom-right.
The content is organised around the user's intent — translate first,
pick a language second. The "Translate this page" row sits at the top
when it is actionable (web tab + supported source + supported target),
with the detected source and the target under the label so the user can
tell what the backend will do before they click. Once a page is
translated, that row flips to "Show original (<source>)". Below the
action strip is Automatic + the six supported languages, each with a
two-letter code chip in the left slot and a ✓ on the current pin.
Unsupported languages are hidden by default inside a collapsible "More
languages (translator coming later)" group — click to expand, click to
collapse; a pinned-unsupported auto-expands so its ✓ stays visible.
Plumbing matches engine-picker: deferred-load WebContentsView,
closeOnClickAway, setBounds anchored under the chip, picker renderer
reports its own content height after each render so the overlay
contracts and expands with the "More languages" toggle. State pushes
come from emitTranslateState (so the Translate / Show-original row
updates when a page finishes auto-translating with the picker open)
and from broadcastSettings (so a Settings-side language change
re-paints the ✓).
Verified end-to-end: picker loads, shows Automatic + 6 supported in the
default list and 18 greyed in the "More" group, repaints to "⟲ Show
original (Spanish)" after an auto-translate completes.
2026-10-03 21:33:16 +02:00
|
|
|
"lang-picker.html",
|
|
|
|
|
"lang-picker-preload.js",
|
2026-08-02 11:39:00 +02:00
|
|
|
"downloads.html",
|
|
|
|
|
"downloads-preload.js",
|
Theseus UX batch: tabs, address history, password autofill MVP, home cards
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.
2026-08-17 02:17:12 +02:00
|
|
|
"address-picker.html",
|
|
|
|
|
"address-picker-preload.js",
|
|
|
|
|
"pw-fill.html",
|
|
|
|
|
"pw-fill-preload.js",
|
|
|
|
|
"home-preload.js",
|
Theseus 0.1.3: branded error page for load failures (BUILT, NOT DEPLOYED)
Setup f2afc14efc63008cbb9dad44176e94146386db4c0afda4459f1d4eb929172b6d
Portable 5d08b1415526934db8de780949a610896064fe9567aa0e5e1702ebabd7eb7df2
Chromium's default 'This site can't be reached' replaced with a Theseus-
themed error page. did-fail-load on every tab's webContents (main frame
only, non-ignorable code) routes the tab to error.html with the
attempt URL, host, error code, and description as query params. The
page keeps t.url pointing at the failed URL so the address bar shows
what the user typed and they can edit + retry - refreshTabUrl's
existing file:// skip means the error page's own path never leaks
back into the bar.
Five kinds, chosen by pickErrorKind(code, host):
name-not-registered BCNR-eligible host + ERR_NAME_NOT_RESOLVED.
Says "no BCDN record on chain, no clearnet host
either." Offers Register on Sirius + Search +
Retry + Home.
name-unreachable ERR_NAME_NOT_RESOLVED on a non-BCNR host. DNS
failed - offers Retry + Search + Register +
Home.
unreachable CONN_REFUSED/RESET/TIMED_OUT/CLOSED/NETWORK_CHANGED.
Offers Retry + Tor guide + Home.
tls ERR_CERT_* range (-200..-299). Offers Retry +
Home.
generic Everything else.
home-preload.js gains `window.errorpage` alongside `window.home`. Both
APIs are sender-URL-gated in main - a random page seeing the shape
can't invoke them (isErrorPageSender / isHomePageSender). The external-
open handler additionally allowlists Silent Mode domains only.
package.json build.files gets error.html + error-preload.js so
electron-builder actually bundles them (GOTCHAS rule: an unlisted
runtime-loaded file silently opens blank).
Ship pages (releases-manifest.json, tools/index.html, releases/index.html,
site-theseus-x/index.html) updated to 0.1.3 with the new hashes.
DEPLOY STATUS - blocked on VPS SSH: my IP was hit with a full-port ban
mid-turn (likely fail2ban from the burst of scp during the 0.1.0-0.1.2
iterations). Site pages/manifest/installers are committed locally but
NOT yet on dl.silentmode.st or the Sia mirror. Live still reads 0.1.2.
User needs to unban 195.184.247.106 on their end, or wait for the ban
to expire, before the ship pages match reality.
2026-08-31 13:38:05 +02:00
|
|
|
"error.html",
|
|
|
|
|
"error-preload.js",
|
Theseus: add-on framework MVP + Notepad reference add-on
New subsystem for extending Theseus with folders on disk. Each add-on
lives at <userData>/addons/<id>/ with an addon.json manifest and a
CommonJS entry that exports activate(api). Nothing about a private
add-on ships in the public installer - drop the folder, restart, it's
live. Bundled reference add-ons ride in the packaged app under
resources/bundled-addons/ and are seeded into <userData>/addons/ on
first boot; the framework treats seeded and drop-in add-ons the same.
Files:
- addons-host.js Loader + api.registerSidebarPanel() + per-
addon storage on <userData>/addons-data/.
Kept at the CommonJS-scoped top level (lib/
is ESM-scoped via its own package.json).
- sidebar-preload.js Runs in every sidebar panel. Exposes
window.silentmode.storage.{get,set,all} +
onVisibility. Main-side handlers derive the
add-on id from the sender file:// URL, so a
panel can only touch its own store.
- bundled-addons/notepad/ Reference add-on: addon.json, index.js,
note.html. Autosaving textarea with char /
word count.
main.js:
- Extension point: sidebar-panel. One right-anchored WebContentsView
(SIDEBAR_W=340) hosts the current panel; layout() shrinks the tab
views by the sidebar width when visible. First registered panel
wins for MVP; picker for multiple panels lands later.
- initAddons() at app.whenReady(): seedBundledAddons, then
AddonHost.discoverAndActivate.
- IPC surface: sidebar-toggle / sidebar-open / sidebar-close /
sidebar-state, addons-list / addons-set-enabled / addons-reveal /
addons-open-dir / addons-reload, and origin-gated
addon-storage-get/set/all.
- Settings gains `disabledAddons: []` — off-toggled ids persist and
the loader honours them without a restart (discoverAndActivate
runs again on toggle).
chrome.html: toolbar sidebar-toggle button, hidden until at least one
add-on has registered a sidebar panel.
settings.html: new "Add-ons" section under privacy. Lists installed
add-ons with icon / name / version / description / capabilities;
per-add-on enable/disable toggle + Show folder button; page-level
Reload and Open add-ons folder buttons; warning note about the trust
model.
package.json: build.files gains sidebar-preload.js + addons-host.js.
extraResources gains bundled-addons/ so the packaged app carries the
reference notepad for the first-boot seed.
Verified: `npm start` boots, addons-host discovers the notepad,
activates it, registers one sidebar panel. Log confirms
"1 installed, 1 enabled, 1 sidebar panels". Actual sidebar rendering
+ notepad UI need clicked-through validation on a real install.
Not shipped yet - deploy still blocked on the fail2ban VPS SSH ban.
Ships as 0.2.0 once SSH clears (this is a new subsystem, not a fix).
2026-08-31 13:51:08 +02:00
|
|
|
"sidebar-preload.js",
|
feat(theseus/addons): vault-derive, page-inject and approval-modal capabilities
Three opt-in capabilities for add-ons, plus the plumbing they need:
- vault-derive: api.vault.derive("<id>/<path>") resolves once the password
vault is unlocked with a 32-byte HKDF child of the vault root under
"silentmode/addons/<path>". Path must start with the add-on id.
- page-inject: manifest "page-inject" {preload, origins}; a session-wide
preload asks main (sync, against the committed URL) which add-on bridges
apply and runs them in the isolated world with a scoped `theseus` object.
- approval-modal: api.approvalModal({title, body, origin, rows, actions,
checkbox}) shows a consent overlay over the tab area (approval.html);
resolves to the picked action id, "cancel", or "<id>+<checkbox>".
- api.onMessage/emit + window.silentmode.invoke/on for panel <-> activate()
messaging; page bridges use addon-page-msg, gated by tab + origin match.
- api.require so add-ons can share Theseus's dependency tree.
2026-09-06 02:33:26 +02:00
|
|
|
"approval-preload.js",
|
|
|
|
|
"approval.html",
|
Theseus: quick-unlock PIN for the vault, shared with extensions
The vault re-locks on every restart and only the master password opened
it, so every extension that needs it (Aegis, now Pithos) either asked for
the master password itself or grew its own PIN. Theseus now owns one:
- Settings > Passwords sets, changes or removes a 6-digit PIN. The PIN
wraps the master password (PBKDF2-SHA256, 600k iterations, AES-256-GCM)
and the result is sealed with the OS keystore (safeStorage: DPAPI /
Keychain / libsecret), so a copied vault-pin.json cannot be brute-forced
elsewhere. Every unlock still ends at the master password.
- Three wrong PINs in a row require the master password. The strike count
lives in the same file, so a restart does not reset it; a successful
master-password unlock does. A PIN whose password no longer opens the
vault (password changed) is dropped.
- unlock.html is Theseus's own prompt, over the whole window: PIN pad, or
the master password. Extensions call api.vault.requestUnlock({ reason })
(vault-derive capability) and get { ok } back; what the user typed never
reaches them. Settings' locked screen offers "Unlock with PIN" through
the same prompt.
2026-10-03 20:33:26 +02:00
|
|
|
"unlock.html",
|
|
|
|
|
"unlock-preload.js",
|
Theseus ID in Theseus: window.theseusId.signIn and Settings › Theseus ID
Pages of Silent Mode projects can now sign the user in with their Theseus
ID instead of a wallet phrase typed into the page. Theseus writes the
sign-in message itself, takes the origin from the committed top frame, and
signs as a project only on an origin that project's list includes, so a
phishing page cannot get another project's signature and no page can use
the ID key to sign anything else.
- lib/theseus-id.cjs: the policy (first sign-in always asks and lets the
user pick a private or One ID; Silent Mode projects are silent after
that while the vault is open; per-site "always"; 10 silent signatures per
minute per origin), the per-project record encrypted under a key derived
from the vault, origin-list fetching with a 1 h cache and a 7-day stale
fallback, and ID moves that send a proof signed by both keys and only
finish once the project confirms.
- A locked vault is unlocked only for a page the user just clicked or typed
in: navigator.userActivation alone is true on load for pages opened with
loadURL, which would let a page pop the vault prompt by itself.
- Settings › Theseus ID: default mode, One ID, automatic sign-in toggle,
signed-in projects (always, change ID, new ID, revoke) and a recovery key
behind a fresh PIN / password check.
- TheseusID/registry/projects.json is the first-party list (Hephaestus,
Sirius, Pithos); it and TheseusID/lib ship as extraResources.
- Token-aware cashaddrs (BNS owners) now decode for owner-signed lists.
Verified on a scratch profile against a local test project whose server
checks signatures with TheseusID/lib/verify.mjs: locked vault on load gives
"locked" with no prompt, first sign-in prompt, silent second sign-in, a
claimed foreign project refused without a prompt, an ID move that keeps the
project's account, and the recovery key behind the confirm prompt.
2026-10-04 20:48:07 +02:00
|
|
|
"theseus-id-preload.js",
|
2026-09-15 22:30:29 +02:00
|
|
|
"auth-prompt-preload.js",
|
|
|
|
|
"auth-prompt.html",
|
feat(theseus/addons): vault-derive, page-inject and approval-modal capabilities
Three opt-in capabilities for add-ons, plus the plumbing they need:
- vault-derive: api.vault.derive("<id>/<path>") resolves once the password
vault is unlocked with a 32-byte HKDF child of the vault root under
"silentmode/addons/<path>". Path must start with the add-on id.
- page-inject: manifest "page-inject" {preload, origins}; a session-wide
preload asks main (sync, against the committed URL) which add-on bridges
apply and runs them in the isolated world with a scoped `theseus` object.
- approval-modal: api.approvalModal({title, body, origin, rows, actions,
checkbox}) shows a consent overlay over the tab area (approval.html);
resolves to the picked action id, "cancel", or "<id>+<checkbox>".
- api.onMessage/emit + window.silentmode.invoke/on for panel <-> activate()
messaging; page bridges use addon-page-msg, gated by tab + origin match.
- api.require so add-ons can share Theseus's dependency tree.
2026-09-06 02:33:26 +02:00
|
|
|
"addon-inject-preload.js",
|
2026-09-08 12:30:21 +02:00
|
|
|
"addon-tab-preload.js",
|
Theseus: add-on framework MVP + Notepad reference add-on
New subsystem for extending Theseus with folders on disk. Each add-on
lives at <userData>/addons/<id>/ with an addon.json manifest and a
CommonJS entry that exports activate(api). Nothing about a private
add-on ships in the public installer - drop the folder, restart, it's
live. Bundled reference add-ons ride in the packaged app under
resources/bundled-addons/ and are seeded into <userData>/addons/ on
first boot; the framework treats seeded and drop-in add-ons the same.
Files:
- addons-host.js Loader + api.registerSidebarPanel() + per-
addon storage on <userData>/addons-data/.
Kept at the CommonJS-scoped top level (lib/
is ESM-scoped via its own package.json).
- sidebar-preload.js Runs in every sidebar panel. Exposes
window.silentmode.storage.{get,set,all} +
onVisibility. Main-side handlers derive the
add-on id from the sender file:// URL, so a
panel can only touch its own store.
- bundled-addons/notepad/ Reference add-on: addon.json, index.js,
note.html. Autosaving textarea with char /
word count.
main.js:
- Extension point: sidebar-panel. One right-anchored WebContentsView
(SIDEBAR_W=340) hosts the current panel; layout() shrinks the tab
views by the sidebar width when visible. First registered panel
wins for MVP; picker for multiple panels lands later.
- initAddons() at app.whenReady(): seedBundledAddons, then
AddonHost.discoverAndActivate.
- IPC surface: sidebar-toggle / sidebar-open / sidebar-close /
sidebar-state, addons-list / addons-set-enabled / addons-reveal /
addons-open-dir / addons-reload, and origin-gated
addon-storage-get/set/all.
- Settings gains `disabledAddons: []` — off-toggled ids persist and
the loader honours them without a restart (discoverAndActivate
runs again on toggle).
chrome.html: toolbar sidebar-toggle button, hidden until at least one
add-on has registered a sidebar panel.
settings.html: new "Add-ons" section under privacy. Lists installed
add-ons with icon / name / version / description / capabilities;
per-add-on enable/disable toggle + Show folder button; page-level
Reload and Open add-ons folder buttons; warning note about the trust
model.
package.json: build.files gains sidebar-preload.js + addons-host.js.
extraResources gains bundled-addons/ so the packaged app carries the
reference notepad for the first-boot seed.
Verified: `npm start` boots, addons-host discovers the notepad,
activates it, registers one sidebar panel. Log confirms
"1 installed, 1 enabled, 1 sidebar panels". Actual sidebar rendering
+ notepad UI need clicked-through validation on a real install.
Not shipped yet - deploy still blocked on the fail2ban VPS SSH ban.
Ships as 0.2.0 once SSH clears (this is a new subsystem, not a fix).
2026-08-31 13:51:08 +02:00
|
|
|
"addons-host.js",
|
feat(theseus/addons): signed add-on update endpoint, à la Firefox XPI
Decouples bundled-add-on updates from Theseus releases. An add-on
whose addon.json declares an updateURL can be republished at any time
without shipping a new Theseus installer; existing installs pick it up
on the next boot's +30 s background check.
Client flow (main-process only, no UI touchpoints in this commit):
initAddons()
├── promoteStagedUpdates() # promote signed stage if newer
├── seedBundledAddons() # bundle wins over on-disk if newer
└── AddonHost.discoverAndActivate()
30 s later:
└── checkAndStageUpdates() # fetch, verify, download, stage
Signature: Ed25519 over
"silentmode.addon-update-v1|<id>|<version>|<tarball-sha256>",
verified against a hardcoded set of operator pubkeys living in
addon-update-pubkeys.js. Domain-separated so the operator key can't
be tricked into signing a message with a different purpose. Empty
pubkey array is the shipping default — checkAndStageUpdates() then
short-circuits and no outbound requests are made, which is the safe
posture until the operator ceremonies a key in.
Payload: gzipped tar, extracted with the system tar (present on
Win10 1803+, macOS, Linux). Path traversal defended by tar's default
refusal of `..` entries; the extracted manifest's id + version are
re-checked against the signed values before staging.
Staged updates go to <userData>/addons-updates-staged/<id>-<version>/.
Promotion into <userData>/addons/<id>/ reuses seedBundledAddons's
backup dance: existing folder moves to
<userData>/addons-backups/<id>-<oldver>-<timestamp>/ so any local
edits survive.
New files:
- addon-updater.js — client
- addon-update-pubkeys.js — hardcoded pubkeys (empty; edit + rebuild to rotate)
- scripts/generate-update-keypair.mjs — one-time keygen
- scripts/sign-addon-update.mjs — operator packager+signer
- docs/ADDON-UPDATES.md — operator brief + threat model
Wired into main.js at boot; screenshot add-on's addon.json advertises
the reference updateURL for when the endpoint goes live.
2026-09-07 21:58:30 +02:00
|
|
|
"addon-updater.js",
|
|
|
|
|
"addon-update-pubkeys.js",
|
2026-08-29 15:49:30 +02:00
|
|
|
"link-status.html",
|
|
|
|
|
"link-status-preload.js",
|
2026-08-02 01:19:34 +02:00
|
|
|
"collision.html",
|
Theseus: warn before opening a name a blocklist flags
The blocklist consumer existed in the resolver library and the gateway, but
the browser opened a flagged name without comment. Now the indexer process
reads the subscribed lists from the chain every ten minutes and hands the
flags to main. A flagged name loads a warning page naming the reason, the
list and the report; the user may continue, and that is remembered per name.
Two gates, because content is reached two ways. loadBns shows the real
interstitial. serveBns refuses with an inline page on every path that skips
it: reload, back and forward, bns:// links, web app windows. The inline page
has no button, since a page at the site's own origin must not be able to
approve itself; only blocked.html may ask to continue, checked by file URL.
Settings › Naming has the policy: warn (default), never open, or ignore the
lists. The csam reason is never offered a way through. A list that cannot be
read keeps the last known flags and never stops a name from resolving.
The gateway put its own warning in front of flagged sites, which this
browser could not get past: it fetches files itself, with no cookie jar. It
now sends x-bns-policy: client and the gateway stays out of the way for a
client that says it decides for itself.
dev/blocklist-selftest.js runs the real protocol handler and decision
functions against a scratch profile.
2026-10-04 15:50:35 +02:00
|
|
|
"blocked.html",
|
2026-08-02 01:19:34 +02:00
|
|
|
"collision-preload.js",
|
Hermes: wire NIP-17 messaging into Theseus, provision chipnet hermes.bch
- 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
2026-08-18 20:14:43 +02:00
|
|
|
"messages.html",
|
|
|
|
|
"messages-preload.js",
|
Ship Theseus 0.0.8: window.bcnr dApp API + eTLD+1 permission origins
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
2026-08-31 01:38:55 +02:00
|
|
|
"bcnr-preload.js",
|
|
|
|
|
"bcnr-origin.js",
|
2026-09-27 11:33:58 +02:00
|
|
|
"webapps.js",
|
feat(theseus): page dialogs drawn by Theseus instead of Chromium's stock boxes
alert / confirm / prompt from a page came up as bare OS message boxes
titled "theseus-navigator" (the package name), with no hint of who was
asking and nothing of the browser's styling — the PDF Editor's "Delete
signature?" was the reported case.
The session preload replaces the page's three functions with wrappers
that hand the call to the isolated world through a DOM event, which
asks main synchronously and writes the answer back; pages see Chrome's
return values (confirm → boolean, prompt → string or null) and no new
global. Main answers from a sheet hanging under the toolbar, in the
same surface as add-on approvals, that names who is asking: the site's
host, the add-on's name for an add-on page or panel (identified by its
path under the profile's extensions directory), or Theseus for its own
pages. The sheet belongs to the tab that asked — hidden while another
tab is in front, back when its tab returns — and a closing tab or
window answers "cancel" so no renderer stays blocked. Windows without
the chrome (installed apps, plain windows) get a native box with a
proper title, and app.name now reads "Theseus Navigator" for whatever
else still shows one.
2026-09-27 17:53:21 +02:00
|
|
|
"js-dialog.html",
|
|
|
|
|
"js-dialog-preload.js",
|
2026-10-02 23:49:39 +02:00
|
|
|
"quicklinks.html",
|
|
|
|
|
"quicklinks-preload.js",
|
Theseus: the left panel resizes, and steps aside like Opera's
Web apps in the left panel were a fixed 380 px, too narrow for WhatsApp,
and add-on panels a fixed 400. A grip on the panel's right edge now
resizes it, each app keeps its own width (settings.leftPanelWidths), a
double-click resets it, and the page always keeps at least 320 px. The
grip is a small view of Theseus's own laid over the edge, since the panel
may be a third-party page; while dragging it covers the window so the drag
keeps its events.
Like Opera's sidebar, the left panel now hides when a new tab is opened or
the right sidebar opens. It is only hidden, so reopening lands where the
user left off.
Add-on panels on the left used to get the right sidebar's grip on their
left edge, where dragging resized the right sidebar; that grip is hidden
there and its drags are ignored.
2026-10-04 20:53:16 +02:00
|
|
|
"panel-grip-preload.js",
|
|
|
|
|
"panel-grip.html",
|
2026-09-28 19:47:21 +02:00
|
|
|
"engine-icons/**/*",
|
Hermes: wire NIP-17 messaging into Theseus, provision chipnet hermes.bch
- 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
2026-08-18 20:14:43 +02:00
|
|
|
"lib/**/*",
|
2026-07-29 13:54:34 +02:00
|
|
|
"package.json",
|
|
|
|
|
"node_modules/**/*",
|
|
|
|
|
"!**/*.md",
|
|
|
|
|
"!**/*.map",
|
|
|
|
|
"!tor${/*}",
|
|
|
|
|
"!dist-public${/*}",
|
|
|
|
|
"!resolve-test.mjs",
|
|
|
|
|
"!*PROMPT.md"
|
|
|
|
|
],
|
|
|
|
|
"extraResources": [
|
Ship Theseus 0.0.8: window.bcnr dApp API + eTLD+1 permission origins
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
2026-08-31 01:38:55 +02:00
|
|
|
{
|
|
|
|
|
"from": "tor",
|
|
|
|
|
"to": "tor"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"from": "../Argus/src/lib/resolver-web.js",
|
|
|
|
|
"to": "resolver-web.mjs"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"from": "../Argus/src/lib/password-vault.js",
|
|
|
|
|
"to": "password-vault.mjs"
|
|
|
|
|
},
|
Theseus ID in Theseus: window.theseusId.signIn and Settings › Theseus ID
Pages of Silent Mode projects can now sign the user in with their Theseus
ID instead of a wallet phrase typed into the page. Theseus writes the
sign-in message itself, takes the origin from the committed top frame, and
signs as a project only on an origin that project's list includes, so a
phishing page cannot get another project's signature and no page can use
the ID key to sign anything else.
- lib/theseus-id.cjs: the policy (first sign-in always asks and lets the
user pick a private or One ID; Silent Mode projects are silent after
that while the vault is open; per-site "always"; 10 silent signatures per
minute per origin), the per-project record encrypted under a key derived
from the vault, origin-list fetching with a 1 h cache and a 7-day stale
fallback, and ID moves that send a proof signed by both keys and only
finish once the project confirms.
- A locked vault is unlocked only for a page the user just clicked or typed
in: navigator.userActivation alone is true on load for pages opened with
loadURL, which would let a page pop the vault prompt by itself.
- Settings › Theseus ID: default mode, One ID, automatic sign-in toggle,
signed-in projects (always, change ID, new ID, revoke) and a recovery key
behind a fresh PIN / password check.
- TheseusID/registry/projects.json is the first-party list (Hephaestus,
Sirius, Pithos); it and TheseusID/lib ship as extraResources.
- Token-aware cashaddrs (BNS owners) now decode for owner-signed lists.
Verified on a scratch profile against a local test project whose server
checks signatures with TheseusID/lib/verify.mjs: locked vault on load gives
"locked" with no prompt, first sign-in prompt, silent second sign-in, a
claimed foreign project refused without a prompt, an ID move that keeps the
project's account, and the recovery key behind the confirm prompt.
2026-10-04 20:48:07 +02:00
|
|
|
{
|
|
|
|
|
"from": "../TheseusID/lib",
|
|
|
|
|
"to": "theseus-id"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"from": "../TheseusID/registry/projects.json",
|
|
|
|
|
"to": "theseus-id-projects.json"
|
|
|
|
|
},
|
Theseus: read BNS names from Ariadne's indexer; its own is the standby
Migration step 3 (DESIGN-bns-indexer-service.md). Ariadne's Thread now owns
BNS indexing on the machine, so Theseus no longer runs a second electrum
indexer beside it.
bns-indexer.js keeps its process and its messages to main.js, but inside
it is now an index host on the shared source chain:
- Ariadne's indexer over its pipe, trusted only after ariadne-helper.exe
has checked the server process on that connection (found through
Ariadne's uninstall key), then pushes;
- the local copies: Ariadne's files for both scopes, Theseus's own raw
copy, the bundled one. The richest wins.
- Theseus's own index copy, written from the pipe data.
The shared core runs as Theseus's own indexer only while Ariadne is
unhealthy. That means: no pipe 4 s after launch, a pipe that fails the
check, a pipe that went silent, or an index not confirmed for 10 min while
Ariadne is not paused. The own indexer warm-starts from Ariadne's
snapshot, so there is no download and no cold sync. It hands back after
90 s of health, so a flapping service does not start and stop it. Economy
is not a failure and never triggers a takeover. With no checkable Ariadne
(portable, not installed, older than the pipe) the own indexer starts at
once, as in 0.3.70. The one thing Theseus does on Ariadne's side is run
the indexer's task at launch when "Launch at start" is off.
main.js passes the shared module paths (packaged as .mjs, which is why the
shared modules no longer import each other) and keeps the host's status.
The Ariadne panel takes its state from the indexer task when one exists,
and the sub-page says where Theseus's names come from.
2026-10-03 17:06:24 +02:00
|
|
|
{
|
|
|
|
|
"from": "../Argus/src/lib/bns-index-core.js",
|
|
|
|
|
"to": "bns-index-core.mjs"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"from": "../Argus/src/lib/bns-source-chain.js",
|
|
|
|
|
"to": "bns-source-chain.mjs"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"from": "../Argus/src/lib/bns-pipe.js",
|
|
|
|
|
"to": "bns-pipe.mjs"
|
|
|
|
|
},
|
Ship Theseus 0.0.8: window.bcnr dApp API + eTLD+1 permission origins
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
2026-08-31 01:38:55 +02:00
|
|
|
{
|
|
|
|
|
"from": "lib/hermes.js",
|
|
|
|
|
"to": "lib/hermes.mjs"
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"from": "snapshots/bns-name-snapshot.json",
|
|
|
|
|
"to": "bns-name-snapshot.json"
|
Ship Theseus 0.1.0 510f81fd (bundle Ariadne's Thread)
Setup 510f81fd5e9b4287a55817aaf5080e5d46005eecb5359eb06892040cf8d10d87
Portable 96bfb469f2d9dfe11606aa10db92febdfce73df980eec475ab285f2334925158
Bundled AriadneResolver-Setup-0.1.0.exe (9ab725be, unchanged 0.1.0)
Version 0.0.9 -> 0.1.0 marks the "Silent Mode = one install" milestone:
Theseus and the system-wide Ariadne resolver now ship together.
nsis/installer.nsh (electron-builder `nsis.include`) hooks two macros:
customInstall -- If Ariadne's Thread is NOT already installed,
MessageBox MB_YESNO|MB_DEFBUTTON1 asks whether
to install it now. On Yes, chain-invokes the
bundled Inno installer with
/VERYSILENT /SUPPRESSMSGBOXES /NORESTART
(Ariadne raises its own UAC because Inno declares
PrivilegesRequired=admin). Ariadne being present
already suppresses the prompt on upgrades.
customUnInstall -- Reads Ariadne's UninstallString from HKLM 64-bit
Uninstall\{...ARIADNERSLVR}_is1. If present,
symmetric MessageBox asks whether to remove it
too, then ExecWaits the string with the same
silent flags. Skips silently if Ariadne isn't
installed.
Registry probe uses SetRegView 64 (Ariadne installs 64-bit per
ArchitecturesInstallIn64BitMode=x64compatible in its .iss). Reset to
`lastused` after each probe to leave electron-builder's own state
unchanged.
Package changes:
- version 0.0.9 -> 0.1.0
- build.extraResources adds build/AriadneResolver-Setup-0.1.0.exe
(unpacked to $INSTDIR/resources/); build/ stays gitignored - the
binary is regenerated by copying from AriadneResolver's Inno output
- build.nsis.include -> nsis/installer.nsh
Size: installer 122 MB (+25 MB for bundled Ariadne), portable 122 MB.
Portable also carries the Ariadne exe as a side effect of extraResources
being global; portable can't invoke an installer, so the 25 MB is dead
weight there - future rev could scope extraResources per-target.
Site updates: tools page + releases page + theseus.x landing all
reflect the 0.1.0 hashes, sizes, and the new "Ariadne's Thread bundled"
line. tools page's "Coming to the Windows installer" footnote is
rewritten past tense because it landed.
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 and ../site-theseus-x
- verified HEAD 200, manifest reports 0.1.0 2026-08-31, VPS hashes
match local
Existing 0.0.6 (or newer) installs will surface 0.1.0 in the update
chip on next launch.
2026-08-31 05:07:34 +02:00
|
|
|
},
|
Theseus: add-on framework MVP + Notepad reference add-on
New subsystem for extending Theseus with folders on disk. Each add-on
lives at <userData>/addons/<id>/ with an addon.json manifest and a
CommonJS entry that exports activate(api). Nothing about a private
add-on ships in the public installer - drop the folder, restart, it's
live. Bundled reference add-ons ride in the packaged app under
resources/bundled-addons/ and are seeded into <userData>/addons/ on
first boot; the framework treats seeded and drop-in add-ons the same.
Files:
- addons-host.js Loader + api.registerSidebarPanel() + per-
addon storage on <userData>/addons-data/.
Kept at the CommonJS-scoped top level (lib/
is ESM-scoped via its own package.json).
- sidebar-preload.js Runs in every sidebar panel. Exposes
window.silentmode.storage.{get,set,all} +
onVisibility. Main-side handlers derive the
add-on id from the sender file:// URL, so a
panel can only touch its own store.
- bundled-addons/notepad/ Reference add-on: addon.json, index.js,
note.html. Autosaving textarea with char /
word count.
main.js:
- Extension point: sidebar-panel. One right-anchored WebContentsView
(SIDEBAR_W=340) hosts the current panel; layout() shrinks the tab
views by the sidebar width when visible. First registered panel
wins for MVP; picker for multiple panels lands later.
- initAddons() at app.whenReady(): seedBundledAddons, then
AddonHost.discoverAndActivate.
- IPC surface: sidebar-toggle / sidebar-open / sidebar-close /
sidebar-state, addons-list / addons-set-enabled / addons-reveal /
addons-open-dir / addons-reload, and origin-gated
addon-storage-get/set/all.
- Settings gains `disabledAddons: []` — off-toggled ids persist and
the loader honours them without a restart (discoverAndActivate
runs again on toggle).
chrome.html: toolbar sidebar-toggle button, hidden until at least one
add-on has registered a sidebar panel.
settings.html: new "Add-ons" section under privacy. Lists installed
add-ons with icon / name / version / description / capabilities;
per-add-on enable/disable toggle + Show folder button; page-level
Reload and Open add-ons folder buttons; warning note about the trust
model.
package.json: build.files gains sidebar-preload.js + addons-host.js.
extraResources gains bundled-addons/ so the packaged app carries the
reference notepad for the first-boot seed.
Verified: `npm start` boots, addons-host discovers the notepad,
activates it, registers one sidebar panel. Log confirms
"1 installed, 1 enabled, 1 sidebar panels". Actual sidebar rendering
+ notepad UI need clicked-through validation on a real install.
Not shipped yet - deploy still blocked on the fail2ban VPS SSH ban.
Ships as 0.2.0 once SSH clears (this is a new subsystem, not a fix).
2026-08-31 13:51:08 +02:00
|
|
|
{
|
|
|
|
|
"from": "bundled-addons",
|
|
|
|
|
"to": "bundled-addons"
|
2026-08-31 16:32:16 +02:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"from": "build/icon.ico",
|
|
|
|
|
"to": "icon.ico"
|
Ship Theseus 0.0.8: window.bcnr dApp API + eTLD+1 permission origins
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
2026-08-31 01:38:55 +02:00
|
|
|
}
|
2026-07-29 13:54:34 +02:00
|
|
|
],
|
Ship Theseus 0.0.8: window.bcnr dApp API + eTLD+1 permission origins
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
2026-08-31 01:38:55 +02:00
|
|
|
"win": {
|
2026-08-31 16:32:16 +02:00
|
|
|
"icon": "build/icon.ico",
|
Ship Theseus 0.0.8: window.bcnr dApp API + eTLD+1 permission origins
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
2026-08-31 01:38:55 +02:00
|
|
|
"target": [
|
|
|
|
|
"nsis",
|
|
|
|
|
"portable"
|
|
|
|
|
]
|
|
|
|
|
},
|
2026-07-29 13:54:34 +02:00
|
|
|
"nsis": {
|
|
|
|
|
"oneClick": false,
|
|
|
|
|
"perMachine": false,
|
|
|
|
|
"allowToChangeInstallationDirectory": true,
|
Ship Theseus 0.1.0 510f81fd (bundle Ariadne's Thread)
Setup 510f81fd5e9b4287a55817aaf5080e5d46005eecb5359eb06892040cf8d10d87
Portable 96bfb469f2d9dfe11606aa10db92febdfce73df980eec475ab285f2334925158
Bundled AriadneResolver-Setup-0.1.0.exe (9ab725be, unchanged 0.1.0)
Version 0.0.9 -> 0.1.0 marks the "Silent Mode = one install" milestone:
Theseus and the system-wide Ariadne resolver now ship together.
nsis/installer.nsh (electron-builder `nsis.include`) hooks two macros:
customInstall -- If Ariadne's Thread is NOT already installed,
MessageBox MB_YESNO|MB_DEFBUTTON1 asks whether
to install it now. On Yes, chain-invokes the
bundled Inno installer with
/VERYSILENT /SUPPRESSMSGBOXES /NORESTART
(Ariadne raises its own UAC because Inno declares
PrivilegesRequired=admin). Ariadne being present
already suppresses the prompt on upgrades.
customUnInstall -- Reads Ariadne's UninstallString from HKLM 64-bit
Uninstall\{...ARIADNERSLVR}_is1. If present,
symmetric MessageBox asks whether to remove it
too, then ExecWaits the string with the same
silent flags. Skips silently if Ariadne isn't
installed.
Registry probe uses SetRegView 64 (Ariadne installs 64-bit per
ArchitecturesInstallIn64BitMode=x64compatible in its .iss). Reset to
`lastused` after each probe to leave electron-builder's own state
unchanged.
Package changes:
- version 0.0.9 -> 0.1.0
- build.extraResources adds build/AriadneResolver-Setup-0.1.0.exe
(unpacked to $INSTDIR/resources/); build/ stays gitignored - the
binary is regenerated by copying from AriadneResolver's Inno output
- build.nsis.include -> nsis/installer.nsh
Size: installer 122 MB (+25 MB for bundled Ariadne), portable 122 MB.
Portable also carries the Ariadne exe as a side effect of extraResources
being global; portable can't invoke an installer, so the 25 MB is dead
weight there - future rev could scope extraResources per-target.
Site updates: tools page + releases page + theseus.x landing all
reflect the 0.1.0 hashes, sizes, and the new "Ariadne's Thread bundled"
line. tools page's "Coming to the Windows installer" footnote is
rewritten past tense because it landed.
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 and ../site-theseus-x
- verified HEAD 200, manifest reports 0.1.0 2026-08-31, VPS hashes
match local
Existing 0.0.6 (or newer) installs will surface 0.1.0 in the update
chip on next launch.
2026-08-31 05:07:34 +02:00
|
|
|
"artifactName": "TheseusNavigator-Setup-${version}.${ext}",
|
2026-08-31 16:32:16 +02:00
|
|
|
"installerIcon": "build/icon.ico",
|
|
|
|
|
"uninstallerIcon": "build/icon.ico",
|
Ship Theseus 0.3.2 09331b2f (tab context menu + branded installer)
Setup 09331b2fd9ccf136e2183b7cd85354cfd56e2ed50260b7aadeed63c7ea450251
Portable 21752d0fc85fb39ec1e65192920461e9ae395a22d9a68abd27f12e638d0fdd07
Right-click a tab: floating context menu with Reload, Duplicate, Group
(submenu: None / Red / Orange / Yellow / Green / Cyan / Blue / Purple),
Add to Bookmarks, Mute (also Unmute; 🔇 shows next to the title when
muted), Close. Menus close on outside click or Escape.
Group state is per-tab. A grouped tab shows a colored dot before the
title and a matching 2-px accent stripe on the top edge, so a cluster
of same-group tabs reads visually. Palette is drawn from existing
provenance colors (err/warn/acid/srv/sia/blue).
Backend IPCs are all tab-scoped (not "active tab"): tab-reload,
tab-duplicate, tab-mute (toggle or explicit boolean), tab-group,
tab-bookmark. emitTabs payload gains muted, group, and url so the
menu can read current state.
Installer wizard branding: 164×314 sidebar BMP with the compass mark
centered + "Theseus / NAVIGATOR" wordmark under it, plus a 150×57
top-strip header with a mini compass on the right. Sharp can't write
BMP directly (only png/webp/etc), so nsis/make-icons.mjs renders raw
RGB via sharp and wraps it in a hand-rolled 24-bit uncompressed BMP
header. Uninstaller reuses the same sidebar.
Silent-install fix: nsis/installer.nsh's AriadnePageCreate now checks
IfSilent BEFORE touching nsDialogs::Create. In /S mode the flag is
zeroed and the function returns cleanly, so the installer no longer
hangs waiting for a page it will never draw. This is why 0.3.2 needed
two builds — the first hung on /S install; the fixed hash is the one
that ships.
Deployed: scp + sia-upload of both trees. Verified VPS hash matches
local 09331b2f. Fresh /S install to D:\Program Files\Theseus Navigator\
placed 0.3.2 with the correct HKCU Uninstall registry entry.
2026-08-31 19:30:30 +02:00
|
|
|
"installerHeaderIcon": "build/icon.ico",
|
|
|
|
|
"installerSidebar": "build/installerSidebar.bmp",
|
|
|
|
|
"uninstallerSidebar": "build/uninstallerSidebar.bmp",
|
|
|
|
|
"installerHeader": "build/installerHeader.bmp"
|
2026-07-29 13:54:34 +02:00
|
|
|
},
|
Ship Theseus 0.0.8: window.bcnr dApp API + eTLD+1 permission origins
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
2026-08-31 01:38:55 +02:00
|
|
|
"portable": {
|
|
|
|
|
"artifactName": "TheseusNavigator-${version}-portable.${ext}"
|
|
|
|
|
}
|
2026-07-29 13:54:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
2026-10-02 23:49:39 +02:00
|
|
|
|