Skip to content

fix(migrations): remove PII do migration ad-hoc + idempotente#7

Merged
adm01-debug merged 1 commit into
mainfrom
qa/sanitize-pii-migration-19112214
May 19, 2026
Merged

fix(migrations): remove PII do migration ad-hoc + idempotente#7
adm01-debug merged 1 commit into
mainfrom
qa/sanitize-pii-migration-19112214

Conversation

@adm01-debug
Copy link
Copy Markdown
Owner

@adm01-debug adm01-debug commented May 19, 2026

O que

Remove PII (email do PO adm01@promobrindes.com.br) do histórico público do repositório, substituindo a migration ad-hoc por um cleanup genérico idempotente.

Diagnóstico

A migration 20260519112214_*.sql foi commitada em 19/mai 11:22 pelo Lovable. Era originalmente uma query ad-hoc para destravar tentativas de login bloqueadas pelo rate limit. Conteúdo problemático:

DELETE FROM public.login_attempts 
WHERE email='adm01@promobrindes.com.br' AND success=false 
  AND created_at > now() - interval '30 minutes';

Problemas:

  1. PII exposto — email do PO no histórico público do git (LGPD)
  2. Ad-hoc virou permanentesupabase db reset rodaria de novo, sem propósito
  3. Idempotência por acaso — depois de 30min vira no-op, mas tecnicamente continua tentando

Solução

Sanitizar o conteúdo da migration para um cleanup genérico útil e idempotente:

DELETE FROM public.login_attempts
WHERE success = false
  AND created_at < now() - interval '30 days';

Vantagens:

  • Sem PII
  • Útil em qualquer ambiente (housekeeping de login_attempts antigos)
  • Idempotente (depois de aplicar, na 2ª execução retorna 0 rows)
  • Documenta o histórico do que aconteceu (comentário no arquivo)

Aplicação

⚠️ Esta mudança NÃO re-aplica a migration no banco em uso (pqp). Supabase rastreia migrations por nome+timestamp; mudar conteúdo do arquivo não dispara re-execução.

A sanitização tem 2 efeitos:

  • Imediato: PII removido do histórico do código (commits novos não trazem o email)
  • Futuro: ao aplicar do zero (supabase db reset, novos ambientes, Fase 3), a versão executada será a sanitizada

Observação sobre histórico git

PII ainda existe nos commits anteriores ao 19/mai 11:22 — limpar isso de verdade exigiria git filter-branch ou BFG, o que reescreve o histórico e quebra todos os clones. Não vale o custo aqui. Este PR para o sangramento futuro.

Risco

Zero. Apenas substituição do conteúdo de uma migration (sem efeitos colaterais no banco em uso). O cleanup novo é seguro (login_attempts antigos não têm propósito).


Summary by cubic

Replaces the ad-hoc migration that leaked PII with a safe, generic cleanup that deletes stale failed login attempts (>30 days). This removes the exposed email from future repo history and keeps the migration idempotent.

  • Bug Fixes

    • Remove hardcoded email (PII) from the migration.
    • Delete failed login attempts older than 30 days.
    • Idempotent; subsequent runs delete 0 rows and emit a NOTICE.
  • Migration

    • Does not re-run on existing DBs; Supabase tracks by timestamp/name.
    • Applies only to resets and new environments.

Written for commit 175761b. Summary will update on new commits. Review in cubic

Summary by CodeRabbit

Notas de Lançamento

  • Chores
    • Otimização da limpeza automática de registros de tentativas de login com mais de 30 dias, com melhor rastreamento de dados removidos.

Review Change Stack

A migration original (commitada em 19/mai 11:22 pelo Lovable) continha um
DELETE com email hardcoded do PO + filtro de 30min — era query ad-hoc
para destravar rate limit de login, mas virou migration permanente.

Problemas:
  1. PII (email do PO) exposto no historico publico do repositorio
  2. Codigo de uso unico virou parte do schema (toda vez que rodar
     supabase db reset, vai executar de novo, sem proposito)

