summaryrefslogtreecommitdiffstats
path: root/CLAUDE.md
diff options
context:
space:
mode:
Diffstat (limited to 'CLAUDE.md')
-rw-r--r--CLAUDE.md15
1 files changed, 15 insertions, 0 deletions
diff --git a/CLAUDE.md b/CLAUDE.md
index fcdb28a..7a944af 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -323,6 +323,21 @@ anything that assumes one key per person.
`os.kill` — the first version of that test SIGHUPed the developer's own
running node
+- **Device linking is live (2026-08-18).** `identities` is keyed by
+ `(user_id, pk_ed25519)`, so one account holds several devices on a node; the
+ migration rebuilds the table and preserves existing pins. A new device files a
+ request bound by `sha256(code ‖ its own keys)`, and a key the node already
+ pinned countersigns it — the hub holds no user keys and so cannot. **The code
+ never reaches the node**: it lists pending requests with their hashes and the
+ approver recomputes to find the match, which is what makes a substituted key
+ impossible rather than merely detectable. `member unpin` still removes every
+ device; `revoke_device` marks one, because a deleted row is a key the node
+ would happily pin again
+- **`user_devices` on the hub is not the key directory that was H3.** Nothing
+ reads it but the hub, nothing wraps a group key for it, and it is a *different*
+ key from the per-node identities. What it does cost is metadata: the hub now
+ knows how many devices an account has and when each last signed in
+
## Two lessons that cost four rounds of live testing
- **`QE/deploy/e2e.py` cannot test `app.js`.** It is a second implementation of the