Phase 1: FastAPI backend with async job model

- backend/app: FastAPI API wrapping the CAD skill modules
  - upload -> job -> poll -> model / BOM / artifacts -> geometry query
  - SQLite via SQLModel (Model, Job, BomRow, QueryLog)
  - ThreadPoolExecutor worker, serialized, with live stage updates
- docker-compose.yml: dev server (mounts source, --reload) on :8000
- api-test.sh: end-to-end live validation script
- requirements.txt: add fastapi, uvicorn, python-multipart, sqlmodel
- external_diagram.py: port active-area detection OCC.Core -> OCP
- .gitignore, PHASE1.md

Validated live: MR16 round-trip passes (28 BOM rows, 12 artifacts,
bounding-box query, xlsx download; active-area detection working).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Jason Stedwell
2026-06-17 16:38:26 -05:00
parent c1abe36822
commit b3c3e2a3b2
15 changed files with 701 additions and 5 deletions
+22
View File
@@ -0,0 +1,22 @@
"""Runtime configuration. All paths overridable via environment variables so the
same image runs locally (repo root) and on Unraid (/data volume)."""
import os
from pathlib import Path
# Repo root = two levels up from backend/app/config.py
ROOT = Path(__file__).resolve().parents[2]
# The CAD skill source (loader, bom, renderer, query_engine, external_diagram, ...)
SKILL_SRC = Path(os.environ.get("SKILL_SRC", ROOT / "skill.src"))
# Where uploads, per-model output dirs, and the SQLite DB live.
DATA_DIR = Path(os.environ.get("DATA_DIR", ROOT / "_data"))
DB_PATH = Path(os.environ.get("DB_PATH", DATA_DIR / "step_parser.db"))
# CAD jobs are heavy and largely CPU-bound — serialize by default (one at a time).
MAX_WORKERS = int(os.environ.get("MAX_WORKERS", "1"))
# Accepted upload extensions.
ALLOWED_SUFFIXES = {".step", ".stp"}
MODELS_DIR = DATA_DIR / "models"