Systemarchitektur
Canopy ist eine Webanwendung, die aus vier Hauptkomponenten besteht. Diese Seite beschreibt den Stack, erläutert die Designentscheidungen und behandelt die optionalen Module, mit denen Sie die Plattform erweitern können.
Der vierteilige 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)
Die gesamte Benutzeroberfläche ist eine Single-Page-Application, die mit React 18, MUI 6 und React Router 7 erstellt wurde. Vite übernimmt den Build; alle routenbasierten Seiten verwenden lazy()-Importe für Code-Splitting, sodass nur der Code der aktuellen Seite geladen wird. Die SPA kommuniziert ausschließlich über den /api/-Präfix mit dem FastAPI-Backend – es gibt keinen direkten Datenbankzugriff vom Frontend.
Wichtige Frontend-Bibliotheken: AG Grid (Inventartabelle), Recharts (Diagramme), bpmn-js (BPMN-Bearbeitung), TipTap (Rich-Text), @dnd-kit (Drag-and-Drop), React Flow (Architekturdiagramme).
FastAPI-Backend
Das Backend verwaltet die gesamte Geschäftslogik, den Datenzugriff, die Berechtigungsdurchsetzung und Echtzeitereignisse. Es ist als Sammlung von Routern strukturiert (einer pro Fachdomäne), die alle unter /api/v1/ eingehängt sind. Jeder Route-Handler ist async und verwendet SQLAlchemy's asynchrone Session mit dem asyncpg-Treiber.
Die Authentifizierung verwendet JWT-Token (HS256, im sessionStorage des Browsers gespeichert). Bcrypt übernimmt das Passwort-Hashing. Sensible Werte, die in der Datenbank gespeichert werden (SSO-Geheimnisse, SMTP-Passwörter), werden vor dem Schreiben mit symmetrischer Fernet-Verschlüsselung verschlüsselt und beim Lesen entschlüsselt.
PostgreSQL
Alle Anwendungsdaten liegen in PostgreSQL. Das Schema wird von Alembic verwaltet; die Anwendung führt bei jedem Start alembic upgrade head aus, sodass Schema-Migrationen bei Updates automatisch angewendet werden. Tabellen verwenden durchgängig UUID-Primärschlüssel.
Es gibt kein Redis, keine Message Queue und keinen externen Cache. Echtzeit-Updates verwenden Server-Sent Events (SSE) über eine Long-Polling-HTTP-Verbindung direkt vom Backend.
Edge-Nginx
Ein schlanker Nginx-Container sitzt vor den React- und FastAPI-Containern. Er stellt die kompilierte React SPA bereit, leitet /api/* an das Backend weiter (mit SSE-geeigneten Headern), stellt das selbst gehostete DrawIO unter /drawio/* bereit und wendet Sicherheits-Header an (CSP, HSTS, X-Frame-Options usw.). In der Produktion ist dies der einzige Container, der dem Netzwerk ausgesetzt ist.
Optionale Module
Ollama (KI-Vorschläge)
Fügen Sie --profile ai zu Docker Compose hinzu, um einen gebündelten Ollama-Container neben dem Hauptstack zu starten. Die KI-Vorschlagspipeline des Backends ruft die Ollama-HTTP-API auf, um Kartenbeschreibungen mit einem lokal laufenden LLM zu generieren. Das Modell läuft vollständig innerhalb Ihrer Infrastruktur.
Sie können Canopy auch auf einen beliebigen Ollama-kompatiblen externen Anbieter (OpenAI, Anthropic über einen Proxy usw.) verweisen, indem Sie AI_PROVIDER_URL setzen.
MCP-Server
Fügen Sie --profile mcp hinzu, um den Model Context Protocol-Server zu starten. Dieser stellt die Daten von Canopy KI-Assistenten (Claude Desktop, VS Code Copilot usw.) als eine Reihe von Werkzeugen zur Verfügung – standardmäßig schreibgeschützte Abfragen, mit optionalen Schreibwerkzeugen, die durch Größenbeschränkungen pro Aufruf und einen Bestätigungsablauf gesichert sind.
Der MCP-Server authentifiziert sich über OAuth 2.1, delegiert an den Canopy-SSO-Anbieter, sodass Benutzer über MCP-Werkzeuge dieselben Berechtigungen sehen wie in der Web-Benutzeroberfläche.
Datenfluss: Karte speichern
Um die Architektur konkret zu veranschaulichen, hier die Abfolge beim Speichern einer Karte durch einen Benutzer:
- React ruft
PATCH /api/v1/cards/{id}mit dem aktualisierten Payload auf - Nginx leitet die Anfrage an das FastAPI-Backend weiter
- Der Route-Handler validiert das JWT, prüft die
inventory.edit-Berechtigung des Benutzers und validiert den Anfrageinhalt mit einem Pydantic-Schema - SQLAlchemy schreibt die aktualisierte Zeile in PostgreSQL
- Die Berechnungsmaschine führt alle aktiven Formeln für diesen Kartentyp aus
- Der Datenqualitätsscore wird anhand der Feldgewichtungen neu berechnet
- Ein Ereignis wird im In-Memory-SSE-Bus veröffentlicht
- Alle verbundenen Browser empfangen das Ereignis und aktualisieren die Benutzeroberfläche in Echtzeit
Ports und Netzwerk
| Dienst | Interner Port | Host-exponiert |
|---|---|---|
| Nginx (Edge) | 80 | HOST_PORT (Standard 8920) |
| FastAPI | 8000 | Nein – nur intern |
| React (nur Dev) | 5173 | Ja in Dev, via Nginx in Prod |
| PostgreSQL | 5432 | Nein – nur intern |
| Ollama (optional) | 11434 | Nein – nur intern |
| MCP-Server (optional) | 8001 | Via Nginx /mcp/-Präfix |
Siehe auch
- Das Metamodell verstehen – das Datenmodelldesign
- MCP-Integration – Konfiguration des MCP-Servers
- KI-Funktionen – Konfiguration der KI-Vorschlagsfunktion