teqo-backup/src/utilities/leadershipConflict.ts
Francisco Solla c0645067f1 feat(C128): ciclo de vida das capacidades pelas células de /campanha/pessoas (Closes #695)
Qualquer pessoa visível ganha/perde Assessora, Lidera e Aliada em pela
lista: a primeira cidade cria a entidade (conta staff sem credenciais
utilizáveis / liderança / dobradinha), a última remove da tabela com
confirmação destrutiva (manifest: votos+convites da liderança, conta+
autorias+assessorado da assessora; dobradinha sem diálogo). Saída
destrutiva por escopo: assessor encerra Lidera/Aliada com a capacidade
inteira na carteira; Assessora segue coordenação/candidato. Escritas
person-centric por contactId com extração dos deltas B34/B37 e da
cascata de conta (deleteCampaignUserAccount, nextFreeStubCampaignEmail,
matchers de conflito) — sem twin. commitGuard/commitWithNullOwner/
extraFormFields como opt-ins no RelationChipCell. Corrige bug latente
C116 (célula Assessora nunca salvava — contactId faltava no FormData).
Sem migration. Int: 28, unit: 6, e2e: +2.
2026-08-12 15:29:56 -03:00

21 lines
844 B
TypeScript

import 'server-only'
/**
* C128 — shared leadership identity-conflict matcher. Was private to
* `actions/leadership.ts` (create path); the person lifecycle
* (`setPersonLeadershipMunicipalitiesRecord`) creates leaderships too, and the
* `contact` unique violation must map to the same safe message in both
* surfaces. Lives outside the 'use server' module because a plain const cannot
* be re-exported from one (Next.js allows only async function exports there).
*/
export const isUniqueLeadershipConflict = (error: unknown): boolean => {
const message = error instanceof Error ? error.message : String(error)
if (/leadership_contact|duplicate key/i.test(message)) {
return true
}
if (!(error instanceof Error) || error.name !== 'ValidationError') return false
return /contact(?:_id)?/i.test(JSON.stringify(error))
}