<feed xmlns='http://www.w3.org/2005/Atom'>
<title>meshbay.git/packages/meshbay-hub/tests, branch 0.18</title>
<subtitle>MeshBay — read-only public mirror</subtitle>
<id>https://git.meshbay.org/meshbay.git/atom?h=0.18</id>
<link rel='self' href='https://git.meshbay.org/meshbay.git/atom?h=0.18'/>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/'/>
<updated>2026-10-05T11:13:54Z</updated>
<entry>
<title>feat(hub): say "N groups unreachable" on Search for a few seconds, not for good</title>
<updated>2026-10-05T11:13:54Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-10-05T11:13:54Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=92b7afcb186d7aaf475939d58a0385f408425eeb'/>
<id>urn:sha1:92b7afcb186d7aaf475939d58a0385f408425eeb</id>
<content type='text'>
The line sat above the results for as long as the page was open. It is now
said once a cross-group pass is over, for five seconds, in the same passing
note as "Link copied" — moved out of copy-link.js into note.js (`say(text,
ms)`), one note at a time for the whole page. The `.search-unreachable` rule
goes with the line it styled.

The copy-link probe now also checks in Chrome that the note goes by itself.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>test(hub): join from an invitation link and land under the group's handle</title>
<updated>2026-10-05T10:53:48Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-10-05T10:53:48Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=97fa4cf78a826050b9d1df0b484a7794861cda80'/>
<id>urn:sha1:97fa4cf78a826050b9d1df0b484a7794861cda80</id>
<content type='text'>
The invitation probe listed no groups, so after Join the address stayed the
#/group/&lt;id&gt; the button navigated to and the group links' rewrite to
#/name@owner was never exercised on that path. A third case has the hub list
the group once joined, as it does: the group page opens, the address shows
the handle without a history entry of its own, and the code still never
reaches the hub.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat: copy a file's or folder's #/name@owner link from Files, Music, Photos and Search</title>
<updated>2026-10-05T10:23:18Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-10-05T10:23:18Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=1d94a92936abb3d37a8f9bfb36c8850246fee15d'/>
<id>urn:sha1:1d94a92936abb3d37a8f9bfb36c8850246fee15d</id>
<content type='text'>
"Copy link" puts the address group-link.js resolves on the clipboard, on the
hub's origin rather than the page's, so a link copied in the desktop
application is not app://meshbay. Files offers it for one row, from the
right-click menu or the toolbar with one row ticked (a phone's way in);
Music on one track's menu, whose dots a phone has; Photos on a right-clicked
tile and in the lightbox's bar. The video player and the file preview carry
a link button next to Download.

Applications get a `linkFor(entry | folderPath)` prop (MESHBAY_DESIGN.md
§9.2) and offer the action only when it names a link. The group page builds
it from the hub's row; Search from each result's own group and its path
before the merged views prefixed it, and names no link for a folder of the
merged tree, which a group name alone does not identify.

harness/copy_link_probe.py mounts the three applications in Chrome and reads
what reached the clipboard.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat: open a group, a folder or a file from a #/name@owner link</title>
<updated>2026-10-05T09:53:57Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-10-05T09:53:57Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=8f25294b0f6bc3f292442edd69a2e149f0717b52'/>
<id>urn:sha1:8f25294b0f6bc3f292442edd69a2e149f0717b52</id>
<content type='text'>
A group can now be reached by the handle shown under its name, and a path
after it points inside the group: #/name@owner/root/dir/file downloads the
file and opens Files on its folder; a folder opens Files there. The handle
is resolved in the client against the account's own /v1/groups/mine, so no
hub route answers for a name and nobody can probe for one. While a group is
open the address shows the handle (replace, no history entry); a linked path
is taken out of the address once acted on, so a reload does not download
twice.

Signing in no longer sends everyone home: the form stood in for the page the
address named, and that is where a link opened signed out was going.

group-link.js holds the parsing and lookups, executed whole by
test_group_link.py; harness/group_link_probe.py drives the router in Chrome.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>fix: list as members only the accounts the node has admitted</title>
<updated>2026-10-05T09:27:20Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-10-05T09:27:20Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=28752696f376eb11feb686580a435b166750a723'/>
<id>urn:sha1:28752696f376eb11feb686580a435b166750a723</id>
<content type='text'>
The Members list showed the hub's membership, which an account gains when it
accepts the invitation or redeems a link, before it has presented its code to
the node. The node's roster is the authority (MESHBAY_DESIGN.md §3.4), so
the list now crosses the hub's members with the sealed group roster the node
already sends every connected member. An account the node has not admitted
yet is shown to the owner alone, as waiting for its code, with the Remove
button; other members do not see it. When the roster cannot be read, the
hub's list is shown as before.

groupRoster() takes { fresh: true } so the page sees who joined since the
connection opened.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>docs: generate an HTTP API listing for the hub and the node control API</title>
<updated>2026-10-05T08:36:18Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-10-05T08:36:18Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=b8671635cd891068afee81fde05bed880124ec85'/>
<id>urn:sha1:b8671635cd891068afee81fde05bed880124ec85</id>
<content type='text'>
docs/MESHBAY_HTTP_API.md lists every route of the hub (by domain, with the
authentication each requires) and of the node's loopback control API. It is
written by docs/generate_http_api.py from the routes and their docstrings;
test_http_api_doc.py fails when the file drifts from the code or when a
route has no docstring, so a new route must say what it does.

79 routes had no docstring and get a one-line description; a few whose first
line did not describe the route get a summary line.

The login page's developer docs gain an API link next to Design and
Protocol, in every language. README, MESHBAY_DESIGN.md (§0.1, §6.7, §7) and
CLAUDE.md point to the listing; README also points to examples/.

The examples scripts with a shebang become executable.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat(cast): music on the TV, the music bar as its remote</title>
<updated>2026-10-05T00:29:27Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-10-05T00:29:27Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=ee9798fe3b88face2fa34f14874770f509c788a5'/>
<id>urn:sha1:ee9798fe3b88face2fa34f14874770f509c788a5</id>
<content type='text'>
A cast button in Music's toolbar and in the music bar. With a television
chosen, each decrypted track goes to the relay with its cover — found as the
album card finds it — and plays there as music with its title, artist and
album; the bar's play, pause, seek, previous and next drive the receiver, its
clock is the receiver's, and the end of a track there moves the queue on.
A film or a photo taking the television pauses the bar; stopping the cast
carries the track on locally.

Photos and tracks now share one path: a whole file sent to the relay in
pieces (binary frames on Android, written to disk there), served at /file
with byte ranges and its cover at /cover, and loaded as what the relay says
it is. cast:image is gone; cast:chromecast:seek is new.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat(cast): photos on the TV, and a television chosen once for the session</title>
<updated>2026-10-04T23:16:12Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-10-04T23:16:12Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=243bcf017b4957237b3ddf556bd0a37296eb8798'/>
<id>urn:sha1:243bcf017b4957237b3ddf556bd0a37296eb8798</id>
<content type='text'>
A cast button in Videos' toolbar, at the top of Photos, in an album's bar and
in the lightbox, in a group and in Search alike. A television chosen there is
kept for the session: a film opened plays on it with the player as its remote
from the start, and a photo opened in the lightbox is shown on it, scaled to
1920x1080, upright, as JPEG. The lightbox gains a slideshow.

The relay serves one photo at /image behind the stream's token, on the desktop
and on Android; the shell, not the page, decides that the receiver loads it as
a picture.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>feat(android): music keeps playing with the screen off</title>
<updated>2026-10-04T20:46:00Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-10-04T20:46:00Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=652465910dcdcc761aa2e078ff1a82625e2a0aa5'/>
<id>urn:sha1:652465910dcdcc761aa2e078ff1a82625e2a0aa5</id>
<content type='text'>
While a track plays, the page asks the shell to stay awake
(playback:keep-alive): on Android the cast's foreground service and
visible WebView, with a notification; on desktop a power save blocker.

Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>Player: redesigned cast remote</title>
<updated>2026-10-03T12:24:55Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-10-03T12:12:39Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=3a9f18aaa55df75e0ad91c4b3e2f2eb47369feda'/>
<id>urn:sha1:3a9f18aaa55df75e0ad91c4b3e2f2eb47369feda</id>
<content type='text'>
Skip buttons with circular arrows, filled scrubber, large play/pause,
device header; the remote is its own component.

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