@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.
Files changed (332) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +168 -168
  3. package/gates/agent-no-recursive-dispatch.md +82 -82
  4. package/kit/COMANDOS.md +138 -138
  5. package/kit/README.md +76 -76
  6. package/kit/agents/advisor-researcher.md +106 -106
  7. package/kit/agents/assumptions-analyzer.md +107 -107
  8. package/kit/agents/audit-log-implementer.md +313 -313
  9. package/kit/agents/auditor-consistencia-isolamento.md +413 -413
  10. package/kit/agents/b2b-saas-architect.md +156 -156
  11. package/kit/agents/cascading-failures-auditor.md +298 -298
  12. package/kit/agents/codebase-mapper.md +768 -768
  13. package/kit/agents/crm-pipeline-implementer.md +256 -256
  14. package/kit/agents/debugger.md +813 -813
  15. package/kit/agents/detector-tenant-quente.md +337 -337
  16. package/kit/agents/evolution-go-integrator.md +200 -200
  17. package/kit/agents/example-reviewer.md +21 -21
  18. package/kit/agents/executor.md +564 -564
  19. package/kit/agents/integration-checker.md +200 -200
  20. package/kit/agents/invite-flow-implementer.md +189 -189
  21. package/kit/agents/legacy-characterizer.md +368 -368
  22. package/kit/agents/lgpd-compliance-auditor.md +295 -295
  23. package/kit/agents/multi-tenant-isolation-auditor.md +253 -253
  24. package/kit/agents/multi-tenant-rls-writer.md +340 -340
  25. package/kit/agents/nyquist-auditor.md +178 -178
  26. package/kit/agents/observability-coverage-auditor.md +315 -315
  27. package/kit/agents/org-onboarding-implementer.md +223 -223
  28. package/kit/agents/payload-capture-instrumenter.md +273 -273
  29. package/kit/agents/phase-researcher.md +696 -696
  30. package/kit/agents/plan-checker.md +272 -272
  31. package/kit/agents/planner.md +922 -922
  32. package/kit/agents/project-researcher.md +652 -652
  33. package/kit/agents/refactor-safety-auditor.md +404 -404
  34. package/kit/agents/research-synthesizer.md +245 -245
  35. package/kit/agents/roadmapper.md +677 -677
  36. package/kit/agents/seam-finder.md +359 -359
  37. package/kit/agents/shotgun-surgery-detector.md +349 -349
  38. package/kit/agents/supabase-branching-architect.md +562 -562
  39. package/kit/agents/supabase-cicd-pipeline-implementer.md +777 -777
  40. package/kit/agents/supabase-column-privileges-writer.md +399 -399
  41. package/kit/agents/supabase-edge-fn-tester.md +287 -0
  42. package/kit/agents/supabase-edge-fn-writer.md +239 -210
  43. package/kit/agents/supabase-migration-writer.md +385 -385
  44. package/kit/agents/supabase-rbac-implementer.md +392 -392
  45. package/kit/agents/supabase-realtime-implementer.md +363 -267
  46. package/kit/agents/supabase-rls-hardener.md +521 -521
  47. package/kit/agents/supabase-rls-writer.md +323 -323
  48. package/kit/agents/supabase-roles-implementer.md +355 -355
  49. package/kit/agents/super-admin-implementer.md +281 -281
  50. package/kit/agents/ui-auditor.md +437 -437
  51. package/kit/agents/ui-checker.md +302 -302
  52. package/kit/agents/ui-researcher.md +355 -355
  53. package/kit/agents/user-profiler.md +175 -175
  54. package/kit/agents/validador-evolucao-schema.md +335 -335
  55. package/kit/agents/verifier.md +728 -728
  56. package/kit/commands/adicionar-backlog.md +75 -75
  57. package/kit/commands/adicionar-fase.md +42 -42
  58. package/kit/commands/adicionar-tarefa.md +45 -45
  59. package/kit/commands/adicionar-testes.md +41 -41
  60. package/kit/commands/ajuda.md +21 -21
  61. package/kit/commands/atualizar.md +37 -37
  62. package/kit/commands/auditar-cascading.md +111 -111
  63. package/kit/commands/auditar-marco.md +179 -179
  64. package/kit/commands/auditar-observabilidade-cobertura.md +183 -183
  65. package/kit/commands/auditar-refactor.md +219 -219
  66. package/kit/commands/auditar-release.md +109 -109
  67. package/kit/commands/auditar-uat.md +23 -23
  68. package/kit/commands/autonomo.md +40 -40
  69. package/kit/commands/branch-pr.md +24 -24
  70. package/kit/commands/burn-rate-status.md +408 -408
  71. package/kit/commands/capturar-payloads.md +193 -193
  72. package/kit/commands/caracterizar.md +212 -212
  73. package/kit/commands/concluir-marco.md +247 -247
  74. package/kit/commands/configuracoes.md +36 -36
  75. package/kit/commands/dados-distribuidos.md +188 -188
  76. package/kit/commands/definir-perfil.md +10 -10
  77. package/kit/commands/depurar.md +190 -190
  78. package/kit/commands/detectar-duplicacao.md +197 -197
  79. package/kit/commands/discutir-fase.md +131 -131
  80. package/kit/commands/encontrar-seams.md +136 -136
  81. package/kit/commands/entrar-discord.md +17 -17
  82. package/kit/commands/estatisticas.md +18 -18
  83. package/kit/commands/example-greeting.md +33 -33
  84. package/kit/commands/executar-fase.md +58 -58
  85. package/kit/commands/expresso.md +56 -56
  86. package/kit/commands/fase-ui.md +34 -34
  87. package/kit/commands/fazer.md +57 -57
  88. package/kit/commands/fio.md +125 -125
  89. package/kit/commands/fluxos-trabalho.md +64 -64
  90. package/kit/commands/forense.md +176 -176
  91. package/kit/commands/gerenciador.md +38 -38
  92. package/kit/commands/inserir-fase.md +31 -31
  93. package/kit/commands/legacy.md +263 -263
  94. package/kit/commands/limpeza.md +17 -17
  95. package/kit/commands/listar-hipoteses-fase.md +45 -45
  96. package/kit/commands/listar-workspaces.md +18 -18
  97. package/kit/commands/load-shedding.md +117 -117
  98. package/kit/commands/mapear-codebase.md +70 -70
  99. package/kit/commands/multi-tenant.md +163 -163
  100. package/kit/commands/nota.md +33 -33
  101. package/kit/commands/novo-marco.md +43 -43
  102. package/kit/commands/novo-projeto.md +41 -41
  103. package/kit/commands/novo-workspace.md +43 -43
  104. package/kit/commands/pausar-trabalho.md +37 -37
  105. package/kit/commands/perfil-usuario.md +45 -45
  106. package/kit/commands/pesquisar-fase.md +195 -195
  107. package/kit/commands/planejar-fase.md +67 -67
  108. package/kit/commands/planejar-lacunas.md +33 -33
  109. package/kit/commands/plantar-ideia.md +25 -25
  110. package/kit/commands/progresso.md +24 -24
  111. package/kit/commands/proximo.md +30 -30
  112. package/kit/commands/publicar.md +490 -490
  113. package/kit/commands/rapido.md +35 -35
  114. package/kit/commands/reaplicar-patches.md +124 -124
  115. package/kit/commands/refactor-seguro.md +321 -321
  116. package/kit/commands/relatorio-sessao.md +19 -19
  117. package/kit/commands/remover-fase.md +31 -31
  118. package/kit/commands/remover-workspace.md +26 -26
  119. package/kit/commands/resumo-marco.md +50 -50
  120. package/kit/commands/retomar-trabalho.md +40 -40
  121. package/kit/commands/revisar-backlog.md +60 -60
  122. package/kit/commands/revisar-ui.md +32 -32
  123. package/kit/commands/revisar.md +37 -37
  124. package/kit/commands/saude.md +21 -21
  125. package/kit/commands/setup-notion.md +93 -93
  126. package/kit/commands/storytelling.md +179 -179
  127. package/kit/commands/supabase.md +30 -7
  128. package/kit/commands/sync-main.md +68 -68
  129. package/kit/commands/validar-fase.md +35 -35
  130. package/kit/commands/verificar-tarefas.md +44 -44
  131. package/kit/commands/verificar-trabalho.md +64 -64
  132. package/kit/file-manifest.json +14 -8
  133. package/kit/framework/bin/lib/commands.cjs +959 -959
  134. package/kit/framework/bin/lib/config.cjs +442 -442
  135. package/kit/framework/bin/lib/core.cjs +1230 -1230
  136. package/kit/framework/bin/lib/frontmatter.cjs +336 -336
  137. package/kit/framework/bin/lib/init.cjs +1442 -1442
  138. package/kit/framework/bin/lib/milestone.cjs +252 -252
  139. package/kit/framework/bin/lib/model-profiles.cjs +68 -68
  140. package/kit/framework/bin/lib/phase.cjs +888 -888
  141. package/kit/framework/bin/lib/profile-output.cjs +952 -952
  142. package/kit/framework/bin/lib/profile-pipeline.cjs +539 -539
  143. package/kit/framework/bin/lib/roadmap.cjs +329 -329
  144. package/kit/framework/bin/lib/security.cjs +382 -382
  145. package/kit/framework/bin/lib/state.cjs +1031 -1031
  146. package/kit/framework/bin/lib/template.cjs +222 -222
  147. package/kit/framework/bin/lib/uat.cjs +282 -282
  148. package/kit/framework/bin/lib/verify.cjs +888 -888
  149. package/kit/framework/bin/lib/workstream.cjs +491 -491
  150. package/kit/framework/bin/tools.cjs +918 -918
  151. package/kit/framework/commands/workstreams.md +63 -63
  152. package/kit/framework/references/checkpoints.md +778 -778
  153. package/kit/framework/references/continuation-format.md +249 -249
  154. package/kit/framework/references/decimal-phase-calculation.md +64 -64
  155. package/kit/framework/references/git-integration.md +295 -295
  156. package/kit/framework/references/git-planning-commit.md +38 -38
  157. package/kit/framework/references/model-profile-resolution.md +36 -36
  158. package/kit/framework/references/model-profiles.md +139 -139
  159. package/kit/framework/references/phase-argument-parsing.md +61 -61
  160. package/kit/framework/references/planning-config.md +202 -202
  161. package/kit/framework/references/questioning.md +162 -162
  162. package/kit/framework/references/tdd.md +263 -263
  163. package/kit/framework/references/ui-brand.md +160 -160
  164. package/kit/framework/references/user-profiling.md +657 -657
  165. package/kit/framework/references/verification-patterns.md +612 -612
  166. package/kit/framework/references/workstream-flag.md +58 -58
  167. package/kit/framework/templates/DEBUG.md +164 -164
  168. package/kit/framework/templates/UAT.md +265 -265
  169. package/kit/framework/templates/UI-SPEC.md +100 -100
  170. package/kit/framework/templates/VALIDATION.md +76 -76
  171. package/kit/framework/templates/claude-md.md +122 -122
  172. package/kit/framework/templates/codebase/architecture.md +185 -185
  173. package/kit/framework/templates/codebase/concerns.md +205 -205
  174. package/kit/framework/templates/codebase/conventions.md +204 -204
  175. package/kit/framework/templates/codebase/integrations.md +192 -192
  176. package/kit/framework/templates/codebase/stack.md +158 -158
  177. package/kit/framework/templates/codebase/structure.md +199 -199
  178. package/kit/framework/templates/codebase/testing.md +301 -301
  179. package/kit/framework/templates/config.json +44 -44
  180. package/kit/framework/templates/context.md +352 -352
  181. package/kit/framework/templates/continue-here.md +78 -78
  182. package/kit/framework/templates/copilot-instructions.md +7 -7
  183. package/kit/framework/templates/debug-subagent-prompt.md +91 -91
  184. package/kit/framework/templates/dev-preferences.md +20 -20
  185. package/kit/framework/templates/discovery.md +146 -146
  186. package/kit/framework/templates/discussion-log.md +63 -63
  187. package/kit/framework/templates/milestone-archive.md +123 -123
  188. package/kit/framework/templates/milestone.md +115 -115
  189. package/kit/framework/templates/phase-prompt.md +610 -610
  190. package/kit/framework/templates/planner-subagent-prompt.md +117 -117
  191. package/kit/framework/templates/project.md +186 -186
  192. package/kit/framework/templates/requirements.md +231 -231
  193. package/kit/framework/templates/research-project/ARCHITECTURE.md +204 -204
  194. package/kit/framework/templates/research-project/FEATURES.md +147 -147
  195. package/kit/framework/templates/research-project/PITFALLS.md +200 -200
  196. package/kit/framework/templates/research-project/STACK.md +120 -120
  197. package/kit/framework/templates/research-project/SUMMARY.md +170 -170
  198. package/kit/framework/templates/research.md +419 -419
  199. package/kit/framework/templates/retrospective.md +54 -54
  200. package/kit/framework/templates/roadmap.md +202 -202
  201. package/kit/framework/templates/state.md +176 -176
  202. package/kit/framework/templates/summary-complex.md +59 -59
  203. package/kit/framework/templates/summary-minimal.md +41 -41
  204. package/kit/framework/templates/summary-standard.md +48 -48
  205. package/kit/framework/templates/summary.md +209 -209
  206. package/kit/framework/templates/user-profile.md +146 -146
  207. package/kit/framework/templates/user-setup.md +256 -256
  208. package/kit/framework/templates/verification-report.md +258 -258
  209. package/kit/framework/workflows/add-phase.md +112 -112
  210. package/kit/framework/workflows/add-tests.md +351 -351
  211. package/kit/framework/workflows/add-todo.md +158 -158
  212. package/kit/framework/workflows/audit-milestone.md +340 -340
  213. package/kit/framework/workflows/audit-uat.md +109 -109
  214. package/kit/framework/workflows/autonomous.md +891 -891
  215. package/kit/framework/workflows/check-todos.md +177 -177
  216. package/kit/framework/workflows/cleanup.md +152 -152
  217. package/kit/framework/workflows/complete-milestone.md +696 -696
  218. package/kit/framework/workflows/diagnose-issues.md +231 -231
  219. package/kit/framework/workflows/discovery-phase.md +289 -289
  220. package/kit/framework/workflows/discuss-phase-assumptions.md +653 -653
  221. package/kit/framework/workflows/discuss-phase.md +784 -784
  222. package/kit/framework/workflows/do.md +104 -104
  223. package/kit/framework/workflows/execute-phase.md +838 -838
  224. package/kit/framework/workflows/execute-plan.md +510 -510
  225. package/kit/framework/workflows/fast.md +102 -102
  226. package/kit/framework/workflows/forensics.md +265 -265
  227. package/kit/framework/workflows/health.md +181 -181
  228. package/kit/framework/workflows/help.md +619 -619
  229. package/kit/framework/workflows/insert-phase.md +130 -130
  230. package/kit/framework/workflows/list-phase-assumptions.md +178 -178
  231. package/kit/framework/workflows/list-workspaces.md +56 -56
  232. package/kit/framework/workflows/manager.md +362 -362
  233. package/kit/framework/workflows/map-codebase.md +377 -377
  234. package/kit/framework/workflows/milestone-summary.md +223 -223
  235. package/kit/framework/workflows/new-milestone.md +486 -486
  236. package/kit/framework/workflows/new-project.md +1159 -1159
  237. package/kit/framework/workflows/new-workspace.md +237 -237
  238. package/kit/framework/workflows/next.md +97 -97
  239. package/kit/framework/workflows/node-repair.md +92 -92
  240. package/kit/framework/workflows/note.md +156 -156
  241. package/kit/framework/workflows/pause-work.md +176 -176
  242. package/kit/framework/workflows/plan-milestone-gaps.md +273 -273
  243. package/kit/framework/workflows/plan-phase.md +765 -765
  244. package/kit/framework/workflows/plant-seed.md +169 -169
  245. package/kit/framework/workflows/pr-branch.md +129 -129
  246. package/kit/framework/workflows/profile-user.md +450 -450
  247. package/kit/framework/workflows/progress.md +507 -507
  248. package/kit/framework/workflows/quick.md +757 -757
  249. package/kit/framework/workflows/remove-phase.md +155 -155
  250. package/kit/framework/workflows/remove-workspace.md +90 -90
  251. package/kit/framework/workflows/research-phase.md +82 -82
  252. package/kit/framework/workflows/resume-project.md +326 -326
  253. package/kit/framework/workflows/review.md +228 -228
  254. package/kit/framework/workflows/session-report.md +146 -146
  255. package/kit/framework/workflows/settings.md +283 -283
  256. package/kit/framework/workflows/ship.md +228 -228
  257. package/kit/framework/workflows/stats.md +60 -60
  258. package/kit/framework/workflows/transition.md +671 -671
  259. package/kit/framework/workflows/ui-phase.md +302 -302
  260. package/kit/framework/workflows/ui-review.md +165 -165
  261. package/kit/framework/workflows/update.md +323 -323
  262. package/kit/framework/workflows/validate-phase.md +174 -174
  263. package/kit/framework/workflows/verify-phase.md +252 -252
  264. package/kit/framework/workflows/verify-work.md +637 -637
  265. package/kit/hooks/check-update.js +118 -118
  266. package/kit/hooks/context-monitor.js +163 -163
  267. package/kit/hooks/prompt-guard.js +103 -103
  268. package/kit/hooks/statusline.js +125 -125
  269. package/kit/hooks/workflow-guard.js +101 -101
  270. package/kit/settings.json +45 -45
  271. package/kit/skills/_shared-supabase/glossary.md +17 -0
  272. package/kit/skills/ai-prompt-characterization/SKILL.md +335 -335
  273. package/kit/skills/armadilhas-sistemas-distribuidos/SKILL.md +447 -447
  274. package/kit/skills/audit-log-multi-tenant/SKILL.md +340 -340
  275. package/kit/skills/b2b-saas-architecture/SKILL.md +300 -300
  276. package/kit/skills/consistencia-leitura-replica/SKILL.md +385 -385
  277. package/kit/skills/crm-lead-pipeline-patterns/SKILL.md +343 -343
  278. package/kit/skills/escolha-modelo-consistencia/SKILL.md +494 -494
  279. package/kit/skills/evolucao-schema-compativel/SKILL.md +448 -448
  280. package/kit/skills/evolution-go-whatsapp-integration/SKILL.md +322 -322
  281. package/kit/skills/example-skill/SKILL.md +42 -42
  282. package/kit/skills/legacy-api-only-applications/SKILL.md +358 -358
  283. package/kit/skills/legacy-characterization-tests/SKILL.md +330 -330
  284. package/kit/skills/legacy-effect-analysis/SKILL.md +331 -331
  285. package/kit/skills/legacy-extract-class/SKILL.md +203 -203
  286. package/kit/skills/legacy-programming-by-difference/SKILL.md +252 -252
  287. package/kit/skills/legacy-seams-and-test-harness/SKILL.md +460 -460
  288. package/kit/skills/legacy-shotgun-surgery/SKILL.md +286 -286
  289. package/kit/skills/legacy-sprout-wrap-techniques/SKILL.md +434 -434
  290. package/kit/skills/legacy-storytelling-naked-crc/SKILL.md +270 -270
  291. package/kit/skills/lgpd-multi-tenant-compliance/SKILL.md +340 -340
  292. package/kit/skills/member-invite-flow/SKILL.md +305 -305
  293. package/kit/skills/member-management-react-shadcn/SKILL.md +328 -328
  294. package/kit/skills/multi-tenant-performance-scaling/SKILL.md +316 -316
  295. package/kit/skills/multi-tenant-rls-hierarchy/SKILL.md +342 -342
  296. package/kit/skills/org-onboarding-flow/SKILL.md +257 -257
  297. package/kit/skills/org-switcher-react-pattern/SKILL.md +349 -349
  298. package/kit/skills/permission-gate-react-pattern/SKILL.md +271 -271
  299. package/kit/skills/postgres-isolamento-concorrencia/SKILL.md +552 -552
  300. package/kit/skills/pre-refactor-characterization/SKILL.md +421 -421
  301. package/kit/skills/rbac-permissions-matrix-supabase/SKILL.md +338 -338
  302. package/kit/skills/streams-eventos-cdc/SKILL.md +711 -711
  303. package/kit/skills/supabase-branching-workflow/SKILL.md +544 -544
  304. package/kit/skills/supabase-ci-cd-github-actions/SKILL.md +880 -880
  305. package/kit/skills/supabase-column-level-security/SKILL.md +426 -426
  306. package/kit/skills/supabase-config-toml-remotes/SKILL.md +807 -807
  307. package/kit/skills/supabase-custom-claims-rbac/SKILL.md +472 -472
  308. package/kit/skills/supabase-edge-functions/SKILL.md +229 -141
  309. package/kit/skills/supabase-edge-functions-auth/SKILL.md +309 -0
  310. package/kit/skills/supabase-edge-functions-limits/SKILL.md +302 -0
  311. package/kit/skills/supabase-edge-functions-mcp-server/SKILL.md +279 -0
  312. package/kit/skills/supabase-edge-functions-testing/SKILL.md +277 -0
  313. package/kit/skills/supabase-edge-runtime-builtins/SKILL.md +357 -0
  314. package/kit/skills/supabase-migration-repair/SKILL.md +823 -823
  315. package/kit/skills/supabase-migrations/SKILL.md +297 -297
  316. package/kit/skills/supabase-pgtap-testing/SKILL.md +1053 -1053
  317. package/kit/skills/supabase-postgres-roles/SKILL.md +392 -392
  318. package/kit/skills/supabase-realtime/SKILL.md +460 -236
  319. package/kit/skills/supabase-rls-defense-in-depth/SKILL.md +418 -418
  320. package/kit/skills/supabase-rls-policies/SKILL.md +635 -635
  321. package/kit/skills/super-admin-platform-pattern/SKILL.md +326 -326
  322. package/kit/skills/tenant-quente-mitigacao/SKILL.md +605 -605
  323. package/kit/skills/whatsapp-conversation-state-machine/SKILL.md +287 -287
  324. package/package.json +1 -1
  325. package/src/cli/index.js +33 -0
  326. package/src/core/kit.js +216 -216
  327. package/src/core/reflect.js +247 -247
  328. package/src/core/reverse-sync.js +372 -372
  329. package/src/core/sync.js +418 -418
  330. package/src/core/watch.js +121 -121
  331. package/src/mcp-server/index.js +693 -490
  332. package/src/mcp-server/roots.js +124 -0
