Skip to content

Architecture Overview

Sankofa LCA is a modular monolith: a single FastAPI application whose internal structure mirrors the EN 15978 module sequence. This page describes the top-level component layout and the data path from HTTP request to PostgreSQL.

Component diagram

graph TD
    Client["Client\nbrowser · curl · React frontend (Phase 3)"]

    subgraph "FastAPI application — backend/app/"
        Main["main.py\nrouters · lifespan · OpenAPI"]
        Schemas["schemas/\nPydantic v2 — openEPD + proxy_provenance"]
        Domains["domains/\nquantities · lca/* · thermal · energy"]
        Services["services/\nproxy_engine · pedigree · interpolation\nuncertainty · reporting"]
        Models["models/\nSQLAlchemy 2 async ORM"]
    end

    Postgres[("PostgreSQL 16\nasyncpg driver")]

    Client -->|"HTTP / JSON"| Main
    Main -->|"validate in / out"| Schemas
    Main --> Domains
    Main --> Services
    Domains --> Services
    Main --> Models
    Models -->|"async SQLAlchemy"| Postgres

Layer responsibilities

Layer Path Role
Routers backend/app/main.py HTTP surface, dependency injection, OpenAPI spec
Schemas backend/app/schemas/ Pydantic v2 validation of all API payloads; openEPD internal format; proxy_provenance extension
Domain modules backend/app/domains/ EN 15978 calculation logic, one file per module (A1–A3 … D)
Shared services backend/app/services/ Cross-cutting concerns: EPD proxy cascade, pedigree DQI, interpolation, Monte Carlo, reporting
ORM models backend/app/models/ SQLAlchemy 2 async declarative models; all columns typed with naming convention
Database PostgreSQL 16 Persistence; Alembic manages schema migrations

Key design constraints

  • No ORM calls inside domain modules. Domain modules receive typed Pydantic objects and return typed Pydantic objects. Persistence is the router's responsibility.
  • Pydantic v1 / v2 boundary. The openepd library (v 6.34.2) uses Pydantic v1 internally. The boundary is handled by explicit .dict() serialisation before crossing; do not pass openEPD objects directly into Pydantic v2 schemas.
  • Async throughout. All DB access uses AsyncSession; FastAPI endpoints are async def. Synchronous calculation logic in domain modules is acceptable (no I/O).
  • Single LCIA method. EF 3.1 is the only valid lcia_method (decision #1). The LCIAMethodChoice enum enforces this at the schema layer.