-
Notifications
You must be signed in to change notification settings - Fork 0
chore(redeploy-fase2): close T3/T22/T23 gaps with guard + UI checklist #166
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
Changes from 3 commits
31dabde
c0f3c93
daad208
9f51fcb
0f0939c
083b590
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 |
|---|---|---|
| @@ -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 |
|---|---|---|
| @@ -0,0 +1,179 @@ | ||
| # Redeploy Fase 2 — Checklist UI Final | ||
|
|
||
| > **Para quem:** Joaquim (único maintainer, não-dev) | ||
| > **Tempo total:** ~10 minutos | ||
| > **Objetivo:** fechar as 3 pendências da Fase 2 que **só** funcionam via UI (limitação técnica documentada, não preguiça). | ||
| > **Quando rodar:** quando a PR consolidada do Claude (que adiciona o CI guard e atualiza docs) estiver mergeada em `main`. | ||
|
|
||
| --- | ||
|
|
||
| ## ⏱ Resumo de cliques | ||
|
|
||
| | Passo | UI | Cliques | Tempo | | ||
| |---|---|---|---| | ||
| | 1 — Policy de leitura do bucket recibos | Supabase Dashboard | ~7 | 2 min | | ||
| | 2 — Dependabot Alerts + Secret Scanning | GitHub Settings → Security | ~5 toggles | 2 min | | ||
| | 3 — Branch Protection em `main` | GitHub Settings → Branches | ~10 checkboxes | 5 min | | ||
|
|
||
| Total: ~10 min. Faça **na ordem** abaixo (alguns passos dependem do anterior). | ||
|
|
||
| --- | ||
|
|
||
| ## Passo 1 — Storage policy `recibos_authenticated_read` | ||
|
|
||
| ### Por que é manual | ||
|
|
||
| Tentei criar via MCP/SQL 3 vezes e Supabase bloqueia (`42501: must be owner of relation objects`). A tabela `storage.objects` pertence ao role `supabase_storage_admin` e nenhum role acessível via MCP é membro dele. Detalhes em `docs/storage/PUBLIC_BUCKETS.md`. | ||
|
|
||
| As outras 2 policies do mesmo bucket (`_write`, `_update`) também foram criadas via dashboard antes — então o caminho é conhecido. | ||
|
|
||
| ### Cliques exatos | ||
|
|
||
| 1. Abra: **<https://supabase.com/dashboard/project/doufsxqlfjyuvxuezpln/storage/policies>** | ||
| 2. Procure a seção/tabela **`objects`** (schema **`storage`**) | ||
| 3. Clique no botão **`+ New policy`** (canto direito do bloco `storage.objects`) | ||
| 4. Escolha o template **`For full customization`** (não use os templates pré-prontos — eles adicionam cláusulas que não queremos) | ||
| 5. Preencha o formulário **exatamente assim**: | ||
|
|
||
| | Campo | Valor | | ||
| |---|---| | ||
| | Policy name | `recibos_authenticated_read` | | ||
| | Allowed operation | ☑ SELECT (deixar UPDATE/INSERT/DELETE desmarcados) | | ||
| | Target roles | `authenticated` (remover `public` se vier marcado) | | ||
| | USING expression | `bucket_id = 'recibos-entrega'` | | ||
| | WITH CHECK expression | (deixar vazio) | | ||
|
|
||
| 6. Clique **`Review`** → confira o SQL gerado deve ser equivalente a: | ||
| ```sql | ||
| CREATE POLICY "recibos_authenticated_read" ON storage.objects | ||
| FOR SELECT TO authenticated USING (bucket_id = 'recibos-entrega'); | ||
| ``` | ||
| 7. Clique **`Save policy`** | ||
|
|
||
| ### Validação | ||
|
|
||
| Se quiser confirmar (opcional), no SQL Editor: | ||
|
|
||
| ```sql | ||
| SELECT policyname, cmd, roles::text | ||
| FROM pg_policies | ||
| WHERE schemaname='storage' AND tablename='objects' AND policyname LIKE 'recibos%'; | ||
| ``` | ||
|
|
||
| Esperado: **3 linhas** (`_read`, `_write`, `_update`). | ||
|
|
||
| --- | ||
|
|
||
| ## Passo 2 — Security Analysis (issue #80) | ||
|
|
||
| ### Cliques exatos | ||
|
|
||
| 1. Abra: **<https://github.com/adm01-debug/Promo_Gifts/settings/security_analysis>** | ||
| 2. Ative na ordem (clique no botão `Enable` de cada um): | ||
| - ☑ **Dependency graph** (provável que já esteja on) | ||
| - ☑ **Dependabot alerts** | ||
| - ☑ **Dependabot security updates** | ||
| - ☑ **Secret scanning** | ||
| - ☑ **Push protection** (esse é o crítico — bloqueia secret ANTES do push subir) | ||
|
|
||
| Não precisa configurar nada além disso. Os toggles são instantâneos. | ||
|
|
||
| ### Validação | ||
|
|
||
| - <https://github.com/adm01-debug/Promo_Gifts/security/dependabot> — deve responder com listagem (vazia ou populada — qualquer dos dois é OK) | ||
| - Teste push protection (opcional — pode pular): | ||
| ```bash | ||
| # ATENÇÃO: rodar DENTRO do diretório do repo (não em /tmp) | ||
| echo "AKIAIOSFODNN7EXAMPLE" > fake-secret.txt | ||
| git add -f fake-secret.txt && git commit -m "test secret" | ||
| git push | ||
|
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.
When this optional validation is run before branch protection is configured, the push can succeed instead of producing Useful? React with 👍 / 👎. |
||
| # Esperado: erro "GH013: Repository rule violations found - push declined" | ||
| git reset HEAD~1 && rm fake-secret.txt | ||
| ``` | ||
|
|
||
| ### Fechar issue | ||
|
|
||
| Após ativar, vá em <https://github.com/adm01-debug/Promo_Gifts/issues/80> e clique `Close issue` com comentário tipo: *"Ativado em 2026-05-12. Dependabot + Secret Scanning + Push Protection on."* | ||
|
|
||
| --- | ||
|
|
||
| ## Passo 3 — Branch Protection em `main` (issue #78) | ||
|
|
||
| ### ⚠️ Nuance importante para você (único maintainer) | ||
|
|
||
| A doc original da Fase 2 pediu `Require approvals = 1`. **Se você ativar isso sendo único maintainer, NENHUMA PR sua vai conseguir mergar** (GitHub não deixa você aprovar a própria PR). Duas opções: | ||
|
|
||
| - **Opção A (recomendada para você agora):** `Require approvals = 0` mas mantém **todas as outras travas** (status checks obrigatórios, sem force push, sem delete, conversation resolved). Isso bloqueia push direto e exige CI verde, sem exigir 2ª pessoa. | ||
| - **Opção B:** Manter `= 1` mas habilitar **"Allow specified actors to bypass required pull requests"** e adicionar você mesmo como bypass. Menos rigoroso. | ||
|
|
||
| A instrução abaixo segue a Opção A. | ||
|
|
||
| ### Cliques exatos | ||
|
|
||
| 1. Abra: **<https://github.com/adm01-debug/Promo_Gifts/settings/branches>** | ||
| 2. Clique **`Add branch ruleset`** (ou `Add classic branch protection rule` se a UI ainda mostrar isso) | ||
| 3. **Ruleset name**: `main-protection` | ||
| 4. **Enforcement status**: `Active` | ||
| 5. **Target branches** → `Add target` → `Include default branch` | ||
| 6. Em **Branch protections**, marcar: | ||
|
|
||
| | Toggle | Estado | Configuração detalhada | | ||
| |---|---|---| | ||
| | Restrict deletions | ✅ ON | — | | ||
| | Block force pushes | ✅ ON | — | | ||
| | Require linear history | ⬜ OFF (opcional) | — | | ||
| | Require a pull request before merging | ✅ ON | **Required approvals: 0** · Dismiss stale ✅ · Require conversation resolution ✅ | | ||
| | Require status checks to pass | ✅ ON | Require branches to be up to date ✅. **Add checks** abaixo | | ||
| | Block creations | ⬜ OFF | — | | ||
| | Require deployments to succeed | ⬜ OFF | — | | ||
| | Require code scanning results | ⬜ OFF por ora | Pode ligar depois quando CodeQL tiver baseline | | ||
|
|
||
| 7. Em **Require status checks**, adicione (digite cada um — autocomplete vai sugerir após primeiro run de cada workflow): | ||
| - `Verify push to main is from PR merge` (workflow `branch-protection-sentinel.yml`) | ||
|
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.
This checklist tells the maintainer to require Useful? React with 👍 / 👎. |
||
| - `Gitleaks — Secret Scan` (workflow `security.yml`) | ||
| - `Smoke tests (rotas + health-check)` (workflow `ci.yml`, job `smoke`) | ||
| - `Lint, Typecheck & Test` (workflow `ci.yml`, job `quality`) | ||
| - `CodeQL` (workflow `codeql.yml`) | ||
|
|
||
| > **Se algum nome não aparecer no autocomplete**, é porque o workflow ainda não rodou nessa branch — pode digitar manual. Mas idealmente espere que rode 1× para evitar typo. | ||
|
|
||
|
|
||
| 8. Em **Bypass list**: deixar vazio (não dê bypass nem para admin — assim mantém disciplina). | ||
| 9. **Create** (botão no topo). | ||
|
|
||
| ### Validação | ||
|
|
||
| ```bash | ||
| # Tentar push direto — deve falhar: | ||
| git checkout main && git pull | ||
| git commit --allow-empty -m "test direct push" | ||
| git push origin main | ||
| # Esperado: ! [remote rejected] main -> main (protected branch hook declined) | ||
| git reset HEAD~1 | ||
| ``` | ||
|
|
||
| ### Fechar issue | ||
|
|
||
| Após validar, vá em <https://github.com/adm01-debug/Promo_Gifts/issues/78> e clique `Close issue` com comentário: *"Branch protection ativa em main com 5 required checks. Validado em 2026-05-12."* | ||
|
|
||
| --- | ||
|
|
||
| ## Após os 3 passos | ||
|
|
||
| Avise o Claude (este chat ou próximo). Ele vai: | ||
|
|
||
| 1. Re-rodar os advisors do Supabase | ||
| 2. Confirmar a 3ª policy criada | ||
| 3. Verificar issues #78 e #80 fechadas | ||
| 4. Atualizar `docs/redeploy/REDEPLOY-FASE2-EXECUTION-LOG.md` para marcar a Fase 2 como **100% concluída** | ||
| 5. Propor início da Fase 3 (T24-T30): E2E coverage, CI estabilidade, observability, qualidade, docs finais | ||
|
|
||
| --- | ||
|
|
||
| ## Troubleshooting | ||
|
|
||
| | Sintoma | Causa provável | Solução | | ||
| |---|---|---| | ||
| | Não vejo botão `+ New policy` no Supabase | Estou no projeto errado | URL deve ter `doufsxqlfjyuvxuezpln` | | ||
| | Required check não aparece no autocomplete do GitHub | Workflow nunca rodou na branch ainda | Crie qualquer PR pequena para disparar; depois adicione | | ||
| | Push em main funciona mesmo após branch protection | Você é admin e bypass está ativo | Confirme Bypass list vazia | | ||
| | Issue #78 já está fechada | Alguém marcou antes da validação real | Reabrir; validar com um `git push` direto e simples (sem `--force`) — a rejeição "protected branch hook declined" já comprova proteção ativa; depois fechar com evidência | | ||
Uh oh!
There was an error while loading. Please reload this page.