159 lines
4.8 KiB
Markdown
159 lines
4.8 KiB
Markdown
# peer.paste
|
||
|
||
Temporary P2P text snippets for the P2NS network.
|
||
|
||
## Features
|
||
|
||
- Realtime websocket-driven UI updates
|
||
- Text and markdown authoring with live preview
|
||
- Syntax highlighting support in preview and paste views
|
||
- Encryption by default (AES-GCM), optional public mode
|
||
- Optional passphrase-derived encryption mode
|
||
- Expiring pastes (default 24h, max 7 days)
|
||
- Optional burn-after-first-read and max-read limits
|
||
- Lightweight inline attachments with total-size cap
|
||
- Public share links (`/p/:id`)
|
||
- Raw consume API (`/api/pastes/:id/raw`)
|
||
- Metadata replication via HyperDB
|
||
|
||
## API
|
||
|
||
- `POST /api/pastes` create paste
|
||
- `GET /api/pastes` list active pastes
|
||
- `GET /api/pastes/mine` list active pastes owned by local peer
|
||
- `GET /api/pastes/:id` metadata
|
||
- `GET /api/pastes/:id/raw` consume/read paste content
|
||
- `GET /api/pastes/:id/attachments` list attachment metadata
|
||
- `GET /api/pastes/:id/attachments/:attachmentId` get attachment payload
|
||
- `PUT /api/pastes/:id` update paste (owner only, authenticated)
|
||
- `DELETE /api/pastes/:id` delete paste (owner only, authenticated)
|
||
- `GET /api/stats` service stats
|
||
- `GET /api/health` service health
|
||
- `POST /api/admin/cleanup` trigger immediate cleanup (authenticated)
|
||
- `GET /api/docs` interactive API docs page
|
||
- `GET /api/openapi.json` machine-readable OpenAPI schema
|
||
- `GET /p/:id` human-readable paste page
|
||
|
||
## curl examples
|
||
|
||
Replace `https://peer.paste` with your node’s plugin URL. If you use the local P2NS TLS cert, add `-k` to skip verification.
|
||
|
||
### Create a public paste
|
||
|
||
Public pastes store plaintext on the server (no browser encryption step), which is easiest for API clients:
|
||
|
||
```bash
|
||
curl -sS -X POST 'https://peer.paste/api/pastes' \
|
||
-H 'Content-Type: application/json' \
|
||
-d '{
|
||
"public": true,
|
||
"content": "Hello from curl",
|
||
"format": "text",
|
||
"language": "plaintext",
|
||
"expiresHours": 24
|
||
}'
|
||
```
|
||
|
||
Example response (fields may vary):
|
||
|
||
```json
|
||
{
|
||
"success": true,
|
||
"paste": { "id": "abc123...", "format": "text", "isPublic": true, ... },
|
||
"viewUrl": "/p/abc123...",
|
||
"apiUrl": "/api/pastes/abc123...",
|
||
"rawUrl": "/api/pastes/abc123.../raw"
|
||
}
|
||
```
|
||
|
||
Save `paste.id` (or parse it with `jq`):
|
||
|
||
```bash
|
||
PASTE_ID=$(curl -sS -X POST 'https://peer.paste/api/pastes' \
|
||
-H 'Content-Type: application/json' \
|
||
-d '{"public":true,"content":"Quick test","format":"text"}' \
|
||
| jq -r '.paste.id')
|
||
echo "$PASTE_ID"
|
||
```
|
||
|
||
Markdown example:
|
||
|
||
```bash
|
||
curl -sS -X POST 'https://peer.paste/api/pastes' \
|
||
-H 'Content-Type: application/json' \
|
||
-d '{
|
||
"public": true,
|
||
"content": "# Title\n\nSome **markdown**.",
|
||
"format": "markdown",
|
||
"language": "markdown"
|
||
}'
|
||
```
|
||
|
||
Encrypted pastes require a client-generated `encrypted` payload (`iv`, `ciphertext`, optional `salt`); use the web UI or your own crypto before calling `POST /api/pastes` without `"public": true`.
|
||
|
||
### View a paste
|
||
|
||
**Metadata** (does not increment read count):
|
||
|
||
```bash
|
||
curl -sS "https://peer.paste/api/pastes/${PASTE_ID}"
|
||
```
|
||
|
||
**Raw content** (increments `readCount`; may delete burn-after-read pastes):
|
||
|
||
```bash
|
||
curl -sS "https://peer.paste/api/pastes/${PASTE_ID}/raw"
|
||
```
|
||
|
||
For a public paste, the JSON includes `paste.content`. For encrypted pastes, use `paste.encryptedPayload` and decrypt in your client, or open the share link in a browser with the `#k=...` key fragment.
|
||
|
||
**Browser page** (HTML UI, decrypt UI for encrypted pastes):
|
||
|
||
```text
|
||
https://peer.paste/p/${PASTE_ID}
|
||
```
|
||
|
||
Pretty-print raw JSON:
|
||
|
||
```bash
|
||
curl -sS "https://peer.paste/api/pastes/${PASTE_ID}/raw" | jq .
|
||
```
|
||
|
||
## Realtime WebSocket Messages
|
||
|
||
- Client -> server: `request-pastes`, `create-paste`, `destroy-paste`
|
||
- Server -> client: `init`, `pastes-page`, `pastes-updated`, `paste-created`, `paste-destroyed`, `error`
|
||
|
||
## Payload Notes
|
||
|
||
- Create/Update fields used by plugin:
|
||
- `format`: `text` or `markdown`
|
||
- `public`: `true` for plaintext storage, otherwise encrypted payload expected
|
||
- `encrypted`: `{ iv, ciphertext, salt? }` for encrypted mode
|
||
- `encryptionMode`: e.g. `aes-gcm`, `passphrase-aes-gcm`, `none`
|
||
- `attachments`: inline list of `{ id, name, mime, size, data }`
|
||
|
||
## Limits and Behavior
|
||
|
||
- Content max length: `100000` chars
|
||
- Expiry max: `168` hours
|
||
- Max read count value: `1000000`
|
||
- Attachment cap:
|
||
- max attachments processed: `16`
|
||
- max total attachment bytes: `64MB`
|
||
- The realtime sidebar lists **all active pastes** in the replicated database (every peer), not only local ones. Burn-after-read pastes are excluded from that feed.
|
||
- Cleanup task runs hourly and removes expired/consumed entries.
|
||
- Paste data is replicated via HyperDB.
|
||
|
||
## Local Vendor Assets (No CDN)
|
||
|
||
`peer.paste` serves markdown/highlight dependencies locally via:
|
||
|
||
- `/api/vendor/marked.min.js`
|
||
- `/api/vendor/highlight.min.js`
|
||
- `/api/vendor/highlight-dark.css`
|
||
|
||
## Validation Script
|
||
|
||
- Run `node test-scripts/peer-paste-smoke.js https://peer.paste` to validate core API/OpenAPI availability.
|