# 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) ```sql 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:** ```javascript { 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 1. **Novo endpoint**: Adicionar rota em `server.js` 2. **Nova query**: Adicionar funcao em `src/queries.js` 3. **Nova UI**: Modificar `src/dashboard.js` ou criar novo modulo ### Adicionar Novo Fluxo de Transacao 1. Criar query em `src/queries.js` 2. Atualizar `serialize()` para incluir novo fluxo 3. 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 |