Files
kindexr/docs/ARCHITECTURE.md
enki 1b7b70426c feat: Phase 0 bootstrap — kindexr boots, migrates, serves /health
- config: koanf-based loading (defaults → YAML → KINDEXR_ env vars)
- db: embedded SQLite migrations with BEGIN/END-aware statement splitter
- server: chi router, GET /health returns JSON stats
- cmd/kindexr: graceful SIGTERM shutdown
- cmd/kindexr-cli: stub
- deploy: systemd unit, example config, nginx snippet
- all packages covered by race-clean tests
2026-05-16 18:45:15 -07:00

72 lines
3.3 KiB
Markdown

# Architecture
nzbstr is a two-halves daemon:
- **Reader** (Phase 1+): subscribes to Nostr relays for kind 2003 (torrent) and kind 2004 (torrent comment) events, indexes them locally in SQLite, and exposes a Torznab-compatible HTTP API.
- **Writer** (Phase 4+): watches a download client (qBittorrent / Transmission / Deluge) for completed downloads, builds NIP-35 events signed by your npub, and publishes them to configured outbox relays.
## Data flow
```
Sonarr / Radarr / Lidarr / Readarr / Prowlarr
|
v Torznab HTTP/XML
|
+-----------+
| nzbstr |
| reader | <-- subscribes to relays via WebSocket
| writer | --> publishes via WebSocket
+-----------+
^ ^
| |
v v
Nostr relays qBittorrent / Transmission / Deluge
(NIP-35 events) (download client)
```
## Components
### `cmd/nzbstr` — main daemon
Entry point. Loads config, opens the SQLite database (applying any pending migrations), starts the HTTP server, and installs signal handlers for graceful shutdown.
### `internal/config`
koanf-based configuration loading. Load order: compiled-in defaults → YAML file → environment variables (`NZBSTR_` prefix). Missing files are silently skipped so the daemon can start with all defaults.
### `internal/db`
SQLite access via `modernc.org/sqlite` (pure Go, no CGO). Includes an embedded migration runner that applies numbered SQL files from `internal/db/migrations/` on startup. Uses WAL journal mode and a single writer connection for safe concurrent reads.
### `internal/server`
chi-based HTTP server. Phase 0 exposes only `/health`. Phase 1 adds `/api?t=caps`, `/api?t=search`, etc.
### `internal/nostr` (Phase 1+)
Relay subscription loop using `github.com/nbd-wtf/go-nostr`. NIP-77 negentropy bootstrap for efficient historical sync. Parses kind 2003 events into the internal `Torrent` struct and writes them to SQLite.
### `internal/torznab` (Phase 1+)
chi routes for the Torznab API. Auth middleware validates API keys. Returns XML in Torznab RSS format. Categories mapped from NIP-35 `i` tags to newznab integer codes.
### `internal/enrich` (Phase 2+)
Title parser (extracts season/episode/quality/source from release names) and TMDB client for backfilling IMDB/TMDB/TVDB IDs on events that lack them.
### `internal/wot` (Phase 3+)
Web-of-Trust filter. Fetches the operator's kind 3 follow list and optionally follows-of-follows to build an allowed-pubkey set. Integrates with NIP-51 curation sets.
### `internal/publisher` (Phase 4+)
qBittorrent / Transmission / watch-dir integration. Polls for completed downloads in the configured category, builds kind 2003 events, signs them via NIP-46 bunker or local key, and publishes to outbox relays.
## Storage
Single SQLite file at `/var/lib/nzbstr/nzbstr.db`. Schema managed by embedded SQL migrations in `internal/db/migrations/`. FTS5 virtual table on `(title, description)` with triggers to keep it in sync.
## Deployment
Single static binary + systemd unit. No external services required. Sits behind nginx for TLS termination. See `deploy/nzbstr.service` and `deploy/nginx.conf.example`.