Fix header alignment and rhythm, swap Megaphone for CampaignLogo, add progressive disclosure for first access, and extract shared auth shells with corrected individual-account copy; record closed critique items in RS+.
77 KiB
Roadmap — Teqo
Atualizado em: 2026-07-19 (MVP + Ciclo 2 deployados; A2 entregue; A4 Baseline no produto + Gap vs 2022 implementado e mesclado em main (Fases 2–4 + simplify); A7 Fase 1 entregue (agregação drizzle ranking federal; merge pendente; Fases 2–5 pendentes — F4 lista+coroplético pós-B3; F5 batch flip/leverage na lista pós-A5 via capture-review-debts) — plano; C2 engenharia pronta e mesclada em main; C3 Planos de Ação implementado e mesclado em main; C6 Escala e DRY pós-C2 implementado e mesclado em main (Fases 1–5 + simplify); C7 Escala e DRY pós-C3 implementado (Fases 1–5; feed O(n) condicional fora de escopo); C8 Escala e DRY pós-C6 implementado e mesclado em main (Fases 1–4 + duas passagens /simplify); C9 Escala e DRY pós-C8 implementado e mesclado em main (Fases 1–4 + simplify); C10 registrado — escala/DRY pós-C9 do /simplify; C11 registrado — escala/DRY pós-C7 do /simplify — plano; B2 fundação de geometrias do mapa entregue; B5 registrado — escala/DRY pós-B2 (F1 ✓ com B3; Fases 2–3 pendentes, F3 factory via capture-review-debts pós-B3); B6 registrado — escala/DRY pós-B3 (BahiaMap setStyle) — plano; Trilha E registrada — E1–E5 mapa de projeção por município, E1 metas em cenários + prioridade e E3 dobradinhas/encaminhamentos manuais implementados e mesclados em main 2026-07-19 (migration 20260719_054522_add_nucleus_goals_strategy; /simplify → E6); E2 série TSE 2014/2018 + tendência implementado 2026-07-19; E7 registrado — escala/DRY pós-E2 do /simplify — plano; E6 registrado — escala/DRY pós-E1+E3 do /simplify (aggregate lista/overview, geografia baseline, DRY formatação) — plano; Onda 0 MVP — Consent/privacidade provisórios auto-provisionados (migrations) + /privacidade; hold de PII real até jurídico — plano; O0+ registrado — escala/DRY pós-Onda 0 do /simplify — plano; Visitados recentemente MVP implementado (fill-in, client-side localStorage) — plano; VR+ registrado — escala/DRY pós-visitados recentemente do /simplify — plano; Reset senha + foto de perfil MVP implementado (fill-in, Resend + /campanha/perfil) — plano; RS+ registrado — escala/DRY pós-reset senha/perfil do /simplify — plano; A5 alavancagem da chapa expandido — Fase 2 “oportunidade de virada” (majoritários esquerda + federal direita por vencedor ou por participação proporcional alta) absorvida em insight-alavancagem-chapa.md, sem item paralelo; A8 registrado — perfil médio do eleitorado via IBGE (Censo) + manuais na aba Eleitorado — plano; Field Desk polish (Impeccable quieter→polish, critique 28→32) em branch local — PRODUCT.md / DESIGN.md; FD+ registrado — escala/DRY pós-Field Desk do /simplify — plano; FD2 registrado — UX pós-critique (bulk fila, glossário, outline, empty coordenador) — plano)
Registro canônico no repositório dos planos futuros e débitos conhecidos. Status operacional do ciclo atual de Núcleos fica em .cursor/rules/projects/nucleos-eleitorais.mdc; este arquivo lista o que ainda é futuro ou bloqueador, em ordem de execução, com dependências e paralelismo explícitos.
Âncoras do calendário eleitoral 2026 (Res. TSE 23.760/2026)
| Data | Marco | Consequência para o produto |
|---|---|---|
| 20/07–05/08 | Convenções partidárias | Estrutura de núcleos/coordenadores deve estar operando agora |
| 15/08 | Prazo final de registro de candidaturas | TSE publica candidaturas 2026 na sequência → destrava o insight de dobradinha |
| 16/08 | Início da propaganda eleitoral (rua e internet) | "Quem chega em 16/08 com base de dados estruturada tem vantagem operacional" (Politipédia) — base nominal, baseline e agenda precisam estar em produção antes desta data |
| 09–23/10 | Propaganda gratuita rádio/TV | Reta final; congelar mudanças arriscadas no app |
| 04/10 | 1º turno | Operação do dia D (GOTV) — confirmação de comparecimento da base nominal |
| 25/10 | Eventual 2º turno | Chapa majoritária (Lula/Jerônimo); Solla decidido no 1º turno |
Princípios e decisões travadas
- Priorizar ownership de audiência e portabilidade de dados. (README)
- Manter módulos genéricos o bastante para reuso em outros contextos políticos. (README)
- Default seguro e com controle de acesso para equipes de campanha e institucionais. (README)
- Um único app Next.js com três áreas: site público
(frontend), admin Payload(payload), ferramenta interna(campaign)em/campanha. Sem serviço Rust separado. (AGENTS.md) - Hospedagem na Vercel por enquanto; sem migração self-host/Coolify em andamento. (AGENTS.md)
- Doações não entram neste app — só CTA/link para QueroApoiar (
apoiar.me/jorgesolla, homologado TSE). (AGENTS.md) - Pessoa =
Contact+ collections de junção; nunca criar cadastro paralelo de "apoiador/pessoa". (AGENTS.md) - Núcleo Eleitoral é unidade operacional da campanha; Zona TSE é referência oficial distinta. (notebook Núcleos)
- Sem disparo em massa por WhatsApp: vedado pela Res. TSE 23.610 (art. 33) e pela política da Meta; mobilização é orgânica (kits de compartilhamento individuais). (plano cadastro-nominal, pesquisa 2026-07-17)
Onda 0 — Caminho crítico para /campanha em produção
O MVP de Núcleos está entregue e deployado (ondas 1–8 + refactors; 2026-07-18), junto com A1 (território multi-município/bairro), A2 (zonas TSE + sugestões cruzadas — sem migration), A3 (baseline TSE 2022 — modelo + import), A4 (baseline no produto + Gap vs 2022 — mesclado em main), B1 (overview da lista), C1 (compartilhar página), C3 (planos de ação / agenda) e D1 (PWA). C2 (cadastro nominal de apoiadores) tem a engenharia pronta e mesclada em main, mas segue bloqueada em produção pelo lote jurídico (Consent keys). As migrations (20260718_010733_consolidate_campaign_schema, 20260718_190559_territorio_multi_municipio_bairro, 20260718_195854_add_election_results, 20260718_222656_add_supporter, 20260718_222832_add_action_plan, 20260719_011015_add_supporter_import_batch) aplicam automaticamente no pnpm build da Vercel. O que ainda separa a vertical de uso operacional com dados reais é jurídico + smoke pós-deploy:
- Lote jurídico único de LGPD/Consent (externo — assessoria jurídica eleitoral; textos finais substituem os provisórios do Onda 0 MVP; PII real de lideranças/apoiadores permanece em hold até lá). Uma única rodada cobrindo:
- Base do art. 11 da LGPD + texto versionado de
Consent.key = 'lideranca-autopreenchimento'(bloqueador do MVP de Núcleos; o app falha fechado sem a chave). - Textos de
apoiador-cadastroeapoiador-intencao-voto(bloqueadores do cadastro nominal — detalhes). - Texto de
campanha-notificacoes-push(opt-in de push — detalhes). - Aviso de Privacidade / política de privacidade institucional (obrigação do controlador antes de coleta em massa; também é item do site público).
- Avaliação de necessidade de RIPD (tratamento em larga escala + dado sensível).
- Racional: fatiar em rodadas separadas multiplica o lead time externo; quatro textos + aviso numa rodada só.
- Base do art. 11 da LGPD + texto versionado de
- Smoke pós-deploy (após o build Vercel aplicar a migration): conferir
NEXT_PUBLIC_SITE_URLHTTPS exato, login/campanha, criar núcleo de teste, e só então cadastrar o Consent de liderança. Checklist completo no AGENTS.md. - Ativação com dados reais assim que (1) liberar a chave de liderança. (A decisão de 2026-07-17 de não esperar a migração multi-município ficou superada: A1 foi entregue e deployado antes da ativação — coordenadores já estruturam núcleos reais durante as convenções, 20/07–05/08, com o território definitivo.)
- Onboarding do time real (usuários
geral/coordenador, primeiros núcleos, treinamento básico de campo).
O0+ Escala e DRY pós-Onda 0 registrado (2026-07-19) — débitos do /simplify que não entraram no cleanup: revalidate de globals pós-migration/seed, módulo único de chaves Consent, testes do caminho SQL, DRY Lexical/layout no site público (adiar até Pages), link condicional no Footer. Não bloqueia lote jurídico nem smoke com dados fictícios. Plano.
Campanha (/campanha)
Ciclo 1 — Núcleos (entregue)
MVP de território + reporte implementado e enviado (ondas 1–8 + refactors de composição/infra/fixtures): auth isolada campaignUser (geral / coordenador / lideranca), núcleos com slug canônico, designação de coordenador, lideranças, estimativas sugerir/confirmar com versão UUID, atualizações semanais, convites WhatsApp (wa.me, hash, uso único), dashboard e hardening. Detalhes: .cursor/rules/projects/nucleos-eleitorais.mdc.
Ciclo 2 — entregues em 2026-07-18 (mesclados e deployados)
- A1 Território multi-município/bairro —
regions/cities/neighborhoodsviram arrayshasManycom backfill (20260718_190559_territorio_multi_municipio_bairro); bairros exigem município único; regiões derivadas no servidor. Plano. - A3 Baseline TSE 2022 — Fase 1 — collections
electionTally/electionCandidateVote/electionCandidate(grupo adminDados Eleitorais), migration20260718_195854_add_election_results, import localpnpm db:seed:tseidempotente por escopo (year, office, turn). Sem UI ainda — a UI é A4. Plano. - B1 Overview da lista de núcleos — painel agregado (estimativa de votos, cobertura, últimas atualizações) entre filtros e lista, reagindo aos mesmos filtros da URL, com escopo por papel. Plano.
- C1 Compartilhar página — diálogo no detalhe do núcleo com destinatários WhatsApp (coordenação geral, coordenadores, lideranças engajadas) + copiar link; envia só o link, não concede acesso. Plano.
- D1 PWA
/campanha— manifest + service worker escopados em/campanha, shell offline, toast de instalação (Android/iOS) e limpeza de cache no logout; fundação do push (D2). Plano.
Ciclo 2+ — A2 entregue e mesclado em main (2026-07-18)
- A2 Zonas TSE + sugestões cruzadas — cadastro estático
bahiaTseZones(TSE 2024detalhe_votacao_munzonaBA, 417 municípios), motor puroterritorySuggestions(incluioutsideZones), coordenadorNucleusTerritoryAndZonesFieldscom chips{rótulo} +opt-in (município/TI → ZEs; irmãos do TI e cidades da ZE → Municípios),TseZoneInputcontrolado. Sem migration, sem igualdade forçada no save. Plano.
Ciclo 2+ — A4 implementado e mesclado em main (2026-07-18)
- A4 Baseline no produto + Gap vs 2022 — agregação
getNucleusElectoralBaseline/loadNucleusBaseline2022Overview+computeGapVs2022; bloco "Baseline eleitoral 2022" e insight Gap na aba Visão geral do núcleo; card "Baseline 2022" no overview da lista filtrada. Chapa tipada viaBASELINE_TICKET_2022(papéiscandidate/president/governor). Sem migration, sem Consent (dado público TSE). Três passagens/simplifyno PR; débitos maiores → A7. Plano. - A7 Escala e DRY pós-A4 — Fase 1 entregue (2026-07-19; merge pendente) — agregação drizzle do ranking federal no detalhe (
loadFederalCandidateTotalsAggregated); Fases 2–5 pendentes (cityCodeTSE, Alertconfirmed+ helpers gap +Progress, fetch único 2022 lista+coroplético B3, batch federal flip/leverage na lista pós-A5). Passagens/simplify+capture-review-debtspós-B3, pós-A5 e pós-A5-2 classificação territorial (tally único, reuso tallies conversão, ordem classificação antes do flip N+1). Plano. - A8 Perfis do eleitorado IBGE registrado (2026-07-19) — perfil médio/comum do território derivado de indicadores municipais do Censo IBGE (artefato estático + ponderação por
cities[]), exibido na aba Eleitorado junto comvoterProfilesmanuais já existentes; sem migration, sem Consent. Plano.
Ciclo 2+ — B2 fundação de geometrias do mapa (2026-07-18)
- B2 Mapa Fase 1 (geometrias) — TopoJSON estático de municípios IBGE (
bahia-municipalities.topo.json) + Territórios de Identidade por dissolução (bahia-identity-territories.topo.json), tabelabahiaMunicipalityCodes(nome canônico →codarea), helpersbahiaGeometries(getMunicipalityFeature/getTerritoryFeature), script re-executávelpnpm build:geometries. Sem migration, sem UI (Leaflet = B3). Plano. - B5 Escala e DRY pós-B2 — F1 entregue com B3 (2026-07-19); Fases 2–3 pendentes — lazy load de geometrias (split mun/TI + dynamic import) ✓; helper compartilhado de cache CLI (
ensureCachedDownload) e factory mun/TI (buildGeometryModuleFromTopology) pendentes.capture-review-debtspós-B3 registrou F3. Plano. - B6 Escala e DRY pós-B3 registrado (2026-07-19) —
BahiaMapsetStyleincremental (evitar rebuild GeoJSON a cada troca de métrica).capture-review-debtspós-2×/simplifyB3. Plano.
Ciclo 2+ — C2 e C3 mesclados em main (2026-07-18)
- C2 Cadastro nominal de apoiadores — collection
supporter(joinContact↔campanha, núcleo opcional), migration20260718_222656_add_supportercomUNIQUE NULLS NOT DISTINCT (contact_id, nucleus_id), consent por chaves estáveisapoiador-cadastro/apoiador-intencao-votoviacampaignConsent.tsgenérico (getConsentByKey/requireConsentByKey, falha fechada), actions (create / intenção de voto / import CSV sógeral/removeSupporterData), UI/campanha/apoiadores(lista+KPIs, ficha, wizard de import, kit mínimowa.me). Telefone obrigatório no v1;liderancasem acesso à área. Engenharia pronta e mesclada — produção com dados reais espera deploy (build Vercel aplica a migration) + Consent keys + aprovação jurídica (Onda 0). Plano. - C3 Eventos / agenda de mobilização — collection
actionPlan+ vertical/campanha/planos(lista com tabs Próximos/Todos/Realizados/Rascunhos, detalhe com tabs Visão geral/Tarefas/Atualizações, forms novo/editar), blocos "Próximos eventos" no overview de núcleos e no dashboard;startAtopcional só em rascunho (obrigatório ao sair derascunho); access porcoordinators/leadership(escopoliderancasó toggletasks.done+ appendupdates); transações viawithPayloadTransaction; migration20260718_222832_add_action_plan. SemConsent(dado interno de staff). Plano. - C7 Escala e DRY pós-C3 — entregue (2026-07-19) — composição territorial (
useCampaignTerritoryFieldsState+CampaignTerritoryCoreFields),AsyncSearchCombobox, leituras por aba +taskProgress+ typeahead de liderança, short-circuit de hooks em toggle/append; primeira fatia anterior: FormData território, contadores lista, locks,contactSearchQuery. Débitos pós-/simplify→ C11. Plano. - C6 Escala e DRY pós-C2 — implementado e mesclado em
main(2026-07-19) — import bulk drizzle, token HMAC +supporterImportBatch, KPI aggregate, shells compartilhados (campaignListUrl,CampaignListPagination,campaignFormFields,mapCampaignFormActionError). Duas passagens/simplify; débitos maiores → C8. Plano. - C8 Escala e DRY pós-C6 — implementado e mesclado em
main(2026-07-19) — locks advisory em 1 RT, bulk com.returning()+ leituras drizzle na txn, overview semCOUNT(*)redundante, migrationpg_trgmemcontact,drizzleBulk.ts,getCoordinatorNucleusIds, migração da maioria dosformActionsparamapCampaignFormActionError. Duas passagens/simplify(pré- e pós-rebase com C7); débitos maiores → C9. Plano. - C9 Escala e DRY pós-C8 — implementado (2026-07-19) — filtro unificado Payload↔SQL (
supporterListFilters),contactSearchQueryno aggregate/lista,loadSupportersPageData(1× núcleos do coordenador),apoiadores/[id]/formActionsno mapper compartilhado,fieldErrornos componentes de form restantes. Passagem/simplify; débitos maiores → C10. Plano. - C10 Escala e DRY pós-C9 registrado (2026-07-19) — dedup de access na lista de apoiadores (
req.context), query única de núcleos do coordenador (loadCoordinatorNucleusScope),errorPropsnos forms grandes, prefetch opcional na criação. Plano. - C11 Escala e DRY pós-C7 registrado (2026-07-19) — feed de atualizações O(n) (paginação /
actionPlanUpdatecondicional), loaders do detalhe +loadCampaignUserNamesById, selects por aba, hot paths de mutação/form (serializeTasks,mutationKindtipado), utilities de busca/label. Plano.
Ciclo 3 — Trilha E: mapa de projeção por município (registrado 2026-07-19)
Objetivo: equiparar e superar as planilhas "Mapa de projeção de votos Solla 2026" (docs/sheets/) dentro do produto — metas em cenários, prioridade, série histórica com tendência, dobradinhas/encaminhamentos manuais e import único da planilha. Decisões de produto (2026-07-19): sem entidade nova por município (electoralNucleus absorve a camada estratégica) e série 2014/2018 vem do TSE oficial (estende o seed A3), não dos números da planilha. Plano único para os cinco itens:
- E1 Metas em cenários + prioridade — grupo
voteGoals(good/regular/minimum) +priority(alta|normal) emelectoralNucleus(migration compartilhada com E3); card "Metas 2026" no detalhe, filtro na lista, somas no overview B1 e no dashboard (meta estadual derivada). Implementado e mesclado emmain2026-07-19 (migration20260719_054522_add_nucleus_goals_strategy;/simplify→ E6). - E6 Escala e DRY pós-E1+E3 registrado (2026-07-19) — débitos do
/simplifyque não entraram no cleanup: query duplicada lista+overview, re-resolve de geografia no baseline do overview, aggregate SQL de metas/prioridade (padrão C6), DRYformatElectionNumber/campaignPercentage/voteGoalScenarioLabels, tipos do dashboard por papel. Plano. - E2 Série histórica TSE 2014/2018 + tendência — seed
pnpm db:seed:tse -- --year=2014|2018(federal T1 BA only);computeVoteTrend±10% (increase|stable|decline|noBaseline); série + badge no baseline card, insight e card de distribuição no overview; query candidate-only multi-ano (sem migration). Implementado 2026-07-19. Passagem/simplifyno branch; débitos maiores → E7. - E7 Escala e DRY pós-E2 registrado (2026-07-19) — débitos do
/simplifyque não entraram no cleanup: trend VM único no detalhe (sem série duplicada baseline+insights), testes int deloadNucleusListElectionOverview(gap + tendência + conversão A5-1; extensão pós-A5: leverage/flip + spy N+1 federal; extensão pós-A5-2:classification.distribution), tipo únicoVoteTrendDistribution, helpers compartilhados de wipe eleitoral nos int tests. Fase 2 int loader entregue (2026-07-19) —tests/int/nucleusListElectionOverview.int.spec.ts+seedMultiYearFederalCandidateFixture; extensões F2 pós-A5 e pós-A5-2 pendentes; Fases 1, 3 e 4 pendentes. Plano. - E3 Dobradinhas + encaminhamentos manuais —
dobradinhaNotesenextStepsstaff-only na inteligência do núcleo (excluídos dos view models delideranca); versão manual imediata que A6/C4 complementam depois. Implementado e mesclado emmain2026-07-19 (mesma migration E1+E3; UI emNucleusIntelligenceDialog+ cards staff na Visão geral). - E4 Import único da planilha —
pnpm db:seed:mapaidempotente por slug, município canônico viacanonicalizeMunicipalityName; lideranças/assessores da planilha entram como texto staff-only, nuncaContact/leadership(sem telefone/consent). - E5 Salvador por bairro — registrado como futuro (exigiria
votacao_secao+ DE-PARA local↔bairro versionado); a visão por zona já é coberta pelo baseline município×zona.
Referências de design (UX Pilot, 2026-07-18)
Os designs gerados pelo UX Pilot para os próximos ciclos estão em docs/design-refs/latest/ (pares .png + .html com o mesmo nome). A UX/estrutura é a referência a seguir; a paleta não é — os arquivos usam a paleta antiga (vermelho escuro #8E0E23, navy #1B2B4B, dourado #C8874B); toda implementação usa os tokens claros do tema data-theme='campaign' (src/app/(frontend)/styles.css: fundo branco, primário #C51414, superfícies neutras). Cada plano detalha o uso na sua seção "Referência visual (UX Pilot)".
| Item do roadmap | Design | Plano com instruções |
|---|---|---|
| B1 Overview da lista de núcleos | Lista-Nucleos-Overview |
overview-lista-nucleos.md |
| C1 Compartilhar página | Compartilhar-Nucleo |
compartilhar-pagina.md |
| A1 Território multi-município/bairro | Formulario-Territorio (bloco Território) |
territorio-multi-municipio-bairro.md |
| A2 Zonas TSE + sugestões cruzadas | Formulario-Territorio (seção Zonas TSE + chips {rótulo} +) |
zonas-por-municipio.md |
| A3/A4 Baseline TSE 2022 + Gap vs 2022 | Baseline-Eleitoral-2022 (+ bloco "Baseline 2022" em Lista-Nucleos-Overview) |
baseline-eleitoral-tse.md |
| A5 Insights (5 planos) | Baseline-Eleitoral-2022 (card "Insights do território", uma linha por insight) |
conversão · classificação · alavancagem (Fase 1 conversão da base + Fase 2 virada: vencedor dir. ou share dir. alto) · mobilização · competitiva |
| A7 Escala e DRY pós-A4 | — (sem design novo; reusa baseline A4 + Alert/Progress) | escala-dry-pos-a4.md |
| B6 Escala e DRY pós-B3 | — (sem design novo; reusa mapa B3) | escala-dry-pos-b3.md |
| A8 Perfis do eleitorado (IBGE + manuais) | — (sem design nesta leva; reusa aba Eleitorado + NucleusIntelligenceDialog) |
perfil-eleitorado-ibge.md |
| C2 Cadastro nominal de apoiadores | Apoiadores-Lista, Apoiador-Ficha, Importar-CSV-Apoiadores |
cadastro-nominal-apoiadores.md |
| C6 Escala e DRY pós-C2 | — (sem design novo; reusa os de C2 + padrões de núcleos) | escala-dry-pos-c2.md |
| C3 Eventos / agenda de mobilização | Planos-de-Acao, Novo-Plano-de-Acao |
eventos-agenda-mobilizacao.md |
| C7 Escala e DRY pós-C3 | — (sem design novo; reusa os de C3 + padrões de núcleos/C6) | escala-dry-pos-c3.md |
| C8 Escala e DRY pós-C6 | — (sem design novo; reusa os de C2/C6) | escala-dry-pos-c6.md |
| C9 Escala e DRY pós-C8 | — (sem design novo; reusa os de C2/C6/C8) | escala-dry-pos-c8.md |
| C10 Escala e DRY pós-C9 | — (sem design novo; reusa os de C2/C6/C8/C9) | escala-dry-pos-c9.md |
| C11 Escala e DRY pós-C7 | — (sem design novo; reusa os de C3 + padrões de núcleos/C6/C9) | escala-dry-pos-c7.md |
| O0+ Escala e DRY pós-Onda 0 | — (sem design novo; reusa /privacidade + padrão revalidate posts) |
escala-dry-pos-onda0.md |
| VR+ Escala e DRY pós-visitados | — (sem design novo; reusa dashboard + padrões de lista de núcleos) | escala-dry-pos-visitados-recentemente.md |
| RS+ Escala e DRY pós-reset senha/perfil | — (sem design novo; reusa login + perfil + padrões de form de campanha) | escala-dry-pos-reset-senha-perfil.md |
| FD+ Escala e DRY pós-Field Desk | — (sem design novo; reusa shells/strips Field Desk) | escala-dry-pos-field-desk.md |
| FD2 UX Field Desk pós-critique | — (critique Impeccable; reusa dashboard + badges) | field-desk-ux-pos-critique.md |
| B5 Escala e DRY pós-B2 | — (sem design novo; reusa geometrias B2 + padrões de scripts CLI) | escala-dry-pos-b2.md |
| E6 Escala e DRY pós-E1+E3 | — (sem design novo; reusa Metas 2026 + overview B1) | escala-dry-pos-e1.md |
| E7 Escala e DRY pós-E2 | — (sem design novo; reusa Baseline + Insights + overview tendência/conversão) | escala-dry-pos-e2.md (Fase 2 ✓; Fases 1, 3, 4 pendentes) |
| D2 Notificações (sino) | Notificacoes-PWA (central de notificações) |
notifications.md |
D1 PWA /campanha |
Notificacoes-PWA (banner "Instale o app da campanha") |
pwa-campanha.md |
| C5 Operação dia D / GOTV | Dia-D-GOTV |
sem plano ainda — o design é a primeira materialização do item (check-off de apoiadores por seção/zona, progresso "62% da base", filtro "Ainda não confirmados", estado "Sincronizado" offline-tolerante) |
Sem design nesta leva (encomendar na próxima rodada ou desenhar na implementação): A6 dobradinha 2026, A8 perfis do eleitorado IBGE (seguir aba Eleitorado + card de baseline), B2/B3/B4 mapa da Bahia, C4 demandas, E1–E4 mapa de projeção por município (seguir os padrões de Baseline-Eleitoral-2022 e Lista-Nucleos-Overview), fill-ins (listas globais, reset de senha). O detalhe do plano de ação (tabs Visão geral/Tarefas/Atualizações) e a tela de opt-in de push também não vieram — os planos correspondentes indicam o padrão a seguir.
Grafo de dependências
Setas cheias = dependência dura; tracejadas = dependência suave (melhora, não bloqueia).
flowchart TD
subgraph Onda0["Onda 0 — produção"]
JUR["Lote jurídico único<br/>(4 Consent keys + aviso privacidade)"]
DEPLOY["Checklist deploy + lançamento MVP"]
O0DRY["O0+ Escala e DRY pós-Onda 0<br/>(cache / chaves / testes SQL)"]
end
subgraph TrilhaA["Trilha A — dados eleitorais e território"]
A1["A1 Território multi-município/bairro<br/>(migration) ✓"]
A2["A2 Zonas TSE + sugestões cruzadas<br/>(chips opt-in território↔ZE) ✓"]
A3["A3 Baseline TSE 2022 — Fase 1<br/>(import, collections) ✓"]
A4["A4 Baseline no produto + Gap vs 2022<br/>(detalhe, overview) ✓"]
A7["A7 Escala e DRY pós-A4<br/>(F1 agregar federal ✓ / cityCode / Alert / F4 fetch 2022)"]
A5["A5 Insights: conversão, classificação,<br/>alavancagem (+virada), mobilização, competitiva"]
A6["A6 Dobradinha 2026"]
A8["A8 Perfis eleitorado IBGE<br/>(médio calculado + manuais)"]
end
subgraph TrilhaB["Trilha B — superfícies de coordenação"]
B1["B1 Overview da lista de núcleos ✓"]
B2["B2 Mapa Fase 1 (geometrias) ✓"]
B5["B5 Escala e DRY pós-B2<br/>(F1 lazy ✓ / cache CLI / factory)"]
B3["B3 Mapa Fase 2 (Leaflet nas superfícies)"]
B6["B6 Escala e DRY pós-B3<br/>(setStyle Leaflet)"]
B4["B4 Camada de zonas TSE no mapa"]
end
subgraph TrilhaC["Trilha C — operação de campo"]
C1["C1 Compartilhar página ✓"]
C2["C2 Cadastro nominal de apoiadores ✓"]
C6["C6 Escala e DRY pós-C2<br/>(import/listas/forms) ✓"]
C3["C3 Eventos / agenda de mobilização ✓"]
C7["C7 Escala e DRY pós-C3<br/>(território/contato/leituras/hooks) ✓"]
C8["C8 Escala e DRY pós-C6<br/>(locks bulk / leituras / forms DRY) ✓"]
C9["C9 Escala e DRY pós-C8<br/>(filtros unificados / loader / forms) ✓"]
C10["C10 Escala e DRY pós-C9<br/>(access dedup / scope / errorProps)"]
C11["C11 Escala e DRY pós-C7<br/>(feed escala / loaders / hot paths)"]
C4["C4 Demandas"]
C5["C5 Operação dia D / GOTV<br/>(proposto, a validar)"]
end
subgraph TrilhaD["Trilha D — plataforma e engajamento"]
D1["D1 PWA /campanha ✓"]
D2["D2 Notificações (push + sino)"]
end
subgraph TrilhaE["Trilha E — mapa de projeção por município"]
E1["E1 Metas em cenários + prioridade<br/>(migration c/ E3) ✓"]
E2["E2 Série TSE 2014/2018<br/>+ tendência ✓"]
E7["E7 Escala e DRY pós-E2<br/>(trend VM / int loader ✓ / tipos / test helpers)"]
E3["E3 Dobradinhas + encaminhamentos<br/>manuais (staff-only) ✓"]
E4["E4 Import único da planilha<br/>(pnpm db:seed:mapa)"]
E5["E5 Salvador por bairro<br/>(futuro; validar valor)"]
E6["E6 Escala e DRY pós-E1+E3<br/>(aggregate / geo / DRY UI)"]
end
A1 --> A2
A1 --> A8
A3 --> A4
B1 --> A4
A2 -.qualidade de tseZones.-> A4
A4 --> A7
A4 --> A5
A4 --> A6
A7 -.mesmo loader.-> A5
B2 -.codarea IBGE.-> A8
TSE2026["TSE publica candidaturas 2026<br/>(externo, após 15/08)"] --> A6
B1 --> B3
B2 --> B3
B2 --> B5
B5 -.lazy geometrias.-> B3
B3 --> B6
A4 -.métricas do coroplético.-> B3
A7 -.fetch 2022 único.-> B3
A2 --> B4
B3 --> B4
A1 --> C3
A1 --> C4
C3 --> C7
C3 -.relação actionPlan opcional.-> C4
C6 -.campaignListUrl.-> C7
JUR --> C2prod["C2 em produção<br/>(dados reais)"]
C2 --> C2prod
C2 --> C6
C2 --> C5
C6 -.escala da base.-> C5
C6 --> C8
C8 --> C9
C9 --> C10
C7 --> C11
C10 -.forms DRY.-> C11
D1 --> D2
JUR -.chave de push.-> D2
DEPLOY -.engenharia entregue.-> O0DRY
A4 --> E2
E1 --> E6
E6 -.perf lista/overview.-> E4
E1 --> E4
E3 --> E4
E2 -.tendência no import.-> E4
E1 -.metas no coroplético.-> B3
E2 -.classe por cor.-> B3
E2 -.dataset votacao_secao.-> E5
E2 --> E7
E7 -.int loader antes.-> E4
A7 -.mesmo loader do baseline.-> E2
A7 -.mesmo módulo.-> E7
E6 -.geo cache.-> E7
Itens sem seta de entrada (paralelizáveis a qualquer momento): O0+ (após engenharia Onda 0 ✓), VR+ (após Visitados recentemente ✓), RS+ (após Reset senha + perfil ✓), FD+ / FD2 (após polish Field Desk em branch) e fill-ins (listas globais, higiene PascalCase). Entregues e mesclados em main em 2026-07-18/19 (✓ no grafo): A1, A2, A3, A4, B1, B2, C1, C2, C3, C6, C7, C8, C9, D1, E1, E2 e E3 — ver "Ciclo 2", "Ciclo 2+" e "Ciclo 3" acima. Fill-ins entregues em branch local (2026-07-19): Visitados recentemente, Reset senha + foto de perfil. C2 segue com produção bloqueada pelo lote jurídico (Onda 0: Consent keys apoiador-cadastro / apoiador-intencao-voto + aprovação). Destravados por eles: A5/A6 (após A4 ✓), A7 (após A4 ✓; preferencialmente antes ou com A5/B3/E2; F4 reduz custo do coroplético na lista), A8 (após A1 ✓; suave B2 ✓ para codarea — paralelizável agora), E7 (após E2 ✓; Fase 2 int preferível antes de E4), E6 (após E1+E3 ✓), E4 (após E1+E3 ✓; suave: E6 F1 e E7 F2 reduzem custo/risco do overview antes do import em massa), B3 (B1 ✓ + B2 ✓; suave: A4 ✓ para coroplético e B5 F1 para lazy load), B5 (após B2; F1 ✓ com B3; F2–F3 pendentes), B6 (após B3; suave: A7 F4), C4 (A1 + C3 prontos), C10 (após C9 ✓; cortável se a base nominal permanecer pequena), C11 (após C7 ✓; cortável se a agenda permanecer pequena; Fase 1 feed condicional) e D2 push (D1 pronto; falta a chave jurídica).
Sequência de execução por janela do calendário
Janela 1 — agora → 05/08 (convenções): colocar a vertical em produção e consertar a fundação de dados.
| Ordem | Item | Plano | Depende de | Paralelizável com |
|---|---|---|---|---|
| 1 | Onda 0 (textos MVP auto + deploy + hold PII real) | detalhes | engenharia entregue; jurídico final | tudo |
| 2 | A1 Território multi-município/bairro (entregue 2026-07-18) | detalhes | — | B1, C1, A3 |
| 3 | A2 Zonas TSE + sugestões cruzadas (chips opt-in território↔ZE) (entregue 2026-07-18) | detalhes | A1 (nasce contra cities[]) |
B1 ✓, C1 ✓, A3 ✓ |
| 4 | B1 Overview da lista de núcleos (entregue 2026-07-18) | detalhes | — | A1, A2, C1 |
| 5 | C1 Compartilhar página (entregue 2026-07-18) | detalhes | — | tudo |
| 6 | A3 Baseline TSE 2022 — Fase 1 (import) (entregue 2026-07-18) | detalhes | — (dado público; sem bloqueador LGPD) | tudo |
Janela 2 — 05/08 → 16/08 (pré-propaganda): base nominal + inteligência + agenda prontas para o arranque.
| Ordem | Item | Plano | Depende de | Paralelizável com |
|---|---|---|---|---|
| 7 | C2 Cadastro nominal de apoiadores (engenharia pronta e mesclada em main 2026-07-18 — deploy + Consent keys ainda pendentes) |
detalhes | produção: lote jurídico (Onda 0) | A4, C3, C6, C7 |
| 8 | C6 Escala e DRY pós-C2 (import em massa, KPI, shells compartilhados com núcleos) (implementado e mesclado em main 2026-07-19 — Fases 1–5 + simplify) |
detalhes | C2 (merge) | A4, C3, C7, C8 |
| 9 | A4 Baseline no produto + insight Gap vs 2022 (implementado e mesclado em main 2026-07-18 — Fases 2–4 + simplify) |
detalhes | A3 + B1 (suave: A2) | C2, C3, C6, C7, C8 |
| 10 | C3 Eventos / agenda de mobilização (actionPlan) (implementado e mesclado em main 2026-07-18) |
detalhes | A1 | C2, A4, C6, C7, C8 |
| 11 | C7 Escala e DRY pós-C3 (entregue 2026-07-19 — Fases 1–5; feed O(n) condicional fora de escopo) | detalhes | C3 (suave: C6 F2) | A4, C6, C8, E1+E3, E2 |
| 12 | C8 Escala e DRY pós-C6 (locks bulk em 1 RT, leituras/pg_trgm, helpers drizzle, forms DRY) (implementado e mesclado em main 2026-07-19 — Fases 1–4 + simplify) (cortável se a base nominal permanecer pequena) |
detalhes | C6 (merge) | A4, C3, C7, E1+E3, E2, C9 |
| 13 | C9 Escala e DRY pós-C8 (filtro unificado Payload↔SQL, contactSearchQuery no aggregate, loader único /apoiadores, forms restantes) (implementado e mesclado em main 2026-07-19 — Fases 1–4 + simplify) (cortável se a base nominal permanecer pequena) |
detalhes | C8 (merge) | A4, C3, C7, E1+E3, E2, C10 |
| 14 | C10 Escala e DRY pós-C9 (dedup access lista, scope único de núcleos do coordenador, errorProps nos forms) (cortável se a base nominal permanecer pequena; Fase 3 DRY pode entrar isolada) |
detalhes | C9 (merge) | A4, C3, C7, E1+E3, E2, C11 |
| 15 | C11 Escala e DRY pós-C7 (feed O(n) condicional, loaders do detalhe, selects por aba, hot paths mutação/form, utilities de busca) (cortável se a agenda permanecer pequena; Fase 1 migration só com volume medido) | detalhes | C7 (merge) | A4, C3, C10, E1+E3, E2 |
| 16 | E1 Metas em cenários + prioridade + E3 dobradinhas/encaminhamentos manuais (implementado e mesclado em main 2026-07-19 — migration 20260719_054522; /simplify → E6) |
detalhes | — | tudo da janela |
| 17 | E6 Escala e DRY pós-E1+E3 (aggregate SQL metas/prioridade, geografia baseline, DRY formatação) (cortável se poucos núcleos ativos) | detalhes | E1+E3 ✓ | E2, C10, A7, E4 |
| 18 | E2 Série histórica TSE 2014/2018 + tendência automática (seed por ano; sem migration) (implementado 2026-07-19; /simplify → E7) |
detalhes | A4 ✓ (suave: A7 F1 — mesmo loader) | E1+E3, E6, E7, C7, C8, C9, C10, C11 |
| 19 | E7 Escala e DRY pós-E2 (trend VM único no detalhe, int loadNucleusListElectionOverview, tipo VoteTrendDistribution, helpers wipe eleitoral nos int tests) (Fase 2 int entregue 2026-07-19; Fases 1, 3 e 4 pendentes; F4 cortável — só DX de teste) |
detalhes | E2 (merge) | E6, A7, E4, C10 |
Janela 3 — 16/08 → set (campanha de rua): inteligência ampliada, visualização e engajamento.
| Ordem | Item | Plano | Depende de | Paralelizável com |
|---|---|---|---|---|
| 18 | E4 Import único da planilha (pnpm db:seed:mapa; sem criar Contact/leadership) |
detalhes | E1 ✓ + E3 ✓ (suave: E2 ✓ — tendência visível na revisão; E6 F1 — perf da lista) | A5, A7, A8, B3, B5, C4, D2 |
| 19 | A5 Insights derivados do baseline (5 itens, paralelizáveis entre si; conversão e classificação exigem limiares de produto; alavancagem inclui Fase 2 virada por vencedor ou share da direita) | conversão · classificação · alavancagem · mobilização · competitiva | A4 | A7, A8, B3, B5, C4, E4, D1 |
| 20 | A8 Perfis do eleitorado — perfil médio IBGE (Censo) + manuais na aba Eleitorado (cortável: manuais já existem) | detalhes | A1 ✓ (suave: B2 ✓ — codarea) |
A5, A7, B3, B5, C4, E4, D1 |
| 21 | A7 Escala e DRY pós-A4 (cityCode TSE, Alert confirmed + helpers gap + Progress, fetch único 2022 lista+coroplético, batch federal flip/leverage na lista) (Fase 1 agregar federal entregue 2026-07-19; Fases 2–5 pendentes; F4 pós-B3; F5 pós-A5 via capture-review-debts) |
detalhes | A4 ✓ (suave: A5/B3/E2 amplificam o custo) | A5, A8, B3, B5, B6, C4, E4, D1 |
| 22 | B2 Mapa Fase 1 (geometrias) (entregue 2026-07-18) + B3 Leaflet nas superfícies | detalhes | B3 ← B1 ✓ + B2 ✓ (suave: A4 coroplético; E1/E2 métricas; B5 F1 lazy geometrias) | A5, A7, A8, B5, B6, C4, E4, D1 |
| 23 | B5 Escala e DRY pós-B2 (cache CLI + factory mun/TI; F1 lazy ✓) | detalhes | B2 ✓ (F1 entregue com B3) | A5, A7, A8, B3, B6, C4, E4, D1 |
| 24 | B6 Escala e DRY pós-B3 (BahiaMap setStyle incremental) (cortável se troca de métrica for rara) |
detalhes | B3 (suave: A7 F4 na lista) | A5, A7, A8, B5, C4, E4, D1 |
| 25 | C4 Demandas | detalhes | A1 (suave: C3 para a relação actionPlan) |
A5, A7, A8, B3, B5, B6, E4, D1 |
| 26 | D1 PWA /campanha (entregue antecipado em 2026-07-18) |
detalhes | — | tudo |
| 27 | D2 Notificações (push + sino) — sino não depende do PWA; push sim | detalhes | D1 ✓ (push) + chave campanha-notificacoes-push do lote jurídico |
A5, A7, A8, B3, B5, B6, C4, E4 |
Janela 4 — set → 04/10 (reta final): dobradinha, dia D e estabilização.
| Ordem | Item | Plano | Depende de |
|---|---|---|---|
| 28 | A6 Insight dobradinha 2026 | detalhes | A4 + TSE publicar candidaturas 2026 (externo, após 15/08) + taxonomia de alinhamento (produto) |
| 29 | B4 Camada de zonas TSE no mapa | ciclo seguinte do plano do mapa | A2 + B3 |
| 30 | C5 Operação dia D / GOTV (item proposto nesta revisão — validar com produto): confirmação de comparecimento da base nominal em 04/10 (lista de apoiadores por núcleo/zona com marcação "confirmou que vai votar / votou", visão de cobertura para a coordenação). É o uso final da base construída em C2; a literatura de campanha trata a mobilização do dia como onde eleições apertadas se decidem. Sem plano ainda. | design: Dia-D-GOTV |
C2 (suave: C6 para escala da base) |
| 31 | Congelamento: a partir de ~20/09, só correção de bug e dados; nada de migration arriscada perto do dia D. E5 (Salvador por bairro) fica registrado para depois da eleição, condicionado a decisão de produto. | — | — |
Fill-ins (qualquer janela, quando houver folga; nenhum bloqueia nada):
- O0+ Escala e DRY pós-Onda 0 (revalidate globals, chaves Consent, testes SQL provision, DRY Lexical/layout) — engenharia pós-MVP; paralelizável com smoke Onda 0. → detalhes
- Visitados recentemente ✓ (client-side,
localStorage; MVP entregue 2026-07-19). → detalhes - VR+ Escala e DRY pós-visitados recentemente (refresh bfcache/storage, DRY tempo relativo,
CampaignLinkListRow, shell do dashboard) — engenharia pós-MVP; paralelizável com qualquer janela. → detalhes - Reset de senha self-service + foto de perfil ✓ (Resend +
/campanha/perfil; MVP entregue 2026-07-19). → detalhes - RS+ Escala e DRY pós-reset senha/perfil (auth read
depth: 0, avatar fora da TX, auth UI parcial ✓ — shell/card/logo + critique login fechados; pendemCampaignPasswordFields+ login emCampaignFormActionState) — engenharia pós-MVP; paralelizável com qualquer janela. → detalhes - Field Desk polish (Impeccable quieter→polish; critique 28→32) — shells/strips/freshness/filas-first/Mais filtros/empties; em branch local 2026-07-19. →
PRODUCT.md/DESIGN.md - FD+ Escala e DRY pós-Field Desk (
CampaignPageShellsize, heading class, VoteGoals→MetricStrip, datas canônicas, NucleusFilters bag) — engenharia pós-polish; paralelizável com qualquer janela. → detalhes - FD2 UX Field Desk pós-critique (bulk na fila Sem coordenador, glossário inline, outline h2 Filas, empty coordenador+CTA, Sidebar motion cortável) — produto/UX pós-critique; (validar prioridades com produto). → detalhes
- Listas globais (lideranças, atualizações, territórios no nível raiz). (plano MVP; sem plano detalhado ainda)
- Higiene de código: varredura PascalCase dos componentes legados. (notebook Núcleos)
Cortes seguros se o prazo apertar (nesta ordem): E5 Salvador por bairro (já registrado como futuro), B4 camada de zonas, B6 (setStyle Leaflet — cortável se troca de métrica for rara), B5 F2–F3 (cache CLI + factory — F2 é ~20 linhas; F3 é DRY puro), E4 import da planilha (os campos E1/E3 podem ser preenchidos à mão pela coordenação; o import só acelera), A8 perfis IBGE (a aba Eleitorado e voterProfiles manuais já existem; o calculado só acelera o ponto de partida), E7 F1, F3 e F4 (dedup visual/API e helpers de teste — Fase 2 int loader é a mais valiosa antes de E4), E6 F2–F4 (geografia baseline / DRY UI / tipos dashboard — Fase 1 aggregate só se poucos núcleos; preferir E6 F1 antes de E4 ou B3 se a lista ficar lenta), A7 F2–F5 (cityCode / Alert DRY / fetch 2022 único / batch flip lista — F4 mais valiosa com coroplético B3 na lista; F5 cortável se filtros típicos ≤10 núcleos; F2–F3 só se a geografia real dos núcleos permanecer 1–2 municípios), E2 série 2014/2018 (reduzível a só 2018 se o formato TSE de 2014 atrasar; a tendência vira 2 pontos), B3 mapa Leaflet (preferir levar B5 F1 lazy load junto se B3 entrar), C4 demandas, D2 push (mantendo o sino), C6 fases 3–5 (import bulk / preview token / KPI — só se a base nominal permanecer pequena), C8 (escala/DRY pós-C6 — só se a base nominal permanecer pequena; Fases 3–4 DRY podem entrar isoladas), C9 (escala/DRY pós-C8 — só se a base nominal permanecer pequena; Fases 3–4 DRY de forms podem entrar isoladas), C10 (escala/DRY pós-C9 — só se a base nominal permanecer pequena; Fase 3 errorProps pode entrar isolada; Fase 1 access dedup é a mais valiosa se coordenadores usarem /apoiadores com frequência), C11 (escala/DRY pós-C7 — só se a agenda permanecer pequena; Fase 1 migration actionPlanUpdate só com volume medido; Fases 2–3 loaders/selects são as mais valiosas se /campanha/planos tiver uso real), O0+ Fase 4–5 (Lexical/layout shell e Footer condicional — Fases 1–3 preferíveis antes de tráfego real em /privacidade), VR+ Fases 3–5 (row shell, layout wrapper, micro-perf — Fase 1 refresh bfcache é a mais valiosa se usuários reclamarem de painel stale), RS+ Fases 3–5 (shell auth / campos de senha compartilhados / avatar intent único — Fase 1 auth read é a mais valiosa se /campanha ficar lento), FD+ Fases 3–5 (VoteGoals strip / datas / filtros bag — Fases 1–2 shell size + heading são as de maior ROI de consistência), FD2 Fase 5 (Sidebar motion — cortável; preferir Fases 1–2 bulk+glossário se Alex reclamar da fila), fill-ins (D1 PWA já entregue, saiu da lista de cortes). Preferir manter C6 fases 1–2, C7 (entregue), C8 fases 1–2 (perf import/lista), C9 Fase 1 (filtro unificado — evita drift KPI/lista), C10 Fase 1 (access dedup na lista), C11 Fases 2–3 (loaders/selects por aba) se a agenda for usada antes de 16/08, O0+ Fase 1 (revalidate globals pós-migration), RS+ Fase 1 (auth read sem join de avatar em rotas operacionais), E6 Fase 1 (aggregate metas/prioridade — evita dupla query na lista antes de E4/B3), E7 Fase 2 (int do loader combinado gap+trend+conversão; extensão leverage/flip pós-A5) e A7 F1 (agregar federal no detalhe) se A5/B3/E2 forem entrar — o custo de I/O do loader do A4 é herdado por eles. Não cortáveis: Onda 0 (jurídico/Consent), C2 cadastro de apoiadores, C3 eventos/agenda, A4 baseline + gap, E1+E3 metas/prioridade/estratégia manual — são respectivamente o risco legal, a base de dados, a operação da propaganda, o instrumento de alocação de esforço e a paridade mínima com a planilha que a campanha já usa.
Itens consolidados/removidos nesta revisão (2026-07-17)
- "Insight: oportunidade de virada pela chapa" (2026-07-19) — não virou item paralelo na trilha A: absorvido como Fase 2 de alavancagem da chapa. Gatilhos: (A) dep. federal mais votado de direita ou (B) participação proporcional da direita nos nominais federais ≥ limiar — ambos com pré-condição de majoritários locais de esquerda; discurso de completar a chapa.
- "Insight: Gap vs 2022" como item separado — removido: é a Fase 4 do plano de baseline TSE 2022 (item A4), não um item próprio.
- "Import do cadastro oficial de zonas TSE e/ou polígonos GeoJSON" — absorvido: o cadastro tabular é o plano zonas-por-municipio (A2); os polígonos são a camada de zonas do plano do mapa (B4).
- "Sugestões cruzadas no formulário de território" (chips
{Município} +/{TI} +em ZEs; irmãos do TI e cidades da ZE em Municípios) — absorvido em A2 na revisão 2026-07-18; substitui o auto-preenchimento forçado + read-only da versão 2026-07-17 do mesmo plano. - "Notificações WhatsApp Business API" — movido para fora de escopo: a Meta veda o WhatsApp Business API para campanhas políticas no Brasil e a Res. TSE 23.610 (art. 33) veda disparo em massa (pesquisa em cadastro-nominal-apoiadores.md). Push + sino (notifications.md) cobrem a necessidade.
- "Previsão estatística de votos" — mantido, mas explicitamente fora do horizonte deste ciclo eleitoral: sem dado acumulado suficiente antes de 04/10; o baseline TSE + estimativa manual + insights são o "mínimo honesto" (design-ux §4.5). Reavaliar pós-eleição.
- Dependência baseline → zonas-por-municipio — rebaixada de dura para suave:
citiesForTerritoryjá existe e as rows deelectionTallyresolvem cidade↔zona (ver revisão nos planos).
Bloqueadores atuais
| Item | Status | Fonte |
|---|---|---|
Lote jurídico único LGPD (4 textos de Consent + Aviso de Privacidade + avaliação de RIPD) — textos provisórios MVP já provisionados por migration (onda-0.md); substituição final + liberação de PII real aguarda assessoria |
caminho crítico para dados reais | notebook Núcleos; AGENTS checklist; planos cadastro-nominal, notifications e onda-0 |
RBAC em users — todo usuário do admin Payload tem acesso total; necessário antes de abrir /admin a equipe maior. Nota: o import de apoiadores foi desenhado no /campanha justamente para não depender disso |
pendente | AGENTS Known Gap #1 |
Fluxos públicos ainda hardcodam ID de Consent (ex. consent: 2 em submitWhatsapp.ts); migrar para chave estável como na campanha |
pendente | AGENTS Known Gap #2; plano-arquitetura |
Collection Pages inexistente; hero/copy da home ainda hardcoded — bio, propostas e páginas institucionais |
pendente (não bloqueia /campanha) |
AGENTS Known Gap #3 |
Site público
Já entregue: sistema de notícias/publicações (post/tag), listagens e artigos, seed a partir de jorgesolla.com.br, cache com tag posts; página /privacidade via global privacy-policy (texto provisório Onda 0 — revisão jurídica pendente).
Próximos (não bloqueiam /campanha, exceto a política de privacidade, que entra no lote jurídico da Onda 0):
- Página de política de privacidade institucional (LGPD) — MVP entregue (
/privacidade); textos finais e polish pós-simplify (revalidate globals, DRY Lexical) em escala-dry-pos-onda0.md. (plano-arquitetura §3.1) - Modelar e popular
Pagespara conteúdo institucional (biografia, mandato, propostas). (AGENTS Known Gap #3; plano-arquitetura §3) - Tornar editáveis título/subtítulo (e demais textos) da home via global/
Pages. (AGENTS Known Gap #3) - Agenda pública e multimídia: preferir links oficiais (Câmara, YouTube, Flickr). (plano-arquitetura §3.1)
- Garantir superfície clara de CTA "Doar" → QueroApoiar. (AGENTS.md; plano-arquitetura)
- Migrar Consent dos fluxos públicos (WhatsApp, petições) para resolução por chave estável. (AGENTS Known Gap #2)
Admin Payload
- Introduzir
rolesemuserse access control real antes de ampliar quem entra em/admin. (AGENTS Known Gap #1) - Seed reproduzível de documentos
Consentresolvidos por chave (não por ID numérico). (plano-arquitetura §2.3)
Plataforma white-label
- Fase 2 do README: multi-tenant, customização de marca/conteúdo por mandato, módulos compartilhados de comunicação e engajamento.
- Depois da eleição — monorepo e white-label deliberadamente fora de escopo até lá. (README Phase 2; plano-arquitetura §6)
Fora de escopo (por enquanto)
- Serviço Rust (ou outro backend) separado para
/campanha. (AGENTS.md; plano-arquitetura) - Migração self-host / Coolify enquanto a Vercel atender. (AGENTS.md)
- Processamento de pagamentos ou doações dentro deste app. (AGENTS.md)
- Tratar Núcleo Eleitoral como sinônimo de Zona Eleitoral do TSE. (notebook; plano MVP)
- PWA do site público ou do
/admin— só a vertical/campanhaserá instalável. (decisão de produto 2026-07-17) - PostGIS até surgir necessidade de query espacial real; v1 do mapa usa TopoJSON estático versionado no repo. (decisão de produto 2026-07-17)
- WhatsApp Business API — vedado para campanhas políticas pela Meta e sem caminho legal para disparo em massa (Res. TSE 23.610 art. 33); superado por push + sino. (revisão 2026-07-17)
- Disparo em massa de mensagens em qualquer canal — mobilização é orgânica (kits de compartilhamento individuais, art. 33 §2º). (plano cadastro-nominal)
- Previsão estatística de votos neste ciclo eleitoral. (revisão 2026-07-17; reavaliar pós-eleição)
Fontes
AGENTS.md— decisões travadas, Known Gaps, checklist de campanha.cursor/rules/projects/nucleos-eleitorais.mdc— status e decisões do MVP de NúcleosREADME.md— missão e direção de produtodocs/plans/*.md— planos detalhados por itemdocs/sheets/*.xlsx— planilhas "Mapa de projeção de votos Solla 2026" (fonte da Trilha E; estrutura de referência da campanha, não fonte de dados eleitorais — estes vêm do TSE)- Plano Cursor
núcleos_eleitorais_mvp_*.plan.md(fora do repo; workspace local) plano-arquitetura-campanha-2026.mdedesign-ux-campanha.md(Cowork / pasta irmã; fora do repo)- Res. TSE 23.760/2026 (calendário eleitoral) — https://www.tse.jus.br/legislacao/compilada/res/2026/resolucao-no-23-760-de-2-de-marco-de-2026
- Res. TSE 23.610/2019 (propaganda; art. 33 — disparo em massa) e Lei 9.504/1997
- Politipédia AVM — planejamento de campanha, base de dados, territorialização, operação do dia da eleição — https://politipedia.wiki.br