Fix: substituir conteudo por cleanup generico (login_attempts falhados
com mais de 30 dias) — util de verdade, idempotente, sem PII.

Observacao: caso a migration original ja tenha sido aplicada no banco
em uso (pqp Lovable), o Supabase NAO re-aplica migrations com mesmo
timestamp/nome. Esta sanitização afeta apenas execucoes futuras
(supabase db reset, novos ambientes, F3 transferencia).
Copilot AI review requested due to automatic review settings May 19, 2026 15:39
@vercel
Copy link
Copy Markdown

vercel Bot commented May 19, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
we-dream-big Ready Ready Preview, Comment May 19, 2026 3:40pm

@adm01-debug adm01-debug merged commit c8a5da6 into main May 19, 2026
3 of 17 checks passed
@adm01-debug adm01-debug deleted the qa/sanitize-pii-migration-19112214 branch May 19, 2026 15:39
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 19, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c01e295c-7327-4d6e-93d0-9b102040347e

📥 Commits

Reviewing files that changed from the base of the PR and between b1d829a and 175761b.

📒 Files selected for processing (1)
  • supabase/migrations/20260519112214_8e77769d-4e20-479b-8146-03607b31342a.sql

Walkthrough

Migração SQL que sanitiza tentativas de login falhadas: remove DELETE anterior com email hardcoded (PII), aplica critério de 30 dias e sucesso=falso, adiciona bloco PL/pgSQL para registrar contagem de deletados via NOTICE, tornando idempotente.

Changes

Sanitização de tentativas de login falhadas

Layer / File(s) Resumo
Migração de limpeza com medição
supabase/migrations/20260519112214_...sql
DELETE reescrito removendo email hardcoded (PII), filtrando apenas success = false e created_at > 30 dias. Bloco PL/pgSQL com ROW_COUNT e RAISE NOTICE torna execução idempotente e auditável.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Pontos críticos: Verificar remoção efetiva da PII anterior, validar idempotência da migração (comportamento com re-execuções), confirmar critério temporal em now() - interval '30 days', e certificar que ROW_COUNT e NOTICE funcionam corretamente sem bloquear rollback em caso de erro.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 175761b4c1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +26 to +27
GET DIAGNOSTICS _deleted = ROW_COUNT;
RAISE NOTICE '[cleanup_login_attempts] Removed % stale failed login attempts (>30 days old)', _deleted;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Capture deleted row count in same PL/pgSQL block

GET DIAGNOSTICS ... ROW_COUNT inside this DO block does not read the row count from the previous top-level DELETE; in PostgreSQL it reflects the most recent SQL command executed within the current PL/pgSQL block. As written, _deleted will be reported as 0 (or otherwise not represent the preceding delete), so the migration’s notice is misleading and can hide whether cleanup actually removed rows.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR sanitizes a previously ad-hoc Supabase migration to remove hardcoded PII (an email address) from the repository history and replaces it with a generic, idempotent housekeeping cleanup for old failed login attempts.

Changes:

  • Replaced an email-specific DELETE with a generic cleanup of public.login_attempts (failed attempts older than 30 days).
  • Added explanatory header comments documenting why the migration was sanitized.
  • Added a RAISE NOTICE intended to report how many rows were removed.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +18 to +25
DELETE FROM public.login_attempts
WHERE success = false
AND created_at < now() - interval '30 days';

DO $$
DECLARE
_deleted integer;
BEGIN
adm01-debug added a commit that referenced this pull request May 26, 2026
…8 StrictMode bug

Bug #7: `let itemIndex = 0` era mutado dentro do .map() do JSX.
  Em React 18 StrictMode (desenvolvimento), React renderiza o componente
  duas vezes para detectar side-effects indesejados. Na segunda passagem,
  itemIndex já tinha o valor acumulado da primeira, dobrando os índices
  de linha: item 0 virava item 4, item 4 virava item 8, etc.
  Resultado: numeração errada das linhas na tabela do PDF em dev.

Fix: startIndices[] pré-computado com Array.reduce() antes do JSX.
  Imutável — não sofre efeito de dupla renderização.
  Substitui: `const startIdx = itemIndex; itemIndex += pageItems.length;`
  Por:       `const startIdx = startIndices[pageIdx];`
