Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 143 additions & 0 deletions .github/workflows/delete-orphan-edges.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
# Delete Orphan Edge Functions
#
# Workflow manual (workflow_dispatch) que remove 6 edge functions zumbis
# do projeto Supabase doufsxqlfjyuvxuezpln. Estas functions nunca tiveram
# código no repo, nunca foram chamadas pelo frontend e nunca registraram
# uso — auditoria completa em docs/historico/orphan-edges-2026-05-10.md.
#
# Como usar:
# 1. GitHub → Actions → "Delete Orphan Edge Functions" → Run workflow
# 2. Primeira execução: deixar dryRun=true (default) — só lista o que faria
# 3. Segunda execução: dryRun=false E digitar DELETE no campo confirm
#
# Pré-requisito: secret SUPABASE_ACCESS_TOKEN já está configurado no repo
# (mesmo secret usado por deploy-edge-functions.yml).

name: Delete Orphan Edge Functions

on:
workflow_dispatch:
inputs:
dryRun:
description: 'Dry run (apenas lista o que seria deletado, não deleta)'
type: boolean
default: true
confirm:
description: 'Digite DELETE para confirmar (ignorado se dryRun=true)'
type: string
required: false
default: ''

permissions:
contents: read

jobs:
delete:
name: Delete orphan edges
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Validate confirmation gate
if: ${{ inputs.dryRun == false }}
run: |
if [[ "${{ inputs.confirm }}" != "DELETE" ]]; then
echo "::error::Para deletar de verdade, digite exatamente DELETE no campo 'confirm'."
echo "::error::Recebido: '${{ inputs.confirm }}'"
exit 1
fi
echo "✅ Confirmação aceita. Procedendo com a remoção real."

- name: Setup Supabase CLI
uses: supabase/setup-cli@v1
with:
version: latest

- name: Verify SUPABASE_ACCESS_TOKEN
env:
SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }}
run: |
if [[ -z "${SUPABASE_ACCESS_TOKEN:-}" ]]; then
echo "::error::Secret SUPABASE_ACCESS_TOKEN não configurado no repo."
echo "::error::Configurar em Settings → Secrets and variables → Actions."
exit 1
fi
echo "Token presente (length=${#SUPABASE_ACCESS_TOKEN})."

- name: Delete orphan edges
env:
SUPABASE_ACCESS_TOKEN: ${{ secrets.SUPABASE_ACCESS_TOKEN }}
PROJECT_REF: doufsxqlfjyuvxuezpln
DRY_RUN: ${{ inputs.dryRun }}
run: |
set -euo pipefail

ORPHANS=(
super-processor
quick-task
create_user
product-search-v2
product-classifier
guardrails-ml
)

echo "=============================================="
echo " Orphan Edge Functions Cleanup"
echo "=============================================="
echo "Project ref: $PROJECT_REF"
echo "Dry run: $DRY_RUN"
echo "Total: ${#ORPHANS[@]} edge functions"
echo "=============================================="
echo ""

PASS=0
FAIL=0
SKIP=0

for fn in "${ORPHANS[@]}"; do
echo "--- $fn ---"
if [[ "$DRY_RUN" == "true" ]]; then
echo " 🔍 [DRY RUN] supabase functions delete $fn --project-ref $PROJECT_REF"
SKIP=$((SKIP+1))
else
if supabase functions delete "$fn" --project-ref "$PROJECT_REF" 2>&1; then
echo " ✅ Deleted: $fn"
PASS=$((PASS+1))
else
echo " ⚠️ Failed (talvez já não exista): $fn"
FAIL=$((FAIL+1))
fi
Comment on lines +102 to +108
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Falha parcial está passando como sucesso e pode deixar edge vulnerável ativa

Hoje, em execução real, o fluxo só emite warning quando há erro no delete e finaliza com sucesso. Isso mascara falha operacional (token, rede, permissão, CLI) e pode manter product-search-v2 exposta. Em operação de contenção, erro real precisa quebrar o job.

