7. Estrutura do Código Seção 7
7.1 Padrões Arquiteturais Adotados
🏗
Arquitetura atual: Por tratar-se de uma SPA em arquivo único (Vanilla JS), o sistema não segue formalmente Clean Architecture, DDD ou SOLID. No entanto, padrões pragmáticos foram aplicados consistentemente para manter a manutenibilidade do código.
🔧 Module Pattern (aplicado)
- Funções agrupadas por prefixo de módulo (
lic*, aud*, sc*)
- Estado privado via variáveis prefixadas com
_
- Constantes globais imutáveis (
LIC_TIERS, LIC_KPI_META)
- Funções utilitárias puras sem side effects (
calcLicScore, getLicTier)
🔄 Observer Pattern (parcial)
- Override de funções críticas para auto-registro (
audAvancarEtapa, salvarLicKpi)
- Delegação de eventos via
document.addEventListener com closest()
- Badge de alertas atualizado após carregamento via override de
carregarLicLeads
🗂 Repository Pattern (informal)
- Funções de carga isoladas:
carregarLicLeads(), carregarLicAuditoria()
- Dados sempre acessados via variáveis globais — nunca consultas diretas inline
- Re-fetch após mutação garante consistência da UI
🎨 Template Method (views)
- Views seguem padrão:
abrir*() → carregar*() → renderizar*()
- Separação de responsabilidade: UI (render) ≠ dados (carregar) ≠ lógica (calcular)
- Chart.js: destroy antes de recriar (evita memory leak)
7.2 Convenções de Nomenclatura
| Padrão | Uso | Exemplos |
lic* | Funções públicas do módulo Licenciamento | licAddWarehouse(), licToggleWms() |
_lic* | Funções privadas/internas do módulo Licenciamento | _licGoSec(), _licGetCoords() |
aud* | Funções do Pipeline de Auditoria | audAvancarEtapa(), audToggleCheck() |
sc* | Funções do Scorecard | kpiSaude(), kpiCorPaleta() |
dsp* | Funções do painel de Disponibilidade | getM2Disponivel(), executarMatchComercial() |
lc* | Funções do painel de Capacidade | abrirLicCapacidade(), renderizarLicCapacidade() |
LIC_* | Constantes globais do módulo (UPPER_SNAKE_CASE) | LIC_TIERS, LIC_KPI_META, LIC_AUDIT_STAGES |
baseLic* | Variáveis de estado global (arrays/objects) | baseLicLeads |
_lc* | Variáveis privadas de componente | _lcCharts, _licMapMarkers |
lf-* | IDs HTML de campos do formulário interno | lf-razao_social, lf-uf |
p-* | IDs HTML de campos do portal público | p-razao_social, p-cep |
lic-* | Classes CSS do módulo Licenciamento | lic-sec, lic-chip, lic-fc-head |
dsp-* | IDs HTML de componentes de Disponibilidade | dsp-kpi-disponivel, dsp-chart-regioes |
7.3 Organização dos Módulos JavaScript
O código do módulo Licenciamento está organizado em blocos funcionais dentro do <script> de index.html, delimitados por comentários de seção:
// ════════════════════════════════════════════════════════════════
// ── MÓDULO LICENCIAMENTO ─────────────────────────────────────────
// ════════════════════════════════════════════════════════════════
// [1] CONSTANTES E CONFIGURAÇÃO
const LIC_TIERS = [...]; // Configuração de tiers (Platina/Ouro/...)
const LIC_KPI_META = {...}; // Configuração dos 6 KPIs com thresholds
const LIC_AUDIT_STAGES = [...]; // 6 etapas do pipeline de auditoria
const LIC_HIST = {...}; // 12 tipos de evento do histórico
const LIC_ALERTA_TIPOS = {...}; // 9 tipos de alerta proativo
const LICENCIAMENTO_WHITELIST = [...]; // E-mails autorizados
// [2] ESTADO GLOBAL
let baseLicLeads = []; // Todos os leads
let _licPerfData = {}; // KPIs indexados por lead_id
let _audData = {}; // Auditoria indexada por lead_id
let _licHistData = {}; // Histórico indexado por lead_id
let _licPendingFiles = {}; // Arquivos pendentes de upload
let _licExistingAnexos = []; // Anexos carregados ao editar
// [3] FUNÇÕES DE CLASSIFICAÇÃO (puras — sem side effects)
function calcLicScore(lead) {...}
function getLicTier(lead) {...}
function licTierBadge(lead, compact) {...}
// [4] CRUD — Carregamento e persistência
async function carregarLicLeads() {...}
async function carregarLicHistorico(leadId) {...}
async function carregarLicAuditoria() {...}
async function carregarLicPerformance() {...}
// [5] FORMULÁRIO INTERNO (11 seções)
function abrirFormLead(id, returnTo) {...}
function fecharFormLead() {...}
function _licGoSec(idx) {...}
async function salvarLicLead() {...}
function _licGetFormData() {...}
function _licPreencherForm(lead) {...}
// [6] CEP E GEOCODIFICAÇÃO
function licMascaraCEP(input) {...}
async function licBuscarCEP(cep) {...}
// [7] ARMAZÉNS DINÂMICOS
function licAddWarehouse(data) {...}
function _licUpdateSummary() {...}
// [8] UPLOAD DE ANEXOS
function licFilesSelected(tipo, files) {...}
async function licSalvarTodosAnexos(leadId) {...}
async function licCarregarAnexos(leadId) {...}
// [9] DASHBOARD PRINCIPAL
function renderizarLicenciamento() {...}
function renderizarLicDashboard() {...}
// [10] MAPA INTERATIVO
async function abrirLicMapa() {...}
function _licInicializarMapa() {...}
function _licAtualizarChoropleth() {...}
function _licAtualizarMarkers() {...}
function _licMapAbrirPanel(lead) {...}
// [11] KANBAN DE LEADS
function abrirLicKanban() {...}
function renderizarLicKanban() {...}
async function _licKbMoverEtapa(id, etapa, motivo) {...}
// [12] SCORECARD DE PERFORMANCE
function abrirLicScorecard() {...}
function renderizarLicScorecard() {...}
async function salvarLicKpi() {...}
// [13] PIPELINE DE AUDITORIA
function abrirLicAuditoria() {...}
function renderizarLicAuditoria() {...}
async function audAvancarEtapa(leadId) {...}
async function emitirCertificado() {...}
// [14] PAINEL DE CAPACIDADE
function abrirLicCapacidade() {...}
function renderizarLicCapacidade() {...}
// [15] DISPONIBILIDADE COMERCIAL
function abrirLicDisponibilidade() {...}
function renderizarLicDisponibilidade() {...}
function executarMatchComercial() {...}
// [16] BOARD REPORT PDF
async function gerarBoardReport(e) {...}
function _buildBoardReportHtml(metrics) {...}
// [17] CENTRAL DE ALERTAS
function gerarLicAlertas() {...}
function abrirLicAlertas() {...}
function renderizarLicAlertas() {...}
// [18] HISTÓRICO DO LEAD (CRM TIMELINE)
async function registrarLicHistorico(...) {...}
function renderizarTimeline(registros, anexos, containerId) {...}
// [19] GERAÇÃO DE LINK DE PORTAL
async function licGerarLinkForm(leadId) {...}
async function licCriarEGerarLink() {...}
// [20] PDF INDIVIDUAL DO LEAD
async function gerarLicPDF(leadId) {...}
function _licBuildPDFHtml(lead, anexos, logoB64) {...}
7.4 Débito Técnico Mapeado
| # | Débito | Impacto | Prioridade | Solução recomendada |
| DT-001 | Single-file architecture (~11.000 linhas) | Manutenibilidade, colaboração, testes | Alta | Migrar para Vite + ES Modules (ver 12.2) |
| DT-002 | Ausência de testes automatizados | Risco de regressão em deploys | Alta | Playwright E2E + Vitest unitário |
| DT-003 | RLS permissivo (USING true) | Segurança — acesso irrestrito a dados | Média | RLS por e-mail + tabela de permissões |
| DT-004 | Estado global em variáveis soltas | Debugging difícil, race conditions | Média | Context API ou Zustand em migração React |
| DT-005 | Sem ambiente HML/DEV separado | Risco de contaminar dados de produção | Média | Projeto Supabase separado para staging |
| DT-006 | Whitelist hardcoded no JS | Manutenção requer deploy a cada mudança | Baixa | Tabela lic_permissoes no banco |
| DT-007 | Sem validação server-side de MIME type | Uploads maliciosos potenciais | Média | Supabase Edge Function de validação |
| DT-008 | PDFs gerados client-side (html2canvas) | Performance limitada, qualidade variável | Baixa | Puppeteer server-side (Edge Function) |
| DT-009 | Sem monitoramento de erros JS | Bugs em produção invisíveis | Média | Sentry.io (free tier) |
| DT-010 | Overrides de funções via wrapping JS | Debugging complexo, ordem de execução | Baixa | Event system centralizado na migração |
8.1 Performance Atual — Benchmarks
| Operação | Tempo medido | Condição | Meta |
| Carregamento inicial do sistema (login → dashboard) | 1.5–3s | Conexão 10 Mbps; 200 leads | < 3s |
| Carregamento da tela Licenciamento | 800ms–1.5s | Dados em cache + Supabase sa-east-1 | < 2s |
| Inicialização do mapa Leaflet + tiles | 1–2.5s | Primeira carga (tiles não cached) | < 3s |
| Busca de match comercial | < 50ms | Cálculo local em memória (sem rede) | < 500ms ✅ |
| Geração do Board Report PDF | 5–8s | html2canvas scale:2 + jsPDF | < 10s ✅ |
| Hover popup no mapa (ao passar o mouse) | < 100ms | Dados pré-carregados em memória | < 300ms ✅ |
| Lookup de CEP (BrasilAPI) | 300–800ms | Depende da latência da API | < 1.5s |
| Upload de arquivo (10 MB) | 2–8s | Supabase Storage sa-east-1 | < 10s ✅ |
8.2 Estratégias de Cache Implementadas
| Dado | Estratégia | Onde | Invalidação |
Todos os leads (baseLicLeads) | In-memory, carregado uma vez | JavaScript global | Após qualquer CRUD; re-fetch com carregarLicLeads() |
KPIs de performance (_licPerfData) | In-memory, carregado sob demanda | JavaScript global | Após salvarLicKpi(); sem invalidação automática |
Dados de auditoria (_audData) | In-memory, carregado sob demanda | JavaScript global | Após audAvancarEtapa() e emitirCertificado() |
| GeoJSON estados BR | Browser cache HTTP (1h) | Browser Cache-Control | URL imutável (GitHub CDN) |
| Tiles do mapa | Browser cache HTTP (automático) | Akamai/CARTO CDN | TTL do CDN (~1h) |
| Fotos dos armazéns | Cache de URLs em _licMapPhotoCache | JavaScript global | Ao reabrir o mapa |
| Alertas dispensados | localStorage (persistente) | Browser localStorage | Expiração mensal por ID |
| Sessão do usuário (JWT) | localStorage (SDK Supabase) | Browser localStorage | Expiração do JWT (1h) + refresh automático |
| Arquivos estáticos (CSS, JS, fonts) | Akamai CDN (GitHub Pages) | CDN global | Commit novo invalida hash |
8.3 Limites e Gargalos Identificados
// ── GARGALO 1: Carregamento de TODOS os dados na abertura ──
// Problema: carregarLicLeads() faz SELECT * sem paginação
// Impacto: >500 leads → timeout ou UI travada
// Solução: paginação server-side (limit/offset) + lazy loading
const { data } = await supabaseClient
.from('lic_leads')
.select('*') // ← sem LIMIT = carrega tudo
.order('created_at', { ascending: false });
// ── GARGALO 2: Charts destruídos e recriados a cada re-render ──
// Problema: renderizarLicDashboard() recria todos os 9 charts
// Impacto: layout shift visível; CPU pico em máquinas lentas
// Solução: atualizar data dos charts sem destruir (chart.data.datasets[0].data = ...)
Object.values(_licDCharts).forEach(c => {
try { c.destroy(); } catch(e) {} // ← destroy sempre = gargalo
});
// ── GARGALO 3: pdf html2canvas em thread principal ──
// Problema: captura de canvas é síncrona e bloqueia a UI
// Impacto: interface congela durante geração do Board Report
// Solução: Web Worker para processamento off-thread
// ── GARGALO 4: renderizarTimeline com merge de arrays ──
// Problema: combina historico[] + anexos[] a cada abertura do painel
// Impacto: imperceptível agora, O(n log n) com muitos registros
// Solução: cache do resultado por lead_id
8.4 Otimizações Prioritárias
Paginação server-side dos leads
Implementar limit(50).offset(page * 50) na query de leads. Adicionar botão "Carregar mais" ou scroll infinito na tabela. Impacto direto quando >200 leads.
Atualização incremental dos charts
Substituir chart.destroy() + new Chart() por chart.data.datasets[0].data = novosValores; chart.update(). Elimina layout shift e reduz CPU em ~60%.
Lazy loading de módulos pesados
Carregar Leaflet, jsPDF e html2canvas apenas quando o usuário acessar Mapa ou gerar PDF pela primeira vez (import dinâmico ou tag <script defer> condicional).
MarkerCluster no mapa
Para redes com >100 licenciados, implementar L.markerClusterGroup() (Leaflet.markercluster). Mantém performance do mapa com qualquer volume de pontos.
Seleção de colunas específicas no SELECT
Substituir select('*') por select('id,razao_social,status,uf,area_total_m2,fee_mensal,etapa') nas queries de dashboard. Reduz payload em até 70%.
9. Logs e Monitoramento Seção 9
9.1 Matriz de Observabilidade
| Dimensão | Status | Ferramenta | Cobertura | Ação necessária |
| Logs de API | ✅ | Supabase Dashboard | Todas as chamadas REST | Nenhuma |
| Logs de autenticação | ✅ | Supabase Dashboard | Login, logout, falhas | Nenhuma |
| Logs de banco | ✅ | Supabase Postgres Logs | Queries lentas, erros | Nenhuma |
| Auditoria de negócio | ✅ | lic_historico (banco) | Eventos críticos de negócio | Nenhuma |
| Logs de deploy | ✅ | GitHub Actions | Build e deploy history | Nenhuma |
| Erros JavaScript | ❌ | Não implementado | Zero visibilidade | Implementar Sentry.io |
| Métricas de uso | ❌ | Não implementado | Zero visibilidade | Implementar Plausible ou Supabase Telemetry |
| Alertas proativos | ⚠ | Supabase (plano) | Apenas limites de plano | Implementar UptimeRobot |
| Performance frontend | ❌ | Não implementado | Zero visibilidade | Core Web Vitals via Lighthouse CI |
Implementação recomendada — Sentry.io (Fase 1 de evolução)
// Adicionar no <head> do index.html
<script>
Sentry.init({
dsn: "https://xxx@sentry.io/yyy",
environment: location.hostname === 'pipelinevendemmia.com.br'
? 'production' : 'development',
tracesSampleRate: 0.1, // 10% das transações para APM
beforeSend(event) {
// Sanitiza dados sensíveis antes de enviar
if (event.user) delete event.user.email;
return event;
}
});
</script>
// Captura manual em pontos críticos
try {
await salvarLicLead();
} catch(e) {
Sentry.captureException(e, {
tags: { modulo: 'licenciamento', acao: 'salvar_lead' },
user: { email: EMAIL_USUARIO_LOGADO }
});
showToast('Erro ao salvar. Nossa equipe foi notificada.', 'error');
}
10. Deploy e DevOps Seção 10
10.1 Pipeline de Deploy Atual
╔══════════════════════════════════════════════════════════════╗
║ PIPELINE DE DEPLOY ATUAL ║
╚══════════════════════════════════════════════════════════════╝
Developer workstation
│
├─ Edita index.html (ou arquivos Licenciamento/)
│
├─ git add . && git commit -m "feat: ..."
│
└─ git push origin main
│
▼
GitHub Repository (github.com/Gueilee/pipeline-comercial)
│
├─ GitHub Actions detects push to main (~2s)
│
├─ Pages build job (~20-30s)
│ ├─ Copies static files
│ ├─ Configures custom domain
│ └─ Invalidates Akamai cache
│
└─ Deploy complete (~60s total)
│
▼
pipelinevendemmia.com.br ← atualizado globalmente
10.2 Estratégia de Versionamento
| Convenção | Formato | Exemplos |
| Commits | Conventional Commits | feat: adicionar scorecard, fix: corrigir cálculo de m², docs: especificação técnica |
| Co-autor | Trailler no commit | Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> |
| Releases | Não implementado formalmente | Recomendado: git tag v1.0.0 a cada sprint |
| Hotfix | Commit direto em main + push | Recomendado: branch hotfix/desc + PR |
10.3 Procedimentos de Rollback
# Rollback imediato (revert do último commit)
git revert HEAD --no-edit
git push origin main
# Deploy automático em ~60 segundos
# Rollback para versão específica
git log --oneline -10 # identifica o commit-alvo
git revert HEAD~3..HEAD --no-edit # reverte os últimos 3 commits
git push origin main
# Hotfix de emergência (sem histórico de revert)
git reset --hard HEAD~1 # CUIDADO: perde o commit localmente
git push origin main --force-with-lease # força push seguro
# Verificar se o rollback chegou ao usuário
curl -I https://pipelinevendemmia.com.br/index.html
# Verificar header ETag — mudou = cache foi invalidado
11. Requisitos Não-Funcionais Seção 11
⚡Performance
| Métrica | Alvo | Status atual |
| First Contentful Paint (FCP) | < 1.5s | ✅ ~1.2s |
| Time to Interactive (TTI) | < 3.5s | ✅ ~2.8s |
| Latência de chamadas à API Supabase | < 200ms (p95) | ✅ ~120ms (sa-east-1) |
| Renderização do dashboard de leads | < 500ms | ✅ <400ms |
| Geração do Board Report PDF | < 10s | ✅ 5–8s |
| Busca de match comercial (filtro local) | < 100ms | ✅ <50ms |
| Inicialização do mapa Leaflet | < 3s | ✅ <2.5s |
🌐Disponibilidade e SLA
| Componente | SLA contratado | Downtime máx./mês | Fonte |
| GitHub Pages (CDN) | 99.9% | 43 minutos | Akamai SLA |
| Supabase Database (Pro) | 99.9% | 43 minutos | Supabase SLA |
| Supabase Storage | 99.9% | 43 minutos | Supabase SLA |
| BrasilAPI (CEP) | Sem SLA formal | — | Open source |
| CartoDB (Tiles) | Sem SLA formal | — | CARTO ToS |
| SLA composto estimado | ~99.8% | ~87 min | Produto dos SLAs |
👥Concorrência e Capacidade
| Métrica | Capacidade atual | Limite técnico |
| Usuários simultâneos (dashboard) | Testado: 5 usuários | Supabase Pro: 200 conexões simultâneas ao DB |
| Usuários simultâneos (portal público) | Ilimitado (estático) | CDN Akamai: sem limite prático |
| Volume de leads sem degradação | 200 leads testados | ~2.000 leads (estimado) |
| Arquivos por lead | Sem limite | Supabase Storage: 100 GB total |
| Requisições API/segundo | — | Supabase Pro: 500 req/s |
📱Usabilidade e Compatibilidade
- Browsers suportados: Chrome 100+, Firefox 100+, Edge 100+, Safari 15+
- Dispositivos — sistema interno: Desktop/notebook apenas (responsive não otimizado para <1024px)
- Dispositivos — portal público: Responsivo e funcional em smartphones (320px–2560px)
- Idioma: Português Brasileiro (pt-BR) — sem suporte a múltiplos idiomas
- Acessibilidade: Não implementado formalmente (WCAG 2.1 não avaliado)
- PWA: Não implementado — sem service worker nem manifest
12. Plano Técnico de Evolução Seção 12
12.1 Curto Prazo — 0 a 3 meses
EV-001Monitoramento de erros JavaScript (Sentry)Esforço: 4h
Problema
Erros JavaScript em produção são invisíveis — sem notificação quando o sistema falha para o usuário.
Solução
- Integrar Sentry.io via CDN (free tier: 5k erros/mês)
- Configurar
beforeSend para sanitizar e-mails e dados sensíveis - Adicionar contexto de usuário e módulo ativo em cada erro
Resultado esperado
- Alertas por e-mail quando qualquer erro JS ocorrer
- Stack trace completo com contexto do usuário
- Dashboard de erros com frequência e impacto
EV-002Ambiente de homologação (Supabase projeto staging)Esforço: 1 dia
Problema
Desenvolvimento acontece diretamente contra o banco de produção — risco de contaminar dados reais.
Solução
- Criar projeto Supabase separado para staging (free tier)
- Adicionar detecção de ambiente:
location.hostname === 'pipelinevendemmia.com.br'
- Branch
staging no GitHub com deploy automático para URL separada
EV-003RLS granular por e-mail de usuárioEsforço: 2 dias
Problema
Políticas RLS permissivas (USING true) permitem acesso irrestrito ao banco por qualquer usuário autenticado.
Solução
- Criar tabela
lic_permissoes (email TEXT PRIMARY KEY, nivel TEXT, ativo BOOLEAN)
- Atualizar políticas RLS para
USING (auth.email() IN (SELECT email FROM lic_permissoes WHERE ativo = true))
- Remover whitelist hardcoded do JavaScript
12.2 Médio Prazo — 3 a 9 meses
EV-004Migração para Vite + módulos ES (decomposição do single-file)Esforço: 3-4 semanas
Problema
11.000+ linhas em um único arquivo torna colaboração, testes e manutenção progressivamente mais difíceis.
Solução — Estrutura de módulos proposta
src/
├── main.js // entry point
├── supabase.js // client singleton
├── auth/
│ └── auth.js
├── licenciamento/
│ ├── index.js // exports públicos
│ ├── leads.js // CRUD de leads
│ ├── tiers.js // classificação
│ ├── formulario.js // formulário 11 seções
│ ├── mapa.js // Leaflet + choropleth
│ ├── kanban.js // kanban de leads
│ ├── scorecard.js // KPIs
│ ├── auditoria.js // pipeline de auditoria
│ ├── historico.js // CRM timeline
│ ├── alertas.js // central de alertas
│ ├── disponibilidade.js // match comercial
│ └── reports/
│ ├── board-report.js // PDF executivo
│ └── lead-pdf.js // PDF individual
├── portal/ // portal público (standalone)
└── shared/
├── toast.js
├── cep.js
└── storage.js
Resultado esperado
- Possibilidade de testes unitários por módulo
- Tree-shaking: bundle final ~40% menor
- Hot Module Replacement durante desenvolvimento
- Colaboração sem conflitos de merge no mesmo arquivo
EV-005Testes automatizados com PlaywrightEsforço: 2 semanas
Casos de teste críticos (prioridade E2E)
- Login com credenciais válidas → dashboard carrega
- Criar novo lead → aparece na tabela
- CEP válido → campos de endereço preenchidos automaticamente
- Avançar auditoria com checklist completo → etapa muda
- Gerar link de portal → lead recebe form_token no banco
- Board Report → arquivo PDF baixado
- Alertas → badge mostra contagem correta
CI integration
# .github/workflows/tests.yml
on: push
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npx playwright install chromium
- run: npx playwright test
env:
TEST_BASE_URL: "https://staging.pipelinevendemmia.com.br"
EV-006Edge Functions para validação e processamento server-sideEsforço: 1 semana
Use cases para Edge Functions (Deno)
- Validação de MIME type: Interceptar upload e rejeitar tipos inválidos antes de gravar no Storage
- Webhook de formulário preenchido: Enviar e-mail automático ao comercial quando portal é concluído
- Geração de PDF server-side: Puppeteer no servidor substitui html2canvas client-side
- Auditoria de alterações: Trigger que registra automaticamente qualquer UPDATE em
lic_leads
// supabase/functions/notify-form-filled/index.ts
import { serve } from "https://deno.land/std/http/server.ts";
serve(async (req) => {
const { record } = await req.json(); // webhook payload
if (record.form_status === 'concluido') {
await sendEmail({
to: 'comercial@vendemmia.com.br',
subject: `Formulário preenchido: ${record.razao_social}`,
body: `Acesse: https://pipelinevendemmia.com.br`
});
}
return new Response('ok');
});
12.3 Longo Prazo — 9 a 24 meses
EV-007Integração bidirecional com WMS dos licenciadosEsforço: 2-3 meses
Objetivo
Eliminar lançamento manual de KPIs no Scorecard. Dados de OTIF, acuracidade e utilização são importados automaticamente dos sistemas WMS dos parceiros via API REST ou EDI.
Arquitetura proposta
- API Webhook no Supabase Edge Function para receber dados dos WMS
- Tabela
lic_kpi_raw para dados brutos antes de processamento
- Cron job (Supabase Scheduled Functions) para consolidar em
lic_performance
- Autenticação por API key por parceiro (tabela
lic_api_keys)
EV-008App móvel para auditores de campoEsforço: 3-4 meses
Objetivo
Permitir que auditores completem checklists, tirem fotos e registrem relatórios de visita técnica diretamente no campo, sem notebook.
Stack proposta
- React Native + Expo — compartilha lógica com o web app
- Supabase JS SDK — mesma API, zero adaptação de backend
- Offline-first: checklist funciona sem internet; sincroniza ao reconectar
- Camera API: fotos diretamente uploadadas ao Storage
lic-anexos
EV-009Multi-tenancy para a rede (um Pipeline por licenciado)Esforço: 4-6 meses
Objetivo
Cada licenciado ativo acessa um painel próprio para visualizar sua performance, ocupação, clientes alocados e documentos — sem ver dados de outros licenciados.
Mudanças arquiteturais
- Adicionar
tenant_id em todas as tabelas
- RLS por tenant:
USING (tenant_id = auth.uid()::bigint)
- Subdomínio por licenciado:
parceiro-abc.pipelinevendemmia.com.br
- Portal público evolui para portal do licenciado (autenticado)
12.4 Arquitetura-Alvo (Versão 3.0 — 24 meses)
╔══════════════════════════════════════════════════════════════╗
║ ARQUITETURA-ALVO (versão 3.0) ║
╚══════════════════════════════════════════════════════════════╝
┌─────────────────────────────────────────────────────────────┐
│ CLIENTES │
│ Browser (React SPA) │ Mobile (React Native) │ Portal │
└───────────┬───────────┴──────────┬──────────────┴────┬─────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────┐
│ API GATEWAY (Supabase) │
│ Auth (JWT) │ PostgREST │ Storage │ Realtime (WS) │
└──────────────┬──────────────┬──────────┴───────────────────┘
│ │
┌──────────▼──┐ ┌──────▼──────────────────────────────┐
│ PostgreSQL │ │ Edge Functions (Deno) │
│ 17 │ │ - PDF generation (Puppeteer) │
│ 5 tabelas │ │ - Email notifications │
│ lic_* │ │ - MIME validation │
│ RLS por │ │ - WMS webhook processor │
│ tenant │ │ - Scheduled KPI sync │
└─────────────┘ └──────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ INFRAESTRUTURA │
│ │
│ GitHub Pages (CDN) │ Supabase Cloud (sa-east-1) │
│ React SPA (Vite build) │ PostgreSQL managed │
│ Akamai CDN global │ Storage S3-compatible │
│ SSL automático │ Auth + Edge Functions │
│ │ Backups automáticos PITR │
├─────────────────────────┴────────────────────────────────── │
│ CI/CD: GitHub Actions │
│ Tests: Playwright E2E + Vitest unit │
│ Monitoring: Sentry + UptimeRobot + Supabase Dashboard │
│ Alertas: PagerDuty (via Sentry) para erros críticos │
└─────────────────────────────────────────────────────────────┘
Glossário Técnico Anexo A
| Termo | Definição |
BaaS | Backend as a Service — plataforma que fornece backend completo (banco, auth, storage) sem servidor próprio. Ex: Supabase, Firebase |
PostgREST | Servidor que gera automaticamente uma API REST completa a partir de um schema PostgreSQL |
RLS | Row Level Security — controle de acesso granular por linha em PostgreSQL, executado no banco antes de qualquer query |
JWT | JSON Web Token — token de autenticação assinado digitalmente; contém claims do usuário e expira em tempo determinado |
SPA | Single Page Application — aplicação web onde toda a UI é renderizada no browser; apenas dados trafegam entre cliente e servidor |
JAMstack | Arquitetura web: JavaScript + APIs + Markup. Frontend estático, backend como serviços externos via API |
CDN | Content Delivery Network — rede de servidores geograficamente distribuídos que servem conteúdo estático com baixa latência |
Edge Function | Função serverless executada próxima ao usuário (edge da rede). Supabase usa Deno como runtime |
html2canvas | Biblioteca que renderiza elementos HTML em um canvas, permitindo captura como imagem para geração de PDF client-side |
GeoJSON | Formato JSON para representar dados geográficos (pontos, linhas, polígonos). Usado para o choropleth de estados do Brasil |
Choropleth | Mapa temático onde regiões são coloridas proporcionalmente a um valor quantitativo |
PITR | Point-in-Time Recovery — restauração do banco para qualquer momento nos últimos N dias a partir dos WAL logs |
WAL | Write-Ahead Log — log de transações do PostgreSQL; base para replicação e PITR |
Débito técnico | Custo futuro de retrabalho gerado por decisões de implementação subótimas tomadas agora por conveniência ou velocidade |
pgBouncer | Pool de conexões do PostgreSQL — o Supabase usa para gerenciar conexões simultâneas ao banco sem overhead |
Histórico de Revisões Anexo B
| Versão | Data | Fase | Descrição | Autor |
| 1.0 | Maio 2026 | Fase 1 | Arquitetura geral, stack tecnológica, state management, modelagem completa de banco de dados (5 tabelas + índices + RLS) | Arquitetura Vendemmia / Claude Sonnet |
| 1.0 | Maio 2026 | Fase 2 | APIs PostgREST (endpoints CRUD completos), Supabase Auth API, Storage API, 5 APIs externas, tratamento de erros, segurança (JWT, RLS, LGPD, vulnerabilidades), infraestrutura (hosting, CI/CD, ambientes, monitoramento, backup/DR) | Arquitetura Vendemmia / Claude Sonnet |
| 1.0 | Maio 2026 | Fase 3 | Estrutura do código (17 módulos + convenções), 10 débitos técnicos mapeados, benchmarks de performance, estratégias de cache, 5 gargalos identificados, observabilidade, pipeline de deploy, RNF (SLA, concorrência, compatibilidade), plano de evolução (9 itens em 3 horizontes) e arquitetura-alvo versão 3.0 | Arquitetura Vendemmia / Claude Sonnet |
✅ Especificação Técnica ET-LIC-2026-001 — Documento Completo (3 fases)
Fase 1 · Fase 2 · Fase 3 — Módulo de Licenciamento · Pipeline Vendemmia · Versão 1.0 · Maio 2026
APROVADO PARA PRODUÇÃO
PIPELINE by Vendemmia
ET-LIC-2026-001 · Versão 1.0 · Fase 3/3 — DOCUMENTO TÉCNICO FINAL
Confidencial — Vendemmia Comércio Internacional Ltda.
pipelinevendemmia.com.br · Maio 2026