系统架构
Canopy 是一个由四个主要组件构建的 Web 应用程序。本页介绍技术栈、解释设计选择,并介绍可添加以扩展平台的可选模块。
四组件技术栈
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(前端)
整个用户界面是使用 React 18、MUI 6 和 React Router 7 构建的单页应用程序。Vite 负责构建;所有路由级页面使用 lazy() 导入进行代码分割,因此只加载当前页面的代码。SPA 通过 /api/ 前缀与 FastAPI 后端通信——前端无法直接访问数据库。
关键前端库:AG Grid(库存表格)、Recharts(图表)、bpmn-js(BPMN 编辑)、TipTap(富文本)、@dnd-kit(拖放)、React Flow(架构图)。
FastAPI 后端
后端处理所有业务逻辑、数据访问、权限执行和实时事件。它由一组路由器构成(每个域一个),全部挂载在 /api/v1/ 下。每个路由处理器都是 async 的,使用 SQLAlchemy 的异步会话和 asyncpg 驱动。
身份验证使用 JWT 令牌(HS256,存储在浏览器的 sessionStorage 中)。Bcrypt 处理密码哈希。存储在数据库中的敏感值(SSO 密钥、SMTP 密码)在写入前使用 Fernet 对称加密,读取时解密。
PostgreSQL
所有应用程序数据存储在 PostgreSQL 中。架构由 Alembic 管理;应用程序在每次启动时运行 alembic upgrade head,因此架构迁移在更新时会自动应用。所有表均使用 UUID 主键。
无 Redis、无消息队列、无外部缓存。实时更新通过 Server-Sent Events(SSE)在直接来自后端的长轮询 HTTP 连接上传输。
边缘 Nginx
一个轻量级 Nginx 容器位于 React 和 FastAPI 容器之前。它提供编译后的 React SPA、将 /api/* 代理到后端(使用 SSE 适当的标头)、在 /drawio/* 处提供自托管的 DrawIO,并应用安全标头(CSP、HSTS、X-Frame-Options 等)。在生产环境中,这是唯一暴露给网络的 容器。
可选模块
Ollama(AI 建议)
向 Docker Compose 添加 --profile ai 可在主技术栈旁启动捆绑的 Ollama 容器。后端的 AI 建议流水线调用 Ollama HTTP API,使用本地运行的 LLM 生成卡片描述。模型完全在您的基础设施内运行。
您也可以通过设置 AI_PROVIDER_URL 将 Canopy 指向任何兼容 Ollama 的外部提供商(OpenAI、通过代理的 Anthropic 等)。
MCP 服务器
添加 --profile mcp 可启动 Model Context Protocol 服务器。这将 Canopy 的数据以一组工具的形式暴露给 AI 助手(Claude Desktop、VS Code Copilot 等)——默认为只读查询,可选的写入工具受每次调用大小限制和确认流程保护。
MCP 服务器通过委托给 Canopy SSO 提供商的 OAuth 2.1 进行身份验证,因此用户通过 MCP 工具看到的权限与在 Web 界面中相同。
数据流:保存一张卡片
为了使架构更加具体,以下是用户保存卡片时发生的事情:
- React 使用更新 后的有效载荷调用
PATCH /api/v1/cards/{id} - Nginx 将请求代理到 FastAPI 后端
- 路由处理器验证 JWT、检查用户的
inventory.edit权限,并使用 Pydantic 架构验证请求体 - SQLAlchemy 将更新后的行写入 PostgreSQL
- 计算引擎运行此卡片类型的所有活动公式
- 根据字段权重重新计算数据质量评分
- 一个事件被发布到内存 SSE 总线
- 任何连接的浏览器接收该事件并实时更新界面
端口与网络
| 服务 | 内部端口 | 主机暴露 |
|---|---|---|
| Nginx(边缘) | 80 | HOST_PORT(默认 8920) |
| FastAPI | 8000 | 否——仅内部 |
| React(仅开发) | 5173 | 开发中是,生产中通过 Nginx 提供 |
| PostgreSQL | 5432 | 否——仅内部 |
| Ollama(可选) | 11434 | 否——仅内部 |
| MCP 服务器(可选) | 8001 | 通过 Nginx /mcp/ 前缀 |