2026 03 10_nostr_nip_completion_plan - mark-ik/graphshell GitHub Wiki
Date: 2026-03-10
Status: Active / planning
Scope: NIP coverage gaps in NostrCoreRegistry required for a functional Nostr client
Parent: register/2026-03-08_sector_c_identity_verse_plan.md
Related:
- register/nostr_core_registry_spec.md
- 2026-03-05_nostr_mod_system.md
- register/2026-03-08_sector_c_identity_verse_plan.md
Landed in Sector C:
-
NIP-01: full relay protocol — WebSocket connect/subscribe/publish via
TungsteniteRelayService, subscription persistence,NostrSignedEvent/NostrUnsignedEvent/NostrFilterSettypes -
NIP-44: encryption primitive —
nostr::nips::nip44imported and used for NIP-46 envelope - NIP-46: delegated remote signer — bunker URI parse, session key, encrypted RPC, permission memory
-
NIP-07: host-owned bridge —
window.nostrinjection,getPublicKey/signEvent/getRelays, per-origin permission memory
Runtime gap closure landed in NostrCoreRegistry relay transport path:
- Added inbound frame handling for subscription and publish confirmation paths:
- subscription observation now inspects
EOSE,NOTICE, andCLOSEDframes afterREQ - publish acknowledgment now inspects
OKandNOTICEframes afterEVENT
- subscription observation now inspects
- Publish receipts now reflect relay acknowledgment state (
accepted/rejected) instead of send-only optimistic success.
Code path:
-
shell/desktop/runtime/registries/nostr_core.rsobserve_subscription_confirmation(...)await_publish_ack(...)recv_json(...)
Targeted validation landed:
nostr_relay_worker_publish_observes_ok_acknostr_relay_worker_publish_notice_marks_receipt_rejected- existing regression guard still green:
nostr_relay_worker_emits_req_event_and_close_over_websocket
Residual NIP-01 follow-on (still open):
- General relay event-stream ingestion/dispatch for non-NIP-46 subscription payloads remains follow-on work (current closure is message-type acknowledgment and receipt semantics in the relay transport contract).
Not landed — confirmed by grep across codebase:: - No bech32 encode/decode, no npub/nsec/nprofile/nevent/naddr codec (NIP-19)
- No
nostr:URI scheme handler (NIP-21) - No kind
3contact list publish/fetch (NIP-02) - No kind
10002relay list metadata (NIP-65) - No kind
7reactions (NIP-25) - No kind
30000-range lists (NIP-51) - No relay info document fetch (NIP-11)
- No NIP-05 identifier resolution
- No NIP-17 sealed DMs
-
npub1examplestrings in tests are literal placeholder strings, not real bech32
Every user-facing identity representation in Nostr uses bech32. Without it:
-
authorsfilter fields cannot accept user input (they must be raw hex pubkeys) - Public keys cannot be displayed in any standard Nostr format
- Events cannot be referenced by
neventlinks - The
getPublicKeyNIP-07 response returns raw hex, but web content expectsnpubon display
Entities: npub1 (public key), nsec1 (secret — display-only decode for import),
note1 (event ID), nprofile1 (pubkey + relay hints), nevent1 (event + relay hints),
naddr1 (replaceable event address).
For a browser, this is as fundamental as http://. Nostr-aware web content embeds
nostr:npub1... and nostr:nevent1... links. Without a nostr: protocol handler,
those links fail silently or open nothing. Graphshell's ProtocolRegistry already
handles custom schemes — nostr: must be registered there.
A user's canonical list of read/write relays, published as a replaceable event. Without it, Graphshell can only find events on hardcoded relays. With it, relay selection becomes portable — you follow someone and automatically know where their events appear. This is how the Nostr social graph works at scale.
The contact list. A set of pubkeys (and optional relay hints and petnames) the user follows. Without NIP-02, there is no social graph — you cannot subscribe to a user's feed or know who they follow. This is required before any social timeline surface can exist.
HTTP GET to a relay URL returns JSON: supported NIPs, name, description, pubkey,
limitations. Required for intelligent relay selection — before connecting to a relay
you should know what it supports. Also needed to warn users when a relay doesn't
support a required NIP.
Likes, +/-, emoji reactions. Users expect to react to notes. Without NIP-25
the client is fully read-only from a social perspective.
Maps user@domain to a pubkey via a .well-known/nostr.json HTTP endpoint.
For a browser, DNS-based identity is a natural fit. Users expect to type a human
address rather than a 64-char hex string.
Bookmark lists, mute lists, pinned notes, categorized follow sets. Required for any content organization feature. Mute lists in particular are a basic trust/safety tool — without them users cannot suppress spam or unwanted content.
NIP-44: Versioned encryption — already landed as a primitive (used in NIP-46). The encryption function itself exists; it just needs wiring to DM send/receive.
The modern DM standard using NIP-44 + kind 1059 gift wrap. Preferable over
NIP-04 for new implementation since metadata leakage is much lower. NIP-44 being
already landed means the crypto is done; the message kind handling and thread model
are the remaining work.
The nostr crate (already a dependency via NIP-44 import) includes NIP-19 types.
Expose them through NostrCoreRegistry as a codec surface rather than re-implementing.
// In nostr_core.rs — new codec module
pub(crate) fn encode_npub(pubkey_hex: &str) -> Result<String, NostrCoreError>
pub(crate) fn encode_note(event_id_hex: &str) -> Result<String, NostrCoreError>
pub(crate) fn encode_nprofile(pubkey_hex: &str, relays: &[String]) -> Result<String, NostrCoreError>
pub(crate) fn encode_nevent(event_id_hex: &str, relays: &[String], kind: Option<u16>, author: Option<&str>) -> Result<String, NostrCoreError>
pub(crate) fn encode_naddr(identifier: &str, pubkey_hex: &str, kind: u16, relays: &[String]) -> Result<String, NostrCoreError>
pub(crate) fn decode_bech32(bech32_str: &str) -> Result<NostrEntityRef, NostrCoreError>
pub(crate) enum NostrEntityRef {
PublicKey(String), // hex pubkey
Note(String), // hex event id
Profile { pubkey: String, relays: Vec<String> },
Event { event_id: String, relays: Vec<String>, kind: Option<u16>, author: Option<String> },
Addr { identifier: String, pubkey: String, kind: u16, relays: Vec<String> },
}Also: NostrFilterSet::authors currently takes raw hex strings from test code. The
filter construction path should accept bech32 and decode internally before sending
REQ messages (NIP-01 requires hex on the wire).
Done gates:
-
encode_npub/encode_note/encode_nprofile/encode_nevent/encode_naddrimplemented -
decode_bech32decodes all five entity types toNostrEntityRef -
NostrFilterSetbuilder accepts bech32 authors and decodes to hex - NIP-07
getPublicKeyresponse available in both hex and npub forms - Unit tests: encode/decode round-trip for all five entity types; invalid input returns
Err
Register nostr: in ProtocolRegistry. The handler decodes the entity using N1.1,
then routes to the appropriate graph action:
-
nostr:npub1...→ open profile node or navigate to pubkey -
nostr:nevent1...→ open event node or navigate to event -
nostr:nprofile1...→ open profile with relay hints -
nostr:naddr1...→ open addressable event -
nostr:note1...→ open note event
The routing target is a GraphIntent proposal (per the mod system architecture:
Nostr-originated changes are proposals, not direct mutations). Unknown or
unsupported entity types return an explicit unsupported state, not a silent failure.
Done gates:
-
nostr:registered inProtocolRegistryas a handled scheme - Handler decodes bech32 entity and emits appropriate graph intent proposal
- Unsupported entity types return explicit error node, not blank pane
- Integration test:
nostr:npub1...link in webview content routes through the handler
HTTP GET to a relay's base URL with Accept: application/nostr+json returns relay
info. Implement as a one-shot async fetch in NostrCoreRegistry:
pub(crate) struct NostrRelayInfo {
pub(crate) name: Option<String>,
pub(crate) description: Option<String>,
pub(crate) pubkey: Option<String>,
pub(crate) supported_nips: Vec<u16>,
pub(crate) software: Option<String>,
pub(crate) version: Option<String>,
pub(crate) limitation: Option<NostrRelayLimitation>,
}
pub(crate) struct NostrRelayLimitation {
pub(crate) max_message_length: Option<u32>,
pub(crate) max_subscriptions: Option<u32>,
pub(crate) auth_required: Option<bool>,
pub(crate) payment_required: Option<bool>,
}
// In NostrCoreRegistry:
pub(crate) async fn fetch_relay_info(relay_url: &str) -> Result<NostrRelayInfo, NostrCoreError>Cache relay info per URL session-locally (no persistent cache needed initially). Surface in Settings → Sync relay list view so users can see what each relay supports.
Done gates:
-
fetch_relay_info()fetches and parses NIP-11 JSON -
supported_nipsfield is populated and queryable -
NostrRelayPolicycan gate connection to relays that don't support required NIPs - Relay list in Settings → Sync displays relay name and NIP-11 status
Fetch https://<domain>/.well-known/nostr.json?name=<local>, parse the names
object, return the hex pubkey. Used at two points:
- When a user types
user@domainin any identity input field - When displaying a profile that has a
nip05metadata tag — verify and badge it
pub(crate) async fn resolve_nip05(identifier: &str) -> Result<Nip05Resolution, NostrCoreError>
pub(crate) struct Nip05Resolution {
pub(crate) pubkey_hex: String,
pub(crate) relays: Vec<String>, // from the optional `relays` field
pub(crate) verified: bool,
}Done gates:
-
resolve_nip05()fetches and parses well-known JSON - Resolution result includes relay hints from the
relaysfield if present - Cache resolution TTL (session-local, 10 min default)
- Invalid/non-resolving identifiers return
Errwith an explicit reason
Publish and fetch a user's canonical read/write relay list.
pub(crate) struct NostrRelayListEntry {
pub(crate) url: String,
pub(crate) marker: Option<RelayMarker>, // Read | Write | None (both)
}
pub(crate) enum RelayMarker { Read, Write }
// In NostrCoreRegistry:
pub(crate) fn build_relay_list_event(entries: &[NostrRelayListEntry]) -> NostrUnsignedEvent
pub(crate) fn parse_relay_list_event(event: &NostrSignedEvent) -> Vec<NostrRelayListEntry>On startup, if a user identity is configured, subscribe to kind 10002 for that
pubkey to discover their relay list. When the user updates their relay list in
Settings → Sync, publish a new kind 10002 event.
NostrRelayPolicy::default_relays should be seeded from the NIP-65 list if one
is found, falling back to the hardcoded default (wss://relay.damus.io) only when
no kind 10002 event exists.
Done gates:
-
build_relay_list_event()produces a valid kind10002event withrtags -
parse_relay_list_event()extracts read/write markers fromrtags - On identity load, subscribe to kind
10002for own pubkey - Settings → Sync relay list can publish a new kind
10002 -
NostrRelayPolicyprefers NIP-65 relays over hardcoded defaults
Publish and fetch the user's contact list. Kind 3 events contain p tags:
["p", "<hex-pubkey>", "<relay-hint>", "<petname>"].
pub(crate) struct NostrContact {
pub(crate) pubkey_hex: String,
pub(crate) relay_hint: Option<String>,
pub(crate) petname: Option<String>,
}
// In NostrCoreRegistry:
pub(crate) fn build_contact_list_event(contacts: &[NostrContact]) -> NostrUnsignedEvent
pub(crate) fn parse_contact_list_event(event: &NostrSignedEvent) -> Vec<NostrContact>Important: kind 3 is a replaceable event — publishing a new one replaces the
old one. The entire contact list must be included every time (no partial updates).
This is a common footgun; the API must enforce it.
Graph integration: each contact in the follow list maps naturally to a graph node. A "Fetch follows" intent can populate the graph with the user's social graph as nodes connected by traversal-derived edges. This is the primary Nostr → graph integration surface.
Done gates:
-
build_contact_list_event()produces a valid kind3event -
parse_contact_list_event()extracts pubkey, relay hint, and petname - Contact list is fetched on identity load (subscribe kind
3for own pubkey) - Graph intent proposal:
NostrFetchFollowscreates graph nodes from contact list - Publishing always replaces: API enforces full-list-on-publish invariant
Parameterized replaceable events for user-curated lists. Most immediately useful:
- Kind
10000— mute list (pubkeys, event IDs, hashtags to suppress) - Kind
10001— pin list (pinned note IDs) - Kind
30000— categorized follow sets (named groups of pubkeys) - Kind
30001— bookmark sets
pub(crate) enum NostrListKind {
MuteList, // kind 10000
PinList, // kind 10001
FollowSet(String), // kind 30000 with identifier
BookmarkSet(String), // kind 30001 with identifier
}
pub(crate) struct NostrListEntry {
pub(crate) tag_type: String, // "p", "e", "t", "a"
pub(crate) value: String,
pub(crate) relay_hint: Option<String>,
}
pub(crate) fn build_list_event(kind: NostrListKind, entries: &[NostrListEntry]) -> NostrUnsignedEvent
pub(crate) fn parse_list_event(event: &NostrSignedEvent) -> (NostrListKind, Vec<NostrListEntry>)Start with mute list (kind 10000) as the first concrete implementation — it has
immediate usability value and blocks spam/safety concerns. Muted pubkeys/events
should be filtered out in NostrFilterSet construction and in event rendering.
Done gates (mute list minimum):
-
build_list_event(NostrListKind::MuteList, ...)produces valid kind10000 -
parse_list_event()extracts muted pubkeys, event IDs, and hashtags - Muted pubkeys are excluded from display and subscriptions where applicable
- Mute list is fetched on identity load
Reactions are kind 7 events with an e tag (event being reacted to), a p tag
(author of that event), and content +, -, or an emoji.
pub(crate) fn build_reaction_event(
target_event_id: &str,
target_author_pubkey: &str,
reaction: &str, // "+", "-", or emoji
) -> NostrUnsignedEventReaction counts on an event are fetched by subscribing to kind 7 with #e filter
pointing at the event ID. Display: aggregate + count, - count, and up to N
unique emoji reactions.
Done gates:
-
build_reaction_event()produces a valid kind7event - Reaction subscription filter uses
#etag filter correctly - Reaction aggregation helper:
count_reactions(events: &[NostrSignedEvent]) -> ReactionSummary
Gift-wrapped sealed DMs using NIP-44 encryption. The crypto is already landed (NIP-44). The remaining work is the event kind structure:
- Kind
14— sealed DM (encrypted, signed by sender) - Kind
1059— gift wrap (outer envelope, signed by ephemeral key, sent to recipient's relay)
pub(crate) fn build_dm_gift_wrap(
recipient_pubkey_hex: &str,
plaintext: &str,
sender_backend: &NostrSignerBackend,
) -> Result<NostrUnsignedEvent, NostrCoreError>
pub(crate) fn unwrap_dm_gift_wrap(
event: &NostrSignedEvent,
recipient_backend: &NostrSignerBackend,
) -> Result<String, NostrCoreError>Gift-wrap events should be published to the recipient's NIP-65 write relays (N2.3),
not the sender's default relays. The inbox subscription is kind 1059 events
addressed to the user's pubkey.
Done gates:
-
build_dm_gift_wrap()produces a valid kind1059event with NIP-44 inner encryption -
unwrap_dm_gift_wrap()decrypts the inner kind14content - DM inbox subscription uses kind
1059with#pfilter for own pubkey - Gift wrap uses ephemeral signing key for the outer envelope (not user's main key)
- Send path uses recipient's NIP-65 write relays when available
N1.1 (NIP-19 codec)
└─ N1.2 (NIP-21 URI handler) ← needs decode
└─ N2.2 (NIP-05 resolve) ← needs npub encode for display
└─ N2.3 (NIP-65 relay list) ← needs bech32 for filter authors
└─ N3.1 (NIP-02 follow list) ← needs bech32 for filter authors
└─ N3.2 (NIP-51 lists) ← needs bech32 for muted entities
└─ N4.1 (NIP-25 reactions) ← needs bech32 for event refs
N2.3 (NIP-65 relay list)
└─ N4.2 (NIP-17 DMs) ← send to recipient's write relays
N3.1 (NIP-02 follow list)
└─ Graph social graph integration
N2.1 (NIP-11) is independent — no bech32 dependency, pure HTTP.
The nostr crate is already a dependency (imported in nostr_core.rs for NIP-44
and key types). It includes NIP-19 codec, NIP-05 resolution helpers, and event
builders for all the kinds above. Use it rather than re-implementing:
-
nostr::nips::nip19— bech32 encode/decode -
nostr::nips::nip05— well-known JSON fetch -
nostr::nips::nip11— relay info fetch -
nostr::nips::nip65— relay list event helpers -
nostr::event::builder::EventBuilder— kind-specific event constructors
Thin wrapper functions in NostrCoreRegistry keep the public API stable while
delegating to the crate. This avoids leaking nostr crate types across the
registry boundary.
All Nostr-originated graph mutations are intent proposals per the mod system contract. The mapping for the NIPs in this plan:
| NIP result | Graph intent proposal |
|---|---|
| NIP-02 follow list fetch |
NostrFetchFollows → create profile nodes + follow edges |
NIP-21 nostr:npub1... link |
NostrOpenProfile → navigate to or create profile node |
NIP-21 nostr:nevent1... link |
NostrOpenEvent → navigate to or create event node |
| NIP-51 mute list | Filter applied before node creation (no intent needed) |
| NIP-25 reaction publish |
NostrPublishReaction → publish + annotate event node |
| NIP-17 DM send |
NostrSendDm → publish + create conversation thread node |
NostrCoreRegistry emits the proposal; graph reducers decide whether and how to
apply it. The registry never directly mutates graph state.
A functional Nostr client layer exists when:
- NIP-19 codec is implemented and all user-facing pubkey/event display uses bech32
- NIP-21
nostr:URIs resolve in Graphshell without silent failure - NIP-11 relay info is fetched before connection and surfaced in Settings → Sync
- NIP-65 relay list is loaded on identity init and used for relay selection
- NIP-02 follow list can be fetched and published
- NIP-05 identifiers resolve to pubkeys
- NIP-25 reactions can be published (send path)
- NIP-51 mute list is loaded and applied to filter muted content
- NIP-17 DMs can be sent and received (gift-wrap / sealed inbox)
- All new event kinds route through
relay_publish/relay_subscribecapability gates -
npub1exampleplaceholder strings in tests are replaced with valid bech32 test fixtures
This section answers the "all possible NIPs" request using the upstream nostr-protocol/nips
repository inventory at authoring time (85 NIP markdown files).
Scoring legend:
- Difficulty:
Low/Medium/Highimplementation cost for Graphshell. - Graphshell Utility:
Low/Medium/High/Criticalrelative product value. - Rationale: one-line project-specific reason, not protocol-generic value.
| NIP | Title | Difficulty | Graphshell Utility | Rationale |
|---|---|---|---|---|
| NIP-01 | Events and signatures | Medium | Critical | Core relay event protocol + signing baseline. |
| NIP-02 | Uses | Medium | High | Follow graph is core to social discovery and graph seeding. |
| NIP-03 | Unknown | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-04 | Security Warning | Medium | Medium | Identity/linking semantics improve browser and graph routing UX. |
| NIP-05 | Finding users from their NIP-05 identifier | Low | High | Human identity resolution improves usability in browser-like flows. |
| NIP-06 | Unknown | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-07 | Unknown | Low | High | Already landed host bridge surface for web-app interoperability. |
| NIP-08 | Unknown | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-09 | Client Usage | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-10 | Abstract | Medium | Medium | Threading conventions needed for coherent note/reply graph rendering. |
| NIP-11 | Unknown | Low | High | Relay capability discovery needed for policy and diagnostics. |
| NIP-12 | Unknown | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-13 | Unknown | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-14 | Unknown | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-15 | Terms | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-16 | Unknown | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-17 | Kind Definitions | High | High | Modern DM support is a major user expectation. |
| NIP-18 | Quote Reposts | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-19 | Bare keys and ids | Medium | Critical | bech32 identity and entity handling is required for user-facing interoperability. |
| NIP-20 | Unknown | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-21 | Unknown | Medium | Critical | nostr: URI support is essential for browser routing and in-content links. |
| NIP-22 | Examples | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-23 | Example Event | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-24 | Unknown | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-25 | Unknown | Low | Medium | Reactions are expected social interaction baseline. |
| NIP-26 | Delegator: | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-27 | Example of a profile mention process | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-28 | Kind 40: Create channel | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-29 | Relay-generated events | Low | Medium | Relay interoperability/ops NIP; useful for transport reliability. |
| NIP-30 | Unknown | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-31 | Unknown | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-32 | Unknown | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-33 | Unknown | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-34 | Repository announcements | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-35 | Tags | Medium | Medium | Content organization semantics may map to graph labeling/workbench views. |
| NIP-36 | Unknown | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-37 | Relay List for Private Content | Low | Medium | Relay interoperability/ops NIP; useful for transport reliability. |
| NIP-38 | Abstract | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-39 | Abstract | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-40 | Unknown | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-42 | Motivation | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-43 | Membership Lists | Medium | Medium | Content organization semantics may map to graph labeling/workbench views. |
| NIP-44 | Versions | Medium | High | Encryption primitive required for secure messaging and signer envelopes. |
| NIP-45 | Motivation | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-46 | Changes | High | High | Remote signer compatibility broadens wallet/signer interop. |
| NIP-47 | Rationale | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-48 | Unknown | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-49 | Password Unicode Normalization | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-50 | Abstract | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-51 | Types of lists | Medium | High | Lists support organization, mute/bookmark safety and productivity. |
| NIP-52 | Calendar Events | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-53 | Live Streaming | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-54 | Articles | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-55 | Usage for Android applications | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-56 | Unknown | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-57 | Protocol flow | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-58 | Unknown | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-59 | Overview | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-60 | High-level flow | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-61 | High-level flow | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-62 | Request to Vanish from Relay | Low | Medium | Relay interoperability/ops NIP; useful for transport reliability. |
| NIP-64 | Note | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-65 | Unknown | Medium | High | Relay-list metadata is needed for correct relay targeting. |
| NIP-66 | Relay Discovery Events | Low | Medium | Relay interoperability/ops NIP; useful for transport reliability. |
| NIP-68 | Picture Events | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-69 | Abstract | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-70 | The tag | Medium | Medium | Content organization semantics may map to graph labeling/workbench views. |
| NIP-71 | Video Events | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-72 | Community Definition | Medium | Medium | Community semantics are useful for Verse/community-layer integration. |
| NIP-73 | Supported IDs | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-75 | Nostr Event | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-77 | High-Level Protocol Description | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-78 | Nostr event | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-84 | Format | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-85 | Assertion Events | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-86 | Unknown | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-87 | Rationale | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-88 | Events | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-89 | Rationale | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-90 | Kinds | High | Medium | DVM jobs are strategic but not required for baseline client usability. |
| NIP-92 | Example | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-94 | Event format | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-96 | Introduction | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-98 | Nostr event | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
| NIP-99 | Example Event | Medium | Low | Long-tail NIP; no direct Graphshell core dependency identified yet. |
- This is an execution-planning matrix, not a standards-committee value judgment.
- Several long-tail NIPs may move up in utility if product scope changes (for example, payments, commerce, media-first workflows, or heavy community moderation).
- Keep this matrix versioned in this file; if upstream adds new NIPs, append rows and assign rank fields before implementation starts.