test
This commit is contained in:
parent
efd21a7297
commit
441676be27
97 changed files with 10764 additions and 223 deletions
262
README.md
262
README.md
|
|
@ -1,30 +1,131 @@
|
|||
# scholarr
|
||||
|
||||
API-first, self-hosted scholar tracking backend in the spirit of the `*arr` ecosystem.
|
||||
<div align="center">
|
||||
|
||||
The legacy server-rendered UI has been removed. This repository now focuses on core ingestion, scheduling, and multi-user API functionality.
|
||||
API-first, self-hosted scholar tracking in the spirit of the `*arr` ecosystem.
|
||||
|
||||
## Current Scope
|
||||
[](https://github.com/justinzeus/scholarr/actions/workflows/ci.yml)
|
||||
[](https://hub.docker.com/r/justinzeus/scholarr)
|
||||
[](https://hub.docker.com/r/justinzeus/scholarr)
|
||||
|
||||
- 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`
|
||||
</div>
|
||||
|
||||
## Functionality Tracking
|
||||
## What This Includes
|
||||
|
||||
Planned and supported backend functionality is tracked in:
|
||||
- Multi-user accounts with admin-managed lifecycle
|
||||
- Cookie session auth with CSRF enforcement
|
||||
- Scholar CRUD + name-search discovery + profile image management
|
||||
- Per-user ingestion settings and scheduler
|
||||
- Manual runs with idempotency behavior
|
||||
- Run history and continuation queue diagnostics/actions
|
||||
- Publications workflow (`new` / `all`, mark-selected-read, mark-all-read)
|
||||
- Vue 3 + Vite frontend served from the same container image as the API
|
||||
|
||||
- `AGENTS.MD`
|
||||
## Docker Image
|
||||
|
||||
- Image: `justinzeus/scholarr`
|
||||
- Published by GitHub Actions on every push to `main`
|
||||
- Architectures: `linux/amd64`, `linux/arm64`
|
||||
- Tags:
|
||||
- `latest`
|
||||
- `sha-<short_commit>`
|
||||
|
||||
## Quick Deploy (Copy Compose + Fill Env)
|
||||
|
||||
1. Copy `docker-compose.yml` and `.env.example` into your deployment directory.
|
||||
2. Create `.env` from `.env.example`.
|
||||
3. Set at minimum:
|
||||
- `SESSION_SECRET_KEY`
|
||||
- `POSTGRES_PASSWORD`
|
||||
4. Pull and start:
|
||||
|
||||
```bash
|
||||
docker compose pull
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
5. Open:
|
||||
|
||||
- App + API: `http://localhost:8000`
|
||||
- Health check: `http://localhost:8000/healthz`
|
||||
|
||||
The SPA and API are same-origin by default in this deployment model.
|
||||
|
||||
## Required Environment Variables
|
||||
|
||||
| Variable | Required | Purpose |
|
||||
| --- | --- | --- |
|
||||
| `SESSION_SECRET_KEY` | Yes | Session signing key. Use a long random value. |
|
||||
| `POSTGRES_PASSWORD` | Yes | Database password for the bundled Postgres service. |
|
||||
|
||||
Optional startup bootstrap:
|
||||
|
||||
| Variable | Default | Purpose |
|
||||
| --- | --- | --- |
|
||||
| `BOOTSTRAP_ADMIN_ON_START` | `0` | Auto-create admin on app start. |
|
||||
| `BOOTSTRAP_ADMIN_EMAIL` | empty | Admin email for bootstrap. |
|
||||
| `BOOTSTRAP_ADMIN_PASSWORD` | empty | Admin password for bootstrap. |
|
||||
| `BOOTSTRAP_ADMIN_FORCE_PASSWORD` | `0` | Force-reset bootstrap admin password if exists. |
|
||||
|
||||
## Ports
|
||||
|
||||
| Port | Service | Description |
|
||||
| --- | --- | --- |
|
||||
| `8000` | `app` | scholarr API + frontend |
|
||||
|
||||
## Volumes
|
||||
|
||||
| Volume | Container Path | Purpose |
|
||||
| --- | --- | --- |
|
||||
| `postgres_data` | `/var/lib/postgresql/data` | Postgres persistence |
|
||||
| `scholar_uploads` | `/var/lib/scholarr/uploads` | Scholar image upload persistence |
|
||||
|
||||
## Upgrade
|
||||
|
||||
```bash
|
||||
docker compose pull
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
## Development Workflow
|
||||
|
||||
Default `docker-compose.yml` is deployment-oriented (prebuilt image).
|
||||
|
||||
For local development with source mounts + Vite dev server:
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d --build
|
||||
```
|
||||
|
||||
Then open:
|
||||
|
||||
- API: `http://localhost:8000`
|
||||
- Frontend dev server: `http://localhost:5173`
|
||||
|
||||
## Test and Quality Commands
|
||||
|
||||
Backend:
|
||||
|
||||
```bash
|
||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml run --rm app uv run pytest tests/unit
|
||||
docker compose -f docker-compose.yml -f docker-compose.dev.yml run --rm app uv run pytest -m integration
|
||||
```
|
||||
|
||||
Frontend:
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
npm install
|
||||
npm run typecheck
|
||||
npm run test:run
|
||||
npm run build
|
||||
```
|
||||
|
||||
Contract drift check:
|
||||
|
||||
```bash
|
||||
python3 scripts/check_frontend_api_contract.py
|
||||
```
|
||||
|
||||
## API Base
|
||||
|
||||
|
|
@ -34,122 +135,13 @@ Planned and supported backend functionality is tracked in:
|
|||
- 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:
|
||||
Important envs:
|
||||
|
||||
- `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
|
||||
```
|
||||
- `LOG_LEVEL`
|
||||
- `LOG_FORMAT` (`console` or `json`)
|
||||
- `LOG_REQUESTS`
|
||||
- `LOG_UVICORN_ACCESS`
|
||||
- `LOG_REQUEST_SKIP_PATHS`
|
||||
- `LOG_REDACT_FIELDS`
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue