From aff8c6cbf37e404784fb682bd26d2fae64eb781a Mon Sep 17 00:00:00 2001 From: Francisco Solla Date: Mon, 24 Aug 2026 23:57:52 -0300 Subject: [PATCH] =?UTF-8?q?fix(test):=20S9+=20=E2=80=94=20harness=20ciente?= =?UTF-8?q?=20do=20guard=20de=20Consent=20(CI=20do=20#771)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - campaignSupporter: destaca voteIntentionConsent dos supporters antes de purgar o consent canônico de intenção de voto — o seed mínimo cria vínculos vivos nessa chave, e o delete passou a depender do SET NULL silencioso que o guard agora bloqueia (falha determinística em DB fresca de CI). - campaignInvite: purga da chave lideranca-autopreenchimento na janela mutável passa a raw SQL (precedente Onda0/lease) — lifecycle de harness nunca deve passar pelo caminho admin/beforeDelete. --- tests/int/campaignInvite.int.spec.ts | 10 ++++++---- tests/int/campaignSupporter.int.spec.ts | 11 +++++++++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/tests/int/campaignInvite.int.spec.ts b/tests/int/campaignInvite.int.spec.ts index d408efb2..a3a9b74a 100644 --- a/tests/int/campaignInvite.int.spec.ts +++ b/tests/int/campaignInvite.int.spec.ts @@ -611,10 +611,12 @@ describe('campaign invite domain', () => { const actions = await import('@/app/(campaign)/campanha/actions/invite').catch(() => null) expect(actions).not.toBeNull() - await payload.delete({ - collection: 'consent', - where: { key: { equals: 'lideranca-autopreenchimento' } }, - }) + // Harness purge (Onda0-provision / lease precedent): raw SQL so the + // admin-path beforeDelete guard and access checks never apply to this + // lifecycle setup — the window lease already guarantees isolation. + await payload.db.drizzle.execute( + sql`DELETE FROM "consent" WHERE "key" = ${'lideranca-autopreenchimento'}`, + ) const coordinator = await campaignFixtures().createCampaignUser('coordinator') const municipality = await campaignFixtures().getMunicipality() const { leadership } = await createInviteLeadershipGraph(coordinator, municipality.id) diff --git a/tests/int/campaignSupporter.int.spec.ts b/tests/int/campaignSupporter.int.spec.ts index 3ba7ee4a..96432978 100644 --- a/tests/int/campaignSupporter.int.spec.ts +++ b/tests/int/campaignSupporter.int.spec.ts @@ -212,6 +212,17 @@ describe('campaign supporter domain', () => { limit: 1, }) if (existingVoteConsent.docs[0]) { + // S9+: Consent.beforeDelete refuses deleting an in-use legal text. The + // minimal seed links seeded supporters to this canonical consent, so + // detach the live voteIntentionConsent references FIRST — the explicit, + // ordered version of the FK `ON DELETE SET NULL` this purge relied on + // silently before the guard existed. + await payload.update({ + collection: 'supporter', + where: { voteIntentionConsent: { equals: existingVoteConsent.docs[0].id } }, + data: { voteIntentionConsent: null }, + overrideAccess: true, + }) await payload.delete({ collection: 'consent', id: existingVoteConsent.docs[0].id,