@luanpdd/kit-mcp 1.33.0 → 1.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +168 -168
- package/gates/agent-no-recursive-dispatch.md +84 -84
- package/kit/COMANDOS.md +138 -138
- package/kit/COMPATIBILITY.md +70 -70
- package/kit/README.md +76 -76
- package/kit/agents/advisor-researcher.md +109 -109
- package/kit/agents/ai-mutation-tester.md +289 -289
- package/kit/agents/assumptions-analyzer.md +110 -110
- package/kit/agents/audit-log-implementer.md +314 -314
- package/kit/agents/auditor-consistencia-isolamento.md +414 -414
- package/kit/agents/b2b-saas-architect.md +157 -157
- package/kit/agents/burn-rate-forecaster.md +153 -153
- package/kit/agents/cascading-failures-auditor.md +299 -299
- package/kit/agents/codebase-mapper.md +769 -769
- package/kit/agents/crm-pipeline-implementer.md +257 -257
- package/kit/agents/debugger.md +814 -814
- package/kit/agents/designer-ui.md +216 -216
- package/kit/agents/detector-tenant-quente.md +338 -338
- package/kit/agents/evolution-go-integrator.md +201 -201
- package/kit/agents/example-reviewer.md +22 -22
- package/kit/agents/executor.md +565 -565
- package/kit/agents/golden-signals-instrumenter.md +232 -232
- package/kit/agents/incident-investigator.md +238 -238
- package/kit/agents/integration-checker.md +203 -203
- package/kit/agents/invite-flow-implementer.md +190 -190
- package/kit/agents/legacy-characterizer.md +369 -369
- package/kit/agents/lgpd-compliance-auditor.md +296 -296
- package/kit/agents/load-shedding-instrumenter.md +290 -290
- package/kit/agents/multi-tenant-isolation-auditor.md +254 -254
- package/kit/agents/multi-tenant-rls-writer.md +341 -341
- package/kit/agents/nyquist-auditor.md +181 -181
- package/kit/agents/observability-coverage-auditor.md +316 -316
- package/kit/agents/observability-instrumenter.md +191 -191
- package/kit/agents/omm-auditor.md +291 -291
- package/kit/agents/org-onboarding-implementer.md +224 -224
- package/kit/agents/payload-capture-instrumenter.md +274 -274
- package/kit/agents/phase-researcher.md +697 -697
- package/kit/agents/plan-checker.md +275 -275
- package/kit/agents/planner.md +923 -923
- package/kit/agents/postmortem-writer.md +273 -273
- package/kit/agents/project-researcher.md +653 -653
- package/kit/agents/prr-conductor.md +287 -287
- package/kit/agents/refactor-safety-auditor.md +405 -405
- package/kit/agents/release-pipeline-auditor.md +364 -364
- package/kit/agents/research-synthesizer.md +246 -246
- package/kit/agents/roadmapper.md +678 -678
- package/kit/agents/schema-checker.md +160 -160
- package/kit/agents/seam-finder.md +360 -360
- package/kit/agents/shotgun-surgery-detector.md +350 -350
- package/kit/agents/slo-engineer.md +217 -217
- package/kit/agents/storytelling-analyst.md +300 -300
- package/kit/agents/supabase-architect.md +249 -249
- package/kit/agents/supabase-auth-bootstrapper.md +400 -400
- package/kit/agents/supabase-auth-hook-writer.md +418 -418
- package/kit/agents/supabase-branching-architect.md +563 -563
- package/kit/agents/supabase-cicd-pipeline-implementer.md +778 -778
- package/kit/agents/supabase-column-privileges-writer.md +400 -400
- package/kit/agents/supabase-edge-fn-tester.md +288 -288
- package/kit/agents/supabase-edge-fn-writer.md +341 -341
- package/kit/agents/supabase-mfa-implementer.md +439 -439
- package/kit/agents/supabase-migration-writer.md +386 -386
- package/kit/agents/supabase-oauth-server-implementer.md +507 -507
- package/kit/agents/supabase-rbac-implementer.md +393 -393
- package/kit/agents/supabase-realtime-implementer.md +364 -364
- package/kit/agents/supabase-rls-hardener.md +522 -522
- package/kit/agents/supabase-rls-writer.md +324 -324
- package/kit/agents/supabase-roles-implementer.md +356 -356
- package/kit/agents/supabase-social-auth-implementer.md +451 -451
- package/kit/agents/supabase-sso-saml-architect.md +549 -549
- package/kit/agents/supabase-storage-implementer.md +407 -407
- package/kit/agents/super-admin-implementer.md +282 -282
- package/kit/agents/toil-auditor.md +268 -268
- package/kit/agents/ui-auditor.md +438 -438
- package/kit/agents/ui-checker.md +305 -305
- package/kit/agents/ui-researcher.md +356 -356
- package/kit/agents/user-profiler.md +176 -176
- package/kit/agents/validador-evolucao-schema.md +336 -336
- package/kit/agents/verifier.md +729 -729
- package/kit/agents/workflow-generator.md +167 -0
- package/kit/commands/adicionar-backlog.md +75 -75
- package/kit/commands/adicionar-fase.md +42 -42
- package/kit/commands/adicionar-tarefa.md +45 -45
- package/kit/commands/adicionar-testes.md +41 -41
- package/kit/commands/ajuda.md +21 -21
- package/kit/commands/atualizar.md +37 -37
- package/kit/commands/auditar-cascading.md +111 -111
- package/kit/commands/auditar-marco.md +179 -179
- package/kit/commands/auditar-observabilidade-cobertura-workflow.md +121 -0
- package/kit/commands/auditar-observabilidade-cobertura.md +183 -183
- package/kit/commands/auditar-refactor.md +219 -219
- package/kit/commands/auditar-release.md +109 -109
- package/kit/commands/auditar-uat.md +23 -23
- package/kit/commands/autonomo.md +40 -40
- package/kit/commands/branch-pr.md +24 -24
- package/kit/commands/burn-rate-status.md +408 -408
- package/kit/commands/capturar-payloads.md +193 -193
- package/kit/commands/caracterizar.md +212 -212
- package/kit/commands/concluir-marco.md +247 -247
- package/kit/commands/configuracoes.md +36 -36
- package/kit/commands/criar-workflow.md +158 -0
- package/kit/commands/dados-distribuidos.md +188 -188
- package/kit/commands/definir-perfil.md +10 -10
- package/kit/commands/depurar.md +190 -190
- package/kit/commands/detectar-duplicacao.md +197 -197
- package/kit/commands/discutir-fase.md +131 -131
- package/kit/commands/encontrar-seams.md +136 -136
- package/kit/commands/entrar-discord.md +17 -17
- package/kit/commands/estatisticas.md +18 -18
- package/kit/commands/example-greeting.md +33 -33
- package/kit/commands/executar-fase.md +58 -58
- package/kit/commands/expresso.md +56 -56
- package/kit/commands/fase-ui.md +34 -34
- package/kit/commands/fazer.md +57 -57
- package/kit/commands/fio.md +125 -125
- package/kit/commands/fluxos-trabalho.md +64 -64
- package/kit/commands/forense.md +176 -176
- package/kit/commands/gerenciador.md +38 -38
- package/kit/commands/inserir-fase.md +31 -31
- package/kit/commands/legacy.md +263 -263
- package/kit/commands/limpeza.md +17 -17
- package/kit/commands/listar-hipoteses-fase.md +45 -45
- package/kit/commands/listar-workspaces.md +18 -18
- package/kit/commands/load-shedding.md +117 -117
- package/kit/commands/mapear-codebase.md +70 -70
- package/kit/commands/multi-tenant.md +163 -163
- package/kit/commands/nota.md +33 -33
- package/kit/commands/novo-marco.md +43 -43
- package/kit/commands/novo-projeto.md +41 -41
- package/kit/commands/novo-workspace.md +43 -43
- package/kit/commands/pausar-trabalho.md +37 -37
- package/kit/commands/perfil-usuario.md +45 -45
- package/kit/commands/pesquisar-fase.md +195 -195
- package/kit/commands/planejar-fase.md +67 -67
- package/kit/commands/planejar-lacunas.md +33 -33
- package/kit/commands/plantar-ideia.md +25 -25
- package/kit/commands/progresso.md +24 -24
- package/kit/commands/proximo.md +30 -30
- package/kit/commands/publicar.md +490 -490
- package/kit/commands/rapido.md +35 -35
- package/kit/commands/reaplicar-patches.md +124 -124
- package/kit/commands/refactor-seguro.md +321 -321
- package/kit/commands/relatorio-sessao.md +19 -19
- package/kit/commands/remover-fase.md +31 -31
- package/kit/commands/remover-workspace.md +26 -26
- package/kit/commands/resumo-marco.md +50 -50
- package/kit/commands/retomar-trabalho.md +40 -40
- package/kit/commands/revisar-backlog.md +60 -60
- package/kit/commands/revisar-ui.md +32 -32
- package/kit/commands/revisar.md +37 -37
- package/kit/commands/saude.md +21 -21
- package/kit/commands/setup-notion.md +93 -93
- package/kit/commands/storytelling.md +179 -179
- package/kit/commands/supabase.md +238 -238
- package/kit/commands/sync-main.md +68 -68
- package/kit/commands/validar-fase.md +35 -35
- package/kit/commands/verificar-tarefas.md +44 -44
- package/kit/commands/verificar-trabalho.md +64 -64
- package/kit/file-manifest.json +424 -419
- package/kit/framework/bin/lib/commands.cjs +959 -959
- package/kit/framework/bin/lib/config.cjs +442 -442
- package/kit/framework/bin/lib/core.cjs +1230 -1230
- package/kit/framework/bin/lib/frontmatter.cjs +336 -336
- package/kit/framework/bin/lib/init.cjs +1442 -1442
- package/kit/framework/bin/lib/milestone.cjs +252 -252
- package/kit/framework/bin/lib/model-profiles.cjs +68 -68
- package/kit/framework/bin/lib/phase.cjs +888 -888
- package/kit/framework/bin/lib/profile-output.cjs +952 -952
- package/kit/framework/bin/lib/profile-pipeline.cjs +539 -539
- package/kit/framework/bin/lib/roadmap.cjs +329 -329
- package/kit/framework/bin/lib/security.cjs +382 -382
- package/kit/framework/bin/lib/state.cjs +1031 -1031
- package/kit/framework/bin/lib/template.cjs +222 -222
- package/kit/framework/bin/lib/uat.cjs +282 -282
- package/kit/framework/bin/lib/verify.cjs +888 -888
- package/kit/framework/bin/lib/workstream.cjs +491 -491
- package/kit/framework/bin/tools.cjs +918 -918
- package/kit/framework/commands/workstreams.md +63 -63
- package/kit/framework/references/checkpoints.md +778 -778
- package/kit/framework/references/continuation-format.md +249 -249
- package/kit/framework/references/decimal-phase-calculation.md +64 -64
- package/kit/framework/references/git-integration.md +295 -295
- package/kit/framework/references/git-planning-commit.md +38 -38
- package/kit/framework/references/model-profile-resolution.md +36 -36
- package/kit/framework/references/model-profiles.md +139 -139
- package/kit/framework/references/phase-argument-parsing.md +61 -61
- package/kit/framework/references/planning-config.md +202 -202
- package/kit/framework/references/questioning.md +162 -162
- package/kit/framework/references/tdd.md +263 -263
- package/kit/framework/references/ui-brand.md +160 -160
- package/kit/framework/references/user-profiling.md +657 -657
- package/kit/framework/references/verification-patterns.md +612 -612
- package/kit/framework/references/workstream-flag.md +58 -58
- package/kit/framework/templates/DEBUG.md +164 -164
- package/kit/framework/templates/UAT.md +265 -265
- package/kit/framework/templates/UI-SPEC.md +100 -100
- package/kit/framework/templates/VALIDATION.md +76 -76
- package/kit/framework/templates/claude-md.md +122 -122
- package/kit/framework/templates/codebase/architecture.md +185 -185
- package/kit/framework/templates/codebase/concerns.md +205 -205
- package/kit/framework/templates/codebase/conventions.md +204 -204
- package/kit/framework/templates/codebase/integrations.md +192 -192
- package/kit/framework/templates/codebase/stack.md +158 -158
- package/kit/framework/templates/codebase/structure.md +199 -199
- package/kit/framework/templates/codebase/testing.md +301 -301
- package/kit/framework/templates/config.json +44 -44
- package/kit/framework/templates/context.md +352 -352
- package/kit/framework/templates/continue-here.md +78 -78
- package/kit/framework/templates/copilot-instructions.md +7 -7
- package/kit/framework/templates/debug-subagent-prompt.md +91 -91
- package/kit/framework/templates/dev-preferences.md +20 -20
- package/kit/framework/templates/discovery.md +146 -146
- package/kit/framework/templates/discussion-log.md +63 -63
- package/kit/framework/templates/milestone-archive.md +123 -123
- package/kit/framework/templates/milestone.md +115 -115
- package/kit/framework/templates/phase-prompt.md +610 -610
- package/kit/framework/templates/planner-subagent-prompt.md +117 -117
- package/kit/framework/templates/project.md +186 -186
- package/kit/framework/templates/requirements.md +231 -231
- package/kit/framework/templates/research-project/ARCHITECTURE.md +204 -204
- package/kit/framework/templates/research-project/FEATURES.md +147 -147
- package/kit/framework/templates/research-project/PITFALLS.md +200 -200
- package/kit/framework/templates/research-project/STACK.md +120 -120
- package/kit/framework/templates/research-project/SUMMARY.md +170 -170
- package/kit/framework/templates/research.md +419 -419
- package/kit/framework/templates/retrospective.md +54 -54
- package/kit/framework/templates/roadmap.md +202 -202
- package/kit/framework/templates/state.md +176 -176
- package/kit/framework/templates/summary-complex.md +59 -59
- package/kit/framework/templates/summary-minimal.md +41 -41
- package/kit/framework/templates/summary-standard.md +48 -48
- package/kit/framework/templates/summary.md +209 -209
- package/kit/framework/templates/user-profile.md +146 -146
- package/kit/framework/templates/user-setup.md +256 -256
- package/kit/framework/templates/verification-report.md +258 -258
- package/kit/framework/workflows/add-phase.md +112 -112
- package/kit/framework/workflows/add-tests.md +351 -351
- package/kit/framework/workflows/add-todo.md +158 -158
- package/kit/framework/workflows/audit-milestone.md +340 -340
- package/kit/framework/workflows/audit-uat.md +109 -109
- package/kit/framework/workflows/autonomous.md +891 -891
- package/kit/framework/workflows/check-todos.md +177 -177
- package/kit/framework/workflows/cleanup.md +152 -152
- package/kit/framework/workflows/complete-milestone.md +696 -696
- package/kit/framework/workflows/diagnose-issues.md +231 -231
- package/kit/framework/workflows/discovery-phase.md +289 -289
- package/kit/framework/workflows/discuss-phase-assumptions.md +653 -653
- package/kit/framework/workflows/discuss-phase.md +784 -784
- package/kit/framework/workflows/do.md +104 -104
- package/kit/framework/workflows/execute-phase.md +838 -838
- package/kit/framework/workflows/execute-plan.md +510 -510
- package/kit/framework/workflows/fast.md +102 -102
- package/kit/framework/workflows/forensics.md +265 -265
- package/kit/framework/workflows/health.md +181 -181
- package/kit/framework/workflows/help.md +619 -619
- package/kit/framework/workflows/insert-phase.md +130 -130
- package/kit/framework/workflows/list-phase-assumptions.md +178 -178
- package/kit/framework/workflows/list-workspaces.md +56 -56
- package/kit/framework/workflows/manager.md +362 -362
- package/kit/framework/workflows/map-codebase.md +377 -377
- package/kit/framework/workflows/milestone-summary.md +223 -223
- package/kit/framework/workflows/new-milestone.md +486 -486
- package/kit/framework/workflows/new-project.md +1159 -1159
- package/kit/framework/workflows/new-workspace.md +237 -237
- package/kit/framework/workflows/next.md +97 -97
- package/kit/framework/workflows/node-repair.md +92 -92
- package/kit/framework/workflows/note.md +156 -156
- package/kit/framework/workflows/pause-work.md +176 -176
- package/kit/framework/workflows/plan-milestone-gaps.md +273 -273
- package/kit/framework/workflows/plan-phase.md +765 -765
- package/kit/framework/workflows/plant-seed.md +169 -169
- package/kit/framework/workflows/pr-branch.md +129 -129
- package/kit/framework/workflows/profile-user.md +450 -450
- package/kit/framework/workflows/progress.md +507 -507
- package/kit/framework/workflows/quick.md +757 -757
- package/kit/framework/workflows/remove-phase.md +155 -155
- package/kit/framework/workflows/remove-workspace.md +90 -90
- package/kit/framework/workflows/research-phase.md +82 -82
- package/kit/framework/workflows/resume-project.md +326 -326
- package/kit/framework/workflows/review.md +228 -228
- package/kit/framework/workflows/session-report.md +146 -146
- package/kit/framework/workflows/settings.md +283 -283
- package/kit/framework/workflows/ship.md +228 -228
- package/kit/framework/workflows/stats.md +60 -60
- package/kit/framework/workflows/transition.md +671 -671
- package/kit/framework/workflows/ui-phase.md +302 -302
- package/kit/framework/workflows/ui-review.md +165 -165
- package/kit/framework/workflows/update.md +323 -323
- package/kit/framework/workflows/validate-phase.md +174 -174
- package/kit/framework/workflows/verify-phase.md +252 -252
- package/kit/framework/workflows/verify-work.md +637 -637
- package/kit/hooks/check-update.js +118 -118
- package/kit/hooks/context-monitor.js +163 -163
- package/kit/hooks/kit-attribution-reminder.cjs +92 -92
- package/kit/hooks/kit-router.cjs +137 -137
- package/kit/hooks/prompt-guard.js +103 -103
- package/kit/hooks/statusline.js +125 -125
- package/kit/hooks/workflow-guard.js +101 -101
- package/kit/settings.json +45 -45
- package/kit/skills/ai-prompt-characterization/SKILL.md +335 -335
- package/kit/skills/armadilhas-sistemas-distribuidos/SKILL.md +447 -447
- package/kit/skills/audit-log-multi-tenant/SKILL.md +340 -340
- package/kit/skills/b2b-saas-architecture/SKILL.md +300 -300
- package/kit/skills/consistencia-leitura-replica/SKILL.md +385 -385
- package/kit/skills/crm-lead-pipeline-patterns/SKILL.md +343 -343
- package/kit/skills/dynamic-workflow-authoring/SKILL.md +223 -0
- package/kit/skills/escolha-modelo-consistencia/SKILL.md +494 -494
- package/kit/skills/evolucao-schema-compativel/SKILL.md +448 -448
- package/kit/skills/evolution-go-whatsapp-integration/SKILL.md +322 -322
- package/kit/skills/example-skill/SKILL.md +42 -42
- package/kit/skills/legacy-api-only-applications/SKILL.md +358 -358
- package/kit/skills/legacy-characterization-tests/SKILL.md +330 -330
- package/kit/skills/legacy-effect-analysis/SKILL.md +331 -331
- package/kit/skills/legacy-extract-class/SKILL.md +203 -203
- package/kit/skills/legacy-programming-by-difference/SKILL.md +252 -252
- package/kit/skills/legacy-seams-and-test-harness/SKILL.md +460 -460
- package/kit/skills/legacy-shotgun-surgery/SKILL.md +286 -286
- package/kit/skills/legacy-sprout-wrap-techniques/SKILL.md +434 -434
- package/kit/skills/legacy-storytelling-naked-crc/SKILL.md +270 -270
- package/kit/skills/lgpd-multi-tenant-compliance/SKILL.md +340 -340
- package/kit/skills/member-invite-flow/SKILL.md +305 -305
- package/kit/skills/member-management-react-shadcn/SKILL.md +328 -328
- package/kit/skills/multi-tenant-performance-scaling/SKILL.md +316 -316
- package/kit/skills/multi-tenant-rls-hierarchy/SKILL.md +342 -342
- package/kit/skills/org-onboarding-flow/SKILL.md +257 -257
- package/kit/skills/org-switcher-react-pattern/SKILL.md +349 -349
- package/kit/skills/permission-gate-react-pattern/SKILL.md +271 -271
- package/kit/skills/postgres-isolamento-concorrencia/SKILL.md +552 -552
- package/kit/skills/pre-refactor-characterization/SKILL.md +421 -421
- package/kit/skills/rbac-permissions-matrix-supabase/SKILL.md +338 -338
- package/kit/skills/streams-eventos-cdc/SKILL.md +711 -711
- package/kit/skills/supabase-auth-hardening/SKILL.md +674 -674
- package/kit/skills/supabase-auth-hooks/SKILL.md +875 -875
- package/kit/skills/supabase-auth-methods/SKILL.md +486 -486
- package/kit/skills/supabase-auth-sessions/SKILL.md +579 -579
- package/kit/skills/supabase-auth-ssr/SKILL.md +306 -306
- package/kit/skills/supabase-branching-workflow/SKILL.md +544 -544
- package/kit/skills/supabase-ci-cd-github-actions/SKILL.md +880 -880
- package/kit/skills/supabase-column-level-security/SKILL.md +426 -426
- package/kit/skills/supabase-config-toml-remotes/SKILL.md +807 -807
- package/kit/skills/supabase-custom-claims-rbac/SKILL.md +472 -472
- package/kit/skills/supabase-edge-functions/SKILL.md +330 -330
- package/kit/skills/supabase-edge-functions-auth/SKILL.md +309 -309
- package/kit/skills/supabase-edge-functions-limits/SKILL.md +302 -302
- package/kit/skills/supabase-edge-functions-mcp-server/SKILL.md +279 -279
- package/kit/skills/supabase-edge-functions-testing/SKILL.md +277 -277
- package/kit/skills/supabase-edge-runtime-builtins/SKILL.md +357 -357
- package/kit/skills/supabase-enterprise-sso-saml/SKILL.md +545 -545
- package/kit/skills/supabase-jwt-signing-keys/SKILL.md +399 -399
- package/kit/skills/supabase-mfa/SKILL.md +488 -488
- package/kit/skills/supabase-migration-repair/SKILL.md +823 -823
- package/kit/skills/supabase-migrations/SKILL.md +297 -297
- package/kit/skills/supabase-oauth-server/SKILL.md +537 -537
- package/kit/skills/supabase-pgtap-testing/SKILL.md +1053 -1053
- package/kit/skills/supabase-postgres-roles/SKILL.md +392 -392
- package/kit/skills/supabase-realtime/SKILL.md +460 -460
- package/kit/skills/supabase-rls-defense-in-depth/SKILL.md +418 -418
- package/kit/skills/supabase-rls-policies/SKILL.md +635 -635
- package/kit/skills/supabase-social-oauth/SKILL.md +480 -480
- package/kit/skills/supabase-third-party-auth/SKILL.md +450 -450
- package/kit/skills/super-admin-platform-pattern/SKILL.md +326 -326
- package/kit/skills/tenant-quente-mitigacao/SKILL.md +605 -605
- package/kit/skills/ui-anti-padroes-ia/SKILL.md +261 -261
- package/kit/skills/ui-contexto-produto/SKILL.md +248 -248
- package/kit/skills/ui-cor-estrategia/SKILL.md +213 -213
- package/kit/skills/ui-critica-auditoria/SKILL.md +260 -260
- package/kit/skills/ui-motion-funcional/SKILL.md +264 -264
- package/kit/skills/ui-ritmo-espacial/SKILL.md +259 -259
- package/kit/skills/ui-tipografia/SKILL.md +211 -211
- package/kit/skills/whatsapp-conversation-state-machine/SKILL.md +287 -287
- package/kit/workflows/auditar-observabilidade-cobertura.workflow.js +250 -0
- package/package.json +65 -63
- package/src/core/kit.js +333 -216
- package/src/core/reflect.js +247 -247
- package/src/core/registry.js +123 -112
- package/src/core/reverse-sync.js +448 -372
- package/src/core/sync.js +477 -437
- package/src/core/watch.js +121 -121
- package/src/mcp-server/index.js +794 -794
|
@@ -1,288 +1,288 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: supabase-edge-fn-tester
|
|
3
|
-
tier: specialized
|
|
4
|
-
description: Gera Deno tests para Edge Functions Supabase — equivalence classes happy/validation/auth/rate-limit/timeout, fixtures sanitizados, snapshot jsr:@std/testing, characterization para legacy.
|
|
5
|
-
tools: Read, Write, Edit, Bash, Grep, Glob, Task
|
|
6
|
-
color: teal
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
Você é o Edge Function **tester** Supabase. Recebe nome de uma Edge Function existente e gera `supabase/functions/tests/<fn>-test.ts` com cobertura canônica de 5 equivalence classes + opcionalmente captura fixtures reais via logs.
|
|
10
|
-
|
|
11
|
-
**Compat:** Full em todos os IDEs (filesystem-only).
|
|
12
|
-
|
|
13
|
-
## Por que existe
|
|
14
|
-
|
|
15
|
-
`supabase-edge-fn-writer` cria funções com instrumentação OTel + SRE defenses, mas **não gera tests automaticamente**. Tests são primeira camada de regressão para mudanças futuras — sem eles, refactor é cego. Este agent é o **handoff downstream** canônico.
|
|
16
|
-
|
|
17
|
-
## Skills consultadas
|
|
18
|
-
|
|
19
|
-
- [`supabase-edge-functions-testing`](../skills/supabase-edge-functions-testing/SKILL.md) — folder structure + Deno test runner
|
|
20
|
-
- [`supabase-edge-functions-auth`](../skills/supabase-edge-functions-auth/SKILL.md) — autenticar tests user-scoped
|
|
21
|
-
- [`supabase-edge-functions-limits`](../skills/supabase-edge-functions-limits/SKILL.md) — status codes esperados
|
|
22
|
-
- [`legacy-characterization-tests`](../skills/legacy-characterization-tests/SKILL.md) — Edge Function sem tests prévios
|
|
23
|
-
- [`pre-refactor-characterization`](../skills/pre-refactor-characterization/SKILL.md) — payload capture pattern
|
|
24
|
-
- [`ai-prompt-characterization`](../skills/ai-prompt-characterization/SKILL.md) — Edge Function com LLM (temperature=0 + seed fixo)
|
|
25
|
-
- [`legacy-api-only-applications`](../skills/legacy-api-only-applications/SKILL.md) — FakeProvider para tests determinísticos
|
|
26
|
-
|
|
27
|
-
## Inputs esperados
|
|
28
|
-
|
|
29
|
-
- `function_name`: kebab-case (ex: `orders`, `stripe-webhook`)
|
|
30
|
-
- (Opcional) `auth_mode`: detectado automaticamente de `config.toml` se não passado
|
|
31
|
-
- (Opcional) `pattern`: `'basic' | 'characterization' | 'webhook' | 'rag' | 'mcp'`
|
|
32
|
-
- (Opcional) `capture_payloads`: bool — se true, agent invoca `payload-capture-instrumenter` antes para coletar fixtures reais
|
|
33
|
-
|
|
34
|
-
## Passos
|
|
35
|
-
|
|
36
|
-
### Step 0 — Preflight
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
# 1. localizar função
|
|
40
|
-
test -d supabase/functions/<function_name> || exit "função não existe"
|
|
41
|
-
|
|
42
|
-
# 2. ler config.toml para detectar verify_jwt + entrypoint
|
|
43
|
-
grep -A 3 "^\[functions\.<function_name>\]" supabase/config.toml
|
|
44
|
-
|
|
45
|
-
# 3. checar se já existem tests
|
|
46
|
-
ls supabase/functions/tests/<function_name>-test.ts 2>/dev/null && \
|
|
47
|
-
echo "WARN: tests já existem — extending vs replacing?"
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
### Step 1 — Ler o `index.ts` da função
|
|
51
|
-
|
|
52
|
-
Extrair:
|
|
53
|
-
- Auth mode (procura `withSupabase({ auth: ... })` ou `auth.getUser`)
|
|
54
|
-
- Endpoints (Hono routes / método HTTP)
|
|
55
|
-
- Inputs (zod schema, parse de body)
|
|
56
|
-
- Error classifier (`classifyError` enum)
|
|
57
|
-
- Dependências externas (npm imports → fakeable?)
|
|
58
|
-
|
|
59
|
-
### Step 2 — Decidir pattern de tests
|
|
60
|
-
|
|
61
|
-
| Pattern | Quando usar | Skills |
|
|
62
|
-
|---|---|---|
|
|
63
|
-
| `basic` | Função nova com behavior conhecido | testing |
|
|
64
|
-
| `characterization` | Função legacy SEM tests — capturar estado atual antes de qualquer mudança | legacy-characterization-tests + pre-refactor-characterization |
|
|
65
|
-
| `webhook` | Função com signature validation (Stripe/GitHub) | testing + fake signature fixture |
|
|
66
|
-
| `rag` | Edge Function com Supabase.ai ou OpenAI | ai-prompt-characterization (temp=0 + seed) |
|
|
67
|
-
| `mcp` | MCP server (mcp-lite) | testing + MCP inspector spec |
|
|
68
|
-
|
|
69
|
-
### Step 3 — Gerar `supabase/functions/tests/<fn>-test.ts`
|
|
70
|
-
|
|
71
|
-
**Template canônico (5 equivalence classes):**
|
|
72
|
-
|
|
73
|
-
```ts
|
|
74
|
-
// supabase/functions/tests/<fn>-test.ts
|
|
75
|
-
import { assert, assertEquals, assertSnapshot } from 'jsr:@std/assert@1'
|
|
76
|
-
import { createClient, FunctionsHttpError } from 'npm:@supabase/supabase-js@2.95.0'
|
|
77
|
-
import 'jsr:@std/dotenv@0.225.5/load'
|
|
78
|
-
|
|
79
|
-
const URL = Deno.env.get('SUPABASE_URL')!
|
|
80
|
-
const KEY = Deno.env.get('SUPABASE_PUBLISHABLE_KEY')!
|
|
81
|
-
const supabase = createClient(URL, KEY, {
|
|
82
|
-
auth: { autoRefreshToken: false, persistSession: false, detectSessionInUrl: false },
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
// =========================
|
|
86
|
-
// 1. HAPPY PATH
|
|
87
|
-
// =========================
|
|
88
|
-
Deno.test('<fn> — happy path', async () => {
|
|
89
|
-
const { data, error } = await supabase.functions.invoke('<fn>', {
|
|
90
|
-
body: { /* ... valid payload ... */ },
|
|
91
|
-
})
|
|
92
|
-
assert(!error, `unexpected error: ${error?.message}`)
|
|
93
|
-
assertEquals(data.status, 'ok')
|
|
94
|
-
})
|
|
95
|
-
|
|
96
|
-
// =========================
|
|
97
|
-
// 2. VALIDATION ERROR
|
|
98
|
-
// =========================
|
|
99
|
-
Deno.test('<fn> — validation rejection', async () => {
|
|
100
|
-
const { error } = await supabase.functions.invoke('<fn>', { body: {} })
|
|
101
|
-
assert(error instanceof FunctionsHttpError)
|
|
102
|
-
const body = await (error as FunctionsHttpError).context.json()
|
|
103
|
-
assertEquals(body.code, 'validation')
|
|
104
|
-
})
|
|
105
|
-
|
|
106
|
-
// =========================
|
|
107
|
-
// 3. AUTH FAILURE
|
|
108
|
-
// =========================
|
|
109
|
-
Deno.test('<fn> — unauthorized when JWT missing', async () => {
|
|
110
|
-
const anon = createClient(URL, 'invalid_key')
|
|
111
|
-
const { error } = await anon.functions.invoke('<fn>', { body: { /* ... */ } })
|
|
112
|
-
assert(error instanceof FunctionsHttpError)
|
|
113
|
-
assertEquals((error as FunctionsHttpError).context.status, 401)
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
// =========================
|
|
117
|
-
// 4. RATE LIMIT (se aplicável — função recursive)
|
|
118
|
-
// =========================
|
|
119
|
-
Deno.test('<fn> — graceful handling of RateLimitError', async () => {
|
|
120
|
-
// Simular saturação invocando 50x em série
|
|
121
|
-
const promises = Array.from({ length: 50 }, () => supabase.functions.invoke('<fn>', { body: { quick: true } }))
|
|
122
|
-
const results = await Promise.allSettled(promises)
|
|
123
|
-
// Pelo menos algumas devem retornar 429 ou Retry-After
|
|
124
|
-
const rejected = results.filter((r) => r.status === 'fulfilled' && r.value.error)
|
|
125
|
-
// Não asserta exatamente — depende do budget atual
|
|
126
|
-
assert(rejected.length >= 0)
|
|
127
|
-
})
|
|
128
|
-
|
|
129
|
-
// =========================
|
|
130
|
-
// 5. TIMEOUT / DOWNSTREAM ERROR
|
|
131
|
-
// =========================
|
|
132
|
-
Deno.test('<fn> — fail gracefully on downstream timeout', async () => {
|
|
133
|
-
const { data, error } = await supabase.functions.invoke('<fn>', {
|
|
134
|
-
body: { simulate: 'downstream-timeout' }, // requer feature flag/test mode
|
|
135
|
-
})
|
|
136
|
-
if (error instanceof FunctionsHttpError) {
|
|
137
|
-
assertEquals((error as FunctionsHttpError).context.status, 504)
|
|
138
|
-
} else {
|
|
139
|
-
// ou response normal com fallback degraded
|
|
140
|
-
assertEquals(data.degraded, true)
|
|
141
|
-
}
|
|
142
|
-
})
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
### Step 4 — Pattern-specific extensions
|
|
146
|
-
|
|
147
|
-
**`characterization` — captura golden snapshot:**
|
|
148
|
-
|
|
149
|
-
```ts
|
|
150
|
-
import payloads from './fixtures/<fn>-payloads.json' with { type: 'json' }
|
|
151
|
-
|
|
152
|
-
Deno.test('<fn> — characterization (5 equivalence classes)', async (t) => {
|
|
153
|
-
for (const { name, input, expected_status } of payloads) {
|
|
154
|
-
await t.step(name, async () => {
|
|
155
|
-
const { data, error } = await supabase.functions.invoke('<fn>', { body: input })
|
|
156
|
-
if (expected_status >= 400) {
|
|
157
|
-
assert(error instanceof FunctionsHttpError)
|
|
158
|
-
assertEquals((error as FunctionsHttpError).context.status, expected_status)
|
|
159
|
-
} else {
|
|
160
|
-
await assertSnapshot(t, data)
|
|
161
|
-
}
|
|
162
|
-
})
|
|
163
|
-
}
|
|
164
|
-
})
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
Gerar fixtures: invocar `payload-capture-instrumenter` (handoff cooperativo).
|
|
168
|
-
|
|
169
|
-
**`webhook` — signature fixture:**
|
|
170
|
-
|
|
171
|
-
```ts
|
|
172
|
-
import { encodeHex } from 'jsr:@std/encoding@1.0.8/hex'
|
|
173
|
-
import { hmac } from 'jsr:@std/crypto@1/hmac'
|
|
174
|
-
|
|
175
|
-
const SECRET = 'test_webhook_secret'
|
|
176
|
-
|
|
177
|
-
function signBody(body: string): string {
|
|
178
|
-
return 't=' + Date.now() + ',v1=' + encodeHex(hmac('SHA-256', SECRET, body))
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
Deno.test('<fn> — accept valid signature', async () => {
|
|
182
|
-
const body = JSON.stringify({ type: 'invoice.paid' })
|
|
183
|
-
const res = await fetch(`${URL}/functions/v1/<fn>`, {
|
|
184
|
-
method: 'POST',
|
|
185
|
-
headers: {
|
|
186
|
-
'Content-Type': 'application/json',
|
|
187
|
-
'Stripe-Signature': signBody(body),
|
|
188
|
-
},
|
|
189
|
-
body,
|
|
190
|
-
})
|
|
191
|
-
assertEquals(res.status, 200)
|
|
192
|
-
})
|
|
193
|
-
|
|
194
|
-
Deno.test('<fn> — reject invalid signature', async () => {
|
|
195
|
-
const res = await fetch(`${URL}/functions/v1/<fn>`, {
|
|
196
|
-
method: 'POST',
|
|
197
|
-
headers: { 'Content-Type': 'application/json', 'Stripe-Signature': 'invalid' },
|
|
198
|
-
body: '{}',
|
|
199
|
-
})
|
|
200
|
-
assertEquals(res.status, 400)
|
|
201
|
-
})
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
**`rag` — determinismo via temperature=0 + seed:**
|
|
205
|
-
|
|
206
|
-
```ts
|
|
207
|
-
Deno.test('<fn> — deterministic embedding', async () => {
|
|
208
|
-
const { data: a } = await supabase.functions.invoke('<fn>', { body: { text: 'hello world' } })
|
|
209
|
-
const { data: b } = await supabase.functions.invoke('<fn>', { body: { text: 'hello world' } })
|
|
210
|
-
// gte-small é determinístico — same input, same vector
|
|
211
|
-
assertEquals(a.embedding, b.embedding)
|
|
212
|
-
})
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
### Step 5 — `.env.local` fixture
|
|
216
|
-
|
|
217
|
-
Garante `supabase/functions/.env` ou `.env.local` com chaves locais para testing:
|
|
218
|
-
|
|
219
|
-
```bash
|
|
220
|
-
test -f supabase/functions/.env || cat > supabase/functions/.env <<EOF
|
|
221
|
-
SUPABASE_URL=http://localhost:54321
|
|
222
|
-
SUPABASE_PUBLISHABLE_KEY=$(supabase status --output json | jq -r '.api.publishableKey // .anon_key')
|
|
223
|
-
SUPABASE_SECRET_KEY=$(supabase status --output json | jq -r '.api.secretKey // .service_role_key')
|
|
224
|
-
EOF
|
|
225
|
-
```
|
|
226
|
-
|
|
227
|
-
### Step 6 — Handoff opcional para payload capture
|
|
228
|
-
|
|
229
|
-
Se `pattern == characterization` e fixtures não existem, sugira:
|
|
230
|
-
|
|
231
|
-
```
|
|
232
|
-
═══════════════════════════════════════════════════════════
|
|
233
|
-
HANDOFF SUGERIDO · payload-capture-instrumenter
|
|
234
|
-
═══════════════════════════════════════════════════════════
|
|
235
|
-
|
|
236
|
-
Para gerar fixtures reais (sanitizados) via mcp__supabase__get_logs:
|
|
237
|
-
/capturar-payloads <function_name> --days 7
|
|
238
|
-
|
|
239
|
-
Após captura, este agent gera characterization tests usando fixtures.
|
|
240
|
-
```
|
|
241
|
-
|
|
242
|
-
### Step 7 — Output
|
|
243
|
-
|
|
244
|
-
```
|
|
245
|
-
═══════════════════════════════════════════════════════════
|
|
246
|
-
EDGE FUNCTION TESTS CRIADOS · <function_name>
|
|
247
|
-
═══════════════════════════════════════════════════════════
|
|
248
|
-
|
|
249
|
-
Arquivo: supabase/functions/tests/<function_name>-test.ts
|
|
250
|
-
|
|
251
|
-
Coverage:
|
|
252
|
-
✓ happy path (1 test)
|
|
253
|
-
✓ validation error (1 test)
|
|
254
|
-
✓ auth failure (1 test)
|
|
255
|
-
✓ rate limit handling (1 test)
|
|
256
|
-
✓ timeout / downstream error (1 test)
|
|
257
|
-
[pattern-specific: characterization | webhook | rag | mcp]
|
|
258
|
-
|
|
259
|
-
Rodar:
|
|
260
|
-
supabase start # se ainda não rodando
|
|
261
|
-
supabase functions serve <function_name> --env-file supabase/functions/.env
|
|
262
|
-
deno test --allow-all supabase/functions/tests/<function_name>-test.ts
|
|
263
|
-
|
|
264
|
-
Debug:
|
|
265
|
-
supabase functions serve <function_name> --inspect-mode brk # Chrome DevTools porta 8083
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
## Anti-patterns prevenidos
|
|
269
|
-
|
|
270
|
-
- Test contra prod (sempre `localhost:54321` via `supabase start`)
|
|
271
|
-
- Mock do client Supabase inteiro (DB real é mais fiel)
|
|
272
|
-
- Test sem cleanup (entre testes, estado vaza)
|
|
273
|
-
- `error.message` como assertion (string fragil — assert `error.code` enum)
|
|
274
|
-
- Test rodando em paralelo sem `policy = "per_worker"` para Edge runtime
|
|
275
|
-
|
|
276
|
-
## Quando NÃO invocar
|
|
277
|
-
|
|
278
|
-
- Função sem código próprio (só passthrough de DB function) — escreva `pgtap` em vez (skill: `supabase-pgtap-testing`)
|
|
279
|
-
- Função com side effects irreversíveis sem mode de test (e-commerce real charge) — exigir feature flag `SIMULATE=1` primeiro
|
|
280
|
-
- Função MCP server — usar MCP Inspector em vez de Deno test
|
|
281
|
-
|
|
282
|
-
## Ver também
|
|
283
|
-
|
|
284
|
-
- [`supabase-edge-fn-writer`](./supabase-edge-fn-writer.md) — upstream que cria a função
|
|
285
|
-
- [`payload-capture-instrumenter`](./payload-capture-instrumenter.md) — capturar fixtures reais
|
|
286
|
-
- [`legacy-characterizer`](./legacy-characterizer.md) — characterization tests genéricos
|
|
287
|
-
- [`supabase-edge-functions-testing`](../skills/supabase-edge-functions-testing/SKILL.md) — folder structure + Chrome debug
|
|
288
|
-
- [`supabase-pgtap-testing`](../skills/supabase-pgtap-testing/SKILL.md) — tests de DB layer
|
|
1
|
+
---
|
|
2
|
+
name: supabase-edge-fn-tester
|
|
3
|
+
tier: specialized
|
|
4
|
+
description: Gera Deno tests para Edge Functions Supabase — equivalence classes happy/validation/auth/rate-limit/timeout, fixtures sanitizados, snapshot jsr:@std/testing, characterization para legacy.
|
|
5
|
+
tools: Read, Write, Edit, Bash, Grep, Glob, Task
|
|
6
|
+
color: teal
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
Você é o Edge Function **tester** Supabase. Recebe nome de uma Edge Function existente e gera `supabase/functions/tests/<fn>-test.ts` com cobertura canônica de 5 equivalence classes + opcionalmente captura fixtures reais via logs.
|
|
10
|
+
|
|
11
|
+
**Compat:** Full em todos os IDEs (filesystem-only).
|
|
12
|
+
|
|
13
|
+
## Por que existe
|
|
14
|
+
|
|
15
|
+
`supabase-edge-fn-writer` cria funções com instrumentação OTel + SRE defenses, mas **não gera tests automaticamente**. Tests são primeira camada de regressão para mudanças futuras — sem eles, refactor é cego. Este agent é o **handoff downstream** canônico.
|
|
16
|
+
|
|
17
|
+
## Skills consultadas
|
|
18
|
+
|
|
19
|
+
- [`supabase-edge-functions-testing`](../skills/supabase-edge-functions-testing/SKILL.md) — folder structure + Deno test runner
|
|
20
|
+
- [`supabase-edge-functions-auth`](../skills/supabase-edge-functions-auth/SKILL.md) — autenticar tests user-scoped
|
|
21
|
+
- [`supabase-edge-functions-limits`](../skills/supabase-edge-functions-limits/SKILL.md) — status codes esperados
|
|
22
|
+
- [`legacy-characterization-tests`](../skills/legacy-characterization-tests/SKILL.md) — Edge Function sem tests prévios
|
|
23
|
+
- [`pre-refactor-characterization`](../skills/pre-refactor-characterization/SKILL.md) — payload capture pattern
|
|
24
|
+
- [`ai-prompt-characterization`](../skills/ai-prompt-characterization/SKILL.md) — Edge Function com LLM (temperature=0 + seed fixo)
|
|
25
|
+
- [`legacy-api-only-applications`](../skills/legacy-api-only-applications/SKILL.md) — FakeProvider para tests determinísticos
|
|
26
|
+
|
|
27
|
+
## Inputs esperados
|
|
28
|
+
|
|
29
|
+
- `function_name`: kebab-case (ex: `orders`, `stripe-webhook`)
|
|
30
|
+
- (Opcional) `auth_mode`: detectado automaticamente de `config.toml` se não passado
|
|
31
|
+
- (Opcional) `pattern`: `'basic' | 'characterization' | 'webhook' | 'rag' | 'mcp'`
|
|
32
|
+
- (Opcional) `capture_payloads`: bool — se true, agent invoca `payload-capture-instrumenter` antes para coletar fixtures reais
|
|
33
|
+
|
|
34
|
+
## Passos
|
|
35
|
+
|
|
36
|
+
### Step 0 — Preflight
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# 1. localizar função
|
|
40
|
+
test -d supabase/functions/<function_name> || exit "função não existe"
|
|
41
|
+
|
|
42
|
+
# 2. ler config.toml para detectar verify_jwt + entrypoint
|
|
43
|
+
grep -A 3 "^\[functions\.<function_name>\]" supabase/config.toml
|
|
44
|
+
|
|
45
|
+
# 3. checar se já existem tests
|
|
46
|
+
ls supabase/functions/tests/<function_name>-test.ts 2>/dev/null && \
|
|
47
|
+
echo "WARN: tests já existem — extending vs replacing?"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Step 1 — Ler o `index.ts` da função
|
|
51
|
+
|
|
52
|
+
Extrair:
|
|
53
|
+
- Auth mode (procura `withSupabase({ auth: ... })` ou `auth.getUser`)
|
|
54
|
+
- Endpoints (Hono routes / método HTTP)
|
|
55
|
+
- Inputs (zod schema, parse de body)
|
|
56
|
+
- Error classifier (`classifyError` enum)
|
|
57
|
+
- Dependências externas (npm imports → fakeable?)
|
|
58
|
+
|
|
59
|
+
### Step 2 — Decidir pattern de tests
|
|
60
|
+
|
|
61
|
+
| Pattern | Quando usar | Skills |
|
|
62
|
+
|---|---|---|
|
|
63
|
+
| `basic` | Função nova com behavior conhecido | testing |
|
|
64
|
+
| `characterization` | Função legacy SEM tests — capturar estado atual antes de qualquer mudança | legacy-characterization-tests + pre-refactor-characterization |
|
|
65
|
+
| `webhook` | Função com signature validation (Stripe/GitHub) | testing + fake signature fixture |
|
|
66
|
+
| `rag` | Edge Function com Supabase.ai ou OpenAI | ai-prompt-characterization (temp=0 + seed) |
|
|
67
|
+
| `mcp` | MCP server (mcp-lite) | testing + MCP inspector spec |
|
|
68
|
+
|
|
69
|
+
### Step 3 — Gerar `supabase/functions/tests/<fn>-test.ts`
|
|
70
|
+
|
|
71
|
+
**Template canônico (5 equivalence classes):**
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
// supabase/functions/tests/<fn>-test.ts
|
|
75
|
+
import { assert, assertEquals, assertSnapshot } from 'jsr:@std/assert@1'
|
|
76
|
+
import { createClient, FunctionsHttpError } from 'npm:@supabase/supabase-js@2.95.0'
|
|
77
|
+
import 'jsr:@std/dotenv@0.225.5/load'
|
|
78
|
+
|
|
79
|
+
const URL = Deno.env.get('SUPABASE_URL')!
|
|
80
|
+
const KEY = Deno.env.get('SUPABASE_PUBLISHABLE_KEY')!
|
|
81
|
+
const supabase = createClient(URL, KEY, {
|
|
82
|
+
auth: { autoRefreshToken: false, persistSession: false, detectSessionInUrl: false },
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
// =========================
|
|
86
|
+
// 1. HAPPY PATH
|
|
87
|
+
// =========================
|
|
88
|
+
Deno.test('<fn> — happy path', async () => {
|
|
89
|
+
const { data, error } = await supabase.functions.invoke('<fn>', {
|
|
90
|
+
body: { /* ... valid payload ... */ },
|
|
91
|
+
})
|
|
92
|
+
assert(!error, `unexpected error: ${error?.message}`)
|
|
93
|
+
assertEquals(data.status, 'ok')
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
// =========================
|
|
97
|
+
// 2. VALIDATION ERROR
|
|
98
|
+
// =========================
|
|
99
|
+
Deno.test('<fn> — validation rejection', async () => {
|
|
100
|
+
const { error } = await supabase.functions.invoke('<fn>', { body: {} })
|
|
101
|
+
assert(error instanceof FunctionsHttpError)
|
|
102
|
+
const body = await (error as FunctionsHttpError).context.json()
|
|
103
|
+
assertEquals(body.code, 'validation')
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
// =========================
|
|
107
|
+
// 3. AUTH FAILURE
|
|
108
|
+
// =========================
|
|
109
|
+
Deno.test('<fn> — unauthorized when JWT missing', async () => {
|
|
110
|
+
const anon = createClient(URL, 'invalid_key')
|
|
111
|
+
const { error } = await anon.functions.invoke('<fn>', { body: { /* ... */ } })
|
|
112
|
+
assert(error instanceof FunctionsHttpError)
|
|
113
|
+
assertEquals((error as FunctionsHttpError).context.status, 401)
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
// =========================
|
|
117
|
+
// 4. RATE LIMIT (se aplicável — função recursive)
|
|
118
|
+
// =========================
|
|
119
|
+
Deno.test('<fn> — graceful handling of RateLimitError', async () => {
|
|
120
|
+
// Simular saturação invocando 50x em série
|
|
121
|
+
const promises = Array.from({ length: 50 }, () => supabase.functions.invoke('<fn>', { body: { quick: true } }))
|
|
122
|
+
const results = await Promise.allSettled(promises)
|
|
123
|
+
// Pelo menos algumas devem retornar 429 ou Retry-After
|
|
124
|
+
const rejected = results.filter((r) => r.status === 'fulfilled' && r.value.error)
|
|
125
|
+
// Não asserta exatamente — depende do budget atual
|
|
126
|
+
assert(rejected.length >= 0)
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
// =========================
|
|
130
|
+
// 5. TIMEOUT / DOWNSTREAM ERROR
|
|
131
|
+
// =========================
|
|
132
|
+
Deno.test('<fn> — fail gracefully on downstream timeout', async () => {
|
|
133
|
+
const { data, error } = await supabase.functions.invoke('<fn>', {
|
|
134
|
+
body: { simulate: 'downstream-timeout' }, // requer feature flag/test mode
|
|
135
|
+
})
|
|
136
|
+
if (error instanceof FunctionsHttpError) {
|
|
137
|
+
assertEquals((error as FunctionsHttpError).context.status, 504)
|
|
138
|
+
} else {
|
|
139
|
+
// ou response normal com fallback degraded
|
|
140
|
+
assertEquals(data.degraded, true)
|
|
141
|
+
}
|
|
142
|
+
})
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Step 4 — Pattern-specific extensions
|
|
146
|
+
|
|
147
|
+
**`characterization` — captura golden snapshot:**
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
import payloads from './fixtures/<fn>-payloads.json' with { type: 'json' }
|
|
151
|
+
|
|
152
|
+
Deno.test('<fn> — characterization (5 equivalence classes)', async (t) => {
|
|
153
|
+
for (const { name, input, expected_status } of payloads) {
|
|
154
|
+
await t.step(name, async () => {
|
|
155
|
+
const { data, error } = await supabase.functions.invoke('<fn>', { body: input })
|
|
156
|
+
if (expected_status >= 400) {
|
|
157
|
+
assert(error instanceof FunctionsHttpError)
|
|
158
|
+
assertEquals((error as FunctionsHttpError).context.status, expected_status)
|
|
159
|
+
} else {
|
|
160
|
+
await assertSnapshot(t, data)
|
|
161
|
+
}
|
|
162
|
+
})
|
|
163
|
+
}
|
|
164
|
+
})
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Gerar fixtures: invocar `payload-capture-instrumenter` (handoff cooperativo).
|
|
168
|
+
|
|
169
|
+
**`webhook` — signature fixture:**
|
|
170
|
+
|
|
171
|
+
```ts
|
|
172
|
+
import { encodeHex } from 'jsr:@std/encoding@1.0.8/hex'
|
|
173
|
+
import { hmac } from 'jsr:@std/crypto@1/hmac'
|
|
174
|
+
|
|
175
|
+
const SECRET = 'test_webhook_secret'
|
|
176
|
+
|
|
177
|
+
function signBody(body: string): string {
|
|
178
|
+
return 't=' + Date.now() + ',v1=' + encodeHex(hmac('SHA-256', SECRET, body))
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
Deno.test('<fn> — accept valid signature', async () => {
|
|
182
|
+
const body = JSON.stringify({ type: 'invoice.paid' })
|
|
183
|
+
const res = await fetch(`${URL}/functions/v1/<fn>`, {
|
|
184
|
+
method: 'POST',
|
|
185
|
+
headers: {
|
|
186
|
+
'Content-Type': 'application/json',
|
|
187
|
+
'Stripe-Signature': signBody(body),
|
|
188
|
+
},
|
|
189
|
+
body,
|
|
190
|
+
})
|
|
191
|
+
assertEquals(res.status, 200)
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
Deno.test('<fn> — reject invalid signature', async () => {
|
|
195
|
+
const res = await fetch(`${URL}/functions/v1/<fn>`, {
|
|
196
|
+
method: 'POST',
|
|
197
|
+
headers: { 'Content-Type': 'application/json', 'Stripe-Signature': 'invalid' },
|
|
198
|
+
body: '{}',
|
|
199
|
+
})
|
|
200
|
+
assertEquals(res.status, 400)
|
|
201
|
+
})
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
**`rag` — determinismo via temperature=0 + seed:**
|
|
205
|
+
|
|
206
|
+
```ts
|
|
207
|
+
Deno.test('<fn> — deterministic embedding', async () => {
|
|
208
|
+
const { data: a } = await supabase.functions.invoke('<fn>', { body: { text: 'hello world' } })
|
|
209
|
+
const { data: b } = await supabase.functions.invoke('<fn>', { body: { text: 'hello world' } })
|
|
210
|
+
// gte-small é determinístico — same input, same vector
|
|
211
|
+
assertEquals(a.embedding, b.embedding)
|
|
212
|
+
})
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Step 5 — `.env.local` fixture
|
|
216
|
+
|
|
217
|
+
Garante `supabase/functions/.env` ou `.env.local` com chaves locais para testing:
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
test -f supabase/functions/.env || cat > supabase/functions/.env <<EOF
|
|
221
|
+
SUPABASE_URL=http://localhost:54321
|
|
222
|
+
SUPABASE_PUBLISHABLE_KEY=$(supabase status --output json | jq -r '.api.publishableKey // .anon_key')
|
|
223
|
+
SUPABASE_SECRET_KEY=$(supabase status --output json | jq -r '.api.secretKey // .service_role_key')
|
|
224
|
+
EOF
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Step 6 — Handoff opcional para payload capture
|
|
228
|
+
|
|
229
|
+
Se `pattern == characterization` e fixtures não existem, sugira:
|
|
230
|
+
|
|
231
|
+
```
|
|
232
|
+
═══════════════════════════════════════════════════════════
|
|
233
|
+
HANDOFF SUGERIDO · payload-capture-instrumenter
|
|
234
|
+
═══════════════════════════════════════════════════════════
|
|
235
|
+
|
|
236
|
+
Para gerar fixtures reais (sanitizados) via mcp__supabase__get_logs:
|
|
237
|
+
/capturar-payloads <function_name> --days 7
|
|
238
|
+
|
|
239
|
+
Após captura, este agent gera characterization tests usando fixtures.
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Step 7 — Output
|
|
243
|
+
|
|
244
|
+
```
|
|
245
|
+
═══════════════════════════════════════════════════════════
|
|
246
|
+
EDGE FUNCTION TESTS CRIADOS · <function_name>
|
|
247
|
+
═══════════════════════════════════════════════════════════
|
|
248
|
+
|
|
249
|
+
Arquivo: supabase/functions/tests/<function_name>-test.ts
|
|
250
|
+
|
|
251
|
+
Coverage:
|
|
252
|
+
✓ happy path (1 test)
|
|
253
|
+
✓ validation error (1 test)
|
|
254
|
+
✓ auth failure (1 test)
|
|
255
|
+
✓ rate limit handling (1 test)
|
|
256
|
+
✓ timeout / downstream error (1 test)
|
|
257
|
+
[pattern-specific: characterization | webhook | rag | mcp]
|
|
258
|
+
|
|
259
|
+
Rodar:
|
|
260
|
+
supabase start # se ainda não rodando
|
|
261
|
+
supabase functions serve <function_name> --env-file supabase/functions/.env
|
|
262
|
+
deno test --allow-all supabase/functions/tests/<function_name>-test.ts
|
|
263
|
+
|
|
264
|
+
Debug:
|
|
265
|
+
supabase functions serve <function_name> --inspect-mode brk # Chrome DevTools porta 8083
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
## Anti-patterns prevenidos
|
|
269
|
+
|
|
270
|
+
- Test contra prod (sempre `localhost:54321` via `supabase start`)
|
|
271
|
+
- Mock do client Supabase inteiro (DB real é mais fiel)
|
|
272
|
+
- Test sem cleanup (entre testes, estado vaza)
|
|
273
|
+
- `error.message` como assertion (string fragil — assert `error.code` enum)
|
|
274
|
+
- Test rodando em paralelo sem `policy = "per_worker"` para Edge runtime
|
|
275
|
+
|
|
276
|
+
## Quando NÃO invocar
|
|
277
|
+
|
|
278
|
+
- Função sem código próprio (só passthrough de DB function) — escreva `pgtap` em vez (skill: `supabase-pgtap-testing`)
|
|
279
|
+
- Função com side effects irreversíveis sem mode de test (e-commerce real charge) — exigir feature flag `SIMULATE=1` primeiro
|
|
280
|
+
- Função MCP server — usar MCP Inspector em vez de Deno test
|
|
281
|
+
|
|
282
|
+
## Ver também
|
|
283
|
+
|
|
284
|
+
- [`supabase-edge-fn-writer`](./supabase-edge-fn-writer.md) — upstream que cria a função
|
|
285
|
+
- [`payload-capture-instrumenter`](./payload-capture-instrumenter.md) — capturar fixtures reais
|
|
286
|
+
- [`legacy-characterizer`](./legacy-characterizer.md) — characterization tests genéricos
|
|
287
|
+
- [`supabase-edge-functions-testing`](../skills/supabase-edge-functions-testing/SKILL.md) — folder structure + Chrome debug
|
|
288
|
+
- [`supabase-pgtap-testing`](../skills/supabase-pgtap-testing/SKILL.md) — tests de DB layer
|