128 lines
3.9 KiB
Markdown
128 lines
3.9 KiB
Markdown
# Backend
|
||
|
||
Rust backend for the Nostr relay hosting platform. This service manages tenants, relays, invoices, and billing, and provisions relays by calling the zooid HTTP API. It authenticates requests using NIP-98.
|
||
|
||
## Tech Stack
|
||
|
||
- Rust (Edition 2024)
|
||
- Axum (HTTP server)
|
||
- SQLx + SQLite (persistence)
|
||
- Nostr SDK (NIP-98 verification)
|
||
|
||
## Layout
|
||
|
||
```
|
||
backend/
|
||
migrations/ # SQL migrations
|
||
src/
|
||
auth.rs # NIP-98 verification helper
|
||
billing.rs # Billing loop + invoice generation
|
||
config.rs # Env-based configuration
|
||
db.rs # SQLite pool + migrations
|
||
main.rs # Axum server entrypoint
|
||
models.rs # Data models
|
||
notifications.rs # NIP-17 DM sender + relay discovery
|
||
platform.rs # Startup kind 0/10050 publishing
|
||
provisioning.rs # Zooid provisioning worker
|
||
repo.rs # Data access layer
|
||
```
|
||
|
||
## Configuration
|
||
|
||
Environment variables:
|
||
|
||
| Variable | Description | Default |
|
||
|---|---|---|
|
||
| `DATABASE_URL` | SQLite database URL | `sqlite://data/caravel.db` |
|
||
| `HOST` | Bind host | `127.0.0.1` |
|
||
| `PORT` | Bind port | `3000` |
|
||
| `ZOOID_API_URL` | Zooid API base URL | `http://127.0.0.1:8032` |
|
||
| `PLATFORM_SECRET` | Platform Nostr secret key for NIP-98 auth | _required_ |
|
||
| `RELAY_DOMAIN` | Relay base domain for subdomains | `spaces.coracle.social` |
|
||
| `NWC_URL` | Platform NWC URL for invoice generation | _required for billing_ |
|
||
| `NOSTR_INDEXER_RELAYS` | Comma-separated relays to fetch kind `10050` DM relays | _required for notifications_ |
|
||
| `PLATFORM_NAME` | Platform display name for kind `0` metadata | _optional_ |
|
||
| `PLATFORM_DESCRIPTION` | Platform description for kind `0` metadata | _optional_ |
|
||
| `PLATFORM_PICTURE` | Platform picture URL for kind `0` metadata | _optional_ |
|
||
| `PLATFORM_MESSAGING_RELAYS` | Comma-separated relays published in kind `10050` | _optional_ |
|
||
|
||
The database directory is created automatically if it doesn’t exist.
|
||
|
||
## Database Schema
|
||
|
||
Created via `migrations/0001_init.sql`:
|
||
|
||
- `tenants`
|
||
- `relays`
|
||
- `invoices`
|
||
- `invoice_items`
|
||
|
||
## Running
|
||
|
||
```bash
|
||
cd backend
|
||
cargo run
|
||
```
|
||
|
||
Health check:
|
||
|
||
```
|
||
GET /healthz
|
||
```
|
||
|
||
## NIP-98 Authentication
|
||
|
||
NIP-98 verification is implemented in `auth.rs` using the Rust Nostr SDK. It verifies:
|
||
|
||
- Authorization header format
|
||
- Event signature and kind
|
||
- URL + HTTP method tags
|
||
- Timestamp validity
|
||
|
||
This is ready to be used by API routes.
|
||
|
||
## Billing Jobs
|
||
|
||
The backend runs an in-process billing loop that:
|
||
|
||
- Generates monthly invoices (using `NWC_URL`)
|
||
- Uses the tenant’s `tenant_nwc_url` for recurring pull payments (if set)
|
||
- Sends NIP-17 DMs with invoices when recurring is off
|
||
- Sends NIP-17 DMs on successful payment when recurring is on
|
||
|
||
NIP-17 relay discovery:
|
||
|
||
- Uses `NOSTR_INDEXER_RELAYS` to fetch kind `10050` for each tenant
|
||
- Cached for a short period
|
||
- If no relays are found, no DM is sent
|
||
|
||
On startup, the backend publishes:
|
||
|
||
- Kind `0` metadata (name/description)
|
||
- Kind `10050` relay list for DMs
|
||
|
||
These are published to the relays listed in `NOSTR_INDEXER_RELAYS`.
|
||
|
||
## API Routes
|
||
|
||
Tenant routes (all require NIP-98 auth; pubkey is inferred from the token):
|
||
|
||
- `GET /tenant` — fetch (or create) tenant
|
||
- `GET /tenant/relays` — list tenant relays
|
||
- `POST /tenant/relays` — create relay
|
||
- `GET /tenant/relays/:id` — get relay
|
||
- `PUT /tenant/relays/:id` — update relay
|
||
- `DELETE /tenant/relays/:id` — deactivate relay
|
||
- `GET /tenant/invoices` — list invoices
|
||
- `PUT /tenant/billing` — update tenant billing (NWC URL)
|
||
|
||
Admin routes (all require NIP-98 auth; pubkey must be in `PLATFORM_ADMIN_PUBKEYS`):
|
||
|
||
- `GET /admin/tenants` — list tenants
|
||
- `GET /admin/tenants/:pubkey` — tenant detail (includes relays)
|
||
- `PUT /admin/tenants/:pubkey` — update tenant status
|
||
- `GET /admin/relays` — list relays
|
||
- `GET /admin/relays/:id` — get relay
|
||
- `PUT /admin/relays/:id` — update relay
|
||
- `DELETE /admin/relays/:id` — deactivate relay
|