diff --git a/README.md b/README.md new file mode 100644 index 0000000..7bc5f6f --- /dev/null +++ b/README.md @@ -0,0 +1,58 @@ +# My Library: Personal Book Collection Tracker + +Flask + React + PostgreSQL. Users catalog their books, track reading progress, keep a reading journal per +book, and search/filter their library. Each user sees only their own data. + +## Run (CoderPad) + +The pad starts Flask (`backend/app.py`, port 5000) and Vite automatically. The schema is created on startup. +Optionally set `PASSWORD_PEPPER` (≥ 32 chars). Without it, a development pepper is generated into +`backend/.pepper` and a warning is logged. + +## Run (local) + +```bash +mise trust && mise install # Python 3.14, Node 24 +docker compose up -d db # postgres:16 on 127.0.0.1:5432 +docker compose exec -T db pg_isready -U postgres # repeat until it reports "accepting connections" +mise exec -- python -m venv .venv && .venv/bin/pip install -r backend/requirements.txt +mise exec -- npm install +.venv/bin/python backend/app.py # API on :5000 +mise exec -- npm run dev # UI; /api is proxied to Flask +``` + +## Test + +```bash +.venv/bin/python -W error -m unittest discover -s backend/tests -t backend -v # real Postgres (books_test); run from repo root +mise exec -- npm test && mise exec -- npm run typecheck +``` + +## Design + +- **Feature slices.** One Flask Blueprint per feature: `auth.py`, `books.py` and `notes.py` each hold their + routes, validation and SQL. `db.py` holds the pool and transactions; `validation.py` holds the shared input rules. +- **Isolation in SQL.** Every query filters on the session's user (`AND user_id = %s`, or joins to `books` + for notes). Another user's book and a missing book return the same 404. +- **Passwords.** Peppered PBKDF2-HMAC-SHA256 (FIPS-approved, stdlib only). See [ADR-0001](docs/adr/0001-password-hashing-pbkdf2.md). +- **Sessions.** Opaque tokens hashed at rest; 30-minute idle and 12-hour absolute expiry; real logout; CSRF + handled by SameSite plus a JSON-only rule. See [ADR-0002](docs/adr/0002-server-side-sessions.md). +- **Data rules in two places.** The API returns specific 400s, and Postgres CHECK and FK constraints + backstop them. +- **Frontend.** React Router (search and filter state lives in the URL), a small auth context, Tailwind. + No state library. + +Full spec: [docs/superpowers/specs/2026-10-02-book-tracker-design.md](docs/superpowers/specs/2026-10-02-book-tracker-design.md) + +## Known trade-offs + +| Not included | Add when | +|---|---| +| Pagination | libraries exceed a few hundred books | +| Trigram/full-text index | ILIKE search slows (thousands of books) | +| Login rate limiting | before production | +| Migrations tool | schema changes after first deploy | +| Pepper rotation | before production key management | + +A request that fails with 4xx rolls back its transaction, including the session idle-window slide, so failed +requests don't extend the 30-minute idle timeout.