Commit graph

11 commits

Author SHA1 Message Date
Theseus Dev
f76ca4f9f4 Theseus 0.3.132: layout revert, Nostr per-site identities, Mail as sidebar quicklink, connector token stays persistent
Startpage layout reverted to the pre-0.3.131 shape. 0.3.131's full-page-
height sidebar was a mistake — slots in a short strip under a hero at
the top, cards and slots sharing one row of panels at the same height,
is what matches the design. .page/.main-col/.sidebar structure dropped,
hero back as a body sibling of .homepage, slots-list back to repeat(3,
72px) with minSlots=9. Two of the user's own tweaks baked into the
defaults: .section.chromeless on the left column so slot icons float
on the page background instead of sitting in a boxed panel, and
defaultState().iconSize = "large" (60 px tiles).

Game.X in the SM cards (replaces SilentMode.X in its slot, stub
description + a built-in gamepad brand mark until game.x goes live).
SilentMode.X moved to the quick-links strip as the 5th slot. moveItem
now strips the pinned-slot anchor when a q item moves to sm — a link
dragged onto the cards used to flip back on the next render because
its slot number was still set.

Nostr NIP-07 signer grows per-site identities (0.1.0 → 0.1.1). First
approval modal picks between the Hermes identity (one npub for DMs
and public notes, the one published as the np record on your BNS
name) and a site-specific HKDF-derived npub (unique per origin, so
Nostr clients can't cross-correlate your activity). The chooser shows
both npubs so the user sees what each button reveals. Grants without
a stored profileId (migrated from 0.3.131) default to the Hermes
identity so existing approvals keep behaving the same.
lib/hermes.js:nostrKeyFromRootForOrigin HKDFs with info
silentmode/nostr-origin/v1/<origin> over the existing 32-byte
messengerRoot. main.js _nostrAPI methods take {profileId, origin};
signer cache per profile.

Silent Mode Mail retired as an extension — now a Sidebar quicklink
(id: silentmail). Its 0.1.0 panel iframed mail.silentmode.st, which
sends X-Frame-Options: DENY; the browser rendered the block page and
STILL fired the iframe's load event, so the 5 s "did it embed?"
watchdog saw it as loaded and the panel stayed black. The whole
extension was just a landing page with an Open Mail button — exactly
what a sidebar quicklink does, without taking a panel slot or an
Extensions row. migrateAegisRename auto-retires any existing
extensions/mail/ to addons-backups/mail-migrated-<stamp>/ on first
boot of this Theseus; "mail" added to the first-party reserved-ids
list so a community add-on can't claim the id.

Claude connector 0.2.1 → 0.2.2: the bearer token no longer rotates on
every server stop. The old stop() generated a fresh token every time
Theseus quit, the panel toggled off, or a 0.3.X install replaced the
app — the Connect button wrote the new token to ~/.claude.json but
any already-running Claude Code or Claude Desktop process held the
previous token in memory and only re-reads config on launch, so /mcp
reconnect kept sending the stale bearer and the server rejected it
forever. Infinite loop: install Theseus upgrade, click Connect, MCP
still 401, close Claude, open Claude, install another upgrade a day
later, repeat. The explicit Revoke token button still rotates for
users who want fresh keys; everything else is persistent.

Sidebar panel apps blank to about:blank after 2 min of being closed to
free their render tree (iframes, media, listeners). Fast reopen within
the window still reuses the loaded page.

Light theme palette flip under body.light — the full set of
--ink / --mut / --card / --line tokens flip plus hero + card
translucent panels switch to light-glass, so hero titles, SM card
text, slot labels and the ".bch" tld read correctly on the light
background preset instead of as pale ghosts.
2026-10-30 03:45:32 +02:00
Theseus Dev
9c29331e5b Theseus 0.3.131: Mail promoted to Sidebar quicklink, Nostr signer ships, panels free RAM when idle, Game.X in SM cards
Silent Mode Mail is no longer an extension. The 0.1.0 panel was a black
screen (iframe to mail.silentmode.st which sends X-Frame-Options: DENY;
the browser rendered the block page and still fired the iframe's load
event, so the 5-second "did it embed?" watchdog saw it as loaded and the
fallback never swapped in). The whole extension existed to put one "Open
Mail" button in a panel — that is exactly what a sidebar quicklink does,
without taking a panel slot or an Extensions row. So:

  - settings.quickLinks default list gains silentmail at the top
    (Silent Mode Mail → https://mail.silentmode.st/).
  - migrateAegisRename grew a mail retirement block: any existing
    extensions/mail/ folder on the user's box moves to
    addons-backups/mail-migrated-<stamp>/ on first boot of this
    Theseus, so the old extension vanishes from Settings instead of
    sitting there with a broken panel.
  - "mail" added to the first-party reserved-ids list so no community
    add-on can claim the id after retirement.

Nostr NIP-07 signer finally ships. The bundled-addons/nostr/ folder was
sitting untracked in the main checkout, so the detached-HEAD build
worktree 0.3.130 used never saw it (same reason build/, tor/, snapshots/
have to be hand-copied into the worktree). This build committed the
folder and copied it in. Puts window.nostr on https + localhost pages;
identity is Hermes's key (one npub for DMs and public notes). Per-origin
read/sign grants; kinds 0/3/5/10002 re-prompt every time with no
remember option.

Sidebar panel apps free their render tree after idle. closeLeftPanel
used to keep the loaded page warm forever — great for fast reopen, bad
for RAM when the user docks a heavy panel (Hermes, Pithos, Aegis) once
and never comes back. A 2-minute idle timer now blanks the panel to
about:blank after close; reopen within the window still reuses the
loaded page (cancelLeftPanelIdleUnload on open), reopen after the
window reloads fresh. LEFT_PANEL_IDLE_MS = 2 * 60 * 1000. Right-side
sidebar view (webapp tabs — Telegram, X, WhatsApp, AI chat) is longer-
lived by design and untouched here.

Startpage layout:
  - Game.X takes SilentMode.X's slot in the Silent Mode cards (stub
    description + a built-in gamepad brand mark until game.x goes
    live). SilentMode.X moves to the quick-links strip as the 5th
    slot. Still TODO: push the swap into the remote home-cards.json
    for existing profiles.
  - Light-theme palette flip under body.light. The @media
    (prefers-color-scheme: light) block only triggered on OS-level
    light preference; picking the "light" background preset left --ink
    white against a white page, so hero titles, card titles, slot
    labels and the ".bch" extension read as pale ghosts. Added a full
    body.light { --ink; --mut; --card; --line; ... } block plus
    overrides for the hero + card translucent panels (dark-glass →
    light-glass on light theme) and the ctx-menu / modal. Dark theme
    untouched.
2026-10-30 00:38:08 +02:00
Theseus Dev
b4cea7b83f Theseus 0.3.130: startpage sidebar fills the panel, searchbar stops auto-growing, Store Claude Desktop detected
Startpage sidebar is now a real left column that starts at the Theseus
title's top edge and runs the full page height. The slot grid is 3
columns stretched to the full sidebar width, with enough rows to cover
the sidebar vertically (count derived from the main column's height on
each render, and re-derived on viewport resize). Empty cells sit as
semi-transparent dashed outlines in the exact position a filled tile
would occupy, so the grid reads as one uniform surface; any empty cell
doubles as the "add link" surface and clicking it opens the Add-link
modal with that cell pre-pinned, so new links land exactly where the
click did instead of being pushed to the end. The dedicated "+" button
is gone — the pin-location is the click target. A "Theseus v0.3.X —
What's new" link appears under the search tip, pointing at
silentmode.st/releases; version comes from a new getVersion exposed on
window.home over the existing app-version IPC.

Chrome toolbar: 0.3.128's "give the searchbox more room while typing"
rule is removed — focusing the search field was pulling the drag handle
with it, which made the URL / search ratio impossible to set by hand.
The URL bar now caps at 75% of the pair's shared budget via a hard CSS
max-width (so a wide urlBarWidthPx stored under the old 80% ceiling
clamps on load without the user having to re-drag), and the drag floor
matches at 25 % so the search field always keeps at least a quarter of
the pair.

Claude connector: bumped bundled-addons/claude-connector from 0.2.0 to
0.2.1. The clients.cjs Store-install detection and the panel-access
work shipped in 0.3.129's bundled 0.2.0, but seedBundledAddons only
overwrites the installed copy when the bundle is strictly newer, so
every user with an existing 0.2.0 kept the stale pre-fix copy from
%APPDATA%/Theseus/extensions/claude-connector/. The version bump
surfaces the Store-install detection ("Claude Desktop not installed on
this computer" was false on every Microsoft Store install) and the
add-on-panel approvals split in the connector panel, both of which
were already in-tree but gated behind the version check.
2026-10-29 14:46:29 +02:00
Local Dev
ed441b4e9d Passwords: save and fill logins inside iframes too
Sign-in widgets and embedded checkouts often put the login form in an
iframe, and the password hooks only ran in a tab's top frame, so those
logins were never offered for saving or filling.

- Web tabs now run preloads in iframes (nodeIntegrationInSubFrames; pages
  still get no Node). Only the password hooks act there: the home-page
  bridge, window.bcnr, add-on page scripts and window.theseusId return early
  outside the top frame, exactly as before.
- A login in a frame belongs to the frame's own site, taken from that
  frame's committed URL. The save prompt says "login.example (in a frame on
  shop.example)", the fill offer names both, and the fill goes into that
  exact frame only while it is still that tab's and still on that site.
- The "did the login go through" check runs against the frame.

Verified with a shop page embedding a cross-site login frame: save offer,
fill offer and fill all target the frame; the outer page gets nothing;
top-frame logins behave as before.
2026-10-05 20:34:17 +02:00
Local Dev
8db0a2f9f9 Merge branch 'claude/focused-visvesvaraya-177d2e' into release/0.3.80
# Conflicts:
#	TheseusNavigator/main.js
#	TheseusNavigator/settings.html
2026-10-05 20:04:12 +02:00
Local Dev
7907451b24 Theseus: a page click closes the left panel unless it is pinned
Opera's other sidebar rule. A click in the active tab's page now hides the
left panel (web app or add-on panel), so a chat opened for a quick look
gets out of the way on its own. A pin button in the strip, shown while a
panel is open, keeps that app open instead; pins are per app and survive
restarts (settings.leftPanelPinned). The click is reported by
home-preload, which every web tab already runs; main ignores it unless a
panel is open and the click came from the active tab.
2026-10-04 20:58:03 +02:00
Local Dev
a6f7b335a5 Vault: PIN setup steps, 6-8 digit PINs, save and offer logins, keep sign-ins
The PIN could only be six digits and was set from three bare inputs; the
unlock prompt sat at the top of the page; and the password manager only
filled when you found the key chip, never offered to save, and "Clear
cookies on quit" signed you out of every site, including the ones whose
login the vault already holds.

- PINs are 6 to 8 digits. The PIN record stores its length so pads draw the
  right number of dots and submit on the last digit; a PIN of the wrong
  length is refused without a strike, so an older Aegis pad cannot burn the
  count against an 8-digit PIN.
- Settings sets a PIN in steps: master password, choose the PIN on a pad
  (6/7/8), repeat it, done. The locked vault opens Theseus's own prompt,
  which is now centred, with the PIN pad or the master password field.
- After a sign-in or sign-up form is sent and the page moves on, Theseus
  offers to save (or update) the login, with an optional "ask for my PIN or
  password before filling it". Focusing a login form offers the saved
  logins under it; on a locked vault it offers to unlock first. A failed
  login (the password field still showing) gets no offer.
- "Keep sign-ins for sites in your vault" (on): the quit clear spares the
  cookies and site storage of sites with a saved login. Their hostnames are
  kept sealed with the OS keystore so the list is readable at quit while
  the vault is locked. Verified end to end on a scratch profile: signed in,
  restarted, still signed in; another site's cookie was cleared.
2026-10-04 20:23:43 +02:00
Local Dev
8e60469703 fix(theseus/home): dynamic search-engine name in placeholder
Home page's search-box placeholder was hardcoded "Search the web
(DuckDuckGo)", but the browser's default engine has been Startpage
for a while and any user can switch to another in Settings. The
"DuckDuckGo" claim then contradicted the actual engine that would
run the query (main.js routes through settings.searchEngine).

Fix: placeholder starts as plain "Search the web" and populates on
load with "Search the web with <engine.name>" via a new
window.home.getEngines() IPC (reuses the existing search-engines
handler). Silently no-ops if the preload isn't bound.

Also swapped the never-fires no-preload fallback URL from
duckduckgo.com to startpage.com so it matches Theseus's own default.
2026-09-08 00:20:37 +02:00
Local Dev
5d248541cf Ship Theseus 0.3.0 bb9d8dec (home cards decoupled from browser release)
Setup    bb9d8dec124b8e2a976642ed77051b04edd1d03185581f99db845ef168919836
Portable 1e2d02aea13656574c374440b0c41374290f1bbf85ac6313cec075292cfc34f8

Home cards decoupled from the installer. Theseus now fetches
https://dl.silentmode.st/home-cards.json at boot and every 6h, caches
into <userData>/home-cards-remote.json, and applies it as the default
tier. Priority in loadHomeCards() is:
  1. <userData>/home-cards.json  (user edits — unchanged, always win)
  2. <userData>/home-cards-remote.json  (last successful fetch)
  3. DEFAULT_HOME_CARDS  (code fallback for offline first-boot)
On a successful refresh, main pushes the new list to every home tab
via the home-cards IPC — but only when the user has NO local edits.
The user's edit mode remains authoritative.

Content updates now happen by editing site/home-cards.json and running
scp + sia-upload. No browser build required.

Prometheus.X copy fix: "Decentralized App Marketplace" (was
"marketplace for BCDN-hosted apps" — the marketplace isn't BCDN-
specific). Applied to both DEFAULT_HOME_CARDS (fallback) and
site/home-cards.json (canonical live copy).

Deployed:
- scp installers + manifest + tools/ + releases/ + home-cards.json
  to /opt/silent-mode/dl/ and /opt/silent-mode/site/
- sia-upload of both site trees
- verified home-cards.json served 200, manifest 0.3.0 live

Existing installs of 0.2.5 will surface 0.3.0 in the update chip and
also pull the new home-cards.json — so the "Decentralized App
Marketplace" wording lands on ANY current install (0.3.0+) the moment
this commit deploys, without waiting for anyone to install 0.3.0.

Wait — 0.3.0 is what CARRIES the fetch logic. So the auto-pull benefit
only kicks in from 0.3.0 onward. Users on 0.2.5 or earlier need to
install 0.3.0 once; from then on every home-card edit reaches them
without a new browser release.
2026-08-31 18:38:09 +02:00
Local Dev
e43e009f73 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
Local Dev
2be859267e 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