diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-09-30 15:06:14 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-09-30 15:06:14 +0200 |
| commit | 91297944791a36f30302ef8c86dd69ebeb177671 (patch) | |
| tree | 568188114baf438059458f1bc87903f4894cec90 /packages/meshbay-hub/tests/test_playlist_store.py | |
| parent | a55d40b74bda77dff6ec565abdd551607fc665d6 (diff) | |
| download | meshbay-91297944791a36f30302ef8c86dd69ebeb177671.tar.gz | |
feat: bundles sealed per node under the passphrase and the hub's pepper
The session key is M = HKDF(Argon2(passphrase) || pepper, account id); each
node's bundle key and the playlist key derive from it. Bundles are MBK3, bound
to account and node; MBK1/MBK2 are refused by name, never replaced silently.
Playlists move to key v2 and are re-sealed over unreadable node copies.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-hub/tests/test_playlist_store.py')
| -rw-r--r-- | packages/meshbay-hub/tests/test_playlist_store.py | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/packages/meshbay-hub/tests/test_playlist_store.py b/packages/meshbay-hub/tests/test_playlist_store.py index 701de41..3c1d109 100644 --- a/packages/meshbay-hub/tests/test_playlist_store.py +++ b/packages/meshbay-hub/tests/test_playlist_store.py @@ -272,16 +272,25 @@ def test_a_node_holding_something_unreadable_does_not_wedge_the_sync(steps): assert "Depuis le menu" in s["names"] -def test_a_session_from_before_the_hkdf_handle_degrades_rather_than_failing(steps): - """A bundle key loaded out of IndexedDB from before `deriveBundleKeys` - existed has no HKDF handle, and the passphrase is not in memory to - re-derive from. Playlists stay local until the next sign-in — reported, - rather than silently doing nothing.""" - r = steps["a session from before the HKDF handle"]["result"] +def test_a_session_from_before_the_pepper_degrades_rather_than_failing(steps): + """A bundle key from before the pepper opens nothing, and the passphrase + is not in memory to re-derive from. Playlists stay local until it is + entered again — reported, rather than silently doing nothing.""" + r = steps["a session from before the pepper"]["result"] assert r["ok"] is False and r["reason"] == "no_key" assert r["pushed"] == 0 +def test_a_node_sealed_under_the_previous_key_is_sealed_again(steps): + """After the playlist key changed, every row on a node has the revision the + local copy has. All of it is sealed again under the current key, no + revision goes down, and a body nothing here can name is dropped.""" + s = steps["a node sealed under the previous key"] + assert s["readable"] == s["kinds"], "a row is still sealed under the old key" + assert s["remaining"] == s["kinds"], "the unknown body was not dropped" + assert s["revsNotLowered"] is True + + def test_what_a_playlist_costs_sealed_is_measured_not_quoted(steps): """The ceiling the UI promises comes from here, not from the design doc. |