reorg documentation

This commit is contained in:
Davide Scaini
2026-04-08 19:37:33 +02:00
parent f76cc0ce7e
commit 2007f53580
10 changed files with 1065 additions and 456 deletions
+208
View File
@@ -0,0 +1,208 @@
# API reference
`bincio serve` exposes a JSON API on `/api/*`. In production, nginx proxies these routes from the public domain. In local development, Vite proxies them from `astro dev`.
All request and response bodies are `application/json`. Authentication uses an httpOnly session cookie (`bincio_session`).
---
## Authentication
### `GET /api/me`
Returns the currently authenticated user, or 404 if not logged in.
**Response 200**
```json
{
"handle": "dave",
"display_name": "Dave",
"is_admin": true
}
```
**Response 404** — not authenticated
---
### `POST /api/auth/login`
Rate-limited: 10 attempts per 15 minutes per IP.
**Request**
```json
{ "handle": "dave", "password": "your-password" }
```
**Response 200** — sets `bincio_session` cookie (httpOnly, SameSite=Lax, 30-day max-age)
```json
{ "ok": true, "handle": "dave", "display_name": "Dave" }
```
**Response 401** — invalid credentials
**Response 429** — rate limit exceeded
---
### `POST /api/auth/logout`
Deletes the session from the database and clears the cookie.
**Response 200**
```json
{ "ok": true }
```
---
## Registration
### `POST /api/register`
Creates a new user account using a valid invite code.
**Request**
```json
{
"code": "ABCD1234",
"handle": "alice",
"password": "my-password",
"display_name": "Alice"
}
```
Handle rules: lowercase letters, numbers, `_`, `-`; 130 characters.
Password: minimum 8 characters.
**Response 200** — sets session cookie, logs in immediately
```json
{ "ok": true, "handle": "alice" }
```
**Response 400** — invalid handle, password too short, or invalid/used invite code
**Response 409** — handle already taken
---
## Invites
All invite endpoints require authentication.
### `GET /api/invites`
Lists invite codes created by the current user.
**Response 200**
```json
[
{
"code": "ABCD1234",
"used": false,
"used_by": null,
"created_at": "2026-04-01T10:00:00Z",
"used_at": null
}
]
```
---
### `POST /api/invites`
Generates a new invite code for the current user. Regular users are limited to 3 invites; admins are unlimited.
**Response 200**
```json
{ "ok": true, "code": "EFGH5678" }
```
**Response 400** — invite limit reached
---
## Admin
### `GET /api/admin/users`
Lists all users. Admin only.
**Response 200**
```json
[
{
"handle": "dave",
"display_name": "Dave",
"is_admin": true,
"created_at": "2026-03-01T00:00:00Z"
}
]
```
**Response 403** — not an admin
---
## Write API
All write endpoints require authentication. Users can only read/write their own activities.
### `GET /api/activity/{activity_id}`
Returns the full activity JSON for an activity owned by the current user.
**Response 200** — BAS activity detail object
**Response 404** — activity not found or not owned by user
---
### `POST /api/activity/{activity_id}`
Writes a sidecar edit for an activity. Triggers an incremental shard rebuild if `--site-dir` was passed to `bincio serve`.
**Request**
```json
{
"title": "Epic climb",
"description": "Rode with friends.",
"sport": "cycling",
"private": false,
"highlight": false,
"gear": "Trek Domane"
}
```
All fields are optional. Only provided fields are written to the sidecar.
**Response 200**
```json
{ "ok": true }
```
---
### `POST /api/strava/sync`
Triggers a Strava sync for the current user's data directory. Uses the stored OAuth token in `{handle}/strava_token.json`.
**Response 200**
```json
{ "new_count": 3, "error_count": 0 }
```
---
## Error format
All errors follow FastAPI's default format:
```json
{ "detail": "Invalid credentials" }
```
---
## Notes
- The session cookie is `SameSite=Lax`. The server sets `secure=False` because TLS termination is handled by nginx/caddy. If you serve `bincio serve` directly on HTTPS (not recommended), set `secure=True` in `server.py`.
- There is no CSRF protection — the API relies on the same-origin constraint enforced by `SameSite=Lax` cookies.
- The CORS policy allows `localhost:*` origins for local development only. Cross-origin requests from production domains are blocked — all traffic must go through the nginx proxy.
+160
View File
@@ -0,0 +1,160 @@
# CLI reference
All commands are run via `uv run bincio <command>` from the project root.
---
## bincio extract
Extract GPX/FIT/TCX files into a BAS data store.
```bash
uv run bincio extract [OPTIONS]
```
| Option | Default | Description |
|---|---|---|
| `--config PATH` | `extract_config.yaml` | Path to config file |
| `--input DIR` | from config | Input directory (scanned recursively) |
| `--output DIR` | from config | Output BAS data store directory |
| `--file PATH` | — | Extract a single file, print JSON to stdout |
| `--since DATE` | — | Only process files newer than this date (YYYY-MM-DD) |
| `--dev N` | — | Dev mode: sample N files evenly, output to `/tmp/bincio_dev/` |
Extraction is incremental by default — unchanged files (same hash) are skipped. To force a full re-extract: `rm -rf <output_dir>`.
Supported formats: GPX, FIT, TCX — all with optional `.gz` compression.
---
## bincio render
Merge sidecar edits and build (or serve) the Astro site.
```bash
uv run bincio render [OPTIONS]
```
| Option | Default | Description |
|---|---|---|
| `--data-dir DIR` | auto-detected | BAS data store |
| `--site-dir DIR` | `./site` | Astro project directory |
| `--out DIR` | `site/dist` | Build output directory |
| `--serve` | false | Start dev server instead of building |
| `--deploy TARGET` | — | Deploy after build. Currently: `github` |
| `--handle HANDLE` | — | (Multi-user) Re-merge one user's shard only, then rewrite root manifest |
`bincio render` always:
1. Runs `merge_all()` — applies sidecar edits, produces `_merged/`
2. (Multi-user) Rewrites the root `index.json` shard manifest
3. Symlinks `site/public/data` → data directory
4. Runs `astro build` (or `astro dev` with `--serve`)
Data directory auto-detection order:
1. `--data-dir` flag
2. `output.dir` in `extract_config.yaml` (if found in cwd)
3. `./site/public/data` (symlink)
4. `../bincio_data`
---
## bincio edit
Start the local single-user edit server. For personal use only — no authentication.
```bash
uv sync --extra edit # install dependencies (one-time)
uv run bincio edit [OPTIONS]
```
| Option | Default | Description |
|---|---|---|
| `--data-dir DIR` | auto-detected | BAS data store |
| `--host HOST` | `127.0.0.1` | Bind address |
| `--port PORT` | `4041` | Bind port |
| `--strava-client-id ID` | from config | Strava OAuth client ID |
| `--strava-client-secret SECRET` | from config | Strava OAuth client secret |
Set `PUBLIC_EDIT_URL=http://localhost:4041` in `site/.env` to enable the Edit button and Upload ↑ button in the site.
Credentials resolution: `--strava-client-*` flags → `STRAVA_CLIENT_ID/SECRET` env vars → `import.strava.*` in `extract_config.yaml`.
---
## bincio init
Bootstrap a fresh multi-user instance. Run once per VPS.
```bash
uv sync --extra serve # install dependencies (one-time)
uv run bincio init [OPTIONS]
```
| Option | Required | Description |
|---|---|---|
| `--data-dir DIR` | yes | BAS data directory to initialise |
| `--handle HANDLE` | yes | Admin user handle (lowercase, URL-safe) |
| `--password PASSWORD` | yes | Admin password (prompted if omitted) |
| `--display-name NAME` | no | Admin display name (defaults to handle) |
| `--name NAME` | no | Instance name shown in the feed |
Creates:
- `instance.db` — SQLite database with users/sessions/invites tables
- `{handle}/` — admin user data directory and subdirectories
- `index.json` — root shard manifest with `"private": true`
- Prints a first invite code to stdout
Idempotent — safe to re-run. Skips steps already completed.
---
## bincio serve
Start the multi-user application server (VPS mode).
```bash
uv run bincio serve [OPTIONS]
```
| Option | Default | Description |
|---|---|---|
| `--data-dir DIR` | required | BAS data directory (must contain `instance.db`) |
| `--site-dir DIR` | — | Astro site dir — enables post-write incremental rebuilds |
| `--host HOST` | `127.0.0.1` | Bind address (keep on localhost; nginx proxies from outside) |
| `--port PORT` | `4041` | Bind port |
Requires `bincio init` to have been run first. Handles auth, user management, and write operations. nginx is responsible for serving static files and proxying `/api/*` to this server.
See [multi-user deployment](../deployment/multi-user.md) for nginx configuration.
---
## bincio import strava
Import activities directly from the Strava API.
```bash
uv sync --extra strava
uv run bincio import strava [OPTIONS]
```
| Option | Default | Description |
|---|---|---|
| `--output DIR` | from config | BAS data store output directory |
| `--since DATE` | last sync | Only import activities after this date |
| `--reauth` | false | Force a new OAuth flow even if a token exists |
| `--dev N` | — | Dev mode: import N most recent activities to `/tmp/bincio_dev/` |
Credentials: set `import.strava.client_id` and `import.strava.client_secret` in `extract_config.yaml`. The Authorization Callback Domain in the Strava app settings must be `localhost`.
Tokens are stored in `<data_dir>/strava_token.json` and auto-refreshed.
---
## Global flags
```bash
uv run bincio --version # print version
uv run bincio --help # list commands
uv run bincio <cmd> --help # command-specific help
```