<feed xmlns='http://www.w3.org/2005/Atom'>
<title>meshbay.git/packages/meshbay-client, branch 0.7</title>
<subtitle>MeshBay — read-only public mirror</subtitle>
<id>https://git.meshbay.org/meshbay.git/atom?h=0.7</id>
<link rel='self' href='https://git.meshbay.org/meshbay.git/atom?h=0.7'/>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/'/>
<updated>2026-08-22T16:26:22Z</updated>
<entry>
<title>feat(node): systemd service panel on the Node page, and a clean CLI restart</title>
<updated>2026-08-22T16:26:22Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-08-22T16:26:22Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=8dc11dc05a35a5d64ba4d2c892ccc01c7bfae3da'/>
<id>urn:sha1:8dc11dc05a35a5d64ba4d2c892ccc01c7bfae3da</id>
<content type='text'>
Add a status panel at the top of the Node page — always visible, even
before an MNP connection exists — showing the meshbay-node systemd
unit's own state (via `systemctl --user show`, main process only) with
Start/Stop/Restart controls. This is the piece the rest of the page
cannot provide: it has to work while the daemon is stopped or crash-
looping, which the MNP-based sections require the daemon to already
answer.

While touching node lifecycle: `reload` and `restart-daemon` in the
CLI shelled out to pgrep + SIGTERM/SIGHUP and respawned the process by
hand, logging to a hardcoded /tmp path. That pattern already SIGHUPed
a developer's own running node by accident once (see the old
test_cli_dispatch.py comment). Both now delegate to
`systemctl --user reload|restart meshbay-node`, which the unit already
supports correctly (ExecReload=, Restart=on-failure).

Co-Authored-By: Claude Sonnet 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_016SF6RKNBKg9qejmoMJ9ybA
</content>
</entry>
<entry>
<title>fix: first-run wizard reliability and node startup performance</title>
<updated>2026-08-22T14:40:54Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-08-22T14:40:54Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=9c136a0e37add42f5d0c8675a797969cfe690de0'/>
<id>urn:sha1:9c136a0e37add42f5d0c8675a797969cfe690de0</id>
<content type='text'>
Node daemon no longer blocks startup on slow directory scans — initial
indexing runs in the background so the node reaches "running" immediately
after transports are up. Fixes the wizard failing to detect the node when
large USB/NAS roots take minutes to scan.

Also: wizard key-linking deadlock resolved (main.js links during poll),
invite form stays in DOM during reconnects (disabled instead of destroyed),
pairing code bridges to renderer, and firewall docs for LAN casting added.

Co-Authored-By: Claude Opus 4.6 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>fix: find meshbay-node in ~/.local/bin when not in PATH</title>
<updated>2026-08-22T10:37:35Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-08-22T10:37:35Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=2dbd70484e65ae57e18c323381136077cd00adad'/>
<id>urn:sha1:2dbd70484e65ae57e18c323381136077cd00adad</id>
<content type='text'>
Electron does not run in a login shell, so ~/.local/bin is not in PATH
and `which meshbay-node` fails. Check that well-known location first
in both node:installed and the node:start fallback.

Co-Authored-By: Claude Opus 4.6 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat: node:start auto-provisions config and unlock key</title>
<updated>2026-08-22T10:29:32Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-08-22T10:29:32Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=6d1ece3156c3ee7ce3fe1c19aabeb45b34d6436a'/>
<id>urn:sha1:6d1ece3156c3ee7ce3fe1c19aabeb45b34d6436a</id>
<content type='text'>
When the wizard calls node:start with {hubUrl, username}, the handler
writes a minimal node.toml and a random unlock.key if they don't exist.
The daemon then creates the keystore on first start using the unlock
file — fully non-interactive.

Existing configs are left untouched: if node.toml or unlock.key already
exist, provisioning is skipped and the node starts as before.

Co-Authored-By: Claude Opus 4.6 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>docs: add npm 11 Electron setup steps to meshbay-client README</title>
<updated>2026-08-22T09:09:22Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-08-22T09:09:22Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=4a350362a4819e8acf2bd85149c42703b0af0b37'/>
<id>urn:sha1:4a350362a4819e8acf2bd85149c42703b0af0b37</id>
<content type='text'>
npm &gt;= 11 blocks install scripts by default. Document the
approve-scripts + manual install + chrome-sandbox SUID steps.

Co-Authored-By: Claude Opus 4.6 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>fix: move meshbay-client build scripts out of gitignored build/ dir</title>
<updated>2026-08-22T09:02:15Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-08-22T09:02:15Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=3b677af830672759198a0bb8167b4929a9afd997'/>
<id>urn:sha1:3b677af830672759198a0bb8167b4929a9afd997</id>
<content type='text'>
The root .gitignore ignores build/ (Python convention), which silently
prevented sync-ui.js and its companion index.html from being committed.
Rename to scripts/ so the files are tracked normally.

Co-Authored-By: Claude Opus 4.6 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat: D.6 first-run wizard — detect, start, link, group, gek-init, pair</title>
<updated>2026-08-21T15:50:08Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-08-21T15:50:08Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=73490d331179cb640828b8625abb75208cd7ae5f'/>
<id>urn:sha1:73490d331179cb640828b8625abb75208cd7ae5f</id>
<content type='text'>
Desktop client guides new users through the full onboarding sequence
without a terminal: detect local node → start daemon (systemd with
direct-start fallback for dev) → link node key to hub → create group →
attach directories → gek-init → operator pair.

