Arquitetura do Sistema
Esta página é uma análise detalhada de como o FeedbackPulse SaaS é construído. Entender a arquitetura ajuda a depurar problemas, estender a plataforma e tomar decisões informadas de implantação.
Stack Tecnológico
| Camada | Tecnologia | Finalidade |
|---|---|---|
| Backend | Laravel 12 (PHP 8.4+) | Framework de aplicação, roteamento, ORM, filas |
| Banco de Dados | MySQL 8.0+ / MariaDB 10.6+ | Armazenamento persistente de dados |
| Frontend | Blade + Alpine.js + Tailwind CSS | UI renderizada no servidor com componentes reativos |
| Pagamentos | Stripe PHP SDK + PayPal REST API | Cobrança de assinaturas |
| IA | OpenAI GPT API | Análise de sentimento, auto-etiquetagem, sugestões de resposta |
| Auth | Laravel Socialite | OAuth com Google e GitHub |
| Laravel Mail (SMTP) | E-mails transacionais, resumos, relatórios | |
| Tempo Real | Server-Sent Events (SSE) | Streaming ao vivo de envios |
| Agendamento | Laravel Scheduler (cron) | Resumos, expiração de testes, retenção de dados |
Modelo Multi-Tenant
O FeedbackPulse utiliza um modelo de multi-tenancy com banco de dados único e esquema compartilhado. Isso significa:
- Um banco de dados atende todos os tenants
- Cada tabela com escopo de tenant possui uma coluna
tenant_id - Um escopo global (
TenantScope) filtra automaticamente todas as consultas para o tenant atual - Um trait (
BelongsToTenant) preenche automaticamente otenant_idna criação e aplica o escopo
Como Funciona a Resolução de Tenant
Quando uma requisição chega, o middleware ResolveTenant determina o tenant atual usando esta prioridade:
- Subdomínio —
acme.yourdomain.com→ busca o tenant com subdomínio "acme" - Domínio personalizado —
feedback.acmecorp.com→ busca o domínio verificado na tabelatenant_domains - Usuário autenticado — usa o
tenant_iddo usuário logado como fallback
Para páginas públicas (como /wall/acme-corp), o tenant é resolvido diretamente pelo slug da URL no controller (ignorando o middleware).
Isolamento de Dados
+------------------------------------------+
| Banco de Dados |
| |
| products (tenant_id = 1) -> Dados Acme |
| products (tenant_id = 2) -> TechCorp |
| products (tenant_id = 3) -> E-Commerce |
| |
| TenantScope garante que Acme veja APENAS|
| linhas onde tenant_id = 1 |
+------------------------------------------+
Segurança: Controllers públicos usam
withoutGlobalScopes()para ignorar o escopo de tenant e filtram manualmente pelo ID do tenant. Isso é intencional — páginas públicas precisam exibir dados sem uma sessão autenticada.
Estrutura de Diretórios
feedbackpulse-saas/
+-- app/
| +-- Console/Commands/ # 7 comandos artisan (resumos, retenção, alertas)
| +-- Http/
| | +-- Controllers/
| | | +-- Admin/ # Controllers do painel superadmin
| | | +-- Auth/ # Login, registro, 2FA, OAuth, impersonação
| | | +-- Customer/ # Portal do cliente
| | | +-- Public/ # Páginas públicas (mural, formulário, roadmap, changelog, hub)
| | | +-- Tenant/ # Controllers do painel do tenant
| | | +-- Webhooks/ # Handlers de webhooks Stripe & PayPal
| | +-- Middleware/ # 15 middlewares personalizados
| +-- Mail/ # 7 classes mailable
| +-- Models/ # 28 modelos Eloquent
| +-- Scopes/ # TenantScope (escopo global de consulta)
| +-- Services/ # Lógica de negócio (IA, pagamentos, webhooks, etc.)
| +-- Traits/ # Trait BelongsToTenant
| +-- Providers/ # Service providers
+-- config/ # 11 arquivos de configuração Laravel
+-- database/
| +-- migrations/ # 35+ arquivos de migração
| +-- seeders/ # Seeders de dados de demonstração
+-- public/ # Raiz web (index.php, assets, symlink de storage)
+-- resources/views/ # 86 templates Blade
| +-- admin/ # Views do superadmin
| +-- auth/ # Views de autenticação (login, registro, 2FA)
| +-- tenant/ # Views do painel do tenant
| +-- public/ # Views das páginas públicas
| +-- emails/ # Templates de e-mail
| +-- layouts/ # Templates de layout (admin, tenant, guest, install)
| +-- partials/ # Componentes compartilhados (nav, meta, paleta de comandos)
| +-- install/ # Views do instalador web
| +-- legal/ # Páginas de privacidade, termos, cookies
| +-- errors/ # Páginas de erro (403, 404, 419, 429, 500)
| +-- landing/ # Partials da landing page
+-- routes/
| +-- web.php # 416 linhas de rotas web
| +-- api.php # Rotas da API v2
+-- storage/ # Uploads, cache, sessões, logs
+-- bootstrap/ # Arquivos de bootstrap do framework
Funções de Usuário
O FeedbackPulse possui quatro funções de usuário, armazenadas na coluna users.role:
| Função | Acesso | URL de Login |
|---|---|---|
superadmin | Controle total da plataforma (/admin/*) | /login |
tenant_admin | Controle total do tenant (/dashboard, /settings/*) | /login |
tenant_staff | Acesso limitado ao tenant (sem faturamento, sem exclusão) | /login |
customer | Somente portal do cliente (/customer/dashboard) | /customer/login |
Hierarquia de Funções
superadmin
+-- Pode impersonar qualquer tenant_admin
+-- tenant_admin
+-- Pode convidar tenant_staff
+-- Pode gerenciar faturamento, configurações, equipe
+-- tenant_staff
+-- Pode gerenciar envios, campanhas
+-- customer
+-- Pode ver seu próprio feedback
Ciclo de Vida da Requisição
Veja o que acontece quando uma requisição chega ao FeedbackPulse:
Requisição do Navegador
|
v
public/index.php
|
v
Laravel Kernel (pilha de middlewares)
|
+-- EnsureInstalled -> Redireciona para /install se não configurado
+-- SecurityHeaders -> Adiciona HSTS, CSP, X-Frame-Options
+-- VerifyCsrfToken -> Verifica token CSRF (exceto webhooks)
+-- ResolveTenant -> Determina o tenant atual
+-- Authenticate -> Verifica se o usuário está logado
+-- EnsureTenantAccess -> Verifica se o usuário pertence ao tenant
+-- EnsureTwoFactorVerified -> Verifica 2FA se habilitado
+-- CheckPlanLimit -> Impõe limites de recursos do plano
|
v
Controller (processa a requisição)
|
v
Blade View (renderiza HTML)
|
v
Resposta -> Navegador
Arquitetura do Banco de Dados
Tabelas Principais
| Tabela | Escopo | Finalidade |
|---|---|---|
tenants | Plataforma | Contas multi-tenant |
users | Plataforma | Todas as contas de usuário (todas as funções) |
plans | Plataforma | Planos de assinatura |
platform_settings | Plataforma | Configuração global chave-valor |
products | Tenant | Produtos de feedback |
feedback_campaigns | Tenant | Configurações de formulários de feedback |
feedback_submissions | Tenant | Entradas individuais de feedback |
feedback_tags | Tenant | Tags (many-to-many com envios) |
roadmap_items | Tenant | Itens do kanban de roadmap |
roadmap_votes | Tenant | Votos anônimos em itens do roadmap |
feature_requests | Tenant | Sugestões de funcionalidades da comunidade |
changelog_entries | Tenant | Notas de versão do produto |
team_members | Tenant | Registros de membros da equipe |
team_invitations | Tenant | Convites pendentes |
api_keys | Tenant | Chaves de acesso à API |
audit_logs | Plataforma | Trilha de auditoria de ações |
notifications | Plataforma | Notificações no aplicativo |
payment_events | Plataforma | Eventos de webhook Stripe/PayPal |
webhook_logs | Tenant | Logs de entrega de webhooks de saída |
data_deletion_requests | Tenant | Solicitações de exclusão GDPR |
landing_pages | Plataforma | Dados do construtor de landing page |
tenant_domains | Tenant | Mapeamentos de domínios personalizados |
referral_codes | Tenant | Códigos de indicação |
referral_conversions | Plataforma | Rastreamento de conversões de indicação |
cron_logs | Plataforma | Logs de execução de tarefas agendadas |
Índices-Chave
Todas as tabelas com escopo de tenant são indexadas em (tenant_id, created_at) para desempenho otimizado de consultas. A tabela feedback_submissions possui índices adicionais em status, product_id, campaign_id e sentiment_label.
Arquitetura de Segurança
| Camada | Proteção |
|---|---|
| Transporte | HTTPS imposto, cabeçalhos HSTS |
| Autenticação | Bcrypt (12 rounds), 2FA opcional (TOTP) |
| Autorização | Middleware baseado em função + classes de política |
| CSRF | Tokens CSRF do Laravel em todos os formulários |
| XSS | Auto-escape do Blade ({{ }}) |
| Injeção SQL | Consultas parametrizadas do Eloquent |
| Limitação de Taxa | Throttling por rota (5-120 req/min) |
| Segurança da API | Chaves de API com hash SHA256, limites de taxa por tenant |
| Segurança de Webhook | Verificação de assinatura HMAC (Stripe), proteção SSRF |
| Dados | Configurações sensíveis criptografadas em repouso |
| Sessões | Cookies criptografados, HTTP-only, seguros |
| Cabeçalhos | CSP, X-Frame-Options, X-Content-Type-Options |
Próximos Passos
- Glossário de Termos — entenda a terminologia
- Guia de Instalação — configure seu servidor
- Esquema do Banco de Dados — estruturas detalhadas das tabelas