NIP-46 sign-in: remote-signer sessions behind the same facade, memory-only

Implements login-methods.md §LM5 phase one. Core gains nostr/nip46.ts -- a
Nip46Client speaking kind-24133 RPC with NIP-44 transport encryption,
bunker:// parsing, nostrconnect listen (secret echo is proof-of-scan),
auth_url surfacing, and typed deadline errors -- plus subscribeLive on
RelayConnection with re-REQ on reconnect, and live post-EOSE delivery in
the MockRelay so tests exercise real round trips against a fake bunker.

The ephemeral client key and Nip46Client live in the crypto worker
(§LM5.4); nip46* actions bypass the serial queue so a signer waiting
minutes for human approval cannot block other worker calls, and the
signer's auth_url reaches the UI as the worker's first notification frame.

The widget's connect screen runs both legs at once: a nostrconnect QR --
rendered as dot-style inline SVG with rounded finder eyes, per owner
preference -- for phone signers, and a bunker:// paste box (password
input; the URI carries a token). window.nostr is now an element-routed
provider, so a NIP-46 session claims the slot and hosts reading it get
the remote signer transparently; NIP-07 still leaves the slot to the
extension. Sessions stay thin per §LM7: no vault, no persistence.
Persistence remains gated on the external vault review (§LM5.3).

14 new tests (core fake-bunker e2e, QR geometry, signer delegation) and
two policy pins: bunker option below the password path, element stays
web-storage-free.

Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
thePR0M3TH3ANandClaude Fable 5 committed 2026-08-04 10:31:36 -04:00
1 parent b616068689
commit 49682dd75c
23 files changed
+1625 -70

No files matched your search

+16 -9
View File
@@ -1991,14 +1991,14 @@
"version": "0.1.0",
"license": "MIT",
"dependencies": {
"@noble/ciphers": "^2.2.0",
"@noble/curves": "^1.9.1",
"@noble/hashes": "^1.7.1",
"@scure/base": "^1.2.6",
"@scure/bip39": "^1.5.4",
"canonicalize": "^2.0.0",
"diceware-wordlist-en-eff": "^1.0.1",
"hash-wasm": "^4.12.0"
"@noble/ciphers": "2.2.0",
"@noble/curves": "1.9.7",
"@noble/hashes": "1.8.0",
"@scure/base": "1.2.6",
"@scure/bip39": "1.6.0",
"canonicalize": "2.1.0",
"diceware-wordlist-en-eff": "1.0.1",
"hash-wasm": "4.12.0"
},
"devDependencies": {
"@types/node": "^22.10.0",
@@ -2019,12 +2019,19 @@
"license": "MIT",
"dependencies": {
"@bitlogin/core": "*",
"@getalby/bitcoin-connect": "^3.12.3"
"@getalby/bitcoin-connect": "3.12.3",
"qrcode-generator": "^2.0.4"
},
"devDependencies": {
"typescript": "^5.7.3",
"vite": "^6.1.0"
}
},
"packages/widget/node_modules/qrcode-generator": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/qrcode-generator/-/qrcode-generator-2.0.4.tgz",
"integrity": "sha512-mZSiP6RnbHl4xL2Ap5HfkjLnmxfKcPWpWe/c+5XxCuetEenqmNFf1FH/ftXPCtFG5/TDobjsjz6sSNL0Sr8Z9g==",
"license": "MIT"
}
}
}