scholarr/README.md
2026-02-17 15:21:08 +01:00

155 lines
3.7 KiB
Markdown

# scholarr
API-first, self-hosted scholar tracking backend in the spirit of the `*arr` ecosystem.
The legacy server-rendered UI has been removed. This repository now focuses on core ingestion, scheduling, and multi-user API functionality.
## Current Scope
- Multi-user accounts with admin-managed user lifecycle
- Same-origin cookie sessions with CSRF enforcement
- API auth flows (login, logout, me, password change)
- Admin user management API
- Scholar CRUD per user
- Per-user ingestion settings
- Manual runs with idempotency support
- Run history, run detail diagnostics, and continuation queue actions
- Publication listing (`new` / `all`) and mark-all-read
- Ingestion scheduler + continuation queue retries
- Structured logging with request IDs + redaction
- PostgreSQL + Alembic migrations
- Container-first development workflow with `uv`
## Functionality Tracking
Planned and supported backend functionality is tracked in:
- `AGENTS.MD`
## API Base
- Base path: `/api/v1`
- Success envelope:
- `{"data": ..., "meta": {"request_id": "..."}}`
- Error envelope:
- `{"error": {"code": "...", "message": "...", "details": ...}, "meta": {"request_id": "..."}}`
## Auth & Session Model
- Session transport: same-origin cookie session (`HttpOnly`, `SameSite=Lax`)
- CSRF:
- Required for unsafe methods (`POST`, `PUT`, `PATCH`, `DELETE`) via `X-CSRF-Token`
- Bootstrap token via `GET /api/v1/auth/csrf`
## API Surface
- Auth:
- `GET /api/v1/auth/csrf`
- `POST /api/v1/auth/login`
- `GET /api/v1/auth/me`
- `POST /api/v1/auth/change-password`
- `POST /api/v1/auth/logout`
- Admin users:
- `GET /api/v1/admin/users`
- `POST /api/v1/admin/users`
- `PATCH /api/v1/admin/users/{id}/active`
- `POST /api/v1/admin/users/{id}/reset-password`
- Scholars:
- `GET /api/v1/scholars`
- `POST /api/v1/scholars`
- `PATCH /api/v1/scholars/{id}/toggle`
- `DELETE /api/v1/scholars/{id}`
- Settings:
- `GET /api/v1/settings`
- `PUT /api/v1/settings`
- Runs:
- `GET /api/v1/runs`
- `GET /api/v1/runs/{id}`
- `POST /api/v1/runs/manual` (`Idempotency-Key` supported)
- `GET /api/v1/runs/queue/items`
- `POST /api/v1/runs/queue/{id}/retry`
- `POST /api/v1/runs/queue/{id}/drop`
- `DELETE /api/v1/runs/queue/{id}`
- Publications:
- `GET /api/v1/publications`
- `POST /api/v1/publications/mark-all-read`
- Ops:
- `GET /healthz`
## Quick Start
1. Copy environment defaults:
```bash
cp .env.example .env
```
2. Optional bootstrap admin on startup:
```bash
export BOOTSTRAP_ADMIN_ON_START=1
export BOOTSTRAP_ADMIN_EMAIL=admin@example.com
export BOOTSTRAP_ADMIN_PASSWORD=change-me-now
```
3. Start stack:
```bash
docker compose up --build
```
4. Health check:
```text
http://localhost:8000/healthz
```
## Admin Bootstrap (Manual)
```bash
docker compose run --rm app uv run python scripts/bootstrap_admin.py \
--email admin@example.com \
--password change-me-now \
--force-password
```
## Test Workflow
- Unit tests:
```bash
docker compose run --rm app uv run pytest tests/unit
```
- Integration tests:
```bash
docker compose run --rm app uv run pytest -m integration
```
- Smoke checks:
```bash
./scripts/smoke_compose.sh
```
## Logging
Configurable env vars:
- `LOG_LEVEL` (default `INFO`)
- `LOG_FORMAT` (`console` or `json`, default `console`)
- `LOG_REQUESTS` (`1`/`0`, default `1`)
- `LOG_UVICORN_ACCESS` (`1`/`0`, default `0`)
- `LOG_REQUEST_SKIP_PATHS` (default `/healthz`)
- `LOG_REDACT_FIELDS` (additional redact keys)
## Project Layout
```text
app/ FastAPI app (API routers, auth, services, db, middleware)
alembic/ Migration environment and versions
scripts/ Entrypoint, db wait/bootstrap, smoke automation
tests/ Unit, integration, and smoke suites
planning/ Scope and implementation planning notes
```