📍 Origem:
times/produto/cadencia/foundation/tech-principles.mdnopd-framework. Última sync: 2026-05-25.
Tech Principles — Cadência¶
8 princípios técnicos não-negociáveis. Trocar qualquer um exige ADR formal + decisão Felipe + entrada em
../memory/decisions.md.Extraídos de:
SOUL.md§ Princípios técnicos +CLAUDE.mdrepo cadencia-app + decisões históricas.
1. Multi-tenant nativo desde V1¶
Princípio: RLS Supabase em todas as tabelas que armazenam dados de tenant. Sem exceção. Não existe "modo single-tenant" no produto.
Por quê: Cadência nasceu multi-tenant. Migração para multi-tenant em produto single-tenant é custo proibitivo. Construir multi-tenant first elimina classe inteira de bugs e vazamentos.
Como aplicar: - Toda nova tabela = RLS + policy de isolation por tenant_id - Toda query do cliente final = via JWT com tenant_id claim - Service role só em scripts admin/cron, nunca path do usuário - Storage paths sempre prefixados com <tenant_id>/
Detalhes: multi-tenant-strategy.md.
2. Supabase é source of truth¶
Princípio: PostgreSQL Supabase é fonte única de verdade. DB + Storage + Auth. Não duplicar estado em Redis, cache externo, ou outro DB.
Por quê: Multi-store gera sincronização eventual e bugs de consistência. PostgreSQL aguenta o volume Cadência. RLS resolve isolation. Storage Supabase é integrado.
Como aplicar: - Sem Redis cache de leitura no path principal (usar Postgres + PostgREST) - Sem DB secundário (MongoDB, Firestore, etc) - Storage = Supabase Storage (não S3 separado) - Auth = Supabase Auth (não Auth0/Cognito)
Exceções permitidas: - Sentry (errors externos) - Mixpanel/PostHog/GA4 (analytics — duplicação esperada) - Stripe (transações com source of truth próprio) - Resend, Stripe e providers de canal (cada um é fonte de verdade dos próprios eventos externos)
3. Frontend Vercel main, Workers Coolify VPS Master master (migrando Coolify)¶
Princípio: dois pipelines de deploy, sincronizados por git push origin main:master.
Por quê: Frontend e workers têm ritmos de release diferentes. Frontend pode deployar 10x/dia, workers idealmente menos. Separação evita downtime de UI quando worker quebra.
Como aplicar: - Push em main → Vercel deploy frontend automático - Push em master (espelhamento de main) → Coolify VPS Master deploy workers - Comando padrão pós-push: git push origin main:master - Pós-push: validar vercel ls | head -3 Ready e logs Coolify sem erro
Migração ativa: Railway → Coolify VPS Master (PDL-18 a 23 cadeia). Após migração, master push vai para Coolify.
4. CRM nativo e provider por canal¶
Princípio: o CRM Cadencia é a fonte de verdade; cada canal usa uma integração especializada atrás de contratos próprios.
Por quê: contatos, empresas, oportunidades, pipelines, tags, scoring e cadências precisam compartilhar o mesmo modelo multi-tenant e as mesmas garantias de RLS. Email, WhatsApp e publicação social têm requisitos externos diferentes e evoluem sem reescrever o CRM.
Como aplicar: - CRM e cadências → Supabase PostgreSQL - Email transacional e marketing → Resend, com eventos Svix - WhatsApp e agenda → Lara/Evolution, sempre por tenant - Social → provider específico do canal - Estado só avança depois da confirmação do writer ou provider
Anti-padrões: - ❌ Duplicar o estado canônico do CRM em um provider - ❌ Usar credencial, sender ou instância global como fallback entre tenants - ❌ Marcar envio, publicação ou etapa como concluída antes da confirmação externa
5. Renderer Playwright HTML→PNG¶
Princípio: carrosséis e covers são HTML renderizado para PNG via Playwright. 1080×1440. 7 famílias template. 11 presets visuais. 29 modelos YAML.
Por quê: HTML/CSS dá flexibilidade visual incomparável. Playwright headless garante consistência cross-browser. PNG é universal pra Instagram/LinkedIn/blog. SVG/Canvas/lib JS = limitação de tipografia e composição.
Como aplicar: - Templates novos = HTML + CSS + variáveis injetáveis - Cover Identity Lock = HTML + foto Gemini-generated + composição - Tests visuais: tests/visual/test_slide_contrast.py (40/40 PASS antes de push) - Output → Supabase Storage
Não substituir por: - ❌ Canvas API JavaScript - ❌ Libs tipo Sharp/Jimp pra composição - ❌ Templates Figma exportados - ❌ SVG renderizado pelo browser
6. LLM stack fixa (trocar exige ADR)¶
Princípio: OpenAI (texto via OpenRouter), Gemini 2.5 Flash (capas + Identity Lock), Apify (análise IG), Pexels (fallback stock). Trocar qualquer um = ADR formal.
Por quê: trocar LLM sem critério gera regressões caras (prompt engineering, validação de output, refatoração agents). Cada provider tem trade-off claro. OpenAI/OpenRouter já tem prompts otimizados; Gemini Identity Lock é único; Apify scrape IG estável; Pexels free tier suficiente.
Como aplicar: - Mudança de modelo (gpt-5 → gpt-6) sem ADR — OK se mesmo provider - Mudança de provider (OpenAI → Anthropic) — exige ADR - Provider novo (ex: Vertex AI) — exige ADR + benchmark documentado
PR ativo: #2 — OpenRouter via OPENAI_BASE_URL/OPENAI_MODEL (ainda no domínio OpenAI compat, sem ADR).
7. Pipeline 7-step orchestrator é contrato¶
Princípio: Research → Model Selector → Headline → Carousel → Caption → Cover → Renderer é a espinha dorsal. Features novas se encaixam como steps adicionais — não substituem.
Por quê: orchestrator é estável, testado, validado em produção. Substituir = retrabalho monumental + risco de regressão. Adicionar step novo = baixo custo + composição limpa.
Como aplicar: - Feature nova de geração = step novo (ex: video transcript step) ou pré/pós-processing - Mudança no fluxo (ordem dos 7 steps) = ADR formal - Steps podem ser opt-in por plano (Growth Pro tem step Remotion)
Anti-padrões: - ❌ Pipeline paralelo separado (mantém o orchestrator único) - ❌ Bypass do Model Selector (sempre passa pelos 12 flags) - ❌ Renderer custom por feature (sempre Playwright HTML→PNG)
8. Validar antes de declarar pronto¶
Princípio: compilou ≠ testou. Build ≠ validação. Lint ≠ QA.
Por quê: histórico documentado de incidents (Vercel 6+7 deploys falhando silenciosos, P0 NameError, 38 bugs renderer, textos invisíveis recorrentes). Compilar é mínimo necessário — não suficiente.
Como aplicar (checklist obrigatório):
[ ] npm run build → ZERO erros (não-Sentry)
[ ] Se mexeu no renderer: python tests/visual/test_slide_contrast.py → 40/40 PASS
[ ] Rendi 1 post real local via Playwright OU declarei explicitamente que NÃO testei
[ ] Se NÃO consegui testar: avisei Felipe ANTES de pushar
Pós-push:
[ ] vercel ls | head -3 → Ready (não Error)
[ ] Se backend Python: git push origin main:master + logs Coolify
Pós-deploy VPS (qualquer projeto):
[ ] python3 -c 'compile(open("ARQUIVO").read(), "test", "exec")'
[ ] Dry-run com dados reais: importar funções, chamar queries, verificar output
[ ] Se cron: crontab -l confere o schedule
[ ] Se NÃO consegui dry-run: avisar Felipe
Honestidade obrigatória: se não testou, dizer "compilou mas NÃO testei". Sem desculpa. Skill /validar-deploy-vps automatiza checklist.
Princípios meta (sobre os princípios)¶
Como atualizar¶
- Decisão Felipe explícita
- ADR formal em
cadencia-app/docs/adr/NNNN-<descricao>.md - Entrada em
../memory/decisions.md - Atualização deste doc + git commit referenciando ADR
Quando NÃO seguir¶
Princípio só é violável com: - ADR documentando trade-off - Aprovação Felipe explícita - Plano de retorno ao princípio (se for exceção temporária)
Senão, princípio vence — sempre.
Refs¶
../SOUL.md§ Princípios técnicosmulti-tenant-strategy.md(princípio 1)tech-architecture.md(princípios 2, 3, 5, 6, 7)cadencia-app/CLAUDE.md(princípio 8 — checklist completo)cadencia-app/docs/adr/0001-stripe-em-vez-de-asaas.mdcadencia-app/docs/incidentes/(histórico que origina princípio 8)