Arquitetura do Sistema
O Canopy é uma aplicação web construída a partir de quatro componentes principais. Esta página descreve a pilha tecnológica, explica as escolhas de design e aborda os módulos opcionais que pode adicionar para estender a plataforma.
A pilha de quatro componentes
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)
Toda a interface é uma aplicação de página única construída com React 18, MUI 6 e React Router 7. O Vite trata da compilação; todas as páginas ao nível de rota utilizam importações lazy() para divisão de código, pelo que apenas o código da página atual é carregado. A SPA comunica exclusivamente com o backend FastAPI através do prefixo /api/ — não existe acesso direto à base de dados a partir do frontend.
Bibliotecas frontend principais: AG Grid (tabela de inventário), Recharts (gráficos), bpmn-js (edição de BPMN), TipTap (texto enriquecido), @dnd-kit (arrastar e largar), React Flow (diagramas de arquitetura).
Backend FastAPI
O backend trata de toda a lógica de negócio, acesso a dados, aplicação de permissões e eventos em tempo real. É estruturado como um conjunto de routers (um por domínio) que se montam todos sob /api/v1/. Todos os handlers de rota são async, utilizando a sessão assíncrona do SQLAlchemy com o driver asyncpg.
A autenticação utiliza tokens JWT (HS256, armazenados no sessionStorage do browser). O Bcrypt trata do hashing de palavras-passe. Os valores sensíveis armazenados na base de dados (segredos SSO, palavras-passe SMTP) são encriptados com encriptação simétrica Fernet antes de serem escritos e desencriptados na leitura.
PostgreSQL
Todos os dados da aplicação residem no PostgreSQL. O esquema é gerido pelo Alembic; a aplicação executa alembic upgrade head a cada arranque, pelo que as migrações de esquema são aplicadas automaticamente na atualização. As tabelas utilizam chaves primárias UUID em toda a aplica ção.
Não existe Redis, nenhuma fila de mensagens nem cache externa. As atualizações em tempo real utilizam Server-Sent Events (SSE) numa ligação HTTP de longa duração diretamente a partir do backend.
Nginx de Perímetro
Um contentor Nginx leve situa-se à frente dos contentores React e FastAPI. Serve a React SPA compilada, faz proxy de /api/* para o backend (com cabeçalhos apropriados para SSE), serve o DrawIO auto-hospedado em /drawio/* e aplica cabeçalhos de segurança (CSP, HSTS, X-Frame-Options, etc.). Em produção, este é o único contentor exposto à rede.
Módulos opcionais
Ollama (sugestões de IA)
Adicione --profile ai ao Docker Compose para iniciar um contentor Ollama integrado junto com a pilha principal. O pipeline de sugestões de IA do backend chama a API HTTP do Ollama para gerar descrições de cartões utilizando um LLM a executar localmente. O modelo funciona inteiramente dentro da sua infraestrutura.
Também pode apontar o Canopy para qualquer fornecedor externo compatível com Ollama (OpenAI, Anthropic via proxy, etc.) definindo AI_PROVIDER_URL.
Servidor MCP
Adicione --profile mcp para iniciar o servidor Model Context Protocol. Isto expõe os dados do Canopy a assistentes de IA (Claude Desktop, VS Code Copilot, etc.) como um conjunto de ferramentas — consultas apenas de leitura por predefinição, com ferramentas de escrita opcionais protegidas por limites de tamanho por chamada e um fluxo de confirmação.
O servidor MCP autentica-se via OAuth 2.1 delegado ao fornecedor SSO do Canopy, pelo que os utilizadores veem as mesmas permissões através das ferramentas MCP e na interface web.
Fluxo de dados: guardar um cartão
Para tornar a arquitetura concreta, eis o que acontece quando um utilizador guarda um cartão:
- O React chama
PATCH /api/v1/cards/{id}com o payload atualizado - O Nginx faz proxy do pedido para o backend FastAPI
- O handler de rota valida o JWT, verifica a permissão
inventory.editdo utilizador e valida o corpo do pedido com um esquema Pydantic - O SQLAlchemy escreve a linha atualizada no PostgreSQL
- O motor de cálculo executa quaisquer fórmulas ativas para este tipo de cartão
- A pontuação de qualidade de dados é recalculada a partir dos pesos dos campos
- Um evento é publicado no bus SSE em memória
- Qualquer browser ligado recebe o evento e atualiza a interface em tempo real
Portas e rede
| Serviço | Porta interna | Exposta no host |
|---|---|---|
| Nginx (perímetro) | 80 | HOST_PORT (predefinição 8920) |
| FastAPI | 8000 | Não — apenas interno |
| React (apenas desenvolvimento) | 5173 | Sim em desenvolvimento, servido via Nginx em produção |
| PostgreSQL | 5432 | Não — apenas interno |
| Ollama (opcional) | 11434 | Não — apenas interno |
| Servidor MCP (opcional) | 8001 | Via prefixo Nginx /mcp/ |
Consulte também
- Compreender o Metamodelo — o design do modelo de dados
- Integração MCP — configurar o servidor MCP
- Capacidades de IA — configurar a funcionalidade de sugestões de IA