Problem
The backend has two patterns for DB access. The contexts/ package owns ~66 query operations, but ~22 endpoints in api/handlers/v1/ still call SQLAlchemy directly (.execute() / .filter()). Same operations are reimplemented in both places, no single source of truth for query logic, and authorization/validation that lives in contexts is bypassed by inline queries.
Goal
All DB access from handlers goes through contexts/. Handlers stay thin: parse input → call context → shape response.
Approach
- Audit handlers under
extralit-server/src/extralit_server/api/handlers/v1/ for direct SQLAlchemy usage. Produce a list (handler → operation).
- For each, either reuse an existing
contexts/<module> function or add one.
- Replace inline queries with the context call.
- Add a CI lint (
ruff custom rule or grep check) that fails when handler files import from sqlalchemy or models/.
Out of scope
Restructuring contexts/ itself — this is purely about routing handlers through the existing layer.
Acceptance criteria
grep -rn "session.execute\|session.scalars" src/extralit_server/api/handlers/v1/ returns nothing.
- Handler files don't import from
sqlalchemy or extralit_server.models directly.
- Existing test suite passes; no new behavior change.
Problem
The backend has two patterns for DB access. The
contexts/package owns ~66 query operations, but ~22 endpoints inapi/handlers/v1/still call SQLAlchemy directly (.execute()/.filter()). Same operations are reimplemented in both places, no single source of truth for query logic, and authorization/validation that lives in contexts is bypassed by inline queries.Goal
All DB access from handlers goes through
contexts/. Handlers stay thin: parse input → call context → shape response.Approach
extralit-server/src/extralit_server/api/handlers/v1/for direct SQLAlchemy usage. Produce a list (handler → operation).contexts/<module>function or add one.ruffcustom rule orgrepcheck) that fails when handler files import fromsqlalchemyormodels/.Out of scope
Restructuring
contexts/itself — this is purely about routing handlers through the existing layer.Acceptance criteria
grep -rn "session.execute\|session.scalars" src/extralit_server/api/handlers/v1/returns nothing.sqlalchemyorextralit_server.modelsdirectly.