@luanpdd/kit-mcp 1.28.0 → 1.30.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 +82 -82
- package/kit/COMANDOS.md +138 -138
- package/kit/README.md +76 -76
- package/kit/agents/advisor-researcher.md +106 -106
- package/kit/agents/assumptions-analyzer.md +107 -107
- package/kit/agents/audit-log-implementer.md +313 -313
- package/kit/agents/auditor-consistencia-isolamento.md +413 -413
- package/kit/agents/b2b-saas-architect.md +156 -156
- package/kit/agents/cascading-failures-auditor.md +298 -298
- package/kit/agents/codebase-mapper.md +768 -768
- package/kit/agents/crm-pipeline-implementer.md +256 -256
- package/kit/agents/debugger.md +813 -813
- package/kit/agents/detector-tenant-quente.md +337 -337
- package/kit/agents/evolution-go-integrator.md +200 -200
- package/kit/agents/example-reviewer.md +21 -21
- package/kit/agents/executor.md +564 -564
- package/kit/agents/integration-checker.md +200 -200
- package/kit/agents/invite-flow-implementer.md +189 -189
- package/kit/agents/legacy-characterizer.md +368 -368
- package/kit/agents/lgpd-compliance-auditor.md +295 -295
- package/kit/agents/multi-tenant-isolation-auditor.md +253 -253
- package/kit/agents/multi-tenant-rls-writer.md +340 -340
- package/kit/agents/nyquist-auditor.md +178 -178
- package/kit/agents/observability-coverage-auditor.md +315 -315
- package/kit/agents/org-onboarding-implementer.md +223 -223
- package/kit/agents/payload-capture-instrumenter.md +273 -273
- package/kit/agents/phase-researcher.md +696 -696
- package/kit/agents/plan-checker.md +272 -272
- package/kit/agents/planner.md +922 -922
- package/kit/agents/project-researcher.md +652 -652
- package/kit/agents/refactor-safety-auditor.md +404 -404
- package/kit/agents/research-synthesizer.md +245 -245
- package/kit/agents/roadmapper.md +677 -677
- package/kit/agents/seam-finder.md +359 -359
- package/kit/agents/shotgun-surgery-detector.md +349 -349
- package/kit/agents/supabase-branching-architect.md +562 -562
- package/kit/agents/supabase-cicd-pipeline-implementer.md +777 -777
- package/kit/agents/supabase-column-privileges-writer.md +399 -399
- package/kit/agents/supabase-edge-fn-tester.md +287 -0
- package/kit/agents/supabase-edge-fn-writer.md +239 -210
- package/kit/agents/supabase-migration-writer.md +385 -385
- package/kit/agents/supabase-rbac-implementer.md +392 -392
- package/kit/agents/supabase-realtime-implementer.md +363 -267
- package/kit/agents/supabase-rls-hardener.md +521 -521
- package/kit/agents/supabase-rls-writer.md +323 -323
- package/kit/agents/supabase-roles-implementer.md +355 -355
- package/kit/agents/super-admin-implementer.md +281 -281
- package/kit/agents/ui-auditor.md +437 -437
- package/kit/agents/ui-checker.md +302 -302
- package/kit/agents/ui-researcher.md +355 -355
- package/kit/agents/user-profiler.md +175 -175
- package/kit/agents/validador-evolucao-schema.md +335 -335
- package/kit/agents/verifier.md +728 -728
- 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.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 +30 -7
- 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 +14 -8
- 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/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/_shared-supabase/glossary.md +17 -0
- 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-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 +229 -141
- package/kit/skills/supabase-edge-functions-auth/SKILL.md +309 -0
- package/kit/skills/supabase-edge-functions-limits/SKILL.md +302 -0
- package/kit/skills/supabase-edge-functions-mcp-server/SKILL.md +279 -0
- package/kit/skills/supabase-edge-functions-testing/SKILL.md +277 -0
- package/kit/skills/supabase-edge-runtime-builtins/SKILL.md +357 -0
- package/kit/skills/supabase-migration-repair/SKILL.md +823 -823
- package/kit/skills/supabase-migrations/SKILL.md +297 -297
- 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 -236
- 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/super-admin-platform-pattern/SKILL.md +326 -326
- package/kit/skills/tenant-quente-mitigacao/SKILL.md +605 -605
- package/kit/skills/whatsapp-conversation-state-machine/SKILL.md +287 -287
- package/package.json +1 -1
- package/src/cli/index.js +33 -0
- package/src/core/kit.js +216 -216
- package/src/core/reflect.js +247 -247
- package/src/core/reverse-sync.js +372 -372
- package/src/core/sync.js +418 -418
- package/src/core/watch.js +121 -121
- package/src/mcp-server/index.js +693 -490
- package/src/mcp-server/roots.js +124 -0
|
@@ -1,242 +1,330 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: supabase-edge-functions
|
|
3
|
-
description: Use ao escrever Edge Functions — Deno + imports npm:/jsr
|
|
3
|
+
description: Use ao escrever Edge Functions Supabase — Deno + imports versionados npm:/jsr:/node:, env vars 2026 (JSON dict SUPABASE_PUBLISHABLE_KEYS/SUPABASE_SECRET_KEYS), per-function deno.json, config.toml por função (verify_jwt, entrypoint, static_files), file writes APENAS em /tmp ou /s3/<bucket>, EdgeRuntime.waitUntil, CORS via @supabase/supabase-js/cors v2.95+.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Supabase — Edge Functions (Deno)
|
|
6
|
+
# Supabase — Edge Functions (Deno) · 2026
|
|
7
7
|
|
|
8
8
|
## Quando usar
|
|
9
9
|
|
|
10
|
-
LLM carrega esta skill quando criar, editar ou debugar Supabase Edge Functions
|
|
10
|
+
LLM carrega esta skill quando criar, editar ou debugar Supabase Edge Functions. Trigger phrases:
|
|
11
11
|
|
|
12
12
|
- "criar Edge Function", "Supabase functions"
|
|
13
|
-
- "Deno + Supabase"
|
|
14
|
-
- "
|
|
15
|
-
- "Edge Function
|
|
16
|
-
- "
|
|
13
|
+
- "Deno + Supabase", "supabase functions deploy/serve"
|
|
14
|
+
- "Edge Function background task", "EdgeRuntime.waitUntil"
|
|
15
|
+
- "import npm: jsr: node: em Edge Function"
|
|
16
|
+
- "deno.json per function", "config.toml functions"
|
|
17
|
+
|
|
18
|
+
> **Cross-refs canônicos v1.30:**
|
|
19
|
+
> - Auth modes / `@supabase/server` → [`supabase-edge-functions-auth`](../supabase-edge-functions-auth/SKILL.md)
|
|
20
|
+
> - Tests / Chrome DevTools debug → [`supabase-edge-functions-testing`](../supabase-edge-functions-testing/SKILL.md)
|
|
21
|
+
> - `Supabase.ai.Session`, /s3, WebSockets, Wasm, regional → [`supabase-edge-runtime-builtins`](../supabase-edge-runtime-builtins/SKILL.md)
|
|
22
|
+
> - Limits / status codes / `RateLimitError` → [`supabase-edge-functions-limits`](../supabase-edge-functions-limits/SKILL.md)
|
|
23
|
+
> - MCP server pattern (mcp-lite) → [`supabase-edge-functions-mcp-server`](../supabase-edge-functions-mcp-server/SKILL.md)
|
|
24
|
+
> - Glossário CLI → [`_shared-supabase/glossary.md`](../_shared-supabase/glossary.md)
|
|
17
25
|
|
|
18
26
|
## Regras absolutas
|
|
19
27
|
|
|
20
28
|
- **Runtime é Deno**, não Node.js. Use APIs Deno (`Deno.serve`, `Deno.env`, `Deno.writeTextFile`).
|
|
21
|
-
- **Imports SEMPRE com `npm:` ou `
|
|
22
|
-
- **
|
|
23
|
-
- **Env vars pre-populadas
|
|
29
|
+
- **Imports SEMPRE com `npm:`, `jsr:` ou `node:`** prefix. **NUNCA** bare specifiers — falha em runtime.
|
|
30
|
+
- **Versão pinada obrigatória** — `npm:hono@4.6.14`, `npm:@supabase/supabase-js@2.95.0`. Sem version, latest pode quebrar deploy.
|
|
31
|
+
- **Env vars 2026 (JSON dict)** — pre-populadas no runtime hospedado:
|
|
24
32
|
- `SUPABASE_URL`
|
|
25
|
-
- `SUPABASE_PUBLISHABLE_KEYS`
|
|
26
|
-
- `SUPABASE_SECRET_KEYS` (service role
|
|
27
|
-
- `SUPABASE_DB_URL`
|
|
28
|
-
-
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
32
|
-
-
|
|
33
|
+
- `SUPABASE_PUBLISHABLE_KEYS` — **JSON dict**. `JSON.parse(...)['default']` para chave anon padrão.
|
|
34
|
+
- `SUPABASE_SECRET_KEYS` — **JSON dict** (service role). Idem. Server-side only.
|
|
35
|
+
- `SUPABASE_DB_URL` — Postgres direto.
|
|
36
|
+
- `SUPABASE_JWKS` — JWK Set para verificar JWTs.
|
|
37
|
+
- `SB_REGION`, `SB_EXECUTION_ID`, `DENO_DEPLOYMENT_ID` — runtime metadata.
|
|
38
|
+
- Legacy (ainda funcionam, evitar em código novo): `SUPABASE_ANON_KEY`, `SUPABASE_SERVICE_ROLE_KEY`.
|
|
39
|
+
- **Outros secrets:** `supabase secrets set --env-file path/to/.env` (max 100, 48 KiB cada, nome NÃO pode começar com `SUPABASE_`).
|
|
40
|
+
- **`Deno.serve`** é o entry point canônico. **Nunca** `addEventListener('fetch')` (deprecated) ou `serve` legado de `deno.land/std`.
|
|
41
|
+
- **File writes:** APENAS `/tmp` (ephemeral) ou `/s3/<bucket-name>/...` (persistent S3FS — ver [`supabase-edge-runtime-builtins`](../supabase-edge-runtime-builtins/SKILL.md)). Qualquer outro path é read-only.
|
|
42
|
+
- **Background work:** `EdgeRuntime.waitUntil(promise)`. Sem isso, função termina antes da promise.
|
|
43
|
+
- **Multi-rota:** prefixar todas as rotas com `/<function-name>` (Hono `basePath('/api')`). Sem prefix, request 404 em produção.
|
|
44
|
+
- **CORS (v2.95.0+):** importar `corsHeaders` direto do SDK — `import { corsHeaders } from 'npm:@supabase/supabase-js@2.95.0/cors'`. Mantém-se sincronizado com novos headers do SDK automaticamente.
|
|
33
45
|
|
|
34
46
|
## Patterns canônicos
|
|
35
47
|
|
|
36
|
-
### Função básica
|
|
48
|
+
### Pattern 1 — Função básica com env vars 2026
|
|
37
49
|
|
|
38
50
|
```ts
|
|
39
51
|
// supabase/functions/hello/index.ts
|
|
40
|
-
// PT-BR: imports versionados
|
|
41
|
-
import { createClient } from 'npm:@supabase/supabase-js@2'
|
|
52
|
+
// PT-BR: imports versionados + JSON dict de secret keys
|
|
53
|
+
import { createClient } from 'npm:@supabase/supabase-js@2.95.0'
|
|
42
54
|
|
|
43
|
-
Deno.
|
|
44
|
-
const supabase = createClient(
|
|
45
|
-
Deno.env.get('SUPABASE_URL')!,
|
|
46
|
-
Deno.env.get('SUPABASE_SECRET_KEYS')! // service role server-side
|
|
47
|
-
)
|
|
55
|
+
const SUPABASE_SECRET_KEYS = JSON.parse(Deno.env.get('SUPABASE_SECRET_KEYS')!)
|
|
48
56
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
57
|
+
const supabase = createClient(
|
|
58
|
+
Deno.env.get('SUPABASE_URL')!,
|
|
59
|
+
// PT-BR: 'default' é a chave canônica; multi-key permite scoping (ex: 'automations')
|
|
60
|
+
SUPABASE_SECRET_KEYS['default'],
|
|
61
|
+
)
|
|
53
62
|
|
|
63
|
+
Deno.serve(async (req) => {
|
|
64
|
+
const { data, error } = await supabase.from('tasks').select('id, title').limit(10)
|
|
54
65
|
if (error) {
|
|
55
66
|
return new Response(JSON.stringify({ error: error.message }), {
|
|
56
67
|
status: 500,
|
|
57
68
|
headers: { 'Content-Type': 'application/json' },
|
|
58
69
|
})
|
|
59
70
|
}
|
|
60
|
-
|
|
61
|
-
return new Response(JSON.stringify(data), {
|
|
62
|
-
headers: { 'Content-Type': 'application/json' },
|
|
63
|
-
})
|
|
71
|
+
return Response.json(data)
|
|
64
72
|
})
|
|
65
73
|
```
|
|
66
74
|
|
|
67
|
-
###
|
|
75
|
+
### Pattern 2 — CORS canônico (v2.95+)
|
|
68
76
|
|
|
69
77
|
```ts
|
|
70
|
-
//
|
|
71
|
-
|
|
78
|
+
// PT-BR: import corsHeaders do SDK — auto-sync com novos headers em releases futuras
|
|
79
|
+
import { corsHeaders } from 'npm:@supabase/supabase-js@2.95.0/cors'
|
|
72
80
|
|
|
73
81
|
Deno.serve(async (req) => {
|
|
74
|
-
|
|
82
|
+
if (req.method === 'OPTIONS') return new Response('ok', { headers: corsHeaders })
|
|
75
83
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
`/tmp/audit-${Date.now()}.log`,
|
|
81
|
-
JSON.stringify(body)
|
|
82
|
-
)
|
|
83
|
-
// PT-BR: pode chamar APIs externas, gerar embeddings, etc.
|
|
84
|
-
await fetch('https://example.com/audit', {
|
|
85
|
-
method: 'POST',
|
|
86
|
-
body: JSON.stringify(body),
|
|
84
|
+
try {
|
|
85
|
+
const { name } = await req.json()
|
|
86
|
+
return new Response(JSON.stringify({ message: `Hello ${name}!` }), {
|
|
87
|
+
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
|
|
87
88
|
})
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
89
|
+
} catch (error) {
|
|
90
|
+
return new Response(JSON.stringify({ error: error.message }), {
|
|
91
|
+
status: 400,
|
|
92
|
+
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
|
|
93
|
+
})
|
|
94
|
+
}
|
|
92
95
|
})
|
|
93
96
|
```
|
|
94
97
|
|
|
95
|
-
###
|
|
98
|
+
### Pattern 3 — Background task com `waitUntil` + `beforeunload`
|
|
96
99
|
|
|
97
100
|
```ts
|
|
98
|
-
|
|
99
|
-
// PT-BR:
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const app = new Hono().basePath('/api')
|
|
101
|
+
addEventListener('beforeunload', (ev) => {
|
|
102
|
+
// PT-BR: log antes do isolate desligar — registra qual deadline foi atingido
|
|
103
|
+
console.log('Function will shutdown:', (ev as CustomEvent).detail?.reason)
|
|
104
|
+
})
|
|
103
105
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
const body = await c.req.json()
|
|
108
|
-
return c.json({ created: body }, 201)
|
|
106
|
+
addEventListener('unhandledrejection', (ev) => {
|
|
107
|
+
console.log('unhandledrejection', (ev as PromiseRejectionEvent).reason)
|
|
108
|
+
ev.preventDefault()
|
|
109
109
|
})
|
|
110
110
|
|
|
111
|
-
Deno.serve(
|
|
111
|
+
Deno.serve(async (req) => {
|
|
112
|
+
const body = await req.json()
|
|
113
|
+
EdgeRuntime.waitUntil((async () => {
|
|
114
|
+
try {
|
|
115
|
+
await Deno.writeTextFile(`/tmp/audit-${Date.now()}.log`, JSON.stringify(body))
|
|
116
|
+
await fetch('https://example.com/audit', { method: 'POST', body: JSON.stringify(body) })
|
|
117
|
+
} catch (err) {
|
|
118
|
+
console.error('background task failed', err)
|
|
119
|
+
}
|
|
120
|
+
})())
|
|
121
|
+
return new Response('accepted', { status: 202 })
|
|
122
|
+
})
|
|
112
123
|
```
|
|
113
124
|
|
|
114
|
-
###
|
|
125
|
+
### Pattern 4 — Per-function `deno.json` (recomendado 2026)
|
|
115
126
|
|
|
116
|
-
|
|
117
|
-
// supabase/functions/hash/index.ts
|
|
118
|
-
// PT-BR: imports do JSR + Node built-in (precisa node: prefix)
|
|
119
|
-
import { encodeHex } from 'jsr:@std/encoding/hex'
|
|
120
|
-
import { createHash } from 'node:crypto'
|
|
127
|
+
Cada função tem seu próprio `deno.json` para isolamento de dependências:
|
|
121
128
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
+
```
|
|
130
|
+
supabase/functions/
|
|
131
|
+
├── orders/
|
|
132
|
+
│ ├── index.ts
|
|
133
|
+
│ └── deno.json # PT-BR: dependencies isoladas por função
|
|
134
|
+
├── shipments/
|
|
135
|
+
│ ├── index.ts
|
|
136
|
+
│ └── deno.json
|
|
137
|
+
└── _shared/
|
|
138
|
+
├── cors.ts # legacy — preferir 'npm:@supabase/supabase-js/cors'
|
|
139
|
+
└── supabase-admin.ts
|
|
129
140
|
```
|
|
130
141
|
|
|
131
|
-
|
|
142
|
+
```json
|
|
143
|
+
// supabase/functions/orders/deno.json
|
|
144
|
+
{
|
|
145
|
+
"imports": {
|
|
146
|
+
"hono": "npm:hono@4.6.14",
|
|
147
|
+
"supabase": "npm:@supabase/supabase-js@2.95.0",
|
|
148
|
+
"zod": "npm:zod@3.23.8"
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
```
|
|
132
152
|
|
|
133
|
-
|
|
134
|
-
// supabase/functions/admin-action/index.ts
|
|
135
|
-
// PT-BR: service-role bypassa RLS — apenas server-side
|
|
136
|
-
import { createClient } from 'npm:@supabase/supabase-js@2'
|
|
153
|
+
Após criar `deno.json`, imports usam alias direto: `import { Hono } from 'hono'`. **Não use `import_map.json` global** — é legacy; prefira per-function. CLI 1.207.9+.
|
|
137
154
|
|
|
138
|
-
|
|
139
|
-
// PT-BR: extrair JWT do header Authorization e validar
|
|
140
|
-
const authHeader = req.headers.get('Authorization')
|
|
141
|
-
if (!authHeader?.startsWith('Bearer ')) {
|
|
142
|
-
return new Response('unauthorized', { status: 401 })
|
|
143
|
-
}
|
|
155
|
+
### Pattern 5 — Per-function `config.toml`
|
|
144
156
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
)
|
|
157
|
+
```toml
|
|
158
|
+
# supabase/config.toml
|
|
159
|
+
[functions.stripe-webhook]
|
|
160
|
+
verify_jwt = false # webhook externo: signature-based
|
|
150
161
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
authHeader.replace('Bearer ', '')
|
|
154
|
-
)
|
|
155
|
-
if (!user || error) return new Response('unauthorized', { status: 401 })
|
|
162
|
+
[functions.image-processor]
|
|
163
|
+
import_map = "./functions/image-processor/import_map.json" # apenas se ainda em import_map legacy
|
|
156
164
|
|
|
157
|
-
|
|
158
|
-
|
|
165
|
+
[functions.legacy-js]
|
|
166
|
+
entrypoint = "./functions/legacy-js/index.js" # JS puro (CLI 1.215.0+)
|
|
159
167
|
|
|
160
|
-
|
|
161
|
-
|
|
168
|
+
[functions.wasm-add]
|
|
169
|
+
static_files = ["./functions/wasm-add/add-wasm/pkg/*"] # bundle Wasm com a função (CLI 2.7.0+)
|
|
170
|
+
|
|
171
|
+
[edge_runtime]
|
|
172
|
+
policy = "per_worker" # mantém isolate alive — required p/ WebSocket + background task local
|
|
173
|
+
deno_version = 2
|
|
162
174
|
```
|
|
163
175
|
|
|
164
|
-
|
|
176
|
+
`policy = "per_worker"` é OBRIGATÓRIO para testar localmente **background tasks** e **WebSockets** — caso contrário o isolate é terminado após request. Caveat: hot-reload é desativado; restart manual via `supabase functions serve`.
|
|
165
177
|
|
|
166
|
-
###
|
|
178
|
+
### Pattern 6 — Imports JSR + Node built-in
|
|
167
179
|
|
|
168
|
-
**Errado:**
|
|
169
180
|
```ts
|
|
170
|
-
import {
|
|
181
|
+
import { encodeHex } from 'jsr:@std/encoding@1.0.8/hex'
|
|
182
|
+
import { createHash } from 'node:crypto' // PT-BR: node: prefix obrigatório
|
|
183
|
+
import process from 'node:process'
|
|
171
184
|
```
|
|
172
185
|
|
|
173
|
-
|
|
186
|
+
### Pattern 7 — Custom NPM registry / private packages
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
# Custom registry corporativa
|
|
190
|
+
NPM_CONFIG_REGISTRY=https://npm.corp.com/ supabase functions deploy my-fn
|
|
191
|
+
|
|
192
|
+
# Private package via .npmrc (per-function)
|
|
193
|
+
# supabase/functions/my-fn/.npmrc
|
|
194
|
+
@myorg:registry=https://npm.registryhost.com
|
|
195
|
+
//npm.registryhost.com/:_authToken=VALID_AUTH_TOKEN
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
```ts
|
|
199
|
+
import pkg from 'npm:@myorg/private-package@1.0.1'
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
CLI 1.207.9+ para `.npmrc` per-function; CLI 2.2.8+ para `NPM_CONFIG_REGISTRY`.
|
|
203
|
+
|
|
204
|
+
## Anti-patterns
|
|
205
|
+
|
|
206
|
+
### A1 — Bare specifier
|
|
174
207
|
|
|
175
|
-
**Certo:**
|
|
176
208
|
```ts
|
|
177
|
-
|
|
209
|
+
// ⚠ Errado — Module not found
|
|
210
|
+
import { createClient } from '@supabase/supabase-js'
|
|
211
|
+
// ✓ Certo
|
|
212
|
+
import { createClient } from 'npm:@supabase/supabase-js@2.95.0'
|
|
178
213
|
```
|
|
179
214
|
|
|
180
|
-
###
|
|
215
|
+
### A2 — Tratar `SUPABASE_SECRET_KEYS` como string (regressão 2025 → 2026)
|
|
181
216
|
|
|
182
|
-
**Errado:**
|
|
183
217
|
```ts
|
|
184
|
-
|
|
185
|
-
|
|
218
|
+
// ⚠ Errado — em 2026 é JSON dict; passar como string quebra createClient
|
|
219
|
+
const supabase = createClient(URL, Deno.env.get('SUPABASE_SECRET_KEYS')!)
|
|
220
|
+
|
|
221
|
+
// ✓ Certo
|
|
222
|
+
const SECRET_KEYS = JSON.parse(Deno.env.get('SUPABASE_SECRET_KEYS')!)
|
|
223
|
+
const supabase = createClient(URL, SECRET_KEYS['default'])
|
|
186
224
|
```
|
|
187
225
|
|
|
188
|
-
|
|
226
|
+
### A3 — `Deno.writeTextFile` fora de `/tmp` ou `/s3/<bucket>`
|
|
189
227
|
|
|
190
|
-
**Certo:**
|
|
191
228
|
```ts
|
|
229
|
+
await Deno.writeTextFile('/data/audit.log', data) // ⚠ EACCES — read-only
|
|
230
|
+
await Deno.writeTextFile('./local/x.log', data) // ⚠ idem
|
|
231
|
+
// ✓
|
|
192
232
|
await Deno.writeTextFile(`/tmp/audit-${Date.now()}.log`, data)
|
|
233
|
+
await Deno.writeTextFile(`/s3/my-bucket/audit.log`, data) // S3FS_* env vars necessários
|
|
193
234
|
```
|
|
194
235
|
|
|
195
|
-
###
|
|
236
|
+
### A4 — Trabalho pesado inline (cliente espera)
|
|
196
237
|
|
|
197
|
-
**Errado:**
|
|
198
238
|
```ts
|
|
239
|
+
// ⚠ Errado — bloqueia response até 30s+; client timeout
|
|
199
240
|
Deno.serve(async (req) => {
|
|
200
|
-
|
|
201
|
-
await processHeavyJob(body) // ⚠ trava response 30s+
|
|
202
|
-
await sendEmail(body) // ⚠ idem
|
|
241
|
+
await processHeavyJob(await req.json())
|
|
203
242
|
return new Response('done')
|
|
204
243
|
})
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
**Por quê:** cliente espera resposta. Edge Functions têm timeout (default 60s). Falhas pontuais quebram UX.
|
|
208
244
|
|
|
209
|
-
|
|
210
|
-
```ts
|
|
245
|
+
// ✓ Certo — waitUntil libera response
|
|
211
246
|
Deno.serve(async (req) => {
|
|
212
247
|
const body = await req.json()
|
|
213
|
-
EdgeRuntime.waitUntil((
|
|
214
|
-
await processHeavyJob(body)
|
|
215
|
-
await sendEmail(body)
|
|
216
|
-
})())
|
|
248
|
+
EdgeRuntime.waitUntil(processHeavyJob(body))
|
|
217
249
|
return new Response('accepted', { status: 202 })
|
|
218
250
|
})
|
|
219
251
|
```
|
|
220
252
|
|
|
221
|
-
###
|
|
253
|
+
### A5 — Multi-rota sem `basePath`
|
|
222
254
|
|
|
223
|
-
**Errado:**
|
|
224
255
|
```ts
|
|
225
|
-
const app = new Hono() // ⚠
|
|
256
|
+
const app = new Hono() // ⚠ /users em produção = 404
|
|
226
257
|
app.get('/users', handler)
|
|
227
|
-
|
|
258
|
+
// ✓ basePath com o nome canônico da função
|
|
259
|
+
const app = new Hono().basePath('/api')
|
|
228
260
|
```
|
|
229
261
|
|
|
230
|
-
|
|
262
|
+
### A6 — Import map global em `supabase/functions/import_map.json`
|
|
263
|
+
|
|
264
|
+
Legacy, ainda suportado mas **não recomendado**. Cada update em uma função pode quebrar outras (deps acopladas). Prefira `deno.json` per-function.
|
|
265
|
+
|
|
266
|
+
### A7 — Custom CORS string hard-coded
|
|
231
267
|
|
|
232
|
-
**Certo:**
|
|
233
268
|
```ts
|
|
234
|
-
|
|
269
|
+
// ⚠ Errado — desatualiza quando SDK adiciona novos headers (drift silencioso)
|
|
270
|
+
const corsHeaders = { 'Access-Control-Allow-Headers': 'authorization, apikey, content-type' }
|
|
271
|
+
|
|
272
|
+
// ✓ Certo (v2.95.0+) — import sincronizado com releases
|
|
273
|
+
import { corsHeaders } from 'npm:@supabase/supabase-js@2.95.0/cors'
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### A8 — Confundir `Authorization` (JWT) vs `apikey` (API key)
|
|
277
|
+
|
|
278
|
+
`Authorization: Bearer <user-jwt>` — JWT do usuário Supabase Auth.
|
|
279
|
+
`apikey: sb_publishable_... | sb_secret_...` — API key do projeto.
|
|
280
|
+
|
|
281
|
+
Enviar `sb_publishable_*` como Bearer = 401. Ver [`supabase-edge-functions-auth`](../supabase-edge-functions-auth/SKILL.md).
|
|
282
|
+
|
|
283
|
+
## Estrutura recomendada
|
|
284
|
+
|
|
285
|
+
```
|
|
286
|
+
supabase/
|
|
287
|
+
├── config.toml
|
|
288
|
+
└── functions/
|
|
289
|
+
├── _shared/ # shared (underscore prefix evita deploy)
|
|
290
|
+
│ ├── supabase-admin.ts
|
|
291
|
+
│ └── supabase-client.ts
|
|
292
|
+
├── orders/
|
|
293
|
+
│ ├── index.ts
|
|
294
|
+
│ ├── deno.json # per-function (2026)
|
|
295
|
+
│ └── .npmrc # opcional — private NPM
|
|
296
|
+
└── tests/
|
|
297
|
+
├── orders-test.ts
|
|
298
|
+
└── shipments-test.ts
|
|
235
299
|
```
|
|
236
300
|
|
|
301
|
+
Diretrizes:
|
|
302
|
+
- **"Fat functions":** combine endpoints relacionados em uma função (reduz cold start). Multi-rota com Hono/Oak/Express.
|
|
303
|
+
- **Hyphens em nomes:** URL-friendly.
|
|
304
|
+
- **`_shared/` underscore:** não é deployado, importado relativamente.
|
|
305
|
+
- **`tests/` separado:** sufixo `-test.ts`. Ver [`supabase-edge-functions-testing`](../supabase-edge-functions-testing/SKILL.md).
|
|
306
|
+
|
|
307
|
+
## Limits & quotas (resumo — detalhe em [`supabase-edge-functions-limits`](../supabase-edge-functions-limits/SKILL.md))
|
|
308
|
+
|
|
309
|
+
| Recurso | Free | Pro/Team |
|
|
310
|
+
|---|---|---|
|
|
311
|
+
| Memory | 256 MB | 256 MB |
|
|
312
|
+
| CPU (per request) | 2s | 2s |
|
|
313
|
+
| Wall clock (isolate lifetime) | 150s | 400s |
|
|
314
|
+
| Request idle timeout | 150s | 150s |
|
|
315
|
+
| Max function size (bundled) | 20 MB | 20 MB |
|
|
316
|
+
| Max functions/project | 100 | 500 / 1000 |
|
|
317
|
+
| Nested function calls | ~5000/min/chain | ~5000/min/chain |
|
|
318
|
+
|
|
319
|
+
Outgoing ports `25` e `587` bloqueados (use Resend/SendGrid HTTP API).
|
|
320
|
+
|
|
237
321
|
## Ver também
|
|
238
322
|
|
|
239
|
-
- [supabase-auth
|
|
240
|
-
- [supabase-
|
|
241
|
-
- [supabase-
|
|
242
|
-
- [
|
|
323
|
+
- [`supabase-edge-functions-auth`](../supabase-edge-functions-auth/SKILL.md) — `@supabase/server`, withSupabase, 4 auth modes, verify_jwt
|
|
324
|
+
- [`supabase-edge-functions-testing`](../supabase-edge-functions-testing/SKILL.md) — Deno test, supabase functions serve, Chrome DevTools
|
|
325
|
+
- [`supabase-edge-runtime-builtins`](../supabase-edge-runtime-builtins/SKILL.md) — `Supabase.ai.Session`, /s3 persistent, WebSockets, Wasm, regional
|
|
326
|
+
- [`supabase-edge-functions-limits`](../supabase-edge-functions-limits/SKILL.md) — limits, status codes, RateLimitError
|
|
327
|
+
- [`supabase-edge-functions-mcp-server`](../supabase-edge-functions-mcp-server/SKILL.md) — mcp-lite pattern
|
|
328
|
+
- [`supabase-cron-queues`](../supabase-cron-queues/SKILL.md) — pattern `cron → pgmq → Edge Function`
|
|
329
|
+
- [`supabase-auth-ssr`](../supabase-auth-ssr/SKILL.md) — clients SSR
|
|
330
|
+
- [`_shared-supabase/glossary.md`](../_shared-supabase/glossary.md) — CLI + termos canônicos
|