NIP-800 BDD
```
Feature: Kind-scoped NIP-07 NIP-44 decryption permissions
In order to prevent hostile nostr apps from gaining broad private-data access
As a NIP-07 extension or remote signer
I want decryption permission to be scoped to the encrypted payload category
Background:
Given the user has a nostr keypair
And the app origin is "
https://recipes.example"
And the extension supports NIP-07
And the extension supports NIP-44 encryption and decryption
And the extension records decryption grants per app origin and encrypted payload kind
Rule: Plain NIP-44 decrypt is broad and must not be silently granted
Scenario: App requests raw NIP-44 decrypt without typed encrypted payload
Given an encrypted NIP-44 payload with no embedded kind metadata
When the app requests NIP-44 decryption for that payload
Then the extension must show a broad decryption warning
And the warning must say the app may decrypt arbitrary NIP-44 payloads
And the extension must not store a kind-scoped grant
Scenario: User rejects broad raw decryption
Given an encrypted NIP-44 payload with no embedded kind metadata
When the app requests NIP-44 decryption for that payload
And the user rejects the prompt
Then the extension must not return plaintext to the app
And the extension must record no grant for "
https://recipes.example"
Rule: Typed encrypted payloads can receive narrow grants
Scenario: App requests decrypt for a typed private bookmark payload
Given an encrypted NIP-44 payload whose plaintext is JSON:
"""
{
"kind": 10003,
"payload": [["r", "
https://damagebdd.com"]]
}
"""
And kind 10003 is classified as "private bookmarks"
When the app requests NIP-44 decryption for that payload
Then the extension must decrypt internally before showing the permission prompt
And the prompt must say "recipes.example wants to decrypt private bookmarks"
And the prompt must not say "decrypt all private messages"
And the prompt must not say "decrypt all NIP-44 data"
Scenario: User grants only private bookmark decryption
Given an encrypted NIP-44 payload whose embedded kind is 10003
And kind 10003 is classified as "private bookmarks"
When the app requests NIP-44 decryption for that payload
And the user allows "always allow this kind"
Then the extension must store a grant for:
| origin | permission | kind |
|
https://recipes.example | nip44_decrypt_kind | 10003 |
And the extension must return the decrypted payload to the app
Scenario: Bookmark grant does not allow DM decryption
Given the app has an existing grant:
| origin | permission | kind |
|
https://recipes.example | nip44_decrypt_kind | 10003 |
And an encrypted NIP-44 payload whose embedded kind is 14
And kind 14 is classified as "private direct messages"
When the app requests NIP-44 decryption for that payload
Then the extension must not use the private bookmark grant
And the extension must show a new prompt for private direct messages
And the extension must not return plaintext unless the user approves kind 14
Rule: The app must not be trusted to declare the kind during decryption
Scenario: App lies and claims a DM payload is a bookmark payload
Given an encrypted NIP-44 payload whose embedded kind is 14
And the app claims the payload kind is 10003
And the app has an existing grant:
| origin | permission | kind |
|
https://recipes.example | nip44_decrypt_kind | 10003 |
When the app requests NIP-44 decryption for that payload
Then the extension must ignore the app-provided kind
And the extension must classify the payload using the decrypted embedded kind
And the extension must require permission for kind 14
And the extension must not return plaintext under the kind 10003 grant
Rule: Event-level decryption must validate the outer event before policy decisions
Scenario: Extension refuses to decrypt an unsigned or invalid event
Given a nostr event containing encrypted NIP-44 content
And the event signature is invalid
When the app requests event-aware decryption
Then the extension must reject the request before returning plaintext
And the extension must show an error "invalid event signature"
And the extension must not create or reuse a decryption grant
Scenario: Extension refuses mismatched sender pubkey
Given a signed nostr event containing encrypted NIP-44 content
And the encryption sender pubkey does not match the event pubkey policy
When the app requests event-aware decryption
Then the extension must reject or warn according to configured policy
And the extension must not silently return plaintext
Rule: Decrypted event mutation must not be confused with signed event validity
Scenario: Extension returns decrypted copy without pretending signature remains valid
Given a signed nostr event containing encrypted content
And the encrypted content decrypts successfully
When the extension returns a decrypted event-shaped object
Then the returned object must be marked as "decrypted_copy"
And the extension must not claim the decrypted object has the original signature validity
And the original signed event must remain available for audit comparison
Rule: Unknown or malformed typed payloads fall back safely
Scenario: Payload decrypts but is not valid JSON
Given an encrypted NIP-44 payload whose plaintext is not valid JSON
When the app requests NIP-44 decryption
Then the extension must show a broad decryption warning
And the extension must not infer a kind
And the extension must not store a kind-scoped grant
Scenario: Payload decrypts to JSON without kind
Given an encrypted NIP-44 payload whose plaintext is JSON:
"""
{
"payload": "secret text"
}
"""
When the app requests NIP-44 decryption
Then the extension must show a broad decryption warning
And the extension must not store a kind-scoped grant
Scenario: Payload declares an unknown kind
Given an encrypted NIP-44 payload whose embedded kind is 987654
When the app requests NIP-44 decryption
Then the extension must show "unknown encrypted payload kind 987654"
And the extension must require explicit one-time approval
And the extension must not auto-map it to direct messages, bookmarks, or mute lists
Rule: Grants are origin-bound and revocable
Scenario: Grant for one origin does not apply to another origin
Given "
https://recipes.example" has a grant for kind 10003
And "
https://evil.example" has no grants
And an encrypted NIP-44 payload whose embedded kind is 10003
When "
https://evil.example" requests NIP-44 decryption
Then the extension must show a permission prompt
And the extension must not reuse the grant from "
https://recipes.example"
Scenario: Revoked grant blocks future silent decrypts
Given "
https://recipes.example" had a grant for kind 10003
And the user revoked that grant
When the app requests NIP-44 decryption for a kind 10003 payload
Then the extension must show a new permission prompt
And the extension must not return plaintext silently
```
View quoted note →