Pular para o conteúdo principal

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:

  1. O React chama PATCH /api/v1/cards/{id} com o payload atualizado
  2. O Nginx faz proxy do pedido para o backend FastAPI
  3. O handler de rota valida o JWT, verifica a permissão inventory.edit do utilizador e valida o corpo do pedido com um esquema Pydantic
  4. O SQLAlchemy escreve a linha atualizada no PostgreSQL
  5. O motor de cálculo executa quaisquer fórmulas ativas para este tipo de cartão
  6. A pontuação de qualidade de dados é recalculada a partir dos pesos dos campos
  7. Um evento é publicado no bus SSE em memória
  8. Qualquer browser ligado recebe o evento e atualiza a interface em tempo real

Portas e rede

ServiçoPorta internaExposta no host
Nginx (perímetro)80HOST_PORT (predefinição 8920)
FastAPI8000Não — apenas interno
React (apenas desenvolvimento)5173Sim em desenvolvimento, servido via Nginx em produção
PostgreSQL5432Não — apenas interno
Ollama (opcional)11434Não — apenas interno
Servidor MCP (opcional)8001Via prefixo Nginx /mcp/

Consulte também