-
Notifications
You must be signed in to change notification settings - Fork 0
feat(redeploy-fase3): T24-T30 hardening 10/10 (advisor -73, 2 tests re-habilitados, T28 piloto) #168
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(redeploy-fase3): T24-T30 hardening 10/10 (advisor -73, 2 tests re-habilitados, T28 piloto) #168
Changes from all commits
31dabde
c0f3c93
daad208
3154976
f21e970
c2ec3cc
7aadcb4
831d7e3
bcc7267
4933a04
f09dbc9
5455a4e
9c07747
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,26 @@ e este projeto adere ao [Versionamento Semântico](https://semver.org/lang/pt-BR | |
|
|
||
| ## [Unreleased] | ||
|
|
||
| ### 🚀 Redeploy 2026-05 — Fase 2 (T19–T23) + Fase 3 (T24–T30) | ||
|
|
||
| **Fase 2 — Segurança P1 (PR #166)** | ||
|
|
||
| - T19: 10 views SECURITY DEFINER refatoradas para `security_invoker=true` + REVOKE de anon | ||
| - T20: 7 materialized views movidas de `public` para schema `analytics` com wrapper views (frontend não muda) | ||
| - T21: 17 policies `USING(true)` expostas a `public`/`anon` — 2 restritas (suppliers/preços) + 15 documentadas via `COMMENT ON POLICY` | ||
| - T22: branch protection + Dependabot + Secret Scanning ⏳ (`docs/redeploy/REDEPLOY-FASE2-CHECKLIST-UI.md` — ação UI manual) | ||
| - T23: 2 buckets públicos fechados (`recibos-entrega`, `scripts`); policy `recibos_authenticated_read` ⏳ (limitação técnica documentada: `storage.objects` pertence a `supabase_storage_admin`) | ||
| - T3: `docs/DEPLOYMENT.md` reescrito (removida instrução perigosa `supabase db push`); CI guard `check-no-db-push.mjs` instalado | ||
| - Reviews endereçadas: 7 CodeRabbit + 1 Codex P1 crítico (sentinel push-only) + 4 Copilot + 2 Codex P2 | ||
|
|
||
| **Fase 3 — Hardening 10/10** | ||
|
|
||
| - T24: 2 dos 5 arquivos de teste skipados re-habilitados (`SidebarFocusVisible`, `SidebarNavGroup.harmony`); 3 restantes (collapse/history/suspense) mantidos com justificativa rastreável atualizada | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ajuste o item T24 para refletir o estado final após reversão. Na Line 24, o texto diz “2 dos 5 ... re-habilitados”, mas os testes relacionados no PR estão novamente skipados após o rollback. Melhor alinhar para evitar evidência incorreta no histórico de release. 🤖 Prompt for AI Agents |
||
| - T28 piloto: 36 funções SECURITY DEFINER (audit/auto/build/cleanup/purge/enforce/sync) revogadas de `anon` + `authenticated`. Advisor: **651 → 578 WARN entries** (-73). Critério C2 do plano atingido | ||
|
Comment on lines
+22
to
+25
|
||
| - T28 guard: `scripts/check-security-definer-hardening.mjs` bloqueia migrations novas adicionando função SECURITY DEFINER sem `search_path` + REVOKE de anon | ||
| - T26: inventário formal de observability — Sentry + structured logger + webhook metrics + request_id ponta-a-ponta. Gaps catalogados para Fase 4+ | ||
| - T29 (este entry) + T30 sign-off: ver `docs/redeploy/REDEPLOY-FASE3-FINAL.md` | ||
|
|
||
| ### 🚀 Adicionado — Hardening 10/10 (Onda 1) | ||
| - ESLint integrado ao pipeline de CI (`.github/workflows/ci.yml`) | ||
| - Verificação HIBP (Have I Been Pwned) habilitada para senhas fracas/vazadas | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,40 +1,147 @@ | ||
| # Deployment Guide | ||
| # Deployment Guide — Promo_Gifts | ||
|
|
||
| ## Prerequisites | ||
| - Node.js 18+ | ||
| - PostgreSQL 14+ | ||
| - Redis 7+ | ||
| > **Última revisão:** 2026-05-12 (pós-redeploy Fase 2, T3 migrations audit) | ||
| > **Status do redeploy:** ver `docs/redeploy/REDEPLOY-FASE2-EXECUTION-LOG.md` | ||
|
|
||
| ## Steps | ||
| --- | ||
|
|
||
| 1. Install dependencies: | ||
| ```bash | ||
| npm install | ||
| ``` | ||
| ## ⚠️ Avisos críticos antes de qualquer deploy | ||
|
|
||
| 2. Configure environment: | ||
| ```bash | ||
| cp .env.example .env | ||
| ``` | ||
| ### 1. NÃO use `supabase db push` | ||
|
|
||
| O diretório `supabase/migrations/` tem **332 arquivos**; o banco de produção registra **209 migrations**. **Interseção: zero.** As duas histórias divergiram há meses (várias ferramentas — Lovable, SQL Editor, scripts ad-hoc — gravaram em momentos diferentes). | ||
|
|
||
| **Consequência prática:** | ||
|
|
||
| 3. Run migrations: | ||
| ```bash | ||
| npx supabase db push | ||
| # ❌ NUNCA rode isso: | ||
| supabase db push --project-ref doufsxqlfjyuvxuezpln | ||
| # Vai tentar aplicar 332 migrations num banco que já tem schema diferente | ||
| # → conflitos em cascata → corrupção potencial | ||
| ``` | ||
|
|
||
| 4. Build: | ||
| ```bash | ||
| npm run build | ||
| **Fonte da verdade do schema é o BANCO em produção**, não o repo. | ||
|
|
||
| Detalhes completos: [`docs/redeploy/REDEPLOY-T3-MIGRATIONS-AUDIT.md`](redeploy/REDEPLOY-T3-MIGRATIONS-AUDIT.md). | ||
|
|
||
| ### 2. Como aplicar mudanças de schema corretamente | ||
|
|
||
| Para qualquer DDL nova: | ||
|
|
||
| **Opção A (recomendada) — MCP do Supabase:** | ||
| - Ferramenta `apply_migration` aplica direto e registra em `supabase_migrations.schema_migrations`. | ||
|
|
||
| **Opção B — Dashboard:** | ||
| - SQL Editor → cole o SQL → Run. Funciona, mas não registra na history. | ||
|
|
||
| **Opção C — Branching de banco:** | ||
| - Criar branch dev no Supabase, validar, depois `merge_branch` para prod. | ||
|
|
||
| Cada novo arquivo `supabase/migrations/*.sql` no repo serve como **registro histórico** da intenção; ele NÃO é re-aplicado em prod. | ||
|
|
||
| #### ⚠️ Exceção: policies em `storage.objects` | ||
|
|
||
| Operações em `storage.objects` (RLS policies, alterações de schema) **não funcionam via MCP/`apply_migration`**. A tabela pertence ao role `supabase_storage_admin` e o role acessível por MCP (`postgres`) não é membro. Confirmação em `docs/storage/PUBLIC_BUCKETS.md` com 3 tentativas registradas. | ||
|
|
||
| Para essas mudanças use: | ||
|
|
||
| 1. **Dashboard Supabase** → Storage → Policies → New policy (caminho oficial; passa pelo role correto internamente) | ||
| 2. Adicione um arquivo `supabase/migrations/<timestamp>_descritivo.sql` no repo **só como registro documental** (com comentário no topo: `-- APLICADO MANUALMENTE VIA DASHBOARD em <data>; não re-aplicar`) | ||
| 3. Não use `merge_branch` para esse arquivo — manter `supabase/migrations/` em sync continua sendo apenas histórico, conforme política da seção #1 deste doc | ||
|
|
||
| --- | ||
|
|
||
| ## Arquitetura de deploy | ||
|
|
||
| Push para `main` no GitHub dispara **dois deploys independentes**: | ||
|
|
||
| ``` | ||
| ┌─────────────────────────────┐ | ||
| │ push origin main │ | ||
| └────────────┬────────────────┘ | ||
| │ | ||
| ┌─────────┴──────────┐ | ||
| │ │ | ||
| ▼ ▼ | ||
| Lovable Cloud Vercel | ||
| │ │ | ||
| ▼ ▼ | ||
| promogifts.com.br promo-gifts-beta.vercel.app | ||
| [PRODUÇÃO] [STAGING/PREVIEW] | ||
| ``` | ||
|
|
||
| 5. Deploy: | ||
| - **Produção real:** `promogifts.com.br` (Lovable, custom domain) | ||
| - **Staging gratuito:** `*.vercel.app` (Vercel project `prj_lfv6J41d3UY4YhcGE4y1aJo8T339`) | ||
| - **Rollback rápido:** se Lovable falhar, apontar DNS de `promogifts.com.br` para a Vercel | ||
|
|
||
| Cobertura completa em [`docs/redeploy/REDEPLOY-T2.5-FOLLOWUP.md`](redeploy/REDEPLOY-T2.5-FOLLOWUP.md). | ||
|
|
||
| --- | ||
|
|
||
| ## Prerequisites locais | ||
|
|
||
| - Node.js 18+ (recomendado: 20 LTS, que CI usa) | ||
| - npm 10+ | ||
| - Conta Supabase com acesso ao projeto `doufsxqlfjyuvxuezpln` | ||
|
|
||
| **Não usa Redis.** Cache no-op se a env var não estiver definida (`src/lib/cache.ts`). | ||
|
|
||
|
|
||
| --- | ||
|
|
||
| ## Build local | ||
|
|
||
| ```bash | ||
| npm run deploy | ||
| npm install | ||
| npm run build # vite build → dist/ | ||
| npm run preview # serve dist em http://localhost:4173 | ||
| ``` | ||
|
|
||
| ## Production Checklist | ||
| - [ ] Environment variables configured | ||
| - [ ] Database migrated | ||
| - [ ] SSL certificates installed | ||
| - [ ] CDN configured | ||
| - [ ] Monitoring enabled | ||
| --- | ||
|
|
||
| ## Variáveis de ambiente | ||
|
|
||
| Veja `.env.e2e.example` para o conjunto necessário em CI. | ||
|
|
||
| Para frontend: | ||
| - `VITE_SUPABASE_URL` | ||
| - `VITE_SUPABASE_PUBLISHABLE_KEY` | ||
|
|
||
| Para edge functions e backend (configuradas no Supabase Dashboard, não no repo): | ||
| - ver inventário em `recovery/block19_secrets_inventory.md` e `recovery/block22_edge_secrets_inventory.md` | ||
|
|
||
| --- | ||
|
|
||
| ## Production Checklist (pré-redeploy) | ||
|
|
||
| - [ ] Branch protection ativa em `main` (ver `docs/BRANCH_PROTECTION.md`) | ||
| - [ ] Dependabot Security Alerts + Secret Scanning + Push Protection ativos (ver `docs/SECURITY_ALERTS.md`) | ||
| - [ ] Advisor de segurança Supabase com 0 ERRORs (ver `mcp__get_advisors`) | ||
| - [ ] Buckets públicos zerados (ver `docs/storage/PUBLIC_BUCKETS.md`) | ||
| - [ ] Policy `recibos_authenticated_read` criada em `storage.objects` | ||
| - [ ] CI verde no commit que vai entrar em prod | ||
| - [ ] Smoke E2E passando em `promogifts.com.br` após deploy | ||
|
|
||
| --- | ||
|
|
||
| ## Rollback | ||
|
|
||
| Se um deploy quebrar produção: | ||
|
|
||
| 1. **Frontend:** reverter o commit em `main` via `git revert` + push → Lovable redeploys | ||
| 2. **Schema (Postgres):** restaurar via Supabase point-in-time recovery (PITR) — dashboard → Database → Backups | ||
| 3. **Storage (arquivos):** ⚠️ **PITR NÃO recupera arquivos do Storage** — restaura apenas a tabela `storage.objects` (metadados). Os objetos físicos ficam num backend S3-compatible separado, fora do escopo do backup. Estratégia atual: | ||
| - Buckets em uso (`recibos-entrega`, `scripts`) **não têm versionamento ativo** | ||
| - Para incidentes: tentar reconciliação manual via `storage.objects` metadata + backup externo (se existir) | ||
| - **Recomendação P2 para Fase 3:** habilitar versionamento de bucket OU job periódico de cópia para R2/S3 externo. Tracking em issue própria a abrir | ||
| 4. **Edge functions:** redeploy do commit anterior via MCP `deploy_edge_function` (preferido) ou `supabase functions deploy` se tiver CLI local | ||
|
|
||
| --- | ||
|
|
||
| ## Referências cruzadas | ||
|
|
||
| - `docs/redeploy/REDEPLOY-FASE2-EXECUTION-LOG.md` — fase atual do redeploy | ||
| - `docs/redeploy/REDEPLOY-T3-MIGRATIONS-AUDIT.md` — detalhe do desync de migrations | ||
| - `docs/redeploy/REDEPLOY-T2.5-FOLLOWUP.md` — arquitetura Lovable + Vercel | ||
| - `docs/BRANCH_PROTECTION.md` — política de proteção de branch | ||
| - `docs/SECURITY_ALERTS.md` — Dependabot + CodeQL + Secret Scanning | ||
| - `docs/storage/PUBLIC_BUCKETS.md` — política de buckets | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -110,3 +110,29 @@ try { | |
|
|
||
| - `tests/observability/structured-logger.test.ts` — garante schema de saída. | ||
| - `scripts/check-edge-structured-logging.mjs` — gate (próxima onda) para garantir que toda nova edge function importa `createStructuredLogger`. | ||
|
|
||
|
Comment on lines
112
to
+113
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Evite status contraditório do gate de CI no mesmo documento. A Line 112 diz que o gate é “próxima onda”, enquanto a Line 124 marca o gate como concluído (✅). Vale alinhar um único estado para não comprometer a leitura de prontidão. Also applies to: 124-125 🤖 Prompt for AI Agents |
||
| ## 8. Inventário de prontidão (T26 do redeploy Fase 3, 2026-05-12) | ||
|
|
||
| | Capacidade | Estado | Cobertura | | ||
| |---|---|---| | ||
| | Sentry integrado | ✅ | `src/lib/sentry.ts` + `error-reporter.ts` | | ||
| | Structured logger client | ✅ | `src/lib/telemetry/structuredLogger.ts` | | ||
| | Structured logger edge | ✅ | `_shared/structured-logger.ts` (via `createStructuredLogger`) | | ||
| | `request_id` correlation client → edge → DB | ✅ | seção 1 deste doc | | ||
| | Webhook metrics (`webhook_delivery_metrics`) | ✅ | `get_webhook_delivery_summary(minutes)` | | ||
| | Dashboard admin | ✅ | `/admin/observabilidade` | | ||
| | CI gate sobre estrutura de logs | ✅ | seção 7 deste doc | | ||
|
|
||
| ### Gaps conhecidos (Fase 4+ — não bloqueia redeploy 10/10) | ||
|
|
||
| | Gap | Severidade | Onde fica documentado | | ||
| |---|---|---| | ||
| | Sem RUM (Real User Monitoring) — Web Vitals não capturados em produção | Médio | abrir issue dedicada na Fase 4 | | ||
| | Healthcheck endpoint público (`/api/health`) inexistente — Lovable não tem auto-monitor, Vercel sim mas só sobre `*.vercel.app` | Médio | abrir issue dedicada na Fase 4 | | ||
| | Retention de logs Supabase ≤ 7 dias (default plan) — sem externalização para storage longo | Médio | avaliar custo de Log Drains Supabase ou export via cron | | ||
| | Sem alerta automático sobre quota Supabase (DB, storage, edge invocations) | Baixo | Sentry Pulse cobre parte; revisar thresholds | | ||
| | Audit interna `audit_rls_coverage()` / `audit_rls_matrix()` existem mas resultado não é monitorado | Baixo | agendar cron + alerta Sentry se cobertura cair | | ||
|
|
||
| ### Recomendação operacional | ||
|
|
||
| A prontidão atual (Sentry + structured logger + webhook metrics + request_id ponta-a-ponta) **é suficiente para redeploy 10/10**. Os gaps acima são melhorias incrementais — abrir issues separadas e priorizar conforme volume de tráfego pós-redeploy. | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: adm01-debug/Promo_Gifts
Length of output: 3038
O guard de SECURITY DEFINER aceita hardening incompleto para funções admin-only.
A validação REVOKE do script busca apenas
FROM anon, não cobreauthenticated. Funções admin-only que revogam só de anon (deixando authenticated sem revoke) passam no check sem erro. A comentário (linha 103) promete validar ambos, mas o regex (linha 72) só enforça anon.Além disso:
Recomende: estenda a validação REVOKE para exigir authenticated quando a função não tem o marker
-- rls-helper:.🤖 Prompt for AI Agents