feat: upgrade app template server from vet reference

- integer-id persistence: memory (default, zero-dep) + mongo_int repos
  selected by REPO_BACKEND via create_repo factory
- interfaces/_common.py: shared svc/dump/paginate/expand_ref/read_or_404
  helpers; item/job routes rebuilt on them (paginated {total,items} lists,
  PUT replace, 204 deletes, int path ids)
- interfaces/system: /health liveness probe (public)
- openapi.yaml rewritten to 3.1.0 with x- extensions on Item/Job
  (x-resource, x-primary-key, x-display-format, x-list-columns, x-label,
  x-order, x-hidden, x-filterable, x-sortable, x-autocomplete), auth-server
  x-* securityScheme wiring, shared error responses
- config/init/main: REPO_BACKEND knob, load_dotenv before spec build
Verified: 7/7 tests pass; live smoke test (/health ok, 401 without token)
This commit is contained in:
2026-10-19 17:06:47 +05:30
parent ee954431cc
commit e88005d936
19 changed files with 1213 additions and 215 deletions

View File

@@ -3,6 +3,12 @@
FastAPI application bootstrap — uses OpenAPIFirstApp for spec-driven routing.
Handlers are looked up by operationId in interfaces.openapi, so no router tables
are declared here; the lifespan initializes and shuts down app resources.
---
``load_dotenv()`` runs before the app is constructed so ``{AUTH_SERVER}`` in
``openapi.yaml``'s bearer-JWT security scheme resolves from ``.env`` at build
time (openapi_first resolves env placeholders when the spec is loaded).
"""
# ruff: noqa: E402
import logging
@@ -12,8 +18,6 @@ from dotenv import load_dotenv
from openapi_first.app import OpenAPIFirstApp
from starlette.middleware.cors import CORSMiddleware
from init import init, shutdown
load_dotenv()
logging.basicConfig(
@@ -22,6 +26,7 @@ logging.basicConfig(
)
import interfaces.openapi as openapi_routes
from init import init, shutdown
logger = logging.getLogger(__name__)
@@ -47,9 +52,9 @@ async def lifespan(app: OpenAPIFirstApp):
app = OpenAPIFirstApp(
openapi_path="openapi.yaml",
routes_module=openapi_routes,
title="Item API",
title="App Template API",
version="0.1.0",
lifespan=lifespan,
)
app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"])
app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"])