diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-09-30 16:58:31 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-09-30 16:58:31 +0200 |
| commit | 6d167392f6f8ede37e2794a68a3738f8ba03131d (patch) | |
| tree | 9caacef15dd034c6425f4bb623e0cd50a28ec52a /packages/meshbay-hub/src/meshbay_hub/static/profile-page.js | |
| parent | 8926f163dad9d32dc06c3a142658a4e11d9c12c1 (diff) | |
| download | meshbay-6d167392f6f8ede37e2794a68a3738f8ba03131d.tar.gz | |
feat(client): the desktop application keeps M and every node identity in its main process
keyring.js derives, opens, mints, seals, signs and agrees there; the page gets
public keys and a handle. Argon2 comes from the page's own WebAssembly build
(Electron's crypto has none). Without OS key storage the page keeps its keys as
a browser does. A node's bundle is settled after connecting, re-sealed when the
key changed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/profile-page.js')
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/static/profile-page.js | 51 |
1 files changed, 32 insertions, 19 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/profile-page.js b/packages/meshbay-hub/src/meshbay_hub/static/profile-page.js index 7a309a9..cd00f03 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/profile-page.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/profile-page.js @@ -4,6 +4,7 @@ import { import { t } from './i18n.js'; import { ask } from './ask.js'; import { Icon } from './icon.js'; +import * as platform from './platform.js'; import { hubFetch, HUB, session, setAuth, _storeBundleKey, _loadBundleKey, _storeRecoveryKey, @@ -143,33 +144,45 @@ export function ProfilePage({ user, onLogout }) { // run at all the account is left untouched. // Both keys from the passphrases, with the pepper this open session asks // for: the old one opens the bundles as they are, the new one seals them. + // In the desktop application both are kept by its main process, the new + // one set aside until the hub has accepted the change. const K = window.MeshBayKeys; const { pepper, version } = await K.fetchBundlePepper(user.token); - const oldKey = await K.deriveBundleSessionKey( + const oldKey = await K.sessionBundleKey( cpOld, user.username, user.userId, pepper, version); - const newKey = await K.deriveBundleSessionKey( - cpNew, user.username, user.userId, pepper, version); - const result = await window.MeshBayTransport.rewrapAllNodes({ - hubUrl: HUB, token: user.token, - username: user.username, userId: user.userId, - bundleKey: oldKey, newBundleKey: newKey, - onProgress: setCpProgress, - }); - - const oldAuthKey = await window.MeshBayKeys.deriveAuthKey(cpOld, user.username); - const newAuthKey = await window.MeshBayKeys.deriveAuthKey(cpNew, user.username); - const resp = await hubFetch('/v1/users/password', { - method: 'POST', token: user.token, - body: { old_auth_key: oldAuthKey, new_auth_key: newAuthKey }, - }); + const newKey = await K.sessionBundleKey( + cpNew, user.username, user.userId, pepper, version, { pending: true }); + let resp; + try { + const result = await window.MeshBayTransport.rewrapAllNodes({ + hubUrl: HUB, token: user.token, + username: user.username, userId: user.userId, + bundleKey: oldKey, newBundleKey: newKey, + onProgress: setCpProgress, + }); + const oldAuthKey = await window.MeshBayKeys.deriveAuthKey(cpOld, user.username); + const newAuthKey = await window.MeshBayKeys.deriveAuthKey(cpNew, user.username); + resp = await hubFetch('/v1/users/password', { + method: 'POST', token: user.token, + body: { old_auth_key: oldAuthKey, new_auth_key: newAuthKey }, + }); + setCpResult(result); + } catch (err) { + if (newKey.native) await platform.keys.dropPending(user.userId); + throw err; + } // Keep this tab signed in with the fresh pair, and move the session's // bundle key forward so the next node connection opens the new bundles. setAuth({ ...user, token: resp.access_token, refreshToken: resp.refresh_token }); - session.bundleKey = newKey; - _storeBundleKey(newKey); + if (newKey.native) { + await platform.keys.commitPending(user.userId); + session.bundleKey = { ...newKey, pending: false }; + } else { + session.bundleKey = newKey; + _storeBundleKey(newKey); + } - setCpResult(result); setCpPhase('done'); } catch (err) { const msg = err.message === 'account_locked' |