diff options
| author | pablof7z <pfer@me.com> | 2026-02-23 19:40:24 +0000 |
|---|---|---|
| committer | pablof7z <pfer@me.com> | 2026-02-23 19:40:24 +0000 |
| commit | 0bf544216cf833346f4f3cbd3e7918e278456fee (patch) | |
| tree | 27f1fa9c78a835e215c52950efb45ead191b1e3a /C1.md | |
| parent | b805093e5ca36ae9ac33bfcbf8daa61d1902e9c4 (diff) | |
C1: expand to any event kind, add d+a tag requirements, client backlink verification
Diffstat (limited to 'C1.md')
| -rw-r--r-- | C1.md | 99 |
1 files changed, 74 insertions, 25 deletions
| @@ -6,7 +6,7 @@ Collaborative Ownership | |||
| 6 | 6 | ||
| 7 | `draft` `optional` | 7 | `draft` `optional` |
| 8 | 8 | ||
| 9 | This NIP defines a mechanism for multiple pubkeys to collaboratively maintain addressable events while preserving backwards compatibility. | 9 | This NIP defines a mechanism for multiple pubkeys to collaboratively maintain events. |
| 10 | 10 | ||
| 11 | ## Motivation | 11 | ## Motivation |
| 12 | 12 | ||
| @@ -20,14 +20,14 @@ Certain applications require shared ownership where: | |||
| 20 | 20 | ||
| 21 | ### Collaborative Pointer Event | 21 | ### Collaborative Pointer Event |
| 22 | 22 | ||
| 23 | A new addressable event kind `39382` serves as a pointer to collaboratively-owned content: | 23 | An addressable event kind `39382` serves as a pointer to collaboratively-owned content: |
| 24 | 24 | ||
| 25 | ```jsonc | 25 | ```jsonc |
| 26 | { | 26 | { |
| 27 | "kind": 39382, | 27 | "kind": 39382, |
| 28 | "pubkey": "<creator-pubkey>", | 28 | "pubkey": "<creator-pubkey>", |
| 29 | "tags": [ | 29 | "tags": [ |
| 30 | ["d", "<slug>"], | 30 | ["d", "<identifier>"], |
| 31 | ["k", "<target-kind>"], | 31 | ["k", "<target-kind>"], |
| 32 | ["p", "<owner-1-pubkey>"], | 32 | ["p", "<owner-1-pubkey>"], |
| 33 | ["p", "<owner-2-pubkey>"], | 33 | ["p", "<owner-2-pubkey>"], |
| @@ -42,35 +42,65 @@ A new addressable event kind `39382` serves as a pointer to collaboratively-owne | |||
| 42 | 42 | ||
| 43 | | Tag | Required | Description | | 43 | | Tag | Required | Description | |
| 44 | |-----|----------|-------------| | 44 | |-----|----------|-------------| |
| 45 | | `d` | Yes | `<slug> |` | 45 | | `d` | Yes | Shared identifier for the collaborative content | |
| 46 | | `k` | Yes | Target event kind | | 46 | | `k` | Yes | Target event kind (any kind) | |
| 47 | | `p` | Yes | Owner pubkeys (one or more) | | 47 | | `p` | Yes | Owner pubkeys (one or more) | |
| 48 | 48 | ||
| 49 | ### Resolution Algorithm | 49 | The creator's pubkey is implicitly an owner and SHOULD NOT appear in `p` tags. |
| 50 | 50 | ||
| 51 | To resolve the current state of collaboratively-owned content: | 51 | ### Target Events |
| 52 | 52 | ||
| 53 | 1. Parse the `39382` pointer event to extract owners (`p` tags) and target kind (`k` tag) | 53 | Any event kind MAY be a target of collaborative ownership. All target events: |
| 54 | 2. Extract the slug from the `d` tag (everything after the first `-`) | ||
| 55 | 3. Query: `{"kinds": [<target-kind>], "authors": [<all-owners>], "#d": ["<slug>"], "limit": 1}` | ||
| 56 | 54 | ||
| 57 | ### Back-Reference | 55 | - MUST include a `d` tag matching the pointer's `d` tag |
| 58 | 56 | - MUST include an `a` tag referencing the `39382` pointer event | |
| 59 | Target events MUST include an `a` tag pointing to the `39382` pointer: | ||
| 60 | 57 | ||
| 61 | ```jsonc | 58 | ```jsonc |
| 62 | { | 59 | { |
| 63 | "kind": 30023, | 60 | "kind": <target-kind>, |
| 61 | "pubkey": "<owner-pubkey>", | ||
| 64 | "tags": [ | 62 | "tags": [ |
| 65 | ["d", "my-article"], | 63 | ["d", "<identifier>"], |
| 66 | ["a", "39382:<pointer-creator-pubkey>:30023-my-article"] | 64 | ["a", "39382:<pointer-creator-pubkey>:<identifier>"] |
| 67 | ] | 65 | ], |
| 66 | "content": "..." | ||
| 68 | } | 67 | } |
| 69 | ``` | 68 | ``` |
| 70 | 69 | ||
| 71 | This allows clients to discover collaborative ownership from either direction: pointer → content or content → pointer. | 70 | The `d` tag is required regardless of whether the target kind is normally addressable. For addressable event kinds (30000-39999), the `d` tag serves its usual role. For all other kinds, the `d` tag enables grouping and correlation with the pointer. |
| 71 | |||
| 72 | ### Resolution Algorithm | ||
| 73 | |||
| 74 | To resolve the current state of collaboratively-owned content: | ||
| 75 | |||
| 76 | 1. Parse the `39382` pointer event to extract owners (`p` tags) and target kind (`k` tag) | ||
| 77 | 2. Extract the identifier from the `d` tag | ||
| 78 | 3. Query: `{"kinds": [<target-kind>], "authors": [<all-owners>], "#d": ["<identifier>"]}` | ||
| 79 | 4. For addressable target kinds: return the event with the highest `created_at` | ||
| 80 | 5. For non-addressable target kinds: return all matching events that contain a valid `a` tag backlinking to the pointer | ||
| 81 | |||
| 82 | ### Initial Discovery | ||
| 83 | |||
| 84 | Clients that do not yet have any version of the event MUST query by `#d` tag alone or by known owner pubkeys. | ||
| 85 | |||
| 86 | ## Client Behavior | ||
| 87 | |||
| 88 | ### Co-Author Attribution | ||
| 72 | 89 | ||
| 73 | ## Example | 90 | Clients SHOULD NOT display co-author attribution for a target event unless: |
| 91 | |||
| 92 | 1. The event contains an `a` tag referencing a `39382` pointer event, **and** | ||
| 93 | 2. The event's author pubkey appears in that pointer's `p` tags (or is the pointer's creator) | ||
| 94 | |||
| 95 | An event without a verifiable `a` tag backlink to a `39382` pointer MUST NOT be presented as collaboratively authored. This prevents spoofed co-authorship claims. | ||
| 96 | |||
| 97 | ### Display Recommendations | ||
| 98 | |||
| 99 | - Clients SHOULD display which pubkey signed each version | ||
| 100 | - Clients SHOULD indicate when an event is part of a collaborative set | ||
| 101 | - Clients MAY show the full owner set from the pointer event alongside the signing pubkey | ||
| 102 | |||
| 103 | ## Examples | ||
| 74 | 104 | ||
| 75 | ### Pointer Event | 105 | ### Pointer Event |
| 76 | 106 | ||
| @@ -81,7 +111,6 @@ This allows clients to discover collaborative ownership from either direction: p | |||
| 81 | "tags": [ | 111 | "tags": [ |
| 82 | ["d", "collaborative-guide"], | 112 | ["d", "collaborative-guide"], |
| 83 | ["k", "30023"], | 113 | ["k", "30023"], |
| 84 | ["p", "alice-pubkey"], | ||
| 85 | ["p", "bob-pubkey"], | 114 | ["p", "bob-pubkey"], |
| 86 | ["p", "carol-pubkey"] | 115 | ["p", "carol-pubkey"] |
| 87 | ], | 116 | ], |
| @@ -89,7 +118,7 @@ This allows clients to discover collaborative ownership from either direction: p | |||
| 89 | } | 118 | } |
| 90 | ``` | 119 | ``` |
| 91 | 120 | ||
| 92 | ### Target Article (by any owner) | 121 | ### Addressable Target (kind 30023) |
| 93 | 122 | ||
| 94 | ```jsonc | 123 | ```jsonc |
| 95 | { | 124 | { |
| @@ -98,7 +127,21 @@ This allows clients to discover collaborative ownership from either direction: p | |||
| 98 | "tags": [ | 127 | "tags": [ |
| 99 | ["d", "collaborative-guide"], | 128 | ["d", "collaborative-guide"], |
| 100 | ["title", "A Collaborative Guide"], | 129 | ["title", "A Collaborative Guide"], |
| 101 | ["a", "39382:alice-pubkey:30023-collaborative-guide"] | 130 | ["a", "39382:alice-pubkey:collaborative-guide"] |
| 131 | ], | ||
| 132 | "content": "..." | ||
| 133 | } | ||
| 134 | ``` | ||
| 135 | |||
| 136 | ### Non-Addressable Target (kind 4199) | ||
| 137 | |||
| 138 | ```jsonc | ||
| 139 | { | ||
| 140 | "kind": 4199, | ||
| 141 | "pubkey": "carol-pubkey", | ||
| 142 | "tags": [ | ||
| 143 | ["d", "collaborative-guide"], | ||
| 144 | ["a", "39382:alice-pubkey:collaborative-guide"] | ||
| 102 | ], | 145 | ], |
| 103 | "content": "..." | 146 | "content": "..." |
| 104 | } | 147 | } |
| @@ -107,7 +150,13 @@ This allows clients to discover collaborative ownership from either direction: p | |||
| 107 | ### Client Resolution | 150 | ### Client Resolution |
| 108 | 151 | ||
| 109 | 1. Client receives `naddr` for the `39382` pointer | 152 | 1. Client receives `naddr` for the `39382` pointer |
| 110 | 2. Parses owners: `[alice, bob, carol]` | 153 | 2. Parses owners: `[alice, bob, carol]`, target kind: `30023` |
| 111 | 3. Queries: `{"kinds": [30023], "authors": ["alice", "bob", "carol"], "#d": ["collaborative-guide"], "limit": 1}` | 154 | 3. Queries: `{"kinds": [30023], "authors": ["alice", "bob", "carol"], "#d": ["collaborative-guide"]}` |
| 112 | 4. Returns most recent version regardless of which owner published it | 155 | 4. Filters results: only events with `["a", "39382:alice-pubkey:collaborative-guide"]` are considered collaborative |
| 156 | 5. Returns most recent version (for addressable kinds) or full set (for non-addressable kinds) | ||
| 157 | |||
| 158 | ## Security Considerations | ||
| 113 | 159 | ||
| 160 | - Owners can unilaterally modify content | ||
| 161 | - An `a` tag backlink alone is insufficient — clients MUST verify the referenced pointer event includes the author in its `p` tags | ||
| 162 | - Owner changes on the pointer event take effect immediately; old target events from removed owners are no longer authoritative | ||