@luanpdd/kit-mcp 1.33.0 → 1.35.0

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