Ir para o conteúdo

System Architecture

Turbo EA is a self-hosted web application built from four main components. This page describes the stack, explains the design choices, and covers the optional modules you can add to extend the platform.

The four-component stack

Browser (React SPA)
       │
       │  /api/*  (HTTP proxy)
       ▼
Edge Nginx  ──────────────────────────►  /drawio/*  (self-hosted DrawIO)
       │
       │  proxy_pass :8000
       ▼
FastAPI Backend (Python 3.12, uvicorn)
  ├── SQLAlchemy 2 (async, asyncpg)
  ├── Alembic migrations
  ├── JWT auth (HS256) + bcrypt
  ├── SSE event stream
  └── Rate limiting (slowapi)
       │
       ▼
PostgreSQL 18

React SPA (frontend)

The entire UI is a single-page application built with React 18, MUI 6, and React Router 7. Vite handles the build; all route-level pages use lazy() imports for code splitting, so only the code for the current page is loaded. The SPA talks exclusively to the FastAPI backend through the /api/ prefix — there is no direct database access from the frontend.

Key frontend libraries: AG Grid (inventory table), Recharts (charts), bpmn-js (BPMN editing), TipTap (rich text), @dnd-kit (drag-and-drop), React Flow (architecture diagrams).

FastAPI backend

The backend handles all business logic, data access, permission enforcement, and real-time events. It is structured as a collection of routers (one per domain) that all mount under /api/v1/. Every route handler is async, using SQLAlchemy's async session with the asyncpg driver.

Authentication uses JWT tokens (HS256, stored in the browser's sessionStorage). Bcrypt handles password hashing. Sensitive values stored in the database (SSO secrets, SMTP passwords) are encrypted with Fernet symmetric encryption before writing and decrypted on read.

PostgreSQL

All application data lives in PostgreSQL. The schema is managed by Alembic; the application runs alembic upgrade head on every startup, so schema migrations are applied automatically on update. Tables use UUID primary keys throughout.

There is no Redis, no message queue, and no external cache. Real-time updates use Server-Sent Events (SSE) over a long-polling HTTP connection directly from the backend.

Edge Nginx

A thin Nginx container sits in front of the React and FastAPI containers. It serves the compiled React SPA, proxies /api/* to the backend (with SSE-appropriate headers), serves the self-hosted DrawIO at /drawio/*, and applies security headers (CSP, HSTS, X-Frame-Options, etc.). In production this is the only container exposed to the network.

Why self-hosted?

Enterprise Architecture models contain highly sensitive data: technology budgets, vendor contracts, strategic initiatives, and organisational hierarchies. Many organisations have compliance or data residency requirements that prevent storing this information in a third-party SaaS. Turbo EA is designed to run entirely within your infrastructure — your data never leaves your network.

Optional modules

Ollama (AI suggestions)

Add --profile ai to Docker Compose to start a bundled Ollama container alongside the main stack. The backend's AI suggestion pipeline calls the Ollama HTTP API to generate card descriptions using a locally-running LLM. The model runs entirely within your infrastructure.

You can also point Turbo EA at any Ollama-compatible external provider (OpenAI, Anthropic via a proxy, etc.) by setting AI_PROVIDER_URL.

MCP server

Add --profile mcp to start the Model Context Protocol server. This exposes Turbo EA's data to AI assistants (Claude Desktop, VS Code Copilot, etc.) as a set of tools — read-only queries by default, with opt-in write tools guarded by per-call size limits and a confirmation flow.

The MCP server authenticates via OAuth 2.1 delegated to the Turbo EA SSO provider, so users see the same permissions through MCP tools as they do in the web UI.

Data flow: a card save

To make the architecture concrete, here is what happens when a user saves a card:

  1. React calls PATCH /api/v1/cards/{id} with the updated payload
  2. Nginx proxies the request to the FastAPI backend
  3. The route handler validates the JWT, checks the user's inventory.edit permission, and validates the request body with a Pydantic schema
  4. SQLAlchemy writes the updated row to PostgreSQL
  5. The calculation engine runs any active formulas for this card type
  6. The data quality score is recomputed from the fields' weights
  7. An event is published to the in-memory SSE bus
  8. Any connected browser receives the event and updates the UI in real time

Ports and networking

Service Internal port Host-exposed
Nginx (edge) 80 HOST_PORT (default 8920)
FastAPI 8000 No — internal only
React (dev only) 5173 Yes in dev, served via Nginx in prod
PostgreSQL 5432 No — internal only
Ollama (optional) 11434 No — internal only
MCP server (optional) 8001 Via Nginx /mcp/ prefix

See also