diff options
| -rw-r--r-- | 01.md | 5 | ||||
| -rw-r--r-- | 09.md | 5 | ||||
| -rw-r--r-- | 18.md | 21 | ||||
| -rw-r--r-- | 26.md | 8 | ||||
| -rw-r--r-- | 31.md | 15 | ||||
| -rw-r--r-- | 98.md | 68 | ||||
| -rw-r--r-- | README.md | 7 |
7 files changed, 115 insertions, 14 deletions
| @@ -16,7 +16,7 @@ The only object type that exists is the `event`, which has the following format | |||
| 16 | 16 | ||
| 17 | ```json | 17 | ```json |
| 18 | { | 18 | { |
| 19 | "id": <32-bytes lowercase hex-encoded sha256 of the serialized event data> | 19 | "id": <32-bytes lowercase hex-encoded sha256 of the serialized event data>, |
| 20 | "pubkey": <32-bytes lowercase hex-encoded public key of the event creator>, | 20 | "pubkey": <32-bytes lowercase hex-encoded public key of the event creator>, |
| 21 | "created_at": <unix timestamp in seconds>, | 21 | "created_at": <unix timestamp in seconds>, |
| 22 | "kind": <integer>, | 22 | "kind": <integer>, |
| @@ -99,7 +99,7 @@ This NIP defines no rules for how `NOTICE` messages should be sent or treated. | |||
| 99 | ## Basic Event Kinds | 99 | ## Basic Event Kinds |
| 100 | 100 | ||
| 101 | - `0`: `set_metadata`: the `content` is set to a stringified JSON object `{name: <username>, about: <string>, picture: <url, string>}` describing the user who created the event. A relay may delete past `set_metadata` events once it gets a new one for the same pubkey. | 101 | - `0`: `set_metadata`: the `content` is set to a stringified JSON object `{name: <username>, about: <string>, picture: <url, string>}` describing the user who created the event. A relay may delete past `set_metadata` events once it gets a new one for the same pubkey. |
| 102 | - `1`: `text_note`: the `content` is set to the plaintext content of a note (anything the user wants to say). Do not use Markdown! Clients should not have to guess how to interpret content like `[]()`. Use different event kinds for parsable content. | 102 | - `1`: `text_note`: the `content` is set to the **plaintext** content of a note (anything the user wants to say). Content that must be parsed, such as Markdown and HTML, should not be used. Clients should also not parse content as those. |
| 103 | - `2`: `recommend_server`: the `content` is set to the URL (e.g., `wss://somerelay.com`) of a relay the event creator wants to recommend to its followers. | 103 | - `2`: `recommend_server`: the `content` is set to the URL (e.g., `wss://somerelay.com`) of a relay the event creator wants to recommend to its followers. |
| 104 | 104 | ||
| 105 | A relay may choose to treat different message kinds differently, and it may or may not choose to have a default way to handle kinds it doesn't know about. | 105 | A relay may choose to treat different message kinds differently, and it may or may not choose to have a default way to handle kinds it doesn't know about. |
| @@ -110,3 +110,4 @@ A relay may choose to treat different message kinds differently, and it may or m | |||
| 110 | - The `tags` array can store a tag identifier as the first element of each subarray, plus arbitrary information afterward (always as strings). This NIP defines `"p"` — meaning "pubkey", which points to a pubkey of someone that is referred to in the event —, and `"e"` — meaning "event", which points to the id of an event this event is quoting, replying to or referring to somehow. See [NIP-10](10.md) for a detailed description of "e" and "p" tags. | 110 | - The `tags` array can store a tag identifier as the first element of each subarray, plus arbitrary information afterward (always as strings). This NIP defines `"p"` — meaning "pubkey", which points to a pubkey of someone that is referred to in the event —, and `"e"` — meaning "event", which points to the id of an event this event is quoting, replying to or referring to somehow. See [NIP-10](10.md) for a detailed description of "e" and "p" tags. |
| 111 | - The `<recommended relay URL>` item present on the `"e"` and `"p"` tags is an optional (could be set to `""`) URL of a relay the client could attempt to connect to fetch the tagged event or other events from a tagged profile. It MAY be ignored, but it exists to increase censorship resistance and make the spread of relay addresses more seamless across clients. | 111 | - The `<recommended relay URL>` item present on the `"e"` and `"p"` tags is an optional (could be set to `""`) URL of a relay the client could attempt to connect to fetch the tagged event or other events from a tagged profile. It MAY be ignored, but it exists to increase censorship resistance and make the spread of relay addresses more seamless across clients. |
| 112 | - Clients should use the created_at field to judge the age of a metadata event and completely replace older metadata events with newer metadata events regardless of the order in which they arrive. Clients should not merge any filled fields within older metadata events into empty fields of newer metadata events. | 112 | - Clients should use the created_at field to judge the age of a metadata event and completely replace older metadata events with newer metadata events regardless of the order in which they arrive. Clients should not merge any filled fields within older metadata events into empty fields of newer metadata events. |
| 113 | - When a websocket is closed by the relay with a status code 4000 that means the client shouldn't try to connect again. | ||
| @@ -8,7 +8,7 @@ Event Deletion | |||
| 8 | 8 | ||
| 9 | A special event with kind `5`, meaning "deletion" is defined as having a list of one or more `e` tags, each referencing an event the author is requesting to be deleted. | 9 | A special event with kind `5`, meaning "deletion" is defined as having a list of one or more `e` tags, each referencing an event the author is requesting to be deleted. |
| 10 | 10 | ||
| 11 | Each tag entry must contain an "e" event id intended for deletion. | 11 | Each tag entry must contain an "e" event id and/or NIP-33 `a` tags intended for deletion. |
| 12 | 12 | ||
| 13 | The event's `content` field MAY contain a text note describing the reason for the deletion. | 13 | The event's `content` field MAY contain a text note describing the reason for the deletion. |
| 14 | 14 | ||
| @@ -20,7 +20,8 @@ For example: | |||
| 20 | "pubkey": <32-bytes hex-encoded public key of the event creator>, | 20 | "pubkey": <32-bytes hex-encoded public key of the event creator>, |
| 21 | "tags": [ | 21 | "tags": [ |
| 22 | ["e", "dcd59..464a2"], | 22 | ["e", "dcd59..464a2"], |
| 23 | ["e", "968c5..ad7a4"] | 23 | ["e", "968c5..ad7a4"], |
| 24 | ["a", "<kind>:<pubkey>:<d-identifier>"] | ||
| 24 | ], | 25 | ], |
| 25 | "content": "these posts were published by accident", | 26 | "content": "these posts were published by accident", |
| 26 | ...other fields | 27 | ...other fields |
| @@ -6,11 +6,10 @@ Reposts | |||
| 6 | 6 | ||
| 7 | `draft` `optional` `author:jb55` `author:fiatjaf` `author:arthurfranca` | 7 | `draft` `optional` `author:jb55` `author:fiatjaf` `author:arthurfranca` |
| 8 | 8 | ||
| 9 | A repost is a `kind 6` note that is used to signal to followers | 9 | A repost is a `kind 6` event that is used to signal to followers |
| 10 | that another event is worth reading. | 10 | that a `kind 1` text note is worth reading. |
| 11 | 11 | ||
| 12 | The `content` of a repost event is empty. Optionally, it MAY contain | 12 | The `content` of a repost event is _the stringified JSON of the reposted note_. It MAY also be empty, but that is not recommended. |
| 13 | the stringified JSON of the reposted note event for quick look up. | ||
| 14 | 13 | ||
| 15 | The repost event MUST include an `e` tag with the `id` of the note that is | 14 | The repost event MUST include an `e` tag with the `id` of the note that is |
| 16 | being reposted. That tag MUST include a relay URL as its third entry | 15 | being reposted. That tag MUST include a relay URL as its third entry |
| @@ -21,5 +20,15 @@ reposted. | |||
| 21 | 20 | ||
| 22 | ## Quote Reposts | 21 | ## Quote Reposts |
| 23 | 22 | ||
| 24 | Quote reposts are `kind 1` events with an embedded `e` tag (see [NIP-08](08.md) and [NIP-27](27.md)). | 23 | Quote reposts are `kind 1` events with an embedded `e` tag |
| 25 | Because a quote repost includes an `e` tag, it may show up along replies to the reposted note. | 24 | (see [NIP-08](08.md) and [NIP-27](27.md)). Because a quote repost includes |
| 25 | an `e` tag, it may show up along replies to the reposted note. | ||
| 26 | |||
| 27 | ## Generic Reposts | ||
| 28 | |||
| 29 | Since `kind 6` reposts are reserved for `kind 1` contents, we use `kind 16` | ||
| 30 | as a "generic repost", that can include any kind of event inside other than | ||
| 31 | `kind 1`. | ||
| 32 | |||
| 33 | `kind 16` reposts SHOULD contain a `k` tag with the stringified kind number | ||
| 34 | of the reposted event as its value. | ||
| @@ -1,4 +1,4 @@ | |||
| 1 | NIP: 26 | 1 | NIP-26 |
| 2 | ======= | 2 | ======= |
| 3 | 3 | ||
| 4 | Delegated Event Signing | 4 | Delegated Event Signing |
| @@ -52,7 +52,9 @@ For example, the following condition strings are valid: | |||
| 52 | - `kind=0&kind=1&created_at>1675721813` | 52 | - `kind=0&kind=1&created_at>1675721813` |
| 53 | - `kind=1&created_at>1674777689&created_at<1675721813` | 53 | - `kind=1&created_at>1674777689&created_at<1675721813` |
| 54 | 54 | ||
| 55 | For the vast majority of use-cases, it is advisable that query strings should include a `created_at` ***after*** condition reflecting the current time, to prevent the delegatee from publishing historic notes on the delegator's behalf. | 55 | For the vast majority of use-cases, it is advisable that: |
| 56 | 1. Query strings should include a `created_at` ***after*** condition reflecting the current time, to prevent the delegatee from publishing historic notes on the delegator's behalf. | ||
| 57 | 2. Query strings should include a `created_at` ***before*** condition that is not empty and is not some extremely distant time in the future. If delegations are not limited in time scope, they expose similar security risks to simply using the root key for authentication. | ||
| 56 | 58 | ||
| 57 | #### Example | 59 | #### Example |
| 58 | 60 | ||
| @@ -105,4 +107,4 @@ Clients should display the delegated note as if it was published directly by the | |||
| 105 | 107 | ||
| 106 | Relays should answer requests such as `["REQ", "", {"authors": ["A"]}]` by querying both the `pubkey` and delegation tags `[1]` value. | 108 | Relays should answer requests such as `["REQ", "", {"authors": ["A"]}]` by querying both the `pubkey` and delegation tags `[1]` value. |
| 107 | 109 | ||
| 108 | Relays SHOULD allow the delegator (8e0d3d3e) to delete the events published by the delegatee (477318cf). \ No newline at end of file | 110 | Relays SHOULD allow the delegator (8e0d3d3e) to delete the events published by the delegatee (477318cf). |
| @@ -0,0 +1,15 @@ | |||
| 1 | NIP-31 | ||
| 2 | ====== | ||
| 3 | |||
| 4 | Dealing with unknown event kinds | ||
| 5 | -------------------------------- | ||
| 6 | |||
| 7 | `draft` `optional` `author:pablof7z` `author:fiatjaf` | ||
| 8 | |||
| 9 | When creating a new custom event kind that is part of a custom protocol and isn't meant to be read as text (like `kind:1`), clients should use an `alt` tag to write a short human-readable plaintext summary of what that event is about. | ||
| 10 | |||
| 11 | The intent is that social clients, used to display only `kind:1` notes, can still show something in case a custom event pops up in their timelines. The content of the `alt` tag should provide enough context for a user that doesn't know anything about this event kind to understand what it is. | ||
| 12 | |||
| 13 | These clients that only know `kind:1` are not expected to ask relays for events of different kinds, but users could still reference these weird events on their notes, and without proper context these could be nonsensical notes. Having the fallback text makes that situation much better -- even if only for making the user aware that they should try to view that custom event elsewhere. | ||
| 14 | |||
| 15 | `kind:1`-centric clients can make interacting with these event kinds more functional by supporting [NIP-89](https://github.com/nostr-protocol/nips/blob/master/89.md). | ||
| @@ -0,0 +1,68 @@ | |||
| 1 | NIP-98 | ||
| 2 | ====== | ||
| 3 | |||
| 4 | HTTP Auth | ||
| 5 | ------------------------- | ||
| 6 | |||
| 7 | `draft` `optional` `author:kieran` `author:melvincarvalho` | ||
| 8 | |||
| 9 | This NIP defines an ephemerial event used to authorize requests to HTTP servers using nostr events. | ||
| 10 | |||
| 11 | This is useful for HTTP services which are build for Nostr and deal with Nostr user accounts. | ||
| 12 | |||
| 13 | ## Nostr event | ||
| 14 | |||
| 15 | A `kind 27235` (In reference to [RFC 7235](https://www.rfc-editor.org/rfc/rfc7235)) event is used. | ||
| 16 | |||
| 17 | The `content` SHOULD be empty. | ||
| 18 | |||
| 19 | The following tags are defined as REQUIRED. | ||
| 20 | |||
| 21 | * `u` - absolute URL | ||
| 22 | * `method` - HTTP Request Method | ||
| 23 | |||
| 24 | Example event: | ||
| 25 | ```json | ||
| 26 | { | ||
| 27 | "id": "fe964e758903360f28d8424d092da8494ed207cba823110be3a57dfe4b578734", | ||
| 28 | "pubkey": "63fe6318dc58583cfe16810f86dd09e18bfd76aabc24a0081ce2856f330504ed", | ||
| 29 | "content": "", | ||
| 30 | "kind": 27235, | ||
| 31 | "created_at": 1682327852, | ||
| 32 | "tags": [ | ||
| 33 | [ | ||
| 34 | "u", | ||
| 35 | "https://api.snort.social/api/v1/n5sp/list" | ||
| 36 | ], | ||
| 37 | [ | ||
| 38 | "method", | ||
| 39 | "GET" | ||
| 40 | ] | ||
| 41 | ], | ||
| 42 | "sig": "5ed9d8ec958bc854f997bdc24ac337d005af372324747efe4a00e24f4c30437ff4dd8308684bed467d9d6be3e5a517bb43b1732cc7d33949a3aaf86705c22184" | ||
| 43 | } | ||
| 44 | ``` | ||
| 45 | |||
| 46 | Servers MUST perform the following checks in order to validate the event: | ||
| 47 | 1. The `kind` MUST be `27235`. | ||
| 48 | 2. The `created_at` MUST be within a reasonable time window (suggestion 60 seconds). | ||
| 49 | 3. The `u` tag MUST be exactly the same as the absolute request URL (including query parameters). | ||
| 50 | 4. The `method` tag MUST be the same HTTP method used for the requested resource. | ||
| 51 | |||
| 52 | When the request contains a body (as in POST/PUT/PATCH methods) clients SHOULD include a SHA256 hash of the request body in a `payload` tag as hex (`["payload", "<sha256-hex>"]`), servers MAY check this to validate that the requested payload is authorized. | ||
| 53 | |||
| 54 | If one of the checks was to fail the server SHOULD respond with a 401 Unauthorized response code. | ||
| 55 | |||
| 56 | All other checks which server MAY do are OPTIONAL, and implementation specific. | ||
| 57 | |||
| 58 | ## Request Flow | ||
| 59 | |||
| 60 | Using the `Authorization` header, the `kind 27235` event MUST be `base64` encoded and use the Authorization scheme `Nostr` | ||
| 61 | |||
| 62 | Example HTTP Authorization header: | ||
| 63 | ``` | ||
| 64 | Authorization: Nostr eyJpZCI6ImZlOTY0ZTc1ODkwMzM2MGYyOGQ4NDI0ZDA5MmRhODQ5NGVkMjA3Y2JhODIzMTEwYmUzYTU3ZGZlNGI1Nzg3MzQiLCJwdWJrZXkiOiI2M2ZlNjMxOGRjNTg1ODNjZmUxNjgxMGY4NmRkMDllMThiZmQ3NmFhYmMyNGEwMDgxY2UyODU2ZjMzMDUwNGVkIiwiY29udGVudCI6IiIsImtpbmQiOjI3MjM1LCJjcmVhdGVkX2F0IjoxNjgyMzI3ODUyLCJ0YWdzIjpbWyJ1cmwiLCJodHRwczovL2FwaS5zbm9ydC5zb2NpYWwvYXBpL3YxL241c3AvbGlzdCJdLFsibWV0aG9kIiwiR0VUIl1dLCJzaWciOiI1ZWQ5ZDhlYzk1OGJjODU0Zjk5N2JkYzI0YWMzMzdkMDA1YWYzNzIzMjQ3NDdlZmU0YTAwZTI0ZjRjMzA0MzdmZjRkZDgzMDg2ODRiZWQ0NjdkOWQ2YmUzZTVhNTE3YmI0M2IxNzMyY2M3ZDMzOTQ5YTNhYWY4NjcwNWMyMjE4NCJ9 | ||
| 65 | ``` | ||
| 66 | |||
| 67 | ## Reference Implementations | ||
| 68 | - C# ASP.NET `AuthenticationHandler` [NostrAuth.cs](https://gist.github.com/v0l/74346ae530896115bfe2504c8cd018d3) \ No newline at end of file | ||
| @@ -46,6 +46,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos | |||
| 46 | - [NIP-27: Text Note References](27.md) | 46 | - [NIP-27: Text Note References](27.md) |
| 47 | - [NIP-28: Public Chat](28.md) | 47 | - [NIP-28: Public Chat](28.md) |
| 48 | - [NIP-30: Custom Emoji](30.md) | 48 | - [NIP-30: Custom Emoji](30.md) |
| 49 | - [NIP-31: Dealing with Unknown Events](31.md) | ||
| 49 | - [NIP-33: Parameterized Replaceable Events](33.md) | 50 | - [NIP-33: Parameterized Replaceable Events](33.md) |
| 50 | - [NIP-36: Sensitive Content](36.md) | 51 | - [NIP-36: Sensitive Content](36.md) |
| 51 | - [NIP-39: External Identities in Profiles](39.md) | 52 | - [NIP-39: External Identities in Profiles](39.md) |
| @@ -63,6 +64,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos | |||
| 63 | - [NIP-78: Application-specific data](78.md) | 64 | - [NIP-78: Application-specific data](78.md) |
| 64 | - [NIP-89: Recommended Application Handlers](89.md) | 65 | - [NIP-89: Recommended Application Handlers](89.md) |
| 65 | - [NIP-94: File Metadata](94.md) | 66 | - [NIP-94: File Metadata](94.md) |
| 67 | - [NIP-98: HTTP Auth](98.md) | ||
| 66 | 68 | ||
| 67 | ## Event Kinds | 69 | ## Event Kinds |
| 68 | 70 | ||
| @@ -74,9 +76,10 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos | |||
| 74 | | `3` | Contacts | [2](02.md) | | 76 | | `3` | Contacts | [2](02.md) | |
| 75 | | `4` | Encrypted Direct Messages | [4](04.md) | | 77 | | `4` | Encrypted Direct Messages | [4](04.md) | |
| 76 | | `5` | Event Deletion | [9](09.md) | | 78 | | `5` | Event Deletion | [9](09.md) | |
| 77 | | `6` | Reposts | [18](18.md) | | 79 | | `6` | Repost | [18](18.md) | |
| 78 | | `7` | Reaction | [25](25.md) | | 80 | | `7` | Reaction | [25](25.md) | |
| 79 | | `8` | Badge Award | [58](58.md) | | 81 | | `8` | Badge Award | [58](58.md) | |
| 82 | | `16` | Generic Repost | [18](18.md) | | ||
| 80 | | `40` | Channel Creation | [28](28.md) | | 83 | | `40` | Channel Creation | [28](28.md) | |
| 81 | | `41` | Channel Metadata | [28](28.md) | | 84 | | `41` | Channel Metadata | [28](28.md) | |
| 82 | | `42` | Channel Message | [28](28.md) | | 85 | | `42` | Channel Message | [28](28.md) | |
| @@ -94,6 +97,7 @@ They exist to document what may be implemented by [Nostr](https://github.com/nos | |||
| 94 | | `23194` | Wallet Request | [47](47.md) | | 97 | | `23194` | Wallet Request | [47](47.md) | |
| 95 | | `23195` | Wallet Response | [47](47.md) | | 98 | | `23195` | Wallet Response | [47](47.md) | |
| 96 | | `24133` | Nostr Connect | [46](46.md) | | 99 | | `24133` | Nostr Connect | [46](46.md) | |
| 100 | | `27235` | HTTP Auth | [98](98.md) | | ||
| 97 | | `30000` | Categorized People List | [51](51.md) | | 101 | | `30000` | Categorized People List | [51](51.md) | |
| 98 | | `30001` | Categorized Bookmark List | [51](51.md) | | 102 | | `30001` | Categorized Bookmark List | [51](51.md) | |
| 99 | | `30008` | Profile Badges | [58](58.md) | | 103 | | `30008` | Profile Badges | [58](58.md) | |
| @@ -146,6 +150,7 @@ When experimenting with kinds, keep in mind the classification introduced by [NI | |||
| 146 | | name | value | other parameters | NIP | | 150 | | name | value | other parameters | NIP | |
| 147 | | ----------------- | ------------------------------------ | -------------------- | ------------------------ | | 151 | | ----------------- | ------------------------------------ | -------------------- | ------------------------ | |
| 148 | | `a` | coordinates to an event | relay URL | [33](33.md), [23](23.md) | | 152 | | `a` | coordinates to an event | relay URL | [33](33.md), [23](23.md) | |
| 153 | | `alt` | Alt tag | -- | [31](31.md) | | ||
| 149 | | `d` | identifier | -- | [33](33.md) | | 154 | | `d` | identifier | -- | [33](33.md) | |
| 150 | | `e` | event id (hex) | relay URL, marker | [1](01.md), [10](10.md) | | 155 | | `e` | event id (hex) | relay URL, marker | [1](01.md), [10](10.md) | |
| 151 | | `g` | geohash | -- | [12](12.md) | | 156 | | `g` | geohash | -- | [12](12.md) | |