Settings
Status: 🟢 Estável (identidade + branding + pixel + compliance + domínios) Code: backend/app/modules/settings UI: frontend/src/app/(admin)/[slug]/admin/settings Última revisão deste doc: 2026-05-13 por Felipe + Claude Dependências fortes: fonte de kill switches centrais (council, agents, ai_auto_reply); custom domains com Traefik
1. Identidade
O que faz (uma frase)
Configurações por tenant: identity (nome, logo, contato, kill switches Conselho/Agentes), branding (cores, fonts), pixels (Meta, GA4, GTM, TikTok, Hotjar, Clarity, LinkedIn), compliance (LGPD, DPO), custom domains (DNS verification + Traefik YAML), legal entities (CNPJs lado vendedor).
Por que existe (negócio)
Sem este módulo:
- Branding hardcoded.
- Pixels manuais em cada landing page.
- Sem self-service de domínio próprio.
- Compliance docs avulsos.
Com Settings:
- Mais Consciente customiza visual completo (cores, logo).
- Pixel Meta + GA4 + Hotjar setado uma vez → todas as páginas aplicam.
go.maisconsciente.com.brcadastrado → DNS verify → Traefik provisiona SSL automaticamente.- LGPD compliance documentada (DPO, controlador, base legal, retention).
Status atual
Em prod, tudo deployado. Kill switches separados (Conselho council_enabled vs Agentes ai_auto_reply_enabled) — memória [[conselho-e-agentes-kill-switches-separados]].
2. Cases de uso reais
Case 1: Felipe customiza branding
UI → cores primária/secundária/accent → save → PUT /branding upsert → tenant.branding propagado pra UI via GET /public-bundle (SSR Next).
Case 2: Custom domain go.maisconsciente.com.br
- UI
/settings/domains→ "Adicionar" → backend geraverification_token. - Felipe coloca TXT
_mandir-verify.go.maisconsciente.com.br=<token>no DNS. - Beat
check_pending_domains(10min) → DNS lookup → match → status=active + Redis update + Traefik YAML escrito + SSL provision. go.maisconsciente.com.brresolve pra Suite.
Case 3: Kill switch Conselho
Felipe vai pra /admin/council/advisors → toggle "Conselho" off → PATCH /api/council/settings {council_enabled: false} → próxima @conselho no grupo é silenciosamente ignorada.
3. Oportunidades de negócio
- Whitelabel completo: branding + custom domain + pixel = produto sob marca própria do cliente.
- DNS as a service: wizards step-by-step por registrar (Namecheap, GoDaddy, Registro.br) — UX killer.
- Compliance pack vendido: LGPD docs prontos pra setores regulados.
4. Arquitetura interna
Arquivos
models.py— 6 tabelas.service.py(~500 linhas).tasks.py—check_pending_domains(Beat 10min).routes.py— 22 endpoints.
Tasks
| Task | Schedule | O que faz |
|---|---|---|
settings.check_pending_domains | Beat 10min | DNS lookup _mandir-verify.<domain> → escreve Traefik YAML + Redis |
5. Tabelas (6)
settings_identity ⭐
| Coluna | Notas |
|---|---|
tenant_id | UNIQUE |
display_name / logo_url / tagline / contact_email / contact_whatsapp | |
ai_auto_reply_enabled | Kill switch Agentes (default true) |
council_enabled | Kill switch Conselho (default true) — independente |
settings_branding
Cores (primary, secondary, accent), fonts, custom CSS. UNIQUE per tenant.
settings_pixel
| Coluna | Notas |
|---|---|
provider | meta / ga4 / gtm / tiktok / hotjar / clarity / linkedin |
pixel_id | |
server_token | NUNCA retornado em GET (só configurado, never fetched via API) |
is_active |
UNIQUE (tenant_id, provider).
settings_compliance
LGPD: privacy_policy_url, terms_url, dpo_name, dpo_email, controller, legal_basis, CNPJ company info. UNIQUE per tenant.
settings_domain
| Coluna | Notas |
|---|---|
domain | UNIQUE GLOBAL |
verification_token | TXT record |
status | pending / verifying / active / failed |
ssl_status | pending / issued / failed |
service_type | all / student_area / links / landing_pages / forms / surveys / email_tracking / admin |
is_primary |
settings_legal_entity
CNPJs do tenant (lado vendedor). UNIQUE (tenant_id, cnpj).
Relacionamentos cross-módulo
| Direção | Outro módulo | Como |
|---|---|---|
| ↘ Lê | council | _council_enabled() lê council_enabled |
| ↘ Lê | agents | _ai_auto_reply_enabled() lê ai_auto_reply_enabled |
| ↘ Escreve | Traefik filesystem | Custom domains → YAML dinâmico |
| ↘ Escreve | Redis | Domain → tenant_id mapping |
6. API / Endpoints (22)
Prefixo /api/settings.
Identity / Branding / Compliance (6)
GET/PUT /identity, /branding, /compliance (upsert).
Pixels (3)
GET /pixels, PUT /pixels (upsert por provider), DELETE /pixels/{provider}.
Domains (5)
GET/POST /domains, PUT /domains/{id}, POST /domains/{id}/verify, GET /domains/{id}/dns-instructions (passo-a-passo por registrador), DELETE /domains/{id}.
Legal Entities (4)
GET/POST/PATCH/DELETE /legal-entities.
Public Bundle (1)
GET /public-bundle — chamado SSR Next, sem secrets.
7. Configuração
Env vars
| Var | Propósito |
|---|---|
MANDIR_TRAEFIK_DYNAMIC_DIR | /data/coolify/proxy/dynamic/mandir |
MANDIR_TRAEFIK_CERT_RESOLVER | letsencrypt-cf / letsencrypt-google |
MANDIR_VASUDEVA_HOST / MANDIR_VASUDEVA_USER | SSH remoto |
MANDIR_API_INTERNAL_HOST / MANDIR_APP_INTERNAL_HOST | Hostname interno |
8. Operações + Troubleshooting
Sintoma: Domain stuck em pending
Diagnóstico: Verificar TXT record DNS — dig TXT _mandir-verify.<domain>.
Fix: Garantir TXT registrado, aguardar propagação (até 24h), wait beat ou re-trigger POST /domains/{id}/verify.
Sintoma: SSL não emitiu
Causa: Let's Encrypt rate limit ou DNS propagation lag. Fix: Aguardar 5-10min após status=active.
9. Limitações e débitos técnicos
| # | Item |
|---|---|
| 1 | DNS verification race — alteração entre check cycles |
| 2 | Traefik priority 8500 hardcoded |
| 3 | SSL pending lag visível |
| 4 | Redis domain TTL 2h — beat off-line > 2h quebra resolution |
| 5 | Pixel server_token redaction |
10. Histórico
Em prod desde Suite v2. Kill switch Conselho separado em mig 0111 (memória [[conselho-e-agentes-kill-switches-separados]]).