2026-05-16 11:01:20 +05:30
|
|
|
# Gateway (FastAPI)
|
2026-05-15 10:39:16 +05:30
|
|
|
|
2026-05-16 11:01:20 +05:30
|
|
|
Phase 0 task **"FastAPI service scaffolding"** (Dev 1). Skeleton only — every
|
|
|
|
|
PDF-touching route returns **501** until the pybind11 engine module in
|
|
|
|
|
[`bindings/python/`](../bindings/python/) lands at Gate G0b.
|
2026-05-15 10:39:16 +05:30
|
|
|
|
2026-05-16 11:01:20 +05:30
|
|
|
What the gateway eventually does (see `docs/phase0.md` and engine blueprint §8):
|
2026-05-15 10:39:16 +05:30
|
|
|
|
|
|
|
|
- Auth, metadata, storage (S3 / MinIO), async job queue.
|
|
|
|
|
- Bridges to the C++ engine via **pybind11** (`bindings/python/`).
|
2026-05-16 11:01:20 +05:30
|
|
|
- Hosts the API the React + TypeScript viewer in [`frontend/`](../frontend/) calls.
|
2026-05-15 10:39:16 +05:30
|
|
|
|
2026-05-16 11:01:20 +05:30
|
|
|
## Current state
|
2026-05-15 10:39:16 +05:30
|
|
|
|
|
|
|
|
```
|
|
|
|
|
gateway/
|
2026-05-16 11:01:20 +05:30
|
|
|
pyproject.toml # pinned FastAPI/uvicorn/pydantic + ruff/pytest
|
2026-05-15 10:39:16 +05:30
|
|
|
app/
|
2026-05-16 11:01:20 +05:30
|
|
|
__init__.py # exports __version__
|
|
|
|
|
main.py # FastAPI app factory
|
|
|
|
|
config.py # pydantic-settings (PDFENGINE_* env vars)
|
|
|
|
|
routers/ # PEP 420 namespace pkg — no __init__.py needed
|
|
|
|
|
health.py # GET /health → 200
|
|
|
|
|
documents.py # CRUD → 501 (placeholder)
|
|
|
|
|
render.py # render/text → 501 (placeholder)
|
|
|
|
|
edits.py # apply edits → 501 (placeholder)
|
|
|
|
|
services/ # PEP 420 namespace pkg
|
|
|
|
|
engine.py # lazy pybind11 import wrapper (engine absent in Phase 0)
|
2026-05-15 10:39:16 +05:30
|
|
|
tests/
|
2026-05-16 11:01:20 +05:30
|
|
|
conftest.py
|
|
|
|
|
test_health.py # /health works without the engine
|
|
|
|
|
test_placeholders.py # every PDF route 501s until G0b lands
|
2026-05-15 10:39:16 +05:30
|
|
|
```
|
2026-05-16 11:01:20 +05:30
|
|
|
|
|
|
|
|
The gateway depends on **no C++** today — the `engine` service module probes
|
|
|
|
|
for `import pdfengine` lazily and reports `engine_available: false` via
|
|
|
|
|
`/health` while the pybind11 module does not exist.
|
|
|
|
|
|
|
|
|
|
## Local development
|
|
|
|
|
|
|
|
|
|
Requires Python 3.11+ (3.12 works). Build dirs are git-ignored.
|
|
|
|
|
|
|
|
|
|
```powershell
|
|
|
|
|
cd gateway
|
|
|
|
|
python -m venv .venv
|
|
|
|
|
.venv\Scripts\Activate.ps1
|
|
|
|
|
pip install -e ".[dev]"
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
# Linux/macOS
|
|
|
|
|
cd gateway
|
|
|
|
|
python -m venv .venv
|
|
|
|
|
source .venv/bin/activate
|
|
|
|
|
pip install -e ".[dev]"
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
Run the service:
|
|
|
|
|
|
2026-05-27 12:25:00 +05:30
|
|
|
Using the startup script (Windows):
|
|
|
|
|
```powershell
|
2026-07-23 17:02:45 +05:30
|
|
|
# Default port (8765)
|
2026-05-27 12:25:00 +05:30
|
|
|
powershell -File scripts/start_gateway.ps1
|
|
|
|
|
|
|
|
|
|
# Custom port (e.g. 8080)
|
|
|
|
|
powershell -File scripts/start_gateway.ps1 -Port 8080
|
2026-05-16 11:01:20 +05:30
|
|
|
```
|
|
|
|
|
|
2026-05-27 12:25:00 +05:30
|
|
|
Or run directly via uvicorn (cross-platform):
|
|
|
|
|
```sh
|
2026-07-23 17:02:45 +05:30
|
|
|
# Default port (8765)
|
2026-05-27 12:25:00 +05:30
|
|
|
uvicorn app.main:app --reload
|
|
|
|
|
|
|
|
|
|
# Custom port (e.g. 8080)
|
|
|
|
|
uvicorn app.main:app --reload --port 8080
|
|
|
|
|
```
|
|
|
|
|
# → http://127.0.0.1:<port>/health
|
|
|
|
|
# → http://127.0.0.1:<port>/docs (OpenAPI UI)
|
|
|
|
|
|
|
|
|
|
|
2026-05-16 11:01:20 +05:30
|
|
|
Lint, format, and test (the exact commands CI runs):
|
|
|
|
|
|
|
|
|
|
```sh
|
|
|
|
|
ruff check .
|
|
|
|
|
ruff format --check .
|
|
|
|
|
pytest
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Configuration
|
|
|
|
|
|
|
|
|
|
Environment variables are read by `app/config.py` with the prefix
|
|
|
|
|
`PDFENGINE_`:
|
|
|
|
|
|
|
|
|
|
| Var | Default | Meaning |
|
|
|
|
|
|------------------------------|---------|--------------------------------------------------|
|
|
|
|
|
| `PDFENGINE_ENVIRONMENT` | `dev` | `dev` / `staging` / `prod` — echoed in `/health` |
|
|
|
|
|
| `PDFENGINE_ENGINE_AVAILABLE` | `false` | Forces the engine-availability flag for testing |
|
|
|
|
|
|
2026-05-27 12:25:00 +05:30
|
|
|
Additionally, the gateway startup scripts and frontend configuration support:
|
|
|
|
|
|
|
|
|
|
| Var | Default | Meaning |
|
|
|
|
|
|--------------------|-------------------------|--------------------------------------------------|
|
2026-07-23 17:02:45 +05:30
|
|
|
| `PORT` | `8765` | Gateway listening port (used by `start_gateway.ps1`). |
|
|
|
|
|
| `VITE_GATEWAY_URL` | `http://127.0.0.1:8765` | URL of the gateway API (used by the frontend). |
|
2026-05-27 12:25:00 +05:30
|
|
|
|
2026-05-16 11:01:20 +05:30
|
|
|
A `.env` file in `gateway/` is auto-loaded if present (it is git-ignored
|
|
|
|
|
via the repo-wide `.venv/` and Python rules — add `.env` to your local
|
|
|
|
|
ignores if you keep secrets in it).
|
|
|
|
|
|
|
|
|
|
## CI
|
|
|
|
|
|
|
|
|
|
The `gateway` job in [`.github/workflows/ci.yml`](../.github/workflows/ci.yml)
|
|
|
|
|
runs on **ubuntu-latest only** — the gateway is pure Python with no
|
|
|
|
|
OS-specific surface, so a cross-platform matrix would burn runner minutes
|
|
|
|
|
catching nothing. The engine `build` matrix still covers Linux + macOS +
|
|
|
|
|
Windows; once the pybind11 wheel is built per-platform there, the gateway
|
|
|
|
|
job will install it and run integration tests against the real engine.
|
|
|
|
|
|
|
|
|
|
## What is **not** here yet (and why)
|
|
|
|
|
|
|
|
|
|
- **Real document/render/edit routes** — blocked on Gate G0b
|
|
|
|
|
(`PdfDocument` / `PdfPage` interface contracts) and the pybind11 module.
|
|
|
|
|
Stubbing them earlier would just lock us into a bad API.
|
|
|
|
|
- **Auth, storage, job queue** — Phase 1 / 2 work. Leaving these out of
|
|
|
|
|
Phase 0 keeps the surface area small enough to keep CI green while the
|
|
|
|
|
engine is still being scaffolded.
|
|
|
|
|
- **Containerization (Dockerfile, compose)** — added when there is
|
|
|
|
|
something non-trivial to package. A FastAPI app with a `/health` route
|
|
|
|
|
does not need an image yet.
|