From 91297944791a36f30302ef8c86dd69ebeb177671 Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Wed, 30 Sep 2026 15:06:14 +0200 Subject: 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 --- packages/meshbay-hub/tests/harness/playlist_ui_probe.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'packages/meshbay-hub/tests/harness/playlist_ui_probe.py') diff --git a/packages/meshbay-hub/tests/harness/playlist_ui_probe.py b/packages/meshbay-hub/tests/harness/playlist_ui_probe.py index c705244..6e3be1e 100644 --- a/packages/meshbay-hub/tests/harness/playlist_ui_probe.py +++ b/packages/meshbay-hub/tests/harness/playlist_ui_probe.py @@ -173,12 +173,11 @@ const clickMenu = async (i) => { try { await initLocale(); - // A real HKDF handle, so the store derives its key the way it really does. + // A real master key, so the store derives its key the way it really does. const raw = new Uint8Array(32).fill(3); session.bundleKey = { - v2: await crypto.subtle.importKey('raw', raw, { name: 'AES-GCM' }, false, - ['encrypt', 'decrypt']), - v2hkdf: await crypto.subtle.importKey('raw', raw, 'HKDF', false, ['deriveKey']), + v3: await crypto.subtle.importKey('raw', raw, 'HKDF', false, ['deriveKey', 'deriveBits']), + pepperVersion: 1, }; // Deleting a playlist asks, in the page (ask.js) — so the probe answers the // dialog the way a person would, by clicking its OK button. -- cgit v1.2.3