mirror of
https://github.com/PR0M3TH3AN/VoxVera.git
synced 2026-10-27 09:40:40 +00:00
Add NIP-46 remote signer to the board login gate
The board's connect gate now offers "Remote signer (NIP-46)" alongside NIP-07 / nsec / create-key. Pasting a bunker:// link establishes the viewer's pubkey (for the web-of-trust filter and display) and keeps the connection alive so getBoardSigner can sign reports and deletions remotely this session — its whole point being that the secret never leaves the signer app. After a reload the board reconnects read-only from the remembered pubkey (session-only, like the editor). The minimal NIP-46 client (parse bunker URI, NIP-44 codec with NIP-04 decrypt fallback, raw-WebSocket request/response) is ported into board.js, which is an independent IIFE. Reuses the editor's translations for the 3 new BOARD_UI strings across all 14 languages (i18n parity passes). Test: connect the board via a fake bunker signer doing real NIP-44 crypto, confirm it reveals as that identity, and that a report is signed through the remote signer (kind-1984 with the signer's pubkey). All 6 engines. Full suite 360 passing. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
29ed45533d
commit
b38dea1294
5 files changed
+326
-29
No files matched your search
@@ -276,15 +276,19 @@ de-duplicated per author+`d` identifier, keeping the latest.
|
||||
never print (hidden in the `@media print` block alongside the other app
|
||||
chrome).
|
||||
- **The board is gated behind a connected Nostr identity.** On load it shows a
|
||||
login gate (`#board-gate`) instead of the table, with three ways to connect:
|
||||
a **NIP-07** extension (`window.nostr.getPublicKey()`), **pasting an `nsec`**
|
||||
(decoded in-page to derive the pubkey, then discarded — the secret is never
|
||||
stored or transmitted), or **creating a new key** (reuses this device's anon
|
||||
key in `voxvera_nostr_anon_secret_hex` if present, else generates one, and
|
||||
reveals the `nsec` with a save-it warning before continuing). On success it
|
||||
reveals the table and surfaces the connected npub (`#board-identity`) with a
|
||||
Disconnect control. The board only ever needs the *pubkey* (it reads, never
|
||||
signs), so the connected pubkey is remembered in `localStorage`
|
||||
login gate (`#board-gate`) instead of the table, with four ways to connect:
|
||||
a **NIP-07** extension (`window.nostr.getPublicKey()`), a **NIP-46 remote
|
||||
signer** (paste a `bunker://` link; same hand-rolled client as the editor —
|
||||
it establishes the viewer pubkey via `get_public_key` and keeps the connection
|
||||
so `getBoardSigner` can sign reports/deletes remotely this session, then falls
|
||||
back to read-only after a reload), **pasting an `nsec`** (decoded in-page to
|
||||
derive the pubkey, then discarded — the secret is never stored or transmitted),
|
||||
or **creating a new key** (reuses this device's anon key in
|
||||
`voxvera_nostr_anon_secret_hex` if present, else generates one, and reveals the
|
||||
`nsec` with a save-it warning before continuing). On success it reveals the
|
||||
table and surfaces the connected npub (`#board-identity`) with a Disconnect
|
||||
control. The board only ever needs the *pubkey* to view (it reads to filter),
|
||||
so the connected pubkey is remembered in `localStorage`
|
||||
(`voxvera_connected_pubkey`, shared with the main client) and a return visit
|
||||
reconnects from it directly — no prompt or re-entry, any method. This is
|
||||
**not access control** — the events are public on the relays regardless — it
|
||||
|
||||
+10
-6
@@ -198,15 +198,19 @@ board can show them flyers from people they trust.
|
||||
riskier than a NIP-07 extension that keeps the key isolated; the input is a
|
||||
password field, the value is cleared after use, and nothing is transmitted. The
|
||||
**NIP-46 remote signer** (below) is now the safer mobile path.
|
||||
- **NIP-46 remote signer (shipped).** The editor can connect a remote signer
|
||||
- **NIP-46 remote signer (shipped — editor *and* board).** Both the editor's
|
||||
publishing identity and the board's login gate can connect a remote signer
|
||||
(bunker) by pasting a `bunker://` link: the user's secret stays in their signer
|
||||
app (nsec.app, Amber, …) and the browser only holds an ephemeral local key. The
|
||||
client is hand-rolled over a raw WebSocket using the vendored NIP-44 (with a
|
||||
NIP-04 decrypt fallback) — the bundle ships no nip46 module. Connections are
|
||||
**session-only** (the bunker token is never written to disk, so a reload returns
|
||||
to anonymous). Covered by the cross-engine e2e suite (full connect →
|
||||
get_public_key → sign_event → publish round-trip against a fake signer doing
|
||||
real NIP-44 crypto).
|
||||
NIP-04 decrypt fallback) — the bundle ships no nip46 module. On the board it
|
||||
establishes the viewer pubkey and keeps the connection so reports/deletes are
|
||||
signed remotely (read-only after a reload). Connections are **session-only**
|
||||
(the bunker token is never written to disk, so a reload returns to anonymous /
|
||||
read-only). Covered by the cross-engine e2e suite (editor: connect →
|
||||
get_public_key → sign_event → publish; board: connect → reveal → report
|
||||
signed through the remote signer — both against a fake signer doing real
|
||||
NIP-44 crypto).
|
||||
- **Editor identity (shipped).** The editor signs under anon / NIP-07 / imported
|
||||
nsec / remote signer. A remembered nsec is PIN-encrypted at rest (PBKDF2 600k →
|
||||
AES-GCM); plaintext is never stored. **Known weakness:** a short numeric PIN is
|
||||
|
||||
Reference in new issue
Block a user