Proposal 2: Batched requests, cleaner prompts, policy-based approval
Problem
Nostr clients fire many signEvent / nip04.decrypt / nip44.decrypt calls
in bursts. Each spawns a separate prompt showing raw event JSON. Users get
fatigued, stop reading, and click "approve" blindly — defeating the permission
system entirely.
Proposal
Three coordinated improvements:
2a. Human-readable prompt rendering
Render pending requests semantically instead of as raw JSON:
- "Publish a note: 'gm frens ☕'" (kind 1)
- "Decrypt a DM from npub1xyz…" (
nip44.decrypt) - "Overwrite your contact list (312 follows)" (kind 3)
- "Update your relay list" (kind 10002)
Dangerous kinds (0, 3, 10002, key-related) get visually distinct, louder treatment.
2b. Batched request UI
PromptManager already queues prompts; extend it to present a single prompt
containing the pending batch: a scrollable list with per-item approve/deny,
plus approve-all / deny-all. Optionally support a non-standard
window.nostr.signEvents(events[]) batch method for clients that opt in.
2c. Policy-based auto-approval
Add per-site, per-operation policies with scope and expiry:
- Always allow: e.g., nip44 decrypt for kind 4/44 DMs, sign kind 7 reactions — low-risk, high-frequency operations.
- Always prompt: e.g., signing kind 1 notes, kind 0 metadata, kind 3 contact lists, anything key-related — high-impact operations the user must see every time.
- Time-boxed grants: "allow kind 1 for this site for the next hour."
Policy UI lives in the Options page (per-site permission list) and in the prompt itself ("Always allow this for this site" checkbox with sensible defaults per kind).
Design principle
Prompt once per trust decision, not once per action (the passkey model: enroll once, act freely within scope). Per-event prompts should be reserved for high-impact operations.
Prior art in upstream nos2x
Upstream (fiatjaf/nos2x v2.x) has already shipped pieces of this:
- Kind-scoped policies: its policy model is
policies[host][accept][type].conditions.kinds— "authorize kind 7 forever" / "reject kind 3 forever" (accept and reject grants, reverse policies cancel each other). Adopt this conditions model instead of inventing a new one; merge with our time-boxed grants (which upstream lacks). - Result-in-prompt: it performs the operation before asking and shows the decryption result in the prompt, so users see the actual plaintext being approved. Relevant to 2a, with a caveat: crypto happens regardless of consent, only disclosure is gated.
- Notifications as audit log: optional
notificationspermission fires a browser notification for every auto-allowed/denied action — a cheap answer to the audit question below. peekPublicKey: a non-prompting method that returns the pubkey only ifgetPublicKeywas previously authorized,''otherwise — lets clients probe without spawning prompts.
Open questions
- Sensible default policy matrix (which kinds default to allow/prompt/deny).
- Batch method: propose as a NIP, or ship as an extension-specific extra first?
- How to revoke/audit policies (a log of auto-approved signatures?).