Replace the `Function`-typed payload param (no-unsafe-function-type lint error
blocking pre-push) with `Pick<Payload, 'find' | 'create'>`, which also surfaced
missing Lexical `version` fields in the consent fixture — now added.
Rename the operational unit "Praça"/"Núcleo" to "Município" (code identifier
`municipality`) and land the 2026-07-23 course changes:
- New `candidate` role with unrestricted visibility (`isCampaignStaff` now
includes it) alongside coordinator/advisor; leader is locked down to the
supporter contact tool only.
- Demandas become staff-only; dobradinhas modeled via a `stateDeputy` entity.
- Camaçari consolidated to a single município (ZE 170/171 aggregated);
Salvador keeps its 19 zone municípios.
- Map moves to the staff dashboard; `/campanha/municipios` is list/overview.
- Vote pledges keep the declared vs estimated (scenario) asymmetry; leaders
never see estimates.
Destructive migration for the campaign vertical (drops nucleus/plaza-era
tables, wipes campaign rows, seeds 435 municípios). Public-site data untouched.
Includes the post-delivery /simplify cleanups: shared reloadStaffActor /
reloadCoordinatorActor helpers, req.context cache for getFreshCampaignUser,
parallelized dashboard loads, candidate dashboard-copy fix, and dead
leader-dashboard / roleKind code removal.
436 seeded Praças (municipality-based; per-TSE-zone in Salvador/Camaçari) become
the operational unit; roles renamed to coordinator/advisor/leader with advisors
scoped to administered Praças. Leadership is one record per person across many
Praças/organizations; vote pledges split leader-declared vs staff-estimated
(estimates never serialized to leaders). Adds organizations, demand workflow
with staff-only cost/receipts, action-plan results with deputy presence, manual
political trend, multi-candidate comparison and the diverging red/white/blue
map mode. Migration 20260721_020109_remodel_plazas deliberately resets the
campaign vertical in production (public site untouched); test suite ported to
the new model (unit 187 / int 306 / e2e 9 green).
Align the campaign desk with quieter KPI strips, queues-first dashboard, shared shells, and advanced filters; capture Impeccable design context and the remaining simplify/critique debts on the roadmap.
Phase 1 UX: StrictCombobox municipality in SupporterForm, AlertDialog in
RemoveSupporterDataButton. Phase 2 DRY: campaignListUrl + CampaignListPagination
+ campaignFormFields + mapCampaignFormActionError shared across nuclei,
supporters and action plans. Phase 3: single SQL aggregate for supporter list
KPIs via drizzle in the Payload txn. Phase 4: bulk drizzle insert for CSV import
inside the existing Payload txn with ON CONFLICT DO NOTHING, plus a fail-closed
skipContactPhoneInvariant context flag. Phase 5: HMAC-signed single-use import
token backed by a new supporterImportBatch staging collection so the full ok-row
set never crosses the Server Action boundary twice.
Replace scalar region/city/neighborhood with hasMany arrays so nuclei can span multiple Bahia municipalities while keeping neighborhoods scoped to a single city.
Adds electoral nuclei, leaderships, updates, and WhatsApp invite flows behind campaign auth, plus the consolidated schema migration that Vercel applies on deploy.