Commit graph

276 commits

Author SHA1 Message Date
Local Dev
dbc18da36e feat(theseus): tabs in the title bar, link-opened tabs next to their opener, clearer active tab
Three tab-strip changes from use:

- A tab opened from a link (target=_blank, middle-click, the context menu,
  Duplicate) now goes right after the tab it came from — and after any
  siblings that tab already opened — instead of at the end of the strip.
  The + button, session restore and add-on requests still append.
- The selected tab gets an accent stripe and outline on top of its brighter
  fill; with a dozen same-size tabs the fill alone was easy to lose. A
  grouped tab keeps its group colour on the stripe.
- On Windows the tab row is the title bar: the native frame is hidden, the
  minimise/maximise/close buttons are drawn as an overlay over the chrome
  (colours follow the theme), the row is a drag region with every control
  in it opted out, and 140px (or the overlay's real width when the API is
  exposed) is kept clear on the right. The page gains the old title bar's
  height. Other platforms keep the native frame.
2026-09-20 02:19:19 +02:00
Local Dev
cd098bc9f3 screenshot 0.6.5: line tool + resizable text box
Two annotation-editor asks:

- Line tool: same drag flow as the arrow, no arrowhead. New toolbar
  button between arrow and rect, shortcut L.
- Text box is resizable: swapped the single-line input for a textarea
  with resize:both and a drag corner. Enter still commits, Shift+Enter
  inserts a newline, blur commits. Multi-line rendering steps the
  fillText baseline by 1.15x the font size per line so the baked
  pixels match the live layout.

The textarea swallows its own pointer events so drag-resizing the
corner doesn't leak to the canvas underneath.
2026-09-18 01:02:56 +02:00
Local Dev
ed323713d7 fix(theseus): Ariadne's Thread card — find the installed resolver, answer in ~2 s
Two reasons the Plug-ins card looked dead ("only a Refresh button"):

1. The state check ran Get-ScheduledTask, whose module import took 8–10 s
   cold, and only then fetched the release manifest. Every button is hidden
   during "checking…", so for 10–15 s the card showed nothing but Refresh.
   Task state now comes from the Task Scheduler COM object (numeric, locale-
   independent — schtasks.exe prints localized words on non-English
   Windows) and the manifest fetch runs in parallel: ~2 s.

2. The Inno installer's AppId is written as {{…}}, which Inno registers as
   {…}}_is1 (doubled closing brace). Theseus looked for the single-brace
   key, never found it, and so never knew the installed version — no Update
   button, no Uninstall button. The entry is now found by DisplayName.
2026-09-16 20:15:19 +02:00
Local Dev
27a1243e4d feat(theseus): consume owner-signed DNS records alongside on-chain records
Owners can now publish a signed _records.json (A/AAAA/MX/TXT/CNAME/NS)
beside their Sia content; the gateway verifies it against the current NFT
holder and serves it as GET /api/dns/<name>. Every BCDN resolution now
starts a background fetch of that answer (3 s cap, 30 s cache, seq rollback
guard) and attaches it to the entry as entry.dns. Navigation never waits
for it — on-chain h/s3/ip/p/u stay authoritative — except when a name has
no content record at all and a signed A is the only way to reach it. Only
registered names are looked up, so ICANN hosts never reach the gateway.

Exposed as window.bcnr.dnsRecords(name) for add-ons (TXT verification, MX
for mail bridges), on resolveName() as .dns, and as a "Signed DNS" row in
the site-info popover.
2026-09-16 00:53:13 +02:00
Local Dev
621758834a chore(theseus): 0.3.48 — HTTP auth prompt, local files from the address bar, on top of 0.3.47 2026-09-15 23:09:45 +02:00
Local Dev
f9a7063635 merge: 0.3.47 plug-in category + panel-driven add-on self-update, aegis 0.6.31 into master line 2026-09-15 23:09:30 +02:00
Local Dev
27265c4e21 fix(theseus): put the last two main.js hunks where they belong
df181d9 and b2c6f62 were staged hunk-by-hunk from a working tree that also
carried unrelated uncommitted edits, and the context-free hunks landed a
few lines off: the local-file check ran after the search rewrite (so paths
still went to the search engine in the committed file), the loadBns header
sat inside loadLocalFile's comment, and the refreshTabUrl comment was split
by the auth block. Content is unchanged; only placement is corrected.
2026-09-15 22:33:07 +02:00
Local Dev
ab78535192 fix(theseus): prompt for HTTP authentication instead of showing the bare 401
Sites behind Basic/Digest auth (silentmode.st/guardian/admin) rendered the
server's 401 page because nothing listened for Electron's login event,
which cancels every challenge by default. A modal sign-in prompt now asks
for the credentials and answers the challenge; Cancel leaves the 401 page.
Concurrent challenges for the same host and realm share one prompt while it
is open, and a rejected answer re-prompts instead of replaying the same
credentials until Chromium gives up with ERR_TOO_MANY_RETRIES.

