From 0378e8e0912a1a7e6cea4424e69d524e7afecbf8 Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Wed, 30 Sep 2026 21:04:39 +0200 Subject: fix: an identity signs a named kind, and a device approval answers a request The desktop main process builds every transcript itself from fields (transcripts.js) and signs no raw bytes; the page's identity has the same contract (crypto.js transcriptFor). The keyring seals no bundle while browser access is off. On the node, device_add must redeem a pending request filed by the same keys, and device_revoke is signed under its own prefix (meshbay:device_revoke:v1), so a retirement signature admits nothing. Co-Authored-By: Claude Opus 5.5 --- packages/meshbay-node/src/meshbay_node/roster.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'packages/meshbay-node/src/meshbay_node/roster.py') diff --git a/packages/meshbay-node/src/meshbay_node/roster.py b/packages/meshbay-node/src/meshbay_node/roster.py index 8144373..0116aaa 100644 --- a/packages/meshbay-node/src/meshbay_node/roster.py +++ b/packages/meshbay-node/src/meshbay_node/roster.py @@ -512,19 +512,22 @@ class Roster: await self._db.commit() return expires - async def take_device_request(self, code_hash: str, - user_id: str) -> dict | None: + async def take_device_request(self, code_hash: str, user_id: str, + pk_ed25519: str, pk_x25519: str) -> dict | None: """ - Claim a pending request by its hash, for this account only. + Claim a pending request by its hash, for this account and these keys. Single use and scoped to the account: a request filed for one person cannot be redeemed by another even with the code, and a code that has - been spent is gone. + been spent is gone. Scoped to the keys too: the request is what the new + device filed and signed, so an approval redeeming it admits those keys + and no others. """ assert self._db async with self._db.execute( "SELECT * FROM device_requests WHERE code_hash = ? AND user_id = ? " - "AND expires_at > ?", (code_hash, user_id, _now()) + "AND pk_ed25519 = ? AND pk_x25519 = ? AND expires_at > ?", + (code_hash, user_id, pk_ed25519, pk_x25519, _now()) ) as cur: row = await cur.fetchone() if row is None: -- cgit v1.2.3