@luanpdd/kit-mcp 1.33.0 → 1.34.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/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/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 +13 -11
- 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/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,309 +1,309 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: supabase-edge-functions-auth
|
|
3
|
-
description: Use ao autenticar Edge Functions Supabase 2026 — package @supabase/server, withSupabase({auth}), createSupabaseContext, Authorization JWT vs apikey, toggle verify_jwt por função no config.toml.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Supabase — Edge Functions Auth (`@supabase/server`) · 2026
|
|
7
|
-
|
|
8
|
-
## Quando usar
|
|
9
|
-
|
|
10
|
-
Carrega quando:
|
|
11
|
-
|
|
12
|
-
- "auth em Edge Function", "withSupabase", "createSupabaseContext"
|
|
13
|
-
- "verify_jwt true/false", "Authorization vs apikey", "401 edge function"
|
|
14
|
-
- "Stripe webhook auth", "service-to-service edge", "cron chamar edge function"
|
|
15
|
-
- "RBAC Edge Function", "user JWT no handler"
|
|
16
|
-
|
|
17
|
-
> Pré-requisito: [`supabase-edge-functions`](../supabase-edge-functions/SKILL.md) (Deno + env vars JSON dict).
|
|
18
|
-
> Complemento: [`supabase-edge-functions-limits`](../supabase-edge-functions-limits/SKILL.md) (status codes 401/403).
|
|
19
|
-
|
|
20
|
-
## Conceito-chave: 2 headers, 2 camadas
|
|
21
|
-
|
|
22
|
-
| Header | Valor | Para |
|
|
23
|
-
|---|---|---|
|
|
24
|
-
| `Authorization` | `Bearer <user-jwt>` | Usuário logado via Supabase Auth |
|
|
25
|
-
| `apikey` | `sb_publishable_...` ou `sb_secret_...` | Cliente browser ou service-to-service |
|
|
26
|
-
|
|
27
|
-
**2 camadas de validação:**
|
|
28
|
-
|
|
29
|
-
1. **Platform-level (`verify_jwt`)** — plataforma valida JWT em `Authorization` antes do handler. Se header ausente/inválido → **401 não chega no código**.
|
|
30
|
-
2. **Handler-level** — você decide o que fazer com credencial recebida.
|
|
31
|
-
|
|
32
|
-
### Pegadinha canônica (#1 causa de 401)
|
|
33
|
-
|
|
34
|
-
Mandar API key (`sb_publishable_*` / `sb_secret_*`) como Bearer:
|
|
35
|
-
|
|
36
|
-
```
|
|
37
|
-
⚠ Authorization: Bearer sb_publishable_abc123 → 401 (não é JWT)
|
|
38
|
-
✓ Authorization: Bearer eyJhbGciOiJI... → JWT válido
|
|
39
|
-
✓ apikey: sb_publishable_abc123 → API key correta
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
API keys 2026 (`sb_*`) **não são JWTs** — a platform check não valida; seu handler não pode usar `auth.getUser()` nelas.
|
|
43
|
-
|
|
44
|
-
## Toggle `verify_jwt` por função
|
|
45
|
-
|
|
46
|
-
```toml
|
|
47
|
-
# supabase/config.toml
|
|
48
|
-
[functions.user-profile]
|
|
49
|
-
verify_jwt = true # default — para funções chamadas com JWT do usuário
|
|
50
|
-
|
|
51
|
-
[functions.stripe-webhook]
|
|
52
|
-
verify_jwt = false # webhook externo (Stripe assina o body — não envia JWT)
|
|
53
|
-
|
|
54
|
-
[functions.internal-cron]
|
|
55
|
-
verify_jwt = false # chamada por cron com apikey: secret_key
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
Regra: deixe `true` quando o caller é browser logado (`supabase.functions.invoke`); desligue para webhooks externos ou service-to-service que autentica via `apikey`.
|
|
59
|
-
|
|
60
|
-
CLI local pode passar `--no-verify-jwt` para um deploy/serve único:
|
|
61
|
-
|
|
62
|
-
```bash
|
|
63
|
-
supabase functions serve hello-world --no-verify-jwt
|
|
64
|
-
supabase functions deploy stripe-webhook --no-verify-jwt
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
## `@supabase/server` — wrapper canônico 2026
|
|
68
|
-
|
|
69
|
-
Package npm que reduz boilerplate de auth + contexto Supabase pré-configurado.
|
|
70
|
-
|
|
71
|
-
### Auth modes
|
|
72
|
-
|
|
73
|
-
| Mode | Aceita | `ctx` recebido |
|
|
74
|
-
|---|---|---|
|
|
75
|
-
| `'user'` | JWT válido em `Authorization` | `ctx.supabase` scoped ao caller (respeita RLS), `ctx.userClaims` |
|
|
76
|
-
| `'secret:<name>'` | `sb_secret_<name>` em `apikey` | `ctx.supabaseAdmin` (bypassa RLS) |
|
|
77
|
-
| `'publishable:<name>'` | `sb_publishable_<name>` em `apikey` | `ctx.supabase` anon |
|
|
78
|
-
| `'none'` | Qualquer caller (sem check) | Cliente plain — handler responsabilidade total |
|
|
79
|
-
|
|
80
|
-
`<name>` referencia chaves nomeadas criadas em **Settings > API keys** (ex: `'secret:automations'`).
|
|
81
|
-
|
|
82
|
-
Combinar modos: `auth: ['user', 'secret:automations']` — primeiro match vence; `ctx.authMode` indica qual.
|
|
83
|
-
|
|
84
|
-
## Patterns canônicos
|
|
85
|
-
|
|
86
|
-
### Pattern 1 — User-facing (RLS aplicada)
|
|
87
|
-
|
|
88
|
-
```ts
|
|
89
|
-
// supabase/functions/notes/index.ts
|
|
90
|
-
import { withSupabase } from 'npm:@supabase/server@1'
|
|
91
|
-
|
|
92
|
-
export default {
|
|
93
|
-
fetch: withSupabase({ auth: 'user' }, async (req, ctx) => {
|
|
94
|
-
// ctx.supabase já vem scoped ao caller → RLS policies do user aplicadas
|
|
95
|
-
const { data, error } = await ctx.supabase.from('notes').select('*')
|
|
96
|
-
if (error) return Response.json({ error: error.message }, { status: 500 })
|
|
97
|
-
return Response.json({ data, email: ctx.userClaims?.email })
|
|
98
|
-
}),
|
|
99
|
-
}
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
```toml
|
|
103
|
-
[functions.notes]
|
|
104
|
-
verify_jwt = true
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
### Pattern 2 — Service-to-service (cron/pg_net/worker)
|
|
108
|
-
|
|
109
|
-
```ts
|
|
110
|
-
// supabase/functions/run-automations/index.ts
|
|
111
|
-
import { withSupabase } from 'npm:@supabase/server@1'
|
|
112
|
-
|
|
113
|
-
export default {
|
|
114
|
-
fetch: withSupabase({ auth: 'secret:automations' }, async (req, ctx) => {
|
|
115
|
-
// ctx.supabaseAdmin → bypassa RLS, scoped ao secret key 'automations'
|
|
116
|
-
await ctx.supabaseAdmin.from('automation_log').insert({ ran_at: new Date() })
|
|
117
|
-
return Response.json({ ok: true })
|
|
118
|
-
}),
|
|
119
|
-
}
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
```toml
|
|
123
|
-
[functions.run-automations]
|
|
124
|
-
verify_jwt = false
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
Crie a chave nomeada no Dashboard → **Settings > API keys** com nome `automations`. Compartilhe `sb_secret_...` resultante apenas com o serviço chamador.
|
|
128
|
-
|
|
129
|
-
### Pattern 3 — Webhook externo (Stripe/GitHub/Resend)
|
|
130
|
-
|
|
131
|
-
```ts
|
|
132
|
-
// supabase/functions/stripe-webhook/index.ts
|
|
133
|
-
import { withSupabase } from 'npm:@supabase/server@1'
|
|
134
|
-
import Stripe from 'npm:stripe@17'
|
|
135
|
-
|
|
136
|
-
const stripe = new Stripe(Deno.env.get('STRIPE_SECRET_KEY')!)
|
|
137
|
-
|
|
138
|
-
export default {
|
|
139
|
-
fetch: withSupabase({ auth: 'none' }, async (req, ctx) => {
|
|
140
|
-
const signature = req.headers.get('stripe-signature') ?? ''
|
|
141
|
-
const body = await req.text()
|
|
142
|
-
try {
|
|
143
|
-
stripe.webhooks.constructEvent(body, signature, Deno.env.get('STRIPE_WEBHOOK_SECRET')!)
|
|
144
|
-
} catch {
|
|
145
|
-
return new Response('bad signature', { status: 400 })
|
|
146
|
-
}
|
|
147
|
-
// ctx.supabaseAdmin disponível para DB writes
|
|
148
|
-
await ctx.supabaseAdmin.from('stripe_events').insert({ raw: body })
|
|
149
|
-
return Response.json({ received: true })
|
|
150
|
-
}),
|
|
151
|
-
}
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
```toml
|
|
155
|
-
[functions.stripe-webhook]
|
|
156
|
-
verify_jwt = false
|
|
157
|
-
```
|
|
158
|
-
|
|
159
|
-
`auth: 'none'` desliga toda checagem de credencial Supabase. **Você é responsável por validar via signature do provedor.** Nunca use em endpoint sensível sem outro mecanismo.
|
|
160
|
-
|
|
161
|
-
### Pattern 4 — Função pública (health check)
|
|
162
|
-
|
|
163
|
-
```ts
|
|
164
|
-
// supabase/functions/health/index.ts
|
|
165
|
-
import { withSupabase } from 'npm:@supabase/server@1'
|
|
166
|
-
|
|
167
|
-
export default {
|
|
168
|
-
fetch: withSupabase({ auth: 'none' }, async (_req, _ctx) => {
|
|
169
|
-
return Response.json({ ok: true, region: Deno.env.get('SB_REGION') })
|
|
170
|
-
}),
|
|
171
|
-
}
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
```toml
|
|
175
|
-
[functions.health]
|
|
176
|
-
verify_jwt = false
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
### Pattern 5 — Modo combinado (user + service)
|
|
180
|
-
|
|
181
|
-
```ts
|
|
182
|
-
// supabase/functions/dual/index.ts
|
|
183
|
-
import { withSupabase } from 'npm:@supabase/server@1'
|
|
184
|
-
|
|
185
|
-
export default {
|
|
186
|
-
fetch: withSupabase({ auth: ['user', 'secret:automations'] }, async (req, ctx) => {
|
|
187
|
-
if (ctx.authMode === 'user') {
|
|
188
|
-
// user flow — ctx.supabase scoped ao caller
|
|
189
|
-
const { data } = await ctx.supabase.from('me').select('*').single()
|
|
190
|
-
return Response.json(data)
|
|
191
|
-
}
|
|
192
|
-
// service flow — ctx.supabaseAdmin bypassa RLS
|
|
193
|
-
await ctx.supabaseAdmin.from('audit').insert({ source: 'automation' })
|
|
194
|
-
return Response.json({ ok: true })
|
|
195
|
-
}),
|
|
196
|
-
}
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
### Pattern 6 — Erros customizados via `createSupabaseContext`
|
|
200
|
-
|
|
201
|
-
```ts
|
|
202
|
-
import { createSupabaseContext } from 'npm:@supabase/server@1'
|
|
203
|
-
|
|
204
|
-
export default {
|
|
205
|
-
fetch: async (req: Request) => {
|
|
206
|
-
const { data: ctx, error } = await createSupabaseContext(req, { auth: 'user' })
|
|
207
|
-
if (error) {
|
|
208
|
-
// shape 401 conforme contrato API
|
|
209
|
-
return Response.json(
|
|
210
|
-
{ message: error.message, code: error.code },
|
|
211
|
-
{ status: error.status, headers: { 'WWW-Authenticate': 'Bearer' } },
|
|
212
|
-
)
|
|
213
|
-
}
|
|
214
|
-
return Response.json({ message: `hello ${ctx.userClaims?.email}` })
|
|
215
|
-
},
|
|
216
|
-
}
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
### Pattern 7 — Sem `@supabase/server` (RLS manual)
|
|
220
|
-
|
|
221
|
-
Quando precisar de controle fino ou não puder adicionar dependência:
|
|
222
|
-
|
|
223
|
-
```ts
|
|
224
|
-
import { createClient } from 'npm:@supabase/supabase-js@2.95.0'
|
|
225
|
-
|
|
226
|
-
const PUBLISHABLE = JSON.parse(Deno.env.get('SUPABASE_PUBLISHABLE_KEYS')!)
|
|
227
|
-
|
|
228
|
-
Deno.serve(async (req) => {
|
|
229
|
-
// PT-BR: forward Authorization → supabase-js → queries respeitam RLS do user
|
|
230
|
-
const supabase = createClient(
|
|
231
|
-
Deno.env.get('SUPABASE_URL')!,
|
|
232
|
-
PUBLISHABLE['default'],
|
|
233
|
-
{ global: { headers: { Authorization: req.headers.get('Authorization')! } } },
|
|
234
|
-
)
|
|
235
|
-
const { data, error } = await supabase.from('profiles').select('*')
|
|
236
|
-
if (error) return Response.json({ error: error.message }, { status: 500 })
|
|
237
|
-
return Response.json(data)
|
|
238
|
-
})
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
Para validar JWT manualmente:
|
|
242
|
-
|
|
243
|
-
```ts
|
|
244
|
-
const { data: { user }, error } = await supabase.auth.getUser(
|
|
245
|
-
req.headers.get('Authorization')?.replace('Bearer ', '') ?? ''
|
|
246
|
-
)
|
|
247
|
-
if (!user || error) return new Response('unauthorized', { status: 401 })
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
## Env vars 2026 esperadas
|
|
251
|
-
|
|
252
|
-
`@supabase/server` lê estas (auto-provisionadas na plataforma + CLI local):
|
|
253
|
-
|
|
254
|
-
| Variável | O que é |
|
|
255
|
-
|---|---|
|
|
256
|
-
| `SUPABASE_URL` | URL do projeto |
|
|
257
|
-
| `SUPABASE_PUBLISHABLE_KEYS` | JSON dict de chaves publishable |
|
|
258
|
-
| `SUPABASE_SECRET_KEYS` | JSON dict de chaves secret |
|
|
259
|
-
| `SUPABASE_JWKS` | JWK Set para validar user JWTs |
|
|
260
|
-
|
|
261
|
-
Fallback local (single-key): `SUPABASE_PUBLISHABLE_KEY` e `SUPABASE_SECRET_KEY` ainda funcionam.
|
|
262
|
-
|
|
263
|
-
## Anti-patterns
|
|
264
|
-
|
|
265
|
-
### AA1 — API key como Bearer
|
|
266
|
-
|
|
267
|
-
```
|
|
268
|
-
⚠ Authorization: Bearer sb_publishable_abc → 401, gateway rejeita
|
|
269
|
-
✓ apikey: sb_publishable_abc
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
### AA2 — Chamar `auth.getUser()` em função `verify_jwt=false` sem repassar Authorization
|
|
273
|
-
|
|
274
|
-
Função com `verify_jwt=false` desliga apenas a **plataforma** — `auth.getUser()` ainda pode ser chamada se o caller mandar JWT. Mas se você não recebe JWT (webhook), `auth.getUser()` retorna `null`. Para Service-to-Service, use `auth: 'secret:<name>'` e `ctx.supabaseAdmin`.
|
|
275
|
-
|
|
276
|
-
### AA3 — `service_role` no client browser
|
|
277
|
-
|
|
278
|
-
`SUPABASE_SECRET_KEYS` (e legacy `SUPABASE_SERVICE_ROLE_KEY`) bypassam RLS. NUNCA expor em código browser. Só server-side (Edge Function, backend Node).
|
|
279
|
-
|
|
280
|
-
### AA4 — `auth: 'none'` em endpoint que lê/grava dado sensível
|
|
281
|
-
|
|
282
|
-
`'none'` aceita qualquer caller. Use apenas quando há outra validação (signature webhook, mTLS, etc.) ou endpoint genuinamente público (health check).
|
|
283
|
-
|
|
284
|
-
### AA5 — Hardcode `'service_role'` em vez de chave nomeada
|
|
285
|
-
|
|
286
|
-
Em 2026, prefira chaves nomeadas (`secret:automations`, `secret:internal-cron`) — permite rotação granular e audit por consumidor. Legacy `SUPABASE_SERVICE_ROLE_KEY` ainda funciona mas é uma única chave global.
|
|
287
|
-
|
|
288
|
-
### AA6 — `Authorization` E `apikey` ambos errados
|
|
289
|
-
|
|
290
|
-
Browser logado chamando `supabase.functions.invoke` envia **ambos**: `Authorization: Bearer <user-jwt>` + `apikey: sb_publishable_default`. É esperado e correto.
|
|
291
|
-
|
|
292
|
-
## Diagnóstico de 401
|
|
293
|
-
|
|
294
|
-
| Sintoma | Causa provável | Fix |
|
|
295
|
-
|---|---|---|
|
|
296
|
-
| 401 antes do handler | `verify_jwt=true` + Authorization ausente/inválido | mandar JWT válido OU `verify_jwt = false` |
|
|
297
|
-
| 401 do handler (`@supabase/server`) | apikey errada para o mode declarado | conferir mode vs header enviado |
|
|
298
|
-
| 401 só em produção, ok em dev | env vars não setadas em prod | `supabase secrets set` |
|
|
299
|
-
| 401 com `auth.getUser()` returning null | JWT expirou ou JWKS errado | refresh JWT no client |
|
|
300
|
-
|
|
301
|
-
## Ver também
|
|
302
|
-
|
|
303
|
-
- [`supabase-edge-functions`](../supabase-edge-functions/SKILL.md) — base Deno + env vars JSON dict
|
|
304
|
-
- [`supabase-edge-functions-limits`](../supabase-edge-functions-limits/SKILL.md) — status codes 401/403/405
|
|
305
|
-
- [`supabase-custom-claims-rbac`](../supabase-custom-claims-rbac/SKILL.md) — Custom Claims em JWT acessíveis via `ctx.userClaims`
|
|
306
|
-
- [`supabase-rls-policies`](../supabase-rls-policies/SKILL.md) — RLS aplicada quando `ctx.supabase` scoped
|
|
307
|
-
- [`supabase-rls-defense-in-depth`](../supabase-rls-defense-in-depth/SKILL.md) — `secret_role` caveat
|
|
308
|
-
- [`supabase-auth-ssr`](../supabase-auth-ssr/SKILL.md) — clients Next.js v16
|
|
309
|
-
- [`_shared-supabase/glossary.md`](../_shared-supabase/glossary.md) — termos canônicos auth
|
|
1
|
+
---
|
|
2
|
+
name: supabase-edge-functions-auth
|
|
3
|
+
description: Use ao autenticar Edge Functions Supabase 2026 — package @supabase/server, withSupabase({auth}), createSupabaseContext, Authorization JWT vs apikey, toggle verify_jwt por função no config.toml.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Supabase — Edge Functions Auth (`@supabase/server`) · 2026
|
|
7
|
+
|
|
8
|
+
## Quando usar
|
|
9
|
+
|
|
10
|
+
Carrega quando:
|
|
11
|
+
|
|
12
|
+
- "auth em Edge Function", "withSupabase", "createSupabaseContext"
|
|
13
|
+
- "verify_jwt true/false", "Authorization vs apikey", "401 edge function"
|
|
14
|
+
- "Stripe webhook auth", "service-to-service edge", "cron chamar edge function"
|
|
15
|
+
- "RBAC Edge Function", "user JWT no handler"
|
|
16
|
+
|
|
17
|
+
> Pré-requisito: [`supabase-edge-functions`](../supabase-edge-functions/SKILL.md) (Deno + env vars JSON dict).
|
|
18
|
+
> Complemento: [`supabase-edge-functions-limits`](../supabase-edge-functions-limits/SKILL.md) (status codes 401/403).
|
|
19
|
+
|
|
20
|
+
## Conceito-chave: 2 headers, 2 camadas
|
|
21
|
+
|
|
22
|
+
| Header | Valor | Para |
|
|
23
|
+
|---|---|---|
|
|
24
|
+
| `Authorization` | `Bearer <user-jwt>` | Usuário logado via Supabase Auth |
|
|
25
|
+
| `apikey` | `sb_publishable_...` ou `sb_secret_...` | Cliente browser ou service-to-service |
|
|
26
|
+
|
|
27
|
+
**2 camadas de validação:**
|
|
28
|
+
|
|
29
|
+
1. **Platform-level (`verify_jwt`)** — plataforma valida JWT em `Authorization` antes do handler. Se header ausente/inválido → **401 não chega no código**.
|
|
30
|
+
2. **Handler-level** — você decide o que fazer com credencial recebida.
|
|
31
|
+
|
|
32
|
+
### Pegadinha canônica (#1 causa de 401)
|
|
33
|
+
|
|
34
|
+
Mandar API key (`sb_publishable_*` / `sb_secret_*`) como Bearer:
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
⚠ Authorization: Bearer sb_publishable_abc123 → 401 (não é JWT)
|
|
38
|
+
✓ Authorization: Bearer eyJhbGciOiJI... → JWT válido
|
|
39
|
+
✓ apikey: sb_publishable_abc123 → API key correta
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
API keys 2026 (`sb_*`) **não são JWTs** — a platform check não valida; seu handler não pode usar `auth.getUser()` nelas.
|
|
43
|
+
|
|
44
|
+
## Toggle `verify_jwt` por função
|
|
45
|
+
|
|
46
|
+
```toml
|
|
47
|
+
# supabase/config.toml
|
|
48
|
+
[functions.user-profile]
|
|
49
|
+
verify_jwt = true # default — para funções chamadas com JWT do usuário
|
|
50
|
+
|
|
51
|
+
[functions.stripe-webhook]
|
|
52
|
+
verify_jwt = false # webhook externo (Stripe assina o body — não envia JWT)
|
|
53
|
+
|
|
54
|
+
[functions.internal-cron]
|
|
55
|
+
verify_jwt = false # chamada por cron com apikey: secret_key
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Regra: deixe `true` quando o caller é browser logado (`supabase.functions.invoke`); desligue para webhooks externos ou service-to-service que autentica via `apikey`.
|
|
59
|
+
|
|
60
|
+
CLI local pode passar `--no-verify-jwt` para um deploy/serve único:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
supabase functions serve hello-world --no-verify-jwt
|
|
64
|
+
supabase functions deploy stripe-webhook --no-verify-jwt
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## `@supabase/server` — wrapper canônico 2026
|
|
68
|
+
|
|
69
|
+
Package npm que reduz boilerplate de auth + contexto Supabase pré-configurado.
|
|
70
|
+
|
|
71
|
+
### Auth modes
|
|
72
|
+
|
|
73
|
+
| Mode | Aceita | `ctx` recebido |
|
|
74
|
+
|---|---|---|
|
|
75
|
+
| `'user'` | JWT válido em `Authorization` | `ctx.supabase` scoped ao caller (respeita RLS), `ctx.userClaims` |
|
|
76
|
+
| `'secret:<name>'` | `sb_secret_<name>` em `apikey` | `ctx.supabaseAdmin` (bypassa RLS) |
|
|
77
|
+
| `'publishable:<name>'` | `sb_publishable_<name>` em `apikey` | `ctx.supabase` anon |
|
|
78
|
+
| `'none'` | Qualquer caller (sem check) | Cliente plain — handler responsabilidade total |
|
|
79
|
+
|
|
80
|
+
`<name>` referencia chaves nomeadas criadas em **Settings > API keys** (ex: `'secret:automations'`).
|
|
81
|
+
|
|
82
|
+
Combinar modos: `auth: ['user', 'secret:automations']` — primeiro match vence; `ctx.authMode` indica qual.
|
|
83
|
+
|
|
84
|
+
## Patterns canônicos
|
|
85
|
+
|
|
86
|
+
### Pattern 1 — User-facing (RLS aplicada)
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
// supabase/functions/notes/index.ts
|
|
90
|
+
import { withSupabase } from 'npm:@supabase/server@1'
|
|
91
|
+
|
|
92
|
+
export default {
|
|
93
|
+
fetch: withSupabase({ auth: 'user' }, async (req, ctx) => {
|
|
94
|
+
// ctx.supabase já vem scoped ao caller → RLS policies do user aplicadas
|
|
95
|
+
const { data, error } = await ctx.supabase.from('notes').select('*')
|
|
96
|
+
if (error) return Response.json({ error: error.message }, { status: 500 })
|
|
97
|
+
return Response.json({ data, email: ctx.userClaims?.email })
|
|
98
|
+
}),
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
```toml
|
|
103
|
+
[functions.notes]
|
|
104
|
+
verify_jwt = true
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Pattern 2 — Service-to-service (cron/pg_net/worker)
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
// supabase/functions/run-automations/index.ts
|
|
111
|
+
import { withSupabase } from 'npm:@supabase/server@1'
|
|
112
|
+
|
|
113
|
+
export default {
|
|
114
|
+
fetch: withSupabase({ auth: 'secret:automations' }, async (req, ctx) => {
|
|
115
|
+
// ctx.supabaseAdmin → bypassa RLS, scoped ao secret key 'automations'
|
|
116
|
+
await ctx.supabaseAdmin.from('automation_log').insert({ ran_at: new Date() })
|
|
117
|
+
return Response.json({ ok: true })
|
|
118
|
+
}),
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
```toml
|
|
123
|
+
[functions.run-automations]
|
|
124
|
+
verify_jwt = false
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Crie a chave nomeada no Dashboard → **Settings > API keys** com nome `automations`. Compartilhe `sb_secret_...` resultante apenas com o serviço chamador.
|
|
128
|
+
|
|
129
|
+
### Pattern 3 — Webhook externo (Stripe/GitHub/Resend)
|
|
130
|
+
|
|
131
|
+
```ts
|
|
132
|
+
// supabase/functions/stripe-webhook/index.ts
|
|
133
|
+
import { withSupabase } from 'npm:@supabase/server@1'
|
|
134
|
+
import Stripe from 'npm:stripe@17'
|
|
135
|
+
|
|
136
|
+
const stripe = new Stripe(Deno.env.get('STRIPE_SECRET_KEY')!)
|
|
137
|
+
|
|
138
|
+
export default {
|
|
139
|
+
fetch: withSupabase({ auth: 'none' }, async (req, ctx) => {
|
|
140
|
+
const signature = req.headers.get('stripe-signature') ?? ''
|
|
141
|
+
const body = await req.text()
|
|
142
|
+
try {
|
|
143
|
+
stripe.webhooks.constructEvent(body, signature, Deno.env.get('STRIPE_WEBHOOK_SECRET')!)
|
|
144
|
+
} catch {
|
|
145
|
+
return new Response('bad signature', { status: 400 })
|
|
146
|
+
}
|
|
147
|
+
// ctx.supabaseAdmin disponível para DB writes
|
|
148
|
+
await ctx.supabaseAdmin.from('stripe_events').insert({ raw: body })
|
|
149
|
+
return Response.json({ received: true })
|
|
150
|
+
}),
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
```toml
|
|
155
|
+
[functions.stripe-webhook]
|
|
156
|
+
verify_jwt = false
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
`auth: 'none'` desliga toda checagem de credencial Supabase. **Você é responsável por validar via signature do provedor.** Nunca use em endpoint sensível sem outro mecanismo.
|
|
160
|
+
|
|
161
|
+
### Pattern 4 — Função pública (health check)
|
|
162
|
+
|
|
163
|
+
```ts
|
|
164
|
+
// supabase/functions/health/index.ts
|
|
165
|
+
import { withSupabase } from 'npm:@supabase/server@1'
|
|
166
|
+
|
|
167
|
+
export default {
|
|
168
|
+
fetch: withSupabase({ auth: 'none' }, async (_req, _ctx) => {
|
|
169
|
+
return Response.json({ ok: true, region: Deno.env.get('SB_REGION') })
|
|
170
|
+
}),
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
```toml
|
|
175
|
+
[functions.health]
|
|
176
|
+
verify_jwt = false
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Pattern 5 — Modo combinado (user + service)
|
|
180
|
+
|
|
181
|
+
```ts
|
|
182
|
+
// supabase/functions/dual/index.ts
|
|
183
|
+
import { withSupabase } from 'npm:@supabase/server@1'
|
|
184
|
+
|
|
185
|
+
export default {
|
|
186
|
+
fetch: withSupabase({ auth: ['user', 'secret:automations'] }, async (req, ctx) => {
|
|
187
|
+
if (ctx.authMode === 'user') {
|
|
188
|
+
// user flow — ctx.supabase scoped ao caller
|
|
189
|
+
const { data } = await ctx.supabase.from('me').select('*').single()
|
|
190
|
+
return Response.json(data)
|
|
191
|
+
}
|
|
192
|
+
// service flow — ctx.supabaseAdmin bypassa RLS
|
|
193
|
+
await ctx.supabaseAdmin.from('audit').insert({ source: 'automation' })
|
|
194
|
+
return Response.json({ ok: true })
|
|
195
|
+
}),
|
|
196
|
+
}
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Pattern 6 — Erros customizados via `createSupabaseContext`
|
|
200
|
+
|
|
201
|
+
```ts
|
|
202
|
+
import { createSupabaseContext } from 'npm:@supabase/server@1'
|
|
203
|
+
|
|
204
|
+
export default {
|
|
205
|
+
fetch: async (req: Request) => {
|
|
206
|
+
const { data: ctx, error } = await createSupabaseContext(req, { auth: 'user' })
|
|
207
|
+
if (error) {
|
|
208
|
+
// shape 401 conforme contrato API
|
|
209
|
+
return Response.json(
|
|
210
|
+
{ message: error.message, code: error.code },
|
|
211
|
+
{ status: error.status, headers: { 'WWW-Authenticate': 'Bearer' } },
|
|
212
|
+
)
|
|
213
|
+
}
|
|
214
|
+
return Response.json({ message: `hello ${ctx.userClaims?.email}` })
|
|
215
|
+
},
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Pattern 7 — Sem `@supabase/server` (RLS manual)
|
|
220
|
+
|
|
221
|
+
Quando precisar de controle fino ou não puder adicionar dependência:
|
|
222
|
+
|
|
223
|
+
```ts
|
|
224
|
+
import { createClient } from 'npm:@supabase/supabase-js@2.95.0'
|
|
225
|
+
|
|
226
|
+
const PUBLISHABLE = JSON.parse(Deno.env.get('SUPABASE_PUBLISHABLE_KEYS')!)
|
|
227
|
+
|
|
228
|
+
Deno.serve(async (req) => {
|
|
229
|
+
// PT-BR: forward Authorization → supabase-js → queries respeitam RLS do user
|
|
230
|
+
const supabase = createClient(
|
|
231
|
+
Deno.env.get('SUPABASE_URL')!,
|
|
232
|
+
PUBLISHABLE['default'],
|
|
233
|
+
{ global: { headers: { Authorization: req.headers.get('Authorization')! } } },
|
|
234
|
+
)
|
|
235
|
+
const { data, error } = await supabase.from('profiles').select('*')
|
|
236
|
+
if (error) return Response.json({ error: error.message }, { status: 500 })
|
|
237
|
+
return Response.json(data)
|
|
238
|
+
})
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
Para validar JWT manualmente:
|
|
242
|
+
|
|
243
|
+
```ts
|
|
244
|
+
const { data: { user }, error } = await supabase.auth.getUser(
|
|
245
|
+
req.headers.get('Authorization')?.replace('Bearer ', '') ?? ''
|
|
246
|
+
)
|
|
247
|
+
if (!user || error) return new Response('unauthorized', { status: 401 })
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
## Env vars 2026 esperadas
|
|
251
|
+
|
|
252
|
+
`@supabase/server` lê estas (auto-provisionadas na plataforma + CLI local):
|
|
253
|
+
|
|
254
|
+
| Variável | O que é |
|
|
255
|
+
|---|---|
|
|
256
|
+
| `SUPABASE_URL` | URL do projeto |
|
|
257
|
+
| `SUPABASE_PUBLISHABLE_KEYS` | JSON dict de chaves publishable |
|
|
258
|
+
| `SUPABASE_SECRET_KEYS` | JSON dict de chaves secret |
|
|
259
|
+
| `SUPABASE_JWKS` | JWK Set para validar user JWTs |
|
|
260
|
+
|
|
261
|
+
Fallback local (single-key): `SUPABASE_PUBLISHABLE_KEY` e `SUPABASE_SECRET_KEY` ainda funcionam.
|
|
262
|
+
|
|
263
|
+
## Anti-patterns
|
|
264
|
+
|
|
265
|
+
### AA1 — API key como Bearer
|
|
266
|
+
|
|
267
|
+
```
|
|
268
|
+
⚠ Authorization: Bearer sb_publishable_abc → 401, gateway rejeita
|
|
269
|
+
✓ apikey: sb_publishable_abc
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### AA2 — Chamar `auth.getUser()` em função `verify_jwt=false` sem repassar Authorization
|
|
273
|
+
|
|
274
|
+
Função com `verify_jwt=false` desliga apenas a **plataforma** — `auth.getUser()` ainda pode ser chamada se o caller mandar JWT. Mas se você não recebe JWT (webhook), `auth.getUser()` retorna `null`. Para Service-to-Service, use `auth: 'secret:<name>'` e `ctx.supabaseAdmin`.
|
|
275
|
+
|
|
276
|
+
### AA3 — `service_role` no client browser
|
|
277
|
+
|
|
278
|
+
`SUPABASE_SECRET_KEYS` (e legacy `SUPABASE_SERVICE_ROLE_KEY`) bypassam RLS. NUNCA expor em código browser. Só server-side (Edge Function, backend Node).
|
|
279
|
+
|
|
280
|
+
### AA4 — `auth: 'none'` em endpoint que lê/grava dado sensível
|
|
281
|
+
|
|
282
|
+
`'none'` aceita qualquer caller. Use apenas quando há outra validação (signature webhook, mTLS, etc.) ou endpoint genuinamente público (health check).
|
|
283
|
+
|
|
284
|
+
### AA5 — Hardcode `'service_role'` em vez de chave nomeada
|
|
285
|
+
|
|
286
|
+
Em 2026, prefira chaves nomeadas (`secret:automations`, `secret:internal-cron`) — permite rotação granular e audit por consumidor. Legacy `SUPABASE_SERVICE_ROLE_KEY` ainda funciona mas é uma única chave global.
|
|
287
|
+
|
|
288
|
+
### AA6 — `Authorization` E `apikey` ambos errados
|
|
289
|
+
|
|
290
|
+
Browser logado chamando `supabase.functions.invoke` envia **ambos**: `Authorization: Bearer <user-jwt>` + `apikey: sb_publishable_default`. É esperado e correto.
|
|
291
|
+
|
|
292
|
+
## Diagnóstico de 401
|
|
293
|
+
|
|
294
|
+
| Sintoma | Causa provável | Fix |
|
|
295
|
+
|---|---|---|
|
|
296
|
+
| 401 antes do handler | `verify_jwt=true` + Authorization ausente/inválido | mandar JWT válido OU `verify_jwt = false` |
|
|
297
|
+
| 401 do handler (`@supabase/server`) | apikey errada para o mode declarado | conferir mode vs header enviado |
|
|
298
|
+
| 401 só em produção, ok em dev | env vars não setadas em prod | `supabase secrets set` |
|
|
299
|
+
| 401 com `auth.getUser()` returning null | JWT expirou ou JWKS errado | refresh JWT no client |
|
|
300
|
+
|
|
301
|
+
## Ver também
|
|
302
|
+
|
|
303
|
+
- [`supabase-edge-functions`](../supabase-edge-functions/SKILL.md) — base Deno + env vars JSON dict
|
|
304
|
+
- [`supabase-edge-functions-limits`](../supabase-edge-functions-limits/SKILL.md) — status codes 401/403/405
|
|
305
|
+
- [`supabase-custom-claims-rbac`](../supabase-custom-claims-rbac/SKILL.md) — Custom Claims em JWT acessíveis via `ctx.userClaims`
|
|
306
|
+
- [`supabase-rls-policies`](../supabase-rls-policies/SKILL.md) — RLS aplicada quando `ctx.supabase` scoped
|
|
307
|
+
- [`supabase-rls-defense-in-depth`](../supabase-rls-defense-in-depth/SKILL.md) — `secret_role` caveat
|
|
308
|
+
- [`supabase-auth-ssr`](../supabase-auth-ssr/SKILL.md) — clients Next.js v16
|
|
309
|
+
- [`_shared-supabase/glossary.md`](../_shared-supabase/glossary.md) — termos canônicos auth
|