Commit graph

330 commits

Author SHA1 Message Date
Cursor Agent
f27563d694
style: Prettier (O0+ #34) 2026-08-01 06:04:44 +00:00
Cursor Agent
cbe171c597
O0+ (#34): consent key DRY, SQL int tests, Footer condicional, B68 suggest RSC
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-01 06:04:05 +00:00
Francisco Solla
5c6ed8cf31
Merge pull request #82 from fsolla/cursor/pool-i23-0fce1b59-4cb2
B87 — Ações rápidas — Assessores (unrestricted)
2026-08-01 03:03:49 -03:00
Cursor Agent
86f948540b
fix: rebase on main (B85 demands + B87 assessores) 2026-08-01 05:49:25 +00:00
Cursor Agent
be317191b6
B87 — Ações rápidas assessores (unrestricted)
Registry B79 para /campanha/assessores (lista + detalhe): catálogo
new-advisor com deep link ?criar=1; mount gate só unrestricted;
/novo redireciona para o deep link; busca global permanece na lista
(B91 no drawer).

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-01 05:48:08 +00:00
Cursor Agent
a9b0db7a99
B91 — Prettier format 2026-08-01 05:47:26 +00:00
Cursor Agent
c73034aa77
B91 — Mount drawer search only when expanded; unify body export
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-01 05:46:42 +00:00
Cursor Agent
d639988b83
B91 — Global search in mobile quick-actions drawer
Extract CampaignGlobalSearchMount (provider + body) from home chrome
so the same home-search contract mounts in CampaignQuickActionsDrawer
when expanded. Refactor CampaignHomeStaffChrome to use the provider.

Closes #55

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-01 05:42:59 +00:00
Francisco Solla
90d130af33
Merge pull request #80 from fsolla/cursor/pool-i21-97442a76-e99b
B85 — Ações rápidas — Demandas
2026-08-01 02:41:05 -03:00
Cursor Agent
dfa080f74d
B89 — Ações rápidas em Contatos (liderança)
Wire the B79 drawer on /campanha/contatos for leader role with the B45
catalog (register-supporter, my-contacts). Actions use in-page hash anchors
instead of staff home-search; no drawer on Início (existing B79 gate).

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-01 05:27:45 +00:00
Cursor Agent
aa0cc4e15a
test: resolve searchStaffMunicipalityHits conflict after rebase 2026-08-01 05:27:41 +00:00
Cursor Agent
1cfe6948d2
fix(B85): limpar registry após rebase em main (B84) 2026-08-01 05:26:23 +00:00
Cursor Agent
7812dee1f3
style: Prettier (B85) 2026-08-01 05:26:12 +00:00
Cursor Agent
c05b04236e
B85 — Ações rápidas no drawer de Demandas (lista + detalhe)
Registra catálogo contextual no chassis B79:
- Lista: um launcher register-demand → /demandas/nova (wizard A5 ainda stub)
- Detalhe: A1–A5 com prefill de município via context sync
- Expõe municipalityId no view model para prefill do form de criação

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-01 05:26:12 +00:00
Cursor Agent
a7ecdbc844
chore: format B88 quick-action files 2026-08-01 05:12:11 +00:00
Cursor Agent
9b76f19b85
B88 — Ações rápidas em Organizações (lista + detalhe)
Registra /campanha/organizacoes no registry B79 com launcher
new-organization na lista; detalhe vazio até existir filtro de
lideranças por org ou município óbvio único.

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-01 05:11:31 +00:00
Cursor Agent
9ab0dbd153
style: Prettier registry after merge 2026-08-01 04:45:16 +00:00
Cursor Agent
b7ad9ad326
merge: sync with main (B80 municipalities quick actions) 2026-08-01 04:44:03 +00:00
Cursor Agent
39b9065ad2
style: Prettier after rebase merge 2026-08-01 04:35:38 +00:00
Cursor Agent
940b866630
style: Prettier on B84 quick-action files 2026-08-01 04:35:38 +00:00
Cursor Agent
eea2d9afa1
B84 — Ações rápidas na vertical Atividades (lista + detalhe)
Registra catálogo B84 no registry B79: Nova atividade e Planejar giro na
lista; wizards A1–A5 com ?municipio= no detalhe quando há município, mais
atalhos Editar/Tarefas/Atualizações. Context bridge no detalhe; drawer
omitido em /atividades/giros (compositor E13 já tem CTAs).

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-01 04:35:38 +00:00
Cursor Agent
3463389942
style: prettier registry 2026-08-01 04:22:25 +00:00
Cursor Agent
6030d42e2f
B80 — Ações rápidas em Municípios (lista + detalhe A1–A5)
Registra catálogo staff no drawer B79 para /campanha/municipios e
/campanha/municipios/[slug]: lista espelha Início (sem prefill); detalhe
prefill ?municipio= nos wizards A1–A5 e omite Ver esquecidos.

Closes #16

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-01 04:21:15 +00:00
Cursor Agent
09e76ec8cb
B81 — format 2026-08-01 04:10:16 +00:00
Cursor Agent
7f2ac29368
B81 — simplify: path constant, role cache, href parity test
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-01 04:09:35 +00:00
Cursor Agent
8c9eeaf273
B81 — register staff Início quick actions on /campanha/territorios
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-01 04:06:22 +00:00
Cursor Agent
7a876ec334 refactor(notifications): bell loaders read through owner access, no bypass
countUnreadNotifications/loadNotificationList took a caller-supplied
recipientID with module-level admin bypass — one misuse away from reading
someone else's inbox. They now take the actor (CampaignUser) and read
with overrideAccess: false under canReadOwnNotifications, keeping the
explicit recipient filter as a second fence. Pin: owner isolation at the
loader level in campaignNotifications.int.spec.ts.

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-07-31 20:57:18 -03:00
Cursor Agent
6705db80eb security: lock public globals update to payloadAdminOnly (Pass 4 P0)
The four public globals (site-settings, home, metadata, privacy-policy)
spelled update access as "any authenticated user" — and campaign JWTs
authenticate against /api/*, so any campaign session (leader included)
could PATCH the public site. payloadAdminOnly matches the collection
lockdown precedent; editors lose config-global writes deliberately
(content editing stays on canManagePublishedContent collections).

Pins: identity + deny (coordinator/editor) + allow (admin fn) + anonymous
read in collectionAccessLockdown.int.spec.ts. Recurrence guard:
globalAccessConventions.unit.spec.ts bans the Boolean(user) shape in
src/globals.

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-07-31 20:57:18 -03:00
Francisco Solla
7a66fe4f25
Merge pull request #5 from fsolla/cursor/p4-shared-sheet-host-78a7
Miss #52 guardrail: shared sheet host on the chip-relation lists + fail-loud guard
2026-07-31 13:21:48 -03:00
Cursor Agent
c83cf28497 test(miss-52): sheet cells without the shared host fail loud
- CampaignCellEditOverlay: dev-mode console.error when a variant=sheet
  cell mounts without CampaignListSheetProvider (prod keeps the
  lazy-mount fallback for resilience; unit tests exercise it, so the
  invariant is development-only).
- sharedSheetHostConventions.unit.spec.ts: any tsx rendering
  <MunicipalityPortfolioCell / <LeadershipStateDeputyRelationCell must
  reference CampaignListSheetProvider — the next chip table cannot
  reintroduce per-cell Drawers by omission.
2026-07-31 13:17:19 -03:00
Cursor Agent
6f42bc3bf3 fix(miss-52): one shared Drawer for the chip-relation lists too
The B42 fix reached the municípios mobile cards, but the three
chip-relation surfaces still mounted a Drawer root per OPENED cell on
coarse pointers (lideranças 50 cells, dobradinhas 50, assessores 25):
the exact hundreds-of-hidden-instances class that tripped React #130 in
prod. Each now wraps its table in CampaignListSheetProvider — cell
bodies portal into the single host Drawer, fine-pointer popover path
untouched (behavior delta: after opening N cells sequentially on touch,
N drawer roots -> 1).
2026-07-31 13:17:19 -03:00
Cursor Agent
9ae062c77c refactor(lib): close the lib→utilities type-import hole + Local API omission guard
- suggestionCatalog type-imports MunicipalityTerritorialClass from
  lib/territorialClassAnchors (the single source) instead of the
  utilities re-export — direction inversion introduced in Pass 3.
- ESLint src/lib zone: @/utilities|components|app restriction now rejects
  type imports too (allowTypeImports: false); shared types live in lib
  contract modules by policy.
- engagementLevel imports DAY_MS from lib/text (fold missed in P3-K).
- searchHomeAdvisors: delete stale 'Intentional admin bypass' comment —
  the call is overrideAccess: false under the staff gate.
- New guard localApiOverrideAccessConventions.unit.spec.ts: payload calls
  with user must declare overrideAccess (baseline measured: 59 calls, 0
  missing), and runtime dynamic import/require of payload/next server
  modules is banned in utilities (dodges the server-only sweep).
2026-07-31 13:17:10 -03:00
Francisco Solla
8dd60cf962 A6 — Dobradinha 2026 automática quando o TSE publicar candidaturas (pós-15/08) (#82)
* docs(A6): freshness audit da #27 no plano de dobradinhas 2026

electionInsights.ts foi deletado no Pass 2 W4a (modulo puro novo),
electionAlliances.ts nao nasce (campoParties + electionPartySpectrum ja
carregam a taxonomia), questoes em aberto resolvidas (tiers, score,
proporcionais, lockdown de lideranca), card na aba Eleicoes, overview da
lista fora de escopo, cache election-tse com bust na conciliacao Fase 5.

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>

* feat(A6): insight de dobradinhas 2026 na aba Eleicoes do municipio

Lista ranqueada de candidatos proporcionais que concorrem de novo em 2026
(runningAgain2026=sim) por geografia do municipio: score 0,6 alinhamento
(campo 2026 + espectro Bolognesi) + 0,4 forca local normalizada pelo maximo
do conjunto. Estado pendente ate a conciliacao pos-15/08; Solla excluido
(referencia, nao parceiro); leitura derivada sem escrita; loader cacheado
sob a tag election-tse como os irmaos; link para /campanha/dobradinhas
como caminho de registro operacional.

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>

* test(A6): cobertura unit/int do insight + lease das colecoes eleitorais

Unit: tiers (campo/espectro/falha-para-o-meio), score, ordenacao, empates,
limite, zero votos. Int: pending2026 sem conciliacao (mesmo com votos
locais), so adversarios, misto com exclusao de Solla/nao e geografia
alheia. Lease advisory election-collections serializa os dois specs que
tratam as colecoes eleitorais como test-owned (o import wipe-all apagaria
as fixtures do novo spec no meio do assert, 48-way paralelo).

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>

* refactor(A6): fixes do /simplify (3 reviewers paralelos)

P1: campo coalition morto removido do input/select/mapping (sem consumidor).
P1: hooks do lease com timeout explicito de 120s nos dois specs eleitorais
(o wait advisory passa dos 10s default do Vitest sob contencao — flake em
ambas as direcoes). P2: sonda de conciliacao via payload.count (idioma da
casa), desempate final por candidateNumber (ordem deterministica), geography
como prop na secao (sem lookup duplicado), casing Dep. Federal/Estadual
alinhado, marcador 1313 via BASELINE_TICKET_2022, entrada no CHANGELOG.

Declinados com justificativa: zones como tupla nao-vazia (churn em tipo
compartilhado por assert provada no catalogo) e early-start da promise
antes do Promise.all (loader-dentro-do-Suspense e o idioma da casa; ganho
so em cache frio).

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-07-31 00:14:27 -03:00
Cursor Agent
118544cbaa fix: remove leftover merge conflict markers in app layout 2026-07-31 02:37:17 +00:00
Cursor Agent
f1759c57a9 fix: remove unused HomeSearchProvider import (CI lint/typecheck) 2026-07-31 02:34:15 +00:00
Cursor Agent
2f1e2b7958 style: prettier after B91 scope trim 2026-07-31 02:34:15 +00:00
Cursor Agent
5d45909780 fix: drop unused quick-action setter hook until B80 2026-07-31 02:34:14 +00:00
Cursor Agent
b756f5cdf4 style: prettier 2026-07-31 02:34:14 +00:00
Cursor Agent
a2eabaccba B79 — chassis do bottom drawer de ações rápidas + busca global (mobile)
Monta CampaignQuickActionsDrawer não-modal no layout (app) para staff fora
do Início e de /acoes, com snap collapsed/expanded, padding de peek no scroll,
registry vazio para catálogos B80+, e busca global reutilizada via
CampaignStaffGlobalSearch.

Closes #15

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-07-31 02:34:08 +00:00
Francisco Solla
b2b11c3dfe Merge pull request #81 from fsolla/cursor/d2-push-sino-in-app-af30
D2 — Push + sino in-app
2026-07-30 23:25:11 -03:00
Cursor Agent
b9a81f7ad0 D2 — skip notification hooks in Vitest; fixture cleanup for push rows 2026-07-31 02:09:52 +00:00
Cursor Agent
de67acf41b D2 — Push + sino in-app para /campanha
- Collections Notification e PushSubscription com migration
- Sino no header (mobile + desktop) com drawer de avisos lidos/não lidos
- Hooks em municipalityUpdate, supporter, activity e convite aceito
- Push Web via web-push + handlers no service worker /campanha/sw.js
- Opt-in LGPD em /campanha/perfil (chave campanha-notificacoes-push)
- Testes unit/int de contrato e access

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-07-31 01:51:41 +00:00
Cursor Agent
479af4f2ef style: prettier bahiaGeometryModuleFactory 2026-07-31 01:42:01 +00:00
Cursor Agent
8188c9a386 refactor(B5): reuse BahiaFeature type and drop wrapper casts 2026-07-31 01:41:00 +00:00
Cursor Agent
ce67738485 refactor(B5): shared geometry module factory for mun/TI (F3)
Extract buildGeometryModuleFromTopology to collapse the duplicate
topojson.feature → features → optional Map pipeline in municipality
and territory geometry submodules. F2 (ensureCachedDownload) was
already delivered in scripts/lib/cli.mjs via P3-H.

Closes #28
2026-07-31 01:38:03 +00:00
Francisco Solla
c4c0d0f14a Merge pull request #70 from fsolla/cursor/b78-wizard-nav-pending-11b5
B78 — Indicação de carregamento nas ações de navegação do wizard
2026-07-30 21:35:16 -03:00
Cursor Agent
90a97d3c76 style: prettier 2026-07-31 00:27:50 +00:00
Cursor Agent
6c8d7d418c B78 — Indicar carregamento na navegação do wizard
Reusa CampaignListPendingBoundary no layout autenticado para compartilhar
useTransition entre o header mobile e o conteúdo do passo. Voltar, X, Pular,
seleção de município e tiles de passo passam por CampaignWizardNavLink;
o corpo dima com aria-busy e o header mostra skeleton nos slots de título.

CampaignTransitionAnchor agora retorna a promise do router para manter o
pending honesto até a navegação terminar.

Closes #14
2026-07-31 00:24:39 +00:00
Cursor Agent
9adf079010 B74 — Apertar gap da strip de ações do Início (gap-4 → gap-3)
Reduz o espaçamento horizontal entre botões de ação rápida na home
do /campanha, conforme feedback pós-B72. Mantém círculo 48px, largura
w-[4.75rem], pan B67 e snap inalterados.

Closes #13
2026-07-31 00:19:42 +00:00
Cursor Agent
fcbc463990 fix: format + wire WIZARD_TREND_SAVED_MESSAGE for knip 2026-07-30 23:03:25 +00:00