- Adiciona Dockerfile e docker-compose para containerizacao - Adiciona docker-entrypoint.sh com inicializacao - Adiciona scripts/seed-admin.js para criar admin inicial - Adiciona docs/ com logos originais CambioReal - Atualiza README.md com instrucoes de uso - Atualiza queries.js com metricas de portfólio Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
14 KiB
14 KiB
Arquitetura - BI Agentes
Documentacao tecnica da arquitetura do sistema BI Agentes.
Visao Geral
O BI Agentes e uma aplicacao web monolitica construida com Node.js/Express que serve dashboards de BI para agentes de cambio. A arquitetura prioriza simplicidade, seguranca e isolamento de dados.
Diagrama de Arquitetura
INTERNET
│
▼
┌───────────────────────────────────────────────────────────────────────────┐
│ SERVIDOR EXPRESS │
│ (PORT 3080) │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌────────────┐ │
│ │ Static │ │ Session │ │ Auth │ │ Dashboard │ │
│ │ Files │ │ Middleware │ │ Middleware │ │ Generator │ │
│ │ /public │ │ (in-memory) │ │ requireAuth │ │ (HTML) │ │
│ └─────────────┘ └──────┬──────┘ └──────┬──────┘ └─────┬──────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌────────────────────────────────────────────────────────────────────┐ │
│ │ REQUEST ROUTER │ │
│ │ │ │
│ │ GET /login ──────▶ login.html │ │
│ │ POST /login ─────▶ authenticate() ──▶ session.create() │ │
│ │ GET /logout ─────▶ session.destroy() │ │
│ │ GET /dashboard ──▶ requireAuth ──▶ fetchTransacoes() ──▶ HTML │ │
│ │ GET / ───────────▶ redirect /dashboard │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │ │ │
└────────────────────────────┼───────────────────────────┼──────────────────┘
│ │
┌──────────────┘ └──────────────┐
▼ ▼
┌───────────────────┐ ┌───────────────────┐
│ SQLite │ │ AWS RDS │
│ (agentes.db) │ │ (cambio_db) │
│ │ │ │
│ ┌─────────────┐ │ │ ┌─────────────┐ │
│ │ agentes │ │ │ │br_transac...│ │
│ │ - id │ │ │ │- id │ │
│ │ - email │ │ │ │- id_conta │ │
│ │ - senha_hash│ │ │ │- amount_brl │ │
│ │ - agente_id │ │ │ │- amount_usd │ │
│ │ - nome │ │ │ │- exchange...| │
│ │ - ativo │ │ │ │- status │ │
│ └─────────────┘ │ │ └─────────────┘ │
│ │ │ │
│ LOCAL (WAL) │ │ ┌─────────────┐ │
│ WRITE + READ │ │ │pagamento_br │ │
└───────────────────┘ │ │- id │ │
│ │- id_conta │ │
│ │- valor │ │
│ │- valor_sol │ │
│ │- cotacao │ │
│ └─────────────┘ │
│ │
│ REMOTE (MySQL) │
│ READ-ONLY │
└───────────────────┘
Componentes
1. Camada de Apresentacao
Tecnologias: HTML5, CSS3, Vanilla JavaScript, Chart.js
| Arquivo | Responsabilidade |
|---|---|
public/login.html |
Formulario de login estilizado |
src/dashboard.js |
Geracao dinamica do HTML do dashboard |
Caracteristicas:
- Server-Side Rendering (SSR) - HTML gerado no backend
- Chart.js carregado via CDN (sem build step)
- CSS inline no dashboard para simplicidade
- Google Fonts Inter para tipografia
2. Camada de Aplicacao
Tecnologias: Node.js, Express.js
| Modulo | Responsabilidade |
|---|---|
server.js |
Entry point, rotas, middleware |
src/auth.js |
Autenticacao, bcrypt, sessoes |
src/queries.js |
Queries SQL, serializacao de dados |
Middleware Stack:
Request
│
▼
express.urlencoded() ← Parse form data
│
▼
express.json() ← Parse JSON
│
▼
express-session() ← Gerenciar sessao
│
▼
requireAuth() ← Verificar autenticacao (rotas protegidas)
│
▼
Route Handler
3. Camada de Dados
SQLite (Local)
Biblioteca: better-sqlite3 (sincrono, WAL mode)
CREATE TABLE agentes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
email TEXT UNIQUE NOT NULL,
senha_hash TEXT NOT NULL,
agente_id INTEGER NOT NULL,
nome TEXT NOT NULL,
ativo INTEGER DEFAULT 1,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
Caracteristicas:
- WAL mode para melhor concorrencia
- Arquivo em
data/agentes.db - Criado automaticamente no primeiro start
MySQL (RDS)
Biblioteca: mysql2/promise (pool de conexoes)
Configuracao do Pool:
{
host: process.env.MYSQL_URL,
user: process.env.USER_MYSQL,
password: process.env.PW_MYSQL,
database: 'cambio_db',
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0
}
Tabelas Consultadas:
| Tabela | Fluxo | Campos Principais |
|---|---|---|
br_transaction_to_usa |
BRL→USD | amount_brl, amount_usd, exchange_rate, iof, ptax |
pagamento_br |
USD→BRL | valor, valor_sol, cotacao, ptax |
ag_contas |
Join | agente_id, conta_id |
conta |
Join | id_conta, nome |
Fluxo de Dados
Autenticacao
┌──────────┐ POST /login ┌──────────┐
│ Browser │ ─────────────────▶ │ Express │
│ │ email, senha │ │
└──────────┘ └────┬─────┘
│
┌────────────────┘
▼
┌──────────────┐
│ SQLite │
│ SELECT WHERE │
│ email = ? │
└──────┬───────┘
│
▼
┌──────────────┐
│ bcrypt │
│ compare │
└──────┬───────┘
│
┌───────┴───────┐
▼ ▼
[MATCH] [NO MATCH]
│ │
▼ ▼
session.agente redirect
= {...} /login?error=1
│
▼
redirect
/dashboard
Carregamento do Dashboard
┌──────────┐ GET /dashboard ┌──────────┐
│ Browser │ ─────────────────▶ │ Express │
│ (cookie) │ │ │
└──────────┘ └────┬─────┘
│
requireAuth()────┘
│
┌─────────────┴─────────────┐
▼ ▼
[NO SESSION] [HAS SESSION]
│ │
▼ ▼
redirect ┌─────────────────┐
/login │ fetchTransacoes │
│ (agente_id) │
└────────┬────────┘
│
┌─────────────────┘
▼
┌──────────────┐
│ AWS RDS │
│ 2 queries: │
│ BRL→USD │
│ USD→BRL │
└──────┬───────┘
│
▼
┌──────────────┐
│ serialize() │
│ merge + │
│ sort │
└──────┬───────┘
│
▼
┌──────────────┐
│ buildHTML() │
│ KPIs + │
│ Charts + │
│ Table │
└──────┬───────┘
│
▼
res.send(html)
Seguranca
Autenticacao
| Aspecto | Implementacao |
|---|---|
| Hash de senha | bcrypt, 10 salt rounds |
| Sessao | express-session, in-memory |
| Timeout | 8 horas (cookie maxAge) |
| Middleware | requireAuth em rotas protegidas |
Protecao de Dados
| Aspecto | Implementacao |
|---|---|
| SQL Injection | Queries parametrizadas (?) |
| Isolamento | WHERE agente_id = ? em todas queries |
| RDS Access | Usuario read-only (sem INSERT/UPDATE/DELETE) |
Recomendacoes para Producao
- Usar Redis para sessoes (em vez de in-memory)
- HTTPS obrigatorio (TLS)
- Helmet.js para headers de seguranca
- Rate limiting no login
- Logs de auditoria
Performance
Estrategias Atuais
- Connection Pool: 10 conexoes MySQL reutilizaveis
- WAL Mode: SQLite com Write-Ahead Logging
- CDN: Chart.js e fonts via CDN (cache do browser)
- SSR: HTML pre-renderizado (sem SPA overhead)
Gargalos Potenciais
| Componente | Risco | Mitigacao |
|---|---|---|
| Sessoes in-memory | Perda em restart | Migrar para Redis |
| Queries RDS | Tabelas grandes | Adicionar indices, paginacao |
| HTML generation | Muitas transacoes | Paginacao server-side |
Estrutura de Modulos
src/
├── auth.js # Autenticacao
│ ├── authenticate(email, senha)
│ └── requireAuth(req, res, next)
│
├── db-local.js # SQLite setup
│ └── initDB()
│
├── db-rds.js # MySQL pool
│ └── pool (export)
│
├── queries.js # Data access
│ ├── fetchTransacoes(agenteId)
│ └── serialize(rowsBrlUsd, rowsUsdBrl)
│
└── dashboard.js # View generation
└── buildHTML(data, agente)
Dependencias
| Pacote | Versao | Proposito |
|---|---|---|
| express | ^4.x | Framework web |
| express-session | ^1.x | Gerenciamento de sessao |
| better-sqlite3 | ^9.x | SQLite driver (sync) |
| mysql2 | ^3.x | MySQL driver (async) |
| bcrypt | ^5.x | Hash de senhas |
| dotenv | ^16.x | Variaveis de ambiente |
Extensibilidade
Adicionar Nova Feature
- Novo endpoint: Adicionar rota em
server.js - Nova query: Adicionar funcao em
src/queries.js - Nova UI: Modificar
src/dashboard.jsou criar novo modulo
Adicionar Novo Fluxo de Transacao
- Criar query em
src/queries.js - Atualizar
serialize()para incluir novo fluxo - Atualizar
buildHTML()para exibir dados
Decisoes de Arquitetura
| Decisao | Justificativa |
|---|---|
| Monolito | Simplicidade para equipe pequena |
| SSR | Sem necessidade de SPA, SEO nao relevante |
| SQLite para auth | Independencia do RDS, portabilidade |
| Vanilla JS | Sem build step, menor complexidade |
| better-sqlite3 | Sync API mais simples para auth |
| mysql2 | Pool de conexoes async para RDS |