12b40e6071
README: add free & open-source (MIT) framing; add a Platforms table (Windows/Linux/macOS/Docker supported, Android-TV build marked experimental, scrcpy phone-capture retained); expand the LED device list to ~20 protocols; correct storage to SQLite, the auth model, and resource names (Output Targets, Automations); add a prebuilt-download section; remove the Architecture and Acknowledgments sections; embed dashboard, channels, live-preview, and device-picker screenshots. docs/API.md: full rewrite from the live route modules — all 253 endpoints across 34 modules, grouped by resource with REST + WebSocket tables, accurate auth model and WS handshake, worked examples, and sensitive-endpoint markers. Replaces the stale v0.1.0 stub. server/CLAUDE.md: storage is now SQLite (BaseSqliteStore / ledgrab.db / LEDGRAB_DATA_DIR / data_migrations.py); fix the auth description (loopback anonymous, LAN rejected with 401 — not all endpoints open); router registration happens in api/__init__.py.
80 lines
4.1 KiB
Markdown
80 lines
4.1 KiB
Markdown
# Claude Instructions for LedGrab Server
|
|
|
|
## Project Structure
|
|
|
|
- `src/ledgrab/main.py` — FastAPI application entry point
|
|
- `src/ledgrab/api/routes/` — REST API endpoints (one file per entity)
|
|
- `src/ledgrab/api/schemas/` — Pydantic request/response models (one file per entity)
|
|
- `src/ledgrab/core/` — Core business logic (capture, devices, audio, processing, automations)
|
|
- `src/ledgrab/storage/` — Data models (dataclasses) and SQLite-backed persistence stores (`BaseSqliteStore`)
|
|
- `src/ledgrab/utils/` — Utility functions (logging, monitor detection, SSRF validation, sound playback)
|
|
- `src/ledgrab/static/` — Frontend files (TypeScript, CSS, locales)
|
|
- `src/ledgrab/templates/` — Jinja2 HTML templates
|
|
- `config/` — Configuration files (YAML)
|
|
- `data/` — Runtime data: SQLite database (`ledgrab.db`) + assets. Relocate the root with `LEDGRAB_DATA_DIR`.
|
|
|
|
## Entity & Storage Pattern
|
|
|
|
Each entity follows: dataclass model (`storage/`) + SQLite store (`storage/*_store.py`, subclassing `BaseSqliteStore`) + Pydantic schemas (`api/schemas/`) + routes (`api/routes/`).
|
|
|
|
Stores keep an in-memory write-through cache over a per-entity SQLite table (the legacy `BaseJsonStore` still exists for reference but new stores use `BaseSqliteStore`). Schema/data shape changes go through `storage/data_migrations.py` — migrations are idempotent and tracked in a dedicated `data_migrations` audit table, so they run safely on every startup. **When renaming or restructuring stored fields, add a migration there** (see the Data Migration Policy in the root `CLAUDE.md`).
|
|
|
|
## Authentication
|
|
|
|
API key authentication via Bearer token in the `Authorization` header (`Authorization: Bearer <key>`). WebSocket connections authenticate with a first-message handshake (`{"type":"auth","token":"<key>"}`). See `src/ledgrab/api/auth.py` for the canonical logic.
|
|
|
|
- Config: `config/default_config.yaml` under `auth.api_keys`; env var `LEDGRAB_AUTH__API_KEYS`
|
|
- When `api_keys` is **empty** (default): **loopback** requests (`127.0.0.1` / `::1` / `localhost`) are allowed anonymously, but **LAN / remote** requests are rejected with `401`. Auth is *not* fully open.
|
|
- When `api_keys` is **set**: a valid Bearer token is required from every client (loopback included).
|
|
- `require_authenticated()` rejects even loopback-anonymous callers on sensitive endpoints (e.g. backup download, secret reveal).
|
|
|
|
## Common Tasks
|
|
|
|
### Adding a new API endpoint
|
|
|
|
1. Create route file in `api/routes/` (define an `APIRouter(prefix="/api/v1/...")`)
|
|
2. Define request/response schemas in `api/schemas/`
|
|
3. Register the router in `api/__init__.py` (it aggregates every route module into the single `router` that `main.py` mounts)
|
|
4. Restart the server
|
|
5. Test via `/docs` (Swagger UI)
|
|
|
|
### Adding a new field to existing API
|
|
|
|
1. Update Pydantic schema in `api/schemas/`
|
|
2. Update corresponding dataclass in `storage/`
|
|
3. Update backend logic to populate the field
|
|
4. Restart the server
|
|
5. Update frontend to display the new field
|
|
6. Rebuild bundle: `cd server && npm run build`
|
|
|
|
### Adding translations
|
|
|
|
1. Add keys to `static/locales/en.json`, `static/locales/ru.json`, and `static/locales/zh.json`
|
|
2. Add `data-i18n` attributes to HTML elements in `templates/`
|
|
3. Use `t('key')` in TypeScript modules (`static/js/`)
|
|
4. No server restart needed (frontend only), but rebuild bundle if JS changed
|
|
|
|
### Modifying display/monitor detection
|
|
|
|
1. Update functions in `utils/monitor_names.py` or `core/screen_capture.py`
|
|
2. Restart the server
|
|
3. Test with `GET /api/v1/config/displays`
|
|
|
|
## Testing
|
|
|
|
```bash
|
|
cd server && pytest # Run all tests
|
|
cd server && pytest --cov # With coverage report
|
|
cd server && pytest tests/test_api.py # Single test file
|
|
```
|
|
|
|
Tests are in `server/tests/`. Config in `pyproject.toml` under `[tool.pytest]`.
|
|
|
|
## Frontend Conventions
|
|
|
|
For all frontend conventions (CSS variables, UI patterns, modals, localization, icons, bundling), see [contexts/frontend.md](../contexts/frontend.md).
|
|
|
|
## Server Operations
|
|
|
|
For restart procedures, server modes, and demo mode checklist, see [contexts/server-operations.md](../contexts/server-operations.md).
|