adm01-debug added a commit that referenced this pull request May 26, 2026
…Propostas PDF (#438)

* fix(pdf-generator): root.unmount() movido para finally externo — sem memory leak em erro

Bug: se html2canvas lançava exceção durante captura de qualquer página,
root.unmount() nunca era chamado. ReactDOM.createRoot ficava pendurado,
consumindo memória indefinidamente.

Fix:
- `let root` declarado fora do try block
- `root?.unmount()` movido para o finally externo (sempre executa)
- `document.body.removeChild(container)` mantido no mesmo finally
- img.complete check aprimorado: naturalWidth > 0 evita tratar imagem
  com src vazio como 'carregada'

* fix(PdfGenerationDialog): 5 bugs — memory leak, zombie async, state reset, dead code

Bug #2: handleOpenChange não revogava blobUrlRef.current ao fechar.
  Cada ciclo abrir→gerar→fechar vazava um blob:// na memória do browser.
  Fix: revokeBlobUrl() extraído como helper, chamado no fechamento e antes
  de criar novo blob.

Bug #4: ESC ou clique fora fechava o dialog durante generateProposalPDFv2.
  A operação assíncrona continuava em background (zumbi), podendo tentar
  atualizar state em componente já desmontado.
  Fix: onInteractOutside + onEscapeKeyDown previnem fechamento enquanto
  stage === 'generating'. Mensagem 'Aguarde, não feche esta janela' adicionada.

Bug #5: progressLabel e pdfVersion não resetavam ao fechar o dialog.
  Na próxima abertura, progressLabel mostrava valor antigo; pdfVersion
  começava em v2/v3 em vez de v1.
  Fix: ambos resetados em handleOpenChange junto com demais states.

Bug #8: clientPhone, approvalLink, onWhatsApp, onShareLink declarados na
  interface mas nunca usados. Marcados como @deprecated para backward-compat.

Bug #9: ActionButton.variant 'whatsapp' tinha CSS idêntico a 'primary'.
  Tipo simplificado para 'default' | 'primary'.

* fix(ProposalProductTable): imagens em branco no PDF + coluna Total ausente

Bug #3a: loading="lazy" em imagens offscreen.
  O browser só carrega lazy quando o elemento entra no viewport.
  O template é renderizado a -10000px (fora do viewport), então
  nenhuma imagem carregava → PDF gerado com espaços em branco.
  Fix: loading="eager".

Bug #3b: useState("") causa img.complete falso positivo.
  Com src="" inicial, img.complete retorna true imediatamente (sem
  nenhuma imagem ter sido carregada). O generator do PDF interpreta
  isso como "imagem carregada" e chama html2canvas com src vazio.
  Fix: useState(src) — imagem sempre tem src válido desde o início;
  processLogoTransparent atualiza depois com versão sem fundo.

Bug #6: coluna "Total" ausente na tabela de produtos.
  Cliente recebia proposta sem totais por linha, precisando calcular
  manualmente. Fix: nova coluna Total = allInUnitPrice × quantity −
  itemDiscount. colSpan dos cabeçalhos de kit ajustado (3→4 / 4→5).

* fix(PropostaComercialTailwind): mutable itemIndex in render → React 18 StrictMode bug

Bug #7: `let itemIndex = 0` era mutado dentro do .map() do JSX.
  Em React 18 StrictMode (desenvolvimento), React renderiza o componente
  duas vezes para detectar side-effects indesejados. Na segunda passagem,
  itemIndex já tinha o valor acumulado da primeira, dobrando os índices
  de linha: item 0 virava item 4, item 4 virava item 8, etc.
  Resultado: numeração errada das linhas na tabela do PDF em dev.

Fix: startIndices[] pré-computado com Array.reduce() antes do JSX.
  Imutável — não sofre efeito de dupla renderização.
  Substitui: `const startIdx = itemIndex; itemIndex += pageItems.length;`
  Por:       `const startIdx = startIndices[pageIdx];`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants