Commit 52a5f62
authored
Podkey 0.0.8: general-signer signing, refreshed docs, popup fit, key icons (#23)
* fix(signing): trusted origins sign without a prompt (general NIP-07 signer)
handleSignEvent gated auto-signing on `trusted && autoSign && isSolidAuth`,
so a trusted origin only signed kind-27235 (Solid auth) silently and
re-prompted for every other event kind. A normal Nostr client — the forum
publishes kind 0 / 10002 / 22242 on every load — therefore raised three
approval popups on each page load, making Podkey unusable as a single
general-purpose signer.
Align signing with the trust model already used by GET_PUBLIC_KEY and
nip44.{encrypt,decrypt}: a trusted origin is sufficient to skip the prompt
(decrypting DMs is strictly more sensitive than signing, and is already
silent for trusted origins). An untrusted origin still ALWAYS prompts, and
approving it establishes revocable trust — no silent first-use.
let shouldSign = trusted && autoSign && isSolidAuth;
-> let shouldSign = trusted;
Tests updated to the general-signer contract (133 pass, lint clean).
Co-Authored-By: jjohare <github@thedreamlab.uk>
* docs+ui: refactor README/USAGE/CHANGELOG, fit popup to surface, add key icons
- README/USAGE/CHANGELOG: rewrite to match the current capability and security
model (session-only key, per-origin consent, trusted-origin signing, NIP-98
with fresh nonce + body/URL binding, honest window.nostr surface). UK English.
- popup: cap the trusted-sites list and tighten section spacing so the Export /
GitHub footer stays within the browser popup height instead of scrolling off;
widen to 400px.
- icons: add 16/48/128px key icons (icons/icon.svg master) and wire them into
manifest icons + action.default_icon so the toolbar shows the Podkey key.
Co-Authored-By: jjohare <github@thedreamlab.uk>
* feat(vault): encrypted-at-rest key persistence with passphrase unlock
PR #22's hardening stored the private key only in chrome.storage.session
(in-memory), so it was wiped on every browser restart — getPublicKey() then
threw the non-intuitive "No keypair found" and the user had to re-import their
nsec each time. That is "no at-rest persistence", not "encryption at rest".
Add a real encrypted-at-rest vault:
- src/vault.js: AES-256-GCM ciphertext in chrome.storage.local, key wrapped by
scrypt(passphrase) (N=2^16, r=8, p=1; params sealed in the blob for future
upgrade). Pure encrypt/decrypt split from the storage I/O so the crypto is
unit-tested off-platform. Wrong passphrase / tamper fail closed via the GCM tag.
- Session stays the hot cache: on unlock the decrypted key is held in
chrome.storage.session for fast signing; a browser restart clears it and the
user re-unlocks. The raw key never touches disk.
- background.js: generate/import now take a passphrase and seal the vault;
new UNLOCK_VAULT / LOCK_VAULT; GET_KEYPAIR_STATUS reports none|locked|unlocked.
A locked vault on getPublicKey/sign/nip44 opens the unlock popup and throws a
clear "Podkey is locked — unlock and try again" instead of "No keypair found".
- popup: set-passphrase step on generate, passphrase fields on import, an unlock
screen (with forget-key/start-over), and a Lock action. Pill reads "Unlocked".
Tests: 8 vault crypto tests (round-trip, wrong passphrase, tamper, validation,
salt/iv freshness). Full suite 141 pass; eslint src/ clean.
Co-Authored-By: jjohare <github@thedreamlab.uk>
* docs: privacy policy, vault-current docs, and Actions-based Pages site
- PRIVACY.md: repo-hosted privacy policy (local signer; key encrypted at rest;
no servers/accounts/telemetry; per-permission rationale incl. <all_urls>).
Doubles as the Chrome Web Store privacy disclosure basis.
- README/USAGE/CHANGELOG: bring the security model up to date with the encrypted
vault (was "session-only"), document the passphrase + unlock/lock/forget flow,
bump version 0.0.7 -> 0.0.8, test count 133 -> 141, add vault.js to the file
map, and add a "Where Podkey fits" section positioning it against existing
NIP-07 signers, the did:nostr ecosystem (github.com/topics/did-nostr), and
Solid (solidproject.org) — extends + consolidates rather than reinvents.
- site/: a polished, self-contained docs landing (index.html) + hosted privacy
page (privacy.html) for a clean Web Store privacy URL.
- gh-pages.yml: complete the migration off the legacy gh-pages branch — assemble
the docs site + test page and deploy via actions/deploy-pages (the proper
GitHub Actions Pages workflow), triggered on site/test-page changes.
Co-Authored-By: jjohare <github@thedreamlab.uk>1 parent 384918d commit 52a5f62
21 files changed
Lines changed: 1273 additions & 413 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| 8 | + | |
8 | 9 | | |
9 | 10 | | |
| 11 | + | |
10 | 12 | | |
11 | 13 | | |
12 | 14 | | |
| |||
30 | 32 | | |
31 | 33 | | |
32 | 34 | | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
33 | 43 | | |
34 | 44 | | |
35 | 45 | | |
36 | | - | |
| 46 | + | |
37 | 47 | | |
38 | 48 | | |
39 | 49 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
12 | | - | |
13 | | - | |
14 | | - | |
15 | | - | |
16 | | - | |
17 | | - | |
18 | | - | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
19 | 52 | | |
20 | 53 | | |
21 | 54 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
0 commit comments