@luanpdd/kit-mcp 1.33.0 → 1.34.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (376) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +168 -168
  3. package/gates/agent-no-recursive-dispatch.md +84 -84
  4. package/kit/COMANDOS.md +138 -138
  5. package/kit/COMPATIBILITY.md +70 -70
  6. package/kit/README.md +76 -76
  7. package/kit/agents/advisor-researcher.md +109 -109
  8. package/kit/agents/ai-mutation-tester.md +289 -289
  9. package/kit/agents/assumptions-analyzer.md +110 -110
  10. package/kit/agents/audit-log-implementer.md +314 -314
  11. package/kit/agents/auditor-consistencia-isolamento.md +414 -414
  12. package/kit/agents/b2b-saas-architect.md +157 -157
  13. package/kit/agents/burn-rate-forecaster.md +153 -153
  14. package/kit/agents/cascading-failures-auditor.md +299 -299
  15. package/kit/agents/codebase-mapper.md +769 -769
  16. package/kit/agents/crm-pipeline-implementer.md +257 -257
  17. package/kit/agents/debugger.md +814 -814
  18. package/kit/agents/designer-ui.md +216 -216
  19. package/kit/agents/detector-tenant-quente.md +338 -338
  20. package/kit/agents/evolution-go-integrator.md +201 -201
  21. package/kit/agents/example-reviewer.md +22 -22
  22. package/kit/agents/executor.md +565 -565
  23. package/kit/agents/golden-signals-instrumenter.md +232 -232
  24. package/kit/agents/incident-investigator.md +238 -238
  25. package/kit/agents/integration-checker.md +203 -203
  26. package/kit/agents/invite-flow-implementer.md +190 -190
  27. package/kit/agents/legacy-characterizer.md +369 -369
  28. package/kit/agents/lgpd-compliance-auditor.md +296 -296
  29. package/kit/agents/load-shedding-instrumenter.md +290 -290
  30. package/kit/agents/multi-tenant-isolation-auditor.md +254 -254
  31. package/kit/agents/multi-tenant-rls-writer.md +341 -341
  32. package/kit/agents/nyquist-auditor.md +181 -181
  33. package/kit/agents/observability-coverage-auditor.md +316 -316
  34. package/kit/agents/observability-instrumenter.md +191 -191
  35. package/kit/agents/omm-auditor.md +291 -291
  36. package/kit/agents/org-onboarding-implementer.md +224 -224
  37. package/kit/agents/payload-capture-instrumenter.md +274 -274
  38. package/kit/agents/phase-researcher.md +697 -697
  39. package/kit/agents/plan-checker.md +275 -275
  40. package/kit/agents/planner.md +923 -923
  41. package/kit/agents/postmortem-writer.md +273 -273
  42. package/kit/agents/project-researcher.md +653 -653
  43. package/kit/agents/prr-conductor.md +287 -287
  44. package/kit/agents/refactor-safety-auditor.md +405 -405
  45. package/kit/agents/release-pipeline-auditor.md +364 -364
  46. package/kit/agents/research-synthesizer.md +246 -246
  47. package/kit/agents/roadmapper.md +678 -678
  48. package/kit/agents/schema-checker.md +160 -160
  49. package/kit/agents/seam-finder.md +360 -360
  50. package/kit/agents/shotgun-surgery-detector.md +350 -350
  51. package/kit/agents/slo-engineer.md +217 -217
  52. package/kit/agents/storytelling-analyst.md +300 -300
  53. package/kit/agents/supabase-architect.md +249 -249
  54. package/kit/agents/supabase-auth-bootstrapper.md +400 -400
  55. package/kit/agents/supabase-auth-hook-writer.md +418 -418
  56. package/kit/agents/supabase-branching-architect.md +563 -563
  57. package/kit/agents/supabase-cicd-pipeline-implementer.md +778 -778
  58. package/kit/agents/supabase-column-privileges-writer.md +400 -400
  59. package/kit/agents/supabase-edge-fn-tester.md +288 -288
  60. package/kit/agents/supabase-edge-fn-writer.md +341 -341
  61. package/kit/agents/supabase-mfa-implementer.md +439 -439
  62. package/kit/agents/supabase-migration-writer.md +386 -386
  63. package/kit/agents/supabase-oauth-server-implementer.md +507 -507
  64. package/kit/agents/supabase-rbac-implementer.md +393 -393
  65. package/kit/agents/supabase-realtime-implementer.md +364 -364
  66. package/kit/agents/supabase-rls-hardener.md +522 -522
  67. package/kit/agents/supabase-rls-writer.md +324 -324
  68. package/kit/agents/supabase-roles-implementer.md +356 -356
  69. package/kit/agents/supabase-social-auth-implementer.md +451 -451
  70. package/kit/agents/supabase-sso-saml-architect.md +549 -549
  71. package/kit/agents/supabase-storage-implementer.md +407 -407
  72. package/kit/agents/super-admin-implementer.md +282 -282
  73. package/kit/agents/toil-auditor.md +268 -268
  74. package/kit/agents/ui-auditor.md +438 -438
  75. package/kit/agents/ui-checker.md +305 -305
  76. package/kit/agents/ui-researcher.md +356 -356
  77. package/kit/agents/user-profiler.md +176 -176
  78. package/kit/agents/validador-evolucao-schema.md +336 -336
  79. package/kit/agents/verifier.md +729 -729
  80. package/kit/commands/adicionar-backlog.md +75 -75
  81. package/kit/commands/adicionar-fase.md +42 -42
  82. package/kit/commands/adicionar-tarefa.md +45 -45
  83. package/kit/commands/adicionar-testes.md +41 -41
  84. package/kit/commands/ajuda.md +21 -21
  85. package/kit/commands/atualizar.md +37 -37
  86. package/kit/commands/auditar-cascading.md +111 -111
  87. package/kit/commands/auditar-marco.md +179 -179
  88. package/kit/commands/auditar-observabilidade-cobertura-workflow.md +121 -0
  89. package/kit/commands/auditar-observabilidade-cobertura.md +183 -183
  90. package/kit/commands/auditar-refactor.md +219 -219
  91. package/kit/commands/auditar-release.md +109 -109
  92. package/kit/commands/auditar-uat.md +23 -23
  93. package/kit/commands/autonomo.md +40 -40
  94. package/kit/commands/branch-pr.md +24 -24
  95. package/kit/commands/burn-rate-status.md +408 -408
  96. package/kit/commands/capturar-payloads.md +193 -193
  97. package/kit/commands/caracterizar.md +212 -212
  98. package/kit/commands/concluir-marco.md +247 -247
  99. package/kit/commands/configuracoes.md +36 -36
  100. package/kit/commands/dados-distribuidos.md +188 -188
  101. package/kit/commands/definir-perfil.md +10 -10
  102. package/kit/commands/depurar.md +190 -190
  103. package/kit/commands/detectar-duplicacao.md +197 -197
  104. package/kit/commands/discutir-fase.md +131 -131
  105. package/kit/commands/encontrar-seams.md +136 -136
  106. package/kit/commands/entrar-discord.md +17 -17
  107. package/kit/commands/estatisticas.md +18 -18
  108. package/kit/commands/example-greeting.md +33 -33
  109. package/kit/commands/executar-fase.md +58 -58
  110. package/kit/commands/expresso.md +56 -56
  111. package/kit/commands/fase-ui.md +34 -34
  112. package/kit/commands/fazer.md +57 -57
  113. package/kit/commands/fio.md +125 -125
  114. package/kit/commands/fluxos-trabalho.md +64 -64
  115. package/kit/commands/forense.md +176 -176
  116. package/kit/commands/gerenciador.md +38 -38
  117. package/kit/commands/inserir-fase.md +31 -31
  118. package/kit/commands/legacy.md +263 -263
  119. package/kit/commands/limpeza.md +17 -17
  120. package/kit/commands/listar-hipoteses-fase.md +45 -45
  121. package/kit/commands/listar-workspaces.md +18 -18
  122. package/kit/commands/load-shedding.md +117 -117
  123. package/kit/commands/mapear-codebase.md +70 -70
  124. package/kit/commands/multi-tenant.md +163 -163
  125. package/kit/commands/nota.md +33 -33
  126. package/kit/commands/novo-marco.md +43 -43
  127. package/kit/commands/novo-projeto.md +41 -41
  128. package/kit/commands/novo-workspace.md +43 -43
  129. package/kit/commands/pausar-trabalho.md +37 -37
  130. package/kit/commands/perfil-usuario.md +45 -45
  131. package/kit/commands/pesquisar-fase.md +195 -195
  132. package/kit/commands/planejar-fase.md +67 -67
  133. package/kit/commands/planejar-lacunas.md +33 -33
  134. package/kit/commands/plantar-ideia.md +25 -25
  135. package/kit/commands/progresso.md +24 -24
  136. package/kit/commands/proximo.md +30 -30
  137. package/kit/commands/publicar.md +490 -490
  138. package/kit/commands/rapido.md +35 -35
  139. package/kit/commands/reaplicar-patches.md +124 -124
  140. package/kit/commands/refactor-seguro.md +321 -321
  141. package/kit/commands/relatorio-sessao.md +19 -19
  142. package/kit/commands/remover-fase.md +31 -31
  143. package/kit/commands/remover-workspace.md +26 -26
  144. package/kit/commands/resumo-marco.md +50 -50
  145. package/kit/commands/retomar-trabalho.md +40 -40
  146. package/kit/commands/revisar-backlog.md +60 -60
  147. package/kit/commands/revisar-ui.md +32 -32
  148. package/kit/commands/revisar.md +37 -37
  149. package/kit/commands/saude.md +21 -21
  150. package/kit/commands/setup-notion.md +93 -93
  151. package/kit/commands/storytelling.md +179 -179
  152. package/kit/commands/supabase.md +238 -238
  153. package/kit/commands/sync-main.md +68 -68
  154. package/kit/commands/validar-fase.md +35 -35
  155. package/kit/commands/verificar-tarefas.md +44 -44
  156. package/kit/commands/verificar-trabalho.md +64 -64
  157. package/kit/file-manifest.json +13 -11
  158. package/kit/framework/bin/lib/commands.cjs +959 -959
  159. package/kit/framework/bin/lib/config.cjs +442 -442
  160. package/kit/framework/bin/lib/core.cjs +1230 -1230
  161. package/kit/framework/bin/lib/frontmatter.cjs +336 -336
  162. package/kit/framework/bin/lib/init.cjs +1442 -1442
  163. package/kit/framework/bin/lib/milestone.cjs +252 -252
  164. package/kit/framework/bin/lib/model-profiles.cjs +68 -68
  165. package/kit/framework/bin/lib/phase.cjs +888 -888
  166. package/kit/framework/bin/lib/profile-output.cjs +952 -952
  167. package/kit/framework/bin/lib/profile-pipeline.cjs +539 -539
  168. package/kit/framework/bin/lib/roadmap.cjs +329 -329
  169. package/kit/framework/bin/lib/security.cjs +382 -382
  170. package/kit/framework/bin/lib/state.cjs +1031 -1031
  171. package/kit/framework/bin/lib/template.cjs +222 -222
  172. package/kit/framework/bin/lib/uat.cjs +282 -282
  173. package/kit/framework/bin/lib/verify.cjs +888 -888
  174. package/kit/framework/bin/lib/workstream.cjs +491 -491
  175. package/kit/framework/bin/tools.cjs +918 -918
  176. package/kit/framework/commands/workstreams.md +63 -63
  177. package/kit/framework/references/checkpoints.md +778 -778
  178. package/kit/framework/references/continuation-format.md +249 -249
  179. package/kit/framework/references/decimal-phase-calculation.md +64 -64
  180. package/kit/framework/references/git-integration.md +295 -295
  181. package/kit/framework/references/git-planning-commit.md +38 -38
  182. package/kit/framework/references/model-profile-resolution.md +36 -36
  183. package/kit/framework/references/model-profiles.md +139 -139
  184. package/kit/framework/references/phase-argument-parsing.md +61 -61
  185. package/kit/framework/references/planning-config.md +202 -202
  186. package/kit/framework/references/questioning.md +162 -162
  187. package/kit/framework/references/tdd.md +263 -263
  188. package/kit/framework/references/ui-brand.md +160 -160
  189. package/kit/framework/references/user-profiling.md +657 -657
  190. package/kit/framework/references/verification-patterns.md +612 -612
  191. package/kit/framework/references/workstream-flag.md +58 -58
  192. package/kit/framework/templates/DEBUG.md +164 -164
  193. package/kit/framework/templates/UAT.md +265 -265
  194. package/kit/framework/templates/UI-SPEC.md +100 -100
  195. package/kit/framework/templates/VALIDATION.md +76 -76
  196. package/kit/framework/templates/claude-md.md +122 -122
  197. package/kit/framework/templates/codebase/architecture.md +185 -185
  198. package/kit/framework/templates/codebase/concerns.md +205 -205
  199. package/kit/framework/templates/codebase/conventions.md +204 -204
  200. package/kit/framework/templates/codebase/integrations.md +192 -192
  201. package/kit/framework/templates/codebase/stack.md +158 -158
  202. package/kit/framework/templates/codebase/structure.md +199 -199
  203. package/kit/framework/templates/codebase/testing.md +301 -301
  204. package/kit/framework/templates/config.json +44 -44
  205. package/kit/framework/templates/context.md +352 -352
  206. package/kit/framework/templates/continue-here.md +78 -78
  207. package/kit/framework/templates/copilot-instructions.md +7 -7
  208. package/kit/framework/templates/debug-subagent-prompt.md +91 -91
  209. package/kit/framework/templates/dev-preferences.md +20 -20
  210. package/kit/framework/templates/discovery.md +146 -146
  211. package/kit/framework/templates/discussion-log.md +63 -63
  212. package/kit/framework/templates/milestone-archive.md +123 -123
  213. package/kit/framework/templates/milestone.md +115 -115
  214. package/kit/framework/templates/phase-prompt.md +610 -610
  215. package/kit/framework/templates/planner-subagent-prompt.md +117 -117
  216. package/kit/framework/templates/project.md +186 -186
  217. package/kit/framework/templates/requirements.md +231 -231
  218. package/kit/framework/templates/research-project/ARCHITECTURE.md +204 -204
  219. package/kit/framework/templates/research-project/FEATURES.md +147 -147
  220. package/kit/framework/templates/research-project/PITFALLS.md +200 -200
  221. package/kit/framework/templates/research-project/STACK.md +120 -120
  222. package/kit/framework/templates/research-project/SUMMARY.md +170 -170
  223. package/kit/framework/templates/research.md +419 -419
  224. package/kit/framework/templates/retrospective.md +54 -54
  225. package/kit/framework/templates/roadmap.md +202 -202
  226. package/kit/framework/templates/state.md +176 -176
  227. package/kit/framework/templates/summary-complex.md +59 -59
  228. package/kit/framework/templates/summary-minimal.md +41 -41
  229. package/kit/framework/templates/summary-standard.md +48 -48
  230. package/kit/framework/templates/summary.md +209 -209
  231. package/kit/framework/templates/user-profile.md +146 -146
  232. package/kit/framework/templates/user-setup.md +256 -256
  233. package/kit/framework/templates/verification-report.md +258 -258
  234. package/kit/framework/workflows/add-phase.md +112 -112
  235. package/kit/framework/workflows/add-tests.md +351 -351
  236. package/kit/framework/workflows/add-todo.md +158 -158
  237. package/kit/framework/workflows/audit-milestone.md +340 -340
  238. package/kit/framework/workflows/audit-uat.md +109 -109
  239. package/kit/framework/workflows/autonomous.md +891 -891
  240. package/kit/framework/workflows/check-todos.md +177 -177
  241. package/kit/framework/workflows/cleanup.md +152 -152
  242. package/kit/framework/workflows/complete-milestone.md +696 -696
  243. package/kit/framework/workflows/diagnose-issues.md +231 -231
  244. package/kit/framework/workflows/discovery-phase.md +289 -289
  245. package/kit/framework/workflows/discuss-phase-assumptions.md +653 -653
  246. package/kit/framework/workflows/discuss-phase.md +784 -784
  247. package/kit/framework/workflows/do.md +104 -104
  248. package/kit/framework/workflows/execute-phase.md +838 -838
  249. package/kit/framework/workflows/execute-plan.md +510 -510
  250. package/kit/framework/workflows/fast.md +102 -102
  251. package/kit/framework/workflows/forensics.md +265 -265
  252. package/kit/framework/workflows/health.md +181 -181
  253. package/kit/framework/workflows/help.md +619 -619
  254. package/kit/framework/workflows/insert-phase.md +130 -130
  255. package/kit/framework/workflows/list-phase-assumptions.md +178 -178
  256. package/kit/framework/workflows/list-workspaces.md +56 -56
  257. package/kit/framework/workflows/manager.md +362 -362
  258. package/kit/framework/workflows/map-codebase.md +377 -377
  259. package/kit/framework/workflows/milestone-summary.md +223 -223
  260. package/kit/framework/workflows/new-milestone.md +486 -486
  261. package/kit/framework/workflows/new-project.md +1159 -1159
  262. package/kit/framework/workflows/new-workspace.md +237 -237
  263. package/kit/framework/workflows/next.md +97 -97
  264. package/kit/framework/workflows/node-repair.md +92 -92
  265. package/kit/framework/workflows/note.md +156 -156
  266. package/kit/framework/workflows/pause-work.md +176 -176
  267. package/kit/framework/workflows/plan-milestone-gaps.md +273 -273
  268. package/kit/framework/workflows/plan-phase.md +765 -765
  269. package/kit/framework/workflows/plant-seed.md +169 -169
  270. package/kit/framework/workflows/pr-branch.md +129 -129
  271. package/kit/framework/workflows/profile-user.md +450 -450
  272. package/kit/framework/workflows/progress.md +507 -507
  273. package/kit/framework/workflows/quick.md +757 -757
  274. package/kit/framework/workflows/remove-phase.md +155 -155
  275. package/kit/framework/workflows/remove-workspace.md +90 -90
  276. package/kit/framework/workflows/research-phase.md +82 -82
  277. package/kit/framework/workflows/resume-project.md +326 -326
  278. package/kit/framework/workflows/review.md +228 -228
  279. package/kit/framework/workflows/session-report.md +146 -146
  280. package/kit/framework/workflows/settings.md +283 -283
  281. package/kit/framework/workflows/ship.md +228 -228
  282. package/kit/framework/workflows/stats.md +60 -60
  283. package/kit/framework/workflows/transition.md +671 -671
  284. package/kit/framework/workflows/ui-phase.md +302 -302
  285. package/kit/framework/workflows/ui-review.md +165 -165
  286. package/kit/framework/workflows/update.md +323 -323
  287. package/kit/framework/workflows/validate-phase.md +174 -174
  288. package/kit/framework/workflows/verify-phase.md +252 -252
  289. package/kit/framework/workflows/verify-work.md +637 -637
  290. package/kit/hooks/check-update.js +118 -118
  291. package/kit/hooks/context-monitor.js +163 -163
  292. package/kit/hooks/kit-attribution-reminder.cjs +92 -92
  293. package/kit/hooks/kit-router.cjs +137 -137
  294. package/kit/hooks/prompt-guard.js +103 -103
  295. package/kit/hooks/statusline.js +125 -125
  296. package/kit/hooks/workflow-guard.js +101 -101
  297. package/kit/settings.json +45 -45
  298. package/kit/skills/ai-prompt-characterization/SKILL.md +335 -335
  299. package/kit/skills/armadilhas-sistemas-distribuidos/SKILL.md +447 -447
  300. package/kit/skills/audit-log-multi-tenant/SKILL.md +340 -340
  301. package/kit/skills/b2b-saas-architecture/SKILL.md +300 -300
  302. package/kit/skills/consistencia-leitura-replica/SKILL.md +385 -385
  303. package/kit/skills/crm-lead-pipeline-patterns/SKILL.md +343 -343
  304. package/kit/skills/escolha-modelo-consistencia/SKILL.md +494 -494
  305. package/kit/skills/evolucao-schema-compativel/SKILL.md +448 -448
  306. package/kit/skills/evolution-go-whatsapp-integration/SKILL.md +322 -322
  307. package/kit/skills/example-skill/SKILL.md +42 -42
  308. package/kit/skills/legacy-api-only-applications/SKILL.md +358 -358
  309. package/kit/skills/legacy-characterization-tests/SKILL.md +330 -330
  310. package/kit/skills/legacy-effect-analysis/SKILL.md +331 -331
  311. package/kit/skills/legacy-extract-class/SKILL.md +203 -203
  312. package/kit/skills/legacy-programming-by-difference/SKILL.md +252 -252
  313. package/kit/skills/legacy-seams-and-test-harness/SKILL.md +460 -460
  314. package/kit/skills/legacy-shotgun-surgery/SKILL.md +286 -286
  315. package/kit/skills/legacy-sprout-wrap-techniques/SKILL.md +434 -434
  316. package/kit/skills/legacy-storytelling-naked-crc/SKILL.md +270 -270
  317. package/kit/skills/lgpd-multi-tenant-compliance/SKILL.md +340 -340
  318. package/kit/skills/member-invite-flow/SKILL.md +305 -305
  319. package/kit/skills/member-management-react-shadcn/SKILL.md +328 -328
  320. package/kit/skills/multi-tenant-performance-scaling/SKILL.md +316 -316
  321. package/kit/skills/multi-tenant-rls-hierarchy/SKILL.md +342 -342
  322. package/kit/skills/org-onboarding-flow/SKILL.md +257 -257
  323. package/kit/skills/org-switcher-react-pattern/SKILL.md +349 -349
  324. package/kit/skills/permission-gate-react-pattern/SKILL.md +271 -271
  325. package/kit/skills/postgres-isolamento-concorrencia/SKILL.md +552 -552
  326. package/kit/skills/pre-refactor-characterization/SKILL.md +421 -421
  327. package/kit/skills/rbac-permissions-matrix-supabase/SKILL.md +338 -338
  328. package/kit/skills/streams-eventos-cdc/SKILL.md +711 -711
  329. package/kit/skills/supabase-auth-hardening/SKILL.md +674 -674
  330. package/kit/skills/supabase-auth-hooks/SKILL.md +875 -875
  331. package/kit/skills/supabase-auth-methods/SKILL.md +486 -486
  332. package/kit/skills/supabase-auth-sessions/SKILL.md +579 -579
  333. package/kit/skills/supabase-auth-ssr/SKILL.md +306 -306
  334. package/kit/skills/supabase-branching-workflow/SKILL.md +544 -544
  335. package/kit/skills/supabase-ci-cd-github-actions/SKILL.md +880 -880
  336. package/kit/skills/supabase-column-level-security/SKILL.md +426 -426
  337. package/kit/skills/supabase-config-toml-remotes/SKILL.md +807 -807
  338. package/kit/skills/supabase-custom-claims-rbac/SKILL.md +472 -472
  339. package/kit/skills/supabase-edge-functions/SKILL.md +330 -330
  340. package/kit/skills/supabase-edge-functions-auth/SKILL.md +309 -309
  341. package/kit/skills/supabase-edge-functions-limits/SKILL.md +302 -302
  342. package/kit/skills/supabase-edge-functions-mcp-server/SKILL.md +279 -279
  343. package/kit/skills/supabase-edge-functions-testing/SKILL.md +277 -277
  344. package/kit/skills/supabase-edge-runtime-builtins/SKILL.md +357 -357
  345. package/kit/skills/supabase-enterprise-sso-saml/SKILL.md +545 -545
  346. package/kit/skills/supabase-jwt-signing-keys/SKILL.md +399 -399
  347. package/kit/skills/supabase-mfa/SKILL.md +488 -488
  348. package/kit/skills/supabase-migration-repair/SKILL.md +823 -823
  349. package/kit/skills/supabase-migrations/SKILL.md +297 -297
  350. package/kit/skills/supabase-oauth-server/SKILL.md +537 -537
  351. package/kit/skills/supabase-pgtap-testing/SKILL.md +1053 -1053
  352. package/kit/skills/supabase-postgres-roles/SKILL.md +392 -392
  353. package/kit/skills/supabase-realtime/SKILL.md +460 -460
  354. package/kit/skills/supabase-rls-defense-in-depth/SKILL.md +418 -418
  355. package/kit/skills/supabase-rls-policies/SKILL.md +635 -635
  356. package/kit/skills/supabase-social-oauth/SKILL.md +480 -480
  357. package/kit/skills/supabase-third-party-auth/SKILL.md +450 -450
  358. package/kit/skills/super-admin-platform-pattern/SKILL.md +326 -326
  359. package/kit/skills/tenant-quente-mitigacao/SKILL.md +605 -605
  360. package/kit/skills/ui-anti-padroes-ia/SKILL.md +261 -261
  361. package/kit/skills/ui-contexto-produto/SKILL.md +248 -248
  362. package/kit/skills/ui-cor-estrategia/SKILL.md +213 -213
  363. package/kit/skills/ui-critica-auditoria/SKILL.md +260 -260
  364. package/kit/skills/ui-motion-funcional/SKILL.md +264 -264
  365. package/kit/skills/ui-ritmo-espacial/SKILL.md +259 -259
  366. package/kit/skills/ui-tipografia/SKILL.md +211 -211
  367. package/kit/skills/whatsapp-conversation-state-machine/SKILL.md +287 -287
  368. package/kit/workflows/auditar-observabilidade-cobertura.workflow.js +250 -0
  369. package/package.json +65 -63
  370. package/src/core/kit.js +333 -216
  371. package/src/core/reflect.js +247 -247
  372. package/src/core/registry.js +123 -112
  373. package/src/core/reverse-sync.js +448 -372
  374. package/src/core/sync.js +477 -437
  375. package/src/core/watch.js +121 -121
  376. package/src/mcp-server/index.js +794 -794
@@ -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)