<feed xmlns='http://www.w3.org/2005/Atom'>
<title>meshbay.git/packages/meshbay-hub/tests/test_playlist_store.py, branch 0.16</title>
<subtitle>MeshBay — read-only public mirror</subtitle>
<id>https://git.meshbay.org/meshbay.git/atom?h=0.16</id>
<link rel='self' href='https://git.meshbay.org/meshbay.git/atom?h=0.16'/>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/'/>
<updated>2026-09-16T15:51:19Z</updated>
<entry>
<title>playlists: promise the count that holds when nothing compresses</title>
<updated>2026-09-16T15:51:19Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-09-16T15:51:19Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=929bfcccf8928a30d86d48a8b0137db0dd4a1ee0'/>
<id>urn:sha1:929bfcccf8928a30d86d48a8b0137db0dd4a1ee0</id>
<content type='text'>
The ceiling is 1200 tracks on a library that repeats and 660 on one that
never does; the message said 1000, which would send a reader back into the
wall at 660. It says 500, measured at both ends.

Co-Authored-By: Claude Opus 5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>playlists: refuse a body no frame can carry, and say which one</title>
<updated>2026-09-16T15:47:00Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-09-16T15:47:00Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=c35f3a73eb68cdd7c4179cded3d1ead63ec5a033'/>
<id>urn:sha1:c35f3a73eb68cdd7c4179cded3d1ead63ec5a033</id>
<content type='text'>
A DataChannel send() throws above the max-message-size the node advertises
(aiortc: 65536), so the 1 MB body cap was unreachable and each body push
swallowed the difference in a bare catch. Cap at 62 KB after sealing, name
the playlist in the sync result, keep syncing the rest.

Measured: 1000 tracks seal to 53 276 bytes, so the ceiling is ~1200.

Co-Authored-By: Claude Opus 5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>playlists: make the writes actually leave the browser</title>
<updated>2026-09-16T14:07:18Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-09-16T14:07:18Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=2916aa376009283305a7acec4aafa3c96544499e'/>
<id>urn:sha1:2916aa376009283305a7acec4aafa3c96544499e</id>
<content type='text'>
Reported from a phone: signing in with the same account showed no
playlists. syncWith was called from exactly one place in the interface,
so creating a playlist, deleting one, removing a track and saving the
queue all wrote to IndexedDB and stopped there. The store pushes itself
now, coalesced, so a new mutation cannot forget to.

Silence was the real defect. The node audited only successes, so a
refusal left no trace and user_blob_list none at all; the background
push swallowed its reason; the interface said nothing. All three report
now, and "Sync now" says what happened either way.

An unreadable blob on a node was treated as a fetch failure and returned
before the push — permanent, once the node held anything. It is an
absence: the client is the authority, and it gets overwritten.

A sign-in reconciles whatever this browser already holds, a pending push
is flushed when the page goes away, and a push that did not land is
retried once.

no_key is spelled out: a client that signs in with its remembered device
key only ever has a bundle key persisted before the playlist subkey
existed, and an AES handle is non-extractable.

Co-Authored-By: Claude Opus 5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>playlists: the store, and putting it on nodes</title>
<updated>2026-09-16T09:52:03Z</updated>
<author>
<name>Christophe Besson</name>
<email>cbesson@gmail.com</email>
</author>
<published>2026-09-16T09:52:03Z</published>
<link rel='alternate' type='text/html' href='https://git.meshbay.org/meshbay.git/commit/?id=2e973795383b71f63ae9e3bef0e5dfc7930b4c90'/>
<id>urn:sha1:2e973795383b71f63ae9e3bef0e5dfc7930b4c90</id>
<content type='text'>
playlists.js is IndexedDB, WebCrypto and a transport, and node has no
IndexedDB — so it is driven in Chrome against a node stubbed to record
what it was handed, which is also how what leaves the browser is
checked to be sealed.

Sync asks the node what it holds (user_blob_list) rather than comparing
against the merged watermark, which says nothing about that node: the
first version pushed every body on every sync. A tombstoned playlist's
body is deleted as each node is reached, or the quota fills with graves.

The database version and its stores stay in hub-client.js — two modules
opening one database at versions of their own is a VersionError thrown
at whichever runs second.

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