# Phase 1 — FastAPI wrapper + job model Wrap the Phase 0 CAD modules in a web API with async job processing and a SQLite model library. No frontend yet (Phase 2) — validated with `curl`. ## Architecture ``` backend/app/ config.py paths (SKILL_SRC, DATA_DIR, DB) — all env-overridable db.py SQLite engine + init (SQLModel) models.py tables: Model, Job, BomRow, QueryLog skill_bridge.py puts skill.src on sys.path so `modules.*` import works processing.py pipeline orchestration over the CAD modules worker.py ThreadPoolExecutor — runs jobs, persists stage/status/results main.py FastAPI routes ``` - **Backend is Python/FastAPI**, not Jason's usual Node/Express — the CAD core is Python-native (decided in the roadmap). - **ORM is SQLModel**, not Prisma — Prisma is JS-first; SQLModel is the FastAPI-native SQLAlchemy/Pydantic ORM. DB stays SQLite, single file under the data volume. - **Jobs run in a thread pool** (`MAX_WORKERS=1` by default) so heavy, CPU-bound CAD work doesn't block the event loop. Status/stage are written to SQLite as the job progresses, so polling `GET /api/jobs/{id}` shows live stages (loading → bom → thumbnails → diagram → collect → done). ## Endpoints | Method | Path | Purpose | |--------|------|---------| | GET | `/api/health` | liveness | | POST | `/api/upload` | multipart STEP upload (+ `thumbnails`/`bom`/`diagram`/`translate`/`diagram_mode` form flags) → creates model + job | | GET | `/api/jobs/{id}` | status, stage, error, artifacts | | GET | `/api/models` | list models | | GET | `/api/models/{id}` | model metadata + BOM rows + artifacts | | GET | `/api/models/{id}/artifacts/{name}` | download a generated file | | POST | `/api/models/{id}/query` | run a geometry query (`{"query": "..."}`) | Interactive docs at `/docs`. ## Run (dev) ```bash ./build.sh # only when requirements.txt changed docker compose up # http://localhost:8000 (source mounted, --reload) ./api-test.sh # end-to-end: upload → poll → detail → download → query ``` `docker-compose.yml` mounts `backend/` and `skill.src/` into the image, so code edits hot-reload without a rebuild. Data (uploads, artifacts, SQLite) lives in the `step_parser_data` volume (mounted at `/data`). ## Also in this phase - **OCC → OCP port** in `external_diagram.py` active-area detection: the kernel ships as cadquery's `OCP`, not pythonocc `OCC.Core`. Now the screen-aperture dimension can actually be detected instead of no-opping with a warning. ## Deferred to later phases - Frontend (Phase 2). - Model loads are repeated per query (no in-memory cache) — fine for MVP; add an LRU of loaded kernels if query latency matters. - Auth — none yet; LAN-only. Add before it leaves the network (Phase 4). - Swap Background- thread pool for a real queue (RQ/Celery) only if concurrency demands it.