From 73461b47b26e5a4a9a74a10067bc1b9329001308 Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Tue, 30 Jul 2024 20:17:29 -0500 Subject: [PATCH 01/85] add rough draft for media endpoint --- buds/05.md | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 buds/05.md diff --git a/buds/05.md b/buds/05.md new file mode 100644 index 0000000..97d92b7 --- /dev/null +++ b/buds/05.md @@ -0,0 +1,87 @@ +BUD-05 +====== + +Media optimization endpoints + +`draft` `optional` + +Defines the `PUT /media`, `GET /media/` and `DELETE /media/` endpoints for processing and optimizing media + +## Task Object + +The task object defines a long running media processing task on the server. A task MUST have the following fields + + - `id` A unique id for the task **(required)** + - `status` The status of the job, either `running`, `complete`, or `canceled` **(required)** + - `message` A human-readable description of what is happening or the current status *(optional)* + - `progress` A number from 0 to 100 representing the percentage of the task that is complete *(optional)* + - `blob` A full [Blob Descriptor](./02.md#blob-descriptor) **(required when `complete`)** + +## PUT /media + +The `PUT /media` endpoint MUST accept binary data in the body of the request and MAY use the `Content-Type` and `Content-Length` headers to get the MIME type and size of the media + +The server should preform any optimizations or conversions it deems necessary in order to make the media more suitable for distribution + +The endpoint MUST return a status code of `202` with `Content-Type: application/json` and a [task object](#task-object) or an [error response](./01.md#error-responses) + +Servers MAY reject a media upload for any reason and should respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection + +### Upload Authorization + +Servers may require an `upload` [authorization event](./02.md#upload-authorization-required) to identify the uploader + +If a server requires an `upload` authorization event it MUST preform all the [checks](./02.md#upload-authorization-required) that the `/upload` endpoint does, including that the `x` tag value matches the sha256 hash of the uploaded blob + +## GET /media/task + +Servers may expose a `GET /media/` endpoint to allow clients to get the results or check on the progress of a task + +The endpoint MUST return a `2xx` status code and a [task object](#task-object) if a task with `` exists or an [error response](./01.md#error-responses) + +The `blob` field MUST be set to a [Blob Descriptor](./02.md#blob-descriptor) when the task `status` is `complete` + +Servers may delete (or forget) tasks after a self determined amount of time after the task status is `complete` + +## DELETE /media/task + +Servers may expose a `DELETE /media/` endpoint to allow clients to cancel a processing request + +## Examples + +Upload image `PUT /media` +```json +{ + "id": "0e81bf11-eb84-49b8-a7f0-4c7c60254f2e", + "status": "running", + "progress": 0, + "message": "Resizing Image" +} +``` + +Example `GET /media/eb6e7ec1-b752-4740-91bb-9aaddf92bc57`: +```json +{ + "id": "eb6e7ec1-b752-4740-91bb-9aaddf92bc57", + "status": "running", + "progress": 24, + "message": "Resizing Video" +} +``` + +Example `GET /media/eb6e7ec1-b752-4740-91bb-9aaddf92bc57`: +```json +{ + "id": "eb6e7ec1-b752-4740-91bb-9aaddf92bc57", + "status": "complete", + "progress": 100, + "message": "Finished optimizing video", + "blob": { + "url": "https://cdn.example.com/b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.webm", + "sha256": "b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553", + "size": 18431531, + "type": "video/webm", + "uploaded": 1722386093 + } +} +``` From 81bd6f856f11ab1d70dea72dfbfecf49de564903 Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Mon, 9 Sep 2024 14:57:46 -0500 Subject: [PATCH 02/85] simplify media endpoint --- buds/02.md | 2 +- buds/05.md | 76 +++++++++++------------------------------------------- 2 files changed, 16 insertions(+), 62 deletions(-) diff --git a/buds/02.md b/buds/02.md index 3b9b7f0..21db72b 100644 --- a/buds/02.md +++ b/buds/02.md @@ -47,7 +47,7 @@ Servers MAY reject an upload for any reason and should respond with the appropri Servers MUST accept an authorization event when uploading blobs and should perform additional checks 1. The `t` tag MUST be set to `upload` -2. MUST contain at least one `x` tag matching the sha256 hash of the blob being uploaded +2. MUST contain at least one `x` tag matching the sha256 hash of the body of the request Example Authorization event: diff --git a/buds/05.md b/buds/05.md index 97d92b7..42233f6 100644 --- a/buds/05.md +++ b/buds/05.md @@ -1,21 +1,10 @@ -BUD-05 -====== +# BUD-05 Media optimization endpoints `draft` `optional` -Defines the `PUT /media`, `GET /media/` and `DELETE /media/` endpoints for processing and optimizing media - -## Task Object - -The task object defines a long running media processing task on the server. A task MUST have the following fields - - - `id` A unique id for the task **(required)** - - `status` The status of the job, either `running`, `complete`, or `canceled` **(required)** - - `message` A human-readable description of what is happening or the current status *(optional)* - - `progress` A number from 0 to 100 representing the percentage of the task that is complete *(optional)* - - `blob` A full [Blob Descriptor](./02.md#blob-descriptor) **(required when `complete`)** +Defines the `PUT /media` endpoint for processing and optimizing media ## PUT /media @@ -23,65 +12,30 @@ The `PUT /media` endpoint MUST accept binary data in the body of the request and The server should preform any optimizations or conversions it deems necessary in order to make the media more suitable for distribution -The endpoint MUST return a status code of `202` with `Content-Type: application/json` and a [task object](#task-object) or an [error response](./01.md#error-responses) +The endpoint MUST respond with a `2xx` status and a [blob descriptor](./02.md#blob-descriptor) of the new processed blob -Servers MAY reject a media upload for any reason and should respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection +Servers MAY reject media uploads for any reason and should respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection ### Upload Authorization -Servers may require an `upload` [authorization event](./02.md#upload-authorization-required) to identify the uploader +Servers MAY require an `upload` [authorization event](./02.md#upload-authorization-required) to identify the uploader -If a server requires an `upload` authorization event it MUST preform all the [checks](./02.md#upload-authorization-required) that the `/upload` endpoint does, including that the `x` tag value matches the sha256 hash of the uploaded blob +If a server requires an `upload` authorization event it MUST preform all the checks outlined in the [`/upload`](./02.md#upload-authorization-required) endpoint -## GET /media/task +## Limitations -Servers may expose a `GET /media/` endpoint to allow clients to get the results or check on the progress of a task +This endpoint is intentionally limited to optimizing a single blob with the goal of making it easier to distribute -The endpoint MUST return a `2xx` status code and a [task object](#task-object) if a task with `` exists or an [error response](./01.md#error-responses) +How the blob is optimized is the sole respirability of the server and the client should have no say in what optimization process is used -The `blob` field MUST be set to a [Blob Descriptor](./02.md#blob-descriptor) when the task `status` is `complete` +The goal of this endpoint is to provide a simple "trusted" optimization endpoint clients can use to optimize media for distribution -Servers may delete (or forget) tasks after a self determined amount of time after the task status is `complete` +If a longer optimization or transformation process is needed, or if the client needs to specify how a blob should be transformed. there are other tools and protocol that should be used. -## DELETE /media/task +## Client Implementation -Servers may expose a `DELETE /media/` endpoint to allow clients to cancel a processing request +Clients MAY let a user selected a "trusted processing" server for uploading images or short videos -## Examples +Once a server has been selected, the client can upload the original media to the `/media` endpoint of the trusted server and get the optimized blob back -Upload image `PUT /media` -```json -{ - "id": "0e81bf11-eb84-49b8-a7f0-4c7c60254f2e", - "status": "running", - "progress": 0, - "message": "Resizing Image" -} -``` - -Example `GET /media/eb6e7ec1-b752-4740-91bb-9aaddf92bc57`: -```json -{ - "id": "eb6e7ec1-b752-4740-91bb-9aaddf92bc57", - "status": "running", - "progress": 24, - "message": "Resizing Video" -} -``` - -Example `GET /media/eb6e7ec1-b752-4740-91bb-9aaddf92bc57`: -```json -{ - "id": "eb6e7ec1-b752-4740-91bb-9aaddf92bc57", - "status": "complete", - "progress": 100, - "message": "Finished optimizing video", - "blob": { - "url": "https://cdn.example.com/b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.webm", - "sha256": "b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553", - "size": 18431531, - "type": "video/webm", - "uploaded": 1722386093 - } -} -``` +Then optionally the client can ask the user to sign another `upload` authorization event for the new optimized blob and call the `/mirror` endpoint on other servers to distribute the blob From 2bd04954a41489afa66825662dbbe200227b4a9d Mon Sep 17 00:00:00 2001 From: Quentin Date: Tue, 10 Sep 2024 10:41:34 +0200 Subject: [PATCH 03/85] Paid storage --- README.md | 1 + buds/07.md | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 buds/07.md diff --git a/README.md b/README.md index 9c9c85c..7ca334b 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,7 @@ See the [BUDs](./buds) folder and specifically [BUD-01](./buds/01.md) and [BUD-0 - [BUD-02: Blob upload and management](./buds/02.md) - [BUD-03: User Server List](./buds/03.md) - [BUD-04: Mirroring blobs](./buds/04.md) +- [BUD-07: Paid storage](./buds/07.md) ## Event kinds diff --git a/buds/07.md b/buds/07.md new file mode 100644 index 0000000..64a74d5 --- /dev/null +++ b/buds/07.md @@ -0,0 +1,69 @@ +BUD-07 +====== + +Paid storage +--------------- + +`draft` `optional` + +Payment requirements for blob storage. + +## Payment Required + +Some servers **MAY** require payment for file storage. In that case, these endpoints **MUST** return a **402 Payment Required** status code and a `Www-Authenticate` header when the payment is required. + +- [HEAD /upload](./01.md#head-sha256---has-blob) +- [PUT /upload](./02.md#put-upload---upload-blob) +- [HEAT /](./01.md#head-sha256---has-blob) +- [GET /](./01.md#get-sha256---get-blob) + + +## Authenticate header + +The `Www-Authenticate` header is a standard HTTP header field that defines the authentication method that should be used to gain access to a resource. It is used by the server to challenge the client to authenticate itself. Using the [L402 protocol](https://github.com/lightninglabs/L402), the `Www-Authenticate` header can be used to request payment for specific blobs. + +The `Www-Authenticate` header contains the `macaroon` and `invoice` fields for servers and the `macaroon` and `preimage` fields for clients. + +- `macaroon` A base64 encoded string containing the macaroon, see [L402 macaroons](https://github.com/lightninglabs/L402/blob/master/macaroons.md). +- `invoice` A string containing LN the payment request. +- `preimage` A string containing the payment preimage. + +### Server implementation + +Servers **MUST** return a **402 Payment Required** status code along with a `Www-Authenticate` header containing the `macaroon` and `invoice` fields using the [L402 protocol](https://github.com/lightninglabs/L402) for all requests related to the blob: + +Schema: + +```http +HTTP/1.1 402 Payment Required +Www-Authenticate: L402 macaroon="",invoice="" +``` + +Example: + +```http +HTTP/1.1 402 Payment Required +Www-Authenticate: L402 macaroon="eyJJRCI6IjMyMGQyMDAwZjVjODQ0NmQ3OTgyMjBlYTMxOGY5ZDg0MmM5MWZkMjYyMTliODZhYWE2ODEzMDBjYjc4YTI2YWEiLCJ2ZXJzaW9uIjoiMCIsInBheW1lbnRfaGFzaCI6IjQzN2Q2YTg1Y2M2ZDQxMzNiYWIzZTEwNWM0NjViZjMzNTQ4ODNjNmVkNzNkZmFhODA3MDQ1ZmIyMTI4MTRmMjYiLCJ0b2tlbl9pZCI6IjExMzIiLCJsb2NhdGlvbiI6Ii9hcGkvdjIvbWVkaWEvNjZiMGU3NzFlYTM0ZDE0MTBkNTM4Nzk3MjQ0NGRiN2RkNjU3OGE5OTBhZDhmMjRjZjFiZTE1OWUwYmVkODdmYy8wNmQwM2FmYzJjZTJkYzY2ODUxMjFmNTFhZjM5ZDUyNjM2OWY5NjgyZTFhOWNiNGRiZGFlZDhlOWI1ZTJiNDI3Lm1wNCIsImNhdmVhdHMiOlsiIl19",invoice="lnbc30n1pnvscg5pp56rft56xqcdamm59epsvmes06ymctq7gjt3nfnu3mjaw6fmfuhweqhp5w48l28v60yvythn6qvnpq0lez54422a042yaw4kq8arvd68a6n7qcqzzsxqyz5vqsp5a5tz8qqf897a2psdh3gc8m72tkpfwf03p8j95tgvkwm0jx97ypqs9qxpqysgqxuv6h48rzmguqkyxdyegrwf2m9890st2mty7z68acvcp9s8ukpx5daja0tdfq4tn2lmt443kua45zh6dzuy90grz02hcfauqx999g4gpf9lqhw" +``` + +### Client implementation + +Clients `SHOULD` check the `Www-Authenticate` header recieved from the server and display the payment request to the user. If the payment is done, the client `SHOULD` use *the same macaroon* and the payment `preimage`to create a new `Www-Authenticate` header to be used in the next requests. + +Schema: + +```http +Www-Authenticate: L402 macaroon="",preimage="" +``` + +Example: + +```http +Www-Authenticate: L402 macaroon="eyJJRCI6IjMyMGQyMDAwZjVjODQ0NmQ3OTgyMjBlYTMxOGY5ZDg0MmM5MWZkMjYyMTliODZhYWE2ODEzMDBjYjc4YTI2YWEiLCJ2ZXJzaW9uIjoiMCIsInBheW1lbnRfaGFzaCI6IjQzN2Q2YTg1Y2M2ZDQxMzNiYWIzZTEwNWM0NjViZjMzNTQ4ODNjNmVkNzNkZmFhODA3MDQ1ZmIyMTI4MTRmMjYiLCJ0b2tlbl9pZCI6IjExMzIiLCJsb2NhdGlvbiI6Ii9hcGkvdjIvbWVkaWEvNjZiMGU3NzFlYTM0ZDE0MTBkNTM4Nzk3MjQ0NGRiN2RkNjU3OGE5OTBhZDhmMjRjZjFiZTE1OWUwYmVkODdmYy8wNmQwM2FmYzJjZTJkYzY2ODUxMjFmNTFhZjM5ZDUyNjM2OWY5NjgyZTFhOWNiNGRiZGFlZDhlOWI1ZTJiNDI3Lm1wNCIsImNhdmVhdHMiOlsiIl19",preimage="3e590d1336f241e858359c865802b4883ca91d47379c840af66785e2143bad22" +``` + +### Unpaid Uploads + +Some servers `MAY` accept unpaid uploads and require payment after the upload is completed. In this case, the server `MUST` return a **402 Payment Required** status code along with a `Www-Authenticate` header containing the macaroon and payment request fields using the [L402 protocol](https://github.com/lightninglabs/L402) for the endpoints described in [#payment-required](#payment-required). + +For backward compatibility, the server `SHOULD` display a QR code, JSON file, or other useful information instead of the blob in the response body. When the payment is completed, the server `MUST` replace this information with the actual uploaded file. From 17d6814fd0a01b379dbc13be8ad33aa3e3416711 Mon Sep 17 00:00:00 2001 From: Quentin <125748180+quentintaranpino@users.noreply.github.com> Date: Thu, 12 Sep 2024 09:48:05 +0200 Subject: [PATCH 04/85] Update buds/07.md Co-authored-by: hzrd149 <8001706+hzrd149@users.noreply.github.com> --- buds/07.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buds/07.md b/buds/07.md index 64a74d5..c9c9023 100644 --- a/buds/07.md +++ b/buds/07.md @@ -48,7 +48,7 @@ Www-Authenticate: L402 macaroon="eyJJRCI6IjMyMGQyMDAwZjVjODQ0NmQ3OTgyMjBlYTMxOGY ### Client implementation -Clients `SHOULD` check the `Www-Authenticate` header recieved from the server and display the payment request to the user. If the payment is done, the client `SHOULD` use *the same macaroon* and the payment `preimage`to create a new `Www-Authenticate` header to be used in the next requests. +Clients SHOULD check the `Www-Authenticate` header received from the server and display the payment request to the user. When the payment is complete the client should use *the same macaroon* and the payment `preimage` to create a new `Www-Authenticate` header to be used in the next request. Schema: From c3f7a5da0d495cae8bee9aa0c8f3c3f9ae66a552 Mon Sep 17 00:00:00 2001 From: Quentin <125748180+quentintaranpino@users.noreply.github.com> Date: Thu, 12 Sep 2024 09:48:20 +0200 Subject: [PATCH 05/85] Update buds/07.md Co-authored-by: hzrd149 <8001706+hzrd149@users.noreply.github.com> --- buds/07.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buds/07.md b/buds/07.md index c9c9023..9c498b4 100644 --- a/buds/07.md +++ b/buds/07.md @@ -30,7 +30,7 @@ The `Www-Authenticate` header contains the `macaroon` and `invoice` fields for s ### Server implementation -Servers **MUST** return a **402 Payment Required** status code along with a `Www-Authenticate` header containing the `macaroon` and `invoice` fields using the [L402 protocol](https://github.com/lightninglabs/L402) for all requests related to the blob: +Servers MUST return a **402 Payment Required** status code along with a `Www-Authenticate` header containing the `macaroon` and `invoice` fields using the [L402 protocol](https://github.com/lightninglabs/L402) for all requests related to the blob: Schema: From b6bd9b9a943491e93974574f405a4c77c9d48c91 Mon Sep 17 00:00:00 2001 From: Quentin <125748180+quentintaranpino@users.noreply.github.com> Date: Thu, 12 Sep 2024 09:48:26 +0200 Subject: [PATCH 06/85] Update buds/07.md Co-authored-by: hzrd149 <8001706+hzrd149@users.noreply.github.com> --- buds/07.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buds/07.md b/buds/07.md index 9c498b4..e712794 100644 --- a/buds/07.md +++ b/buds/07.md @@ -10,7 +10,7 @@ Payment requirements for blob storage. ## Payment Required -Some servers **MAY** require payment for file storage. In that case, these endpoints **MUST** return a **402 Payment Required** status code and a `Www-Authenticate` header when the payment is required. +Some servers MAY require payment for file storage. In that case, these endpoints MUST return a **402 Payment Required** status code and a `Www-Authenticate` header when the payment is required. - [HEAD /upload](./01.md#head-sha256---has-blob) - [PUT /upload](./02.md#put-upload---upload-blob) From f0ac329e9062c20466dd5123c027b7cc3cf3dd49 Mon Sep 17 00:00:00 2001 From: Quentin <125748180+quentintaranpino@users.noreply.github.com> Date: Thu, 12 Sep 2024 09:48:34 +0200 Subject: [PATCH 07/85] Update buds/07.md Co-authored-by: hzrd149 <8001706+hzrd149@users.noreply.github.com> --- buds/07.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buds/07.md b/buds/07.md index e712794..4d5e02b 100644 --- a/buds/07.md +++ b/buds/07.md @@ -64,6 +64,6 @@ Www-Authenticate: L402 macaroon="eyJJRCI6IjMyMGQyMDAwZjVjODQ0NmQ3OTgyMjBlYTMxOGY ### Unpaid Uploads -Some servers `MAY` accept unpaid uploads and require payment after the upload is completed. In this case, the server `MUST` return a **402 Payment Required** status code along with a `Www-Authenticate` header containing the macaroon and payment request fields using the [L402 protocol](https://github.com/lightninglabs/L402) for the endpoints described in [#payment-required](#payment-required). +Some servers MAY accept unpaid uploads and require payment after the upload is completed. In this case, the server MUST return a **402 Payment Required** status code along with a `Www-Authenticate` header containing the macaroon and payment request fields using the [L402 protocol](https://github.com/lightninglabs/L402) for the endpoints described in [#payment-required](#payment-required). For backward compatibility, the server `SHOULD` display a QR code, JSON file, or other useful information instead of the blob in the response body. When the payment is completed, the server `MUST` replace this information with the actual uploaded file. From 7a57b0c19a8e1e65aecf988b525925664bd729bf Mon Sep 17 00:00:00 2001 From: quentintaranpino Date: Thu, 12 Sep 2024 10:00:58 +0200 Subject: [PATCH 08/85] Backward compatibility proposal --- buds/07.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/buds/07.md b/buds/07.md index 4d5e02b..34feb59 100644 --- a/buds/07.md +++ b/buds/07.md @@ -62,8 +62,6 @@ Example: Www-Authenticate: L402 macaroon="eyJJRCI6IjMyMGQyMDAwZjVjODQ0NmQ3OTgyMjBlYTMxOGY5ZDg0MmM5MWZkMjYyMTliODZhYWE2ODEzMDBjYjc4YTI2YWEiLCJ2ZXJzaW9uIjoiMCIsInBheW1lbnRfaGFzaCI6IjQzN2Q2YTg1Y2M2ZDQxMzNiYWIzZTEwNWM0NjViZjMzNTQ4ODNjNmVkNzNkZmFhODA3MDQ1ZmIyMTI4MTRmMjYiLCJ0b2tlbl9pZCI6IjExMzIiLCJsb2NhdGlvbiI6Ii9hcGkvdjIvbWVkaWEvNjZiMGU3NzFlYTM0ZDE0MTBkNTM4Nzk3MjQ0NGRiN2RkNjU3OGE5OTBhZDhmMjRjZjFiZTE1OWUwYmVkODdmYy8wNmQwM2FmYzJjZTJkYzY2ODUxMjFmNTFhZjM5ZDUyNjM2OWY5NjgyZTFhOWNiNGRiZGFlZDhlOWI1ZTJiNDI3Lm1wNCIsImNhdmVhdHMiOlsiIl19",preimage="3e590d1336f241e858359c865802b4883ca91d47379c840af66785e2143bad22" ``` -### Unpaid Uploads +### Backward compatibility -Some servers MAY accept unpaid uploads and require payment after the upload is completed. In this case, the server MUST return a **402 Payment Required** status code along with a `Www-Authenticate` header containing the macaroon and payment request fields using the [L402 protocol](https://github.com/lightninglabs/L402) for the endpoints described in [#payment-required](#payment-required). - -For backward compatibility, the server `SHOULD` display a QR code, JSON file, or other useful information instead of the blob in the response body. When the payment is completed, the server `MUST` replace this information with the actual uploaded file. +For backward compatibility, when a client requests an unpaid blob, the server `SHOULD` return alternative information, such as a QR code, a JSON file, or other useful data in the response body. This serves as a placeholder, clearly indicating that the actual file is unavailable until payment is made. Once the payment is completed, the server `MUST` replace this placeholder with the actual blob in subsequent requests. This ensures that legacy clients still receive meaningful responses without breaking functionality, while supporting the new payment logic. \ No newline at end of file From 40a7cd943cb42fa43bb833615232a3d54a7f5ee6 Mon Sep 17 00:00:00 2001 From: quentintaranpino Date: Thu, 12 Sep 2024 10:04:30 +0200 Subject: [PATCH 09/85] fix typos --- buds/07.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buds/07.md b/buds/07.md index 34feb59..a9aa3f2 100644 --- a/buds/07.md +++ b/buds/07.md @@ -64,4 +64,4 @@ Www-Authenticate: L402 macaroon="eyJJRCI6IjMyMGQyMDAwZjVjODQ0NmQ3OTgyMjBlYTMxOGY ### Backward compatibility -For backward compatibility, when a client requests an unpaid blob, the server `SHOULD` return alternative information, such as a QR code, a JSON file, or other useful data in the response body. This serves as a placeholder, clearly indicating that the actual file is unavailable until payment is made. Once the payment is completed, the server `MUST` replace this placeholder with the actual blob in subsequent requests. This ensures that legacy clients still receive meaningful responses without breaking functionality, while supporting the new payment logic. \ No newline at end of file +For backward compatibility, when a client requests an unpaid blob, the server SHOULD return alternative information, such as a QR code, a JSON file, or other useful data in the response body. This serves as a placeholder, clearly indicating that the actual file is unavailable until payment is made. Once the payment is completed, the server MUST replace this placeholder with the actual blob in subsequent requests. This ensures that legacy clients still receive meaningful responses without breaking functionality, while supporting the new payment logic. \ No newline at end of file From cd778dec22d2ef529b7ab46e3bb8531a60a14525 Mon Sep 17 00:00:00 2001 From: quentintaranpino Date: Mon, 16 Sep 2024 09:22:58 +0200 Subject: [PATCH 10/85] change backward compatibility text --- buds/07.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buds/07.md b/buds/07.md index a9aa3f2..ecc639c 100644 --- a/buds/07.md +++ b/buds/07.md @@ -64,4 +64,4 @@ Www-Authenticate: L402 macaroon="eyJJRCI6IjMyMGQyMDAwZjVjODQ0NmQ3OTgyMjBlYTMxOGY ### Backward compatibility -For backward compatibility, when a client requests an unpaid blob, the server SHOULD return alternative information, such as a QR code, a JSON file, or other useful data in the response body. This serves as a placeholder, clearly indicating that the actual file is unavailable until payment is made. Once the payment is completed, the server MUST replace this placeholder with the actual blob in subsequent requests. This ensures that legacy clients still receive meaningful responses without breaking functionality, while supporting the new payment logic. \ No newline at end of file +For backward compatibility with image and video uploads, the server MAY return an image or video displaying a QR code or other useful information instead of the original blob. When the payment is completed, the server SHOULD replace this information with the original uploaded blob. \ No newline at end of file From c746be27e350ec0078d00d63955994c7e500f124 Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Tue, 29 Oct 2024 13:11:34 -0300 Subject: [PATCH 11/85] X-Reason, a header for all user-facing error messages to go. --- buds/01.md | 4 ++++ buds/06.md | 17 ++++++++--------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/buds/01.md b/buds/01.md index 146717f..f3bed29 100644 --- a/buds/01.md +++ b/buds/01.md @@ -10,6 +10,10 @@ _All pubkeys MUST be in hex format_ Servers MUST set the `Access-Control-Allow-Origin: *`, `Access-Control-Allow-Headers: Authorization,*` and `Access-Control-Allow-Methods: GET, PUT, DELETE` headers on all endpoints to ensure compatibility with apps hosted on other domains +## Error responses + +Every time a server sends an error response (HTTP status codes >=400), it may include a human-readable header `X-Reason` that can be displayed to the user. + ## Authorization events Authorization events are used to identify the users to the server diff --git a/buds/06.md b/buds/06.md index c587032..739404b 100644 --- a/buds/06.md +++ b/buds/06.md @@ -8,14 +8,13 @@ Defines how clients can verify if the upload can be completed before sending the ## HEAD /upload - Upload requirements -The `HEAD /upload` endpoint `MUST` use the `X-SHA-256`, `X-Content-Type` and `X-Content-Length` headers sent by client to get the SHA-256 hash, MIME type and size of the blob that will be uploaded, returning a HTTP status code and a custom header `X-Upload-Message` to indicate some human readable message about the upload requirements. +The `HEAD /upload` endpoint `MUST` use the `X-SHA-256`, `X-Content-Type` and `X-Content-Length` headers sent by client to get the SHA-256 hash, MIME type and size of the blob that will be uploaded, returning a HTTP status code and a custom header `X-Reason` to indicate some human readable message about the upload requirements. ### Headers - `X-SHA-256`: A string that represents the blob's SHA-256 hash. - `X-Content-Length`: An integer that represents the blob size in bytes. - `X-Content-Type`: A string that specifies the blob's MIME type, like `application/pdf` or `image/png`. -- `X-Upload-Message`: A human readable message that explains the reason why the upload cannot proceed. ### Upload Authorization @@ -39,36 +38,36 @@ Example response from the server if the upload can be done: HTTP/1.1 200 OK ``` -If the upload cannot proceed, the server `MUST` return an appropriate `4xx` HTTP status code and a custom header `X-Upload-Message` with a human readable error message. +If the upload cannot proceed, the server `MUST` return an appropriate `4xx` HTTP status code and a custom header `X-Reason` with a human readable error message. Some examples of error messages: ```http HTTP/1.1 400 Bad Request -X-Upload-Message: Invalid X-SHA-256 header format. Expected a string. +X-Reason: Invalid X-SHA-256 header format. Expected a string. ``` ```http HTTP/1.1 401 Unauthorized -X-Upload-Message: Authorization required for uploading video files. +X-Reason: Authorization required for uploading video files. ``` ```http HTTP/1.1 403 Forbidden -X-Upload-Message: SHA-256 hash banned. +X-Reason: SHA-256 hash banned. ``` ```http HTTP/1.1 411 Length Required -X-Upload-Message: Missing X-Content-Length header. +X-Reason: Missing X-Content-Length header. ``` ```http HTTP/1.1 413 Content Too Large -X-Upload-Message: File too large. Max allowed size is 100MB. +X-Reason: File too large. Max allowed size is 100MB. ``` ```http HTTP/1.1 415 Unsupported Media Type -X-Upload-Message: Unsupported file type. +X-Reason: Unsupported file type. ``` From 942fb60e976c83eecd938d950cfc69d67a07ff8c Mon Sep 17 00:00:00 2001 From: Quentin Date: Fri, 1 Nov 2024 10:55:49 +0100 Subject: [PATCH 12/85] Update BUD-07 for multiple L2; discard L402 --- buds/07.md | 93 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 63 insertions(+), 30 deletions(-) diff --git a/buds/07.md b/buds/07.md index ecc639c..0ee6ae9 100644 --- a/buds/07.md +++ b/buds/07.md @@ -10,58 +10,91 @@ Payment requirements for blob storage. ## Payment Required -Some servers MAY require payment for file storage. In that case, these endpoints MUST return a **402 Payment Required** status code and a `Www-Authenticate` header when the payment is required. +Some servers MAY require payment for file storage. In that case, these endpoints MUST return a **402 Payment Required** status code and a `X-Payment` header when the payment is required. - [HEAD /upload](./01.md#head-sha256---has-blob) - [PUT /upload](./02.md#put-upload---upload-blob) - [HEAT /](./01.md#head-sha256---has-blob) - [GET /](./01.md#get-sha256---get-blob) +## Server header -## Authenticate header +The `X-Payment` header is used by the server to inform the client that payment is required for the requested operation, MUST contain the following fields: -The `Www-Authenticate` header is a standard HTTP header field that defines the authentication method that should be used to gain access to a resource. It is used by the server to challenge the client to authenticate itself. Using the [L402 protocol](https://github.com/lightninglabs/L402), the `Www-Authenticate` header can be used to request payment for specific blobs. +- blob: The blob to be paid. +- amount: The amount to be paid (*optional*). +- payment_method: The payment system to be used (e.g., cashu, lightning, liquid). +- payment_details: L2 specific payment details. -The `Www-Authenticate` header contains the `macaroon` and `invoice` fields for servers and the `macaroon` and `preimage` fields for clients. +Each payment method has its own requirements and the server SHOULD provide the necessary information for the client to complete the payment. -- `macaroon` A base64 encoded string containing the macaroon, see [L402 macaroons](https://github.com/lightninglabs/L402/blob/master/macaroons.md). -- `invoice` A string containing LN the payment request. -- `preimage` A string containing the payment preimage. +Example for cashu: -### Server implementation +```json +{ + "blob": "481d5f1a374e3750518db22337bc6cb3be5be615d550ba189c9a9a55f6d55644", + "payment_method": "cashu", + "payment_details": { + "amount": "300", + "mints": "https://example.com", + "unit": "sat", + "pubkey": "0a3bce8b6005175d25432244340912dfa431a0d62681d9720cda9196398d7222" + } +} +``` -Servers MUST return a **402 Payment Required** status code along with a `Www-Authenticate` header containing the `macaroon` and `invoice` fields using the [L402 protocol](https://github.com/lightninglabs/L402) for all requests related to the blob: +Example for lightning: + +```json +{ + "blob": "481d5f1a374e3750518db22337bc6cb3be5be615d550ba189c9a9a55f6d55644", + "amount": "300", + "payment_method": "lightning", + "payment_details": { + "payment_request": "lnbc300n1pw4..:", + } +} + +Example for liquid: + +```json +{ + "blob": "481d5f1a374e3750518db22337bc6cb3be5be615d550ba189c9a9a55f6d55644", + "payment_method": "liquid", + "payment_details": { + "payment_request": { + "address": "VJLgF1s3...", + "asset_id": "6f0279e9ed...", + "amount": 0.000300, + "memo": "test" + } + } +} +``` Schema: ```http HTTP/1.1 402 Payment Required -Www-Authenticate: L402 macaroon="",invoice="" -``` - -Example: - -```http -HTTP/1.1 402 Payment Required -Www-Authenticate: L402 macaroon="eyJJRCI6IjMyMGQyMDAwZjVjODQ0NmQ3OTgyMjBlYTMxOGY5ZDg0MmM5MWZkMjYyMTliODZhYWE2ODEzMDBjYjc4YTI2YWEiLCJ2ZXJzaW9uIjoiMCIsInBheW1lbnRfaGFzaCI6IjQzN2Q2YTg1Y2M2ZDQxMzNiYWIzZTEwNWM0NjViZjMzNTQ4ODNjNmVkNzNkZmFhODA3MDQ1ZmIyMTI4MTRmMjYiLCJ0b2tlbl9pZCI6IjExMzIiLCJsb2NhdGlvbiI6Ii9hcGkvdjIvbWVkaWEvNjZiMGU3NzFlYTM0ZDE0MTBkNTM4Nzk3MjQ0NGRiN2RkNjU3OGE5OTBhZDhmMjRjZjFiZTE1OWUwYmVkODdmYy8wNmQwM2FmYzJjZTJkYzY2ODUxMjFmNTFhZjM5ZDUyNjM2OWY5NjgyZTFhOWNiNGRiZGFlZDhlOWI1ZTJiNDI3Lm1wNCIsImNhdmVhdHMiOlsiIl19",invoice="lnbc30n1pnvscg5pp56rft56xqcdamm59epsvmes06ymctq7gjt3nfnu3mjaw6fmfuhweqhp5w48l28v60yvythn6qvnpq0lez54422a042yaw4kq8arvd68a6n7qcqzzsxqyz5vqsp5a5tz8qqf897a2psdh3gc8m72tkpfwf03p8j95tgvkwm0jx97ypqs9qxpqysgqxuv6h48rzmguqkyxdyegrwf2m9890st2mty7z68acvcp9s8ukpx5daja0tdfq4tn2lmt443kua45zh6dzuy90grz02hcfauqx999g4gpf9lqhw" +X-Payment: "" ``` ### Client implementation -Clients SHOULD check the `Www-Authenticate` header received from the server and display the payment request to the user. When the payment is complete the client should use *the same macaroon* and the payment `preimage` to create a new `Www-Authenticate` header to be used in the next request. +Clients MUST check the `X-Payment` header received from the server and display the payment request to the user. When the payment is complete the client MUST use the same header to inform the server that the payment was successful using this structure: + +- blob: The paid blob. +- payment_proof: The payment proof. (e.g., preimage for cashu and lightning, txid for liquid). + +```json +{ + "blob": "481d5f1a374e3750518db22337bc6cb3be5be615d550ba189c9a9a55f6d55644", + "payment_proof": "c3b9e2..." +} +``` Schema: - + ```http -Www-Authenticate: L402 macaroon="",preimage="" +X-Payment: "" ``` - -Example: - -```http -Www-Authenticate: L402 macaroon="eyJJRCI6IjMyMGQyMDAwZjVjODQ0NmQ3OTgyMjBlYTMxOGY5ZDg0MmM5MWZkMjYyMTliODZhYWE2ODEzMDBjYjc4YTI2YWEiLCJ2ZXJzaW9uIjoiMCIsInBheW1lbnRfaGFzaCI6IjQzN2Q2YTg1Y2M2ZDQxMzNiYWIzZTEwNWM0NjViZjMzNTQ4ODNjNmVkNzNkZmFhODA3MDQ1ZmIyMTI4MTRmMjYiLCJ0b2tlbl9pZCI6IjExMzIiLCJsb2NhdGlvbiI6Ii9hcGkvdjIvbWVkaWEvNjZiMGU3NzFlYTM0ZDE0MTBkNTM4Nzk3MjQ0NGRiN2RkNjU3OGE5OTBhZDhmMjRjZjFiZTE1OWUwYmVkODdmYy8wNmQwM2FmYzJjZTJkYzY2ODUxMjFmNTFhZjM5ZDUyNjM2OWY5NjgyZTFhOWNiNGRiZGFlZDhlOWI1ZTJiNDI3Lm1wNCIsImNhdmVhdHMiOlsiIl19",preimage="3e590d1336f241e858359c865802b4883ca91d47379c840af66785e2143bad22" -``` - -### Backward compatibility - -For backward compatibility with image and video uploads, the server MAY return an image or video displaying a QR code or other useful information instead of the original blob. When the payment is completed, the server SHOULD replace this information with the original uploaded blob. \ No newline at end of file From ee1fca7ef543a36dbebb75f6fbfefdc671bed547 Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Mon, 11 Nov 2024 11:54:47 +0000 Subject: [PATCH 13/85] fix headers on BUD-08 --- buds/08.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/buds/08.md b/buds/08.md index 0b79e8d..b5e2ec0 100644 --- a/buds/08.md +++ b/buds/08.md @@ -1,10 +1,12 @@ -# Nostr File Metadata Tags +# BUD-08 + +## Nostr File Metadata Tags `draft` `optional` Describes how a server could return nostr [NIP-94 File Metadata](https://github.com/nostr-protocol/nips/blob/master/94.md) tags from the `/upload` and `/mirror` endpoints -## Returning tags +### Returning tags As described in [BUD-02](./02.md#blob-descriptor) servers MAY add any additional fields to a blob descriptor From b7e4e96ed597351fc17855620b4c50249ac74d97 Mon Sep 17 00:00:00 2001 From: fiatjaf Date: Mon, 11 Nov 2024 13:03:56 -0300 Subject: [PATCH 14/85] remove old Error Responses section. --- buds/01.md | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/buds/01.md b/buds/01.md index f3bed29..d78415d 100644 --- a/buds/01.md +++ b/buds/01.md @@ -67,26 +67,6 @@ Authorization: Nostr eyJpZCI6IjhlY2JkY2RkNTMyOTIwMDEwNTUyNGExNDI4NzkxMzg4MWIzOWQ All endpoints MUST be served from the root path (eg. `https://cdn.example.com/upload`, etc). This allows clients to talk to servers interchangeably when uploading or retrieving blobs -## Error Responses - -For HTTP `4xx` and `5xx` status codes servers MUST repond with `Content-Type: application/json` and a JSON object containing `message` - -The `message` field MUST be human readable and should explain the reason for the error. Optionally servers may include other fields for the client with more information about the error - -Example Error response: - -``` -HTTP/2 401 -content-type: application/json; charset=utf-8 -content-length: 32 -access-control-allow-origin: * -access-control-expose-headers: * -access-control-allow-headers: authorization,* -access-control-allow-methods: get, put, delete - -{"message":"Missing Auth event"} -``` - ## GET /sha256 - Get Blob The `GET /` endpoint MUST return the contents of the blob with the `Content-Type` header set to the appropriate MIME type From 5c0ecbb4fab8b4017d867b9523e103ee6965ea34 Mon Sep 17 00:00:00 2001 From: Quentin Date: Tue, 12 Nov 2024 10:01:43 +0100 Subject: [PATCH 15/85] fix typo --- buds/07.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/buds/07.md b/buds/07.md index 0ee6ae9..c76c389 100644 --- a/buds/07.md +++ b/buds/07.md @@ -55,6 +55,8 @@ Example for lightning: } } +``` + Example for liquid: ```json From bf417ae115dd8e735afd5f559478ea69a55b951b Mon Sep 17 00:00:00 2001 From: Quentin Date: Mon, 18 Nov 2024 12:28:43 +0100 Subject: [PATCH 16/85] using different headers for each payment method --- buds/07.md | 148 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 105 insertions(+), 43 deletions(-) diff --git a/buds/07.md b/buds/07.md index c76c389..880c04a 100644 --- a/buds/07.md +++ b/buds/07.md @@ -10,93 +10,155 @@ Payment requirements for blob storage. ## Payment Required -Some servers MAY require payment for file storage. In that case, these endpoints MUST return a **402 Payment Required** status code and a `X-Payment` header when the payment is required. +Some servers MAY require payment for file storage. In such cases, these endpoints MUST return a **402 Payment Required** status code: -- [HEAD /upload](./01.md#head-sha256---has-blob) +- [HEAD /upload](./01.md#head-sha256---has-blob) (Optional, if [BU-06](./06.md) is implemented) - [PUT /upload](./02.md#put-upload---upload-blob) - [HEAT /](./01.md#head-sha256---has-blob) - [GET /](./01.md#get-sha256---get-blob) -## Server header +When payment is required, the server MUST include one or more `X-{payment_method}` header(s), each corresponding to a supported payment method. -The `X-Payment` header is used by the server to inform the client that payment is required for the requested operation, MUST contain the following fields: +## Server headers -- blob: The blob to be paid. -- amount: The amount to be paid (*optional*). -- payment_method: The payment system to be used (e.g., cashu, lightning, liquid). -- payment_details: L2 specific payment details. +The `X-{payment_method}` header is used by the server to inform the client that payment is required for the requested operation. The server MUST provide specific headers for each supported payment method, using the following conventions: -Each payment method has its own requirements and the server SHOULD provide the necessary information for the client to complete the payment. +- `X-{payment_method}`: Base64 UrlSafe encoded JSON with the payment details. + +Supported payment methods: + +- `X-Cashu`: Payment details for the cashu payment method. +- `X-Lightning`: Payment details for the lightning payment method. + +If a server supports multiple payment methods, it MAY send multiple `X-{payment_method}` headers in the same response. The client MUST choose one of the provided methods and proceed with the payment accordingly. + +### `X-Cashu` Header + +Fields included in the X-Cashu header: + +- identifier: The unique identifier for the payment. +- amount: The amount of ecash being requested +- mints: An array of mints that this server uses +- unit: The cashu `unit` from the `mints` +- pubkey: (optional) a 33 byte pubkey to lock the tokens too. see [NUT-11](https://github.com/cashubtc/nuts/blob/main/11.md) + +The `identifier` field is a unique reference to a specific payment request. It allows the server to distinguish between different payments for the same file or blob. The server MUST ensure that each identifier is unique and link it internally to the relevant file or blob. Example for cashu: ```json { - "blob": "481d5f1a374e3750518db22337bc6cb3be5be615d550ba189c9a9a55f6d55644", - "payment_method": "cashu", - "payment_details": { - "amount": "300", - "mints": "https://example.com", - "unit": "sat", - "pubkey": "0a3bce8b6005175d25432244340912dfa431a0d62681d9720cda9196398d7222" - } + "identifier": "23537", + "amount": "300", + "mints": ["https://example.com", "https://example2.com"], + "unit": "sat", + "pubkey": "0a3bce8b6005175d25432244340912dfa431a0d62681d9720cda9196398d7222" } ``` +```http +HTTP/1.1 402 Payment Required +X-Cashu: ewogICJpZGVudGlmaWVyIjogIjIzNTM3IiwKICAiYW1vdW50IjogIjMwMCIsCiAgIm1pbnRzIjogWyJodHRwczovL2V4YW1wbGUuY29tIiwgImh0dHBzOi8vZXhhbXBsZTIuY29tIl0sCiAgInVuaXQiOiAic2F0IiwKICAicHVia2V5IjogIjBhM2JjZThiNjAwNTE3NWQyNTQzMjI0NDM0MDkxMmRmYTQzMWEwZDYyNjgxZDk3MjBjZGE5MTk2Mzk4ZDcyMjIiCn0 +``` + +### `X-Lightning` Header + +Fields included in the X-Lightning header: + +- identifier: The unique identifier for the payment. +- amount: The amount to be paid. +- payment_request: The lightning payment request. + +The `identifier` field is a unique reference to a specific payment request. It allows the server to distinguish between different payments for the same file or blob. The server MUST ensure that each identifier is unique and link it internally to the relevant file or blob. + Example for lightning: ```json { - "blob": "481d5f1a374e3750518db22337bc6cb3be5be615d550ba189c9a9a55f6d55644", + "identifier": "23537", "amount": "300", - "payment_method": "lightning", - "payment_details": { - "payment_request": "lnbc300n1pw4..:", - } + "payment_request": "lnbc300n1pw4..:", } ``` -Example for liquid: - -```json -{ - "blob": "481d5f1a374e3750518db22337bc6cb3be5be615d550ba189c9a9a55f6d55644", - "payment_method": "liquid", - "payment_details": { - "payment_request": { - "address": "VJLgF1s3...", - "asset_id": "6f0279e9ed...", - "amount": 0.000300, - "memo": "test" - } - } -} +```http +HTTP/1.1 402 Payment Required +X-Lightning: ewogICJpZGVudGlmaWVyIjogIjIzNTM3IiwKICAiYW1vdW50IjogIjMwMCIsCiAgInBheW1lbnRfcmVxdWVzdCI6ICJsbmJjMzAwbjFwdzQuLjoiLAp9 ``` Schema: ```http HTTP/1.1 402 Payment Required -X-Payment: "" +X-Payment-{payment_method}: "" ``` + ### Client implementation -Clients MUST check the `X-Payment` header received from the server and display the payment request to the user. When the payment is complete the client MUST use the same header to inform the server that the payment was successful using this structure: +Clients MUST parse and validate all available `X-{payment_method}` headers received from the server. The client SHOULD provide a way for the user to complete the payment and retry the request using the appropiate `X-Payment-{payment_method}` header. -- blob: The paid blob. -- payment_proof: The payment proof. (e.g., preimage for cashu and lightning, txid for liquid). +- `X-{payment_method}-Payment`: Base64 UrlSafe encoded JSON with the client payment proof. + +- identifier: The unique identifier for the payment. +- payment_proof: The proof of payment, specific to the method: + + - For cashu the payment should be a serialized cashu token according to [NUT-00](https://github.com/cashubtc/nuts/blob/main/00.md#v4-tokens) + - For lightning the payment should be the preimage of the payment request according to [BOLT-11](https://github.com/lightning/bolts/blob/master/11-payment-encoding.md) + +Example for Cashu: ```json { - "blob": "481d5f1a374e3750518db22337bc6cb3be5be615d550ba189c9a9a55f6d55644", + "identifier": "23537", "payment_proof": "c3b9e2..." } + +```http +X-Cashu-Payment: ewogICJpZGVudGlmaWVyIjogIjIzNTM3IiwKICAicGF5bWVudF9wcm9vZiI6ICJjM2I5ZTIiCn0 +``` + +Example for Lightning: + +```json +{ + "identifier": "23537", + "payment_proof": "lnbc300n1pw4..." +} + +```http +X-Lightning-Payment: ewogICJpZGVudGlmaWVyIjogIjIzNTM3IiwKICAicGF5bWVudF9wcm9vZiI6ICJsbmJjMzAwbjFwdzQuLjoiCn0 ``` Schema: ```http -X-Payment: "" +X-{payment_method}-Payment: "" ``` + +### Error handling + +If the client fails to provide the payment proof (expired invoice, invalid token, etc.) the server MUST respond with **402 Payment Required** status code and include the relevant `X-{payment_method}` header(s) with updated payment details. + + +### Extending with Future Payment Methods + +To support future payment methods (e.g., other Layer 2 solutions), the specification allows the addition of new X-{payment_method} headers. Each new method MUST adhere to the following: + +Header Format: + +New methods MUST use a unique `X-{payment_method}` header containing Base64 UrlSafe encoded JSON. + +Required Fields: + +- identifier: Unique reference for the payment. +- amount: Payment amount in the method’s smallest unit. + +Backward Compatibility: + +Servers and clients MUST ignore unknown X-{payment_method} headers. + +Documentation: + +Any new payment method added in the future MUST follow the same structure as existing methods, ensuring that the `identifier` and `amount` fields are always present and well-defined. This consistency allows seamless integration of new methods without breaking compatibility for existing clients and servers. From 3524b81baca9052a33dcff091ad3ed849afbf427 Mon Sep 17 00:00:00 2001 From: Quentin Date: Mon, 18 Nov 2024 12:37:37 +0100 Subject: [PATCH 17/85] fix typos --- buds/07.md | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/buds/07.md b/buds/07.md index 880c04a..33f13c0 100644 --- a/buds/07.md +++ b/buds/07.md @@ -12,7 +12,7 @@ Payment requirements for blob storage. Some servers MAY require payment for file storage. In such cases, these endpoints MUST return a **402 Payment Required** status code: -- [HEAD /upload](./01.md#head-sha256---has-blob) (Optional, if [BU-06](./06.md) is implemented) +- [HEAD /upload](./01.md#head-sha256---has-blob) (Optional, if [BUD-06](./06.md) is implemented) - [PUT /upload](./02.md#put-upload---upload-blob) - [HEAT /](./01.md#head-sha256---has-blob) - [GET /](./01.md#get-sha256---get-blob) @@ -36,11 +36,11 @@ If a server supports multiple payment methods, it MAY send multiple `X-{payment_ Fields included in the X-Cashu header: -- identifier: The unique identifier for the payment. -- amount: The amount of ecash being requested -- mints: An array of mints that this server uses -- unit: The cashu `unit` from the `mints` -- pubkey: (optional) a 33 byte pubkey to lock the tokens too. see [NUT-11](https://github.com/cashubtc/nuts/blob/main/11.md) +- `identifier`: The unique identifier for the payment. +- `amount`: The amount of ecash being requested +- `mints`: An array of mints that this server uses +- `unit`: The cashu `unit` from the `mints` +- `pubkey`: (optional) a 33 byte pubkey to lock the tokens too. see [NUT-11](https://github.com/cashubtc/nuts/blob/main/11.md) The `identifier` field is a unique reference to a specific payment request. It allows the server to distinguish between different payments for the same file or blob. The server MUST ensure that each identifier is unique and link it internally to the relevant file or blob. @@ -65,9 +65,9 @@ X-Cashu: ewogICJpZGVudGlmaWVyIjogIjIzNTM3IiwKICAiYW1vdW50IjogIjMwMCIsCiAgIm1pbnR Fields included in the X-Lightning header: -- identifier: The unique identifier for the payment. -- amount: The amount to be paid. -- payment_request: The lightning payment request. +- `identifier`: The unique identifier for the payment. +- `amount`: The amount to be paid. +- `payment_request`: The lightning payment request. The `identifier` field is a unique reference to a specific payment request. It allows the server to distinguish between different payments for the same file or blob. The server MUST ensure that each identifier is unique and link it internally to the relevant file or blob. @@ -101,8 +101,8 @@ Clients MUST parse and validate all available `X-{payment_method}` headers recei - `X-{payment_method}-Payment`: Base64 UrlSafe encoded JSON with the client payment proof. -- identifier: The unique identifier for the payment. -- payment_proof: The proof of payment, specific to the method: +- `identifier`: The unique identifier for the payment. +- `payment_proof`: The proof of payment, specific to the method: - For cashu the payment should be a serialized cashu token according to [NUT-00](https://github.com/cashubtc/nuts/blob/main/00.md#v4-tokens) - For lightning the payment should be the preimage of the payment request according to [BOLT-11](https://github.com/lightning/bolts/blob/master/11-payment-encoding.md) @@ -114,6 +114,7 @@ Example for Cashu: "identifier": "23537", "payment_proof": "c3b9e2..." } +``` ```http X-Cashu-Payment: ewogICJpZGVudGlmaWVyIjogIjIzNTM3IiwKICAicGF5bWVudF9wcm9vZiI6ICJjM2I5ZTIiCn0 @@ -152,8 +153,8 @@ New methods MUST use a unique `X-{payment_method}` header containing Base64 UrlS Required Fields: -- identifier: Unique reference for the payment. -- amount: Payment amount in the method’s smallest unit. +- `identifier`: Unique reference for the payment. +- `amount`: Payment amount in the method’s smallest unit. Backward Compatibility: From b450680b00b79544f648301b33ec13d7ae2aaf73 Mon Sep 17 00:00:00 2001 From: Quentin Date: Mon, 18 Nov 2024 12:39:10 +0100 Subject: [PATCH 18/85] fix typo --- buds/07.md | 1 + 1 file changed, 1 insertion(+) diff --git a/buds/07.md b/buds/07.md index 33f13c0..071f6e9 100644 --- a/buds/07.md +++ b/buds/07.md @@ -127,6 +127,7 @@ Example for Lightning: "identifier": "23537", "payment_proof": "lnbc300n1pw4..." } +``` ```http X-Lightning-Payment: ewogICJpZGVudGlmaWVyIjogIjIzNTM3IiwKICAicGF5bWVudF9wcm9vZiI6ICJsbmJjMzAwbjFwdzQuLjoiCn0 From 8a4728e3e6085157867be9562832561dff1d9372 Mon Sep 17 00:00:00 2001 From: Quentin Date: Mon, 18 Nov 2024 12:41:43 +0100 Subject: [PATCH 19/85] remove some texts --- buds/07.md | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/buds/07.md b/buds/07.md index 071f6e9..37355f9 100644 --- a/buds/07.md +++ b/buds/07.md @@ -148,19 +148,9 @@ If the client fails to provide the payment proof (expired invoice, invalid token To support future payment methods (e.g., other Layer 2 solutions), the specification allows the addition of new X-{payment_method} headers. Each new method MUST adhere to the following: -Header Format: - New methods MUST use a unique `X-{payment_method}` header containing Base64 UrlSafe encoded JSON. -Required Fields: +**Required Fields:** - `identifier`: Unique reference for the payment. -- `amount`: Payment amount in the method’s smallest unit. - -Backward Compatibility: - -Servers and clients MUST ignore unknown X-{payment_method} headers. - -Documentation: - -Any new payment method added in the future MUST follow the same structure as existing methods, ensuring that the `identifier` and `amount` fields are always present and well-defined. This consistency allows seamless integration of new methods without breaking compatibility for existing clients and servers. +- `amount`: Payment amount in the method’s smallest unit. \ No newline at end of file From 970fc2b072818d8b10ec892262ec991412eefed1 Mon Sep 17 00:00:00 2001 From: Quentin Date: Mon, 18 Nov 2024 12:41:51 +0100 Subject: [PATCH 20/85] fix typo --- buds/07.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buds/07.md b/buds/07.md index 37355f9..3876e9b 100644 --- a/buds/07.md +++ b/buds/07.md @@ -153,4 +153,4 @@ New methods MUST use a unique `X-{payment_method}` header containing Base64 UrlS **Required Fields:** - `identifier`: Unique reference for the payment. -- `amount`: Payment amount in the method’s smallest unit. \ No newline at end of file +- `amount`: Payment amount in the method’s smallest unit. From 0aa5a9dd6f033ce5be4bbc29663ac4e5e255500b Mon Sep 17 00:00:00 2001 From: Quentin Date: Wed, 20 Nov 2024 12:14:00 +0100 Subject: [PATCH 21/85] Refactored to clarify payment header encoding and method-specific requirements --- buds/07.md | 114 +++++++++++++---------------------------------------- 1 file changed, 28 insertions(+), 86 deletions(-) diff --git a/buds/07.md b/buds/07.md index 3876e9b..aad8b53 100644 --- a/buds/07.md +++ b/buds/07.md @@ -17,140 +17,82 @@ Some servers MAY require payment for file storage. In such cases, these endpoint - [HEAT /](./01.md#head-sha256---has-blob) - [GET /](./01.md#get-sha256---get-blob) -When payment is required, the server MUST include one or more `X-{payment_method}` header(s), each corresponding to a supported payment method. +When payment is required, the server MUST include one or more `X-{payment_method}` header(s), each corresponding to a supported payment method. The client MUST choose one of the provided methods and proceed with the payment accordingly. ## Server headers The `X-{payment_method}` header is used by the server to inform the client that payment is required for the requested operation. The server MUST provide specific headers for each supported payment method, using the following conventions: -- `X-{payment_method}`: Base64 UrlSafe encoded JSON with the payment details. - Supported payment methods: -- `X-Cashu`: Payment details for the cashu payment method. -- `X-Lightning`: Payment details for the lightning payment method. +- `X-Cashu`: Payment details for the cashu payment method, adhering to the [NUT-18](https://github.com/cashubtc/nuts/blob/main/18.md) standard. +- `X-Lightning`: Payment details for the lightning payment method, adhering to the [BOLT-11](https://github.com/lightning/bolts/blob/master/11-payment-encoding.md) standard. If a server supports multiple payment methods, it MAY send multiple `X-{payment_method}` headers in the same response. The client MUST choose one of the provided methods and proceed with the payment accordingly. +Schema: + +```http +HTTP/1.1 402 Payment Required +X-Payment-{payment_method}: "" +``` + ### `X-Cashu` Header -Fields included in the X-Cashu header: - -- `identifier`: The unique identifier for the payment. -- `amount`: The amount of ecash being requested -- `mints`: An array of mints that this server uses -- `unit`: The cashu `unit` from the `mints` -- `pubkey`: (optional) a 33 byte pubkey to lock the tokens too. see [NUT-11](https://github.com/cashubtc/nuts/blob/main/11.md) - -The `identifier` field is a unique reference to a specific payment request. It allows the server to distinguish between different payments for the same file or blob. The server MUST ensure that each identifier is unique and link it internally to the relevant file or blob. +When using the X-Cashu header, the server MUST adhere to the [NUT-18](https://github.com/cashubtc/nuts/blob/main/18.md) standard. Example for cashu: -```json -{ - "identifier": "23537", - "amount": "300", - "mints": ["https://example.com", "https://example2.com"], - "unit": "sat", - "pubkey": "0a3bce8b6005175d25432244340912dfa431a0d62681d9720cda9196398d7222" -} -``` - ```http HTTP/1.1 402 Payment Required -X-Cashu: ewogICJpZGVudGlmaWVyIjogIjIzNTM3IiwKICAiYW1vdW50IjogIjMwMCIsCiAgIm1pbnRzIjogWyJodHRwczovL2V4YW1wbGUuY29tIiwgImh0dHBzOi8vZXhhbXBsZTIuY29tIl0sCiAgInVuaXQiOiAic2F0IiwKICAicHVia2V5IjogIjBhM2JjZThiNjAwNTE3NWQyNTQzMjI0NDM0MDkxMmRmYTQzMWEwZDYyNjgxZDk3MjBjZGE5MTk2Mzk4ZDcyMjIiCn0 +X-Cashu: creqApWF0gaNhdGVub3N0cmFheKlucHJvZmlsZTFxeTI4d3VtbjhnaGo3dW45ZDNzaGp0bnl2OWtoMnVld2Q5aHN6OW1od2RlbjV0ZTB3ZmprY2N0ZTljdXJ4dmVuOWVlaHFjdHJ2NWhzenJ0aHdkZW41dGUwZGVoaHh0bnZkYWtxcWd5ZGFxeTdjdXJrNDM5eWtwdGt5c3Y3dWRoZGh1NjhzdWNtMjk1YWtxZWZkZWhrZjBkNDk1Y3d1bmw1YWeBgmFuYjE3YWloYjdhOTAxNzZhYQphdWNzYXRhbYF4Imh0dHBzOi8vbm9mZWVzLnRlc3RudXQuY2FzaHUuc3BhY2U ``` ### `X-Lightning` Header -Fields included in the X-Lightning header: - -- `identifier`: The unique identifier for the payment. -- `amount`: The amount to be paid. -- `payment_request`: The lightning payment request. - -The `identifier` field is a unique reference to a specific payment request. It allows the server to distinguish between different payments for the same file or blob. The server MUST ensure that each identifier is unique and link it internally to the relevant file or blob. - +When using the X-Lightning header, the server MUST adhere to the [BOLT-11](https://github.com/lightning/bolts/blob/master/11-payment-encoding.md) standard. Example for lightning: -```json -{ - "identifier": "23537", - "amount": "300", - "payment_request": "lnbc300n1pw4..:", -} - -``` - ```http HTTP/1.1 402 Payment Required -X-Lightning: ewogICJpZGVudGlmaWVyIjogIjIzNTM3IiwKICAiYW1vdW50IjogIjMwMCIsCiAgInBheW1lbnRfcmVxdWVzdCI6ICJsbmJjMzAwbjFwdzQuLjoiLAp9 +X-Lightning: lnbc30n1pnnmw3lpp57727jjq8zxctahfavqacymellq56l70f7lwfkmhxfjva6dgul2zqhp5w48l28v60yvythn6qvnpq0lez54422a042yaw4kq8arvd68a6n7qcqzzsxqyz5vqsp5sqezejdfaxx5hge83tf59a50h6gagwah59fjn9mw2d5mn278jkys9qxpqysgqt2q2lhjl9kgfaqz864mhlsspftzdyr642lf3zdt6ljqj6wmathdhtgcn0e6f4ym34jl0qkt6gwnllygvzkhdlpq64c6yv3rta2hyzlqp8k28pz ``` -Schema: - -```http -HTTP/1.1 402 Payment Required -X-Payment-{payment_method}: "" -``` - - ### Client implementation -Clients MUST parse and validate all available `X-{payment_method}` headers received from the server. The client SHOULD provide a way for the user to complete the payment and retry the request using the appropiate `X-Payment-{payment_method}` header. +Clients MUST parse and validate all available `X-{payment_method}` headers received from the server. The client SHOULD provide a way for the user to complete the payment and retry the request using the same `X-{payment_method}` header. -- `X-{payment_method}-Payment`: Base64 UrlSafe encoded JSON with the client payment proof. +The client MUST provide the payment proof in the request headers using the same `X-{payment_method}` header that was chosen. The payment proof MUST aling with the payment method specification: -- `identifier`: The unique identifier for the payment. -- `payment_proof`: The proof of payment, specific to the method: - - - For cashu the payment should be a serialized cashu token according to [NUT-00](https://github.com/cashubtc/nuts/blob/main/00.md#v4-tokens) - - For lightning the payment should be the preimage of the payment request according to [BOLT-11](https://github.com/lightning/bolts/blob/master/11-payment-encoding.md) +- For cashu the payment proof should be a serialized cashu token according to [NUT-00](https://github.com/cashubtc/nuts/blob/main/00.md#v4-tokens) +- For lightning the payment proof should be the preimage of the payment request according to [BOLT-11](https://github.com/lightning/bolts/blob/master/11-payment-encoding.md) + +Schema: + +```http +X-{payment_method}: "" +``` Example for Cashu: -```json -{ - "identifier": "23537", - "payment_proof": "c3b9e2..." -} -``` - ```http -X-Cashu-Payment: ewogICJpZGVudGlmaWVyIjogIjIzNTM3IiwKICAicGF5bWVudF9wcm9vZiI6ICJjM2I5ZTIiCn0 +X-Cashu: cashuBo2F0gqJhaUgA_9SLj17PgGFwgaNhYQFhc3hAYWNjMTI0MzVlN2I4NDg0YzNjZjE4NTAxNDkyMThhZjkwZjcxNmE1MmJmNGE1ZWQzNDdlNDhlY2MxM2Y3NzM4OGFjWCECRFODGd5IXVW ``` Example for Lightning: -```json -{ - "identifier": "23537", - "payment_proof": "lnbc300n1pw4..." -} -``` - ```http -X-Lightning-Payment: ewogICJpZGVudGlmaWVyIjogIjIzNTM3IiwKICAicGF5bWVudF9wcm9vZiI6ICJsbmJjMzAwbjFwdzQuLjoiCn0 -``` - -Schema: - -```http -X-{payment_method}-Payment: "" +X-Lightning: "966fcb8f153339372f9a187f725384ff4ceae0047c25b9ce607488d7c7e93bba" ``` ### Error handling If the client fails to provide the payment proof (expired invoice, invalid token, etc.) the server MUST respond with **402 Payment Required** status code and include the relevant `X-{payment_method}` header(s) with updated payment details. - ### Extending with Future Payment Methods To support future payment methods (e.g., other Layer 2 solutions), the specification allows the addition of new X-{payment_method} headers. Each new method MUST adhere to the following: -New methods MUST use a unique `X-{payment_method}` header containing Base64 UrlSafe encoded JSON. +New methods MUST use a unique `X-{payment_method}` header containing the specific payment details. -**Required Fields:** - -- `identifier`: Unique reference for the payment. -- `amount`: Payment amount in the method’s smallest unit. +New methods MUST adhere their own specification, which MUST be publicly available and linked in the header. From 8600dbecfc44f89b21cd08cfeae9215a67bd6bfa Mon Sep 17 00:00:00 2001 From: Quentin Date: Wed, 20 Nov 2024 12:35:18 +0100 Subject: [PATCH 22/85] Recurring payments. --- buds/07.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/buds/07.md b/buds/07.md index aad8b53..19d6293 100644 --- a/buds/07.md +++ b/buds/07.md @@ -85,6 +85,18 @@ Example for Lightning: X-Lightning: "966fcb8f153339372f9a187f725384ff4ceae0047c25b9ce607488d7c7e93bba" ``` +### Recurring Payments + +Servers MAY accept recurring payments for blob storage using the following Nostr event types: + +- **Cashu**: Using [NIP-61](https://github.com/nostr-protocol/nips/blob/master/61.md) for details. + +- **Lightning**: Using [NIP-57](https://github.com/nostr-protocol/nips/blob/master/57.md) for details. + +The event MUST include a custom `x` tag containing the hash of the blob being paid for. + +- `x`: A string that represents the blob's SHA-256 hash. + ### Error handling If the client fails to provide the payment proof (expired invoice, invalid token, etc.) the server MUST respond with **402 Payment Required** status code and include the relevant `X-{payment_method}` header(s) with updated payment details. @@ -96,3 +108,5 @@ To support future payment methods (e.g., other Layer 2 solutions), the specifica New methods MUST use a unique `X-{payment_method}` header containing the specific payment details. New methods MUST adhere their own specification, which MUST be publicly available and linked in the header. + +New methods MAY have a Nostr event type for recurring payments, which MUST be linked in the Recurring Payments section. From e003b22318a3ff9533944f961baea47c83118002 Mon Sep 17 00:00:00 2001 From: Quentin Date: Wed, 20 Nov 2024 12:40:39 +0100 Subject: [PATCH 23/85] Fix typos. --- buds/07.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/buds/07.md b/buds/07.md index 19d6293..227e4ba 100644 --- a/buds/07.md +++ b/buds/07.md @@ -21,7 +21,7 @@ When payment is required, the server MUST include one or more `X-{payment_method ## Server headers -The `X-{payment_method}` header is used by the server to inform the client that payment is required for the requested operation. The server MUST provide specific headers for each supported payment method, using the following conventions: +The `X-{payment_method}` header is used by the server to inform the client that payment is required for the requested operation. The server MUST provide specific headers for each supported payment method. Supported payment methods: @@ -64,9 +64,9 @@ Clients MUST parse and validate all available `X-{payment_method}` headers recei The client MUST provide the payment proof in the request headers using the same `X-{payment_method}` header that was chosen. The payment proof MUST aling with the payment method specification: -- For cashu the payment proof should be a serialized cashu token according to [NUT-00](https://github.com/cashubtc/nuts/blob/main/00.md#v4-tokens) -- For lightning the payment proof should be the preimage of the payment request according to [BOLT-11](https://github.com/lightning/bolts/blob/master/11-payment-encoding.md) - +- For cashu the payment proof should be a serialized cashu token according to [NUT-00](https://github.com/cashubtc/nuts/blob/main/00.md#v4-tokens). +- For lightning the payment proof should be the preimage of the payment request according to [BOLT-11](https://github.com/lightning/bolts/blob/master/11-payment-encoding.md). + Schema: ```http @@ -89,9 +89,9 @@ X-Lightning: "966fcb8f153339372f9a187f725384ff4ceae0047c25b9ce607488d7c7e93bba" Servers MAY accept recurring payments for blob storage using the following Nostr event types: -- **Cashu**: Using [NIP-61](https://github.com/nostr-protocol/nips/blob/master/61.md) for details. +- **Cashu**: Using [NIP-61](https://github.com/nostr-protocol/nips/blob/master/61.md) standard. -- **Lightning**: Using [NIP-57](https://github.com/nostr-protocol/nips/blob/master/57.md) for details. +- **Lightning**: Using [NIP-57](https://github.com/nostr-protocol/nips/blob/master/57.md) standard. The event MUST include a custom `x` tag containing the hash of the blob being paid for. From cda53cf47afb31d2747fead6fef8a8ab1e6e85a5 Mon Sep 17 00:00:00 2001 From: Quentin <125748180+quentintaranpino@users.noreply.github.com> Date: Wed, 20 Nov 2024 16:25:33 +0100 Subject: [PATCH 24/85] Update buds/07.md Co-authored-by: hzrd149 <8001706+hzrd149@users.noreply.github.com> --- buds/07.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buds/07.md b/buds/07.md index 227e4ba..6e539de 100644 --- a/buds/07.md +++ b/buds/07.md @@ -17,7 +17,7 @@ Some servers MAY require payment for file storage. In such cases, these endpoint - [HEAT /](./01.md#head-sha256---has-blob) - [GET /](./01.md#get-sha256---get-blob) -When payment is required, the server MUST include one or more `X-{payment_method}` header(s), each corresponding to a supported payment method. The client MUST choose one of the provided methods and proceed with the payment accordingly. +When payment is required, the server MUST include one or more `X-{payment_method}` header(s), each corresponding to a supported payment method. ## Server headers From 0d039843a0989af58756d2cb92e5ddeb9994b42f Mon Sep 17 00:00:00 2001 From: Quentin <125748180+quentintaranpino@users.noreply.github.com> Date: Wed, 20 Nov 2024 16:25:58 +0100 Subject: [PATCH 25/85] Update buds/07.md Co-authored-by: hzrd149 <8001706+hzrd149@users.noreply.github.com> --- buds/07.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buds/07.md b/buds/07.md index 6e539de..8c180c5 100644 --- a/buds/07.md +++ b/buds/07.md @@ -21,7 +21,7 @@ When payment is required, the server MUST include one or more `X-{payment_method ## Server headers -The `X-{payment_method}` header is used by the server to inform the client that payment is required for the requested operation. The server MUST provide specific headers for each supported payment method. +The 402 status code and `X-{payment_method}` header is used by the server to inform the client that a payment is required for the requested operation. The server MUST provide specific headers for each supported payment method. Supported payment methods: From ffe55bbffcce6413ab8b95325911cfba9bd31783 Mon Sep 17 00:00:00 2001 From: Quentin <125748180+quentintaranpino@users.noreply.github.com> Date: Wed, 20 Nov 2024 16:26:17 +0100 Subject: [PATCH 26/85] Update buds/07.md Co-authored-by: hzrd149 <8001706+hzrd149@users.noreply.github.com> --- buds/07.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buds/07.md b/buds/07.md index 8c180c5..4a8b7f3 100644 --- a/buds/07.md +++ b/buds/07.md @@ -28,7 +28,7 @@ Supported payment methods: - `X-Cashu`: Payment details for the cashu payment method, adhering to the [NUT-18](https://github.com/cashubtc/nuts/blob/main/18.md) standard. - `X-Lightning`: Payment details for the lightning payment method, adhering to the [BOLT-11](https://github.com/lightning/bolts/blob/master/11-payment-encoding.md) standard. -If a server supports multiple payment methods, it MAY send multiple `X-{payment_method}` headers in the same response. The client MUST choose one of the provided methods and proceed with the payment accordingly. +If a server supports multiple payment methods, it MAY send multiple `X-{payment_method}` headers in the same response. Schema: From 8f95ad746819281d1d772cc5172a841fcb59b58a Mon Sep 17 00:00:00 2001 From: Quentin <125748180+quentintaranpino@users.noreply.github.com> Date: Wed, 20 Nov 2024 16:27:35 +0100 Subject: [PATCH 27/85] Update buds/07.md Co-authored-by: hzrd149 <8001706+hzrd149@users.noreply.github.com> --- buds/07.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buds/07.md b/buds/07.md index 4a8b7f3..62fb9fe 100644 --- a/buds/07.md +++ b/buds/07.md @@ -1,7 +1,7 @@ BUD-07 ====== -Paid storage +Paid upload and download --------------- `draft` `optional` From 38274c6a5e263f59dd415b8eb49bbf22f69b0a42 Mon Sep 17 00:00:00 2001 From: Quentin <125748180+quentintaranpino@users.noreply.github.com> Date: Wed, 20 Nov 2024 16:28:13 +0100 Subject: [PATCH 28/85] Update buds/07.md Co-authored-by: hzrd149 <8001706+hzrd149@users.noreply.github.com> --- buds/07.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buds/07.md b/buds/07.md index 62fb9fe..c414721 100644 --- a/buds/07.md +++ b/buds/07.md @@ -14,7 +14,7 @@ Some servers MAY require payment for file storage. In such cases, these endpoint - [HEAD /upload](./01.md#head-sha256---has-blob) (Optional, if [BUD-06](./06.md) is implemented) - [PUT /upload](./02.md#put-upload---upload-blob) -- [HEAT /](./01.md#head-sha256---has-blob) +- [HEAD /](./01.md#head-sha256---has-blob) - [GET /](./01.md#get-sha256---get-blob) When payment is required, the server MUST include one or more `X-{payment_method}` header(s), each corresponding to a supported payment method. From f9f44fc592c1407b836ea94ced6a6a829e48a77b Mon Sep 17 00:00:00 2001 From: Quentin <125748180+quentintaranpino@users.noreply.github.com> Date: Wed, 20 Nov 2024 16:32:04 +0100 Subject: [PATCH 29/85] Update buds/07.md Co-authored-by: hzrd149 <8001706+hzrd149@users.noreply.github.com> --- buds/07.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buds/07.md b/buds/07.md index c414721..bb07c09 100644 --- a/buds/07.md +++ b/buds/07.md @@ -62,7 +62,7 @@ X-Lightning: lnbc30n1pnnmw3lpp57727jjq8zxctahfavqacymellq56l70f7lwfkmhxfjva6dgul Clients MUST parse and validate all available `X-{payment_method}` headers received from the server. The client SHOULD provide a way for the user to complete the payment and retry the request using the same `X-{payment_method}` header. -The client MUST provide the payment proof in the request headers using the same `X-{payment_method}` header that was chosen. The payment proof MUST aling with the payment method specification: +The client MUST provide the payment proof when re-trying the request using the same `X-{payment_method}` header that was chosen. The payment proof MUST align with the payment method specification: - For cashu the payment proof should be a serialized cashu token according to [NUT-00](https://github.com/cashubtc/nuts/blob/main/00.md#v4-tokens). - For lightning the payment proof should be the preimage of the payment request according to [BOLT-11](https://github.com/lightning/bolts/blob/master/11-payment-encoding.md). From 73fcfbfbd3c399915ece48ca9941a8a64c945d42 Mon Sep 17 00:00:00 2001 From: Quentin Date: Wed, 20 Nov 2024 20:57:46 +0100 Subject: [PATCH 30/85] update BUD-07 --- buds/07.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buds/07.md b/buds/07.md index bb07c09..516c093 100644 --- a/buds/07.md +++ b/buds/07.md @@ -60,7 +60,7 @@ X-Lightning: lnbc30n1pnnmw3lpp57727jjq8zxctahfavqacymellq56l70f7lwfkmhxfjva6dgul ### Client implementation -Clients MUST parse and validate all available `X-{payment_method}` headers received from the server. The client SHOULD provide a way for the user to complete the payment and retry the request using the same `X-{payment_method}` header. +Clients MUST parse and validate the `X-{payment_method}` header received from the server. The client SHOULD provide a way for the user to complete the payment and retry the request using the same `X-{payment_method}` header. The client MUST provide the payment proof when re-trying the request using the same `X-{payment_method}` header that was chosen. The payment proof MUST align with the payment method specification: From 463f28da7b879be42e4948eb60c7b4e9ee9f131c Mon Sep 17 00:00:00 2001 From: Quentin Date: Wed, 20 Nov 2024 21:22:20 +0100 Subject: [PATCH 31/85] error handling 402->400. Special note for Head requests --- buds/07.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/buds/07.md b/buds/07.md index 516c093..8b5dde3 100644 --- a/buds/07.md +++ b/buds/07.md @@ -85,6 +85,10 @@ Example for Lightning: X-Lightning: "966fcb8f153339372f9a187f725384ff4ceae0047c25b9ce607488d7c7e93bba" ``` +**Special Note on HEAD Requests** + +The HEAD endpoints are only used to retrieve blob or server information. They MUST NOT be retried with payment proof. Instead, clients should complete the payment and proceed with the `PUT` or `GET` request. + ### Recurring Payments Servers MAY accept recurring payments for blob storage using the following Nostr event types: @@ -99,7 +103,7 @@ The event MUST include a custom `x` tag containing the hash of the blob being pa ### Error handling -If the client fails to provide the payment proof (expired invoice, invalid token, etc.) the server MUST respond with **402 Payment Required** status code and include the relevant `X-{payment_method}` header(s) with updated payment details. +If the client fails to provide the payment proof (expired invoice, invalid token, etc.) the server MUST respond with **400 Bad request** status code and include a `X-Reason` header with a human-readable message. The client SHOULD inform the user about the error and provide a way to retry the request. ### Extending with Future Payment Methods From bafed19c7f083fdadf8fc899c623cbc56e9025e0 Mon Sep 17 00:00:00 2001 From: hzrd149 <8001706+hzrd149@users.noreply.github.com> Date: Thu, 21 Nov 2024 15:16:21 -0600 Subject: [PATCH 32/85] Add BUD-05 to readme --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index e171a16..1f8115a 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,8 @@ Blossom Servers expose four endpoints for managing blobs - `Authentication`: Signed [nostr event](./buds/02.md#delete-authorization-required) - `PUT /mirror` [BUD-04](./buds/04.md#put-mirror---mirror-blob) - `Authentication`: Signed [nostr event](./buds/02.md#upload-authorization-required) +- `PUT /media` [BUD-05](./buds/05.md) + - `Authentication`: Signed [nostr event](./buds/05.md#upload-authorization) ## Protocol specification (BUDs) @@ -40,6 +42,7 @@ See the [BUDs](./buds) folder and specifically [BUD-01](./buds/01.md) and [BUD-0 - [BUD-02: Blob upload and management](./buds/02.md) - [BUD-03: User Server List](./buds/03.md) - [BUD-04: Mirroring blobs](./buds/04.md) +- [BUD-05: Media optimization](./buds/05.md) - [BUD-06: Upload requirements](./buds/06.md) - [BUD-08: Nostr File Metadata Tags](./buds/08.md) From 854218f573f8e712433d62a16361ad7cc19a98c8 Mon Sep 17 00:00:00 2001 From: hzrd149 <8001706+hzrd149@users.noreply.github.com> Date: Thu, 21 Nov 2024 15:16:59 -0600 Subject: [PATCH 33/85] fix header in BUD-05 --- buds/05.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buds/05.md b/buds/05.md index 42233f6..a628fc1 100644 --- a/buds/05.md +++ b/buds/05.md @@ -1,6 +1,6 @@ # BUD-05 -Media optimization endpoints +## Media optimization endpoints `draft` `optional` From 2d7e013b47051bff8f2f260fc34f58c1178ced4b Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Fri, 22 Nov 2024 13:44:50 -0600 Subject: [PATCH 34/85] BUD-02 require the file extension in the url field --- buds/02.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/buds/02.md b/buds/02.md index 230ecad..6d8519c 100644 --- a/buds/02.md +++ b/buds/02.md @@ -12,12 +12,14 @@ Defines the `/upload`, `/list` and `DELETE /` endpoints A blob descriptor is a JSON object containing `url`, `sha256`, `size`, `type`, and `uploaded` fields -- `url` A publicly accessible URL to the [BUD-01](./01.md#get-sha256---get-blob) `GET /` endpoint (optionally with a file extension) +- `url` A publicly accessible URL to the [BUD-01](./01.md#get-sha256---get-blob) `GET /` endpoint with a file extension - `sha256` The sha256 hash of the blob - `size` The size of the blob in bytes - `type` (optional) The MIME type of the blob - `uploaded` The unix timestamp of when the blob was uploaded to the server +Servers MUST include a file extension in the URL in the `url` field to allow clients to easily embed the URL in social posts or other content + Servers MAY include additional fields in the descriptor like `magnet`, `infohash`, or `ipfs` depending on other protocols they support Example: From c5d90aa74d72f3cc8652afb2e516fea18f1595b0 Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Fri, 22 Nov 2024 16:51:51 -0600 Subject: [PATCH 35/85] Add HEAD /media endpoint --- README.md | 5 +++-- buds/05.md | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1f8115a..f55862e 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Blobs are packs of binary data addressed by their sha256 hash ## How does it work? -Blossom Servers expose four endpoints for managing blobs +Blossom Servers expose a few endpoints for managing blobs - `GET /` (optional file `.ext`) [BUD-01](./buds/01.md#get-sha256---get-blob) - `HEAD /` (optional file `.ext`) [BUD-01](./buds/01.md#head-sha256---has-blob) @@ -27,7 +27,8 @@ Blossom Servers expose four endpoints for managing blobs - `Authentication`: Signed [nostr event](./buds/02.md#delete-authorization-required) - `PUT /mirror` [BUD-04](./buds/04.md#put-mirror---mirror-blob) - `Authentication`: Signed [nostr event](./buds/02.md#upload-authorization-required) -- `PUT /media` [BUD-05](./buds/05.md) +- `HEAD /media` [BUD-05](./buds/05.md#head-media) +- `PUT /media` [BUD-05](./buds/05.md#put-media) - `Authentication`: Signed [nostr event](./buds/05.md#upload-authorization) ## Protocol specification (BUDs) diff --git a/buds/05.md b/buds/05.md index a628fc1..2ad9851 100644 --- a/buds/05.md +++ b/buds/05.md @@ -22,6 +22,10 @@ Servers MAY require an `upload` [authorization event](./02.md#upload-authorizati If a server requires an `upload` authorization event it MUST preform all the checks outlined in the [`/upload`](./02.md#upload-authorization-required) endpoint +## HEAD /media + +Servers MUST respond to `HEAD` requests on the `/media` endpoint in a similar way to the `HEAD /upload` endpoint defined in [BUD-06](./06.md) + ## Limitations This endpoint is intentionally limited to optimizing a single blob with the goal of making it easier to distribute From 36a741a87b74eaea1fb9631809c8a55870d00574 Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Sat, 23 Nov 2024 09:26:38 -0600 Subject: [PATCH 36/85] add range requests section to BUD-01 --- buds/01.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/buds/01.md b/buds/01.md index e94b8d4..a9cd558 100644 --- a/buds/01.md +++ b/buds/01.md @@ -134,3 +134,9 @@ Example event for retrieving multiple blobs from single server: The `HEAD /` endpoint MUST respond with either a `200` or `404` status code The endpoint MUST accept an optional file extension in the URL similar to the `GET /` endpoint. ie. `.pdf`, `.png`, etc + +## Range requests + +To better support mobile devices or low bandwidth connections. server should support range requests ([RFC 7233 section 3](https://www.rfc-editor.org/rfc/rfc7233#section-3)) on the `GET /` endpoint and signal support using the `accept-ranges: bytes` and `content-length` headers on the `HEAD /` endpoint + +See [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests) for more details From 34a50d09f5b1ef095eeb0824bc6fe538448e6639 Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Tue, 26 Nov 2024 09:15:39 -0600 Subject: [PATCH 37/85] require NIP-94 values to be strings --- buds/08.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/buds/08.md b/buds/08.md index b5e2ec0..8964cc7 100644 --- a/buds/08.md +++ b/buds/08.md @@ -12,7 +12,7 @@ As described in [BUD-02](./02.md#blob-descriptor) servers MAY add any additional Servers MAY return an additional `nip94` field in the [blob descriptor](./02.md#blob-descriptor) from the `/upload` or `/mirror` endpoints -The `nip94` field should contain a JSON object with the keys being the tag names defined in [NIP-94](https://github.com/nostr-protocol/nips/blob/master/94.md) +The `nip94` field should contain a JSON object with the keys being the tag names defined in [NIP-94](https://github.com/nostr-protocol/nips/blob/master/94.md) and the values being strings An example response would look like: @@ -27,7 +27,7 @@ An example response would look like: "url": "https://cdn.example.com/b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf", "m": "application/pdf", "x": "b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553", - "size": 184292, + "size": "184292", "magnet": "magnet:?xt=urn:btih:9804c5286a3fb07b2244c968b39bc3cc814313bc&dn=bitcoin.pdf", "i": "9804c5286a3fb07b2244c968b39bc3cc814313bc" } From ec40af6b95bf6fae3659dc80cac526ea30bbccec Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Mon, 2 Dec 2024 10:50:46 -0600 Subject: [PATCH 38/85] clarify root paths --- buds/01.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buds/01.md b/buds/01.md index e94b8d4..1c8ea6f 100644 --- a/buds/01.md +++ b/buds/01.md @@ -71,7 +71,7 @@ Authorization: Nostr eyJpZCI6IjhlY2JkY2RkNTMyOTIwMDEwNTUyNGExNDI4NzkxMzg4MWIzOWQ ## Endpoints -All endpoints MUST be served from the root path (eg. `https://cdn.example.com/upload`, etc). This allows clients to talk to servers interchangeably when uploading or retrieving blobs +All endpoints MUST be served from the root of the domain (eg. the `/upload` endpoint MUST accessable from `https://cdn.example.com/upload`, etc). This allows clients to talk to servers interchangeably when uploading or retrieving blobs ## GET /sha256 - Get Blob From 1a44035b7da0e6e03f4a35e69ce89254ef91858a Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Mon, 2 Dec 2024 10:52:00 -0600 Subject: [PATCH 39/85] spelling --- buds/01.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buds/01.md b/buds/01.md index 1c8ea6f..2e23470 100644 --- a/buds/01.md +++ b/buds/01.md @@ -71,7 +71,7 @@ Authorization: Nostr eyJpZCI6IjhlY2JkY2RkNTMyOTIwMDEwNTUyNGExNDI4NzkxMzg4MWIzOWQ ## Endpoints -All endpoints MUST be served from the root of the domain (eg. the `/upload` endpoint MUST accessable from `https://cdn.example.com/upload`, etc). This allows clients to talk to servers interchangeably when uploading or retrieving blobs +All endpoints MUST be served from the root of the domain (eg. the `/upload` endpoint MUST accessible from `https://cdn.example.com/upload`, etc). This allows clients to talk to servers interchangeably when uploading or retrieving blobs ## GET /sha256 - Get Blob From c99b4898f5e7208cf4799852a90e6ef3e31ca187 Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Mon, 2 Dec 2024 10:56:43 -0600 Subject: [PATCH 40/85] add comment about videos --- buds/01.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buds/01.md b/buds/01.md index a9cd558..a087c94 100644 --- a/buds/01.md +++ b/buds/01.md @@ -137,6 +137,6 @@ The endpoint MUST accept an optional file extension in the URL similar to the `G ## Range requests -To better support mobile devices or low bandwidth connections. server should support range requests ([RFC 7233 section 3](https://www.rfc-editor.org/rfc/rfc7233#section-3)) on the `GET /` endpoint and signal support using the `accept-ranges: bytes` and `content-length` headers on the `HEAD /` endpoint +To better support mobile devices, video files, or low bandwidth connections. servers should support range requests ([RFC 7233 section 3](https://www.rfc-editor.org/rfc/rfc7233#section-3)) on the `GET /` endpoint and signal support using the `accept-ranges: bytes` and `content-length` headers on the `HEAD /` endpoint See [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests) for more details From 4d9b22a96c3c8ed76bb6001a7898d4c864fcdb0d Mon Sep 17 00:00:00 2001 From: quentintaranpino Date: Tue, 3 Dec 2024 13:03:23 +0100 Subject: [PATCH 41/85] remove recurring payments --- buds/07.md | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/buds/07.md b/buds/07.md index 8b5dde3..8b4bb3e 100644 --- a/buds/07.md +++ b/buds/07.md @@ -89,18 +89,6 @@ X-Lightning: "966fcb8f153339372f9a187f725384ff4ceae0047c25b9ce607488d7c7e93bba" The HEAD endpoints are only used to retrieve blob or server information. They MUST NOT be retried with payment proof. Instead, clients should complete the payment and proceed with the `PUT` or `GET` request. -### Recurring Payments - -Servers MAY accept recurring payments for blob storage using the following Nostr event types: - -- **Cashu**: Using [NIP-61](https://github.com/nostr-protocol/nips/blob/master/61.md) standard. - -- **Lightning**: Using [NIP-57](https://github.com/nostr-protocol/nips/blob/master/57.md) standard. - -The event MUST include a custom `x` tag containing the hash of the blob being paid for. - -- `x`: A string that represents the blob's SHA-256 hash. - ### Error handling If the client fails to provide the payment proof (expired invoice, invalid token, etc.) the server MUST respond with **400 Bad request** status code and include a `X-Reason` header with a human-readable message. The client SHOULD inform the user about the error and provide a way to retry the request. @@ -111,6 +99,4 @@ To support future payment methods (e.g., other Layer 2 solutions), the specifica New methods MUST use a unique `X-{payment_method}` header containing the specific payment details. -New methods MUST adhere their own specification, which MUST be publicly available and linked in the header. - -New methods MAY have a Nostr event type for recurring payments, which MUST be linked in the Recurring Payments section. +New methods MUST adhere their own specification, which MUST be publicly available and linked in the header. \ No newline at end of file From 8e12280410443029cbae882450d5714fef930414 Mon Sep 17 00:00:00 2001 From: quentintaranpino Date: Tue, 3 Dec 2024 13:06:04 +0100 Subject: [PATCH 42/85] fix typo --- buds/07.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buds/07.md b/buds/07.md index 8b4bb3e..5c88aab 100644 --- a/buds/07.md +++ b/buds/07.md @@ -34,7 +34,7 @@ Schema: ```http HTTP/1.1 402 Payment Required -X-Payment-{payment_method}: "" +X-{payment_method}: "" ``` ### `X-Cashu` Header From c195efdf3065597ad2eecc53bf241538c91c5317 Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Thu, 26 Dec 2024 09:44:15 -0600 Subject: [PATCH 43/85] Change /media endpoint to require "media" auth --- buds/05.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/buds/05.md b/buds/05.md index 2ad9851..97d9ff9 100644 --- a/buds/05.md +++ b/buds/05.md @@ -18,9 +18,12 @@ Servers MAY reject media uploads for any reason and should respond with the appr ### Upload Authorization -Servers MAY require an `upload` [authorization event](./02.md#upload-authorization-required) to identify the uploader +Servers MAY require a `media` [authorization event](./02.md#upload-authorization-required) to identify the uploader -If a server requires an `upload` authorization event it MUST preform all the checks outlined in the [`/upload`](./02.md#upload-authorization-required) endpoint +If a server requires a `media` authorization event it MUST preform the following checks + +1. The `t` tag MUST be set to `media` +2. MUST contain at least one `x` tag matching the sha256 hash of the body of the request ## HEAD /media @@ -40,6 +43,6 @@ If a longer optimization or transformation process is needed, or if the client n Clients MAY let a user selected a "trusted processing" server for uploading images or short videos -Once a server has been selected, the client can upload the original media to the `/media` endpoint of the trusted server and get the optimized blob back +Once a server has been selected, the client uploads the original media to the `/media` endpoint of the trusted server and get the optimized blob back -Then optionally the client can ask the user to sign another `upload` authorization event for the new optimized blob and call the `/mirror` endpoint on other servers to distribute the blob +Then the client can ask the user to sign another `upload` authorization event for the new optimized blob and call the `/mirror` endpoint on other servers to distribute the blob From b50a5374b31a93213db0497567a66a767cd4fe02 Mon Sep 17 00:00:00 2001 From: "k." Date: Wed, 1 Jan 2025 19:38:07 +0000 Subject: [PATCH 44/85] Update 01.md --- buds/01.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/buds/01.md b/buds/01.md index 5d5434f..41466bb 100644 --- a/buds/01.md +++ b/buds/01.md @@ -36,7 +36,7 @@ Authorization events MAY have multiple `x` tags for endpoints that require a sha Example event: -```json +```jsonc { "id": "bb653c815da18c089f3124b41c4b5ec072a40b87ca0f50bbbc6ecde9aca442eb", "pubkey": "b53185b9f27962ebdf76b8a9b0a84cd8b27f9f3d4abd59f715788a3bf9e7f75e", @@ -45,7 +45,7 @@ Example event: "created_at": 1708773959, "tags": [ ["t", "upload"], - // Authorization events MAY have multiple "x" tags + // Authorization events MAY have multiple "x" tags. ["x", "b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553"], ["expiration", "1708858680"] ], @@ -71,22 +71,22 @@ Authorization: Nostr eyJpZCI6IjhlY2JkY2RkNTMyOTIwMDEwNTUyNGExNDI4NzkxMzg4MWIzOWQ ## Endpoints -All endpoints MUST be served from the root of the domain (eg. the `/upload` endpoint MUST accessible from `https://cdn.example.com/upload`, etc). This allows clients to talk to servers interchangeably when uploading or retrieving blobs +All endpoints MUST be served from the root of the domain (eg. the `/upload` endpoint MUST be accessible from `https://cdn.example.com/upload`, etc). This allows clients to talk to servers interchangeably when uploading or retrieving blobs ## GET /sha256 - Get Blob -The `GET /` endpoint MUST return the contents of the blob with the `Content-Type` header set to the appropriate MIME type +The `GET /` endpoint MUST return the contents of the blob with the `Content-Type` header set to the appropriate MIME-type The endpoint MUST accept an optional file extension in the URL. ie. `.pdf`, `.png`, etc -If the endpoints returns a 301 or 302 redirect it MUST redirect to a URL containing the same sha256 hash as requested blob. +If the endpoints returns a 301 or 302 redirect it MUST redirect to a URL containing the same sha256 hash as the requested blob. This ensures that if a user was to copy or reuse the redirect URL it would still contain the original sha256 hash ### Get Authorization (optional) The server may optionally require authorization when retrieving blobs from the `GET /` endpoint -In this case the server MUST perform additional checks on the authorization event +In this case, the server MUST perform additional checks on the authorization event 1. A `t` tag MUST be present and set to `get` 2. The event MUST contain either a `server` tag containing the full URL to the server or MUST contain at least one `x` tag matching the sha256 hash of the blob being retrieved From 550d8693e02dc92b1e1af7124b26431c3ef4f36e Mon Sep 17 00:00:00 2001 From: "k." Date: Wed, 1 Jan 2025 19:38:47 +0000 Subject: [PATCH 45/85] Update 04.md --- buds/04.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/buds/04.md b/buds/04.md index 92559c0..eb1d19f 100644 --- a/buds/04.md +++ b/buds/04.md @@ -12,8 +12,8 @@ A server may expose a `PUT /mirror` endpoint to allow users to copy a blob from Clients MUST pass the URL of the remote blob as a stringified JSON object in the request body -```json -// request body +```jsonc +// request body... { "url": "https://cdn.satellite.earth/b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf" } From 29cbfbf504041b2a3ff553a024a390510535b8dc Mon Sep 17 00:00:00 2001 From: Kay Date: Thu, 2 Jan 2025 11:13:28 +0000 Subject: [PATCH 46/85] bud-07: media report. --- buds/01.md | 2 +- buds/07.md | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 buds/07.md diff --git a/buds/01.md b/buds/01.md index 41466bb..13b2bd3 100644 --- a/buds/01.md +++ b/buds/01.md @@ -26,7 +26,7 @@ Authorization events are used to identify the users to the server Authorization events must be generic and must NOT be scoped to specific servers. This allows pubkeys to sign a single event and interact the same way with multiple servers. -Events MUST be kind `24242` and have a `t` tag with a verb of `get`, `upload`, `list`, or `delete` +Events MUST be kind `24242` and have a `t` tag with a verb of `get`, `upload`, `list`, `report`, or `delete` Events MUST have the `content` set to a human readable string explaining to the user what the events inteded use is. For example `Upload Blob`, `Delete dog-picture.png`, `List Images`, etc diff --git a/buds/07.md b/buds/07.md new file mode 100644 index 0000000..8c2098b --- /dev/null +++ b/buds/07.md @@ -0,0 +1,43 @@ +# BUD-07 + +## Media Report + +`draft` `optional` + +This bud defines a new endpoint for clients and users to report medias to servers. + + +### PUT /report/ - reporting a media + +Client MUST provide a report json according to the [NIP-56](https://github.com/nostr-protocol/nips/blob/master/56.md) in the request body. + +Example: + +```json +{ + "kind": 1984, + "tags": [ + ["x", "", ""], + ], + "content": "", + // other fields... +} +``` + +A report request may contain multiple `x` tags or contain some `p` or `e` tags which is not related to blossom server but is SHOULD be considered as a valid request. + +Server MUST response to report request with a successful code or a code in 4xx/5xx range if there was any error. + + +> Note: servers may requests for authorization with `t` tag of `report` as per [BUD-01](./01.md). + +### Client behavior + +The clients can show a media report button on posts or in media details. Or they merge this with normal nostr report and send it to both relays and blossom server. other clients can receive it from relays and hide or blur reported medias from trusted friends. + +### Server behavior + +The servers MAY keep the reports somewhere for operators to check and take action on them. they MAY use a list of trusted people or moderators to directly take action on media without operator request. + +Servers MAY consider removed medias sha256 as blocked in order to prevent rewrite. +Servers MAY advertise a route or landing page to provide their rules and term of service which affects the report process. From 7a9111f54d6bda0c0bb451ccbafa3ebd90077603 Mon Sep 17 00:00:00 2001 From: Kay Date: Thu, 2 Jan 2025 11:17:48 +0000 Subject: [PATCH 47/85] small fixes. --- README.md | 11 +++++++++++ buds/07.md | 12 ++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index f55862e..0d60b61 100644 --- a/README.md +++ b/README.md @@ -15,22 +15,32 @@ Blobs are packs of binary data addressed by their sha256 hash Blossom Servers expose a few endpoints for managing blobs - `GET /` (optional file `.ext`) [BUD-01](./buds/01.md#get-sha256---get-blob) + - `HEAD /` (optional file `.ext`) [BUD-01](./buds/01.md#head-sha256---has-blob) + - `PUT /upload` [BUD-02](./buds/02.md#put-upload---upload-blob) - `Authentication`: Signed [nostr event](./buds/02.md#upload-authorization-required) - Return a blob descriptor + - `HEAD /upload` [BUD-06](./buds/06.md#head-upload---upload-requirements) + - `GET /list/` [BUD-02](./buds/02.md#get-listpubkey---list-blobs) - Returns an array of blob descriptors - `Authentication` _(optional)_: Signed [nostr event](./buds/02.md#list-authorization-optional) + - `DELETE /` [BUD-02](./buds/02.md#delete-sha256---delete-blob) - `Authentication`: Signed [nostr event](./buds/02.md#delete-authorization-required) + - `PUT /mirror` [BUD-04](./buds/04.md#put-mirror---mirror-blob) - `Authentication`: Signed [nostr event](./buds/02.md#upload-authorization-required) + - `HEAD /media` [BUD-05](./buds/05.md#head-media) + - `PUT /media` [BUD-05](./buds/05.md#put-media) - `Authentication`: Signed [nostr event](./buds/05.md#upload-authorization) +- `PUT /report/` [BUD-07](./buds/07.md) + ## Protocol specification (BUDs) BUDs stand for **Blossom Upgrade Documents**. @@ -45,6 +55,7 @@ See the [BUDs](./buds) folder and specifically [BUD-01](./buds/01.md) and [BUD-0 - [BUD-04: Mirroring blobs](./buds/04.md) - [BUD-05: Media optimization](./buds/05.md) - [BUD-06: Upload requirements](./buds/06.md) +- [BUD-07: Blob Report](./buds/07.md) - [BUD-08: Nostr File Metadata Tags](./buds/08.md) ## Event kinds diff --git a/buds/07.md b/buds/07.md index 8c2098b..29fb2d7 100644 --- a/buds/07.md +++ b/buds/07.md @@ -1,10 +1,10 @@ # BUD-07 -## Media Report +## Blob Report `draft` `optional` -This bud defines a new endpoint for clients and users to report medias to servers. +This bud defines a new endpoint for clients and users to report blobs to servers. ### PUT /report/ - reporting a media @@ -17,7 +17,7 @@ Example: { "kind": 1984, "tags": [ - ["x", "", ""], + ["x", "", ""], ], "content": "", // other fields... @@ -33,11 +33,11 @@ Server MUST response to report request with a successful code or a code in 4xx/5 ### Client behavior -The clients can show a media report button on posts or in media details. Or they merge this with normal nostr report and send it to both relays and blossom server. other clients can receive it from relays and hide or blur reported medias from trusted friends. +The clients can show a blob report button on posts or in blob details. Or its RECOMMENDED to merge this with normal nostr report and send it to both relays and blossom server. other clients can receive it from relays and hide or blur reported blob from trusted friends. ### Server behavior -The servers MAY keep the reports somewhere for operators to check and take action on them. they MAY use a list of trusted people or moderators to directly take action on media without operator request. +The servers MAY keep the reports somewhere for operators to check and take action on them. they MAY use a list of trusted people or moderators to directly take action on blob without operator request. -Servers MAY consider removed medias sha256 as blocked in order to prevent rewrite. +Servers MAY consider removed blobs sha256 as blocked in order to prevent rewrite. Servers MAY advertise a route or landing page to provide their rules and term of service which affects the report process. From e5462c3e1a6ffc9a55ac1b995e0d73c5111b0079 Mon Sep 17 00:00:00 2001 From: Kay Date: Thu, 2 Jan 2025 11:18:02 +0000 Subject: [PATCH 48/85] small fixes. --- buds/07.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buds/07.md b/buds/07.md index 29fb2d7..9b0a332 100644 --- a/buds/07.md +++ b/buds/07.md @@ -13,7 +13,7 @@ Client MUST provide a report json according to the [NIP-56](https://github.com/n Example: -```json +```jsonc { "kind": 1984, "tags": [ From fa676debf3ca48c41cdfdb85675344abc3d65a76 Mon Sep 17 00:00:00 2001 From: Kay Date: Fri, 3 Jan 2025 12:51:09 +0000 Subject: [PATCH 49/85] fix requests. --- README.md | 2 +- buds/{07.md => 09.md} | 13 +++++-------- 2 files changed, 6 insertions(+), 9 deletions(-) rename buds/{07.md => 09.md} (71%) diff --git a/README.md b/README.md index 0d60b61..6ec425b 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ Blossom Servers expose a few endpoints for managing blobs - `PUT /media` [BUD-05](./buds/05.md#put-media) - `Authentication`: Signed [nostr event](./buds/05.md#upload-authorization) -- `PUT /report/` [BUD-07](./buds/07.md) +- `PUT /report` [BUD-09](./buds/09.md) ## Protocol specification (BUDs) diff --git a/buds/07.md b/buds/09.md similarity index 71% rename from buds/07.md rename to buds/09.md index 9b0a332..a86bb5e 100644 --- a/buds/07.md +++ b/buds/09.md @@ -1,4 +1,4 @@ -# BUD-07 +# BUD-09 ## Blob Report @@ -7,9 +7,9 @@ This bud defines a new endpoint for clients and users to report blobs to servers. -### PUT /report/ - reporting a media +### PUT /report - reporting a media -Client MUST provide a report json according to the [NIP-56](https://github.com/nostr-protocol/nips/blob/master/56.md) in the request body. +The requests body MUST be a signed [NIP-56](https://github.com/nostr-protocol/nips/blob/master/56.md) report event with `x` tags containing that hashes of the blobs being reported. Example: @@ -19,7 +19,7 @@ Example: "tags": [ ["x", "", ""], ], - "content": "", + "content": "", // other fields... } ``` @@ -28,9 +28,6 @@ A report request may contain multiple `x` tags or contain some `p` or `e` tags w Server MUST response to report request with a successful code or a code in 4xx/5xx range if there was any error. - -> Note: servers may requests for authorization with `t` tag of `report` as per [BUD-01](./01.md). - ### Client behavior The clients can show a blob report button on posts or in blob details. Or its RECOMMENDED to merge this with normal nostr report and send it to both relays and blossom server. other clients can receive it from relays and hide or blur reported blob from trusted friends. @@ -40,4 +37,4 @@ The clients can show a blob report button on posts or in blob details. Or its RE The servers MAY keep the reports somewhere for operators to check and take action on them. they MAY use a list of trusted people or moderators to directly take action on blob without operator request. Servers MAY consider removed blobs sha256 as blocked in order to prevent rewrite. -Servers MAY advertise a route or landing page to provide their rules and term of service which affects the report process. +Servers SHOULD advertise a route or landing page to provide their rules and term of service which affects the report process. From 4e6e322aa371243ae6e7379eb7dcc3e3bc865792 Mon Sep 17 00:00:00 2001 From: Kay Date: Fri, 3 Jan 2025 12:55:43 +0000 Subject: [PATCH 50/85] fix requests. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6ec425b..89544ad 100644 --- a/README.md +++ b/README.md @@ -55,8 +55,8 @@ See the [BUDs](./buds) folder and specifically [BUD-01](./buds/01.md) and [BUD-0 - [BUD-04: Mirroring blobs](./buds/04.md) - [BUD-05: Media optimization](./buds/05.md) - [BUD-06: Upload requirements](./buds/06.md) -- [BUD-07: Blob Report](./buds/07.md) - [BUD-08: Nostr File Metadata Tags](./buds/08.md) +- [BUD-08: Blob Report](./buds/08.md) ## Event kinds From 287b32b531ebc43c853cfd8ed813b6eaf357624b Mon Sep 17 00:00:00 2001 From: "k." Date: Fri, 3 Jan 2025 14:59:39 +0000 Subject: [PATCH 51/85] Update buds/01.md Co-authored-by: hzrd149 <8001706+hzrd149@users.noreply.github.com> --- buds/01.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buds/01.md b/buds/01.md index 13b2bd3..41466bb 100644 --- a/buds/01.md +++ b/buds/01.md @@ -26,7 +26,7 @@ Authorization events are used to identify the users to the server Authorization events must be generic and must NOT be scoped to specific servers. This allows pubkeys to sign a single event and interact the same way with multiple servers. -Events MUST be kind `24242` and have a `t` tag with a verb of `get`, `upload`, `list`, `report`, or `delete` +Events MUST be kind `24242` and have a `t` tag with a verb of `get`, `upload`, `list`, or `delete` Events MUST have the `content` set to a human readable string explaining to the user what the events inteded use is. For example `Upload Blob`, `Delete dog-picture.png`, `List Images`, etc From 72d5c1690a19042fbf2d458bdc84a23f1dfb933f Mon Sep 17 00:00:00 2001 From: "k." Date: Fri, 3 Jan 2025 14:59:53 +0000 Subject: [PATCH 52/85] Update README.md Co-authored-by: hzrd149 <8001706+hzrd149@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 89544ad..ae01168 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ See the [BUDs](./buds) folder and specifically [BUD-01](./buds/01.md) and [BUD-0 - [BUD-05: Media optimization](./buds/05.md) - [BUD-06: Upload requirements](./buds/06.md) - [BUD-08: Nostr File Metadata Tags](./buds/08.md) -- [BUD-08: Blob Report](./buds/08.md) +- [BUD-09: Blob Report](./buds/09.md) ## Event kinds From 9e468f874947f240c583b588eeab4077cc3e888b Mon Sep 17 00:00:00 2001 From: "k." Date: Sat, 4 Jan 2025 17:37:58 +0000 Subject: [PATCH 53/85] Update buds/09.md Co-authored-by: Kieran --- buds/09.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buds/09.md b/buds/09.md index a86bb5e..425761e 100644 --- a/buds/09.md +++ b/buds/09.md @@ -9,7 +9,7 @@ This bud defines a new endpoint for clients and users to report blobs to servers ### PUT /report - reporting a media -The requests body MUST be a signed [NIP-56](https://github.com/nostr-protocol/nips/blob/master/56.md) report event with `x` tags containing that hashes of the blobs being reported. +The request body MUST be a signed [NIP-56](https://github.com/nostr-protocol/nips/blob/master/56.md) report event with one or more `x` tags containing the hashes of the blobs being reported. Example: From 8487a70a2271aa37dee549999167704ea14bce37 Mon Sep 17 00:00:00 2001 From: "k." Date: Sat, 4 Jan 2025 17:38:54 +0000 Subject: [PATCH 54/85] Update buds/09.md Co-authored-by: Kieran --- buds/09.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buds/09.md b/buds/09.md index 425761e..c9e6a05 100644 --- a/buds/09.md +++ b/buds/09.md @@ -26,7 +26,7 @@ Example: A report request may contain multiple `x` tags or contain some `p` or `e` tags which is not related to blossom server but is SHOULD be considered as a valid request. -Server MUST response to report request with a successful code or a code in 4xx/5xx range if there was any error. +Server MUST respond to a report request with a success code or a code in 4xx/5xx range if there was any error. ### Client behavior From 52abe4467a80087da02d05ac677496fcbef51683 Mon Sep 17 00:00:00 2001 From: "k." Date: Sat, 4 Jan 2025 19:01:39 +0000 Subject: [PATCH 55/85] Update 09.md --- buds/09.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/buds/09.md b/buds/09.md index c9e6a05..875067c 100644 --- a/buds/09.md +++ b/buds/09.md @@ -18,15 +18,16 @@ Example: "kind": 1984, "tags": [ ["x", "", ""], + ["x", "", ""] ], "content": "", // other fields... } ``` -A report request may contain multiple `x` tags or contain some `p` or `e` tags which is not related to blossom server but is SHOULD be considered as a valid request. +The clients can include `e` or `p` tags to point to the event or the profile that contains this media if they want to make this report event useful for relays as well. -Server MUST respond to a report request with a success code or a code in 4xx/5xx range if there was any error. +Server MUST respond to a report request with a success code or a code in the 4xx/5xx range if there was any error. ### Client behavior @@ -36,5 +37,5 @@ The clients can show a blob report button on posts or in blob details. Or its RE The servers MAY keep the reports somewhere for operators to check and take action on them. they MAY use a list of trusted people or moderators to directly take action on blob without operator request. -Servers MAY consider removed blobs sha256 as blocked in order to prevent rewrite. +Servers MAY consider removed blobs sha256 as blocked to prevent rewrite. Servers SHOULD advertise a route or landing page to provide their rules and term of service which affects the report process. From eaa37c348dd1f27dc39967e6da0459c32f584f38 Mon Sep 17 00:00:00 2001 From: "k." Date: Tue, 7 Jan 2025 17:37:14 +0000 Subject: [PATCH 56/85] Update 09.md --- buds/09.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buds/09.md b/buds/09.md index 875067c..0c2f808 100644 --- a/buds/09.md +++ b/buds/09.md @@ -7,7 +7,7 @@ This bud defines a new endpoint for clients and users to report blobs to servers. -### PUT /report - reporting a media +### PUT /report - reporting a blob The request body MUST be a signed [NIP-56](https://github.com/nostr-protocol/nips/blob/master/56.md) report event with one or more `x` tags containing the hashes of the blobs being reported. From b29ada0e112d5a656d034b72f97ff90b0daa8212 Mon Sep 17 00:00:00 2001 From: hzrd149 <8001706+hzrd149@users.noreply.github.com> Date: Tue, 11 Feb 2025 08:59:38 -0600 Subject: [PATCH 57/85] Update README.md --- README.md | 9 --------- 1 file changed, 9 deletions(-) diff --git a/README.md b/README.md index ae01168..628b37a 100644 --- a/README.md +++ b/README.md @@ -15,30 +15,21 @@ Blobs are packs of binary data addressed by their sha256 hash Blossom Servers expose a few endpoints for managing blobs - `GET /` (optional file `.ext`) [BUD-01](./buds/01.md#get-sha256---get-blob) - - `HEAD /` (optional file `.ext`) [BUD-01](./buds/01.md#head-sha256---has-blob) - - `PUT /upload` [BUD-02](./buds/02.md#put-upload---upload-blob) - `Authentication`: Signed [nostr event](./buds/02.md#upload-authorization-required) - Return a blob descriptor - - `HEAD /upload` [BUD-06](./buds/06.md#head-upload---upload-requirements) - - `GET /list/` [BUD-02](./buds/02.md#get-listpubkey---list-blobs) - Returns an array of blob descriptors - `Authentication` _(optional)_: Signed [nostr event](./buds/02.md#list-authorization-optional) - - `DELETE /` [BUD-02](./buds/02.md#delete-sha256---delete-blob) - `Authentication`: Signed [nostr event](./buds/02.md#delete-authorization-required) - - `PUT /mirror` [BUD-04](./buds/04.md#put-mirror---mirror-blob) - `Authentication`: Signed [nostr event](./buds/02.md#upload-authorization-required) - - `HEAD /media` [BUD-05](./buds/05.md#head-media) - - `PUT /media` [BUD-05](./buds/05.md#put-media) - `Authentication`: Signed [nostr event](./buds/05.md#upload-authorization) - - `PUT /report` [BUD-09](./buds/09.md) ## Protocol specification (BUDs) From 9d8b3cb677953830f589eb6f7b39d5e9b72151f4 Mon Sep 17 00:00:00 2001 From: Kieran Date: Wed, 26 Feb 2025 21:16:03 +0000 Subject: [PATCH 58/85] Update 08.md --- buds/08.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/buds/08.md b/buds/08.md index 8964cc7..c4a0e0a 100644 --- a/buds/08.md +++ b/buds/08.md @@ -23,13 +23,13 @@ An example response would look like: "size": 184292, "type": "application/pdf", "uploaded": 1725909682, - "nip94": { - "url": "https://cdn.example.com/b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf", - "m": "application/pdf", - "x": "b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553", - "size": "184292", - "magnet": "magnet:?xt=urn:btih:9804c5286a3fb07b2244c968b39bc3cc814313bc&dn=bitcoin.pdf", - "i": "9804c5286a3fb07b2244c968b39bc3cc814313bc" - } + "nip94": [ + "url https://cdn.example.com/b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf", + "m application/pdf", + "x b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553", + "size 184292", + "magnet magnet:?xt=urn:btih:9804c5286a3fb07b2244c968b39bc3cc814313bc&dn=bitcoin.pdf", + "i 9804c5286a3fb07b2244c968b39bc3cc814313bc" + ] } ``` From a3546a5bc3c9d009e39cb9905f6133a7faff6843 Mon Sep 17 00:00:00 2001 From: Kieran Date: Wed, 26 Feb 2025 21:20:25 +0000 Subject: [PATCH 59/85] Update 08.md --- buds/08.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/buds/08.md b/buds/08.md index c4a0e0a..89c1668 100644 --- a/buds/08.md +++ b/buds/08.md @@ -12,7 +12,7 @@ As described in [BUD-02](./02.md#blob-descriptor) servers MAY add any additional Servers MAY return an additional `nip94` field in the [blob descriptor](./02.md#blob-descriptor) from the `/upload` or `/mirror` endpoints -The `nip94` field should contain a JSON object with the keys being the tag names defined in [NIP-94](https://github.com/nostr-protocol/nips/blob/master/94.md) and the values being strings +The `nip94` field should contain a JSON array with KV pairs as defined in [NIP-94](https://github.com/nostr-protocol/nips/blob/master/94.md) An example response would look like: @@ -24,12 +24,12 @@ An example response would look like: "type": "application/pdf", "uploaded": 1725909682, "nip94": [ - "url https://cdn.example.com/b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf", - "m application/pdf", - "x b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553", - "size 184292", - "magnet magnet:?xt=urn:btih:9804c5286a3fb07b2244c968b39bc3cc814313bc&dn=bitcoin.pdf", - "i 9804c5286a3fb07b2244c968b39bc3cc814313bc" + ["url", "https://cdn.example.com/b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf"], + ["m", "application/pdf"], + ["x", "b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553"], + ["size", "184292"], + ["magnet", "magnet:?xt=urn:btih:9804c5286a3fb07b2244c968b39bc3cc814313bc&dn=bitcoin.pdf"], + ["i", "9804c5286a3fb07b2244c968b39bc3cc814313bc"] ] } ``` From 782d382ca7ba228d97bc5d9486bdd598ef5319b6 Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Mon, 17 Mar 2025 21:41:34 +0000 Subject: [PATCH 60/85] Clarify authorization requirements in BUD-04: change `MUST` to `MAY` for the `Authorization` header and specify auth type --- buds/04.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/buds/04.md b/buds/04.md index eb1d19f..474fce8 100644 --- a/buds/04.md +++ b/buds/04.md @@ -19,11 +19,11 @@ Clients MUST pass the URL of the remote blob as a stringified JSON object in the } ``` -Clients MUST set the `Authorization` header to an upload authorization event defined in [BUD-02](./02.md#upload-authorization-required) +Clients MAY set the `Authorization` header to an upload authorization event defined in [BUD-02](./02.md#upload-authorization-required). When using authorization, the event MUST be of type "upload". The `/mirror` endpoint MUST download the blob from the specified URL and verify that there is at least one `x` tag in the authorization event matching the sha256 hash of the download blob -**Multiple `x` tags MUST NOT be interpreted as the user requesting a bulk mirror.** +**Multiple `x` tags in the authorization event MUST NOT be interpreted as the user requesting a bulk mirror.** The endpoint MUST return a [Blob Descriptor](#blob-descriptor) if the mirroring was successful or an error object if it was not From a63959f1e04c81f7ef1107aa63cebad142b045a8 Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Sun, 30 Mar 2025 10:02:21 +0100 Subject: [PATCH 61/85] Use offset limit pagination instead of date based pagination --- buds/02.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buds/02.md b/buds/02.md index 6d8519c..36330c0 100644 --- a/buds/02.md +++ b/buds/02.md @@ -73,7 +73,7 @@ Example Authorization event: The `/list/` endpoint MUST return a JSON array of [Blob Descriptor](#blob-descriptor) that where uploaded by the specified pubkey -The endpoint MUST support a `since` and `until` query parameter to limit the returned blobs by their `uploaded` date +The endpoint MUST support `limit`, `offset` query parameters for pagination. The returned array of blob descriptors MUST be sorted by the `uploaded` date in descending order Servers may reject a list for any reason and MUST respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection From 39d1ae9e93d873c995ff48c46f7650d3d3763383 Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Sun, 30 Mar 2025 10:13:35 +0100 Subject: [PATCH 62/85] add alternative line for cursor based pagination --- buds/02.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/buds/02.md b/buds/02.md index 36330c0..4c6686d 100644 --- a/buds/02.md +++ b/buds/02.md @@ -73,7 +73,9 @@ Example Authorization event: The `/list/` endpoint MUST return a JSON array of [Blob Descriptor](#blob-descriptor) that where uploaded by the specified pubkey -The endpoint MUST support `limit`, `offset` query parameters for pagination. The returned array of blob descriptors MUST be sorted by the `uploaded` date in descending order +The endpoint MUST support `limit`, `offset` query parameters for offset limit based pagination. The returned array of blob descriptors MUST be sorted by the `uploaded` date in descending order + +The endpoint MUST support `cursor` and`limit` query parameters for cursor based pagination. The `cursor` parameter MUST be the `sha256` hash of the last blob in the previous page. The returned array of blob descriptors MUST be sorted by the `uploaded` date in descending order and should not include the blob at the cursor Servers may reject a list for any reason and MUST respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection From 542c654045f858852dedd39b763d1b9fc40b7e39 Mon Sep 17 00:00:00 2001 From: Quentin <125748180+quentintaranpino@users.noreply.github.com> Date: Sun, 20 Apr 2025 18:37:03 +0200 Subject: [PATCH 63/85] Update buds/07.md Co-authored-by: hzrd149 <8001706+hzrd149@users.noreply.github.com> --- buds/07.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buds/07.md b/buds/07.md index 5c88aab..f996045 100644 --- a/buds/07.md +++ b/buds/07.md @@ -39,7 +39,7 @@ X-{payment_method}: "" ### `X-Cashu` Header -When using the X-Cashu header, the server MUST adhere to the [NUT-18](https://github.com/cashubtc/nuts/blob/main/18.md) standard. +When using the X-Cashu header, the server MUST adhere to the [NUT-23](https://github.com/cashubtc/nuts/pull/239) standard. Example for cashu: From 2aa65cc373a0dbe179e2b63cf12493c3b14abdbc Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Fri, 25 Apr 2025 08:00:17 -0500 Subject: [PATCH 64/85] Fix spelling mistakes --- buds/01.md | 2 +- buds/03.md | 2 +- buds/05.md | 4 ++-- buds/06.md | 4 ++-- buds/09.md | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/buds/01.md b/buds/01.md index 41466bb..4c42e94 100644 --- a/buds/01.md +++ b/buds/01.md @@ -28,7 +28,7 @@ Authorization events must be generic and must NOT be scoped to specific servers. Events MUST be kind `24242` and have a `t` tag with a verb of `get`, `upload`, `list`, or `delete` -Events MUST have the `content` set to a human readable string explaining to the user what the events inteded use is. For example `Upload Blob`, `Delete dog-picture.png`, `List Images`, etc +Events MUST have the `content` set to a human readable string explaining to the user what the events intended use is. For example `Upload Blob`, `Delete dog-picture.png`, `List Images`, etc All events MUST have a [NIP-40](https://github.com/nostr-protocol/nips/blob/master/40.md) `expiration` tag set to a unix timestamp at which the event should be considered expired. diff --git a/buds/03.md b/buds/03.md index c6a1730..cebc0fb 100644 --- a/buds/03.md +++ b/buds/03.md @@ -68,7 +68,7 @@ Take the following event as an example Once the client discovers that the URL `https://cdn.broken-domain.com/b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf` is no longer available. It can perform the following steps to find the blob: -1. Get the SHA256 has from the URL +1. Get the SHA256 hash from the URL 2. Look for the authors server list `kind:10063` 3. If found, Attempt to retrieve the blob from each `server` listed started with the first 4. If not found, the client MAY fallback to using a well-known popular blossom server to retrieve the blob diff --git a/buds/05.md b/buds/05.md index 97d9ff9..a7165eb 100644 --- a/buds/05.md +++ b/buds/05.md @@ -20,7 +20,7 @@ Servers MAY reject media uploads for any reason and should respond with the appr Servers MAY require a `media` [authorization event](./02.md#upload-authorization-required) to identify the uploader -If a server requires a `media` authorization event it MUST preform the following checks +If a server requires a `media` authorization event it MUST perform the following checks 1. The `t` tag MUST be set to `media` 2. MUST contain at least one `x` tag matching the sha256 hash of the body of the request @@ -33,7 +33,7 @@ Servers MUST respond to `HEAD` requests on the `/media` endpoint in a similar wa This endpoint is intentionally limited to optimizing a single blob with the goal of making it easier to distribute -How the blob is optimized is the sole respirability of the server and the client should have no say in what optimization process is used +How the blob is optimized is the sole responsibility of the server and the client should have no say in what optimization process is used The goal of this endpoint is to provide a simple "trusted" optimization endpoint clients can use to optimize media for distribution diff --git a/buds/06.md b/buds/06.md index 739404b..f3b9cbe 100644 --- a/buds/06.md +++ b/buds/06.md @@ -8,7 +8,7 @@ Defines how clients can verify if the upload can be completed before sending the ## HEAD /upload - Upload requirements -The `HEAD /upload` endpoint `MUST` use the `X-SHA-256`, `X-Content-Type` and `X-Content-Length` headers sent by client to get the SHA-256 hash, MIME type and size of the blob that will be uploaded, returning a HTTP status code and a custom header `X-Reason` to indicate some human readable message about the upload requirements. +The `HEAD /upload` endpoint MUST use the `X-SHA-256`, `X-Content-Type` and `X-Content-Length` headers sent by client to get the SHA-256 hash, MIME type and size of the blob that will be uploaded, returning a HTTP status code and a custom header `X-Reason` to indicate some human readable message about the upload requirements. ### Headers @@ -38,7 +38,7 @@ Example response from the server if the upload can be done: HTTP/1.1 200 OK ``` -If the upload cannot proceed, the server `MUST` return an appropriate `4xx` HTTP status code and a custom header `X-Reason` with a human readable error message. +If the upload cannot proceed, the server MUST return an appropriate `4xx` HTTP status code and a custom header `X-Reason` with a human readable error message. Some examples of error messages: diff --git a/buds/09.md b/buds/09.md index 0c2f808..bf3a961 100644 --- a/buds/09.md +++ b/buds/09.md @@ -35,7 +35,7 @@ The clients can show a blob report button on posts or in blob details. Or its RE ### Server behavior -The servers MAY keep the reports somewhere for operators to check and take action on them. they MAY use a list of trusted people or moderators to directly take action on blob without operator request. +The servers MAY keep the reports somewhere for operators to check and take action on them. they MAY use a list of trusted people or moderators to directly take action on blob without operator request. Servers MAY consider removed blobs sha256 as blocked to prevent rewrite. -Servers SHOULD advertise a route or landing page to provide their rules and term of service which affects the report process. +Servers SHOULD advertise a route or landing page to provide their rules and terms of service which affects the report process. From 3ae2361b416991389008cc27bf210e8bd46b6414 Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Mon, 12 May 2025 09:38:25 -0500 Subject: [PATCH 65/85] switch to `cursor` and `limit` with optional date filters --- buds/02.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/buds/02.md b/buds/02.md index 4c6686d..22a4566 100644 --- a/buds/02.md +++ b/buds/02.md @@ -73,11 +73,11 @@ Example Authorization event: The `/list/` endpoint MUST return a JSON array of [Blob Descriptor](#blob-descriptor) that where uploaded by the specified pubkey -The endpoint MUST support `limit`, `offset` query parameters for offset limit based pagination. The returned array of blob descriptors MUST be sorted by the `uploaded` date in descending order - The endpoint MUST support `cursor` and`limit` query parameters for cursor based pagination. The `cursor` parameter MUST be the `sha256` hash of the last blob in the previous page. The returned array of blob descriptors MUST be sorted by the `uploaded` date in descending order and should not include the blob at the cursor -Servers may reject a list for any reason and MUST respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection +The endpoint MUST support `since` and `until` query parameters to filter the list of blobs by their `uploaded` date, although it is not recommended for clients to use these parameters for pagination. + +Servers may reject a list request for any reason and MUST respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection ### List Authorization (optional) From 66e6dcec747c98561be4a677e84415a42dc27d87 Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Tue, 13 May 2025 09:31:19 -0500 Subject: [PATCH 66/85] Add BUD-00 to define BUDs and common language --- README.md | 37 ++++++++++++++++++------------------- buds/00.md | 19 +++++++++++++++++++ 2 files changed, 37 insertions(+), 19 deletions(-) create mode 100644 buds/00.md diff --git a/README.md b/README.md index 628b37a..0fc2093 100644 --- a/README.md +++ b/README.md @@ -4,13 +4,29 @@ Blossom uses [nostr](https://github.com/nostr-protocol/nostr) public / private k ## What is it? -Blossom is a spec for a set of HTTP endpoints that allow users to store blobs of data on publicly accessible servers +Blossom is a specification for a set of HTTP endpoints that allow users to store blobs of data on publicly accessible servers ## What are blobs Blobs are packs of binary data addressed by their sha256 hash -## How does it work? +## Protocol specification (BUDs) + +BUDs or **Blossom Upgrade Documents** are short documents that outline an additional feature that a blossom server may implement. + +## BUDs + +- [BUD-00: Blossom Upgrade Documents](./buds/00.md) +- [BUD-01: Server requirements and blob retrieval](./buds/01.md) +- [BUD-02: Blob upload and management](./buds/02.md) +- [BUD-03: User Server List](./buds/03.md) +- [BUD-04: Mirroring blobs](./buds/04.md) +- [BUD-05: Media optimization](./buds/05.md) +- [BUD-06: Upload requirements](./buds/06.md) +- [BUD-08: Nostr File Metadata Tags](./buds/08.md) +- [BUD-09: Blob Report](./buds/09.md) + +## Endpoints Blossom Servers expose a few endpoints for managing blobs @@ -32,23 +48,6 @@ Blossom Servers expose a few endpoints for managing blobs - `Authentication`: Signed [nostr event](./buds/05.md#upload-authorization) - `PUT /report` [BUD-09](./buds/09.md) -## Protocol specification (BUDs) - -BUDs stand for **Blossom Upgrade Documents**. - -See the [BUDs](./buds) folder and specifically [BUD-01](./buds/01.md) and [BUD-02](./buds/02.md) for a detailed explanation of the endpoints - -## BUDs - -- [BUD-01: Server requirements and blob retrieval](./buds/01.md) -- [BUD-02: Blob upload and management](./buds/02.md) -- [BUD-03: User Server List](./buds/03.md) -- [BUD-04: Mirroring blobs](./buds/04.md) -- [BUD-05: Media optimization](./buds/05.md) -- [BUD-06: Upload requirements](./buds/06.md) -- [BUD-08: Nostr File Metadata Tags](./buds/08.md) -- [BUD-09: Blob Report](./buds/09.md) - ## Event kinds | kind | description | BUD | diff --git a/buds/00.md b/buds/00.md new file mode 100644 index 0000000..fc50c19 --- /dev/null +++ b/buds/00.md @@ -0,0 +1,19 @@ +# BUD-00 + +## Blossom Upgrade Documents + +`draft` `mandatory` + +This document details the common language for all following BUDs + +## Language + +All occurences of "MUST", "MUST NOT", "SHOULD", "SHOULD NOT" MUST be interpreted as per [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119) + +## BUDs + +BUDs or "Blossom Upgrade Documents" are short documents that outline an additional requirement or feature that a blossom server MUST or MAY implement. + +## Blobs + +Blobs are raw binary data addressed by the sha256 hash of the data. From fca1c42406b2e98dcf3e839ed21056f99e85133f Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Tue, 13 May 2025 09:31:54 -0500 Subject: [PATCH 67/85] Add missing HEAD for CORS headers --- buds/01.md | 2 +- buds/09.md | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/buds/01.md b/buds/01.md index 4c42e94..894778b 100644 --- a/buds/01.md +++ b/buds/01.md @@ -11,7 +11,7 @@ _All pubkeys MUST be in hex format_ Servers MUST set the `Access-Control-Allow-Origin: *` header on all responses to ensure compatibility with applications hosted on other domains. For [preflight](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#preflighted_requests) (`OPTIONS`) requests, -servers MUST also set, at minimum, the `Access-Control-Allow-Headers: Authorization, *` and `Access-Control-Allow-Methods: GET, PUT, +servers MUST also set, at minimum, the `Access-Control-Allow-Headers: Authorization, *` and `Access-Control-Allow-Methods: GET, HEAD, PUT, DELETE` headers. The header `Access-Control-Max-Age: 86400` MAY be set to cache the results of a preflight request for 24 hours. diff --git a/buds/09.md b/buds/09.md index bf3a961..94c9478 100644 --- a/buds/09.md +++ b/buds/09.md @@ -6,7 +6,6 @@ This bud defines a new endpoint for clients and users to report blobs to servers. - ### PUT /report - reporting a blob The request body MUST be a signed [NIP-56](https://github.com/nostr-protocol/nips/blob/master/56.md) report event with one or more `x` tags containing the hashes of the blobs being reported. From 2d1593d634d23ea60d3d3b42242898642e4d1152 Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Tue, 13 May 2025 10:32:09 -0500 Subject: [PATCH 68/85] Clarify wording on BUD-04 --- buds/04.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/buds/04.md b/buds/04.md index 474fce8..dd041d9 100644 --- a/buds/04.md +++ b/buds/04.md @@ -8,7 +8,7 @@ Defines the `/mirror` endpoint ## PUT /mirror - Mirror Blob -A server may expose a `PUT /mirror` endpoint to allow users to copy a blob from a URL instead of uploading it +A server MAY expose a `PUT /mirror` endpoint to allow users to copy a blob from a URL instead of uploading it Clients MUST pass the URL of the remote blob as a stringified JSON object in the request body @@ -23,19 +23,19 @@ Clients MAY set the `Authorization` header to an upload authorization event defi The `/mirror` endpoint MUST download the blob from the specified URL and verify that there is at least one `x` tag in the authorization event matching the sha256 hash of the download blob -**Multiple `x` tags in the authorization event MUST NOT be interpreted as the user requesting a bulk mirror.** +**Multiple `x` tags in the authorization event MUST NOT be interpreted as the user requesting to mirror multiple blobs.** -The endpoint MUST return a [Blob Descriptor](#blob-descriptor) if the mirroring was successful or an error object if it was not +The endpoint MUST return a [Blob Descriptor](#blob-descriptor) and a `2xx` status code if the mirroring was successful or a `4xx` status code and error messageif it was not -Servers should re-use the `Content-Type` header returned from the URL to discover the mime type of the blob. if none is returned it may use the file extension in the URL +Servers SHOULD re-use the `Content-Type` header returned from the request to the URL to discover the mime type of the blob. If the `Content-Type` header is not returned they SHOULD attempt to use the file extension in the URL to guess the mime type. -Servers MAY reject a mirror request for any reason and should respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection +Servers MAY reject a mirror request for any reason and MUST respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection. ## Example Flow -1. Client signs authorization event and uploads blob to Server A -1. Server A returns blob descriptor with `url` -1. Client sends the `url` to Server B `/mirror` using the original authorization event -1. Server B downloads blob from Server A using the url -1. Server B verifies downloaded blob hash matches `x` tag in authorization event -1. Server B returns [Blob Descriptor](./02.md#blob-descriptor) +1. Client signs an `upload` authorization event and uploads blob to Server A +1. Server A returns a [Blob Descriptor](./02.md#blob-descriptor) with the `url` +1. Client sends the `url` to Server B `/mirror` using the original `upload` authorization event +1. Server B downloads the blob from Server A using the `url` +1. Server B verifies the downloaded blob hash matches the `x` tag in the authorization event +1. Server B returns a [Blob Descriptor](./02.md#blob-descriptor) From 620d74c2a289798ba660e087aa57d2903b7c376d Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Tue, 13 May 2025 10:50:44 -0500 Subject: [PATCH 69/85] Clarify has blob endpoint in BUD-01 Require headers to be identical to get endpoint --- buds/01.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/buds/01.md b/buds/01.md index 4c42e94..09c872b 100644 --- a/buds/01.md +++ b/buds/01.md @@ -75,11 +75,11 @@ All endpoints MUST be served from the root of the domain (eg. the `/upload` endp ## GET /sha256 - Get Blob -The `GET /` endpoint MUST return the contents of the blob with the `Content-Type` header set to the appropriate MIME-type +The `GET /` endpoint MUST return the contents of the blob in the response body. the `Content-Type` header SHOULD beset to the appropriate MIME-type The endpoint MUST accept an optional file extension in the URL. ie. `.pdf`, `.png`, etc -If the endpoints returns a 301 or 302 redirect it MUST redirect to a URL containing the same sha256 hash as the requested blob. +If the endpoint returns a `301` or `302` redirect it MUST redirect to a URL containing the same sha256 hash as the requested blob. This ensures that if a user was to copy or reuse the redirect URL it would still contain the original sha256 hash ### Get Authorization (optional) @@ -131,7 +131,9 @@ Example event for retrieving multiple blobs from single server: ## HEAD /sha256 - Has Blob -The `HEAD /` endpoint MUST respond with either a `200` or `404` status code +The `HEAD /` endpoint MUST be identical to the `GET /` endpoint except that it MUST NOT return the blob in the reponse body per [RFC 7231](https://www.rfc-editor.org/rfc/rfc7231#section-4.3.2) + +The endpoint MUST respond with the same headers that the `GET /` endpoint would respond with including the `Content-Type` header and other content headers. The endpoint MUST accept an optional file extension in the URL similar to the `GET /` endpoint. ie. `.pdf`, `.png`, etc From 0baee02851f4a3de6cd1a0ca83427aaa51233c64 Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Sat, 24 May 2025 12:08:00 -0500 Subject: [PATCH 70/85] add fallback to application/octet-stream --- buds/04.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buds/04.md b/buds/04.md index dd041d9..dde6fc4 100644 --- a/buds/04.md +++ b/buds/04.md @@ -27,7 +27,7 @@ The `/mirror` endpoint MUST download the blob from the specified URL and verify The endpoint MUST return a [Blob Descriptor](#blob-descriptor) and a `2xx` status code if the mirroring was successful or a `4xx` status code and error messageif it was not -Servers SHOULD re-use the `Content-Type` header returned from the request to the URL to discover the mime type of the blob. If the `Content-Type` header is not returned they SHOULD attempt to use the file extension in the URL to guess the mime type. +Servers SHOULD use the `Content-Type` header returned from the requested URL to infer the mime type of the blob. If the `Content-Type` header is not returned they SHOULD attempt to use the file extension in the URL or fallback to `application/octet-stream`. Servers MAY reject a mirror request for any reason and MUST respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection. From d6c2f9721fe7e9004ce55397d3899ae96bd0e6e1 Mon Sep 17 00:00:00 2001 From: Sadeq <141845753+SwimmingRieux@users.noreply.github.com> Date: Fri, 6 Jun 2025 18:56:56 +0330 Subject: [PATCH 71/85] Fix typo: Change 'where' to 'were' in Blob upload and management (BUD-02) --- buds/02.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buds/02.md b/buds/02.md index 6d8519c..7264be9 100644 --- a/buds/02.md +++ b/buds/02.md @@ -71,7 +71,7 @@ Example Authorization event: ## GET /list/pubkey - List Blobs (Optional) -The `/list/` endpoint MUST return a JSON array of [Blob Descriptor](#blob-descriptor) that where uploaded by the specified pubkey +The `/list/` endpoint MUST return a JSON array of [Blob Descriptor](#blob-descriptor) that were uploaded by the specified pubkey The endpoint MUST support a `since` and `until` query parameter to limit the returned blobs by their `uploaded` date From 977d0be083d91d7457000a8e8f74d32925171609 Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Tue, 17 Jun 2025 15:00:33 -0500 Subject: [PATCH 72/85] explicitly require content-type and content-length --- buds/01.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/buds/01.md b/buds/01.md index 09c872b..92e8121 100644 --- a/buds/01.md +++ b/buds/01.md @@ -131,9 +131,9 @@ Example event for retrieving multiple blobs from single server: ## HEAD /sha256 - Has Blob -The `HEAD /` endpoint MUST be identical to the `GET /` endpoint except that it MUST NOT return the blob in the reponse body per [RFC 7231](https://www.rfc-editor.org/rfc/rfc7231#section-4.3.2) +The `HEAD /` endpoint SHOULD be identical to the `GET /` endpoint except that it MUST NOT return the blob in the reponse body per [RFC 7231](https://www.rfc-editor.org/rfc/rfc7231#section-4.3.2) -The endpoint MUST respond with the same headers that the `GET /` endpoint would respond with including the `Content-Type` header and other content headers. +The endpoint MUST respond with the same `Content-Type` and `Content-Length` headers as the `GET /` endpoint. The endpoint MUST accept an optional file extension in the URL similar to the `GET /` endpoint. ie. `.pdf`, `.png`, etc From 5ef2889547dec88427bf17a3cf7869768b876b75 Mon Sep 17 00:00:00 2001 From: Anthony Accioly <1591739+aaccioly@users.noreply.github.com> Date: Wed, 4 Jun 2025 19:13:37 +0100 Subject: [PATCH 73/85] Make type mandatory in the blob descriptor --- buds/02.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buds/02.md b/buds/02.md index 7264be9..e491892 100644 --- a/buds/02.md +++ b/buds/02.md @@ -15,7 +15,7 @@ A blob descriptor is a JSON object containing `url`, `sha256`, `size`, `type`, a - `url` A publicly accessible URL to the [BUD-01](./01.md#get-sha256---get-blob) `GET /` endpoint with a file extension - `sha256` The sha256 hash of the blob - `size` The size of the blob in bytes -- `type` (optional) The MIME type of the blob +- `type` The MIME type of the blob (falling back to `application/octet-stream` if unknown) - `uploaded` The unix timestamp of when the blob was uploaded to the server Servers MUST include a file extension in the URL in the `url` field to allow clients to easily embed the URL in social posts or other content From cacfa520dd9b26f3f7220625d00798da5062422e Mon Sep 17 00:00:00 2001 From: Anthony Accioly <1591739+aaccioly@users.noreply.github.com> Date: Wed, 4 Jun 2025 19:58:02 +0100 Subject: [PATCH 74/85] Clarify requirements around Content-Type and Content-Length - Specify that the server must return the MIME type in the Content-Type header for blob retrieval. - Clarify fallback behaviour for unknown MIME types to application/octet-stream. - Improve the description of how servers should infer MIME types and handle Content-Length for mirror requests. --- buds/01.md | 3 +++ buds/04.md | 9 +++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/buds/01.md b/buds/01.md index c10a883..1b17cc5 100644 --- a/buds/01.md +++ b/buds/01.md @@ -79,6 +79,9 @@ The `GET /` endpoint MUST return the contents of the blob in the respons The endpoint MUST accept an optional file extension in the URL. ie. `.pdf`, `.png`, etc +Regardless of the file extension, the server MUST return the MIME type of the blob in the `Content-Type` +header. If the server does not know the MIME type of the blob, it MUST default to `application/octet-stream` + If the endpoint returns a `301` or `302` redirect it MUST redirect to a URL containing the same sha256 hash as the requested blob. This ensures that if a user was to copy or reuse the redirect URL it would still contain the original sha256 hash diff --git a/buds/04.md b/buds/04.md index dde6fc4..4f323c9 100644 --- a/buds/04.md +++ b/buds/04.md @@ -25,9 +25,14 @@ The `/mirror` endpoint MUST download the blob from the specified URL and verify **Multiple `x` tags in the authorization event MUST NOT be interpreted as the user requesting to mirror multiple blobs.** -The endpoint MUST return a [Blob Descriptor](#blob-descriptor) and a `2xx` status code if the mirroring was successful or a `4xx` status code and error messageif it was not +The endpoint MUST return a [Blob Descriptor](#blob-descriptor) and a `2xx` status code if the mirroring was successful +or a `4xx` status code and error message if it was not. -Servers SHOULD use the `Content-Type` header returned from the requested URL to infer the mime type of the blob. If the `Content-Type` header is not returned they SHOULD attempt to use the file extension in the URL or fallback to `application/octet-stream`. +Servers SHOULD use the `Content-Type` header returned from the requested URL to infer the mime type of the blob. If the +`Content-Type` header is not present they SHOULD attempt to detect the `Content-Type` from the blob contents and file +extension, falling back to `application/octet-stream` if they cannot determine the type. + +Servers MAY use the `Content-Length` header to determine the size of the blob. Servers MAY reject a mirror request for any reason and MUST respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection. From 1a085ed7bf8d4ae86abc17cb9c737df6ff7c6f05 Mon Sep 17 00:00:00 2001 From: Anthony Accioly <1591739+aaccioly@users.noreply.github.com> Date: Wed, 4 Jun 2025 20:15:03 +0100 Subject: [PATCH 75/85] fix: clarify Content-Type handling for blob retrieval and mirroring --- buds/01.md | 9 +++++---- buds/04.md | 6 +++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/buds/01.md b/buds/01.md index 1b17cc5..f45d497 100644 --- a/buds/01.md +++ b/buds/01.md @@ -79,8 +79,8 @@ The `GET /` endpoint MUST return the contents of the blob in the respons The endpoint MUST accept an optional file extension in the URL. ie. `.pdf`, `.png`, etc -Regardless of the file extension, the server MUST return the MIME type of the blob in the `Content-Type` -header. If the server does not know the MIME type of the blob, it MUST default to `application/octet-stream` +Regardless of the file extension, the server MUST return the MIME type of the blob in the `Content-Type` header. If the +server does not know the MIME type of the blob, it MUST default to `application/octet-stream` If the endpoint returns a `301` or `302` redirect it MUST redirect to a URL containing the same sha256 hash as the requested blob. This ensures that if a user was to copy or reuse the redirect URL it would still contain the original sha256 hash @@ -134,9 +134,10 @@ Example event for retrieving multiple blobs from single server: ## HEAD /sha256 - Has Blob -The `HEAD /` endpoint SHOULD be identical to the `GET /` endpoint except that it MUST NOT return the blob in the reponse body per [RFC 7231](https://www.rfc-editor.org/rfc/rfc7231#section-4.3.2) +The `HEAD /` endpoint SHOULD be identical to the `GET /` endpoint except that it MUST NOT return the +blob in the reponse body per [RFC 7231](https://www.rfc-editor.org/rfc/rfc7231#section-4.3.2) -The endpoint MUST respond with the same `Content-Type` and `Content-Length` headers as the `GET /` endpoint. +The endpoint MUST respond with the same `Content-Type` and `Content-Length` headerers as the `GET /` endpoint The endpoint MUST accept an optional file extension in the URL similar to the `GET /` endpoint. ie. `.pdf`, `.png`, etc diff --git a/buds/04.md b/buds/04.md index 4f323c9..6165ed4 100644 --- a/buds/04.md +++ b/buds/04.md @@ -28,9 +28,9 @@ The `/mirror` endpoint MUST download the blob from the specified URL and verify The endpoint MUST return a [Blob Descriptor](#blob-descriptor) and a `2xx` status code if the mirroring was successful or a `4xx` status code and error message if it was not. -Servers SHOULD use the `Content-Type` header returned from the requested URL to infer the mime type of the blob. If the -`Content-Type` header is not present they SHOULD attempt to detect the `Content-Type` from the blob contents and file -extension, falling back to `application/octet-stream` if they cannot determine the type. +The destination server SHOULD use the `Content-Type` header returned from the origin server to infer the mime type of +the blob. If the `Content-Type` header is not present the destination server SHOULD attempt to detect the `Content-Type` +from the blob contents and file extension, falling back to `application/octet-stream` if it cannot determine the type. Servers MAY use the `Content-Length` header to determine the size of the blob. From 611272e251cc25c408f79a2cb33e4425aba309bf Mon Sep 17 00:00:00 2001 From: Anthony Accioly <1591739+aaccioly@users.noreply.github.com> Date: Wed, 4 Jun 2025 21:37:13 +0100 Subject: [PATCH 76/85] Enhance proxying and redirection specification for blob retrieval --- buds/01.md | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/buds/01.md b/buds/01.md index f45d497..657b6ba 100644 --- a/buds/01.md +++ b/buds/01.md @@ -82,8 +82,22 @@ The endpoint MUST accept an optional file extension in the URL. ie. `.pdf`, `.pn Regardless of the file extension, the server MUST return the MIME type of the blob in the `Content-Type` header. If the server does not know the MIME type of the blob, it MUST default to `application/octet-stream` -If the endpoint returns a `301` or `302` redirect it MUST redirect to a URL containing the same sha256 hash as the requested blob. -This ensures that if a user was to copy or reuse the redirect URL it would still contain the original sha256 hash +### Proxying and Redirection (Optional) + +If the endpoint returns a redirection 3xx status code such as 307 or 308 ([RFC 9110 section +15.4](https://datatracker.ietf.org/doc/html/rfc9110#name-redirection-3xx)), it MUST redirect to a URL containing the +same sha256 hash as the requested blob. This ensures that if a user copies or reuses the redirect URL, it will still +contain the original sha56 hash. + +While the final blob may not be served from a Blossom server (e.g. CDN, IPFS, object storage, etc.), the destination +server MUST set the `Access-Control-Allow-Origin: *` header on the response to allow cross-origin requests, as well as +the `Content-Type` and `Content-Length` headers to ensure the blob can be correctly displayed by clients. Two ways to +guarantee this are: + +1. Proxying the blob through the Blossom server, allowing it to override headers such as `Content-Type`. +2. Manipulating the redirect URL to include a file extension that matches the blob type, such as `.pdf`, `.png`, etc. If +the server is unable to determine the MIME type of the blob, it MUST default to `application/octet-stream` and MAY +include a file extension in the URL that reflects the blob type (e.g. `.bin`, `.dat`, etc.). ### Get Authorization (optional) From b1a336fe750bb740552bc3d1cc7ce771e5849d41 Mon Sep 17 00:00:00 2001 From: Anthony Accioly <1591739+aaccioly@users.noreply.github.com> Date: Wed, 4 Jun 2025 21:38:51 +0100 Subject: [PATCH 77/85] Add optional file extension normalization during upload --- buds/02.md | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/buds/02.md b/buds/02.md index e491892..fa073b0 100644 --- a/buds/02.md +++ b/buds/02.md @@ -42,7 +42,15 @@ The endpoint MUST NOT modify the blob in any way and should return the exact sam The endpoint MUST return a [Blob Descriptor](#blob-descriptor) if the upload was successful or an error object if it was not -Servers MAY reject an upload for any reason and should respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection +Servers MAY reject an upload for any reason and should respond with the appropriate HTTP `4xx` status code and an error +message explaining the reason for the rejection + +### File extension normalization (Optional) + +When storing blobs, servers MAY normalise the file extension to a standard format (e.g. `.pdf`, `.png`, etc.) based on +the MIME type of the blob. This can be especially useful when the `GET /` endpoint is redirected to an external +URL (see the [proxying and redirection section from BUD-01](./01.md#proxying-and-redirection-optional)), as external +servers may rely on the file extension to serve the blob correctly. ### Upload Authorization (Optional) From 658c608b119e11702127322531382fabd7959be3 Mon Sep 17 00:00:00 2001 From: Anthony Accioly <1591739+aaccioly@users.noreply.github.com> Date: Wed, 4 Jun 2025 21:46:07 +0100 Subject: [PATCH 78/85] fix: update authorization event reference link in mirroring documentation --- buds/04.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buds/04.md b/buds/04.md index 6165ed4..67b013b 100644 --- a/buds/04.md +++ b/buds/04.md @@ -19,7 +19,7 @@ Clients MUST pass the URL of the remote blob as a stringified JSON object in the } ``` -Clients MAY set the `Authorization` header to an upload authorization event defined in [BUD-02](./02.md#upload-authorization-required). When using authorization, the event MUST be of type "upload". +Clients MAY set the `Authorization` header to an upload authorization event defined in [BUD-02](./02.md#upload-authorization-optional). When using authorization, the event MUST be of type "upload". The `/mirror` endpoint MUST download the blob from the specified URL and verify that there is at least one `x` tag in the authorization event matching the sha256 hash of the download blob From 85de0197f0e14c11fbe19958d7fbd4e7f8f10e26 Mon Sep 17 00:00:00 2001 From: Anthony Accioly <1591739+aaccioly@users.noreply.github.com> Date: Tue, 17 Jun 2025 23:18:13 +0100 Subject: [PATCH 79/85] fix: correct typo in Content-Length headers description in blob retrieval documentation --- buds/01.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buds/01.md b/buds/01.md index 657b6ba..4808b81 100644 --- a/buds/01.md +++ b/buds/01.md @@ -151,7 +151,7 @@ Example event for retrieving multiple blobs from single server: The `HEAD /` endpoint SHOULD be identical to the `GET /` endpoint except that it MUST NOT return the blob in the reponse body per [RFC 7231](https://www.rfc-editor.org/rfc/rfc7231#section-4.3.2) -The endpoint MUST respond with the same `Content-Type` and `Content-Length` headerers as the `GET /` endpoint +The endpoint MUST respond with the same `Content-Type` and `Content-Length` headers as the `GET /` endpoint. The endpoint MUST accept an optional file extension in the URL similar to the `GET /` endpoint. ie. `.pdf`, `.png`, etc From 39ce39aa4d5b02e2b57b745e19debfc412b1f154 Mon Sep 17 00:00:00 2001 From: Anthony Accioly <1591739+aaccioly@users.noreply.github.com> Date: Mon, 23 Jun 2025 14:21:32 +0100 Subject: [PATCH 80/85] fix: correct grammar in bud/01 redirect requirements Co-authored-by: hzrd149 <8001706+hzrd149@users.noreply.github.com> --- buds/01.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/buds/01.md b/buds/01.md index 4808b81..94243bf 100644 --- a/buds/01.md +++ b/buds/01.md @@ -86,8 +86,8 @@ server does not know the MIME type of the blob, it MUST default to `application/ If the endpoint returns a redirection 3xx status code such as 307 or 308 ([RFC 9110 section 15.4](https://datatracker.ietf.org/doc/html/rfc9110#name-redirection-3xx)), it MUST redirect to a URL containing the -same sha256 hash as the requested blob. This ensures that if a user copies or reuses the redirect URL, it will still -contain the original sha56 hash. +same sha256 hash as the requested blob. This ensures that if a user copies or reuses the redirect URL, it will +contain the original sha256 hash. While the final blob may not be served from a Blossom server (e.g. CDN, IPFS, object storage, etc.), the destination server MUST set the `Access-Control-Allow-Origin: *` header on the response to allow cross-origin requests, as well as From 90affdd4d9e87f4a82ed69e50ea7328ea2f821b4 Mon Sep 17 00:00:00 2001 From: hzrd149 <8001706+hzrd149@users.noreply.github.com> Date: Wed, 30 Jul 2025 12:55:58 -0500 Subject: [PATCH 81/85] Update to use cashu NUT-24 --- buds/07.md | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/buds/07.md b/buds/07.md index f996045..af8e278 100644 --- a/buds/07.md +++ b/buds/07.md @@ -10,12 +10,15 @@ Payment requirements for blob storage. ## Payment Required -Some servers MAY require payment for file storage. In such cases, these endpoints MUST return a **402 Payment Required** status code: +Some servers MAY require payment for uploads, downloads, or any other endpoint. In such cases, these endpoints MUST return a **402 Payment Required** status code. -- [HEAD /upload](./01.md#head-sha256---has-blob) (Optional, if [BUD-06](./06.md) is implemented) -- [PUT /upload](./02.md#put-upload---upload-blob) -- [HEAD /](./01.md#head-sha256---has-blob) -- [GET /](./01.md#get-sha256---get-blob) +Some endpoints a server may require payment for: + +- [`HEAD /upload`](./06.md) to signal that payment is required for the `PUT` request ( if [BUD-06](./06.md) is supported ) +- [`PUT /upload`](./02.md#put-upload---upload-blob) to require payment for uploads +- [`HEAD /`](./01.md#head-sha256---has-blob) to signal that payment is required for the `GET` request +- [`GET /`](./01.md#get-sha256---get-blob) to require payment for downloads ( maybe charge by MB downloaded? ) +- [`HEAD /media`](./05.md) and [`PUT /upload`](./05.md) to require payment for media optimizations ( if [BUD-06](./06.md) is supported ) When payment is required, the server MUST include one or more `X-{payment_method}` header(s), each corresponding to a supported payment method. @@ -25,7 +28,7 @@ The 402 status code and `X-{payment_method}` header is used by the server to inf Supported payment methods: -- `X-Cashu`: Payment details for the cashu payment method, adhering to the [NUT-18](https://github.com/cashubtc/nuts/blob/main/18.md) standard. +- `X-Cashu`: Payment details for the cashu payment method, adhering to the [NUT-24](https://github.com/cashubtc/nuts/blob/main/24.md) standard. - `X-Lightning`: Payment details for the lightning payment method, adhering to the [BOLT-11](https://github.com/lightning/bolts/blob/master/11-payment-encoding.md) standard. If a server supports multiple payment methods, it MAY send multiple `X-{payment_method}` headers in the same response. @@ -39,7 +42,7 @@ X-{payment_method}: "" ### `X-Cashu` Header -When using the X-Cashu header, the server MUST adhere to the [NUT-23](https://github.com/cashubtc/nuts/pull/239) standard. +When using the X-Cashu header, the server MUST adhere to the [NUT-24](https://github.com/cashubtc/nuts/blob/main/24.md) standard. Example for cashu: @@ -64,7 +67,7 @@ Clients MUST parse and validate the `X-{payment_method}` header received from th The client MUST provide the payment proof when re-trying the request using the same `X-{payment_method}` header that was chosen. The payment proof MUST align with the payment method specification: -- For cashu the payment proof should be a serialized cashu token according to [NUT-00](https://github.com/cashubtc/nuts/blob/main/00.md#v4-tokens). +- For cashu the payment proof should be a serialized `cashuB` token in the `X-Cashu` header according to [NUT-24](https://github.com/cashubtc/nuts/blob/main/24.md#client-payment). - For lightning the payment proof should be the preimage of the payment request according to [BOLT-11](https://github.com/lightning/bolts/blob/master/11-payment-encoding.md). Schema: @@ -82,7 +85,7 @@ X-Cashu: cashuBo2F0gqJhaUgA_9SLj17PgGFwgaNhYQFhc3hAYWNjMTI0MzVlN2I4NDg0YzNjZjE4N Example for Lightning: ```http -X-Lightning: "966fcb8f153339372f9a187f725384ff4ceae0047c25b9ce607488d7c7e93bba" +X-Lightning: 966fcb8f153339372f9a187f725384ff4ceae0047c25b9ce607488d7c7e93bba ``` **Special Note on HEAD Requests** @@ -99,4 +102,4 @@ To support future payment methods (e.g., other Layer 2 solutions), the specifica New methods MUST use a unique `X-{payment_method}` header containing the specific payment details. -New methods MUST adhere their own specification, which MUST be publicly available and linked in the header. \ No newline at end of file +New methods MUST adhere their own specification, which MUST be publicly available and linked in the header. From 7efca7a2a5f38000407af0248fcabc58b8f379be Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Tue, 4 Nov 2025 09:14:33 -0600 Subject: [PATCH 82/85] Update pagination method for `/list/` endpoint --- buds/02.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/buds/02.md b/buds/02.md index 22a4566..0a21ef9 100644 --- a/buds/02.md +++ b/buds/02.md @@ -38,18 +38,18 @@ Example: The `PUT /upload` endpoint MUST accept binary data in the body of the request and MAY use the `Content-Type` and `Content-Length` headers to get the MIME type and size of the data -The endpoint MUST NOT modify the blob in any way and should return the exact same sha256 that was uploaded. This is critical to allow users to re-upload their blobs to new servers +The endpoint MUST NOT modify the blob in any way and SHOULD return the exact same sha256 that was uploaded. This is critical to allow users to re-upload their blobs to new servers The endpoint MUST return a [Blob Descriptor](#blob-descriptor) if the upload was successful or an error object if it was not -Servers MAY reject an upload for any reason and should respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection +Servers MAY reject an upload for any reason and SHOULD respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection ### Upload Authorization (Optional) -Servers MAY accept an authorization event when uploading blobs and should perform additional checks +Servers MAY accept an authorization event when uploading blobs and SHOULD perform additional checks 1. The `t` tag MUST be set to `upload` -2. MUST contain at least one `x` tag matching the sha256 hash of the body of the request +2. The authorization event MUST contain at least one `x` tag matching the sha256 hash of the body of the request Example Authorization event: @@ -71,21 +71,21 @@ Example Authorization event: ## GET /list/pubkey - List Blobs (Optional) -The `/list/` endpoint MUST return a JSON array of [Blob Descriptor](#blob-descriptor) that where uploaded by the specified pubkey +The `/list/` endpoint MUST return a JSON array of [Blob Descriptor](#blob-descriptor) that were uploaded by the specified pubkey -The endpoint MUST support `cursor` and`limit` query parameters for cursor based pagination. The `cursor` parameter MUST be the `sha256` hash of the last blob in the previous page. The returned array of blob descriptors MUST be sorted by the `uploaded` date in descending order and should not include the blob at the cursor +The endpoint MUST support `cursor` and `limit` query parameters for cursor based pagination. The `cursor` parameter MUST be the `sha256` hash of the last blob in the previous page, or omitted to request the first page. The `limit` parameter specifies the maximum number of results to return. The returned array of blob descriptors MUST be sorted by the `uploaded` date in descending order and MUST NOT include the blob at the cursor -The endpoint MUST support `since` and `until` query parameters to filter the list of blobs by their `uploaded` date, although it is not recommended for clients to use these parameters for pagination. +The endpoint MAY support `since` and `until` query parameters to filter the list of blobs by their `uploaded` date. These parameters are deprecated for pagination purposes as they do not preserve server resources -Servers may reject a list request for any reason and MUST respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection +Servers MAY reject a list request for any reason and MUST respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection ### List Authorization (optional) -The server may optionally require Authorization when listing blobs uploaded by the pubkey +The server MAY optionally require Authorization when listing blobs uploaded by the pubkey -In this case the server must perform additional checks on the authorization event +In this case the server MUST perform additional checks on the authorization event -1. The `t` tag must be set to `list` +1. The `t` tag MUST be set to `list` Example Authorization event: @@ -108,16 +108,16 @@ Example Authorization event: Servers MUST accept `DELETE` requests to the `/` endpoint -Servers may reject a delete request for any reason and should respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection +Servers MAY reject a delete request for any reason and SHOULD respond with the appropriate HTTP `4xx` status code and an error message explaining the reason for the rejection ### Delete Authorization (required) Servers MUST accept an authorization event when deleting blobs -Servers should perform additional checks on the authorization event +Servers SHOULD perform additional checks on the authorization event -1. The `t` tag must be set to `delete` -2. MUST contain at least one `x` tag matching the sha256 hash of the blob being deleted +1. The `t` tag MUST be set to `delete` +2. The authorization event MUST contain at least one `x` tag matching the sha256 hash of the blob being deleted When multiple `x` tags are present on the authorization event the server MUST only delete the blob listed in the URL. From fe8906369c7ebbfd8f8ef770aad0711b6dd2bbd0 Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Tue, 4 Nov 2025 09:44:15 -0600 Subject: [PATCH 83/85] Add blob URI spec Another BUD-10 --- README.md | 1 + buds/10.md | 204 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 205 insertions(+) create mode 100644 buds/10.md diff --git a/README.md b/README.md index 7108f16..1eeb1d4 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ BUDs or **Blossom Upgrade Documents** are short documents that outline an additi - [BUD-07: Payment required](./buds/07.md) - [BUD-08: Nostr File Metadata Tags](./buds/08.md) - [BUD-09: Blob Report](./buds/09.md) +- [BUD-10: Blob URI Schema](./buds/10.md) ## Endpoints diff --git a/buds/10.md b/buds/10.md new file mode 100644 index 0000000..9256724 --- /dev/null +++ b/buds/10.md @@ -0,0 +1,204 @@ +# BUD-10 + +## Blob URI Schema + +`draft` `optional` + +Defines a URI schema for referencing Blossom blobs similar to magnet links. This allows users to share blob references that include discovery hints for locating the blob on other Blossom servers. + +## URI Format + +The `blob:` URI schema MUST follow this format: + +``` +blob:[.ext][?param1=value1¶m2=value2...] +``` + +### Components + +- `blob:` - The URI scheme identifier +- `` - A 64 character lowercase hexadecimal sha256 hash of the blob +- `[.ext]` - An optional file extension (e.g., `.pdf`, `.png`, `.jpg`, `.mp4`) +- `[?params]` - Optional query parameters for discovery hints + +### Examples + +``` +blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553 +blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf +blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.example.com +blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.png?as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&sz=184292 +``` + +## Query Parameters + +The `blob:` URI MAY include the following optional query parameters to assist with blob discovery: + +### `as` - Author + +The `as` parameter specifies the hex pubkey of a user who uploaded the blob. This parameter MAY be repeated multiple times to specify multiple potential authors. + +Clients can use this parameter to lookup the author's [BUD-03](./03.md) server list (`kind:10063`) and attempt to retrieve the blob from those servers. + +Example: +``` +blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0 +``` + +Multiple authors: +``` +blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&as=781208004e09102d7da3b7345e64fd193cd1bc3fce8fdae6008d77f9cabcd036 +``` + +### `xs` - Server + +The `xs` parameter specifies a server domain where the blob may be available. This parameter MAY be repeated multiple times to specify multiple server hints. + +The value SHOULD be a domain name only. Clients MUST assume the server operates at the root of the domain as per [BUD-01](./01.md#endpoints). The protocol scheme (http/https) MAY be included but is optional. When no scheme is specified, clients SHOULD try both `https://` and `http://` with preference given to `https://`. + +Example: +``` +blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.satellite.earth +``` + +With optional scheme: +``` +blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=https://cdn.satellite.earth +``` + +Multiple servers: +``` +blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.satellite.earth&xs=blossom.primal.net +``` + +### `sz` - Size + +The `sz` parameter MAY be used to specify the size of the blob in bytes. This can help clients: + +- Verify the downloaded blob matches the expected size +- Display download progress or estimated time +- Decide whether to download the blob based on size constraints +- Pre-allocate storage space + +Example: +``` +blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?sz=184292 +``` + +The size MUST be a positive integer representing the exact number of bytes in the blob. Clients SHOULD verify that the downloaded blob size matches the `sz` parameter if provided. + +### Combined Parameters + +All parameters MAY be combined in a single URI: + +``` +blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.satellite.earth&as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&xs=blossom.primal.net&sz=184292 +``` + +## Client Implementation + +### Parsing blob URIs + +When parsing a `blob:` URI, clients MUST: + +1. Verify the URI starts with the `blob:` scheme +2. Extract the 64 character hexadecimal sha256 hash +3. Extract the optional file extension if present +4. Parse any query parameters (`as`, `xs`, and `sz`) into appropriate types to handle multiple values + +### Resolution Strategy + +When resolving a `blob:` URI to retrieve the actual blob, clients SHOULD attempt retrieval in the following order: + +1. **Server Hints**: If the URI contains `xs` parameters, attempt to retrieve the blob from each specified server in the order they appear + - For servers without a protocol scheme, try `https://` first, then `http://` + - Request the blob using the [BUD-01](./01.md#get-sha256---get-blob) `GET /` endpoint + - Include the file extension from the URI if present + - If the `sz` parameter is present, verify the `Content-Length` header matches before downloading + +2. **Author Server Lists**: If the URI contains `as` parameters, for each author pubkey: + - Fetch the author's [BUD-03](./03.md) server list (`kind:10063`) + - Attempt to retrieve the blob from each server in the author's list in order + - If multiple authors are specified, try each author's server list before giving up + +3. **Fallback Servers**: If the blob cannot be found using hints, clients MAY fallback to: + - Well-known public Blossom servers + - Local cache or previously known locations + - User-configured default servers + +When downloading is complete, if the `sz` parameter was provided, clients SHOULD verify that the downloaded blob size matches the expected size. + +### Example Resolution Flow + +Given this URI: +``` +blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.example.com&as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&sz=184292 +``` + +A client would: + +1. Try `http://cdn.example.com/b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf` +2. Check that `Content-Length` header is `184292` before downloading +3. If that fails, fetch the `kind:10063` server list for pubkey `ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0` +4. Try each server from the author's list in order +5. Verify the downloaded blob is exactly `184292` bytes +6. If still not found, fallback to well-known servers or local cache + +### Creating and Sharing blob URIs + +When creating or sharing a `blob:` URI, clients SHOULD: + +1. Always include the sha256 hash +2. Include the file extension if known - this is especially important when sharing or embedding the URI in content (such as nostr events, web pages, or messages) as it allows other clients to determine the blob type without downloading or making additional HTTP requests +3. Include the `sz` parameter with the blob size in bytes to help with verification and download management +4. Include at least one `xs` parameter pointing to a server where the blob is known to exist +5. Include the `as` parameter with the uploader's pubkey to enable future discovery via their server list +6. Include multiple `xs` parameters if the blob has been mirrored to multiple servers + +Example of creating a URI after upload: + +```javascript +// After uploading to cdn.satellite.earth +const uri = `blob:${sha256}.${ext}?xs=cdn.satellite.earth&as=${userPubkey}&sz=${size}`; +``` + +## Use Cases + +The `blob:` URI schema enables several use cases: + +- **Decentralized Content Addressing**: Share content by hash with discovery hints instead of relying on a single server URL +- **Resilient Links**: Links that can survive server outages by including multiple server hints or author information +- **P2P Sharing**: Share blob references that don't depend on a specific server remaining online + +## Examples + +### Minimal URI +``` +blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553 +``` + +### With File Extension +``` +blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf +``` + +### With Single Server Hint +``` +blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.satellite.earth +``` + +### With Size and Author +``` +blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&sz=184292 +``` + +### Full Featured URI +``` +blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.satellite.earth&xs=blossom.primal.net&as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&sz=184292 +``` + +### Image with Multiple Authors and Servers +``` +blob:a7b3c2d1e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1.png?xs=cdn.example.com&xs=media.nostr.build&as=781208004e09102d7da3b7345e64fd193cd1bc3fce8fdae6008d77f9cabcd036&as=b53185b9f27962ebdf76b8a9b0a84cd8b27f9f3d4abd59f715788a3bf9e7f75e&sz=2547831 +``` + From 05a6c68dd8f016a251c8c384c3b15ce54eb8a8d8 Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Tue, 4 Nov 2025 09:48:40 -0600 Subject: [PATCH 84/85] Require file extension --- buds/10.md | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/buds/10.md b/buds/10.md index 9256724..a403e5c 100644 --- a/buds/10.md +++ b/buds/10.md @@ -11,23 +11,23 @@ Defines a URI schema for referencing Blossom blobs similar to magnet links. This The `blob:` URI schema MUST follow this format: ``` -blob:[.ext][?param1=value1¶m2=value2...] +blob:.[?param1=value1¶m2=value2...] ``` ### Components - `blob:` - The URI scheme identifier - `` - A 64 character lowercase hexadecimal sha256 hash of the blob -- `[.ext]` - An optional file extension (e.g., `.pdf`, `.png`, `.jpg`, `.mp4`) +- `.` - A file extension (e.g., `.pdf`, `.png`, `.jpg`, `.mp4`). If the file extension is unknown, it MUST default to `.bin` - `[?params]` - Optional query parameters for discovery hints ### Examples ``` -blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553 blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.example.com blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.png?as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&sz=184292 +blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.bin ``` ## Query Parameters @@ -103,7 +103,7 @@ When parsing a `blob:` URI, clients MUST: 1. Verify the URI starts with the `blob:` scheme 2. Extract the 64 character hexadecimal sha256 hash -3. Extract the optional file extension if present +3. Extract the file extension (which MUST be present) 4. Parse any query parameters (`as`, `xs`, and `sz`) into appropriate types to handle multiple values ### Resolution Strategy @@ -146,10 +146,13 @@ A client would: ### Creating and Sharing blob URIs -When creating or sharing a `blob:` URI, clients SHOULD: +When creating or sharing a `blob:` URI, clients MUST: 1. Always include the sha256 hash -2. Include the file extension if known - this is especially important when sharing or embedding the URI in content (such as nostr events, web pages, or messages) as it allows other clients to determine the blob type without downloading or making additional HTTP requests +2. Always include a file extension - if the file extension is unknown or cannot be determined, default to `.bin` (similar to how [BUD-01](./01.md#get-sha256---get-blob) defaults the MIME type to `application/octet-stream`) + +Clients SHOULD also: + 3. Include the `sz` parameter with the blob size in bytes to help with verification and download management 4. Include at least one `xs` parameter pointing to a server where the blob is known to exist 5. Include the `as` parameter with the uploader's pubkey to enable future discovery via their server list @@ -174,12 +177,12 @@ The `blob:` URI schema enables several use cases: ### Minimal URI ``` -blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553 +blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf ``` -### With File Extension +### Unknown File Type ``` -blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf +blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.bin ``` ### With Single Server Hint From 342cae9e5152c5214c83ca1f7f473c2eba0256f1 Mon Sep 17 00:00:00 2001 From: hzrd149 Date: Wed, 5 Nov 2025 13:48:17 -0600 Subject: [PATCH 85/85] switch URI to use "blossom" instead of "blob" --- README.md | 2 +- buds/10.md | 62 +++++++++++++++++++++++++++--------------------------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index 1eeb1d4..a8bfc2f 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ BUDs or **Blossom Upgrade Documents** are short documents that outline an additi - [BUD-07: Payment required](./buds/07.md) - [BUD-08: Nostr File Metadata Tags](./buds/08.md) - [BUD-09: Blob Report](./buds/09.md) -- [BUD-10: Blob URI Schema](./buds/10.md) +- [BUD-10: Blossom URI Schema](./buds/10.md) ## Endpoints diff --git a/buds/10.md b/buds/10.md index a403e5c..b772efd 100644 --- a/buds/10.md +++ b/buds/10.md @@ -1,6 +1,6 @@ # BUD-10 -## Blob URI Schema +## Blossom URI Schema `draft` `optional` @@ -8,15 +8,15 @@ Defines a URI schema for referencing Blossom blobs similar to magnet links. This ## URI Format -The `blob:` URI schema MUST follow this format: +The `blossom:` URI schema MUST follow this format: ``` -blob:.[?param1=value1¶m2=value2...] +blossom:.[?param1=value1¶m2=value2...] ``` ### Components -- `blob:` - The URI scheme identifier +- `blossom:` - The URI scheme identifier - `` - A 64 character lowercase hexadecimal sha256 hash of the blob - `.` - A file extension (e.g., `.pdf`, `.png`, `.jpg`, `.mp4`). If the file extension is unknown, it MUST default to `.bin` - `[?params]` - Optional query parameters for discovery hints @@ -24,15 +24,15 @@ blob:.[?param1=value1¶m2=value2...] ### Examples ``` -blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf -blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.example.com -blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.png?as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&sz=184292 -blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.bin +blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf +blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.example.com +blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.png?as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&sz=184292 +blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.bin ``` ## Query Parameters -The `blob:` URI MAY include the following optional query parameters to assist with blob discovery: +The `blossom:` URI MAY include the following optional query parameters to assist with blob discovery: ### `as` - Author @@ -42,12 +42,12 @@ Clients can use this parameter to lookup the author's [BUD-03](./03.md) server l Example: ``` -blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0 +blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0 ``` Multiple authors: ``` -blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&as=781208004e09102d7da3b7345e64fd193cd1bc3fce8fdae6008d77f9cabcd036 +blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&as=781208004e09102d7da3b7345e64fd193cd1bc3fce8fdae6008d77f9cabcd036 ``` ### `xs` - Server @@ -58,17 +58,17 @@ The value SHOULD be a domain name only. Clients MUST assume the server operates Example: ``` -blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.satellite.earth +blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.satellite.earth ``` With optional scheme: ``` -blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=https://cdn.satellite.earth +blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=https://cdn.satellite.earth ``` Multiple servers: ``` -blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.satellite.earth&xs=blossom.primal.net +blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.satellite.earth&xs=blossom.primal.net ``` ### `sz` - Size @@ -82,7 +82,7 @@ The `sz` parameter MAY be used to specify the size of the blob in bytes. This ca Example: ``` -blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?sz=184292 +blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?sz=184292 ``` The size MUST be a positive integer representing the exact number of bytes in the blob. Clients SHOULD verify that the downloaded blob size matches the `sz` parameter if provided. @@ -92,23 +92,23 @@ The size MUST be a positive integer representing the exact number of bytes in th All parameters MAY be combined in a single URI: ``` -blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.satellite.earth&as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&xs=blossom.primal.net&sz=184292 +blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.satellite.earth&as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&xs=blossom.primal.net&sz=184292 ``` ## Client Implementation -### Parsing blob URIs +### Parsing blossom URIs -When parsing a `blob:` URI, clients MUST: +When parsing a `blossom:` URI, clients MUST: -1. Verify the URI starts with the `blob:` scheme +1. Verify the URI starts with the `blossom:` scheme 2. Extract the 64 character hexadecimal sha256 hash 3. Extract the file extension (which MUST be present) 4. Parse any query parameters (`as`, `xs`, and `sz`) into appropriate types to handle multiple values ### Resolution Strategy -When resolving a `blob:` URI to retrieve the actual blob, clients SHOULD attempt retrieval in the following order: +When resolving a `blossom:` URI to retrieve the actual blob, clients SHOULD attempt retrieval in the following order: 1. **Server Hints**: If the URI contains `xs` parameters, attempt to retrieve the blob from each specified server in the order they appear - For servers without a protocol scheme, try `https://` first, then `http://` @@ -132,7 +132,7 @@ When downloading is complete, if the `sz` parameter was provided, clients SHOULD Given this URI: ``` -blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.example.com&as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&sz=184292 +blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.example.com&as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&sz=184292 ``` A client would: @@ -144,9 +144,9 @@ A client would: 5. Verify the downloaded blob is exactly `184292` bytes 6. If still not found, fallback to well-known servers or local cache -### Creating and Sharing blob URIs +### Creating and Sharing blossom URIs -When creating or sharing a `blob:` URI, clients MUST: +When creating or sharing a `blossom:` URI, clients MUST: 1. Always include the sha256 hash 2. Always include a file extension - if the file extension is unknown or cannot be determined, default to `.bin` (similar to how [BUD-01](./01.md#get-sha256---get-blob) defaults the MIME type to `application/octet-stream`) @@ -162,12 +162,12 @@ Example of creating a URI after upload: ```javascript // After uploading to cdn.satellite.earth -const uri = `blob:${sha256}.${ext}?xs=cdn.satellite.earth&as=${userPubkey}&sz=${size}`; +const uri = `blossom:${sha256}.${ext}?xs=cdn.satellite.earth&as=${userPubkey}&sz=${size}`; ``` ## Use Cases -The `blob:` URI schema enables several use cases: +The `blossom:` URI schema enables several use cases: - **Decentralized Content Addressing**: Share content by hash with discovery hints instead of relying on a single server URL - **Resilient Links**: Links that can survive server outages by including multiple server hints or author information @@ -177,31 +177,31 @@ The `blob:` URI schema enables several use cases: ### Minimal URI ``` -blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf +blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf ``` ### Unknown File Type ``` -blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.bin +blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.bin ``` ### With Single Server Hint ``` -blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.satellite.earth +blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.satellite.earth ``` ### With Size and Author ``` -blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&sz=184292 +blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&sz=184292 ``` ### Full Featured URI ``` -blob:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.satellite.earth&xs=blossom.primal.net&as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&sz=184292 +blossom:b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.satellite.earth&xs=blossom.primal.net&as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0&sz=184292 ``` ### Image with Multiple Authors and Servers ``` -blob:a7b3c2d1e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1.png?xs=cdn.example.com&xs=media.nostr.build&as=781208004e09102d7da3b7345e64fd193cd1bc3fce8fdae6008d77f9cabcd036&as=b53185b9f27962ebdf76b8a9b0a84cd8b27f9f3d4abd59f715788a3bf9e7f75e&sz=2547831 +blossom:a7b3c2d1e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1.png?xs=cdn.example.com&xs=media.nostr.build&as=781208004e09102d7da3b7345e64fd193cd1bc3fce8fdae6008d77f9cabcd036&as=b53185b9f27962ebdf76b8a9b0a84cd8b27f9f3d4abd59f715788a3bf9e7f75e&sz=2547831 ```