- node:detect returns configured field to distinguish missing vs stopped
- node:start tries systemctl first, checks is-active, falls back to
  spawning the binary directly when the unit crashes (dev mode)
- probeNode() extracts the shared config→token→fetch pattern
- SetupWelcome on empty HomePage links to /create-group
- CreateGroupWizard step 0 handles node detection and start
- platform.js exposes node.installed() and node.start()
- 12 setup.* i18n keys added to all 10 locales
- Integration test for node:start fallback logic

Co-Authored-By: Claude Opus 4.6 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat: LAN Wi-Fi casting to Chromecast via local HTTP relay</title>
<updated>2026-08-21T11:52:11Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-08-21T11:52:11Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=8730281d739d9ed1d6f2d366772582eea8ba0294'/>
<id>urn:sha1:8730281d739d9ed1d6f2d366772582eea8ba0294</id>
<content type='text'>
Re-serve decrypted fMP4 video over HTTP on the LAN so a Chromecast can
play the stream. The relay runs in the Electron main process — same trust
boundary as downloads and MSE playback.

- cast-relay.js: HTTP server with BoxAccumulator (reassembles WebRTC
  chunks into moof+mdat pairs), ring buffer, backpressure, finish() for
  clean end-of-stream, fixed port range 19550-19553
- cast-chromecast.js: mDNS discovery (bonjour-service) + CASTV2 protocol
  (castv2-client), connect/reload/disconnect lifecycle
- Seek-aware: relay restarts on every seek, Chromecast reloads new URL;
  generation counter prevents stale async errors from killing active
  restarts; landingPlayheadRef suppresses programmatic seeking events
- Device picker in video top bar with scan, device selection, copy-URL
  fallback, and cast status indicator
- IPC bridge (main/preload/platform) for start/push/stop/finish/status/
  discover/chromecastConnect/chromecastReload/chromecastDisconnect
- Phase 3 design doc for DLNA/Smart TV in docs/cast-smart-tv.md

Co-Authored-By: Claude Opus 4.6 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat: unified group management, public groups, and activity-based sidebar</title>
<updated>2026-08-20T20:21:19Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-08-20T20:21:19Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=2e9490ca27047ae03e495d397abbe1aec1b2273a'/>
<id>urn:sha1:2e9490ca27047ae03e495d397abbe1aec1b2273a</id>
<content type='text'>
Create Group wizard (Electron-only) consolidates 6 steps across 4 interfaces
into a single multi-step page: group creation on hub, node attachment, root
selection via folder picker, GEK initialization, and auto-pairing — all in one
flow. Browser SPA keeps its current behavior unchanged.

Public group support (Option A — GEK for all groups):
- All groups have GEK regardless of visibility; open-join groups auto-admit
  via TOFU when join_policy is "open"
- Key rotation blocked for public groups (API guard + UI hidden)
- Hub signaling allows WebRTC offers for nodes hosting open-join groups even
  when the caller isn't a member yet
- attach_group writes join_policy to node.toml
- Daemon loads GEK for all groups, not just private ones
- Known-device path in join_request now auto-admits to open-join groups

Node loopback API bridge (Electron IPC):
- node:detect, node:call, node:pairing-code IPC handlers in main process
- Renderer never sees tokens, paths, or keys (session token = physical access)
- platform.js node namespace for UI consumption
- Loopback endpoints: roots CRUD, member-upload toggle, reload

Bug fixes:
- Root change detection: removed premature ctx["roots"] updates from add_root
  and remove_root that prevented indexer retarget on reload
- Duplicate offline message: global fallback now gated on !group
- Signaling membership check: fallback to open-join groups for non-members

Sidebar groups sorted by last_activity_at (most recent first):
- New Group.last_activity_at column with Alembic migration
- POST /v1/groups/{id}/activity endpoint, called on connect and chat send
- Client-side sort + throttled hub updates (1/min)

Co-Authored-By: Claude Opus 4.6 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat(node): full Node admin panel — CLI parity, hot-reload, group lifecycle</title>
<updated>2026-08-20T06:56:23Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-08-20T06:56:23Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=c8af746c846b5dbc792f7e4f0d806647d513cc5c'/>
<id>urn:sha1:c8af746c846b5dbc792f7e4f0d806647d513cc5c</id>
<content type='text'>
Node admin panel (NodePage) now covers every CLI operation over MNP:
group attach/detach, roster, member unpin, GEK rotate, denylist, reload.

Daemon hot-loads new groups and tears down removed ones on config reload
instead of requiring a full restart. Group attach/detach via MNP or
local API triggers an automatic reload so the group is live immediately.

Fixed GroupPage hang on first visit to a newly created group: the JWT
issued at login didn't include the new group, the node rejected with
not_a_member, and the token-refresh path returned without re-triggering
the connect effect (Boolean(token) didn't change). Now bumps retryKey
after a successful refresh so the effect re-runs with the fresh token.

NodePage marks groups hosted by the node but absent from the hub with a
"not on hub" badge so stale groups are visible and easy to remove.

Co-Authored-By: Claude Opus 4.6 &lt;noreply@anthropic.com&gt;
</content>
</entry>
</feed>