@@ -1,807 +1,807 @@
1
- ---
2
- name: supabase-config-toml-remotes
3
- description: Use ao configurar Supabase para branching — `[remotes.<name>]` block + branch-specific overrides + secrets per-branch (NÃO herdam) + dotenvx pattern (.env.keys + .env.preview encrypted) + 6…
4
- ---
5
-
6
- # Supabase — Config TOML & Remotes
7
-
8
- ## Quando usar
9
-
10
- Branching Supabase exige configuração per-branch via `supabase/config.toml` — blocos `[remotes.<name>]` declaram **overrides versionados em git** que o Deploy DAG step 4 (configure) aplica em cada branch.
11
-
12
- Esta skill é par-conjugado com `supabase-branching-workflow` (Phase 149) — branching workflow descreve **quando** branches são criados; esta skill descreve **como** configurar.
13
-
14
- Trigger phrases:
15
-
16
- - "remotes block Supabase", "[remotes] config.toml"
17
- - "branch-specific config Supabase", "config.toml staging override"
18
- - "secrets per-branch Supabase", "supabase secrets set"
19
- - "dotenvx Supabase", ".env.keys .env.preview"
20
- - "encrypted: Supabase config", "env() vs encrypted: syntax"
21
- - "Supabase encrypted fields", "auth.hook secrets encrypted"
22
- - "designated secret fields"
23
- - "branch project_id Supabase"
24
-
25
- **Use APENAS para:**
26
-
27
- - Configurar persistent branches (staging, QA, production) via `[remotes.<branch>]` block
28
- - Materializar overrides per-ambiente (db.pool_size, api.max_rows, auth.external.*, edge_runtime.secrets)
29
- - Gerenciar secrets per-branch via `supabase secrets set --env-file`
30
- - Versionar secrets encrypted em git via dotenvx pattern (.env.keys + .env.preview/.env.production)
31
-
32
- **NÃO use para:**
33
-
34
- - Substituir secret vault corporativo (Vault, AWS Secrets Manager) — dotenvx é git-tracked encrypted; vault corporativo tem audit trail + rotation policies
35
- - Gerenciar secrets de runtime de Edge Functions sem `supabase secrets set` — `env()` em config.toml é build-time do CLI, não runtime do projeto
36
- - Versionar a chave de decryption (`.env.keys`) — NUNCA committar; é equivalente a vazar password master
37
- - Apontar `[remotes.<name>]` para branch deletado — operações falham silenciosamente
38
-
39
- ## Princípio canônico
40
-
41
- Três princípios canônicos:
42
-
43
- 1. **`config.toml` é source of truth versionado.** `[remotes.<branch>]` block declara overrides explícitos commitados em git — Deploy DAG step 4 (configure) re-aplica em cada deploy. Sem deriva entre o que está em git e o que está no branch.
44
-
45
- 2. **dotenvx para secrets git-tracked.** `.env.keys` (decryption key, **SEMPRE gitignored**) + `.env.preview`/`.env.production` (encrypted values, committed em git). Permite versionar secrets sem expor — git history rastreia mudanças de secrets sem PII em plaintext.
46
-
47
- 3. **Secrets NÃO herdam entre branches.** Cada branch tem credenciais únicas; criar persistent branch `staging` NÃO copia secrets do `main`. Reset manual via `supabase secrets set --env-file` para CADA branch — incluindo o branch `main` original.
48
-
49
- ### Distinção canônica `env()` vs `encrypted:`
50
-
51
- | | `env(VAR_NAME)` | `encrypted:<value>` |
52
- |---|---|---|
53
- | Resolução | Runtime CLI (build-time) | Decryption via `.env.keys` |
54
- | Onde funciona | **Qualquer** field em config.toml | **APENAS** designated secret fields (Pattern 5) |
55
- | Workflow | Setar env var no shell antes do CLI | Encriptar via `dotenvx set`, committed em git |
56
- | Caveat | Resolve para env var **local** do CLI, NÃO para secrets do projeto Supabase (runtime das Edge Functions) | Em field **não-designated** é silent no-op (literal string usada como valor) |
57
- | Caso de uso | Secrets em env vars do CI (GitHub Actions) | Secrets versionados encrypted em git via dotenvx |
58
-
59
- ## Pattern 1: `[remotes]` block — referenciar branch existente (CFG-01)
60
-
61
- `[remotes.<name>]` em `config.toml` declara que **este bloco se aplica APENAS ao branch nomeado** identificado pelo `project_id`.
62
-
63
- ### Pré-requisito
64
-
65
- Branch já criado (persistent via CLI ou preview via PR webhook):
66
-
67
- ```bash
68
- # criar persistent branch via CLI
69
- supabase --experimental branches create staging --persistent
70
-
71
- # (preview branches são criados automaticamente via GitHub PR — cross-ref skill supabase-branching-workflow Pattern 3)
72
- ```
73
-
74
- ### Workflow canônico
75
-
76
- **Step 1: Obter `project_id` do branch:**
77
-
78
- ```bash
79
- supabase --experimental branches list
80
-
81
- # output esperado:
82
- # BRANCH NAME BRANCH PROJECT ID STATUS
83
- # main main-project-ref active
84
- # staging staging-dedicated-ref active
85
- # pr-42-feature pr42-feature-ref active
86
- ```
87
-
88
- **Step 2: Adicionar `[remotes.<branch>]` block no `supabase/config.toml`:**
89
-
90
- ```toml
91
- [remotes.staging]
92
- project_id = "staging-dedicated-ref"
93
-
94
- [remotes.staging.db.seed]
95
- enabled = true
96
- sql_paths = ["./seeds/staging.sql"]
97
- ```
98
-
99
- **Step 3: Commitar `config.toml` em git → Deploy DAG step 4 (configure) aplica overrides no branch.**
100
-
101
- ### Exemplo TOML — múltiplos branches
102
-
103
- ```toml
104
- # bloco base — aplica a TODOS os branches (incluindo main)
105
- [db]
106
- port = 54322
107
- pool_size = 15
108
-
109
- [api]
110
- port = 54321
111
- max_rows = 1000
112
-
113
- # branch staging — overrides específicos
114
- [remotes.staging]
115
- project_id = "staging-dedicated-ref"
116
-
117
- [remotes.staging.db.seed]
118
- enabled = true
119
- sql_paths = ["./seeds/staging.sql"]
120
-
121
- # branch production — sem seeds em produção
122
- [remotes.production]
123
- project_id = "production-dedicated-ref"
124
-
125
- [remotes.production.db.seed]
126
- enabled = false
127
- ```
128
-
129
- ### Caveat — branch deletado
130
-
131
- `project_id` deve ser de branch **existente**. Se branch foi deletado:
132
-
133
- - Bloco `[remotes.<branch>]` continua válido sintaticamente
134
- - CLI rejeita commands com erro `branch not found`
135
- - DAG step 4 (configure) silenciosamente skip o branch deletado
136
-
137
- **Mitigação:** revisão trimestral — `supabase --experimental branches list` + remover blocos `[remotes.<deleted>]` correspondentes.
138
-
139
- ### Caveat — `project_id` único por bloco
140
-
141
- Cada `[remotes.<name>]` deve apontar para **branch dedicado** criado especificamente. NÃO reutilizar `project_id` do `main` para `staging` (cross-ref Anti-pattern 5).
142
-
143
- ## Pattern 2: Branch-specific configuration overrides (CFG-02)
144
-
145
- Princípio: config base (sem `[remotes...]` prefix) aplica a TODOS os branches; `[remotes.<name>.<section>]` aplica override APENAS no branch nomeado.
146
-
147
- ### Categorias de fields override-able (canônicas)
148
-
149
- **db (database tuning):**
150
-
151
- ```toml
152
- [db]
153
- port = 54322
154
- pool_size = 15 # default
155
-
156
- # staging override
157
- [remotes.staging.db]
158
- port = 54322 # mesma porta — só pool_size muda
159
- pool_size = 25
160
- ```
161
-
162
- **api (PostgREST):**
163
-
164
- ```toml
165
- [api]
166
- port = 54321
167
- max_rows = 1000
168
- schemas = ["public"]
169
-
170
- # staging quer ver schema extensions para debug
171
- [remotes.staging.api]
172
- max_rows = 5000 # debug — limite maior
173
- schemas = ["public", "extensions"]
174
- ```
175
-
176
- **db.seed:**
177
-
178
- ```toml
179
- # default — sem seed
180
- [db.seed]
181
- enabled = false
182
- sql_paths = []
183
-
184
- # staging — seed sintético para QA
185
- [remotes.staging.db.seed]
186
- enabled = true
187
- sql_paths = ["./seeds/staging.sql"]
188
-
189
- # preview — seed minimal para smoke tests
190
- [remotes.preview.db.seed]
191
- enabled = true
192
- sql_paths = ["./seeds/preview-smoke.sql"]
193
- ```
194
-
195
- **auth.external.* (OAuth providers):**
196
-
197
- ```toml
198
- # production GitHub OAuth
199
- [auth.external.github]
200
- enabled = true
201
- client_id = "Iv1.production-app-id"
202
- secret = "encrypted:LSi...prod-github-secret-encrypted...=="
203
-
204
- # staging GitHub OAuth — app diferente
205
- [remotes.staging.auth.external.github]
206
- enabled = true
207
- client_id = "Iv1.staging-app-id"
208
- secret = "encrypted:LSi...staging-github-secret-encrypted...=="
209
- redirect_uri = "https://staging.example.com/auth/callback"
210
- ```
211
-
212
- **edge_runtime.secrets:**
213
-
214
- ```toml
215
- [edge_runtime.secrets]
216
- SENDGRID_API_KEY = "encrypted:LSi...prod-sendgrid-encrypted...=="
217
-
218
- # staging — SendGrid sandbox
219
- [remotes.staging.edge_runtime.secrets]
220
- SENDGRID_API_KEY = "encrypted:LSi...staging-sendgrid-encrypted...=="
221
- SENDGRID_SANDBOX_MODE = "env(STAGING_SENDGRID_SANDBOX_MODE)"
222
- ```
223
-
224
- ### Tabela canônica de fields override-able
225
-
226
- | Section | Fields | Caso de uso típico |
227
- |---------|--------|---------------------|
228
- | `db` | `port`, `pool_size` | Tuning pool size per ambiente (staging menor) |
229
- | `api` | `port`, `max_rows`, `schemas` | Diferenciar response limits + schemas expostos |
230
- | `db.seed` | `enabled`, `sql_paths` | Seeds diferentes por branch |
231
- | `auth.external.<provider>` | `enabled`, `client_id`, `secret`, `redirect_uri` | OAuth keys per ambiente |
232
- | `auth.email.smtp` | `host`, `port`, `user`, `pass` | SMTP staging vs produção |
233
- | `auth.sms.<provider>` | `account_sid`, `auth_token`, etc. | SMS provider keys per ambiente |
234
- | `edge_runtime.secrets.<KEY>` | custom env vars | API keys per branch (SendGrid, Stripe, OpenAI) |
235
- | `studio.openai_api_key` | string | Key diferente para staging studio (lower limits) |
236
-
237
- ### Caveat — merge behavior
238
-
239
- `[remotes.staging.db]` com `pool_size = 25` NÃO sobrescreve `[db]` global completamente — apenas o field específico (`pool_size`). Outros fields do `[db]` global (port, etc.) continuam aplicados.
240
-
241
- ```toml
242
- # config base
243
- [db]
244
- port = 54322
245
- pool_size = 15
246
- shadow_port = 54320
247
-
248
- # staging override — apenas pool_size muda
249
- [remotes.staging.db]
250
- pool_size = 25
251
- # resultado em staging: port=54322, pool_size=25, shadow_port=54320 (mantidos da base)
252
- ```
253
-
254
- ### Caveat — re-deploy required
255
-
256
- Alterações em `config.toml` precisam ser pushed para o branch — Deploy DAG step 4 (configure) só roda em novo deploy (push novo commit no PR ou re-run via Dashboard).
257
-
258
- ## Pattern 3: Secrets management per-branch (CFG-03)
259
-
260
- ### Caveat canônico — secrets NÃO herdam
261
-
262
- > **Secrets NÃO herdam entre branches.** Criar persistent branch `staging` NÃO copia secrets do `main`. Cada branch precisa ter secrets setados separadamente.
263
-
264
- Implicação prática:
265
-
266
- - `Deno.env.get("SENDGRID_API_KEY")` em Edge Function no branch staging retorna `undefined` até `supabase secrets set` ser executado para o staging
267
- - Esse comportamento é silent — sem warning no DAG, sem alert do CLI
268
-
269
- ### CLI canônico
270
-
271
- ```bash
272
- # Set secrets a partir de .env file (recomendação canônica)
273
- supabase secrets set --env-file ./supabase/.env
274
-
275
- # Set secret individual
276
- supabase secrets set SMTP_HOST=smtp.example.com
277
-
278
- # Listar secrets do branch atual
279
- supabase secrets list
280
-
281
- # Remover secret
282
- supabase secrets unset SMTP_HOST
283
- ```
284
-
285
- ### Workflow per-branch canônico
286
-
287
- ```bash
288
- # 1. criar staging branch
289
- supabase --experimental branches create staging --persistent
290
-
291
- # 2. obter project_id do staging
292
- supabase --experimental branches list | grep staging
293
- # output: staging staging-dedicated-ref active
294
-
295
- # 3. link CLI para o branch staging
296
- supabase link --project-ref staging-dedicated-ref
297
-
298
- # 4. setar secrets DO STAGING (arquivo dedicado)
299
- supabase secrets set --env-file ./supabase/.env.staging
300
-
301
- # 5. validar — listar secrets do staging
302
- supabase secrets list
303
-
304
- # 6. voltar para main quando terminar
305
- supabase link --project-ref main-project-ref
306
- ```
307
-
308
- ### Exemplo `.env.staging`
309
-
310
- ```bash
311
- # .env.staging — secrets específicos do branch staging
312
- # Gitignored se não usa dotenvx (Pattern 4); encrypted se usa.
313
- SMTP_HOST=smtp.staging.example.com
314
- SMTP_USER=staging-user
315
- SMTP_PASS=staging-pass
316
- SENDGRID_API_KEY=SG.staging-api-key
317
- OPENAI_API_KEY=sk-staging-openai-key
318
- STRIPE_SECRET_KEY=sk_test_staging_stripe
319
- ```
320
-
321
- ### Caveat — secrets vs config.toml `env()`
322
-
323
- Distinção CRÍTICA — fonte de confusão comum:
324
-
325
- | | `supabase secrets set` | `env()` em config.toml |
326
- |---|---|---|
327
- | Resolvido | Runtime das **Edge Functions** | Build-time do **CLI local** |
328
- | Acesso | `Deno.env.get("KEY")` no código Deno | Substituição literal no `config.toml` pré-deploy |
329
- | Storage | Supabase backend (per-branch) | Env var do shell que rodou o CLI |
330
- | Lifecycle | Persistido no branch | Volátil (só durante invocação do CLI) |
331
-
332
- Exemplo concreto:
333
-
334
- ```bash
335
- # Setar secret no branch (runtime Edge Function)
336
- supabase secrets set SENDGRID_API_KEY=sk-real-key
337
- # → Deno.env.get("SENDGRID_API_KEY") em Edge Function retorna "sk-real-key"
338
-
339
- # Setar env var local (build-time config.toml)
340
- export SENDGRID_API_KEY=sk-different-key
341
- supabase db push
342
- # → config.toml com env(SENDGRID_API_KEY) resolve para "sk-different-key" (do shell)
343
- # → Edge Function ainda retorna "sk-real-key" (do supabase secrets set anterior)
344
- ```
345
-
346
- ### Recomendação canônica
347
-
348
- Usar **dotenvx pattern** (Pattern 4) para versionar secrets encrypted em git em vez de gerenciar `.env.staging` separadamente em cada máquina.
349
-
350
- ## Pattern 4: dotenvx pattern + `encrypted:` vs `env()` syntax (CFG-04)
351
-
352
- ### Princípio dotenvx
353
-
354
- dotenvx ([dotenvx.com](https://dotenvx.com/)) é uma evolução de `dotenv` que permite **encryption symmetric** de valores no arquivo `.env`:
355
-
356
- - Encrypted values podem ser committed em git (`.env.preview`, `.env.production`)
357
- - Decryption key (`.env.keys`) **NUNCA é committed** — gitignored sempre
358
- - Permite versionar secrets sem expor — git history rastreia mudanças de secrets sem PII em plaintext
359
-
360
- ### Tabela canônica de file types (dotenvx convenção)
361
-
362
- | File | Env | gitignore | Encrypted | Caso de uso |
363
- |------|-----|-----------|-----------|-------------|
364
- | `.env.keys` | All | **YES** (NUNCA committar) | No (key plaintext) | Decryption master key |
365
- | `.env.local` | Local dev | YES | No (plaintext OK local) | Overrides de dev individual |
366
- | `.env.production` | Production | No (committed) | YES | Secrets de produção encrypted |
367
- | `.env.preview` | Branches preview | No (committed) | YES | Secrets de preview branches encrypted |
368
- | `.env` | Any (fallback) | Maybe | YES | Default file (custom) |
369
-
370
- **Atenção canônica:** `.env.keys` em `.gitignore` é obrigação canônica — sem isso, o pattern dotenvx é equivalente a commitar secrets plaintext.
371
-
372
- ### Workflow canônico dotenvx
373
-
374
- ```bash
375
- # 1. instalar dotenvx (devDependency)
376
- npm install -D @dotenvx/dotenvx
377
-
378
- # 2. adicionar .env.keys ao .gitignore (BLOQUEANTE — fazer ANTES de qualquer set)
379
- echo ".env.keys" >> .gitignore
380
- git add .gitignore
381
- git commit -m "chore: gitignore dotenvx decryption key"
382
-
383
- # 3. encrypted set — gera .env.keys automaticamente na primeira vez
384
- npx @dotenvx/dotenvx set SUPABASE_AUTH_EXTERNAL_GITHUB_SECRET "ghs_real_secret" -f supabase/.env.preview
385
- # Output:
386
- # set SUPABASE_AUTH_EXTERNAL_GITHUB_SECRET (encrypted) (.env.preview)
387
- # wrote new public-private encryption keys to .env.keys
388
-
389
- # 4. commitar .env.preview (encrypted) + verificar .env.keys NÃO foi committed
390
- git status
391
- # modified: supabase/.env.preview
392
- # (.env.keys NÃO deve aparecer)
393
- git add supabase/.env.preview
394
- git commit -m "feat: add encrypted GitHub OAuth secret for preview"
395
-
396
- # 5. usar com supabase CLI (carregar via --env-file)
397
- npx supabase secrets set --env-file supabase/.env.keys
398
- # ou em workflow CI (decripta + roda CLI):
399
- npx @dotenvx/dotenvx run -- supabase secrets set --env-file supabase/.env.preview
400
- ```
401
-
402
- ### Sintaxes em `config.toml`
403
-
404
- **Option A: `encrypted:<value>` directly em designated secret field:**
405
-
406
- ```toml
407
- [auth.external.github]
408
- enabled = true
409
- client_id = "Iv1.app-id-public"
410
- # secret é designated secret field (Pattern 5 Grupo 8) — encrypted: é decriptado via .env.keys
411
- secret = "encrypted:LSiME...github-secret-encrypted-payload...=="
412
- ```
413
-
414
- **Option B: `env(VAR_NAME)` para resolver via env var (qualquer field):**
415
-
416
- ```toml
417
- [auth.external.github]
418
- enabled = true
419
- client_id = "env(SUPABASE_AUTH_EXTERNAL_GITHUB_CLIENT_ID)"
420
- secret = "env(SUPABASE_AUTH_EXTERNAL_GITHUB_SECRET)"
421
- ```
422
-
423
- ### Warning canônico — `encrypted:` é restrito
424
-
425
- > **`encrypted:` syntax SÓ funciona em designated secret fields** (Pattern 5 — 6 grupos canônicos). Em outros campos não decripta silenciosamente — o valor literal `"encrypted:LSiME..."` é usado como string, expondo o payload encrypted como se fosse plaintext.
426
-
427
- Exemplo concreto do falso silencioso:
428
-
429
- ```toml
430
- # ERRADO — auth.email.smtp.host NÃO é designated secret field
431
- [auth.email.smtp]
432
- host = "encrypted:LSi...wrong...==" # ← silent no-op
433
- # resultado: SMTP tenta conectar em host literal "encrypted:LSi...wrong...==" → DNS fail
434
-
435
- # CERTO — auth.email.smtp.pass É designated (Pattern 5 Grupo 4)
436
- [auth.email.smtp]
437
- host = "smtp.example.com" # plain
438
- pass = "encrypted:LSi...correct-pass...==" # ← decriptado
439
- ```
440
-
441
- ### Quando usar qual
442
-
443
- - **`encrypted:`** — quando quer versionar o secret **encrypted em git** (workflow dotenvx); aplicar APENAS em fields designados (Pattern 5)
444
- - **`env()`** — quando secrets vivem em env vars do CI/local; works em **qualquer field**; flexibilidade ao custo de não versionar em git (rotação via update env var no CI)
445
-
446
- Recomendação canônica para teams maduros: `encrypted:` em produção (auditável via git history) + `env()` em dev local (volátil).
447
-
448
- ## Pattern 5: 6 grupos de encrypted fields canônicos (CFG-05)
449
-
450
- Princípio: apenas estes fields aceitam `encrypted:<value>` syntax — qualquer outro field é **silent no-op** (cross-ref Pattern 4 Warning).
451
-
452
- ### Lista canônica COMPLETA dos 6 grupos lógicos
453
-
454
- A documentação Supabase agrupa estes como **6 grupos lógicos** (Studio, Database, Auth Core/Email/Captcha/Hooks/SMS/External, Edge Runtime) — apresentamos expandido para máxima clareza por subcategoria.
455
-
456
- ### Grupo 1: Studio
457
-
458
- | Field | Caso de uso |
459
- |-------|-------------|
460
- | `studio.openai_api_key` | Studio AI features (SQL suggestions, schema generation) |
461
-
462
- ### Grupo 2: Database
463
-
464
- | Field | Caso de uso |
465
- |-------|-------------|
466
- | `db.root_key` | Root key para encryption-at-rest (Vault) |
467
- | `db.vault.*` (todas subkeys) | Supabase Vault — encryption keys gerenciadas |
468
-
469
- ### Grupo 3: Auth Core
470
-
471
- | Field | Caso de uso |
472
- |-------|-------------|
473
- | `auth.publishable_key` | API publishable key (substitui anon key v2) |
474
- | `auth.secret_key` | API secret key (substitui service_role key v2) |
475
- | `auth.jwt_secret` | JWT signing secret (HS256) |
476
-
477
- ### Grupo 4: Auth Email
478
-
479
- | Field | Caso de uso |
480
- |-------|-------------|
481
- | `auth.email.smtp.pass` | Password do SMTP server (SendGrid, AWS SES, Mailgun, etc.) |
482
-
483
- ### Grupo 5: Auth Captcha
484
-
485
- | Field | Caso de uso |
486
- |-------|-------------|
487
- | `auth.captcha.secret` | hCaptcha ou Turnstile secret key |
488
-
489
- ### Grupo 6: Auth Hooks
490
-
491
- Todos os 6 Auth Hooks (cross-ref skill `supabase-custom-claims-rbac` v1.25):
492
-
493
- | Field | Caso de uso |
494
- |-------|-------------|
495
- | `auth.hook.mfa_verification_attempt.secrets` | Custom MFA verification hook |
496
- | `auth.hook.password_verification_attempt.secrets` | Custom password verification hook |
497
- | `auth.hook.custom_access_token.secrets` | Custom Access Token Auth Hook (RBAC v1.25) |
498
- | `auth.hook.send_sms.secrets` | Custom SMS sender hook |
499
- | `auth.hook.send_email.secrets` | Custom email sender hook |
500
- | `auth.hook.before_user_created.secrets` | Hook para validar/rejeitar signup |
501
-
502
- ### Grupo 7: Auth SMS providers
503
-
504
- 5 providers SMS canônicos:
505
-
506
- | Field | Caso de uso |
507
- |-------|-------------|
508
- | `auth.sms.twilio.auth_token` | Twilio SMS provider |
509
- | `auth.sms.twilio_verify.auth_token` | Twilio Verify (MFA) |
510
- | `auth.sms.messagebird.access_key` | MessageBird provider |
511
- | `auth.sms.textlocal.api_key` | Textlocal (UK provider) |
512
- | `auth.sms.vonage.api_secret` | Vonage (ex-Nexmo) |
513
-
514
- ### Grupo 8: Auth External providers
515
-
516
- | Field | Caso de uso |
517
- |-------|-------------|
518
- | `auth.external.<provider>.secret` | Qualquer OAuth provider — github, google, facebook, apple, twitter, discord, gitlab, bitbucket, azure, linkedin, notion, slack, spotify, twitch, kakao, keycloak, workos, zoom, figma, fly |
519
-
520
- ### Grupo 9: Edge Runtime
521
-
522
- | Field | Caso de uso |
523
- |-------|-------------|
524
- | `edge_runtime.secrets.*` (todas subkeys) | Env vars custom para Edge Functions (SENDGRID, STRIPE, OPENAI, etc.) |
525
-
526
- ### Exemplo TOML completo cobrindo múltiplos grupos
527
-
528
- ```toml
529
- # Grupo 1: Studio
530
- [studio]
531
- openai_api_key = "encrypted:LSi...studio-key-encrypted...=="
532
-
533
- # Grupo 2: Database (Vault)
534
- [db.vault]
535
- secret_master_key = "encrypted:LSi...vault-master-encrypted...=="
536
-
537
- # Grupo 3: Auth Core
538
- [auth]
539
- jwt_secret = "encrypted:LSi...jwt-secret-encrypted...=="
540
- secret_key = "encrypted:LSi...secret-key-encrypted...=="
541
-
542
- # Grupo 4: Auth Email
543
- [auth.email.smtp]
544
- host = "smtp.sendgrid.net"
545
- port = 587
546
- user = "apikey"
547
- pass = "encrypted:LSi...smtp-pass-encrypted...=="
548
-
549
- # Grupo 5: Auth Captcha
550
- [auth.captcha]
551
- enabled = true
552
- provider = "hcaptcha"
553
- secret = "encrypted:LSi...captcha-secret-encrypted...=="
554
-
555
- # Grupo 6: Auth Hooks
556
- [auth.hook.custom_access_token]
557
- enabled = true
558
- uri = "pg-functions://postgres/auth/custom_access_token_hook"
559
- secrets = "encrypted:LSi...hook-secret-encrypted...=="
560
-
561
- [auth.hook.send_email]
562
- enabled = true
563
- uri = "https://example.com/auth/send-email-hook"
564
- secrets = "encrypted:LSi...email-hook-secret-encrypted...=="
565
-
566
- # Grupo 7: Auth SMS (Twilio)
567
- [auth.sms.twilio]
568
- enabled = true
569
- account_sid = "ACxxxxxxxxxxxx"
570
- message_service_sid = "MGxxxxxxxxxxxx"
571
- auth_token = "encrypted:LSi...twilio-token-encrypted...=="
572
-
573
- # Grupo 8: Auth External (GitHub OAuth)
574
- [auth.external.github]
575
- enabled = true
576
- client_id = "Iv1.xxxxxxx"
577
- secret = "encrypted:LSi...github-secret-encrypted...=="
578
-
579
- # Grupo 9: Edge Runtime
580
- [edge_runtime.secrets]
581
- OPENAI_API_KEY = "encrypted:LSi...openai-edge-encrypted...=="
582
- SENDGRID_API_KEY = "encrypted:LSi...sendgrid-edge-encrypted...=="
583
- STRIPE_SECRET_KEY = "encrypted:LSi...stripe-edge-encrypted...=="
584
- ```
585
-
586
- ### Caveat — lista pode evoluir com versões do CLI
587
-
588
- A lista de designated secret fields pode evoluir com novas versões do Supabase CLI (novos providers OAuth, novos Auth Hooks, etc.). Para refresh periódico:
589
-
590
- ```bash
591
- # verificar versão do CLI
592
- supabase --version
593
-
594
- # consultar doc oficial:
595
- # https://supabase.com/docs/guides/local-development/cli/config
596
- ```
597
-
598
- **Recomendação canônica:** review trimestral da lista vs doc oficial — Supabase publica updates regularmente.
599
-
600
- ## Anti-patterns
601
-
602
- ### Anti-pattern 1: Usar `encrypted:` em field não-designated
603
-
604
- **Errado:**
605
-
606
- ```toml
607
- [auth.email.smtp]
608
- host = "encrypted:LSi...wrong-host...==" # smtp.host NÃO é designated
609
- port = 587
610
- ```
611
-
612
- **Por quê:** valor literal é usado como string — SMTP tenta conectar em host literal `"encrypted:LSi...=="`, DNS lookup falha silenciosamente, emails não são enviados, sem erro claro no log.
613
-
614
- **Certo:** consultar Pattern 5 — usar `encrypted:` APENAS nos grupos canônicos. Para `auth.email.smtp.host` use plaintext (não é secret) ou `env(SMTP_HOST)`:
615
-
616
- ```toml
617
- [auth.email.smtp]
618
- host = "smtp.sendgrid.net" # plaintext OK (não é secret)
619
- port = 587
620
- user = "apikey"
621
- pass = "encrypted:LSi...correct-pass...==" # designated secret field
622
- ```
623
-
624
- ### Anti-pattern 2: Assumir secrets herdam entre branches
625
-
626
- **Errado:** criar `staging` branch e assumir que `SENDGRID_API_KEY` do `main` está disponível.
627
-
628
- ```bash
629
- supabase --experimental branches create staging --persistent
630
- # (assume erradamente que secrets do main foram copiados)
631
-
632
- # Edge Function no staging — falha
633
- const apiKey = Deno.env.get("SENDGRID_API_KEY"); // undefined
634
- ```
635
-
636
- **Por quê:** secrets são **per-branch** — staging tem env vars vazias até `supabase secrets set` rodar separadamente; Edge Functions retornam `undefined`; código quebra sem erro claro no DAG.
637
-
638
- **Certo:** rodar `supabase secrets set --env-file` para **CADA branch** (main + staging + preview + production):
639
-
640
- ```bash
641
- # para cada branch
642
- for branch in main staging production; do
643
- supabase link --project-ref "${branch}-project-ref"
644
- supabase secrets set --env-file "./supabase/.env.${branch}"
645
- done
646
- ```
647
-
648
- Documentar workflow no onboarding do projeto.
649
-
650
- ### Anti-pattern 3: Commitar `.env.keys` no git
651
-
652
- **Errado:** `.env.keys` aparece em `git status` e dev faz `git add` distraído:
653
-
654
- ```bash
655
- git status
656
- # Changes not staged for commit:
657
- # modified: supabase/.env.preview
658
- # modified: .env.keys ← BLOQUEANTE
659
- git add .
660
- git commit -m "feat: add preview secrets" # vazou a chave master
661
- git push
662
- ```
663
-
664
- **Por quê:** `.env.keys` é a chave de **decryption master** — com ela, qualquer um decripta `.env.preview`/`.env.production` e tem acesso a TODOS os secrets encrypted; equivalente a vazar password master + todos os tokens OAuth + todas as API keys de uma vez.
665
-
666
- **Certo:**
667
-
668
- ```bash
669
- # adicionar SEMPRE ao .gitignore — ANTES de qualquer set
670
- echo ".env.keys" >> .gitignore
671
- git add .gitignore
672
- git commit -m "chore: gitignore dotenvx decryption key"
673
- ```
674
-
675
- Se foi committed por engano:
676
-
677
- 1. `git filter-repo` (ou BFG) para limpar history
678
- 2. **Rotacionar TODOS os secrets encrypted imediatamente** — sem confiar que ninguém viu antes
679
- 3. Re-encrypt valores em `.env.preview`/`.env.production` com nova `.env.keys`
680
- 4. Force-push branches afetados
681
- 5. Notificar team + auditar acessos
682
-
683
- ### Anti-pattern 4: Confundir `env()` vs `encrypted:` syntax
684
-
685
- **Errado:** tentar combinar os dois prefixos:
686
-
687
- ```toml
688
- [auth.external.github]
689
- secret = "encrypted:env(GITHUB_SECRET)" # syntax inválida — mistura prefixos
690
- ```
691
-
692
- **Por quê:** Supabase CLI parser não combina os dois — valor literal `"encrypted:env(GITHUB_SECRET)"` é usado como string, OAuth callback falha com `invalid client_secret`.
693
-
694
- **Certo:** escolher UM:
695
-
696
- ```toml
697
- # Option A: env() resolve via env var
698
- [auth.external.github]
699
- secret = "env(GITHUB_SECRET)"
700
-
701
- # Option B: encrypted: via dotenvx decryption
702
- [auth.external.github]
703
- secret = "encrypted:LSi...payload-encrypted...=="
704
- ```
705
-
706
- Nunca combinar.
707
-
708
- ### Anti-pattern 5: Reusar `project_id` entre `[remotes]` blocks
709
-
710
- **Errado:**
711
-
712
- ```toml
713
- [remotes.staging]
714
- project_id = "main-project-ref" # ← mesmo ref do main
715
-
716
- [remotes.production]
717
- project_id = "main-project-ref" # ← mesmo ref do main
718
- ```
719
-
720
- **Por quê:** `[remotes.<name>]` deve apontar para branch **DEDICADO** criado via `supabase --experimental branches create`; usar mesmo `project_id` para múltiplos `[remotes]` causa configs sobrescritas no DAG step 4 (configure) — última definição vence, comportamento imprevisível.
721
-
722
- **Certo:** criar branch por ambiente + obter `project_id` único:
723
-
724
- ```bash
725
- supabase --experimental branches create staging --persistent
726
- supabase --experimental branches create production --persistent
727
- supabase --experimental branches list
728
- # BRANCH NAME BRANCH PROJECT ID
729
- # main main-project-ref
730
- # staging staging-dedicated-ref
731
- # production production-dedicated-ref
732
- ```
733
-
734
- ```toml
735
- [remotes.staging]
736
- project_id = "staging-dedicated-ref"
737
-
738
- [remotes.production]
739
- project_id = "production-dedicated-ref"
740
- ```
741
-
742
- ### Anti-pattern 6: Esperar `env()` em config.toml resolver para secrets do projeto
743
-
744
- **Errado:** setar secret via `supabase secrets set` e esperar que `config.toml` com `env()` resolva:
745
-
746
- ```bash
747
- # setar secret no projeto (runtime Edge Functions)
748
- supabase secrets set SENDGRID_API_KEY=sk-real-key
749
-
750
- # config.toml
751
- [edge_runtime.secrets]
752
- # expecta erradamente que o secret do projeto seja resolvido
753
- SENDGRID_API_KEY = "env(SENDGRID_API_KEY)"
754
- ```
755
-
756
- **Por quê:** `env()` em config.toml resolve para env var **do CLI local** (build-time), **NÃO para secrets do projeto Supabase** (runtime das Edge Functions). Se o shell que roda o CLI não tem `SENDGRID_API_KEY` exportado, resolve para string vazia → config quebrada.
757
-
758
- **Certo:**
759
-
760
- - **Para secrets de Edge Functions runtime:** `supabase secrets set` + `Deno.env.get("SENDGRID_API_KEY")` no código Deno
761
- - **Para config.toml build-time:** setar env var no shell antes de rodar CLI:
762
-
763
- ```bash
764
- export SENDGRID_API_KEY=sk-build-time-key
765
- supabase db push
766
- # config.toml com env(SENDGRID_API_KEY) resolve para "sk-build-time-key"
767
- ```
768
-
769
- Em workflow CI (GitHub Actions): expor secret no env do step:
770
-
771
- ```yaml
772
- - name: Push to Supabase
773
- env:
774
- SENDGRID_API_KEY: ${{ secrets.SENDGRID_API_KEY }}
775
- run: supabase db push
776
- ```
777
-
778
- ## Cross-suite integration (v1.27)
779
-
780
- Esta skill é par-conjugado com `supabase-branching-workflow` (Phase 149) — branching workflow descreve **quando** branches são criados; config-toml-remotes descreve **como** configurar.
781
-
782
- Cross-refs canônicas com outras skills v1.27 (Phases 150-153):
783
-
784
- - **supabase-branching-workflow** (Phase 149) — Deploy DAG step 4 (configure) lê `[remotes.<branch>]` block desta skill
785
- - **supabase-ci-cd-github-actions** (Phase 151, futura) — 8 workflows GitHub Actions que exportam env vars + rodam `supabase db push` com `--env-file` (cross-ref Pattern 3 + Pattern 4)
786
- - **supabase-pgtap-testing** (Phase 152, futura) — testes pgTAP que rodam em remote branches via `--db-url` derivada de `[remotes.<branch>]`
787
- - **supabase-migration-repair** (Phase 153, futura) — `migration repair` per `[remotes.<branch>]` quando drift detectado
788
-
789
- Base para agent novo v1.27:
790
-
791
- - **supabase-cicd-pipeline-implementer** (Phase 154, futura) — recebe spec via `Task()` e materializa `[remotes.<branch>]` blocks na config + GitHub Actions workflows com dotenvx integration
792
-
793
- Pattern de handoff cooperativo herdado v1.23-v1.26: **architect** projeta strategy → **cicd-pipeline-implementer** materializa → **release-pipeline-auditor** (v1.10) audita hermeticidade. Nenhum agente descarta upstream — handoff cooperativo SQL (princípio canônico v1.23).
794
-
795
- ## Ver também
796
-
797
- - [supabase-branching-workflow](../supabase-branching-workflow/SKILL.md) (v1.27, Phase 149) — pré-requisito conceitual; Deploy DAG step 4 (configure) aplica `[remotes]`
798
- - [supabase-ci-cd-github-actions](../supabase-ci-cd-github-actions/SKILL.md) (v1.27, Phase 151) — workflows GitHub Actions com `--env-file` + `supabase secrets set`
799
- - [supabase-pgtap-testing](../supabase-pgtap-testing/SKILL.md) (v1.27, Phase 152) — testes que rodam em remote branches via `--db-url`
800
- - [supabase-migration-repair](../supabase-migration-repair/SKILL.md) (v1.27, Phase 153) — `migration repair` per `[remotes.<branch>]`
801
- - [supabase-migrations](../supabase-migrations/SKILL.md) (v1.23) — migrations aplicadas no branch via `supabase db push --linked`
802
- - [supabase-edge-functions](../supabase-edge-functions/SKILL.md) — `Deno.env.get()` lê secrets setados via `supabase secrets set --env-file`
803
- - [supabase-auth-ssr](../supabase-auth-ssr/SKILL.md) — `auth.external.*.secret` encrypted fields usados no auth flow
804
- - [supabase-custom-claims-rbac](../supabase-custom-claims-rbac/SKILL.md) (v1.25) — `auth.hook.custom_access_token.secrets` é Auth Hook (Grupo 6)
805
- - [supabase-postgres-roles](../supabase-postgres-roles/SKILL.md) (v1.26) — cross-ref para system access via secrets DB (`db.root_key`, `db.vault`)
806
- - [glossário compartilhado](../_shared-supabase/glossary.md) — termos `[remotes]`, encrypted:, env(), dotenvx, .env.keys, .env.preview, designated secret fields, branch project_id
807
- - Doc oficial: [Branching Configuration](https://supabase.com/docs/guides/deployment/branching#configuration), [Config Reference](https://supabase.com/docs/guides/local-development/cli/config), [dotenvx](https://dotenvx.com/), [Auth Hooks](https://supabase.com/docs/guides/auth/auth-hooks)
1
+ ---
2
+ name: supabase-config-toml-remotes
3
+ description: Use ao configurar Supabase para branching — `[remotes.<name>]` block + branch-specific overrides + secrets per-branch (NÃO herdam) + dotenvx pattern (.env.keys + .env.preview encrypted) + 6…
4
+ ---
5
+
6
+ # Supabase — Config TOML & Remotes
7
+
8
+ ## Quando usar
9
+
10
+ Branching Supabase exige configuração per-branch via `supabase/config.toml` — blocos `[remotes.<name>]` declaram **overrides versionados em git** que o Deploy DAG step 4 (configure) aplica em cada branch.
11
+
12
+ Esta skill é par-conjugado com `supabase-branching-workflow` (Phase 149) — branching workflow descreve **quando** branches são criados; esta skill descreve **como** configurar.
13
+
14
+ Trigger phrases:
15
+
16
+ - "remotes block Supabase", "[remotes] config.toml"
17
+ - "branch-specific config Supabase", "config.toml staging override"
18
+ - "secrets per-branch Supabase", "supabase secrets set"
19
+ - "dotenvx Supabase", ".env.keys .env.preview"
20
+ - "encrypted: Supabase config", "env() vs encrypted: syntax"
21
+ - "Supabase encrypted fields", "auth.hook secrets encrypted"
22
+ - "designated secret fields"
23
+ - "branch project_id Supabase"
24
+
25
+ **Use APENAS para:**
26
+
27
+ - Configurar persistent branches (staging, QA, production) via `[remotes.<branch>]` block
28
+ - Materializar overrides per-ambiente (db.pool_size, api.max_rows, auth.external.*, edge_runtime.secrets)
29
+ - Gerenciar secrets per-branch via `supabase secrets set --env-file`
30
+ - Versionar secrets encrypted em git via dotenvx pattern (.env.keys + .env.preview/.env.production)
31
+
32
+ **NÃO use para:**
33
+
34
+ - Substituir secret vault corporativo (Vault, AWS Secrets Manager) — dotenvx é git-tracked encrypted; vault corporativo tem audit trail + rotation policies
35
+ - Gerenciar secrets de runtime de Edge Functions sem `supabase secrets set` — `env()` em config.toml é build-time do CLI, não runtime do projeto
36
+ - Versionar a chave de decryption (`.env.keys`) — NUNCA committar; é equivalente a vazar password master
37
+ - Apontar `[remotes.<name>]` para branch deletado — operações falham silenciosamente
38
+
39
+ ## Princípio canônico
40
+
41
+ Três princípios canônicos:
42
+
43
+ 1. **`config.toml` é source of truth versionado.** `[remotes.<branch>]` block declara overrides explícitos commitados em git — Deploy DAG step 4 (configure) re-aplica em cada deploy. Sem deriva entre o que está em git e o que está no branch.
44
+
45
+ 2. **dotenvx para secrets git-tracked.** `.env.keys` (decryption key, **SEMPRE gitignored**) + `.env.preview`/`.env.production` (encrypted values, committed em git). Permite versionar secrets sem expor — git history rastreia mudanças de secrets sem PII em plaintext.
46
+
47
+ 3. **Secrets NÃO herdam entre branches.** Cada branch tem credenciais únicas; criar persistent branch `staging` NÃO copia secrets do `main`. Reset manual via `supabase secrets set --env-file` para CADA branch — incluindo o branch `main` original.
48
+
49
+ ### Distinção canônica `env()` vs `encrypted:`
50
+
51
+ | | `env(VAR_NAME)` | `encrypted:<value>` |
52
+ |---|---|---|
53
+ | Resolução | Runtime CLI (build-time) | Decryption via `.env.keys` |
54
+ | Onde funciona | **Qualquer** field em config.toml | **APENAS** designated secret fields (Pattern 5) |
55
+ | Workflow | Setar env var no shell antes do CLI | Encriptar via `dotenvx set`, committed em git |
56
+ | Caveat | Resolve para env var **local** do CLI, NÃO para secrets do projeto Supabase (runtime das Edge Functions) | Em field **não-designated** é silent no-op (literal string usada como valor) |
57
+ | Caso de uso | Secrets em env vars do CI (GitHub Actions) | Secrets versionados encrypted em git via dotenvx |
58
+
59
+ ## Pattern 1: `[remotes]` block — referenciar branch existente (CFG-01)
60
+
61
+ `[remotes.<name>]` em `config.toml` declara que **este bloco se aplica APENAS ao branch nomeado** identificado pelo `project_id`.
62
+
63
+ ### Pré-requisito
64
+
65
+ Branch já criado (persistent via CLI ou preview via PR webhook):
66
+
67
+ ```bash
68
+ # criar persistent branch via CLI
69
+ supabase --experimental branches create staging --persistent
70
+
71
+ # (preview branches são criados automaticamente via GitHub PR — cross-ref skill supabase-branching-workflow Pattern 3)
72
+ ```
73
+
74
+ ### Workflow canônico
75
+
76
+ **Step 1: Obter `project_id` do branch:**
77
+
78
+ ```bash
79
+ supabase --experimental branches list
80
+
81
+ # output esperado:
82
+ # BRANCH NAME BRANCH PROJECT ID STATUS
83
+ # main main-project-ref active
84
+ # staging staging-dedicated-ref active
85
+ # pr-42-feature pr42-feature-ref active
86
+ ```
87
+
88
+ **Step 2: Adicionar `[remotes.<branch>]` block no `supabase/config.toml`:**
89
+
90
+ ```toml
91
+ [remotes.staging]
92
+ project_id = "staging-dedicated-ref"
93
+
94
+ [remotes.staging.db.seed]
95
+ enabled = true
96
+ sql_paths = ["./seeds/staging.sql"]
97
+ ```
98
+
99
+ **Step 3: Commitar `config.toml` em git → Deploy DAG step 4 (configure) aplica overrides no branch.**
100
+
101
+ ### Exemplo TOML — múltiplos branches
102
+
103
+ ```toml
104
+ # bloco base — aplica a TODOS os branches (incluindo main)
105
+ [db]
106
+ port = 54322
107
+ pool_size = 15
108
+
109
+ [api]
110
+ port = 54321
111
+ max_rows = 1000
112
+
113
+ # branch staging — overrides específicos
114
+ [remotes.staging]
115
+ project_id = "staging-dedicated-ref"
116
+
117
+ [remotes.staging.db.seed]
118
+ enabled = true
119
+ sql_paths = ["./seeds/staging.sql"]
120
+
121
+ # branch production — sem seeds em produção
122
+ [remotes.production]
123
+ project_id = "production-dedicated-ref"
124
+
125
+ [remotes.production.db.seed]
126
+ enabled = false
127
+ ```
128
+
129
+ ### Caveat — branch deletado
130
+
131
+ `project_id` deve ser de branch **existente**. Se branch foi deletado:
132
+
133
+ - Bloco `[remotes.<branch>]` continua válido sintaticamente
134
+ - CLI rejeita commands com erro `branch not found`
135
+ - DAG step 4 (configure) silenciosamente skip o branch deletado
136
+
137
+ **Mitigação:** revisão trimestral — `supabase --experimental branches list` + remover blocos `[remotes.<deleted>]` correspondentes.
138
+
139
+ ### Caveat — `project_id` único por bloco
140
+
141
+ Cada `[remotes.<name>]` deve apontar para **branch dedicado** criado especificamente. NÃO reutilizar `project_id` do `main` para `staging` (cross-ref Anti-pattern 5).
142
+
143
+ ## Pattern 2: Branch-specific configuration overrides (CFG-02)
144
+
145
+ Princípio: config base (sem `[remotes...]` prefix) aplica a TODOS os branches; `[remotes.<name>.<section>]` aplica override APENAS no branch nomeado.
146
+
147
+ ### Categorias de fields override-able (canônicas)
148
+
149
+ **db (database tuning):**
150
+
151
+ ```toml
152
+ [db]
153
+ port = 54322
154
+ pool_size = 15 # default
155
+
156
+ # staging override
157
+ [remotes.staging.db]
158
+ port = 54322 # mesma porta — só pool_size muda
159
+ pool_size = 25
160
+ ```
161
+
162
+ **api (PostgREST):**
163
+
164
+ ```toml
165
+ [api]
166
+ port = 54321
167
+ max_rows = 1000
168
+ schemas = ["public"]
169
+
170
+ # staging quer ver schema extensions para debug
171
+ [remotes.staging.api]
172
+ max_rows = 5000 # debug — limite maior
173
+ schemas = ["public", "extensions"]
174
+ ```
175
+
176
+ **db.seed:**
177
+
178
+ ```toml
179
+ # default — sem seed
180
+ [db.seed]
181
+ enabled = false
182
+ sql_paths = []
183
+
184
+ # staging — seed sintético para QA
185
+ [remotes.staging.db.seed]
186
+ enabled = true
187
+ sql_paths = ["./seeds/staging.sql"]
188
+
189
+ # preview — seed minimal para smoke tests
190
+ [remotes.preview.db.seed]
191
+ enabled = true
192
+ sql_paths = ["./seeds/preview-smoke.sql"]
193
+ ```
194
+
195
+ **auth.external.* (OAuth providers):**
196
+
197
+ ```toml
198
+ # production GitHub OAuth
199
+ [auth.external.github]
200
+ enabled = true
201
+ client_id = "Iv1.production-app-id"
202
+ secret = "encrypted:LSi...prod-github-secret-encrypted...=="
203
+
204
+ # staging GitHub OAuth — app diferente
205
+ [remotes.staging.auth.external.github]
206
+ enabled = true
207
+ client_id = "Iv1.staging-app-id"
208
+ secret = "encrypted:LSi...staging-github-secret-encrypted...=="
209
+ redirect_uri = "https://staging.example.com/auth/callback"
210
+ ```
211
+
212
+ **edge_runtime.secrets:**
213
+
214
+ ```toml
215
+ [edge_runtime.secrets]
216
+ SENDGRID_API_KEY = "encrypted:LSi...prod-sendgrid-encrypted...=="
217
+
218
+ # staging — SendGrid sandbox
219
+ [remotes.staging.edge_runtime.secrets]
220
+ SENDGRID_API_KEY = "encrypted:LSi...staging-sendgrid-encrypted...=="
221
+ SENDGRID_SANDBOX_MODE = "env(STAGING_SENDGRID_SANDBOX_MODE)"
222
+ ```
223
+
224
+ ### Tabela canônica de fields override-able
225
+
226
+ | Section | Fields | Caso de uso típico |
227
+ |---------|--------|---------------------|
228
+ | `db` | `port`, `pool_size` | Tuning pool size per ambiente (staging menor) |
229
+ | `api` | `port`, `max_rows`, `schemas` | Diferenciar response limits + schemas expostos |
230
+ | `db.seed` | `enabled`, `sql_paths` | Seeds diferentes por branch |
231
+ | `auth.external.<provider>` | `enabled`, `client_id`, `secret`, `redirect_uri` | OAuth keys per ambiente |
232
+ | `auth.email.smtp` | `host`, `port`, `user`, `pass` | SMTP staging vs produção |
233
+ | `auth.sms.<provider>` | `account_sid`, `auth_token`, etc. | SMS provider keys per ambiente |
234
+ | `edge_runtime.secrets.<KEY>` | custom env vars | API keys per branch (SendGrid, Stripe, OpenAI) |
235
+ | `studio.openai_api_key` | string | Key diferente para staging studio (lower limits) |
236
+
237
+ ### Caveat — merge behavior
238
+
239
+ `[remotes.staging.db]` com `pool_size = 25` NÃO sobrescreve `[db]` global completamente — apenas o field específico (`pool_size`). Outros fields do `[db]` global (port, etc.) continuam aplicados.
240
+
241
+ ```toml
242
+ # config base
243
+ [db]
244
+ port = 54322
245
+ pool_size = 15
246
+ shadow_port = 54320
247
+
248
+ # staging override — apenas pool_size muda
249
+ [remotes.staging.db]
250
+ pool_size = 25
251
+ # resultado em staging: port=54322, pool_size=25, shadow_port=54320 (mantidos da base)
252
+ ```
253
+
254
+ ### Caveat — re-deploy required
255
+
256
+ Alterações em `config.toml` precisam ser pushed para o branch — Deploy DAG step 4 (configure) só roda em novo deploy (push novo commit no PR ou re-run via Dashboard).
257
+
258
+ ## Pattern 3: Secrets management per-branch (CFG-03)
259
+
260
+ ### Caveat canônico — secrets NÃO herdam
261
+
262
+ > **Secrets NÃO herdam entre branches.** Criar persistent branch `staging` NÃO copia secrets do `main`. Cada branch precisa ter secrets setados separadamente.
263
+
264
+ Implicação prática:
265
+
266
+ - `Deno.env.get("SENDGRID_API_KEY")` em Edge Function no branch staging retorna `undefined` até `supabase secrets set` ser executado para o staging
267
+ - Esse comportamento é silent — sem warning no DAG, sem alert do CLI
268
+
269
+ ### CLI canônico
270
+
271
+ ```bash
272
+ # Set secrets a partir de .env file (recomendação canônica)
273
+ supabase secrets set --env-file ./supabase/.env
274
+
275
+ # Set secret individual
276
+ supabase secrets set SMTP_HOST=smtp.example.com
277
+
278
+ # Listar secrets do branch atual
279
+ supabase secrets list
280
+
281
+ # Remover secret
282
+ supabase secrets unset SMTP_HOST
283
+ ```
284
+
285
+ ### Workflow per-branch canônico
286
+
287
+ ```bash
288
+ # 1. criar staging branch
289
+ supabase --experimental branches create staging --persistent
290
+
291
+ # 2. obter project_id do staging
292
+ supabase --experimental branches list | grep staging
293
+ # output: staging staging-dedicated-ref active
294
+
295
+ # 3. link CLI para o branch staging
296
+ supabase link --project-ref staging-dedicated-ref
297
+
298
+ # 4. setar secrets DO STAGING (arquivo dedicado)
299
+ supabase secrets set --env-file ./supabase/.env.staging
300
+
301
+ # 5. validar — listar secrets do staging
302
+ supabase secrets list
303
+
304
+ # 6. voltar para main quando terminar
305
+ supabase link --project-ref main-project-ref
306
+ ```
307
+
308
+ ### Exemplo `.env.staging`
309
+
310
+ ```bash
311
+ # .env.staging — secrets específicos do branch staging
312
+ # Gitignored se não usa dotenvx (Pattern 4); encrypted se usa.
313
+ SMTP_HOST=smtp.staging.example.com
314
+ SMTP_USER=staging-user
315
+ SMTP_PASS=staging-pass
316
+ SENDGRID_API_KEY=SG.staging-api-key
317
+ OPENAI_API_KEY=sk-staging-openai-key
318
+ STRIPE_SECRET_KEY=sk_test_staging_stripe
319
+ ```
320
+
321
+ ### Caveat — secrets vs config.toml `env()`
322
+
323
+ Distinção CRÍTICA — fonte de confusão comum:
324
+
325
+ | | `supabase secrets set` | `env()` em config.toml |
326
+ |---|---|---|
327
+ | Resolvido | Runtime das **Edge Functions** | Build-time do **CLI local** |
328
+ | Acesso | `Deno.env.get("KEY")` no código Deno | Substituição literal no `config.toml` pré-deploy |
329
+ | Storage | Supabase backend (per-branch) | Env var do shell que rodou o CLI |
330
+ | Lifecycle | Persistido no branch | Volátil (só durante invocação do CLI) |
331
+
332
+ Exemplo concreto:
333
+
334
+ ```bash
335
+ # Setar secret no branch (runtime Edge Function)
336
+ supabase secrets set SENDGRID_API_KEY=sk-real-key
337
+ # → Deno.env.get("SENDGRID_API_KEY") em Edge Function retorna "sk-real-key"
338
+
339
+ # Setar env var local (build-time config.toml)
340
+ export SENDGRID_API_KEY=sk-different-key
341
+ supabase db push
342
+ # → config.toml com env(SENDGRID_API_KEY) resolve para "sk-different-key" (do shell)
343
+ # → Edge Function ainda retorna "sk-real-key" (do supabase secrets set anterior)
344
+ ```
345
+
346
+ ### Recomendação canônica
347
+
348
+ Usar **dotenvx pattern** (Pattern 4) para versionar secrets encrypted em git em vez de gerenciar `.env.staging` separadamente em cada máquina.
349
+
350
+ ## Pattern 4: dotenvx pattern + `encrypted:` vs `env()` syntax (CFG-04)
351
+
352
+ ### Princípio dotenvx
353
+
354
+ dotenvx ([dotenvx.com](https://dotenvx.com/)) é uma evolução de `dotenv` que permite **encryption symmetric** de valores no arquivo `.env`:
355
+
356
+ - Encrypted values podem ser committed em git (`.env.preview`, `.env.production`)
357
+ - Decryption key (`.env.keys`) **NUNCA é committed** — gitignored sempre
358
+ - Permite versionar secrets sem expor — git history rastreia mudanças de secrets sem PII em plaintext
359
+
360
+ ### Tabela canônica de file types (dotenvx convenção)
361
+
362
+ | File | Env | gitignore | Encrypted | Caso de uso |
363
+ |------|-----|-----------|-----------|-------------|
364
+ | `.env.keys` | All | **YES** (NUNCA committar) | No (key plaintext) | Decryption master key |
365
+ | `.env.local` | Local dev | YES | No (plaintext OK local) | Overrides de dev individual |
366
+ | `.env.production` | Production | No (committed) | YES | Secrets de produção encrypted |
367
+ | `.env.preview` | Branches preview | No (committed) | YES | Secrets de preview branches encrypted |
368
+ | `.env` | Any (fallback) | Maybe | YES | Default file (custom) |
369
+
370
+ **Atenção canônica:** `.env.keys` em `.gitignore` é obrigação canônica — sem isso, o pattern dotenvx é equivalente a commitar secrets plaintext.
371
+
372
+ ### Workflow canônico dotenvx
373
+
374
+ ```bash
375
+ # 1. instalar dotenvx (devDependency)
376
+ npm install -D @dotenvx/dotenvx
377
+
378
+ # 2. adicionar .env.keys ao .gitignore (BLOQUEANTE — fazer ANTES de qualquer set)
379
+ echo ".env.keys" >> .gitignore
380
+ git add .gitignore
381
+ git commit -m "chore: gitignore dotenvx decryption key"
382
+
383
+ # 3. encrypted set — gera .env.keys automaticamente na primeira vez
384
+ npx @dotenvx/dotenvx set SUPABASE_AUTH_EXTERNAL_GITHUB_SECRET "ghs_real_secret" -f supabase/.env.preview
385
+ # Output:
386
+ # set SUPABASE_AUTH_EXTERNAL_GITHUB_SECRET (encrypted) (.env.preview)
387
+ # wrote new public-private encryption keys to .env.keys
388
+
389
+ # 4. commitar .env.preview (encrypted) + verificar .env.keys NÃO foi committed
390
+ git status
391
+ # modified: supabase/.env.preview
392
+ # (.env.keys NÃO deve aparecer)
393
+ git add supabase/.env.preview
394
+ git commit -m "feat: add encrypted GitHub OAuth secret for preview"
395
+
396
+ # 5. usar com supabase CLI (carregar via --env-file)
397
+ npx supabase secrets set --env-file supabase/.env.keys
398
+ # ou em workflow CI (decripta + roda CLI):
399
+ npx @dotenvx/dotenvx run -- supabase secrets set --env-file supabase/.env.preview
400
+ ```
401
+
402
+ ### Sintaxes em `config.toml`
403
+
404
+ **Option A: `encrypted:<value>` directly em designated secret field:**
405
+
406
+ ```toml
407
+ [auth.external.github]
408
+ enabled = true
409
+ client_id = "Iv1.app-id-public"
410
+ # secret é designated secret field (Pattern 5 Grupo 8) — encrypted: é decriptado via .env.keys
411
+ secret = "encrypted:LSiME...github-secret-encrypted-payload...=="
412
+ ```
413
+
414
+ **Option B: `env(VAR_NAME)` para resolver via env var (qualquer field):**
415
+
416
+ ```toml
417
+ [auth.external.github]
418
+ enabled = true
419
+ client_id = "env(SUPABASE_AUTH_EXTERNAL_GITHUB_CLIENT_ID)"
420
+ secret = "env(SUPABASE_AUTH_EXTERNAL_GITHUB_SECRET)"
421
+ ```
422
+
423
+ ### Warning canônico — `encrypted:` é restrito
424
+
425
+ > **`encrypted:` syntax SÓ funciona em designated secret fields** (Pattern 5 — 6 grupos canônicos). Em outros campos não decripta silenciosamente — o valor literal `"encrypted:LSiME..."` é usado como string, expondo o payload encrypted como se fosse plaintext.
426
+
427
+ Exemplo concreto do falso silencioso:
428
+
429
+ ```toml
430
+ # ERRADO — auth.email.smtp.host NÃO é designated secret field
431
+ [auth.email.smtp]
432
+ host = "encrypted:LSi...wrong...==" # ← silent no-op
433
+ # resultado: SMTP tenta conectar em host literal "encrypted:LSi...wrong...==" → DNS fail
434
+
435
+ # CERTO — auth.email.smtp.pass É designated (Pattern 5 Grupo 4)
436
+ [auth.email.smtp]
437
+ host = "smtp.example.com" # plain
438
+ pass = "encrypted:LSi...correct-pass...==" # ← decriptado
439
+ ```
440
+
441
+ ### Quando usar qual
442
+
443
+ - **`encrypted:`** — quando quer versionar o secret **encrypted em git** (workflow dotenvx); aplicar APENAS em fields designados (Pattern 5)
444
+ - **`env()`** — quando secrets vivem em env vars do CI/local; works em **qualquer field**; flexibilidade ao custo de não versionar em git (rotação via update env var no CI)
445
+
446
+ Recomendação canônica para teams maduros: `encrypted:` em produção (auditável via git history) + `env()` em dev local (volátil).
447
+
448
+ ## Pattern 5: 6 grupos de encrypted fields canônicos (CFG-05)
449
+
450
+ Princípio: apenas estes fields aceitam `encrypted:<value>` syntax — qualquer outro field é **silent no-op** (cross-ref Pattern 4 Warning).
451
+
452
+ ### Lista canônica COMPLETA dos 6 grupos lógicos
453
+
454
+ A documentação Supabase agrupa estes como **6 grupos lógicos** (Studio, Database, Auth Core/Email/Captcha/Hooks/SMS/External, Edge Runtime) — apresentamos expandido para máxima clareza por subcategoria.
455
+
456
+ ### Grupo 1: Studio
457
+
458
+ | Field | Caso de uso |
459
+ |-------|-------------|
460
+ | `studio.openai_api_key` | Studio AI features (SQL suggestions, schema generation) |
461
+
462
+ ### Grupo 2: Database
463
+
464
+ | Field | Caso de uso |
465
+ |-------|-------------|
466
+ | `db.root_key` | Root key para encryption-at-rest (Vault) |
467
+ | `db.vault.*` (todas subkeys) | Supabase Vault — encryption keys gerenciadas |
468
+
469
+ ### Grupo 3: Auth Core
470
+
471
+ | Field | Caso de uso |
472
+ |-------|-------------|
473
+ | `auth.publishable_key` | API publishable key (substitui anon key v2) |
474
+ | `auth.secret_key` | API secret key (substitui service_role key v2) |
475
+ | `auth.jwt_secret` | JWT signing secret (HS256) |
476
+
477
+ ### Grupo 4: Auth Email
478
+
479
+ | Field | Caso de uso |
480
+ |-------|-------------|
481
+ | `auth.email.smtp.pass` | Password do SMTP server (SendGrid, AWS SES, Mailgun, etc.) |
482
+
483
+ ### Grupo 5: Auth Captcha
484
+
485
+ | Field | Caso de uso |
486
+ |-------|-------------|
487
+ | `auth.captcha.secret` | hCaptcha ou Turnstile secret key |
488
+
489
+ ### Grupo 6: Auth Hooks
490
+
491
+ Todos os 6 Auth Hooks (cross-ref skill `supabase-custom-claims-rbac` v1.25):
492
+
493
+ | Field | Caso de uso |
494
+ |-------|-------------|
495
+ | `auth.hook.mfa_verification_attempt.secrets` | Custom MFA verification hook |
496
+ | `auth.hook.password_verification_attempt.secrets` | Custom password verification hook |
497
+ | `auth.hook.custom_access_token.secrets` | Custom Access Token Auth Hook (RBAC v1.25) |
498
+ | `auth.hook.send_sms.secrets` | Custom SMS sender hook |
499
+ | `auth.hook.send_email.secrets` | Custom email sender hook |
500
+ | `auth.hook.before_user_created.secrets` | Hook para validar/rejeitar signup |
501
+
502
+ ### Grupo 7: Auth SMS providers
503
+
504
+ 5 providers SMS canônicos:
505
+
506
+ | Field | Caso de uso |
507
+ |-------|-------------|
508
+ | `auth.sms.twilio.auth_token` | Twilio SMS provider |
509
+ | `auth.sms.twilio_verify.auth_token` | Twilio Verify (MFA) |
510
+ | `auth.sms.messagebird.access_key` | MessageBird provider |
511
+ | `auth.sms.textlocal.api_key` | Textlocal (UK provider) |
512
+ | `auth.sms.vonage.api_secret` | Vonage (ex-Nexmo) |
513
+
514
+ ### Grupo 8: Auth External providers
515
+
516
+ | Field | Caso de uso |
517
+ |-------|-------------|
518
+ | `auth.external.<provider>.secret` | Qualquer OAuth provider — github, google, facebook, apple, twitter, discord, gitlab, bitbucket, azure, linkedin, notion, slack, spotify, twitch, kakao, keycloak, workos, zoom, figma, fly |
519
+
520
+ ### Grupo 9: Edge Runtime
521
+
522
+ | Field | Caso de uso |
523
+ |-------|-------------|
524
+ | `edge_runtime.secrets.*` (todas subkeys) | Env vars custom para Edge Functions (SENDGRID, STRIPE, OPENAI, etc.) |
525
+
526
+ ### Exemplo TOML completo cobrindo múltiplos grupos
527
+
528
+ ```toml
529
+ # Grupo 1: Studio
530
+ [studio]
531
+ openai_api_key = "encrypted:LSi...studio-key-encrypted...=="
532
+
533
+ # Grupo 2: Database (Vault)
534
+ [db.vault]
535
+ secret_master_key = "encrypted:LSi...vault-master-encrypted...=="
536
+
537
+ # Grupo 3: Auth Core
538
+ [auth]
539
+ jwt_secret = "encrypted:LSi...jwt-secret-encrypted...=="
540
+ secret_key = "encrypted:LSi...secret-key-encrypted...=="
541
+
542
+ # Grupo 4: Auth Email
543
+ [auth.email.smtp]
544
+ host = "smtp.sendgrid.net"
545
+ port = 587
546
+ user = "apikey"
547
+ pass = "encrypted:LSi...smtp-pass-encrypted...=="
548
+
549
+ # Grupo 5: Auth Captcha
550
+ [auth.captcha]
551
+ enabled = true
552
+ provider = "hcaptcha"
553
+ secret = "encrypted:LSi...captcha-secret-encrypted...=="
554
+
555
+ # Grupo 6: Auth Hooks
556
+ [auth.hook.custom_access_token]
557
+ enabled = true
558
+ uri = "pg-functions://postgres/auth/custom_access_token_hook"
559
+ secrets = "encrypted:LSi...hook-secret-encrypted...=="
560
+
561
+ [auth.hook.send_email]
562
+ enabled = true
563
+ uri = "https://example.com/auth/send-email-hook"
564
+ secrets = "encrypted:LSi...email-hook-secret-encrypted...=="
565
+
566
+ # Grupo 7: Auth SMS (Twilio)
567
+ [auth.sms.twilio]
568
+ enabled = true
569
+ account_sid = "ACxxxxxxxxxxxx"
570
+ message_service_sid = "MGxxxxxxxxxxxx"
571
+ auth_token = "encrypted:LSi...twilio-token-encrypted...=="
572
+
573
+ # Grupo 8: Auth External (GitHub OAuth)
574
+ [auth.external.github]
575
+ enabled = true
576
+ client_id = "Iv1.xxxxxxx"
577
+ secret = "encrypted:LSi...github-secret-encrypted...=="
578
+
579
+ # Grupo 9: Edge Runtime
580
+ [edge_runtime.secrets]
581
+ OPENAI_API_KEY = "encrypted:LSi...openai-edge-encrypted...=="
582
+ SENDGRID_API_KEY = "encrypted:LSi...sendgrid-edge-encrypted...=="
583
+ STRIPE_SECRET_KEY = "encrypted:LSi...stripe-edge-encrypted...=="
584
+ ```
585
+
586
+ ### Caveat — lista pode evoluir com versões do CLI
587
+
588
+ A lista de designated secret fields pode evoluir com novas versões do Supabase CLI (novos providers OAuth, novos Auth Hooks, etc.). Para refresh periódico:
589
+
590
+ ```bash
591
+ # verificar versão do CLI
592
+ supabase --version
593
+
594
+ # consultar doc oficial:
595
+ # https://supabase.com/docs/guides/local-development/cli/config
596
+ ```
597
+
598
+ **Recomendação canônica:** review trimestral da lista vs doc oficial — Supabase publica updates regularmente.
599
+
600
+ ## Anti-patterns
601
+
602
+ ### Anti-pattern 1: Usar `encrypted:` em field não-designated
603
+
604
+ **Errado:**
605
+
606
+ ```toml
607
+ [auth.email.smtp]
608
+ host = "encrypted:LSi...wrong-host...==" # smtp.host NÃO é designated
609
+ port = 587
610
+ ```
611
+
612
+ **Por quê:** valor literal é usado como string — SMTP tenta conectar em host literal `"encrypted:LSi...=="`, DNS lookup falha silenciosamente, emails não são enviados, sem erro claro no log.
613
+
614
+ **Certo:** consultar Pattern 5 — usar `encrypted:` APENAS nos grupos canônicos. Para `auth.email.smtp.host` use plaintext (não é secret) ou `env(SMTP_HOST)`:
615
+
616
+ ```toml
617
+ [auth.email.smtp]
618
+ host = "smtp.sendgrid.net" # plaintext OK (não é secret)
619
+ port = 587
620
+ user = "apikey"
621
+ pass = "encrypted:LSi...correct-pass...==" # designated secret field
622
+ ```
623
+
624
+ ### Anti-pattern 2: Assumir secrets herdam entre branches
625
+
626
+ **Errado:** criar `staging` branch e assumir que `SENDGRID_API_KEY` do `main` está disponível.
627
+
628
+ ```bash
629
+ supabase --experimental branches create staging --persistent
630
+ # (assume erradamente que secrets do main foram copiados)
631
+
632
+ # Edge Function no staging — falha
633
+ const apiKey = Deno.env.get("SENDGRID_API_KEY"); // undefined
634
+ ```
635
+
636
+ **Por quê:** secrets são **per-branch** — staging tem env vars vazias até `supabase secrets set` rodar separadamente; Edge Functions retornam `undefined`; código quebra sem erro claro no DAG.
637
+
638
+ **Certo:** rodar `supabase secrets set --env-file` para **CADA branch** (main + staging + preview + production):
639
+
640
+ ```bash
641
+ # para cada branch
642
+ for branch in main staging production; do
643
+ supabase link --project-ref "${branch}-project-ref"
644
+ supabase secrets set --env-file "./supabase/.env.${branch}"
645
+ done
646
+ ```
647
+
648
+ Documentar workflow no onboarding do projeto.
649
+
650
+ ### Anti-pattern 3: Commitar `.env.keys` no git
651
+
652
+ **Errado:** `.env.keys` aparece em `git status` e dev faz `git add` distraído:
653
+
654
+ ```bash
655
+ git status
656
+ # Changes not staged for commit:
657
+ # modified: supabase/.env.preview
658
+ # modified: .env.keys ← BLOQUEANTE
659
+ git add .
660
+ git commit -m "feat: add preview secrets" # vazou a chave master
661
+ git push
662
+ ```
663
+
664
+ **Por quê:** `.env.keys` é a chave de **decryption master** — com ela, qualquer um decripta `.env.preview`/`.env.production` e tem acesso a TODOS os secrets encrypted; equivalente a vazar password master + todos os tokens OAuth + todas as API keys de uma vez.
665
+
666
+ **Certo:**
667
+
668
+ ```bash
669
+ # adicionar SEMPRE ao .gitignore — ANTES de qualquer set
670
+ echo ".env.keys" >> .gitignore
671
+ git add .gitignore
672
+ git commit -m "chore: gitignore dotenvx decryption key"
673
+ ```
674
+
675
+ Se foi committed por engano:
676
+
677
+ 1. `git filter-repo` (ou BFG) para limpar history
678
+ 2. **Rotacionar TODOS os secrets encrypted imediatamente** — sem confiar que ninguém viu antes
679
+ 3. Re-encrypt valores em `.env.preview`/`.env.production` com nova `.env.keys`
680
+ 4. Force-push branches afetados
681
+ 5. Notificar team + auditar acessos
682
+
683
+ ### Anti-pattern 4: Confundir `env()` vs `encrypted:` syntax
684
+
685
+ **Errado:** tentar combinar os dois prefixos:
686
+
687
+ ```toml
688
+ [auth.external.github]
689
+ secret = "encrypted:env(GITHUB_SECRET)" # syntax inválida — mistura prefixos
690
+ ```
691
+
692
+ **Por quê:** Supabase CLI parser não combina os dois — valor literal `"encrypted:env(GITHUB_SECRET)"` é usado como string, OAuth callback falha com `invalid client_secret`.
693
+
694
+ **Certo:** escolher UM:
695
+
696
+ ```toml
697
+ # Option A: env() resolve via env var
698
+ [auth.external.github]
699
+ secret = "env(GITHUB_SECRET)"
700
+
701
+ # Option B: encrypted: via dotenvx decryption
702
+ [auth.external.github]
703
+ secret = "encrypted:LSi...payload-encrypted...=="
704
+ ```
705
+
706
+ Nunca combinar.
707
+
708
+ ### Anti-pattern 5: Reusar `project_id` entre `[remotes]` blocks
709
+
710
+ **Errado:**
711
+
712
+ ```toml
713
+ [remotes.staging]
714
+ project_id = "main-project-ref" # ← mesmo ref do main
715
+
716
+ [remotes.production]
717
+ project_id = "main-project-ref" # ← mesmo ref do main
718
+ ```
719
+
720
+ **Por quê:** `[remotes.<name>]` deve apontar para branch **DEDICADO** criado via `supabase --experimental branches create`; usar mesmo `project_id` para múltiplos `[remotes]` causa configs sobrescritas no DAG step 4 (configure) — última definição vence, comportamento imprevisível.
721
+
722
+ **Certo:** criar branch por ambiente + obter `project_id` único:
723
+
724
+ ```bash
725
+ supabase --experimental branches create staging --persistent
726
+ supabase --experimental branches create production --persistent
727
+ supabase --experimental branches list
728
+ # BRANCH NAME BRANCH PROJECT ID
729
+ # main main-project-ref
730
+ # staging staging-dedicated-ref
731
+ # production production-dedicated-ref
732
+ ```
733
+
734
+ ```toml
735
+ [remotes.staging]
736
+ project_id = "staging-dedicated-ref"
737
+
738
+ [remotes.production]
739
+ project_id = "production-dedicated-ref"
740
+ ```
741
+
742
+ ### Anti-pattern 6: Esperar `env()` em config.toml resolver para secrets do projeto
743
+
744
+ **Errado:** setar secret via `supabase secrets set` e esperar que `config.toml` com `env()` resolva:
745
+
746
+ ```bash
747
+ # setar secret no projeto (runtime Edge Functions)
748
+ supabase secrets set SENDGRID_API_KEY=sk-real-key
749
+
750
+ # config.toml
751
+ [edge_runtime.secrets]
752
+ # expecta erradamente que o secret do projeto seja resolvido
753
+ SENDGRID_API_KEY = "env(SENDGRID_API_KEY)"
754
+ ```
755
+
756
+ **Por quê:** `env()` em config.toml resolve para env var **do CLI local** (build-time), **NÃO para secrets do projeto Supabase** (runtime das Edge Functions). Se o shell que roda o CLI não tem `SENDGRID_API_KEY` exportado, resolve para string vazia → config quebrada.
757
+
758
+ **Certo:**
759
+
760
+ - **Para secrets de Edge Functions runtime:** `supabase secrets set` + `Deno.env.get("SENDGRID_API_KEY")` no código Deno
761
+ - **Para config.toml build-time:** setar env var no shell antes de rodar CLI:
762
+
763
+ ```bash
764
+ export SENDGRID_API_KEY=sk-build-time-key
765
+ supabase db push
766
+ # config.toml com env(SENDGRID_API_KEY) resolve para "sk-build-time-key"
767
+ ```
768
+
769
+ Em workflow CI (GitHub Actions): expor secret no env do step:
770
+
771
+ ```yaml
772
+ - name: Push to Supabase
773
+ env:
774
+ SENDGRID_API_KEY: ${{ secrets.SENDGRID_API_KEY }}
775
+ run: supabase db push
776
+ ```
777
+
778
+ ## Cross-suite integration (v1.27)
779
+
780
+ Esta skill é par-conjugado com `supabase-branching-workflow` (Phase 149) — branching workflow descreve **quando** branches são criados; config-toml-remotes descreve **como** configurar.
781
+
782
+ Cross-refs canônicas com outras skills v1.27 (Phases 150-153):
783
+
784
+ - **supabase-branching-workflow** (Phase 149) — Deploy DAG step 4 (configure) lê `[remotes.<branch>]` block desta skill
785
+ - **supabase-ci-cd-github-actions** (Phase 151, futura) — 8 workflows GitHub Actions que exportam env vars + rodam `supabase db push` com `--env-file` (cross-ref Pattern 3 + Pattern 4)
786
+ - **supabase-pgtap-testing** (Phase 152, futura) — testes pgTAP que rodam em remote branches via `--db-url` derivada de `[remotes.<branch>]`
787
+ - **supabase-migration-repair** (Phase 153, futura) — `migration repair` per `[remotes.<branch>]` quando drift detectado
788
+
789
+ Base para agent novo v1.27:
790
+
791
+ - **supabase-cicd-pipeline-implementer** (Phase 154, futura) — recebe spec via `Task()` e materializa `[remotes.<branch>]` blocks na config + GitHub Actions workflows com dotenvx integration
792
+
793
+ Pattern de handoff cooperativo herdado v1.23-v1.26: **architect** projeta strategy → **cicd-pipeline-implementer** materializa → **release-pipeline-auditor** (v1.10) audita hermeticidade. Nenhum agente descarta upstream — handoff cooperativo SQL (princípio canônico v1.23).
794
+
795
+ ## Ver também
796
+
797
+ - [supabase-branching-workflow](../supabase-branching-workflow/SKILL.md) (v1.27, Phase 149) — pré-requisito conceitual; Deploy DAG step 4 (configure) aplica `[remotes]`
798
+ - [supabase-ci-cd-github-actions](../supabase-ci-cd-github-actions/SKILL.md) (v1.27, Phase 151) — workflows GitHub Actions com `--env-file` + `supabase secrets set`
799
+ - [supabase-pgtap-testing](../supabase-pgtap-testing/SKILL.md) (v1.27, Phase 152) — testes que rodam em remote branches via `--db-url`
800
+ - [supabase-migration-repair](../supabase-migration-repair/SKILL.md) (v1.27, Phase 153) — `migration repair` per `[remotes.<branch>]`
801
+ - [supabase-migrations](../supabase-migrations/SKILL.md) (v1.23) — migrations aplicadas no branch via `supabase db push --linked`
802
+ - [supabase-edge-functions](../supabase-edge-functions/SKILL.md) — `Deno.env.get()` lê secrets setados via `supabase secrets set --env-file`
803
+ - [supabase-auth-ssr](../supabase-auth-ssr/SKILL.md) — `auth.external.*.secret` encrypted fields usados no auth flow
804
+ - [supabase-custom-claims-rbac](../supabase-custom-claims-rbac/SKILL.md) (v1.25) — `auth.hook.custom_access_token.secrets` é Auth Hook (Grupo 6)
805
+ - [supabase-postgres-roles](../supabase-postgres-roles/SKILL.md) (v1.26) — cross-ref para system access via secrets DB (`db.root_key`, `db.vault`)
806
+ - [glossário compartilhado](../_shared-supabase/glossary.md) — termos `[remotes]`, encrypted:, env(), dotenvx, .env.keys, .env.preview, designated secret fields, branch project_id
807
+ - Doc oficial: [Branching Configuration](https://supabase.com/docs/guides/deployment/branching#configuration), [Config Reference](https://supabase.com/docs/guides/local-development/cli/config), [dotenvx](https://dotenvx.com/), [Auth Hooks](https://supabase.com/docs/guides/auth/auth-hooks)