Also: THESEUS_NO_UPDATE_CHECK skips the release check, for throwaway dev
instances — the one-click install chip they show targets the real install.
2026-09-15 22:30:29 +02:00
Local Dev
e596454446 fix(theseus): open local files from the address bar instead of searching for them
A typed or pasted path such as D:\Dev\x\page.html has no dotted host, so
the URL-vs-search heuristic handed it to the search engine. Paths (drive,
UNC, file://, and absolute/~ on POSIX) now load as file:// URLs before the
heuristic runs. Local-file tabs keep their file:// URL in the address bar
(normally suppressed because our own home/error pages are file://), show a
"Local file" badge, and hide the registry button since no name resolution
is involved. A missing file lands on the error page with a matching badge.
2026-09-15 01:36:10 +02:00
Local Dev
f46e9112b7 chore(theseus): 0.3.47 — plug-in category + panel-driven addon self-update, aegis 0.6.31
Theseus core:
- addons-host: manifest.category ("plugin") propagates through snapshot(); new
  addon API surface checkAndStageSelfUpdate() + restartApp() so a plug-in
  can offer in-panel "update now → restart to apply" without pushing the
  user to Settings.
- main.js: wires the two new hooks into the AddonHost constructor.
- settings.html: Extensions listing filters out category==="plugin"; those
  add-ons live in Plug-ins instead, single source of truth.

Aegis 0.6.31:
- BTC picker trimmed to Signet only; testnet3 hidden (adapter kept so any
  existing wallet still loads).
- Wallet strip groups by chain, not chain:network; ticker gets a ▾ chevron
  and a dropdown listing every subnetwork with its own totals. Mainnet
  reads as the plain ticker; testnets carry a small Chipnet/Signet/Sepolia
  pill inline.
- Per-unit price sits directly under the ticker; amount + fiat mirror on
  the right — one glance covers name/price/holding/value.
- + Add and ⋯ More promoted from the strip into the header's action row,
  next to the new ✎ chip (was the redundant top ⋯). Duplicate "Manage
  current wallet" entry removed from the More menu.
- Footer update chip is a two-step flow via the new API: stage → restart.
  Falls back to opening Settings on any Theseus that lacks the hooks.
- Manifest declares "category": "plugin".
2026-09-14 02:30:51 +02:00
Local Dev
a43089782a fix(theseus/addons): reseed a bundled add-on only when the bundle is strictly newer
seedBundledAddons reseeded whenever the user copy's version differed from
the bundled one. promoteStagedUpdates runs just before it, so a signed
over-the-air update that had just been promoted (e.g. Aegis 0.6.14 over
the bundled 0.6.2) was backed up and replaced by the older bundle on the
same boot — every OTA add-on update silently reverted at the next launch.
Reseed now only when the bundle is newer, using the same version compare
the promoter uses.
2026-09-13 19:49:23 +02:00
Local Dev
d7d127d7b4 fix(theseus/bns): failed content fetches get a real error page naming the upstream and cause
A bns:// fetch that fails after the name resolved (relay unreachable, DNS
stalling, the site's own server down) used to answer with the bare text
"Theseus error: fetch failed", which reads as a broken browser. The
handler now returns a styled page that names the host, the upstream it
tried (navigate.st, the p-record origin or the ip record), the error and
its cause code, explains the likely reason per cause (unreachable vs DNS),
and offers a retry.
2026-09-12 09:09:06 +02:00
Local Dev
1596463b70 chore(theseus): 0.3.46 2026-09-12 00:31:47 +02:00
Local Dev
3c0f13c1e5 fix(theseus/updater): run the installer only after the app has exited, via a detached batch helper with self-heal
A 0.3.44 → 0.3.45 auto-update on 2026-09-11 left the install without
app.asar and ffmpeg.dll ("ffmpeg.dll not found" at launch). The setup was
hash-verified; the old-version uninstaller had moved the whole old install
into its temp folder when both NSIS processes died ~8 s after the spawn,
and the install step never wrote a file. The killer was not identified, so
every overlap with the app's own lifetime is removed instead:

- install-update-now no longer spawns the setup; it records the path and
  quits. will-quit writes <userData>\update-helper.cmd and starts it as a
  detached cmd.exe (verified to outlive the app; not a child of ours).
- The helper waits for our PID to be gone (child powershell Wait-Process),
  gives Chromium's children a grace period, runs the setup directly, and
  runs it once more if resources\app.asar is missing afterwards — the
  installer is idempotent, so a second pass repairs a torn install. The
  helper deletes itself.
- Zone.Identifier is stripped from the verified download so nothing that
  starts it through the shell raises a mark-of-the-web prompt.

Console-less cmd.exe traps discovered and designed around (see the module):
child console programs' redirected stdout is empty (no tasklist|find
probing), `start /wait` on a .cmd hangs, a detached powershell.exe
started straight from Node does nothing, `timeout` needs a console.
Scenario tests: setup starts only after the process exits, once with
app.asar present, twice without, helper gone afterwards.
2026-09-12 00:31:46 +02:00
Local Dev
ed48646c71 feat(theseus/chrome): "Open link in new window" on the link context menu
A standalone page window on the same session (cookies, bns:// protocol,
session-wide bcnr preload) with Theseus's fingerprint + WebRTC policy and
no toolbar. Loads BCNR-first like a tab: a dotted host with a BCNR record
goes over bns://, otherwise clearnet; collision names follow the configured
policy without the "Open with…" interstitial. Cross-host navigations inside
the window stay BCNR-first; popups go to the main window's tabs. Its own
context menu offers open-in-tab / open-in-window / copy link and
back/forward/reload. Add-on page bridges (wallet inject) are tab-scoped and
don't run in these windows. openLinkWindow is exported for the test harness.

Verified in the dev app: coinspectrum.x opened as bns://coinspectrum.x with
the page title; navigate.st stayed https.
2026-09-10 22:25:19 +02:00
Local Dev
43d0021bf6 docs(theseus): add-on update channel lives on Sia, not the VPS — publish with sia-upload
The publishing steps pointed at scp to /opt/silent-mode/site/addons/, which
never existed; the screenshot channel (and now aegis) is served from
s3://bns/theseus/extensions/<id>/ through navigate.st/bns/theseus.x/….
Also: sign from a git-archive copy so uncommitted edits don't ship.
2026-09-10 22:25:18 +02:00
Local Dev
ee5e53512a docs(theseus/prompts): tool-agnostic phrasing in session-prompt templates 2026-09-10 22:21:19 +02:00
Local Dev
50eb143b0a chore(theseus): 0.3.45 2026-09-10 00:12:35 +02:00
Local Dev
c9dbcbde86 fix(ariadne): Theseus on/off toggle never reached the tasks; updater read a stale manifest; uninstall left NRPT rules
Theseus (Settings › Plug-ins › Ariadne's Thread):
- The elevated start/stop script was embedded in a double-quoted outer
  PowerShell string, so `$t` was interpolated away before the elevated
  shell saw it. It received `foreach ( in …)`, failed to parse, and the
  outer shell still exited 0 — "Turn on/off" reported success while doing
  nothing, in every shipped build. The script now goes across as
  -EncodedCommand. Off = Stop + Disable (the daemon task has an
  at-startup trigger, so a plain stop came back on reboot); on = Enable +
  Start. Exit 2 = daemon task missing, surfaced as a clear error.
- Version/update check now reads dl.silentmode.st's releases manifest,
  the same one the Theseus updater uses. The silentmode.st copy lagged a
  day behind (still listing Theseus 0.3.31), so a new Ariadne release
  published to dl would not have been offered.
- Install/update/uninstall now propagate the installer's exit code
  (-PassThru; exit $p.ExitCode) instead of always reading as success.

Resolver package (needs a new installer build to reach users):
- uninstall.ps1 removed only the ".bch" NRPT rule; install.ps1 adds one
  per advertised TLD. Sweep every "BNS .<tld> resolver" rule.

Verified: daemon resolves BNS names and passes ICANN A/AAAA through when
run unprivileged on port 15353; the encoded-command construction runs
intact and propagates exit codes 0/2 in an unelevated reproduction.
2026-09-09 23:04:23 +02:00
Local Dev
56eff58fda feat(theseus/chrome): page zoom, 80/20 address/search ratio, collapsed dock renders icon images
- Per-tab page zoom on Chrome's ladder (25–500 %) via setZoomFactor, so
  Chromium keys it per host: every tab on a site shares the level and it
  persists across navigations and restarts. Ctrl +/=/numpad+ in,
  Ctrl -/numpad- out, Ctrl 0 reset, Ctrl+wheel via zoom-changed. A
  percentage chip appears in the address bar when a tab isn't at 100 %;
  clicking it resets. Settings and add-on tabs never zoom.
- Address bar / search bar drag ratio floor lowered from 30 % to 20 %,
  so the split runs 80/20 to 20/80 (pixel floors still apply).
- The collapsed extension-dock button and its dropdown printed a data:
  URI icon as text ("data:image/svg+xml…"). One addonIconHtml() renderer
  now serves the dock buttons, the collapsed button and the dropdown.
2026-09-09 23:04:22 +02:00
Local Dev
7b8539fb8d feat(theseus/screenshot): 0.6.4 — Polaroid sounds, trash icon, centred cluster, filename footer + open-in-folder
Rolling every user report from the 0.6.3 rollout into one bundle:

Sounds — the Web-Audio synth palette matches the metaphor now:
- Screenshot: Polaroid shutter — sharp metallic tick + curtain-close click
  chained to a film-advance whir (band-passed noise sweeping 900→400 Hz).
- Copy: printer "chika-chika-chika" — three descending percussive noise
  bursts pinned by short sine ticks. Reads as a print-head sweep.
- Discard: paper crumple — three overlapping band-limited noise beds
  with per-sample random-amplitude crackle, descending centre freq. No
  more descending sine "boop".
- Save: soft "photo dispensing" hiss (Polaroid ejects) + a small click.
- Both the panel and editor share the design so nothing sounds different
  depending on which surface fired it.

UI polish:
- Discard button now carries a trash-can icon so it's obviously not the
  same as the close-sidebar X (they both used to be plain X's).
- Toolbar drawing tools centre themselves via a new .tool-cluster
  wrapper (flex:1 1 auto, justify-content:center); the Copy/Save actions
  stay right-anchored via margin-left:auto on their own tgroup. Fixes
  the maximized-sidebar case where the drawing groups all crowded the
  left with a big empty gap before Copy/Save on the right.
- Filename moves out of the topbar into a dedicated footer strip under
  the canvas board, alongside a new "Open in folder" button. The topbar
  is now flex-wrap:nowrap and holds only fixed-width window controls,
  so a long filename can never push discard / sound / max / close onto
  a second row (the filename ellipsises instead).
- "Open in folder" invokes a new "openFolder" addon message that calls
  Electron's shell.showItemInFolder() to open the OS file explorer with
  the specific scratch PNG highlighted (falls back to shell.openPath()
  on the scratch dir when no capture is named).

Version bump so the OTA update endpoint picks it up on the next tick.
2026-09-09 22:34:47 +02:00
Local Dev
8eda0433d7 feat(theseus/screenshot): 0.6.3 — per-tile delete, no Select button, text tool halo, right-anchor panel controls
Four issues from the user's report on 0.6.2:

- Recent captures had a global "clear all" but no way to drop a single
  screenshot. Each tile now grows a small × button (visible on hover;
  drops in behind the thumbnail preview so it never obstructs the
  content). Clicking the × invokes clearRecent({name}) and removes both
  the ring entry and the scratch PNG on disk. Bubble-guarded so the ×
  click doesn't also trigger the tile's "load into preview" handler.

- Select tool button removed — clicking it did nothing visible, so users
  read it as broken. The internal "select" mode still exists as the
  no-tool state; you get back to it now by clicking the same drawing
  tool a second time (toggle-off) or hitting Escape. The active-drawing-
  tool button flips its border when armed.

- Text tool made unmistakable: input paints with a 2 px acid border, a
  glowing acid halo, dark background, and the visible ink colour on the
  text itself. Focus attempt is three-layered (sync, rAF, timer) to
  outrun any Chromium build that drops the mid-pointer-event focus. Non-
  Enter/Escape keys get stopPropagation so a stray document listener
  can't steal the focus mid-typing.

- Panel header's sound / max / close cluster kept nudging inward when
  the status text was empty. The parent's `justify-content: space-
  between` distributed the row unevenly. Force-anchor the cluster with
  `#btn-sound { margin-left: auto }` so the three window-control icons
  hug the right edge regardless of what fills the middle.

Bundled but not shipped separately — parent session signs and pushes.
2026-09-09 22:01:06 +02:00
Local Dev
744574ba96 feat(theseus/screenshot): 0.6.2 — Copy/Save move to toolbar, Discard, right-anchored topbar
Layout reorganisation from user's diagram:

- Copy + Save move out of the topbar into the toolbar as their own
  right-anchored tgroup (margin-left:auto). On wide sidebars they sit at
  the end of the drawing-tool row; when the sidebar is narrow, the
  actions cluster wraps as its own row on the right instead of nudging
  the drawing tools around. Toolbar switches from justify-content:center
  to flex-start so the leading tool groups pack left and the actions
  group can find the right edge cleanly.

- Topbar right cluster is now Discard / Sound / Maximize / Close — Copy
  and Save are gone from the topbar entirely so the right edge reads
  as controls-only, not action-mixed.

- Discard button (X icon, danger red on hover) throws away the current
  capture — silentmode.invoke("clearRecent", {name}) removes it from the
  ring and unlinks the scratch file — then navigates back to the panel.
  Distinct from Back, which is non-destructive.

- Close button already existed from 0.6.1 but stays in the same
  right-edge position for continuity.

Bundled but not shipped separately — parent session signs and pushes.
2026-09-09 11:46:21 +02:00
Local Dev
8a99c0959c feat(theseus/chrome): Ariadne's Thread registry menu, address-bar overflow fix, full-width link pill
- Link-status pill: it measured its own width inside a view already
  capped at 100 px, so it could never grow and long hrefs were cut short.
  An off-screen twin now reports the natural width; main caps it to the
  tab area (never under the sidebar) and the pill ellipsises past that.
- Address bar at narrow widths: the URL input's intrinsic minimum width
  pushed the registry chips and the star out past the bar. #url now has
  min-width: 0 and the trailing controls are fixed-size flex items.
- The BCDN/ICANN segmented chips are replaced by one Ariadne's Thread
  icon (spiral + tail) at the end of the bar: acid when served from BCDN,
  blue for ICANN, caret when the name exists on both. Click opens a
  native menu (registry-menu-popup): switch registry, remember per name /
  per TLD, forget choices, collision policy, and a jump to the Plug-ins
  settings section. Reuses the existing switch / remember / policy paths
  (collision-switch body extracted to switchRegistry, open-settings to
  openSettingsTab). preload's openSettings now forwards a section slug.
2026-09-09 11:40:46 +02:00
Local Dev
c9a3db26ce fix(theseus/boot): paint the toolbar first — stop gating startup on chrome.html's load event
Users saw a blank window with a white strip across the top for seconds
on launch. Root cause: every part of startup, including session restore,
waited for chrome.html's did-finish-load. That event also waits for the
page's subresources, and the bookmarks bar loads its favicons over
bns:// — a BNS lookup plus a network fetch each — so a slow link held the
whole boot. On top of that, seven hidden overlay renderers, every restored
tab, the BNS index build and three network fetches all started in the
same tick and stalled the main thread ~1 s while the toolbar tried to
paint.

- Continue boot at chrome.html's dom-ready (toolbar scripts have run, IPC
  listeners exist) instead of did-finish-load; 8 s fallback timer.
- Window and chrome view get the toolbar's --bg for the active theme so
  the pre-paint frame is never white.
- Overlay pages (site info, engine picker, downloads, suggestions,
  password fill, link status, approval) load 250 ms after the toolbar or
  on first use; the approval modal awaits its page so a dapp request
  can't hang.
- Session restore is staggered: active tab first, then one background
  tab per 150 ms slotted into its saved strip position. Session file v2
  records the active index; v1 arrays still load (active = last, as the
  old loop effectively did).
- AddonHost gains api.whenUiReady(); Aegis 0.6.2 defers its heavy
  dependency loading (noble precompute, bitcoinjs, libauth, WizardConnect)
  behind it.
- BNS snapshot warm-up still starts right after createWindow (bookmark
  favicons need it); Sia refresh, update check and home-card fetch move
  to the post-paint phase.

Measured on a clone of the real profile with nine restored tabs: toolbar
usable at ~0.7 s instead of ~1.5 s, main-thread stall during toolbar load
down from ~1.1 s to ~0.2 s.
2026-09-09 11:40:45 +02:00
Local Dev
bf6bcfade2 feat(theseus/screenshot): 0.6.1 — text tool fix, category wrap, sidebar close X
Four user reports from the 0.6.0 rollout:

- Text tool never committed. openTextInput placed the box correctly but
  a couple of Chromium quirks stopped a normal type-Enter cycle:
  focus() called synchronously right after appendChild lost the race
  in some builds, and the input's own mousedown / click was bubbling
  through to #base and re-firing openTextInput on every subsequent
  keystroke click-through, so what looked like "nothing happens" was
  actually "a new empty box spawned on top of the last one every time".
  Now: focus after requestAnimationFrame, contain pointerdown / mousedown
  / click inside the input so they don't bubble to the canvas, track
  the font size on the state so commit uses the same one openTextInput
  measured against, and preventDefault on the base pointerdown so
  Chromium doesn't reset focus back to <body>.

- Toolbar wrapped one dot at a time when the sidebar was narrow (a
  lonely thin/medium/thick width would jump to a second row while the
  swatches stayed above it). Toolbar items are now wrapped in
  `<div class="tgroup">` per category — tools / swatches / widths /
  undo-redo — with `flex: 0 0 auto`, so a whole row wraps as a unit
  and lands cleanly under the previous one. `gap: 10px / row-gap: 6px`
  keeps the visual grouping obvious.

- No way to close the sidebar without hunting for the dock icon. Added
  an X button in the top-right of both the sidebar panel and the
  editor toolbar. Both wire through a new `silentmode.sidebar.close()`
  preload method that calls the existing `sidebar-close` IPC.

- Tightened the pointerdown text branch so preventDefault + explicit
  focus-after-frame make the click-through races impossible.

Bundled but not shipped separately — parent session signs and pushes.
2026-09-09 10:55:21 +02:00
Local Dev
35ec8a3904 fix(theseus/sidebar): visible-at-rest separator between the tab area and the sidebar
The resize grip lived along the sidebar's left edge as a 5-px transparent
hover target — you couldn't see it existed until the pointer landed on it.
Users on both light and dark backgrounds reported the seam between the
tab area and the sidebar as invisible.

Paint a 2-px semi-opaque mid-gray line (`rgba(140,150,170,.55)`) at rest so
the boundary is legible on every panel background; hover ramps to acid
green, active-drag ramps brighter. The visible band is narrower than
before (2 px vs 5 px) so it reads as a subtle divider rather than
competing chrome; the pointer-catch zone stays wide via an invisible
outline extension, so drag-to-resize still catches slack.
2026-09-09 10:50:30 +02:00
Local Dev
0f39429d63 chore: push-split helper for per-project forge repos + Windows Sandbox installer config
scripts/push-split.sh pushes one monorepo subdirectory to its matching
split repo on Hephaestus via an ephemeral git-subtree-split branch, so
history is preserved on the forge side. The remote name is derived from
the directory (Navigator/Resolver suffix stripped) or passed explicitly.

TheseusNavigator/test-installer.wsb is a Windows Sandbox profile that
maps dist-public read-only and launches the setup exe on logon, for
clean-machine installer checks.
2026-09-09 10:33:23 +02:00
Local Dev
992c02ea89 feat(theseus/aegis): 0.6.1 — in-panel vault setup/unlock, BCH wallet imports, opt-in fiat prices, WizardConnect
Aegis Wallet 0.4.4 → 0.6.1:

- Vault lifecycle from the wallet gate. The locked / not-yet-created states
  now show a master-password form (with optional BIP39 mnemonic on setup)
  instead of redirecting users to Settings › Passwords. New
  api.vault.lifecycle {status, setup, unlock, lock} in addons-host, gated by
  the existing "vault-derive" capability. api.openSettings(section) also
  added; settings.html honours a #section hash on open.
- Imported BCH wallets (design M.1a, read-only). Paste a mnemonic + BIP44
  path or a WIF; the cashaddr is derived in the add-on, the signer material
  goes to a separate wallet-imports.enc via api.vault.imports {list, add,
  remove, signer}. Argus password-vault gains createImports / unlockImports /
  saveImports with its own KDF salt so the imports key is disjoint from the
  passwords key. lib/chain-bch-imported.js is a single-address Electrum
  adapter; spend support is deferred to M.1b.
- Opt-in USD prices via CoinGecko (lib/prices.js), off by default, persisted
  in add-on storage. Fiat lines under balances, in the wallet picker, and a
  portfolio total when 2+ wallets are open. Settings tab is now reachable
  while the vault is locked so the toggle is always available.
- WizardConnect wallet-side pairing for BCH wallets (lib/wc.js, lib/wc-sign.js).
  @wizardconnect/{core,wallet} are loaded dynamically via api.import to stay
  on the right side of LGPL §4d. Sign requests go through approvalModal and
  are restricted to P2PKH inputs with SIGHASH_ALL|FORKID|UTXOS.
- DGB adapter load is now soft-fail: when Aegis runs from userData/addons the
  bundled ESM can't resolve peer deps, so DGB becomes unavailable instead of
  taking the whole add-on down.
2026-09-09 10:33:21 +02:00
Local Dev
7405e444e7 feat(theseus/screenshot): 0.6.0 — crop + mosaic redaction, right-anchored sidebar controls, real shutter+print sounds
Editor:
- Crop tool restored — drag to select, marquee sits with a dashed acid
  border and a dimmed backdrop for the area you'll discard, then the
  topbar shows Apply crop / Cancel. Applying trims #base to the rect,
  resets undo (dimensions changed), and drops back into the select tool.
  Enter / Esc keyboard shortcuts while a crop is pending.
- Blur / mosaic redaction tool back — drag a rectangle, editor
  downsamples that region of #base to ~12-block granularity and paints
  the blocks back nearest-neighbour. Commits directly (no confirm step).
- Sidebar-window controls (Back, name, Copy, Save, Sound, Maximize)
  reflow: Back + name on the left, Copy + Save + Sound + Maximize on
  the right so the "put the sidebar back to normal size" affordance
  lives where users expect it. Toolbar's drawing tools stay centred.
- Back arrow icon swapped from a chevron to a proper flat arrow
  (line + arrowhead), matching the new browser back/forward glyphs.

Sounds — modeled on Firefox Screenshots' feedback rather than beeps:
- Shutter is now a real photoshoot click: two mirror-slaps built from a
  band-passed noise burst (metallic ping) plus a very short square-wave
  thud each. Sounds like a camera, not a beep.
- Copy is a two-chirp "printer feed" — filtered noise burst on top of a
  sine chirp per beat, staccato ascending pair. Same shape Firefox Easy
  Screenshot uses for "copied to clipboard".
- Save keeps its ascending triad; Discard keeps its descending pair;
  new small ascending pair for Apply crop.

Chrome:
- Browser Back / Forward chevrons (M10 3 L5 8 L10 13 — two segments
  meeting at a point, no shaft) replaced with straight-arrow glyphs
  (line + arrowhead). Reads as a navigation arrow, not an angle bracket.

Bundled but not shipped separately — parent session OTA-signs and pushes.
2026-09-09 10:24:03 +02:00
Local Dev
882de1654f fix(theseus/net): sec-ch-ua client hints look like stock Chrome (Brave-style)
Cloudflare Bot Fight Mode / Turnstile flag 'UA claims Chrome but client
hints don't confirm it' as bot. Electron's default sec-ch-ua reads
'Chromium';v='130', 'Not(A:Brand';v='99' — no 'Google Chrome' brand
(that's closed-source Google branding open Chromium doesn't carry).
Combined with a UA that's already stripped of the Electron token
(stockChromeUA), the mismatch itself is the fingerprint. This is what
whybitcoincash.com and other CF-fronted sites tripped on: server
returned 503 to Theseus while returning 200 to any curl variant.

Brave, Vivaldi and Opera solved this the same way — ship their own
sec-ch-ua that INCLUDES Chrome-family brands so CF's allow-list catches
them. New applyClientHintsSpoof() registers a session-wide
onBeforeSendHeaders that rewrites the sec-ch-ua family on every
outbound request:
  sec-ch-ua:                'Google Chrome';v=<major>, 'Chromium';v=<major>, 'Not?A_Brand';v='99'
  sec-ch-ua-full-version-list: same trio with real Chromium version
  sec-ch-ua-mobile:         '?0'
  sec-ch-ua-platform:       actual OS name (Windows / macOS / Linux)

Major comes from process.versions.chrome so the story stays internally
consistent — nothing to fingerprint from a Chrome/version mismatch.
Runs alongside applyEmbedCookieShim which uses onHeadersReceived; the
two hooks are separate so no listener collision.
2026-09-09 03:27:41 +02:00
Local Dev
124325673f feat(theseus/settings): per-extension update info inline on the card
The Extensions page had a "Pending updates" strip at the top listing the
staged versions AND a "Check for updates" button that dumped a summary of
every extension's status into a global status blob just below the button.
Two places to look for what a single card was doing.

Fold both surfaces into the extension card itself:
- Each card grows a small update line under its description: green ↻
  "Update vX.Y.Z staged — restart to apply" when a staged tarball is
  waiting, red "Update failed" (with the addon-updater's detail) when
  the last check-updates run couldn't advance the version, plain "Up to
  date" when it could and there was nothing newer.
- The top strip is gone. The "Check for updates" button now just prints a
  one-line summary (N staged / N failed / all up to date) — the detail
  lives on each card.
- listStagedAddonUpdates fires on tab visit and after Reload, so the
  card badge reflects the background poll without needing the user to
  click Check.
2026-09-09 02:43:28 +02:00
Local Dev
0d583fb749 fix(theseus/addons): sidebar auto-restore on tab switch + more forgiving tar
Two follow-ups from user reports on the 0.5.x screenshot rollout:

- When the screenshot editor sidebar is maximized (fills the window) and
  the user hits New Tab / Settings / any address-bar nav that opens a
  different tab, the incoming tab was left invisible behind the sidebar.
  setActive now auto-restores the sidebar to its pre-max width whenever
  it detects a tab switch — the user can hit the maximize button again
  on the way back. Pure additive change, no other setActive semantics
  touched.

- The signed-add-on update pipeline failed the 0.5.0 tarball extract on
  a Windows 10 install with the built-in bsdtar: `tar --force-local -x
  -z -f …` — bsdtar doesn't recognise --force-local and errors out
  before it opens the archive. Try the extraction WITHOUT the flag
  first (safe with the posix-slash paths we already pass on every tar
  we care about — bsdtar, GNU tar, MSYS2 tar) and fall back to WITH
  --force-local only if the first invocation exits non-zero (MSYS2
  path where a bare `C:/…` gets parsed as a `host:` prefix). Original
  error message is surfaced on total failure so we can still tell what
  went wrong.
2026-09-09 02:38:32 +02:00
Local Dev
71b803e020 fix(theseus/screenshot): 0.5.1 — hide "Loading capture" for real + centre the tool bar
Two things the shipped 0.5.0 got wrong:

- `.empty { display: flex }` overrode the plain `[hidden]` attribute the
  init flow sets after the image draws, so the "Loading capture…" pill
  stayed visible on top of the finished capture. Global rule
  `[hidden] { display: none !important }` takes it out.

- Tool bar was left-aligned; older editor iterations grouped the drawing
  tools / swatches / widths / undo-redo in the centre of the bar, which
  read better in a narrow sidebar. Adds `.toolbar { justify-content: center }`;
  the topbar's back / max / sound / name / save / copy stay edge-anchored.

Version bump so the OTA update endpoint picks it up on the next tick.
2026-09-09 02:33:45 +02:00
Local Dev
c64e81a959 toolbar 30% ratio floor + placeholder-safe search + brand map for .x names
Toolbar drag handle now clamps both bars to at least 30 % of the
.urlsearch budget (URL: 30 %–70 %, search fills the rest). The
existing absolute mins (URL 220 px, search bumped from 140 → 180 px
so the 'Search' placeholder always fits) still apply — the tighter of
absolute vs 30 %-of-container wins at any width. .urlsearch also gets
margin-right: 10 px so the search bar has visible breathing room from
the trailing dock (Downloads / extensions / ⛓ Theseus).

Bookmark brand-case now uses a canonical map for multi-word Silent Mode
names so all-caps sources come out correctly cased: SILENTMODE.X →
SilentMode.X, silentmode.x → SilentMode.X, coinspectrum.x →
CoinSpectrum.X. Single-word brands (Theseus, Sirius, Deviant, Aegis,
Ariadne, Argus, Hermes, Prometheus, Hephaestus, Helios, Atlas,
Katalogos, Game, Poutakidis, Syskypo) are in the same map for
consistency. Unknown names fall back to Title-case (foo.x → Foo.X)
— the ALL-CAPS preserve rule is gone, so GAME.X → Game.X now,
matching the user's ask.
2026-09-09 02:25:12 +02:00
Local Dev
dcbe4d55f9 fix(theseus/bookmarks): brand-case .x TLD labels (theseus.x → Theseus.X)
Bookmark chip labels now normalise the .x TLD family to <Name>.X on
render:
  theseus.x      -> Theseus.X
  deviant.x      -> Deviant.X
  Sirius.x       -> Sirius.X
  foo-bar.x      -> Foo-bar.X
Names that were already ALL-CAPS keep their form so the visual weight
carries through:
  GAME.X         -> GAME.X (unchanged)
  SILENTMODE.X   -> SILENTMODE.X (unchanged)
Non-.x titles are untouched (CoinSpectrum, navigate.st, etc.). The
transformation runs after the descriptor trim, so titles like
'theseus.x — the browser…' also come out 'Theseus.X'.
2026-09-09 02:17:27 +02:00
Local Dev
8649bb97ea docs(theseus): draft wallet multi-account amendment
Amends DESIGN-integrated-wallet.md §0 ("one account per profile in v1") with
a formal path to supporting external key imports (BIP39 seeds and raw WIFs)
alongside the primary HD purpose-subtree. Motivated by the user's 15-wallet
Deviant chipnet keystore now encrypted under the same master-password model
that Theseus is designed around.

Key discipline:
- SEPARATE storage file (wallet-imports.enc), same PBKDF2/AES-256-GCM crypto,
  same master password, distinct KDF salt. Imports cannot compromise the
  primary seed and vice versa; corruption of one file does not damage the
  other.
- The imports schema mirrors Deviant's chipnet-keystore/1 shape (cashaddr /
  label / category / source / path / seed / wif) so import is a 1:1 field
  copy, not a translation.
- Every import stores the raw seed + BIP44 path (or the raw WIF) and derives
  addresses DIRECTLY via HDKey.fromMasterSeed, bypassing the vault's
  purposes/wallet HKDF subtree. This is essential: without the bypass,
  pasting a mnemonic re-hashes the seed through HKDF and produces DIFFERENT
  addresses than the source wallet (see memory
  bchwallet-vault-root-derivation).
- No bcnr.importWallet() ever; imports are settings-page only.
- Sign modal grows an account picker with category chips; per-origin
  "recently used" pre-selection with red-flag on category change.

Also introduces:
- bcnr.requestAccount({ account?, category? }) — backwards compatible
- bcnr.getAccounts({ category? })
- Stale-import detection (source-file cashaddr comparison on unlock)
- Sequencing: M.1 (generic import) → M.2 (import from Deviant keystore) →
  M.3 (API extensions) → M.4 (stale detection). M.1 is load-bearing;
  everything else composes.

Companion to Option A which shipped separately as the cross-repo fall-through
in Argus/src/lib/wallet.js.
2026-09-09 02:17:01 +02:00
Local Dev
30734847e9 fix(theseus): tab context menu goes native + bigger uniform bookmark chips with title-only labels
Two visible fixes from the same 2026-09-09 screenshot:

Right-click a tab was building a DOM menu and then growing the chrome
view height so it would fit under the tabstrip. That opened a
visible gap between the toolbar and the tab body while the menu was
up. Now the tab context menu goes through a new IPC
"tab-context-menu-popup" (main.js) that pops an OS-native Menu at
the click point, floating above every WebContentsView — no layout
change, no gap. Preload exposes tabContextMenuPopup(id, {x, y});
chrome.html's tab contextmenu handler now calls it directly and the
DOM openTabContextMenu / openGroupSubmenu / growChromeForMenu path
is bypassed for tabs. (The bookmark bar's own ctxmenu still uses
the DOM path — its short 2-3-row menus don't grow chrome enough
to be visible.)

Bookmark chips were too small (130px max-width, 11px text, 22px row).
Now every chip is a fixed 150px × 28px cell so the row reads as a
uniform grid, 12.5px text, 14px favicon. Labels drop the descriptor:
"GAME.X — Bitcoin Cash game platform" renders as "GAME.X". The
trimmer splits on the first em-dash / en-dash / hyphen that's
surrounded by whitespace, so single-word titles and hyphenated
compound names ("Foo-Bar" with no spaces) come through intact. Full
title still shows on hover.
2026-09-09 02:05:46 +02:00
Local Dev
ba806005fa fix(theseus/updater): re-add --force-run so Theseus auto-relaunches after silent install
install-update-now was spawning setup with ['/S'] alone since the
0.3.31 rewrite. That installs correctly (E2E-proven multiple times
this week) but leaves the user without a running browser after the
install completes — the setup exits, and the user has to click the
Start-menu shortcut to get Theseus back.

--force-run is electron-builder's NSIS convention for 'start the app
when the install finishes'; it makes the whole update feel like a
seamless in-place restart. --updated stays out (was proven not to
affect the install itself on our config).

Reported by user 2026-09-09 after 0.3.37 → 0.3.39 auto-update ran
cleanly but silently, with no post-install relaunch.
2026-09-09 00:58:26 +02:00
Local Dev
81d276f655 feat(theseus/screenshot): 0.5.0 — sidebar-first editor, direct save/copy, sounds
Two problems the old editor kept hitting:
- __pending drain race: opening the editor a second time (refresh, back-and-
  forth navigation) found the storage entry already consumed and bailed to
  a blank canvas silently.
- Cross-origin img loading: editor.html at file:///…/addons/screenshot/
  loading a scratch PNG at file:///…/addons-data/ counts as cross-origin
  under Chromium's file-URL policy; setting crossOrigin="anonymous" made
  the load fail outright.

Rebuilt editor v2:
- Load path is idempotent: silentmode.invoke("getBytes", {name}) → addon
  reads the scratch file and returns a data URL. No __pending drain, no
  cross-origin trickery — data: URLs are same-origin and never taint the
  canvas, so getImageData / toBlob keep working.
- Two-canvas model (#base + #over, over is pointer-events:none) so live
  previews don't cost a full re-composite per mousemove.
- Tools: cursor, arrow, rect, ellipse, pen, text. 6 swatches, 3 widths,
  undo / redo (25-deep). Copy + Save at the top bar. Back and Maximize
  buttons in the same top bar so navigation controls stay reachable when
  the toolbar wraps at narrow widths.
- Keyboard: A/R/O/P/T select tool, Esc = cursor, Ctrl+Z/Shift+Z undo/redo,
  Ctrl+S save, Ctrl+C copy.
- Toast surface for save/copy/error feedback.

Sidebar panel gains a direct raw-save path so the user can copy or save the
capture without entering the editor:
- Two-row actions: [Copy] [Save] on top, [Discard] [Edit] below.
- Copy uses navigator.clipboard.write(ClipboardItem); Save uses
  <a download> with a Blob URL — same path Chromium's will-download
  tracker already handles, so the file lands in Downloads and the chip
  updates like any other save.

Inline "clear all" confirmation replaces the native confirm() — the old
system-modal opened over the tab area (out of the sidebar's visual
context) and looked like Windows 95. Now a compact red strip appears
under the Recent header with Cancel / Delete buttons.

Sounds + a sound-on/off toggle in both surfaces:
- Web Audio oscillator-synthesized (no .wav shipped): shutter click on
  capture, two-tone bloop on copy, descending pair on discard/back,
  ascending triad on save.
- Preference stored in silentmode.storage under "soundOn" (default on),
  shared between the panel and the editor.

Simplifications:
- Dropped the addon's "arm" onMessage handler (superseded by getBytes).
- Manifest capabilities: sidebar-panel + capture-tab (no open-tab,
  no toolbar-menu).

Bundled but not shipped — parent session handles the OTA sign + push.
2026-09-09 00:56:41 +02:00
Local Dev
a65dc0a153 feat(theseus/devtools): 3-mode dock — bottom / sidebar / two-sidebars
New settings.devToolsDock (default 'bottom') read by the F12 handler
in main.js on each open. Values:
  bottom       - Chrome's own default, docked under the tab
  sidebar      - right-side dock (mode:right). Add-on sidebar tucks
                 out of the way while DevTools is up.
  two-sidebars - right-side dock with the add-on sidebar left in
                 place, so both share the right area.

Settings > General > Developer tools now hosts a 3-option radio group
(same .polrow style as the collision policy). Changes apply instantly
- the F12 handler reads settings.devToolsDock every time it opens, so
no relaunch is needed.
2026-09-09 00:51:05 +02:00
Local Dev
d7d4e7eb4e 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
Local Dev
e36d2b361c feat(theseus/toolbar): Firefox-style single drag handle, zero-sum URL/search ratio
The two independent drag handles (right edge of URL bar, left edge of
search bar) are replaced with ONE handle sitting between them, wrapped
in a new .urlsearch flex container that owns the URL-bar-plus-search-bar
budget between the nav buttons on the left and the trailing dock on the
right.

Zero-sum semantics: dragging the handle right grows the URL bar and
shrinks the search bar; dragging left inverts. Nothing else in the
toolbar moves — nav buttons, Downloads, extension dock and the
⛓ Theseus logo all sit outside .urlsearch's flex parent.

When the window shrinks below the responsive breakpoint the search
bar (and the drag handle) hide as before, and the URL bar grows to
fill the .urlsearch budget on its own (added flex: 1 1 auto in the
data-responsive rules for .urlwrap).

Verified static rendering: url=700px → search=157px, url=300px →
search=539px, url=default → 60/40 split, narrow window → search
hidden and url fills.

Old settings (urlBarSize / searchBoxSize / searchBoxWidthPx) are
ignored by chrome.html but kept in main's SETTINGS_DEFAULTS so an
older chrome.html could still read them on a downgrade. Only
urlBarWidthPx is used going forward.
2026-09-09 00:11:26 +02:00
Local Dev
71bd3004e0 feat(theseus/settings): Plug-ins section — Ariadne's Thread + Aegis moved out of General
New sidebar tab between Privacy and Extensions. The two long
system-scoped cards (Ariadne's Thread system-wide resolver, Aegis
built-in wallet) were bloating the General section; they cluster
naturally as "components that live alongside Theseus, each with
install/update/on-off controls of their own" and now have their
own home.

- Adds <a data-sec="plugins">Plug-ins</a> to nav.side
- New <section id="plugins"> with a short lede
- Ariadne + Aegis row blocks moved from General to Plug-ins verbatim
- sections array in showSection() extended with "plugins"
- Tab-switch handler clicks ariadneRefresh so status is never stale;
  Aegis card auto-loads on page-init and its "Check for updates"
  button stays user-initiated (avoid firing a network request every
  time the user opens the Plug-ins tab)
2026-09-08 23:00:41 +02:00
Local Dev
1b10afa1ca feat(theseus/aegis): canonical coin logos from cryptocurrency-icons
Replace the hand-drawn approximations with the official SVGs from
github.com/spothq/cryptocurrency-icons — the permissive-licensed set most
exchanges, block explorers, and other wallets standardised on. Users see
the same BCH / BTC / DGB / SC / TRX / ETH / SOL marks in Aegis they
already recognise from Coinmarketcap, Coingecko, Trezor, MetaMask, etc.

- BCH: green disc with the tilted Bitcoin-Cash B
- BTC: orange disc with the classic Bitcoin B glyph
- DGB: blue disc with the DigiByte D + swash
- SC:  brand-green disc with Siacoin's stylised S
- TRX: red disc with the geometric Tron triangle-net
- ETH: purple disc with the two-triangle Ethereum rhombus
- SOL: mint disc with the three-slash Solana mark

All SVGs are inlined in panel.js — no network fetches at panel load.
Bumped addon 0.4.3 → 0.4.4 so seedBundledAddons reseeds the new panel
on next launch.
2026-09-08 22:47:43 +02:00
Local Dev
344c71b315 fix(theseus/aegis): drop registerSidebarPanel icon override so dock inherits brand shield
The toolbar dock still showed the 🛡 emoji even after chrome.html learned
to render data-URI icons — because registerSidebarPanel({icon}) is the
per-panel icon that overrides manifest.icon, and Aegis was passing "🛡"
verbatim. Dropping the override lets addons-host's `icon = manifest.icon`
default kick in, so the dock button pulls the branded aegis.x/brand
shield the manifest now advertises.

Version bumped 0.4.1 → 0.4.3 to force seedBundledAddons to reseed the
new index.js on next launch.
2026-09-08 22:40:48 +02:00
Local Dev
8047d84c47 Ship Theseus 0.3.35 4a7bd82f (proves 0.3.34 self-update path E2E)
Version bump only, no code changes. Published to prove the just-shipped
0.3.34 install can auto-update itself using the reverted-to ["/S"]
spawn code.

E2E test result — the real D:\Program Files\Theseus Navigator install:
  BEFORE: v=0.3.34, hash e59d6da2..., mtime 09/08 22:02:46
  AFTER:  v=0.3.35, hash 420b7320..., mtime 09/08 22:31:18
  Registry updated at same D:\ path
  Post-install proc count 0 (no --force-run in the current code, as designed)

Second confirmation this session that install-update-now's ["/S"]-only
spawn (unchanged since 0.3.1) does the right thing against a real
install at a path with spaces.

Installer: 4a7bd82f30a00a6795670d0a48cf590832fd077d84726966d8fbea04fc23be1b
Portable:  138c03ad21cb6fb2a6a7f89cc726adee618622c11eb58177857fa24afa955e47
2026-09-08 22:36:50 +02:00
Local Dev
523832cd72 feat(theseus/screenshot): 0.4.0 — editor lives inside the sidebar, maximizable
User report: the sidebar preview lands correctly, but the moment the editor
opens in its own tab the picture is blank. Rather than chase that class of
handoff race again, put the editor in the same webContents as the panel:
the sidebar view navigates panel.html ↔ editor.html in place. Same
document object, same silentmode.storage surface, no cross-tab __pending
transfer at all.

- panel.html "Edit" button now calls silentmode.invoke("arm", …) — the
  add-on rewrites __pending with the currently-previewed capture's bytes,
  and the panel does location.href = "editor.html?name=…". Sidebar view
  loads the editor with the same preload; editor.js's storage-based load
  path pulls the pending entry out and paints.
- editor.html gains a "Back" arrow (returns to panel.html) and a
  maximize / restore icon.
- discard() now navigates to panel.html instead of closeTab() — there is
  no tab to close.
- Manifest drops the "open-tab" capability entirely (no more full-tab
  editor); keeps sidebar-panel + capture-tab.

Framework: new silentmode.sidebar.{maximize, restore, toggleMax, isMax,
onMaxChange}. main.js honours them via new sidebar-maximize / -restore /
-toggle-max / -is-max IPCs, remembering the pre-maximize width so a
restore drops back exactly. The sidebar drag-grip auto-exits maximize
mode on any user drag, so pulling the edge always lands on the pre-max
value plus/minus the delta. sidebar-preload exposes the surface;
chrome.html renderer is untouched — this is a per-panel affordance.

Editor tools (crop / arrow / rect / ellipse / pen / text / mosaic /
undo / redo / copy / save) unchanged. Save still goes through Chromium's
<a download> path, so the file lands in Downloads and appears in the
download chip like any other save.

Bundled but not shipped — leaving version bump + deploy to parent session.
2026-09-08 22:18:41 +02:00
Local Dev
1b74195298 bump theseus 0.3.34 for the real-install auto-updater E2E test 2026-09-08 22:03:04 +02:00
Local Dev
3e784e299c Theseus 0.3.31 rewrite — UI improvements + defensive hash-verify, spawn flags unchanged
Same 0.3.31 version, new binary. Rebuilds the shipped 0.3.31 with the
salvageable content from the reverted 0.3.32-0.3.34 track:

  chrome.html
    - light-mode chrome strip: --bg #e6e8ec, inactive tab #f2f4f7,
      active tab #ffffff. Fixes the "tabs disappear into the light
      Windows title bar" report.
    - bookmark chips shrunk: 130px max-width, 11px text, 12px favicon,
      22px row (was 26). ~40% more chips fit in the same width.
    - bookmark chips draggable with the tab-strip's left/right-half
      drop convention; new .dropbefore/.dropafter accent.
    - light-mode .tor + .logo + .upchip chips: from illegible white-
      on-#253A49 (at 12-13px) to #eef1f5 with #253A49 ink. Both readable
      now. .tor.connecting/.on keep amber/purple hue in light fills.

  main.js
    - will-download update handler now streams the saved setup .exe
      through crypto.createHash("sha256"), compares to the manifest's
      updateAvailable.setupHash before marking ready. Rejects and
      deletes the file on mismatch or on empty manifest hash. Test C
      in the previous session proved this catches truncated payloads
      Electron reports as "completed" (a real class of failure the
      Ariadne addon updater has always guarded against here).
    - new bookmark-move IPC: splices the list, no-ops on self-drop
      or missing entry.

  preload.js
    - moveBookmark(fromUrl, targetUrl, place) exposed for chrome.

Deliberately NOT changed: install-update-now still spawns setup with
["/S"] alone. The 0.3.32 --updated /S --force-run change was proven
in the previous session's real-install E2E to not address the actual
"browser vanished on D:\Program Files install" symptom — every flag
combination (/S alone, --updated /S --force-run, /S /currentuser,
/S /D=<install>) exits 0 without upgrading anything on that specific
install path. That's a separate open bug; not touched here.

Version stays 0.3.31 — this is a binary rewrite of 0.3.31, not a new
release. Existing 0.3.31 installs won't see an update chip (version
compare returns false), which is intentional given the auto-update
path is still broken for non-default install locations.
2026-09-08 21:26:42 +02:00