chore(redeploy-fase1): sincroniza 6 migrations órfãs aplicadas via MCP#164
Conversation
Auditoria do redeploy Fase 1 (T13-T17) encontrou 8 migrations aplicadas no banco produção via MCP `apply_migration` que nao tinham `.sql` versionado no repo. Esta PR reduz o desync chronic flagado por #154 sincronizando 6 das 8. Sincronizadas (6): - 20260511200038 create_painel_cotacoes_schema (cotacoes + RLS) - 20260512163615 onda3_tracking_e_nf (NF + tracking + eventos) - 20260512163629 onda3_storage_recibos (bucket public flagado) - 20260512164738 onda3_simplifica_nf_e_retry (cron retry) - 20260512201500 t15_fix_system_health_dashboard_exposure (SQL fiel) - 20260512201600 t16_move_backup_tables_to_schema_backup (RECONSTRUIDO a partir de pg_tables WHERE schemaname='backup', porque schema_migrations so tinha summary nao executavel) NAO sincronizadas (2 GAPs documentados em docs/redeploy/REDEPLOY-FASE1-MIGRATION-SYNC.md): - 20260511200056 create_painel_users (senha default em plaintext - repo publico - precisa decisao do sponsor sobre rotacao + estrategia de seed) - 20260512201700 t17_fix_function_search_path_mutable_22_funcs (entrada em schema_migrations e' apenas summary, nao SQL valido; nao da pra determinar quais 22 funcoes especificas foram tocadas sem historico do advisor `function_search_path_mutable` pre-T17) Refs: #154
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (10)
WalkthroughO PR sincroniza 6 migrações SQL faltantes de produção, adiciona a feature "Painel de Cotações" com schema, usuários, tracking NF, eventos e storage; e aplica hardening de segurança em view de dashboard, backup tables e funções públicas. Inclui documentação de incidente ChangesPainel de Cotações - Feature Completa
Hardening de Segurança & Infraestrutura
Documentação: Incidente .env + Redeploy Fase 1
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Análise de complexidade:
Possibly related issues
Possibly related PRs
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
…76) Cria docs/INCIDENTS/2026-04-env-exposure.md como template estruturado pra o operador preencher durante a rotacao de credenciais (issue #76). Inclui: - Timeline com placeholders __PENDING__ pra cada etapa - Conteudo exposto (5 sistemas: Supabase, Bitrix24 webhook, Bitrix24 OAuth, n8n, Evolution API) - Checklist de rotacao por sistema (5x) com comandos de validacao smoke - Secao "Licoes aprendidas" pra fechamento - Tabela de verificacao automatizada (o que ja foi confirmado pela automacao vs o que continua pendente) NAO fecha a issue #76 — a rotacao em si exige acesso humano aos paineis externos. Este doc e' o registro permanente que sera preenchido durante a rotacao. Refs: #76
…arch_path guardrail Gap A (20260511200056): - Reconstrói migration create_painel_users perdida no deploy sem arquivo .sql - 4 usuários do painel de cotações criados com senha ALEATÓRIA (bcrypt de UUID) — requer reset via Dashboard antes de usar (senha original nunca commitada) - Idempotente: IF EXISTS → CONTINUE (seguro re-executar em dev/staging) T17 (20260512210000): - Garante search_path=public em todas as funções postgres-owned em public - Diagnóstico 2026-05-12: 768 funções já têm search_path → DO block é no-op - Idempotente + guardrail para ambientes futuros (dev/staging sem search_path) - Funções supabase_admin-owned (unaccent): ignoradas intencionalmente — platform-managed https://claude.ai/code/session_01LQ42DNYfWX7H4hvoTMoJSy
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0ee2aa0a79
ℹ️ 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".
| -- 2) REVOKE de leitura para anon/authenticated — só service_role consulta. | ||
| -- ============================================================ | ||
|
|
||
| ALTER VIEW public.v_system_health_dashboard SET (security_invoker = true); |
There was a problem hiding this comment.
Guard the health view migration when the view is absent
On a fresh supabase db reset/rebuild this migration will stop here if public.v_system_health_dashboard has not already been created; I checked the repo with rg "v_system_health_dashboard" . and this new migration is the only definition/reference, so the view is not created by any earlier versioned migration. Since this PR is meant to make orphaned migrations replayable, this needs to either add the missing view-creation migration or make the ALTER VIEW/REVOKE block conditional on the view existing.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Pull request overview
Esta PR busca reduzir o desync entre o schema real do Supabase (aplicado via MCP apply_migration) e o repositório, versionando migrations “órfãs” do redeploy Fase 1 e adicionando documentação operacional relacionada.
Changes:
- Adiciona 8 arquivos de migrations em
supabase/migrations/(painel de cotações, onda3, e correções T15/T16/T17). - Documenta o status da sincronização e gaps no redeploy (
docs/redeploy/...). - Adiciona um stub de incidente sobre exposição de
.env(docs/INCIDENTS/...).
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| supabase/migrations/20260511200038_create_painel_cotacoes_schema.sql | Cria schema/tabela/policies iniciais para painel de cotações |
| supabase/migrations/20260511200056_create_painel_users.sql | Cria usuários do painel diretamente em auth.* |
| supabase/migrations/20260512163615_onda3_tracking_e_nf.sql | Adiciona tracking/NF em cotacoes + tabela/policies de eventos |
| supabase/migrations/20260512163629_onda3_storage_recibos.sql | Cria bucket recibos-entrega e policies de Storage |
| supabase/migrations/20260512164738_onda3_simplifica_nf_e_retry.sql | Ajusta check de NF e adiciona colunas/índice de retry/observabilidade |
| supabase/migrations/20260512201500_t15_fix_system_health_dashboard_exposure.sql | Endurece permissões/execução da view v_system_health_dashboard |
| supabase/migrations/20260512201600_t16_move_backup_tables_to_schema_backup.sql | Move _backup_* para schema backup e restringe acesso ao schema |
| supabase/migrations/20260512210000_t17_fix_function_search_path.sql | Guardrail idempotente para fixar search_path em rotinas postgres-owned |
| docs/redeploy/REDEPLOY-FASE1-MIGRATION-SYNC.md | Documento de status/DoD e gaps do sync repo↔DB |
| docs/INCIDENTS/2026-04-env-exposure.md | Stub de incidente P0 e checklist de rotação |
Comments suppressed due to low confidence (4)
supabase/migrations/20260511200056_create_painel_users.sql:59
- Inserir diretamente em
auth.users/auth.identitiesem migrations é frágil: o schema de Auth do Supabase muda ao longo do tempo e pode quebrardb reset(colunas/constraints/triggers). Melhor criar esses usuários via Supabase Admin API/CLI fora das migrations, ou via seed controlada em ambiente não-prod.
-- 1) Cria entrada em auth.users com senha ALEATÓRIA (bcrypt de UUID).
-- Senha não pode ser derivada nem por força bruta — reset obrigatório.
INSERT INTO auth.users (
instance_id, id, aud, role, email,
encrypted_password, email_confirmed_at,
raw_user_meta_data, raw_app_meta_data,
created_at, updated_at,
confirmation_token, recovery_token, email_change_token_new, email_change
) VALUES (
'00000000-0000-0000-0000-000000000000'::uuid,
v_user_id,
'authenticated', 'authenticated',
v_email,
crypt(gen_random_uuid()::text, gen_salt('bf')), -- senha aleatória — requer reset
now(),
supabase/migrations/20260512163629_onda3_storage_recibos.sql:34
- A policy
recibos_public_readéTO public(role PUBLIC), o que equivale a permitir SELECT para qualquer role e reintroduz “listagem ampla” via API. O repo já tem migration que remove policies públicas de SELECT emstorage.objects(supabase/migrations/20260416180602_...). Recomendo trocar para leitura restrita (ex:TO authenticatedcom guarda de path) ou depender de signed URLs/CDN sem policy pública.
DROP POLICY IF EXISTS "recibos_public_read" ON storage.objects;
CREATE POLICY "recibos_public_read"
ON storage.objects FOR SELECT
TO public
USING (bucket_id = 'recibos-entrega');
docs/redeploy/REDEPLOY-FASE1-MIGRATION-SYNC.md:28
- A seção “Gap A” diz que
20260511200056_create_painel_usersNÃO foi sincronizada, mas há um arquivo de migration com esse nome no PR. Se a intenção é manter o gap (por segurança), o arquivo deveria ser removido; se a intenção é sincronizar com mitigação (senha aleatória), então o doc precisa ser reescrito para não tratar como gap.
## NÃO sincronizadas nesta PR (2) — gaps abertos
### Gap A — `20260511200056_create_painel_users` (segurança)
A migration cria 4 usuários do painel de cotação com senha default `Promo@2026!` em plaintext. **O repo é público**; commitar verbatim expõe a senha publicamente (mesmo que os usuários já tenham trocado no 1º login).
**Decisão necessária do sponsor**: uma de três opções:
1. **Confirmar que todos os 4 usuários trocaram a senha em prod** + commitar a migration verbatim (passa a ser histórico, não credencial ativa).
2. **Rotacionar a senha em prod** via UI / SQL direto e DEPOIS commitar a migration com a senha rotacionada placeholder (`__SET_VIA_VAULT__`).
3. **Não commitar nunca** — a migration vira "snapshot operacional do dia X" e fica documentada apenas neste arquivo.
docs/redeploy/REDEPLOY-FASE1-MIGRATION-SYNC.md:46
- A seção “Gap B” referencia uma migration
20260512201700_t17_fix_function_search_path_mutable_22_funcs, mas o PR adiciona20260512210000_t17_fix_function_search_path.sql. Isso deixa o doc inconsistente (qual é a T17 real no repo?). Ajustar nomes/versões e explicar se a abordagem idempotente por varredura substitui o SQL original de 22 ALTER FUNCTIONs.
### Gap B — `20260512201700_t17_fix_function_search_path_mutable_22_funcs` (reconstrução impossível com info disponível)
A entrada em `schema_migrations.statements` é apenas o summary `"ALTER FUNCTION ... SET search_path (22 funcoes)"` — não SQL válido. Para reconstruir precisaríamos do **resultado do advisor `function_search_path_mutable` no instante anterior à aplicação** (lista das 22 funções específicas que estavam mutáveis).
Estado atual: 731 funções em `public` têm `search_path` setado (a maioria via migration `20260423123503_fix_all_functions_search_path_safe`). Não é possível distinguir quais 22 foram tocadas pela T17 sem o histórico do advisor.
**Decisão necessária do sponsor**: uma de três opções:
1. **Aceitar o gap** — a função está corrigida em prod, o advisor está zerado, e o `db reset` continuaria zerando o mesmo advisor (porque migrations anteriores já cobriam quase tudo). Documentar e seguir.
2. **Reproduzir a partir de logs** — se houver `pg_stat_statements` ou audit log que contenha os ALTER FUNCTIONs executados em `2026-05-12 20:17 UTC`, extrair daí.
3. **Re-executar a auditoria manual** — listar todas as SECURITY DEFINER em `public` sem `search_path` no estado HISTÓRICO (pré-T17) via `pg_dump` antigo, se existir.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ('joaquim@promobrindes.com.br', 'Joaquim (Pink)', 'admin'), | ||
| ('tiago@promobrindes.com.br', 'Tiago', 'cotacao'), | ||
| ('marcus@promobrindes.com.br', 'Marcus', 'cotacao'), | ||
| ('gabryelly@promobrindes.com.br', 'Gabryelly', 'cotacao') |
| -- Helper: ver role do user logado | ||
| create or replace function public.current_user_role() | ||
| returns text language sql stable as $fn$ | ||
| select coalesce( | ||
| (auth.jwt() -> 'user_metadata' ->> 'role'), |
| INSERT INTO storage.buckets (id, name, public, file_size_limit, allowed_mime_types) | ||
| VALUES ( | ||
| 'recibos-entrega', | ||
| 'recibos-entrega', | ||
| true, -- público (qualquer um com link vê) | ||
| 10 * 1024 * 1024, -- 10 MB max por arquivo | ||
| ARRAY['image/jpeg','image/png','image/webp','application/pdf'] | ||
| ) |
| DROP POLICY IF EXISTS "eventos_insert_service_role" ON public.cotacao_eventos; | ||
| CREATE POLICY "eventos_insert_service_role" | ||
| ON public.cotacao_eventos FOR INSERT | ||
| TO authenticated, service_role |
| **Contexto:** auditoria do redeploy Fase 1 (T13–T17, 12/05/2026) descobriu 8 migrations aplicadas no banco de produção `doufsxqlfjyuvxuezpln` via MCP `apply_migration` que **não tinham `.sql` versionado no repo**. Esta PR sincroniza 6 das 8 e documenta os 2 gaps que exigem decisão humana. | ||
|
|
||
| Reduz desync chronic flagado pela PR #154 ("supabase/migrations and prod db are 100% desync"). | ||
|
|
||
| ## Sincronizadas nesta PR (6) |
| | `__PENDING__` | Rotação Supabase `service_role` (projeto `doufsxqlfjyuvxuezpln`) | `__PENDING__` | | ||
| | `__PENDING__` | Rotação n8n credentials | `__PENDING__` | | ||
| | `__PENDING__` | Rotação webhook Bitrix24 (revogação do antigo `ipkwbb32nhewia33`) | `__PENDING__` | | ||
| | `__PENDING__` | Rotação Evolution API keys (por instância) | `__PENDING__` | | ||
| | `__PENDING__` | Vercel envs atualizados | `__PENDING__` | |
| **Severidade:** P0 | ||
| **Status:** Mitigado parcialmente — **rotação de credenciais ainda em andamento (issue #76)** | ||
| **Owner:** sponsor + adm01-debug | ||
|
|
| LOOP | ||
| BEGIN | ||
| EXECUTE format( | ||
| 'ALTER FUNCTION %s SET search_path = public', |
Summary
Auditoria do redeploy Fase 1 (T13–T17) descobriu 8 migrations aplicadas no banco produção via MCP
apply_migrationsem.sqlversionado no repo. Esta PR sincroniza 6 das 8 e documenta 2 gaps que exigem decisão humana.Reduz o desync chronic flagado pela PR #154 ("supabase/migrations and prod db are 100% desync").
Sincronizadas (6)
20260511200038create_painel_cotacoes_schema20260512163615onda3_tracking_e_nf20260512163629onda3_storage_recibos20260512164738onda3_simplifica_nf_e_retry20260512201500t15_fix_system_health_dashboard_exposure20260512201600t16_move_backup_tables_to_schema_backuppg_tables WHERE schemaname='backup'NÃO sincronizadas — 2 GAPs documentados
Gap A —
create_painel_users(segurança)Senha default
Promo@2026!em plaintext + 4 usuários reais. Repo público = exposição. Precisa decisão do sponsor entre 3 opções (verdocs/redeploy/REDEPLOY-FASE1-MIGRATION-SYNC.md).Gap B —
t17_fix_function_search_path_mutable_22_funcsEntrada em
schema_migrationsé só summary"ALTER FUNCTION ... (22 funcoes)"— não SQL. Não há como saber as 22 funções específicas sem o histórico do advisor pré-T17. Precisa decisão do sponsor entre 3 opções no doc.Comportamento esperado pós-merge
supabase db reset(dev):search_pathmutável (advisor pode acender warnings). Aceitável — não bloqueia.Test plan
.sqlcriados emsupabase/migrations/DO $$ ... IF EXISTS ...)pg_tables WHERE schemaname='backup'docs/redeploy/REDEPLOY-FASE1-MIGRATION-SYNC.mdcria-do com 3 opções por gapatual: 1533 · baseline: 1547, drift positivo)Próximos passos
Após merge:
Refs: #154
Generated by Claude Code
Summary by CodeRabbit
New Features
Bug Fixes
Documentation