Skip to content

Architecture Overview.md

Kelsey Smuczynski edited this page Mar 24, 2026 · 1 revision

Architecture Overview

High-Level Runtime

OcotilloAPI is assembled in this order:

  1. main.py imports create_api_app()
  2. core.factory.initialize_runtime() loads .env and optionally initializes Sentry
  3. core.app.create_base_app() creates the FastAPI app and request-timing middleware
  4. core.initializers.register_api_routes() mounts the REST routers
  5. core.pygeoapi.mount_pygeoapi() mounts the OGC API
  6. Session, CORS, Apitally, and lazy admin middleware are configured

Key Components

Layer Location Role
API Layer api/ Resource-specific route handlers; dependency injection for auth and DB sessions
Database Layer db/ SQLAlchemy models; source of truth for schema
Schema Layer schemas/ Pydantic models for request/response validation and serialization
Service Layer services/ Shared business logic, CRUD helpers, and geospatial processing
OGC API /ogcapi pygeoapi mounted for standard geospatial web services
Admin UI /admin Starlette Admin, lazily initialized, Authentik-backed OIDC login
CLI oco Typer CLI for operational and transfer tasks
Transfer Pipeline transfers/ Legacy NM_Aquifer migration tooling

Request Surfaces

Surface Path
REST API resource routers under api/
OGC API /ogcapi (default) via pygeoapi
Admin UI /admin (lazy, session-backed)
Public OpenAPI filtered to routes marked public_route
Authenticated OpenAPI /openapi-auth.json
Authenticated Swagger /docs-auth

Middleware and Lifecycle

  • Startup lifespan seeds development data via transfers.seed.seed_all() when MODE=development
  • Request timing middleware logs cold-start and warm-request timing details
  • CORS is fully open: allow_origins=["*"], allow_methods=["*"], allow_headers=["*"]
  • Session middleware is only installed when SESSION_SECRET_KEY is present
  • Admin initialization is deferred until the first /admin request

Database Layer

  • SQLAlchemy 2.x ORM with both sync (pg8000) and async (asyncpg) engines
  • Cloud SQL mode uses the Cloud SQL Python Connector and can use IAM auth
  • Pool sizing driven by DB_POOL_SIZE and DB_MAX_OVERFLOW

Spatial Stack

  • PostgreSQL + PostGIS with GeoAlchemy2 integration
  • Primary SRID: 4326 (WGS84); geometry stored as Geometry(POINT, 4326)
  • Common spatial functions: ST_Distance, ST_Within, ST_GeomFromText
  • UTM-to-WGS84 transformations occur in import and migration flows

Search and Derived Data

  • Full-text search via PostgreSQL + sqlalchemy-searchable
  • Search vectors and triggers maintained via db.initialization.sync_search_vector_triggers
  • pygeoapi depends on a mix of tables, views, and materialized views (e.g. ogc_* resources)

Admin Architecture

  • Starlette Admin with SQLAlchemy integration
  • Authentik-backed OIDC login; session storage holds the access token
  • Admin views cover both core tables and many NMA_* legacy tables

Design Observations

  • The codebase treats migration tooling and operational CLI flows as first-class parts of the product, not supporting scripts.
  • README.md has drifted from the live runtime in several places — the code and this wiki are the safer source of truth for entrypoints and environment requirements.

Clone this wiki locally