Skip to content

NIP-G6: OpenWyrd Capability-URL Inline Rendering#2329

Open
DeltaClimbs wants to merge 3 commits intonostr-protocol:masterfrom
DeltaClimbs:nip-g6-decrypt-render
Open

NIP-G6: OpenWyrd Capability-URL Inline Rendering#2329
DeltaClimbs wants to merge 3 commits intonostr-protocol:masterfrom
DeltaClimbs:nip-g6-decrypt-render

Conversation

@DeltaClimbs
Copy link
Copy Markdown

@DeltaClimbs DeltaClimbs commented Apr 29, 2026

TL;DR

Defines a rendering contract for Nostr clients to recognize OpenWyrd MOP capability URLs in kind:1 content (or NIP-17 inner sealed events), fetch the envelope, decrypt client-side using the URL fragment, and render plaintext inline in feed in lieu of the standard OpenGraph card.

Zero sender burden — no tags, no signer changes, no wire-format additions. Senders paste URLs exactly as today; the entire delta is on the rendering client.

Successor to withdrawn NIP-C6

Both review objections from #2327 are baked in:

  1. Sender burden → zero. Entire delta on the rendering client.
  2. URL self-identification → preserved. Clients pattern-match on URL shape (16-char handle + 43-char base64url key — distinctive enough to skip false-positives). The NIP supplies the protocol-specific decryption knowledge that pattern-matching alone can't.

What the client does

1. Detect URL: https://<host>/w/<handle>#<K_read>
   handle: ^[A-Za-z0-9_-]{16}$    K_read: ^[A-Za-z0-9_-]{43}$ (32 bytes)

2. Fetch:    GET https://<host>/api/v1/wyrds/<handle>
             MOP-Protocol-Version: 1
   Returns:  { handle, envelope, k_origin_pub, published_at, expires_at, replies_enabled }

3. Decrypt:  envelope = 0x01 || iv(12) || ct(N) || tag(16)
             aad      = 0x01 || handle_raw(12) || be8(expires_at_ms) || replies_enabled(1)
             plaintext = AES-256-GCM-Decrypt(K_read, iv, ct||tag, aad)

4. Render:   plaintext + "OpenWyrd MOP" badge + expiry indicator,
             replacing the standard OG card.

Full constants, response shapes, tombstone handling, and BIP-340 attestation verification inlined in G6.md §3 — self-contained, no external links required to implement.

Threat model (no privacy delta)

The capability URL is a bearer secret — posting it publicly already grants read access to every reader. This NIP does not change who can decrypt, only whether the recipient sees plaintext in-feed or has to tap-and-leave. Host read-blindness (K_read never travels HTTP, RFC 3986 §3.5) is unchanged. Clients implementing this NIP MUST NOT transmit K_read to any third party.

Reference implementation

@openwyrd/mop on npm (Apache-2.0). Live test: any https://sendwyrd.com/w/<handle>#<key> URL.

Number

G6 picked after scanning merged NIPs and ~200 open/closed PRs — no conflict. G is outside the hex convention used by merged NIPs to date; happy to renumber per editor preference.

Successor in spirit to the withdrawn NIP-C6 (nostr-protocol#2327). Defines a rendering
contract for Nostr clients to recognize OpenWyrd MOP capability URLs in
event content, fetch the envelope, decrypt client-side using the URL
fragment, and render plaintext in feed previews in lieu of the standard
OpenGraph card.

Inherits both review objections from NIP-C6: zero sender burden (clients
do all the work, senders paste URLs unchanged) and URL self-identification
(no event tags; clients pattern-match on URL shape).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant