Arquitetura — AMPLIA
Última atualização: 16/09/2026.
Visão de sistema, diagramas C4 e o contrato entre camadas. Decisões registradas em adr/. Catálogo HTTP em api/endpoints.md.
1. Contexto (C4 — nível 1)
O AMPLIA é o backoffice da operação de adquirência/subadquirência. Operadores (admin global, White Label, representantes, compliance) usam o portal para credenciar estabelecimentos, precificar, acompanhar transações e apurar comissões. O sistema não é o autorizador de cartão: ele orquestra cadastro, governança e consolidação, falando com gateways e provedores.
C4Context
title Portal AMPLIA — contexto
Person(op, "Operador interno", "Admin, WL, representante, compliance")
Person(ec, "Estabelecimento", "Painel user_ec / definição de senha")
System(amplia, "AMPLIA", "Backoffice multi-tenant PHP")
System_Ext(mp, "Movingpay / Adiq", "Transações, planos, credenciamento, TIDs")
System_Ext(aut, "Autentique", "Assinatura eletrônica GraphQL")
System_Ext(gdrive, "Google Drive", "Arquivos de usuário / documentos")
System_Ext(places, "Google Places", "Importação de leads")
System_Ext(oai, "OpenAI", "Resumo de tarefas")
System_Ext(payup, "PayUp", "Credenciamento (em evolução)")
System_Ext(mail, "SMTP / Evolution", "E-mail e WhatsApp")
Rel(op, amplia, "HTTPS sessão + CSRF")
Rel(ec, amplia, "Definir senha / painel")
Rel(amplia, mp, "REST Bearer + Customer")
Rel(amplia, aut, "GraphQL + webhook")
Rel(amplia, gdrive, "Service account")
Rel(amplia, places, "Places API v1")
Rel(amplia, oai, "Chat completions")
Rel(amplia, payup, "REST JWT")
Rel(amplia, mail, "SMTP / HTTP")
Não há Kafka, fila gerenciada nem barramento de eventos neste repositório.
Jobs longos usam daemon CLI (while true + sleep) ou polling HTTP/browser.
2. Contêineres (C4 — nível 2)
C4Container
title Contêineres
Person(op, "Operador")
Container(web, "nginx + PHP-FPM", "Docker php:8.3 / Apache local", "SSR + JSON")
ContainerDb(db, "MySQL / MariaDB", "utf8mb4", "Estado de negócio")
Container(files, "uploads + Drive", "volume / GCS-like Drive", "Binários")
Rel(op, web, "HTTP :8080")
Rel(web, db, "mysqli / PDO")
Rel(web, files, "FS / Google API")
No Docker: um único serviço app (nginx na 80 do container, PHP-FPM 9000).
Volumes: uploads, sessions, app-logs. Banco é externo (não sobe no
compose). Ver deploy.md.
3. Componentes (C4 — nível 3)
Navegador
│ HTML dashboard/*.php → frontend/pages/** → components/
│ JSON backend/api/<modulo>/<acao>.php
│ ├ bootstrap (sessão, CSRF, permissões, log)
│ └ backend/src/services/<dominio>/ SQL + regra
│ ├ integrations/movingpay | autentique | payup
│ └ config/*.php ← getenv / .env
Não existe front controller nem router: cada URL é um .php físico.
Não há camada de repositório: o SQL vive nos serviços. Código majoritariamente
procedural (backend_<dominio>_<acao>), com classes pontuais (Drive, PayUp,
polling, Database legado).
| Pasta | Papel |
|---|---|
dashboard/ | Entrypoints públicos (quase sempre require da view) |
frontend/pages/ | HTML das telas |
components/ | Shell, sidebar, list layout, modais |
assets/ | CSS compilado e JS por página |
backend/api/ | ~191 endpoints JSON |
backend/src/services/ | Domínios de negócio |
backend/src/integrations/ | Clients HTTP externos |
database/migrations/ | Scripts PHP/SQL idempotentes, sem runner |
docker/ | nginx, php.ini, entrypoint (não vai na imagem final) |
4. Autenticação e autorização
- Login bcrypt + rate limit (5 / 900s) em
backend_rate_limits. - Sessão endurecida:
httponly,SameSite=Lax,secureem HTTPS, timeout 7200s, regeneração 1800s, fingerprint do User-Agent. - CSRF 32 bytes; header
X-CSRF-Tokenou campocsrf_token. O cliente injeta o header em todo método que não seja GET/HEAD. - RBAC em dois eixos: papéis (
super-admin100,admin80,marketplace50,representante20) e flagsmodulo.acao. - Dois níveis de tenant: a flag precisa estar no usuário e no
escopo do White Label (
white_label_permissao). Super-admin bypassa. - Módulos opcionais (
tenant_modules): Comercial e Tarefas podem estar desligados por WL.
A UI esconde botões com data-permission, mas isso é cosmético. A API
revalida no servidor.
5. Contrato HTTP
Envelope padrão (backend/src/helpers/response.php):
{ "status": "success", "message": "...", "data": {} }
{ "status": "error", "message": "..." }
Códigos: 200 ok, 400 validação, 401 sessão, 403 permissão/módulo, 405 método, 503 banco saturado / health fail.
Exceções públicas (sem sessão de operador):
GET /backend/api/health.php— diagnóstico env+DBPOST /backend/api/auth/login.php(e forgot/reset)POST /backend/api/assinaturas/webhook.php— HMAC AutentiqueGET /backend/api/financeiro/external/comissoes.php— token de API
6. Dados e consistência
- Charset
utf8mb4. Prepared statements são o padrão. - Transações explícitas em cadastros críticos (usuários, WL, propostas, senha).
- Módulos novos (
leads,assinaturas,tarefas) chamam*_ensure_schema()em runtime (DDL idempotente no request). - Isolamento: quase toda query de negócio filtra
white_label_ide/ou hierarquiausers.user_id, salvo super-admin (can_view_all).
Ver modelo-dados.md.
7. Integrações
| Sistema | Uso | Falha típica |
|---|---|---|
| Movingpay | Transações, planos, EC remoto, dispositivos | Token/ambiente HML vs PROD invertido |
| Autentique | Contrato/termo, webhook de status | Secret de assinatura divergente |
| Google Drive | Arquivos de usuário | JSON da service account ausente no container |
| Google Places | Import de leads (quota por tenant) | Chave só na plataforma, não no WL |
| OpenAI | tarefas/ai-summary.php | OPENAI_API_KEY vazia |
| PayUp | Credenciamento PJ/PF (client pronto, config env) | Credenciais não preenchidas |
| SMTP / Evolution | Recuperação de senha, WhatsApp por conta | Preferência de conta vs env |
Não há client HTTP único: cada integração monta curl_init.
8. Observabilidade
backend_api_log() grava JSON Lines em backend/logs/{modulo}/YYYY-MM-DD.log
e na tabela backend_api_logs. Campos senha, token, authorization etc.
são redigidos. Todo endpoint com bootstrap registra api_request.
Não há APM (Sentry/Datadog) nem rotação automática de log.
9. O que deliberadamente não temos
- SPA / bundler de JS (há Tailwind só para CSS)
- ORM, PSR-4 no app, filas, Kafka, Redis
- CI/CD no repositório (deploy ainda é imagem + env no host)
- Suíte de testes automatizados do produto
Essas ausências são ADRs, não acidentes. Ver adr/.