# CLAUDE.md — face-lock ## Project Summary face-lock is a standalone FastAPI microservice for image subject detection and square cropping. It accepts an uploaded image, finds the primary subject using OpenCV-based detectors, expands the crop with a configurable buffer, and returns either JSON with preview data URLs or a binary JPEG crop. This repo is intentionally independent from the BetterNews API/frontend/worker stack. Treat it as a fifth repo in the workspace with its own runtime, Docker image, and CI. --- ## API Surface | Method | Path | Description | | ------ | ------------------ | ----------- | | GET | `/health` | Health and runtime config summary. | | GET | `/` | Small test UI when enabled. | | POST | `/api/focus` | Returns JSON metadata plus crop and annotated previews as data URLs. | | POST | `/api/focus/image` | Returns the cropped JPEG directly. | | GET | `/docs` | OpenAPI UI when docs are enabled. | | GET | `/openapi.json` | OpenAPI schema when docs are enabled. | --- ## Configuration Key environment variables: - `ENV` or `FACE_LOCK_ENV` — environment label, defaults to `production`. - `PORT` — HTTP port, defaults to `8000`. - `LOG_LEVEL` — standard Python log level, defaults to `info`. - `FACE_LOCK_DOCS` — enable or disable `/docs` and `/openapi.json`. - `FACE_LOCK_TEST_UI` — enable or disable the browser test UI at `/`. - `FACE_LOCK_MAX_UPLOAD_BYTES` — maximum upload size in bytes. - `FACE_LOCK_ALLOWED_MIME_TYPES` — comma-separated allowlist of image MIME types. - `FACE_LOCK_AUTH_TOKEN` — optional shared secret for header auth. - `FACE_LOCK_AUTH_HEADER` — optional header override, defaults to `X-API-Key`. - `WEB_CONCURRENCY` — worker count for the container entrypoint. - `UVICORN_KEEPALIVE_TIMEOUT` — keepalive timeout for the container entrypoint. Auth supports either the configured header value or `Authorization: Bearer `. --- ## Repo Layout - `app/main.py` — FastAPI app, routes, auth, upload validation, response headers. - `app/config.py` — environment parsing and validation. - `app/models.py` — API enums and response models. - `app/ui.py` — embedded test UI HTML. - `app/vision.py` — OpenCV detection and crop logic. - `tests/` — API and image-processing tests. - `docker/entrypoint.sh` — production container startup command. - `.gitea/workflows/python.yml` — test and image build pipeline. --- ## Working Rules 1. Keep the service stateless. Do not introduce local persistence or writable app directories without explicit need. 2. Preserve the current request contract unless a change is clearly documented in both `README.md` and `docs/README.md`. 3. Validate upload size, detector values, and content type at the API boundary before handing data to OpenCV. 4. Prefer explicit, deterministic failures over silent fallbacks when configuration is invalid. 5. Keep the Docker image non-root and production-friendly. 6. Avoid adding new dependencies unless the standard library, FastAPI, or OpenCV cannot reasonably solve the problem. 7. Update tests whenever request validation, auth, output shape, or detector behavior changes. 8. Keep the test UI optional and disabled by default for production-style environments. --- ## Local Development ```sh python -m pip install -r requirements.txt python -m pytest uvicorn app.main:app --reload --host 0.0.0.0 --port 8000 ``` Docker: ```sh docker compose up --build ``` --- ## Verification Before pushing: ```sh python -m compileall -q app tests python -m pytest docker build -t face-lock:test . ```