aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-common/src/meshbay_common/device.py
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-09-30 21:04:39 +0200
committerChristophe Besson <cbesson@gmail.com>2026-09-30 21:04:39 +0200
commit0378e8e0912a1a7e6cea4424e69d524e7afecbf8 (patch)
tree4ae94e32d6638b4c2cc1ae4f74cbe5d00c940636 /packages/meshbay-common/src/meshbay_common/device.py
parent0ed56d3a1b4f71cf622d3e27edc87a15ef33c185 (diff)
downloadmeshbay-0378e8e0912a1a7e6cea4424e69d524e7afecbf8.tar.gz
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 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-common/src/meshbay_common/device.py')
-rw-r--r--packages/meshbay-common/src/meshbay_common/device.py25
1 files changed, 25 insertions, 0 deletions
diff --git a/packages/meshbay-common/src/meshbay_common/device.py b/packages/meshbay-common/src/meshbay_common/device.py
index 3a598d0..2d6747f 100644
--- a/packages/meshbay-common/src/meshbay_common/device.py
+++ b/packages/meshbay-common/src/meshbay_common/device.py
@@ -37,6 +37,7 @@ import hashlib
DEVICE_REQUEST_PREFIX = b"meshbay:device_req:v1"
DEVICE_ADD_PREFIX = b"meshbay:device_add:v1"
DEVICE_HELLO_PREFIX = b"meshbay:device_hello:v1"
+DEVICE_REVOKE_PREFIX = b"meshbay:device_revoke:v1"
# Same as the join and admin transcripts: interactive exchanges that complete in
# milliseconds, so anything older is a replay.
@@ -126,6 +127,30 @@ def device_add_transcript(
])
+def device_revoke_transcript(
+ node_pk_b64: str,
+ user_id: str,
+ pk_ed25519_b64: str,
+ nonce_node: bytes,
+ ts: int,
+) -> bytes:
+ """
+ Signed by a pinned device, retiring one of the account's devices.
+
+ A prefix of its own, never the admission transcript: a signature given to
+ retire a key would otherwise admit that same key on a node where it is not
+ pinned yet, and whoever asks a device to sign a retirement could turn it
+ into an addition.
+ """
+ return _pack(DEVICE_REVOKE_PREFIX, [
+ node_pk_b64.encode(),
+ user_id.encode(),
+ pk_ed25519_b64.encode(),
+ nonce_node,
+ str(ts).encode(),
+ ])
+
+
def device_hello_transcript(
node_pk_b64: str,
group_id: str,