1. Visao Geral
MegaCall — SaaS multi-tenant de atendimento WhatsApp. Stack: Python 3.12+, Flask 3.0, SQLAlchemy 2.0, Socket.IO, PostgreSQL (prod) / SQLite (dev), Redis, Stripe, Evolution API. Frontend: Bootstrap 5.3, Jinja2, Chart.js. Porta dev: 1997.
2. Arquitetura
Clean Architecture em 4 camadas: Domain (models), Application (services), Infrastructure (repositories, gateways), Interface (blueprints, templates, SocketIO). Multi-tenancy por banco dedicado: Control Plane (master) + bancos por tenant. TenantManager resolve tenant por subdominio/JWT.
3. Estrutura de Pastas
megacall/
__init__.py # App factory + context processors
config.py # Config dev/test/prod
extensions.py # db, migrate, login, jwt, csrf, limiter, socketio
core/
errors.py, logging.py, middleware.py, utils.py
security/ # crypto.py (AES-256-GCM), passwords.py (Argon2), tokens.py
tenancy/ # base.py, manager.py, provisioner.py
control_plane/ # models.py, repository.py (banco master)
tenant/ # models.py (schema por cliente)
application/ # 18 services (auth, billing, bot, evolution, etc.)
interface/
web.py # Paginas HTML publicas + app
admin.py # Painel Super Admin (Flask-Login)
health.py # /health
api/ # 12 blueprints de API REST
realtime/ # events.py, emitters.py (Socket.IO)
templates/ # base, landing, login, register, app/*, admin/*
static/ # css/, js/ (14 arquivos), manifest.json, sw.js
migrations/ # Alembic
tests/ # 35 testes pytest
deploy/ # nginx.conf, megacall.service, README
gunicorn.conf.py, wsgi.py, requirements.txt, .env.example
4. Models
Control Plane (megacall/control_plane/models.py)
| Model | Tabela | Campos principais |
| SuperAdmin | super_admins | id, name, email, password_hash, is_active |
| Plan | plans | code(starter/pro/business/enterprise), price_cents, max_users, max_departments, max_connections, max_bots, max_simultaneous_attendances, api_rate_limit, message_rate_limit, storage_mb |
| Tenant | tenants | uuid, company_name, slug, db_name, owner_email, encryption_salt, status(trial/active/blocked/canceled), plan_id, stripe_customer_id, extra_connections, brand_name, logo_url, primary_color |
| Subscription | subscriptions | tenant_id, plan_id, stripe_subscription_id, status, current_period_end |
| Payment | payments | tenant_id, stripe_invoice_id, amount_cents, status |
| EvolutionInstance | evolution_instances | tenant_id, instance_name, status, webhook_token |
| AuditLog | audit_logs | tenant_id, actor_type, action, entity, ip_address, details |
| ApiKey | api_keys | tenant_id, name, key_hash, key_prefix, is_active |
| WebhookConfig | webhook_configs | tenant_id, url, secret, events, is_active |
| WebhookDelivery | webhook_deliveries | webhook_config_id, event_type, payload, status_code, error |
Tenant (megacall/tenant/models.py)
| Model | Tabela | Campos principais |
| User | users | uuid, name, email, password_hash, role(admin/supervisor/agent), is_online, departments(M:N) |
| Department | departments | name, description, is_active, users(M:N), conversations(1:N) |
| Contact | contacts | name, phone, whatsapp_id, is_blocked |
| Conversation | conversations | contact_id, department_id, assigned_user_id, status(open/pending/closed), unread_count, first_response_at, csat_score, tags(M:N), notes(1:N) |
| Message | messages | conversation_id, direction(inbound/outbound), media_type, content_encrypted(AES-256-GCM), external_id, is_read |
| Tag | tags | name, color |
| QuickReply | quick_replies | shortcut, content |
| InternalNote | internal_notes | conversation_id, user_id, content |
| BotFlow | bot_flows | name, status(draft/active/paused), trigger_keywords, nodes_json, start_node_id |
| BotSession | bot_sessions | conversation_id, bot_flow_id, current_node_id, context_json, is_active |
5. Seguranca
| Mecanismo | Arquivo | Descricao |
| AES-256-GCM | core/security/crypto.py | Mensagens cifradas com chave derivada por tenant (HKDF-SHA256). Chave mestra em env var. |
| Argon2id | core/security/passwords.py | Hash de senhas resistente a GPU |
| JWT | Flask-JWT-Extended | Access token 30min + refresh 7 dias. Claims: tenant_id, role, email |
| CSRF | Flask-WTF | Habilitado; API blueprints isentos (usam JWT) |
| Rate Limiting | Flask-Limiter | Login 20/min, Register 10/h, API publica 60/min, dinamico por plano |
| Cloudflare Turnstile | core/security/turnstile.py | Anti-bot nos forms de login e cadastro. Widget client-side + verificacao server-side. Gratis, sem friccao. |
| HMAC-SHA256 | webhook_service.py | Assinatura de webhooks de tenant |
| Stripe Signature | billing_service.py | Verificacao de assinatura de webhooks Stripe |
| Headers (Nginx) | deploy/nginx.conf | HSTS, X-Frame-Options, X-Content-Type-Options, X-XSS-Protection |
| SSL | deploy/nginx.conf | TLSv1.2 + TLSv1.3, Let's Encrypt |
6. Autenticacao
// Login
POST /api/v1/auth/login
{"email": "...", "password": "...", "tenant_slug": "..."}
// Response
{"access_token": "eyJ...", "refresh_token": "eyJ...", "token_type": "Bearer"}
// Usar token
Authorization: Bearer <access_token>
Roles: admin (total), supervisor (operacional), agent (atendimento). Decorator: @require_role("admin", "supervisor").
API Publica: Bearer mc_... (chave de API, sem JWT).
7. API REST
Prefixo base: /api/v1. Todas as respostas sao JSON. Erros seguem formato {"error": "ErrorType", "message": "..."}.
Auth /auth
| Metodo | Rota | Auth | Descricao |
| POST | /register | - | Cadastra empresa + admin + trial |
| GET | /confirm/<token> | - | Confirma email |
| POST | /login | - | Autentica, retorna JWT |
| POST | /refresh | Refresh | Renova access token |
| GET | /me | JWT | Dados do usuario |
Billing /billing
| Metodo | Rota | Role | Descricao |
| GET | /plans | - | Lista planos ativos |
| POST | /checkout | admin | Cria sessao Stripe Checkout |
| POST | /portal | admin | Cria sessao Stripe Portal |
| GET | /status | admin/supervisor | Status da assinatura |
| GET | /connections | admin/supervisor | Limite de conexoes WhatsApp |
| POST | /connections/add | admin | Adiciona numero extra (metered) |
Evolution /evolution
| Metodo | Rota | Role | Descricao |
| POST | /instance | admin | Cria/retorna instancia WhatsApp |
| GET | /qrcode | admin | QR code para conectar |
| GET | /status | admin/supervisor | Estado de conexao |
| POST | /reconnect | admin | Reconecta instancia |
Inbox /inbox
| Metodo | Rota | Auth | Descricao |
| GET | /conversations | JWT | Lista conversas |
| GET | /conversations/<id>/messages | JWT | Lista mensagens decifradas |
| POST | /conversations/<id>/messages | JWT | Envia mensagem (rate limited) |
| POST | /conversations/<id>/assign | JWT | Atribui conversa |
| POST | /conversations/<id>/transfer | JWT | Transfere departamento |
| POST | /conversations/<id>/read | JWT | Marca como lida |
| POST | /conversations/<id>/close | JWT | Fecha conversa |
Manage /manage
| Metodo | Rota | Role | Descricao |
| GET/POST/PUT/DELETE | /departments[/<id>] | admin/supervisor | CRUD departamentos |
| GET/POST/PUT/DELETE | /users[/<id>] | admin | CRUD usuarios (limite por plano) |
| GET/POST/PUT/DELETE | /contacts[/<id>] | admin/supervisor | CRUD contatos (com busca) |
| GET | /audit | admin | Trilha de auditoria |
Bots /bots
| Metodo | Rota | Role | Descricao |
| GET/POST | /flows | admin/supervisor | Lista/cria fluxos |
| GET/PUT/DELETE | /flows/<id> | admin/supervisor | Detalha/atualiza/remove |
| POST | /flows/<id>/activate | admin/supervisor | Ativa fluxo (verifica limite) |
| POST | /flows/<id>/pause | admin/supervisor | Pausa fluxo |
Reports /reports
| Metodo | Rota | Auth | Descricao |
| GET | /stats | JWT | Estatisticas do dashboard |
| GET | /attendance | JWT | Relatorio de atendentes |
| GET | /daily-volume | JWT | Volume de mensagens/dia |
| GET | /frt | JWT | First Response Time |
| GET | /csat | JWT | Satisfacao (CSAT) |
| GET | /departments | JWT | Relatorio por departamento |
| GET | /export/conversations | JWT | Exporta CSV |
| GET | /export/contacts | JWT | Exporta CSV |
API Publica /public + Keys /manage/api-keys
| Metodo | Rota | Auth | Descricao |
| GET | /public/conversations | Bearer mc_... | Lista conversas |
| GET | /public/contacts | Bearer mc_... | Lista contatos |
| GET/POST | /manage/api-keys/ | JWT admin | Lista/cria chaves |
| DELETE | /manage/api-keys/<id> | JWT admin | Revoga chave |
Webhooks /webhooks + Tenant Webhooks /manage/webhooks
| Metodo | Rota | Auth | Descricao |
| POST | /webhooks/stripe | Stripe Signature | Eventos Stripe |
| POST | /webhooks/evolution/<token> | Token URL | Eventos Evolution API |
| GET/POST | /manage/webhooks/ | JWT admin | Lista/cria webhooks de tenant |
| DELETE | /manage/webhooks/<id> | JWT admin | Remove webhook |
| POST | /manage/webhooks/<id>/toggle | JWT admin | Ativa/desativa |
White Label /manage/white-label
| Metodo | Rota | Role | Descricao |
| GET | / | JWT | Config atual (brand_name, logo_url, primary_color) |
| PUT | / | admin | Atualiza white label |
Web (HTML) /
| Rota | Descricao |
| / | Landing page |
| /login, /register, /confirm/<token> | Auth pages |
| /developers | Esta pagina |
| /app | Dashboard |
| /app/inbox | Atendimento |
| /app/whatsapp | Conectar WhatsApp |
| /app/billing | Assinatura |
| /app/departments, /users, /contacts | CRUD |
| /app/bots | Bots/URA com editor visual |
| /app/reports | Relatorios |
| /app/settings | White label + webhooks |
Admin (HTML) /admin
| Rota | Descricao |
| /admin/login, /admin/logout | Auth Super Admin |
| /admin/ | Dashboard (MRR, churn, graficos) |
| /admin/tenants | Lista/busca tenants, block/unblock |
| /admin/audit | Trilha de auditoria global |
| /admin/plans | Planos |
8. Socket.IO (Realtime)
Arquivo: megacall/realtime/events.py
Conexao
const socket = io({ auth: { token: "<jwt>" } });
Eventos Cliente -> Servidor
| Evento | Payload | Descricao |
| conversation:join | {conversation_id} | Entra na sala da conversa |
| conversation:leave | {conversation_id} | Sai da sala |
| message:send | {conversation_id, text} | Envia mensagem |
| typing | {conversation_id, is_typing} | Indicador digitando |
| message:read | {conversation_id} | Marca como lida |
Eventos Servidor -> Cliente
| Evento | Payload | Descricao |
| connected | {tenant_id} | Confirmacao de conexao |
| message:new | {conversation_id, message} | Nova mensagem (inbound/outbound) |
| conversation:update | {...conversation} | Atualizacao de conversa |
| typing | {conversation_id, user_id, is_typing} | Indicador de digitacao |
Isolamento: cada tenant em sua room (tenant:{id}). Conversas em sub-rooms (conv:{tenant_id}:{conv_id}).
9. Camada de Services
| Service | Arquivo | Responsabilidade |
| AuthService | auth_service.py | Registro de empresa, confirmacao email, login JWT |
| BillingService | billing_service.py | Stripe: checkout, portal, webhooks, add-ons metered |
| BotService | bot_service.py | CRUD de fluxos, execucao de nos (start/message/menu/wait/transfer/end) |
| EvolutionService | evolution_service.py | Instancia WhatsApp, QR code, webhook inbound, dispatch webhook eventos |
| MessagingService | messaging_service.py | Store/read mensagens cifradas, listagens |
| OutboundService | outbound_service.py | Envio outbound + Evolution + broadcast SocketIO + webhook dispatch |
| AttendanceService | attendance_service.py | Assign/transfer/mark_read/close conversas |
| ReportService | report_service.py | Dashboard stats, FRT, CSAT, export CSV, relatorio departamentos |
| WebhookService | webhook_service.py | CRUD webhooks, dispatch HMAC-SHA256, registro de entregas |
| ApiKeyService | api_key_service.py | Gerar/listar/revogar chaves mc_..., resolver tenant |
| AuditService | audit_service.py | Log e listagem de auditoria |
| EmailService | email_service.py | SMTP com templates HTML |
| PlanService | plan_service.py | Seed de planos, DEFAULT_PLANS |
| PlanLimitService | plan_limit_service.py | Enforcement de limites em runtime (users, bots, connections, depts) |
| PlatformMetricsService | platform_metrics_service.py | MRR, churn, crescimento, distribuicao por plano |
| RateLimitService | rate_limit_service.py | Rate limiting dinamico por plano (api + message) |
10. Templates (Jinja2)
| Template | Descricao |
| base.html | Base: head, PWA meta, CSS vars (white label), footer, SW registration |
| landing.html | Hero, features, planos (JS carrega via API) |
| login.html, register.html, confirm.html | Auth pages |
| developers.html | Esta pagina |
| app/layout.html | Shell: sidebar (10 items) + topbar, footer oculto |
| app/dashboard.html | Stats via API + conversas recentes |
| app/inbox.html | Chat realtime (Socket.IO), typing, acoes |
| app/whatsapp.html | QR code, status, polling |
| app/billing.html | Planos, checkout, portal |
| app/departments.html | CRUD com modais |
| app/users.html | CRUD com modais, associacao departamentos |
| app/contacts.html | CRUD com busca |
| app/bots.html | Lista fluxos + modal com editor visual drag-and-drop |
| app/reports.html | Graficos Chart.js, exportacao CSV |
| app/settings.html | White label (color picker, logo, brand) + webhooks |
| admin/base.html | Shell admin + footer dev credit |
| admin/login.html | Login Super Admin |
| admin/dashboard.html | MRR, churn, graficos, tenants recentes |
| admin/tenants.html | Lista/busca, block/unblock |
| admin/audit.html | Trilha de auditoria |
| admin/plans.html | Planos |
| emails/* | 11 templates HTML de email |
Context processor injeta: brand_name, logo_url, primary_color, current_year.
11. Arquivos Estaticos (JS/CSS)
JavaScript
| Arquivo | Funcao |
| api.js | API client: JWT em localStorage, refresh automatico, logout |
| app.js | Shell: sidebar, logout, tenant status badge |
| landing.js | Carrega planos via API |
| login.js, register.js | Auth forms |
| inbox.js | Chat realtime com Socket.IO client |
| dashboard.js | Stats via API |
| whatsapp.js | QR code polling, conectar/desconectar |
| billing.js | Checkout/portal |
| departments.js, users.js, contacts.js | CRUD com modais |
| bots.js | CRUD fluxos + integracao FlowEditor |
| flow-editor.js | Editor visual drag-and-drop (canvas, nos, conexoes SVG, painel edicao) |
| reports.js | Chart.js + exportacao CSV |
| settings.js | White label + webhooks management |
CSS
app.css: hero gradient, auth, app shell, sidebar, inbox bubbles, QR box, flow editor, site footer (dark theme).
PWA
manifest.json (standalone, icons, theme-color) + sw.js (cache-first assets, network-first pages).
12. Configuracao
Arquivo: megacall/config.py — 3 ambientes: DevelopmentConfig, TestingConfig, ProductionConfig.
| Variavel | Default Dev | Descricao |
| FLASK_ENV | development | Ambiente |
| SECRET_KEY | dev-secret | Chave Flask/CSRF/tokens |
| JWT_SECRET_KEY | =SECRET_KEY | Chave JWT |
| MASTER_ENCRYPTION_KEY | dev-key | Chave mestra AES (HKDF por tenant) |
| MASTER_DATABASE_URL | SQLite instance/ | Banco control plane |
| TENANT_DATABASE_TEMPLATE | SQLite instance/{db_name} | Template banco tenant |
| REDIS_URL | redis://localhost:6379/0 | Redis |
| SOCKETIO_ASYNC_MODE | threading | eventlet em prod |
| STRIPE_SECRET_KEY | vazio | Stripe |
| EVOLUTION_API_URL | vazio | Evolution API |
| TURNSTILE_SITE_KEY | vazio | Cloudflare Turnstile site key (widget client-side) |
| TURNSTILE_SECRET_KEY | vazio | Cloudflare Turnstile secret key (verificacao server-side) |
| SMTP_HOST | vazio | Servidor email |
| RATELIMIT_STORAGE_URI | memory:// | Redis em prod |
Ver .env.example para referencia completa.
13. Deploy
# 1. Pre-req: Ubuntu + Python 3.11+ + PostgreSQL + Redis + Nginx
# 2. Criar banco: CREATE DATABASE megacall_master OWNER megacall;
# 3. git clone + venv + pip install -r requirements.txt
# 4. cp .env.example .env (ajustar chaves, banco, Stripe, Evolution, SMTP)
# 5. flask --app wsgi init-master && seed-plans && create-superadmin
# 6. flask --app wsgi db upgrade (Alembic)
# 7. sudo cp deploy/nginx.conf /etc/nginx/sites-available/megacall
# 8. sudo cp deploy/megacall.service /etc/systemd/system/
# 9. sudo systemctl enable megacall && start megacall
# 10. SSL: sudo certbot --nginx -d app.seudominio.com
Gunicorn: gunicorn -c gunicorn.conf.py wsgi:app (4 workers eventlet, bind 127.0.0.1:8000)
Nginx: proxy reverso + WebSocket + static files + SSL + headers de seguranca
14. Comandos CLI
flask --app wsgi init-master # Cria tabelas do control plane
flask --app wsgi seed-plans # Cria 4 planos padrao
flask --app wsgi create-superadmin # Cria Super Admin
flask --app wsgi sync-stripe-plans # Sincroniza planos com Stripe
flask --app wsgi backup-tenant <db> # Backup SQLite de um tenant
flask --app wsgi backup-master # Backup SQLite do banco master
flask --app wsgi db upgrade # Aplica migracoes Alembic
python scripts/migrate_tenants.py # Aplica schema em tenants existentes
15. Testes
python -m pytest tests/ -v # 35 testes
| Arquivo | Testes | Cobertura |
| test_auth.py | 6 | register, duplicate, login, wrong password, /me, no token |
| test_billing.py | 4 | plans, status, connections, add connection |
| test_bots.py | 5 | list, create, update, pause, delete |
| test_manage.py | 6 | departments, users, contacts CRUD |
| test_public_api.py | 5 | api keys, public endpoints, no key |
| test_reports.py | 7 | stats, attendance, daily-volume, FRT, CSAT, departments, CSV |
16. Planos e Limites
| Plano | Preco | Usuarios | Depts | Conexoes | Bots | Atend. | API/min | Msg/min |
| Starter | R$ 24,90 | 3 | 2 | 1 | 1 | 10 | 60 | 100 |
| Pro | R$ 79,90 | 10 | 5 | 3 | 5 | 50 | 120 | 300 |
| Business | R$ 139,00 | 30 | 15 | 10 | 20 | 200 | 300 | 600 |
| Enterprise | R$ 249,90 | 200 | 100 | 25 | 100 | 5000 | 1000 | 2000 |
Add-on numero extra: R$ 19,90 (Starter) / R$ 14,90 (Pro) / R$ 9,90 (Business/Enterprise) por numero/mes.
17. PWA
- manifest.json: standalone, icons 192/512, theme-color, start_url
- sw.js: cache-first para assets, network-first para paginas, fallback cache
- Meta tags: theme-color, apple-mobile-web-app-capable, apple-touch-icon
- Registro: no base.html, registra SW no load