Skip to content

App Components

What ships in every standard app, and how the pieces relate. This is the blueprint's component model — templates/app/ is a runnable instance of it.


🗂️ Component model

flowchart LR
    subgraph EDGE["interfaces/ — HTTP edge"]
        OAS["openapi.yaml"]
        RU["resource routes"]
        JU["job routes"]
    end

    subgraph CORE["domain/ — business core"]
        RI["<resource> · models · ports · services"]
        JI["<job/worker> · models · ports · services"]
        PI["pipelines/<family>"]
    end

    subgraph INFRA["infra/ — adapters"]
        DB[("MongoDB repos")]
        CA["redis cache"]
        ST["stores · progress bus"]
        LL["llm clients"]
    end

    W["worker.py"]
    CR["init.py — composition root"]

    OAS --> RU
    OAS --> JU
    RU --> RI
    JU --> JI
    JI --> PI
    PI --> DB
    PI --> LL
    RI --> CA
    RI --> DB
    JI --> ST
    W --> JI
    W --> PI

    CR === RU
    CR === JU
    CR === RI
    CR === JI
    CR === PI
    CR === W
    CR === DB
    CR === CA
    CR === ST

Legend — solid arrows are direct calls; thick links are wires created by the composition root. Every component is injected, never self-constructed.


📦 Component roles

1. interfaces/ — the edge

Thin handlers bound to openapi.yaml operationIds. They parse the request, call a service, and shape the response. No business rules, no I/O.

  • interfaces/openapi.py re-exports every route module so the OpenAPI-first app can resolve handlers.
  • Routes may mount the cache decorator on read endpoints.

2. domain/ — the core

Pure models, ports (abstract contracts), and services (use cases). No framework imports, no drivers.

  • <aggregate>/models.py — dataclasses, enums, document shapes.
  • <aggregate>/ports/db.py — repo contract; <aggregate>/ports/service.py — service contract.
  • Services compose ports and enforce the business rules; the composition root injects the implementations.

3. infra/ — the adapters

Concrete implementations of the domain ports plus cross-cutting infrastructure:

  • db/ — mongo-ops repositories and the connection lifecycle.
  • adapters/ — cache store, progress bus, storages, fetchers (library-backed).
  • Anything else the domain needs, implemented against its ports.

4. pipelines/ — data-driven families (optional)

Extraction and enrichment families, each a deterministic step chain (abc.py / impl.py / pipeline.yaml / resources/). Roots are registered in the pattern registry and driven either by a worker job or a CLI.

5. worker.py — the job worker (optional)

A separate process that polls durable job collections, runs pipeline roots, and publishes progress to the progress bus. It shares the same composition root as the API.

6. init.py — the composition root

The only place anything is constructed: leaf repositories → dependent repositories → services → adapters. Exposes get_svc overloads and starts / stops resources on the app lifespan.


🔗 How the request flows

sequenceDiagram
    participant C as Client
    participant R as route (interfaces)
    participant S as service (domain)
    participant P as repo (infra)
    participant DB as MongoDB

    C->>R: POST /items (operationId)
    R->>S: svc.create(payload)
    S->>P: repo.insert(doc)
    P->>DB: insert
    DB-->>P: ack
    P-->>S: doc
    S-->>R: result
    R-->>C: 200 JSON