# Architecture overview The FSH stack is a codegen pipeline. Declarative Jsonnet configs (Pydantic-validated) compile through a target-agnostic engine into a FastAPI backend, a typed React frontend, an OPA/Rego policy service, and a render sidecar. Generated apps pull shared logic from runtime libraries at load time; infra provisions the AWS/GitHub substrate. See [getting started](../getting_started.md) to stand a project up. ## How it fits together The `codegen` engine holds no framework knowledge: it discovers scopes, orders operations, walks the config tree, and renders Jinja templates, then hands off to **target plugins** (in `codegen-targets`) that emit the `be`/`fe`/`opa`/`render` source. Generated code never re-templates shared logic — the backend calls into `fsh-lib`, the frontend consumes `@fsh/components-library`, the render sidecar consumes `@fsh/codegen-render`. `infra` deploys the result. ``` jsonnet config │ codegen (engine) + codegen-targets (be/fe/opa/render plugins) ▼ generated app: be/ fe/ opa/ render/ │ at runtime: fsh-lib (BE) · @fsh/components-library (FE) · @fsh/codegen-render (render) ▼ deployed by infra (OpenTofu + Terragrunt) → AWS ECS/Aurora/ALB + static FE ``` ## Who owns what The same split holds for every feature; each guide's *How it works* only notes its feature-specific exceptions. **You write:** - SQLAlchemy models (and their migrations). - The jsonnet config (`be/config/*.jsonnet`, `fe/config/fe.jsonnet`) — the declarative source of truth. - Python glue the config references by dotted path: pre/post hooks, `can` guards, action handlers, serializers, comms transports/renderers/resolvers, OPA loaders, auth domain types. - The Rego rules, and the safe-to-edit FE scaffolds — field catalogs, enum displays, action modules, pages. **Codegen generates — never edit:** - The BE routes/handlers, pydantic request/response schemas, serializers, and the OpenAPI spec. - The OPA baseline (RBAC + schemas) and each resource's `_generated/{module}/…`. - The whole TypeScript client — `types`, `sdk`, `queries`, `tables`, action catalogs, the auth bridge — under `fe/src/_generated/`. Two write modes: everything under `_generated/` is overwritten every run; scaffolds (`if_exists=skip`) are written once, then yours. Each guide's code labels — **Generated (do not edit)**, **Scaffolded, safe to edit**, **You write** — mark which is which. ## The repositories | Repo | Kind | Deployed by infra? | What it does | |------|------|--------------------|--------------| | `codegen` | tool | no (published lib/CLI) | Target-agnostic generation engine (pkg `codegen`, fka foundry): config → templates → `BuildStore` → target assembler. | | `codegen-targets` | tool | no (published libs) | uv workspace of target plugins under `packages/`: `codegen-be(-root)`, `codegen-fe(-root)`, `codegen-opa`, `codegen-render-root`. | | `codegen-database` | tool | no (published lib/CLI) | Dimension configs → SQLAlchemy models + Alembic migrations (pkg `codegen_database`, fka pgcraft). | | `python-lib` | runtime lib | no (published to CodeArtifact) | Publishes `fsh-lib` (fka ingot): spec-invariant BE runtime (auth, db, queue, comms, telemetry, reports, opa, RBAC) the `be` templates emit into. | | `components-library` | design system | no (published to CodeArtifact) | `@fsh/components-library` React design system + `@fsh/codegen-render` render library/Hono runtime. | | `codegen-example-app` | generated app | **yes** — `live/internal/example` | Kitchen-sink reference app (be/opa/render ECS + static FE); round-trip validation harness. | | `sales-pipeline` | generated app | **yes** — `live/internal/sales-pipeline` | Deployed sales-domain app: FastAPI + pgqueuer worker (`app.queue.main:main`), all four sides. | | `codegen-template-app` | generated app | no (source/CI only) | Clone-and-fork starting point; `just bootstrap` scaffolds all four sides. | | `cli` | tool | no (published `fsh-cli`) | `fsh` dev/ops surface: SSO login, `ecs`/`secrets`/`db psql`, CodeArtifact auth bootstrap. | | `just-package-manager` | tool | no (published `just-pm`) | Package manager for `just`: vendors shared modules, pins `just.lock`. | | `just-packages` | tool | no (source/CI only) | Shared `just` recipe modules (check/gen/dev/build/db/queue/deps) vendored via `just-pm`. | | `guides` | tool (docs) | yes — `live/docs` (`pages-guides`) | This Sphinx/MyST docs hub; cross-cutting stack concepts. | | `renovate` | infra service | yes — scheduled runner | Self-hosted Renovate config + cron; opens dependency-bump PRs org-wide. | | `infra` | infra | self | OpenTofu + Terragrunt IaC; the control plane for everything below. | - **`codegen`** — the engine; depends only on generic tooling (`typer`, `pydantic`, `jsonnet`, `jinja2`). Every target repo depends on it via the `codegen.targets` entry-point group. - **`codegen-targets`** — the six plugins holding all framework knowledge (FastAPI/SQLAlchemy, openapi-ts + react-query, Rego RBAC, render service, `*-root` bootstraps). - **`python-lib` / `fsh-lib`** — the BE "libc": byte-identical across generated apps; its public signatures are an ABI version-coupled to the `be` templates. - **`components-library`** — the FE analog: design system plus the render library whose openapi-ts plugin turns the BE `render-contract.openapi.json` into per-template types. - **`infra`** — Terragrunt + OpenTofu; deploy target and control plane for all siblings (it even declares the GitHub repos themselves). ## What infra tracks `infra` is a Terragrunt + OpenTofu (Terragrunt Stacks) monorepo. Each environment is its own vended AWS account under a `management` account that owns the AWS Org. It enumerates every org repo in `live/source-code` (teams, branch protection, CI deploy keys), wires per-repo CodeArtifact publish/read roles in `live/package-registry`, deploys `codegen-example-app` and `sales-pipeline` as full per-tier stacks (VPC/Aurora/ECS/ALB/ECR/S3) under `live/internal`, and publishes Cloudflare Pages docs sites via `live/docs`. See [infrastructure](../infra.md) for detail.