mirror of
https://github.com/hzrd149/blossom.git
synced 2026-01-31 01:08:58 +00:00
Compare commits
2 Commits
update-aut
...
4f0a47ff0b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4f0a47ff0b | ||
|
|
442d5c6293 |
15
README.md
15
README.md
@@ -1,6 +1,6 @@
|
||||
# 🌸 Blossom - Blobs stored simply on mediaservers
|
||||
|
||||
Blossom uses [nostr](https://github.com/nostr-protocol/nostr) public / private keys for users identities.
|
||||
Blossom uses [nostr](https://github.com/nostr-protocol/nostr) public / private keys for identities. Users are expected to sign authorization events to prove their identity when interacting with servers
|
||||
|
||||
## What is it?
|
||||
|
||||
@@ -27,7 +27,6 @@ BUDs or **Blossom Upgrade Documents** are short documents that outline an additi
|
||||
- [BUD-08: Nostr File Metadata Tags](./buds/08.md)
|
||||
- [BUD-09: Blob Report](./buds/09.md)
|
||||
- [BUD-10: Blossom URI Schema](./buds/10.md)
|
||||
- [BUD-11: Nostr Authorization](./buds/11.md)
|
||||
|
||||
## Endpoints
|
||||
|
||||
@@ -36,26 +35,26 @@ Blossom Servers expose a few endpoints for managing blobs
|
||||
- `GET /<sha256>` (optional file `.ext`) [BUD-01](./buds/01.md#get-sha256---get-blob)
|
||||
- `HEAD /<sha256>` (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/11.md) (see [BUD-02](./buds/02.md#upload-authorization))
|
||||
- `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/<pubkey>` [BUD-02](./buds/02.md#get-listpubkey---list-blobs-unrecommended) _(optional, unrecommended)_
|
||||
- Returns an array of blob descriptors
|
||||
- `Authentication` _(optional)_: Signed [nostr event](./buds/11.md) (see [BUD-02](./buds/02.md#list-authorization))
|
||||
- `Authentication` _(optional)_: Signed [nostr event](./buds/02.md#list-authorization-optional)
|
||||
- `DELETE /<sha256>` [BUD-02](./buds/02.md#delete-sha256---delete-blob)
|
||||
- `Authentication`: Signed [nostr event](./buds/11.md) (see [BUD-02](./buds/02.md#delete-authorization))
|
||||
- `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/11.md) (see [BUD-02](./buds/02.md#upload-authorization))
|
||||
- `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/11.md) (see [BUD-05](./buds/05.md#upload-authorization))
|
||||
- `Authentication`: Signed [nostr event](./buds/05.md#upload-authorization)
|
||||
- `PUT /report` [BUD-09](./buds/09.md)
|
||||
|
||||
## Event kinds
|
||||
|
||||
| kind | description | BUD |
|
||||
| ------- | ------------------- | ------------------ |
|
||||
| `24242` | Authorization token | [11](./buds/11.md) |
|
||||
| `24242` | Authorization event | [01](./buds/01.md) |
|
||||
| `10063` | User Server List | [03](./buds/03.md) |
|
||||
|
||||
## License
|
||||
|
||||
59
buds/01.md
59
buds/01.md
@@ -20,6 +20,55 @@ The header `Access-Control-Max-Age: 86400` MAY be set to cache the results of a
|
||||
|
||||
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
|
||||
|
||||
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 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.
|
||||
|
||||
Authorization events MAY have multiple `x` tags for endpoints that require a sha256 hash.
|
||||
|
||||
Example event:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"id": "bb653c815da18c089f3124b41c4b5ec072a40b87ca0f50bbbc6ecde9aca442eb",
|
||||
"pubkey": "b53185b9f27962ebdf76b8a9b0a84cd8b27f9f3d4abd59f715788a3bf9e7f75e",
|
||||
"kind": 24242,
|
||||
"content": "Upload bitcoin.pdf",
|
||||
"created_at": 1708773959,
|
||||
"tags": [
|
||||
["t", "upload"],
|
||||
// Authorization events MAY have multiple "x" tags.
|
||||
["x", "b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553"],
|
||||
["expiration", "1708858680"]
|
||||
],
|
||||
"sig": "d0d58c92afb3f4f1925120b99c39cffe77d93e82f488c5f8f482e8f97df75c5357175b5098c338661c37d1074b0a18ab5e75a9df08967bfb200930ec6a76562f"
|
||||
}
|
||||
```
|
||||
|
||||
Servers must perform the following checks in order to validate the event
|
||||
|
||||
1. The `kind` must be `24242`
|
||||
2. `created_at` must be in the past
|
||||
3. The `expiration` tag must be set to a Unix timestamp in the future
|
||||
4. The `t` tag must have a verb matching the intended action of the endpoint
|
||||
5. Additional checks for specific endpoints. `/upload`, `/delete`, etc
|
||||
|
||||
Using the `Authorization` HTTP header, the kind `24242` event MUST be base64 encoded and use the Authorization scheme Nostr
|
||||
|
||||
Example HTTP Authorization header:
|
||||
|
||||
```
|
||||
Authorization: Nostr eyJpZCI6IjhlY2JkY2RkNTMyOTIwMDEwNTUyNGExNDI4NzkxMzg4MWIzOWQxNDA5ZDhiOTBjY2RiNGI0M2Y4ZjBmYzlkMGMiLCJwdWJrZXkiOiI5ZjBjYzE3MDIzYjJjZjUwOWUwZjFkMzA1NzkzZDIwZTdjNzIyNzY5MjhmZDliZjg1NTM2ODg3YWM1NzBhMjgwIiwiY3JlYXRlZF9hdCI6MTcwODc3MTIyNywia2luZCI6MjQyNDIsInRhZ3MiOltbInQiLCJnZXQiXSxbImV4cGlyYXRpb24iLCIxNzA4ODU3NTQwIl1dLCJjb250ZW50IjoiR2V0IEJsb2JzIiwic2lnIjoiMDJmMGQyYWIyM2IwNDQ0NjI4NGIwNzFhOTVjOThjNjE2YjVlOGM3NWFmMDY2N2Y5NmNlMmIzMWM1M2UwN2I0MjFmOGVmYWRhYzZkOTBiYTc1NTFlMzA4NWJhN2M0ZjU2NzRmZWJkMTVlYjQ4NTFjZTM5MGI4MzI4MjJiNDcwZDIifQ==
|
||||
```
|
||||
|
||||
## Endpoints
|
||||
|
||||
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
|
||||
@@ -54,14 +103,14 @@ include a file extension in the URL that reflects the blob type (e.g. `.bin`, `.
|
||||
|
||||
The server may optionally require authorization when retrieving blobs from the `GET /<sha256>` endpoint
|
||||
|
||||
In this case, the server MUST first perform the base validation checks defined in [BUD-11](./11.md#base-validation), then perform the following additional checks:
|
||||
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 authorization token MUST contain either a `server` tag (limiting the token to specific servers) or MUST contain at least one `x` tag matching the sha256 hash of the blob being retrieved (scoping the token to specific blob hashes). see [BUD-11](./11.md#tag-scoping).
|
||||
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
|
||||
|
||||
If the client did not send an `Authorization` header the server must respond with the appropriate HTTP status code `401` (Unauthorized)
|
||||
|
||||
Example authorization token for retrieving a single blob:
|
||||
Example event for retrieving a single blob:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -79,7 +128,7 @@ Example authorization token for retrieving a single blob:
|
||||
}
|
||||
```
|
||||
|
||||
Example authorization token for retrieving multiple blobs from single server:
|
||||
Example event for retrieving multiple blobs from single server:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -91,7 +140,7 @@ Example authorization token for retrieving multiple blobs from single server:
|
||||
"tags": [
|
||||
["t", "get"],
|
||||
["expiration", "1708857340"],
|
||||
["server", "cdn.example.com"]
|
||||
["server", "https://cdn.example.com/"]
|
||||
],
|
||||
"sig": "e402ade78e1714d40cd6bd3091bc5f4ada8e904e90301b5a2b9b5f0b6e95ce908d4f22b15e9fb86f8268a2131f8adbb3d1f0e7e7afd1ab0f4f08acb15822a999"
|
||||
}
|
||||
|
||||
28
buds/02.md
28
buds/02.md
@@ -53,12 +53,12 @@ servers may rely on the file extension to serve the blob correctly.
|
||||
|
||||
### Upload Authorization (Optional)
|
||||
|
||||
Servers MAY require an authorization token when uploading blobs. The server MUST first perform the base validation checks defined in [BUD-11](./11.md#base-validation), then perform the following 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. The authorization token MUST contain at least one `x` tag matching the sha256 hash of the body of the request. The `x` tag scopes the token to specific blob hashes (see [BUD-11](./11.md#tag-scoping)).
|
||||
2. The authorization event MUST contain at least one `x` tag matching the sha256 hash of the body of the request
|
||||
|
||||
Example authorization token:
|
||||
Example Authorization event:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -88,13 +88,15 @@ The endpoint MAY support `since` and `until` query parameters to filter the list
|
||||
|
||||
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
|
||||
### List Authorization (optional)
|
||||
|
||||
The server MAY require a `list` authorization token when listing blobs uploaded by the pubkey. If a server requires authorization it MUST first perform the base validation checks defined in [BUD-11](./11.md#base-validation), then it MUST perform the following additional checks:
|
||||
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
|
||||
|
||||
1. The `t` tag MUST be set to `list`
|
||||
|
||||
Example authorization token:
|
||||
Example Authorization event:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -117,16 +119,20 @@ Servers MUST accept `DELETE` requests to the `/<sha256>` 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
|
||||
|
||||
### Delete Authorization
|
||||
### Delete Authorization (required)
|
||||
|
||||
Servers MAY require a `delete` authorization token when deleting blobs. If a server requires authorization it MUST first perform the base validation checks defined in [BUD-11](./11.md#base-validation), then MUST perform the following additional checks:
|
||||
Servers MUST accept an authorization event when deleting blobs
|
||||
|
||||
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.
|
||||
2. The authorization event MUST contain at least one `x` tag matching the sha256 hash of the blob being deleted
|
||||
|
||||
**Multiple `x` tags in the authorization token MUST NOT be interpreted as the user requesting to delete multiple blobs.**
|
||||
When multiple `x` tags are present on the authorization event the server MUST only delete the blob listed in the URL.
|
||||
|
||||
Example authorization token:
|
||||
**Multiple `x` tags MUST NOT be interpreted as the user requesting a bulk delete.**
|
||||
|
||||
Example Authorization event:
|
||||
|
||||
```json
|
||||
{
|
||||
|
||||
21
buds/04.md
21
buds/04.md
@@ -19,6 +19,12 @@ 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-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
|
||||
|
||||
**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 message if it was not.
|
||||
|
||||
@@ -30,20 +36,11 @@ 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.
|
||||
|
||||
### Upload Authorization
|
||||
|
||||
Servers MAY require an `upload` authorization token when mirroring blobs. The server MUST first perform the base validation checks defined in [BUD-11](./11.md#base-validation), then MUST perform the following additional checks:
|
||||
|
||||
1. The `t` tag MUST be set to `upload`
|
||||
2. The authorization token MUST contain at least one `x` tag matching the sha256 hash of the downloaded blob. The `x` tag scopes the token to specific blob hashes (see [BUD-11](./11.md#tag-scoping)).
|
||||
|
||||
**Multiple `x` tags in the authorization token MUST NOT be interpreted as the user requesting to mirror multiple blobs.**
|
||||
|
||||
## Example Flow
|
||||
|
||||
1. Client signs an `upload` authorization token and uploads blob to Server A
|
||||
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 token
|
||||
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 token
|
||||
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)
|
||||
|
||||
@@ -18,10 +18,12 @@ Servers MAY reject media uploads for any reason and should respond with the appr
|
||||
|
||||
### Upload Authorization
|
||||
|
||||
Servers MAY require a `media` authorization token to identify the uploader. If a server requires a `media` authorization token it MUST first perform the base validation checks defined in [BUD-11](./11.md#base-validation), then MUST perform the following additional checks:
|
||||
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 perform the following checks
|
||||
|
||||
1. The `t` tag MUST be set to `media`
|
||||
2. The authorization token MUST contain at least one `x` tag matching the sha256 hash of the body of the request.
|
||||
2. MUST contain at least one `x` tag matching the sha256 hash of the body of the request
|
||||
|
||||
## HEAD /media
|
||||
|
||||
@@ -43,4 +45,4 @@ Clients MAY let a user selected a "trusted processing" server for uploading imag
|
||||
|
||||
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 the client can ask the user to sign another `upload` authorization token 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
|
||||
|
||||
@@ -18,7 +18,7 @@ The `HEAD /upload` endpoint MUST use the `X-SHA-256`, `X-Content-Type` and `X-Co
|
||||
|
||||
### Upload Authorization
|
||||
|
||||
The `HEAD /upload` endpoint MAY accept an `upload` authorization token using the `Authorization` header similar to what is used in the [`PUT /upload`](./02.md#upload-authorization) endpoint
|
||||
The `HEAD /upload` endpoint MAY accept an `upload` authorization event using the `Authorization` header similar to what is used in the [`PUT /upload`](./02.md#upload-authorization-required) endpoint
|
||||
|
||||
If the server requires authorization to upload it may respond with the `401` status code, or if authorization was provided and is invalid or not permitted it may respond with `403` status code
|
||||
|
||||
|
||||
77
buds/11.md
77
buds/11.md
@@ -1,77 +0,0 @@
|
||||
# BUD-11
|
||||
|
||||
## Nostr Authorization
|
||||
|
||||
`draft` `optional`
|
||||
|
||||
Defines the authorization token format used by blossom servers to identify users. Authorization tokens are optional and servers MAY require them for various endpoints.
|
||||
|
||||
## Authorization tokens
|
||||
|
||||
Authorization tokens are signed nostr events proving to a server that the user (`pubkey`) has permitted an application to take an action on their behalf.
|
||||
|
||||
The authorization token MUST be a nostr event of kind `24242` and have a `t` tag with a verb of `get`, `upload`, `list`, `delete`, or `media`
|
||||
|
||||
Authorization tokens MUST have the `content` set to a human readable string explaining intended use. For example `Upload Blob`, `Delete old blobs`, `List Images`, etc
|
||||
|
||||
All authorization tokens 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 token should be considered expired.
|
||||
|
||||
## Tag scoping
|
||||
|
||||
Authorization tokens MAY include `server` and `x` tags to scope the token to specific servers or blob hashes.
|
||||
|
||||
- **`server` tag**: Limits the token to specific servers by domain name. If no `server` tags are present, the token is valid for all servers. Multiple `server` tags may be present to allow the token to be used on multiple servers. The value MUST be a domain name only (e.g., `cdn.example.com`), not a full URL.
|
||||
|
||||
- **`x` tag**: Scopes the token to specific blob hashes (similar to how `server` scopes to servers). Multiple `x` tags may be present for endpoints that require a sha256 hash. When `x` tags are present, the token is only valid for operations on the specified blob hashes.
|
||||
|
||||
Example authorization token:
|
||||
|
||||
```jsonc
|
||||
{
|
||||
"id": "bb653c815da18c089f3124b41c4b5ec072a40b87ca0f50bbbc6ecde9aca442eb",
|
||||
"pubkey": "b53185b9f27962ebdf76b8a9b0a84cd8b27f9f3d4abd59f715788a3bf9e7f75e",
|
||||
"kind": 24242,
|
||||
"content": "Upload bitcoin.pdf",
|
||||
"created_at": 1708773959,
|
||||
"tags": [
|
||||
["t", "upload"],
|
||||
// Authorization tokens MAY have multiple "x" tags.
|
||||
["x", "b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553"],
|
||||
["expiration", "1708858680"]
|
||||
],
|
||||
"sig": "d0d58c92afb3f4f1925120b99c39cffe77d93e82f488c5f8f482e8f97df75c5357175b5098c338661c37d1074b0a18ab5e75a9df08967bfb200930ec6a76562f"
|
||||
}
|
||||
```
|
||||
|
||||
## Base validation
|
||||
|
||||
Servers must perform the following checks in order to validate the authorization token
|
||||
|
||||
1. The `kind` must be `24242`
|
||||
2. `created_at` must be in the past
|
||||
3. The `expiration` tag must be set to a Unix timestamp in the future
|
||||
4. The `t` tag must have a verb matching the intended action of the endpoint
|
||||
5. If `server` tags are present, the server MUST verify that its domain name is present in at least one `server` tag. If no `server` tags are present, the token is valid for all servers.
|
||||
|
||||
## HTTP Authorization header
|
||||
|
||||
Using the `Authorization` HTTP header, the authorization token (kind `24242`) MUST be base64 encoded and use the Authorization scheme Nostr
|
||||
|
||||
Example HTTP Authorization header:
|
||||
|
||||
```
|
||||
Authorization: Nostr eyJpZCI6IjhlY2JkY2RkNTMyOTIwMDEwNTUyNGExNDI4NzkxMzg4MWIzOWQxNDA5ZDhiOTBjY2RiNGI0M2Y4ZjBmYzlkMGMiLCJwdWJrZXkiOiI5ZjBjYzE3MDIzYjJjZjUwOWUwZjFkMzA1NzkzZDIwZTdjNzIyNzY5MjhmZDliZjg1NTM2ODg3YWM1NzBhMjgwIiwiY3JlYXRlZF9hdCI6MTcwODc3MTIyNywia2luZCI6MjQyNDIsInRhZ3MiOltbInQiLCJnZXQiXSxbImV4cGlyYXRpb24iLCIxNzA4ODU3NTQwIl1dLCJjb250ZW50IjoiR2V0IEJsb2JzIiwic2lnIjoiMDJmMGQyYWIyM2IwNDQ0NjI4NGIwNzFhOTVjOThjNjE2YjVlOGM3NWFmMDY2N2Y5NmNlMmIzMWM1M2UwN2I0MjFmOGVmYWRhYzZkOTBiYTc1NTFlMzA4NWJhN2M0ZjU2NzRmZWJkMTVlYjQ4NTFjZTM5MGI4MzI4MjJiNDcwZDIifQ==
|
||||
```
|
||||
|
||||
## Endpoint-specific requirements (example)
|
||||
|
||||
Individual endpoints may extend the base validation with additional requirements. The following are examples of how endpoints use authorization tokens:
|
||||
|
||||
- **`/upload`** ([BUD-02](./02.md#upload-authorization)): May requires at least one `x` tag matching the sha256 hash of the blob being uploaded
|
||||
- **`DELETE /<sha256>`** ([BUD-02](./02.md#delete-authorization)): May requires at least one `x` tag matching the sha256 hash of the blob being deleted
|
||||
- **`PUT /media`** ([BUD-05](./05.md#upload-authorization)): May requires at least one `x` tag matching the sha256 hash of the media being uploaded
|
||||
- **`GET /<sha256>`** ([BUD-01](./01.md#get-authorization)): May require either a `server` tag or at least one `x` tag matching the sha256 hash of the blob being retrieved
|
||||
- **`GET /list/<pubkey>`** ([BUD-02](./02.md#list-authorization)): May require a `server` tag limiting the token to specific servers
|
||||
- **`PUT /mirror`** ([BUD-04](./04.md#put-mirror---mirror-blob)): May requires at least one `x` tag matching the sha256 hash of the blob being mirrored
|
||||
|
||||
See the respective BUD documents for the exact requirements for each endpoint. All endpoints that accept authorization tokens MUST perform the base validation checks defined above before performing any endpoint-specific checks.
|
||||
13
implementations/README.md
Normal file
13
implementations/README.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# Blossom Implementations
|
||||
|
||||
This directory contains possible uses and implementations of the Blossom protocol. They are not part of the official Blossom specification but provide examples and inspiration for how the protocol can be used.
|
||||
|
||||
## Implementations
|
||||
|
||||
- [Local Blossom Cache](./local-blossom-cache.md)
|
||||
- [HLS Video Formatting](./hls-video-formatting.md)
|
||||
|
||||
## Contributions
|
||||
|
||||
Contributions are welcome! Documents in this directory MUST be compatible with the existing [BUDs](../buds) and should be focused on a single use case or implementation.
|
||||
|
||||
118
implementations/hls-video-formatting.md
Normal file
118
implementations/hls-video-formatting.md
Normal file
@@ -0,0 +1,118 @@
|
||||
# HLS Video Formatting
|
||||
|
||||
This document explains how to format [HLS](https://datatracker.ietf.org/doc/html/rfc8216) (HTTP Live Streaming) videos to be compatible with [BUD-01](./01.md) blob retrieval.
|
||||
|
||||
## Overview
|
||||
|
||||
HLS videos consist of multiple files:
|
||||
- A master playlist (`.m3u8`) that references variant playlists
|
||||
- Variant playlists (`.m3u8`) that reference media segments
|
||||
- Media segment files (typically `.ts` files)
|
||||
|
||||
Each file MUST be uploaded as a separate blob and referenced by its SHA256 hash using the [BUD-01](./01.md#get-sha256---get-blob) `GET /<sha256>` endpoint format.
|
||||
|
||||
## Relative Paths
|
||||
|
||||
To ensure compatibility across different Blossom servers and allow easy server switching, all URLs in HLS playlists MUST use relative paths containing the SHA256 hash of the referenced blob.
|
||||
|
||||
Clients MUST NOT include the full server domain in playlist URLs. This allows the same playlist to work with any Blossom server that hosts the referenced blobs.
|
||||
|
||||
## Master Playlist Format
|
||||
|
||||
The master playlist (`.m3u8`) MUST reference variant playlists using relative paths with SHA256 hashes.
|
||||
|
||||
The master playlist MUST have the MIME type `application/vnd.apple.mpegurl` or `application/x-mpegURL`.
|
||||
|
||||
Example master playlist:
|
||||
|
||||
```m3u8
|
||||
#EXTM3U
|
||||
#EXT-X-VERSION:3
|
||||
#EXT-X-STREAM-INF:BANDWIDTH=1280000,RESOLUTION=854x480
|
||||
a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456.m3u8
|
||||
#EXT-X-STREAM-INF:BANDWIDTH=2560000,RESOLUTION=1280x720
|
||||
f6e5d4c3b2a1098765432109876543210987654321fedcba0987654321fedcba.m3u8
|
||||
```
|
||||
|
||||
## Variant Playlist Format
|
||||
|
||||
Variant playlists (`.m3u8`) MUST reference media segments using relative paths with SHA256 hashes.
|
||||
|
||||
Each segment URL MUST be a relative path containing the SHA256 hash of the segment file. The file extension (`.ts`, `.m4s`, etc.) MAY be included for compatibility with HLS clients.
|
||||
|
||||
Example variant playlist:
|
||||
|
||||
```m3u8
|
||||
#EXTM3U
|
||||
#EXT-X-VERSION:3
|
||||
#EXT-X-TARGETDURATION:10
|
||||
#EXT-X-MEDIA-SEQUENCE:0
|
||||
#EXTINF:10.000,
|
||||
b82fcf4dbcec2d8fab7d94bdd48b070aa6e74d7240b1965a0b28c128d6858477.ts
|
||||
#EXTINF:10.000,
|
||||
cd2a98d055eef5ec3aca73bd136a40340539138da73144d589d9de5a3a52149a.ts
|
||||
#EXTINF:10.000,
|
||||
128e690f89419ecbea473a490c42cac94a2293ecf1f57d60492ceafce3d5cfdb.ts
|
||||
#EXT-X-ENDLIST
|
||||
```
|
||||
|
||||
## Media Segments
|
||||
|
||||
Media segment files (typically `.ts` files) MUST be uploaded as separate blobs. Each segment MUST be retrievable via the [BUD-01](./01.md#get-sha256---get-blob) `GET /<sha256>` endpoint.
|
||||
|
||||
The server SHOULD set the `Content-Type` header appropriately:
|
||||
- `.ts` files: `video/mp2t` or `video/MP2T`
|
||||
- `.m4s` files: `video/iso.segment` or `video/mp4`
|
||||
|
||||
## Client Implementation
|
||||
|
||||
When generating HLS playlists for Blossom:
|
||||
|
||||
1. Upload each media segment as a separate blob using [BUD-02](./02.md#put-upload---upload-blob) `PUT /upload`
|
||||
2. Upload each variant playlist as a separate blob
|
||||
3. Upload the master playlist as a separate blob
|
||||
4. In all playlists, use relative paths containing only the SHA256 hash (and optional file extension) of the referenced blob
|
||||
5. When serving the master playlist, clients MAY prepend the current server's base URL to resolve relative paths
|
||||
|
||||
Example client flow:
|
||||
|
||||
1. Upload segment `segment001.ts` → get SHA256: `1a2b3c4d...`
|
||||
2. Upload segment `segment002.ts` → get SHA256: `2b3c4d5e...`
|
||||
3. Create variant playlist referencing `1a2b3c4d...ts` and `2b3c4d5e...ts`
|
||||
4. Upload variant playlist → get SHA256: `a1b2c3d4...`
|
||||
5. Create master playlist referencing `a1b2c3d4...m3u8`
|
||||
6. Upload master playlist → get SHA256: `f9e8d7c6...`
|
||||
|
||||
## Server Implementation
|
||||
|
||||
When serving HLS playlists, servers MUST:
|
||||
|
||||
1. Return the playlist content with the appropriate `Content-Type` header (`application/vnd.apple.mpegurl` or `application/x-mpegURL`)
|
||||
2. Serve playlists via the [BUD-01](./01.md#get-sha256---get-blob) `GET /<sha256>` endpoint
|
||||
3. Support optional file extensions (e.g., `/<sha256>.m3u8`) as specified in [BUD-01](./01.md#get-sha256---get-blob)
|
||||
|
||||
When a client requests a playlist blob, the server MUST return the playlist content as-is, without modifying relative paths. The client is responsible for resolving relative paths to absolute URLs using the current server's base URL.
|
||||
|
||||
## URL Resolution
|
||||
|
||||
When a client retrieves a playlist from `https://cdn.example.com/<sha256>.m3u8`, relative paths in the playlist (e.g., `a1b2c3d4...m3u8`) MUST be resolved relative to the playlist's origin.
|
||||
|
||||
For example, if a playlist is served from `https://cdn.example.com/f9e8d7c6...m3u8` and contains a relative path `a1b2c3d4...m3u8`, the client SHOULD resolve it to `https://cdn.example.com/a1b2c3d4...m3u8`.
|
||||
|
||||
This allows the same playlist blob to work with any Blossom server, as long as all referenced blobs are available on that server.
|
||||
|
||||
## Example Complete Structure
|
||||
|
||||
```
|
||||
Master Playlist (SHA256: f9e8d7c6...)
|
||||
└─> Variant Playlist 1 (SHA256: a1b2c3d4...)
|
||||
└─> Segment 1 (SHA256: 1a2b3c4d...)
|
||||
└─> Segment 2 (SHA256: 2b3c4d5e...)
|
||||
└─> Segment 3 (SHA256: 3c4d5e6f...)
|
||||
└─> Variant Playlist 2 (SHA256: b2c3d4e5...)
|
||||
└─> Segment 1 (SHA256: 4d5e6f78...)
|
||||
└─> Segment 2 (SHA256: 5e6f7890...)
|
||||
└─> Segment 3 (SHA256: 6f789012...)
|
||||
```
|
||||
|
||||
All references between these files use relative paths containing only SHA256 hashes, making the entire HLS structure portable across different Blossom servers.
|
||||
102
implementations/local-blossom-cache.md
Normal file
102
implementations/local-blossom-cache.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# Local Blossom Cache
|
||||
|
||||
This document defines the specification for a local blob cache server that can be hosted on `127.0.0.1:24242` to provide fast, local access to cached blobs or proxy requests to other public Blossom servers.
|
||||
|
||||
## Server Address
|
||||
|
||||
A local blob cache server MUST be accessible on `http://127.0.0.1:24242`. The port `24242` is chosen to align with the Nostr event kind used for Blossom authorization events.
|
||||
|
||||
## Health Check Endpoint
|
||||
|
||||
The server MUST respond with a 2xx HTTP status code (typically `200 OK`) on the `HEAD /` endpoint to allow local applications to easily detect if the cache server is available.
|
||||
|
||||
The `HEAD /` endpoint MUST return a 2xx HTTP status code. The response MUST NOT include a response body per [RFC 7231](https://www.rfc-editor.org/rfc/rfc7231#section-4.3.2).
|
||||
|
||||
This endpoint enables simple health checks:
|
||||
|
||||
```bash
|
||||
curl -I http://127.0.0.1:24242/
|
||||
```
|
||||
|
||||
## Access Control
|
||||
|
||||
The server SHOULD NOT require any authentication for blob downloads or uploads. All requests MUST be served without requiring an `Authorization` header.
|
||||
|
||||
If an implementation needs to add access control, it SHOULD restrict access based on IP address to ensure requests only come from `127.0.0.1`. This ensures that local applications can freely access cached blobs without the overhead of signing authorization events.
|
||||
|
||||
## Blob Retrieval
|
||||
|
||||
The server MUST implement the `GET /<sha256>` and `HEAD /<sha256>` endpoints as defined in [BUD-01](./01.md#get-sha256---get-blob):
|
||||
|
||||
1. The server MUST accept optional file extensions in the URL (e.g., `/<sha256>.pdf`)
|
||||
2. The server MUST set appropriate `Content-Type` headers or default to `application/octet-stream`
|
||||
|
||||
## Range Requests
|
||||
|
||||
To better support mobile devices, video files, or low bandwidth connections, implementations SHOULD support range requests ([RFC 7233 section 3](https://www.rfc-editor.org/rfc/rfc7233#section-3)) on the `GET /<sha256>` endpoint and signal support using the `accept-ranges: bytes` and `content-length` headers on the `HEAD /<sha256>` endpoint.
|
||||
|
||||
See [MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests) for more details.
|
||||
|
||||
## Proxy Hints
|
||||
|
||||
The server SHOULD accept [BUD-10](./10.md) query parameters `xs` (server) and `as` (author) hints on the `GET /<sha256>` endpoint to enable proxying blob requests to other Blossom servers when the blob is not available in the local cache.
|
||||
|
||||
### Query Parameter Format
|
||||
|
||||
When a blob is not found in the local cache, the server MAY use the following query parameters to attempt retrieval from other Blossom servers:
|
||||
|
||||
- `xs=<server>` - One or more server hints where the blob may be available
|
||||
- `as=<pubkey>` - One or more author pubkeys whose server lists may contain the blob
|
||||
|
||||
### Example Request
|
||||
|
||||
```
|
||||
GET /b1674191a88ec5cdd733e4240a81803105dc412d6c6708d53ab94fc248f4f553.pdf?xs=cdn.example.com&as=ec4425ff5e9446080d2f70440188e3ca5d6da8713db7bdeef73d0ed54d9093f0
|
||||
```
|
||||
|
||||
### Proxy Behavior
|
||||
|
||||
When the server receives a request with proxy hints and the blob is not in the local cache:
|
||||
|
||||
1. The server SHOULD attempt to retrieve the blob from the servers specified in the `xs` parameters
|
||||
2. If `xs` hints fail, the server MAY attempt to retrieve the blob using the `as` parameters by:
|
||||
- Fetching the author's [BUD-03](./03.md) server list (`kind:10063`)
|
||||
- Attempting to retrieve the blob from servers in the author's list
|
||||
3. If the blob is successfully retrieved, the server SHOULD:
|
||||
- Cache the blob locally for future requests
|
||||
- Return the blob to the client with appropriate headers
|
||||
4. If the blob cannot be retrieved from any hint, the server MUST return a `404 Not Found` response
|
||||
|
||||
This proxy functionality allows the local cache server to act as a transparent proxy, automatically fetching and caching blobs from remote Blossom servers when needed.
|
||||
|
||||
## CORS Headers
|
||||
|
||||
The server MUST set the `Access-Control-Allow-Origin: *` header on all responses to ensure compatibility with web applications, as specified in [BUD-01](./01.md#cross-origin-headers).
|
||||
|
||||
## Use Cases
|
||||
|
||||
A local blob cache server enables several use cases:
|
||||
|
||||
- **Fast Local Access**: Applications can check the local cache first before making network requests to remote Blossom servers
|
||||
- **Offline Access**: Previously cached blobs remain accessible even when network connectivity is unavailable
|
||||
- **Bandwidth Savings**: Reduces redundant downloads of frequently accessed blobs
|
||||
- **Development**: Provides a simple local server for testing Blossom applications without requiring remote server access
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
- The server SHOULD implement efficient blob storage, such as using the sha256 hash as the filename or storage key
|
||||
- The server SHOULD implement cache eviction policies (e.g., LRU, size-based limits) to manage storage
|
||||
- The server SHOULD validate that downloaded blobs match their sha256 hash before caching
|
||||
- The server MAY implement the `HEAD /<sha256>` endpoint to allow clients to check blob availability without downloading
|
||||
|
||||
## Example Implementation Flow
|
||||
|
||||
1. Client requests blob: `GET http://127.0.0.1:24242/<sha256>`
|
||||
2. Server checks local cache
|
||||
3. If found: Return blob immediately
|
||||
4. If not found and proxy hints provided:
|
||||
- Attempt to fetch from `xs` server hints
|
||||
- If that fails, attempt to fetch using `as` author hints
|
||||
- Cache the blob if successfully retrieved
|
||||
- Return the blob to the client
|
||||
5. If not found and no proxy hints: Return `404 Not Found`
|
||||
Reference in New Issue
Block a user