Patch sugerido
-              if supabase functions delete "$fn" --project-ref "$PROJECT_REF" 2>&1; then
+              DELETE_OUTPUT="$(supabase functions delete "$fn" --project-ref "$PROJECT_REF" 2>&1)" && RC=0 || RC=$?
+              if [[ $RC -eq 0 ]]; then
                 echo "  ✅ Deleted: $fn"
                 PASS=$((PASS+1))
               else
-                echo "  ⚠️  Failed (talvez já não exista): $fn"
-                FAIL=$((FAIL+1))
+                if grep -qiE "not found|does not exist" <<<"$DELETE_OUTPUT"; then
+                  echo "  ℹ️  Já não existia: $fn"
+                  SKIP=$((SKIP+1))
+                else
+                  echo "  ❌ Falha ao deletar: $fn"
+                  echo "$DELETE_OUTPUT"
+                  FAIL=$((FAIL+1))
+                fi
               fi
@@
           else
             echo "Deleted successfully: $PASS"
             echo "Failed:               $FAIL"
+            echo "Already absent:       $SKIP"
             if [[ $FAIL -gt 0 ]]; then
-              echo "::warning::Algumas edges falharam ao deletar (podem já não existir)."
+              echo "::error::Falhas reais na remoção. Abortando para evitar falso positivo."
+              exit 1
             fi
           fi

Also applies to: 124-128

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/delete-orphan-edges.yml around lines 102 - 108, The delete
loop currently treats failures as warnings (increments FAIL) but lets the job
exit successfully; update the logic around the supabase functions delete "$fn"
--project-ref "$PROJECT_REF" branch so that any deletion error causes the script
to fail fast (or at minimum exit non-zero after the loop) instead of only
echoing a warning—e.g., when the else branch for the supabase delete runs,
ensure you either call exit 1 immediately or set a fatal flag and after the loop
check FAIL>0 and exit 1; apply the same change to the other delete block that
manipulates PASS and FAIL (lines referenced in the comment) so any operational
error (token/network/permission/CLI) breaks the job.

fi
echo ""
done

echo "=============================================="
echo " Summary"
echo "=============================================="
if [[ "$DRY_RUN" == "true" ]]; then
echo "DRY RUN — nenhuma edge function foi de fato deletada."
echo "Skipped (would-delete): $SKIP"
echo ""
echo "Para deletar de verdade, rode novamente com:"
echo " dryRun = false"
echo " confirm = DELETE"
else
echo "Deleted successfully: $PASS"
echo "Failed: $FAIL"
if [[ $FAIL -gt 0 ]]; then
echo "::warning::Algumas edges falharam ao deletar (podem já não existir)."
Comment on lines +126 to +127
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 Fail the workflow when deletion fails

When dryRun=false, any supabase functions delete failure only increments FAIL and emits a warning, so a bad token, API outage, or permission error can leave all six functions in production while the job still finishes green and the success() post-delete hint runs. Because this workflow is intended to remediate an active public data leak, please return a non-zero exit when FAIL > 0 (or validate the functions are gone) so operators do not treat an unsuccessful cleanup as completed.

Useful? React with 👍 / 👎.

fi
fi

- name: Post-delete validation hint
if: ${{ inputs.dryRun == false && success() }}
run: |
echo "## Próximos passos"
echo ""
echo "1. Validar via Supabase MCP que as 6 edges sumiram:"
echo " MCP \`SUPABASE - GESTÃO DE PRODUTOS:list_edge_functions\`"
echo ""
echo "2. Conferir que ai_function_routing não tem entradas órfãs:"
echo " SQL: SELECT function_name FROM public.ai_function_routing"
echo " WHERE function_name IN ('super-processor', ...);"
echo ""
echo "3. Atualizar memória/notes do projeto: 6 edges removidas em $(date -u +%Y-%m-%d)."
Comment on lines +134 to +143
Loading
Loading