Pular para o conteúdo principal

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).

PastaPapel
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

  1. Login bcrypt + rate limit (5 / 900s) em backend_rate_limits.
  2. Sessão endurecida: httponly, SameSite=Lax, secure em HTTPS, timeout 7200s, regeneração 1800s, fingerprint do User-Agent.
  3. CSRF 32 bytes; header X-CSRF-Token ou campo csrf_token. O cliente injeta o header em todo método que não seja GET/HEAD.
  4. RBAC em dois eixos: papéis (super-admin 100, admin 80, marketplace 50, representante 20) e flags modulo.acao.
  5. Dois níveis de tenant: a flag precisa estar no usuário e no escopo do White Label (white_label_permissao). Super-admin bypassa.
  6. 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+DB
  • POST /backend/api/auth/login.php (e forgot/reset)
  • POST /backend/api/assinaturas/webhook.php — HMAC Autentique
  • GET /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_id e/ou hierarquia users.user_id, salvo super-admin (can_view_all).

Ver modelo-dados.md.

7. Integrações

SistemaUsoFalha típica
MovingpayTransações, planos, EC remoto, dispositivosToken/ambiente HML vs PROD invertido
AutentiqueContrato/termo, webhook de statusSecret de assinatura divergente
Google DriveArquivos de usuárioJSON da service account ausente no container
Google PlacesImport de leads (quota por tenant)Chave só na plataforma, não no WL
OpenAItarefas/ai-summary.phpOPENAI_API_KEY vazia
PayUpCredenciamento PJ/PF (client pronto, config env)Credenciais não preenchidas
SMTP / EvolutionRecuperação de senha, WhatsApp por contaPreferê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/.