@luanpdd/kit-mcp 1.30.1 → 1.31.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 (347) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +168 -168
  3. package/gates/agent-no-recursive-dispatch.md +84 -82
  4. package/kit/COMANDOS.md +138 -138
  5. package/kit/README.md +76 -76
  6. package/kit/agents/advisor-researcher.md +107 -106
  7. package/kit/agents/ai-mutation-tester.md +1 -0
  8. package/kit/agents/assumptions-analyzer.md +108 -107
  9. package/kit/agents/audit-log-implementer.md +314 -313
  10. package/kit/agents/auditor-consistencia-isolamento.md +414 -413
  11. package/kit/agents/b2b-saas-architect.md +157 -156
  12. package/kit/agents/burn-rate-forecaster.md +1 -0
  13. package/kit/agents/cascading-failures-auditor.md +299 -298
  14. package/kit/agents/codebase-mapper.md +769 -768
  15. package/kit/agents/crm-pipeline-implementer.md +257 -256
  16. package/kit/agents/debugger.md +814 -813
  17. package/kit/agents/detector-tenant-quente.md +338 -337
  18. package/kit/agents/evolution-go-integrator.md +201 -200
  19. package/kit/agents/example-reviewer.md +22 -21
  20. package/kit/agents/executor.md +565 -564
  21. package/kit/agents/golden-signals-instrumenter.md +1 -0
  22. package/kit/agents/incident-investigator.md +1 -0
  23. package/kit/agents/integration-checker.md +201 -200
  24. package/kit/agents/invite-flow-implementer.md +190 -189
  25. package/kit/agents/legacy-characterizer.md +369 -368
  26. package/kit/agents/lgpd-compliance-auditor.md +296 -295
  27. package/kit/agents/load-shedding-instrumenter.md +1 -0
  28. package/kit/agents/multi-tenant-isolation-auditor.md +254 -253
  29. package/kit/agents/multi-tenant-rls-writer.md +341 -340
  30. package/kit/agents/nyquist-auditor.md +179 -178
  31. package/kit/agents/observability-coverage-auditor.md +316 -315
  32. package/kit/agents/observability-instrumenter.md +1 -0
  33. package/kit/agents/omm-auditor.md +1 -0
  34. package/kit/agents/org-onboarding-implementer.md +224 -223
  35. package/kit/agents/payload-capture-instrumenter.md +274 -273
  36. package/kit/agents/phase-researcher.md +697 -696
  37. package/kit/agents/plan-checker.md +273 -272
  38. package/kit/agents/planner.md +923 -922
  39. package/kit/agents/postmortem-writer.md +1 -0
  40. package/kit/agents/project-researcher.md +653 -652
  41. package/kit/agents/prr-conductor.md +1 -0
  42. package/kit/agents/refactor-safety-auditor.md +405 -404
  43. package/kit/agents/release-pipeline-auditor.md +1 -0
  44. package/kit/agents/research-synthesizer.md +246 -245
  45. package/kit/agents/roadmapper.md +678 -677
  46. package/kit/agents/schema-checker.md +1 -0
  47. package/kit/agents/seam-finder.md +360 -359
  48. package/kit/agents/shotgun-surgery-detector.md +350 -349
  49. package/kit/agents/slo-engineer.md +1 -0
  50. package/kit/agents/storytelling-analyst.md +1 -0
  51. package/kit/agents/supabase-architect.md +1 -0
  52. package/kit/agents/supabase-auth-bootstrapper.md +1 -0
  53. package/kit/agents/supabase-branching-architect.md +563 -562
  54. package/kit/agents/supabase-cicd-pipeline-implementer.md +778 -777
  55. package/kit/agents/supabase-column-privileges-writer.md +400 -399
  56. package/kit/agents/supabase-edge-fn-tester.md +2 -1
  57. package/kit/agents/supabase-edge-fn-writer.md +2 -1
  58. package/kit/agents/supabase-migration-writer.md +386 -385
  59. package/kit/agents/supabase-rbac-implementer.md +393 -392
  60. package/kit/agents/supabase-realtime-implementer.md +364 -363
  61. package/kit/agents/supabase-rls-hardener.md +522 -521
  62. package/kit/agents/supabase-rls-writer.md +324 -323
  63. package/kit/agents/supabase-roles-implementer.md +356 -355
  64. package/kit/agents/supabase-storage-implementer.md +1 -0
  65. package/kit/agents/super-admin-implementer.md +282 -281
  66. package/kit/agents/toil-auditor.md +1 -0
  67. package/kit/agents/ui-auditor.md +438 -437
  68. package/kit/agents/ui-checker.md +303 -302
  69. package/kit/agents/ui-researcher.md +356 -355
  70. package/kit/agents/user-profiler.md +176 -175
  71. package/kit/agents/validador-evolucao-schema.md +336 -335
  72. package/kit/agents/verifier.md +729 -728
  73. package/kit/commands/adicionar-backlog.md +75 -75
  74. package/kit/commands/adicionar-fase.md +42 -42
  75. package/kit/commands/adicionar-tarefa.md +45 -45
  76. package/kit/commands/adicionar-testes.md +41 -41
  77. package/kit/commands/ajuda.md +21 -21
  78. package/kit/commands/atualizar.md +37 -37
  79. package/kit/commands/auditar-cascading.md +111 -111
  80. package/kit/commands/auditar-marco.md +179 -179
  81. package/kit/commands/auditar-observabilidade-cobertura.md +183 -183
  82. package/kit/commands/auditar-refactor.md +219 -219
  83. package/kit/commands/auditar-release.md +109 -109
  84. package/kit/commands/auditar-uat.md +23 -23
  85. package/kit/commands/autonomo.md +40 -40
  86. package/kit/commands/branch-pr.md +24 -24
  87. package/kit/commands/burn-rate-status.md +408 -408
  88. package/kit/commands/capturar-payloads.md +193 -193
  89. package/kit/commands/caracterizar.md +212 -212
  90. package/kit/commands/concluir-marco.md +247 -247
  91. package/kit/commands/configuracoes.md +36 -36
  92. package/kit/commands/dados-distribuidos.md +188 -188
  93. package/kit/commands/definir-perfil.md +10 -10
  94. package/kit/commands/depurar.md +190 -190
  95. package/kit/commands/detectar-duplicacao.md +197 -197
  96. package/kit/commands/discutir-fase.md +131 -131
  97. package/kit/commands/encontrar-seams.md +136 -136
  98. package/kit/commands/entrar-discord.md +17 -17
  99. package/kit/commands/estatisticas.md +18 -18
  100. package/kit/commands/example-greeting.md +33 -33
  101. package/kit/commands/executar-fase.md +58 -58
  102. package/kit/commands/expresso.md +56 -56
  103. package/kit/commands/fase-ui.md +34 -34
  104. package/kit/commands/fazer.md +57 -57
  105. package/kit/commands/fio.md +125 -125
  106. package/kit/commands/fluxos-trabalho.md +64 -64
  107. package/kit/commands/forense.md +176 -176
  108. package/kit/commands/gerenciador.md +38 -38
  109. package/kit/commands/inserir-fase.md +31 -31
  110. package/kit/commands/legacy.md +263 -263
  111. package/kit/commands/limpeza.md +17 -17
  112. package/kit/commands/listar-hipoteses-fase.md +45 -45
  113. package/kit/commands/listar-workspaces.md +18 -18
  114. package/kit/commands/load-shedding.md +117 -117
  115. package/kit/commands/mapear-codebase.md +70 -70
  116. package/kit/commands/multi-tenant.md +163 -163
  117. package/kit/commands/nota.md +33 -33
  118. package/kit/commands/novo-marco.md +43 -43
  119. package/kit/commands/novo-projeto.md +41 -41
  120. package/kit/commands/novo-workspace.md +43 -43
  121. package/kit/commands/pausar-trabalho.md +37 -37
  122. package/kit/commands/perfil-usuario.md +45 -45
  123. package/kit/commands/pesquisar-fase.md +195 -195
  124. package/kit/commands/planejar-fase.md +67 -67
  125. package/kit/commands/planejar-lacunas.md +33 -33
  126. package/kit/commands/plantar-ideia.md +25 -25
  127. package/kit/commands/progresso.md +24 -24
  128. package/kit/commands/proximo.md +30 -30
  129. package/kit/commands/publicar.md +490 -490
  130. package/kit/commands/rapido.md +35 -35
  131. package/kit/commands/reaplicar-patches.md +124 -124
  132. package/kit/commands/refactor-seguro.md +321 -321
  133. package/kit/commands/relatorio-sessao.md +19 -19
  134. package/kit/commands/remover-fase.md +31 -31
  135. package/kit/commands/remover-workspace.md +26 -26
  136. package/kit/commands/resumo-marco.md +50 -50
  137. package/kit/commands/retomar-trabalho.md +40 -40
  138. package/kit/commands/revisar-backlog.md +60 -60
  139. package/kit/commands/revisar-ui.md +32 -32
  140. package/kit/commands/revisar.md +37 -37
  141. package/kit/commands/saude.md +21 -21
  142. package/kit/commands/setup-notion.md +93 -93
  143. package/kit/commands/storytelling.md +179 -179
  144. package/kit/commands/sync-main.md +68 -68
  145. package/kit/commands/validar-fase.md +35 -35
  146. package/kit/commands/verificar-tarefas.md +44 -44
  147. package/kit/commands/verificar-trabalho.md +64 -64
  148. package/kit/file-manifest.json +82 -81
  149. package/kit/framework/bin/lib/commands.cjs +959 -959
  150. package/kit/framework/bin/lib/config.cjs +442 -442
  151. package/kit/framework/bin/lib/core.cjs +1230 -1230
  152. package/kit/framework/bin/lib/frontmatter.cjs +336 -336
  153. package/kit/framework/bin/lib/init.cjs +1442 -1442
  154. package/kit/framework/bin/lib/milestone.cjs +252 -252
  155. package/kit/framework/bin/lib/model-profiles.cjs +68 -68
  156. package/kit/framework/bin/lib/phase.cjs +888 -888
  157. package/kit/framework/bin/lib/profile-output.cjs +952 -952
  158. package/kit/framework/bin/lib/profile-pipeline.cjs +539 -539
  159. package/kit/framework/bin/lib/roadmap.cjs +329 -329
  160. package/kit/framework/bin/lib/security.cjs +382 -382
  161. package/kit/framework/bin/lib/state.cjs +1031 -1031
  162. package/kit/framework/bin/lib/template.cjs +222 -222
  163. package/kit/framework/bin/lib/uat.cjs +282 -282
  164. package/kit/framework/bin/lib/verify.cjs +888 -888
  165. package/kit/framework/bin/lib/workstream.cjs +491 -491
  166. package/kit/framework/bin/tools.cjs +918 -918
  167. package/kit/framework/commands/workstreams.md +63 -63
  168. package/kit/framework/references/checkpoints.md +778 -778
  169. package/kit/framework/references/continuation-format.md +249 -249
  170. package/kit/framework/references/decimal-phase-calculation.md +64 -64
  171. package/kit/framework/references/git-integration.md +295 -295
  172. package/kit/framework/references/git-planning-commit.md +38 -38
  173. package/kit/framework/references/model-profile-resolution.md +36 -36
  174. package/kit/framework/references/model-profiles.md +139 -139
  175. package/kit/framework/references/phase-argument-parsing.md +61 -61
  176. package/kit/framework/references/planning-config.md +202 -202
  177. package/kit/framework/references/questioning.md +162 -162
  178. package/kit/framework/references/tdd.md +263 -263
  179. package/kit/framework/references/ui-brand.md +160 -160
  180. package/kit/framework/references/user-profiling.md +657 -657
  181. package/kit/framework/references/verification-patterns.md +612 -612
  182. package/kit/framework/references/workstream-flag.md +58 -58
  183. package/kit/framework/templates/DEBUG.md +164 -164
  184. package/kit/framework/templates/UAT.md +265 -265
  185. package/kit/framework/templates/UI-SPEC.md +100 -100
  186. package/kit/framework/templates/VALIDATION.md +76 -76
  187. package/kit/framework/templates/claude-md.md +122 -122
  188. package/kit/framework/templates/codebase/architecture.md +185 -185
  189. package/kit/framework/templates/codebase/concerns.md +205 -205
  190. package/kit/framework/templates/codebase/conventions.md +204 -204
  191. package/kit/framework/templates/codebase/integrations.md +192 -192
  192. package/kit/framework/templates/codebase/stack.md +158 -158
  193. package/kit/framework/templates/codebase/structure.md +199 -199
  194. package/kit/framework/templates/codebase/testing.md +301 -301
  195. package/kit/framework/templates/config.json +44 -44
  196. package/kit/framework/templates/context.md +352 -352
  197. package/kit/framework/templates/continue-here.md +78 -78
  198. package/kit/framework/templates/copilot-instructions.md +7 -7
  199. package/kit/framework/templates/debug-subagent-prompt.md +91 -91
  200. package/kit/framework/templates/dev-preferences.md +20 -20
  201. package/kit/framework/templates/discovery.md +146 -146
  202. package/kit/framework/templates/discussion-log.md +63 -63
  203. package/kit/framework/templates/milestone-archive.md +123 -123
  204. package/kit/framework/templates/milestone.md +115 -115
  205. package/kit/framework/templates/phase-prompt.md +610 -610
  206. package/kit/framework/templates/planner-subagent-prompt.md +117 -117
  207. package/kit/framework/templates/project.md +186 -186
  208. package/kit/framework/templates/requirements.md +231 -231
  209. package/kit/framework/templates/research-project/ARCHITECTURE.md +204 -204
  210. package/kit/framework/templates/research-project/FEATURES.md +147 -147
  211. package/kit/framework/templates/research-project/PITFALLS.md +200 -200
  212. package/kit/framework/templates/research-project/STACK.md +120 -120
  213. package/kit/framework/templates/research-project/SUMMARY.md +170 -170
  214. package/kit/framework/templates/research.md +419 -419
  215. package/kit/framework/templates/retrospective.md +54 -54
  216. package/kit/framework/templates/roadmap.md +202 -202
  217. package/kit/framework/templates/state.md +176 -176
  218. package/kit/framework/templates/summary-complex.md +59 -59
  219. package/kit/framework/templates/summary-minimal.md +41 -41
  220. package/kit/framework/templates/summary-standard.md +48 -48
  221. package/kit/framework/templates/summary.md +209 -209
  222. package/kit/framework/templates/user-profile.md +146 -146
  223. package/kit/framework/templates/user-setup.md +256 -256
  224. package/kit/framework/templates/verification-report.md +258 -258
  225. package/kit/framework/workflows/add-phase.md +112 -112
  226. package/kit/framework/workflows/add-tests.md +351 -351
  227. package/kit/framework/workflows/add-todo.md +158 -158
  228. package/kit/framework/workflows/audit-milestone.md +340 -340
  229. package/kit/framework/workflows/audit-uat.md +109 -109
  230. package/kit/framework/workflows/autonomous.md +891 -891
  231. package/kit/framework/workflows/check-todos.md +177 -177
  232. package/kit/framework/workflows/cleanup.md +152 -152
  233. package/kit/framework/workflows/complete-milestone.md +696 -696
  234. package/kit/framework/workflows/diagnose-issues.md +231 -231
  235. package/kit/framework/workflows/discovery-phase.md +289 -289
  236. package/kit/framework/workflows/discuss-phase-assumptions.md +653 -653
  237. package/kit/framework/workflows/discuss-phase.md +784 -784
  238. package/kit/framework/workflows/do.md +104 -104
  239. package/kit/framework/workflows/execute-phase.md +838 -838
  240. package/kit/framework/workflows/execute-plan.md +510 -510
  241. package/kit/framework/workflows/fast.md +102 -102
  242. package/kit/framework/workflows/forensics.md +265 -265
  243. package/kit/framework/workflows/health.md +181 -181
  244. package/kit/framework/workflows/help.md +619 -619
  245. package/kit/framework/workflows/insert-phase.md +130 -130
  246. package/kit/framework/workflows/list-phase-assumptions.md +178 -178
  247. package/kit/framework/workflows/list-workspaces.md +56 -56
  248. package/kit/framework/workflows/manager.md +362 -362
  249. package/kit/framework/workflows/map-codebase.md +377 -377
  250. package/kit/framework/workflows/milestone-summary.md +223 -223
  251. package/kit/framework/workflows/new-milestone.md +486 -486
  252. package/kit/framework/workflows/new-project.md +1159 -1159
  253. package/kit/framework/workflows/new-workspace.md +237 -237
  254. package/kit/framework/workflows/next.md +97 -97
  255. package/kit/framework/workflows/node-repair.md +92 -92
  256. package/kit/framework/workflows/note.md +156 -156
  257. package/kit/framework/workflows/pause-work.md +176 -176
  258. package/kit/framework/workflows/plan-milestone-gaps.md +273 -273
  259. package/kit/framework/workflows/plan-phase.md +765 -765
  260. package/kit/framework/workflows/plant-seed.md +169 -169
  261. package/kit/framework/workflows/pr-branch.md +129 -129
  262. package/kit/framework/workflows/profile-user.md +450 -450
  263. package/kit/framework/workflows/progress.md +507 -507
  264. package/kit/framework/workflows/quick.md +757 -757
  265. package/kit/framework/workflows/remove-phase.md +155 -155
  266. package/kit/framework/workflows/remove-workspace.md +90 -90
  267. package/kit/framework/workflows/research-phase.md +82 -82
  268. package/kit/framework/workflows/resume-project.md +326 -326
  269. package/kit/framework/workflows/review.md +228 -228
  270. package/kit/framework/workflows/session-report.md +146 -146
  271. package/kit/framework/workflows/settings.md +283 -283
  272. package/kit/framework/workflows/ship.md +228 -228
  273. package/kit/framework/workflows/stats.md +60 -60
  274. package/kit/framework/workflows/transition.md +671 -671
  275. package/kit/framework/workflows/ui-phase.md +302 -302
  276. package/kit/framework/workflows/ui-review.md +165 -165
  277. package/kit/framework/workflows/update.md +323 -323
  278. package/kit/framework/workflows/validate-phase.md +174 -174
  279. package/kit/framework/workflows/verify-phase.md +252 -252
  280. package/kit/framework/workflows/verify-work.md +637 -637
  281. package/kit/hooks/check-update.js +118 -118
  282. package/kit/hooks/context-monitor.js +163 -163
  283. package/kit/hooks/kit-attribution-reminder.cjs +30 -36
  284. package/kit/hooks/kit-router.cjs +137 -0
  285. package/kit/hooks/prompt-guard.js +103 -103
  286. package/kit/hooks/statusline.js +125 -125
  287. package/kit/hooks/workflow-guard.js +101 -101
  288. package/kit/settings.json +45 -45
  289. package/kit/skills/ai-prompt-characterization/SKILL.md +335 -335
  290. package/kit/skills/armadilhas-sistemas-distribuidos/SKILL.md +447 -447
  291. package/kit/skills/audit-log-multi-tenant/SKILL.md +340 -340
  292. package/kit/skills/b2b-saas-architecture/SKILL.md +300 -300
  293. package/kit/skills/consistencia-leitura-replica/SKILL.md +385 -385
  294. package/kit/skills/crm-lead-pipeline-patterns/SKILL.md +343 -343
  295. package/kit/skills/escolha-modelo-consistencia/SKILL.md +494 -494
  296. package/kit/skills/evolucao-schema-compativel/SKILL.md +448 -448
  297. package/kit/skills/evolution-go-whatsapp-integration/SKILL.md +322 -322
  298. package/kit/skills/example-skill/SKILL.md +42 -42
  299. package/kit/skills/legacy-api-only-applications/SKILL.md +358 -358
  300. package/kit/skills/legacy-characterization-tests/SKILL.md +330 -330
  301. package/kit/skills/legacy-effect-analysis/SKILL.md +331 -331
  302. package/kit/skills/legacy-extract-class/SKILL.md +203 -203
  303. package/kit/skills/legacy-programming-by-difference/SKILL.md +252 -252
  304. package/kit/skills/legacy-seams-and-test-harness/SKILL.md +460 -460
  305. package/kit/skills/legacy-shotgun-surgery/SKILL.md +286 -286
  306. package/kit/skills/legacy-sprout-wrap-techniques/SKILL.md +434 -434
  307. package/kit/skills/legacy-storytelling-naked-crc/SKILL.md +270 -270
  308. package/kit/skills/lgpd-multi-tenant-compliance/SKILL.md +340 -340
  309. package/kit/skills/member-invite-flow/SKILL.md +305 -305
  310. package/kit/skills/member-management-react-shadcn/SKILL.md +328 -328
  311. package/kit/skills/multi-tenant-performance-scaling/SKILL.md +316 -316
  312. package/kit/skills/multi-tenant-rls-hierarchy/SKILL.md +342 -342
  313. package/kit/skills/org-onboarding-flow/SKILL.md +257 -257
  314. package/kit/skills/org-switcher-react-pattern/SKILL.md +349 -349
  315. package/kit/skills/permission-gate-react-pattern/SKILL.md +271 -271
  316. package/kit/skills/postgres-isolamento-concorrencia/SKILL.md +552 -552
  317. package/kit/skills/pre-refactor-characterization/SKILL.md +421 -421
  318. package/kit/skills/rbac-permissions-matrix-supabase/SKILL.md +338 -338
  319. package/kit/skills/streams-eventos-cdc/SKILL.md +711 -711
  320. package/kit/skills/supabase-branching-workflow/SKILL.md +544 -544
  321. package/kit/skills/supabase-ci-cd-github-actions/SKILL.md +880 -880
  322. package/kit/skills/supabase-column-level-security/SKILL.md +426 -426
  323. package/kit/skills/supabase-config-toml-remotes/SKILL.md +807 -807
  324. package/kit/skills/supabase-custom-claims-rbac/SKILL.md +472 -472
  325. package/kit/skills/supabase-edge-functions/SKILL.md +1 -1
  326. package/kit/skills/supabase-edge-functions-auth/SKILL.md +1 -1
  327. package/kit/skills/supabase-edge-functions-limits/SKILL.md +1 -1
  328. package/kit/skills/supabase-edge-functions-mcp-server/SKILL.md +1 -1
  329. package/kit/skills/supabase-edge-functions-testing/SKILL.md +1 -1
  330. package/kit/skills/supabase-edge-runtime-builtins/SKILL.md +1 -1
  331. package/kit/skills/supabase-migration-repair/SKILL.md +823 -823
  332. package/kit/skills/supabase-migrations/SKILL.md +297 -297
  333. package/kit/skills/supabase-pgtap-testing/SKILL.md +1053 -1053
  334. package/kit/skills/supabase-postgres-roles/SKILL.md +392 -392
  335. package/kit/skills/supabase-realtime/SKILL.md +460 -460
  336. package/kit/skills/supabase-rls-defense-in-depth/SKILL.md +418 -418
  337. package/kit/skills/supabase-rls-policies/SKILL.md +635 -635
  338. package/kit/skills/super-admin-platform-pattern/SKILL.md +326 -326
  339. package/kit/skills/tenant-quente-mitigacao/SKILL.md +605 -605
  340. package/kit/skills/whatsapp-conversation-state-machine/SKILL.md +287 -287
  341. package/package.json +1 -1
  342. package/src/core/kit.js +216 -216
  343. package/src/core/reflect.js +247 -247
  344. package/src/core/reverse-sync.js +372 -372
  345. package/src/core/sync.js +437 -418
  346. package/src/core/watch.js +121 -121
  347. package/src/mcp-server/index.js +794 -715
@@ -1,300 +1,300 @@
1
- ---
2
- name: b2b-saas-architecture
3
- description: Use ao desenhar app B2B multi-tenant (org→department→leader→collaborator) com Supabase + React…
4
- ---
5
-
6
- # B2B SaaS Multi-Tenant — Arquitetura Canônica
7
-
8
- ## Quando usar
9
-
10
- LLM carrega esta skill ao desenhar arquitetura de app B2B SaaS multi-tenant em Supabase. Trigger phrases:
11
-
12
- - "B2B SaaS multi-tenant", "arquitetura multi-tenant", "isolation strategy"
13
- - "single schema vs schema-per-tenant"
14
- - "schema canônico organizations", "departments table", "members"
15
- - "JWT claims multi-tenant", "app_metadata orgs"
16
- - "slug org imutável", "tenant routing"
17
-
18
- Esta skill define o **schema canônico** que `multi-tenant-rls-writer` (Phase 108), `org-onboarding-implementer` (Phase 107), `super-admin-implementer` (Phase 111), `audit-log-implementer` (Phase 109), e demais agents da suíte v1.21 consomem como entrada.
19
-
20
- ## Regras absolutas
21
-
22
- **REGRA #1 (estratégia default):** **Single Schema + `org_id` + RLS** é o caminho canônico para 90% dos B2B SaaS. Schema-per-tenant é justificado apenas em compliance extremo (saúde/jurídico com auditoria isolacional). Database-per-tenant é inviável economicamente fora de contratos enterprise.
23
-
24
- **REGRA #2 (JWT minimal):** **APENAS** `super_admin: bool` em `app_metadata`. Lista de orgs no JWT é anti-pattern — bloat linear no token + stale de 1h após mudança de role. O banco (helper functions PG) é fonte de verdade.
25
-
26
- **REGRA #3 (slug imutável):** `organizations.slug` é **append-only** após criação. Mutação requer tabela `slug_history` + redirect 301 em rotas afetadas. Quebra silenciosa de bookmarks/webhooks/OAuth callbacks é o pior bug que cliente B2B encontra.
27
-
28
- **REGRA #4 (super_admin via service_role):** `app_metadata.super_admin = true` é setado **APENAS** via `auth.admin.updateUserById()` (service role). Cliente NUNCA consegue mutá-lo (≠ `user_metadata` que é editável).
29
-
30
- **REGRA #5 (FKs com CASCADE explícito):** Todas as FKs têm `ON DELETE` explícito (CASCADE para entidades dependentes da org, RESTRICT para evitar deleção acidental). Sem default — força decisão consciente.
31
-
32
- ## Patterns canônicos
33
-
34
- ### Estratégia de isolation — tabela comparativa
35
-
36
- | Estratégia | Isolation | Custo ops | Compliance | Quando usar |
37
- |---|---|---|---|---|
38
- | **Single Schema + `org_id` + RLS** ⭐ | Lógico (RLS) | Baixo | Padrão B2B SaaS | **DEFAULT 90% dos casos** — Stripe, Linear, Vercel, Notion |
39
- | Schema-per-tenant | Físico (PG schemas) | Médio (N migrations) | Compliance auditável | Saúde/jurídico/governo com requisito explícito de isolamento |
40
- | Database-per-tenant | Físico (DB separadas) | Alto (N projects Supabase) | Compliance extremo | Apenas contratos enterprise com SLA de isolamento físico |
41
-
42
- **Recomendação:** comece sempre com Single Schema. Migração para schema-per-tenant é viável (script de fan-out por org_id). Migração reversa não é.
43
-
44
- ### Schema canônico — 7 tabelas (DDL completo)
45
-
46
- ```sql
47
- -- Ordem de criação respeita dependências FK
48
-
49
- -- 1. organizations (root tenant)
50
- create table public.organizations (
51
- id uuid primary key default gen_random_uuid(),
52
- name text not null,
53
- slug text unique not null check (slug ~ '^[a-z0-9-]+$' and length(slug) between 2 and 60),
54
- owner_id uuid not null references auth.users(id) on delete restrict,
55
- plan text not null default 'free' check (plan in ('free', 'pro', 'enterprise')),
56
- status text not null default 'active' check (status in ('active', 'suspended', 'archived')),
57
- metadata jsonb not null default '{}'::jsonb,
58
- created_at timestamptz not null default now(),
59
- updated_at timestamptz not null default now()
60
- );
61
-
62
- -- 2. departments (sub-tenant opcional)
63
- create table public.departments (
64
- id uuid primary key default gen_random_uuid(),
65
- org_id uuid not null references public.organizations(id) on delete cascade,
66
- parent_id uuid references public.departments(id) on delete set null,
67
- name text not null,
68
- slug text not null check (slug ~ '^[a-z0-9-]+$'),
69
- metadata jsonb not null default '{}'::jsonb,
70
- created_at timestamptz not null default now(),
71
- updated_at timestamptz not null default now(),
72
- unique (org_id, slug)
73
- );
74
-
75
- -- 3. roles (org-scoped, custom roles permitidos)
76
- create table public.roles (
77
- id uuid primary key default gen_random_uuid(),
78
- org_id uuid not null references public.organizations(id) on delete cascade,
79
- name text not null check (name ~ '^[a-z_]+$'),
80
- description text,
81
- is_built_in boolean not null default false,
82
- created_at timestamptz not null default now(),
83
- unique (org_id, name)
84
- );
85
-
86
- -- 4. permissions (catálogo global)
87
- create table public.permissions (
88
- id uuid primary key default gen_random_uuid(),
89
- action text not null check (action ~ '^[a-z_]+$'),
90
- resource text not null check (resource ~ '^[a-z_]+$'),
91
- description text,
92
- created_at timestamptz not null default now(),
93
- unique (action, resource)
94
- );
95
-
96
- -- 5. role_permissions (M:N — roles ganham permissions)
97
- create table public.role_permissions (
98
- role_id uuid not null references public.roles(id) on delete cascade,
99
- permission_id uuid not null references public.permissions(id) on delete restrict,
100
- created_at timestamptz not null default now(),
101
- primary key (role_id, permission_id)
102
- );
103
-
104
- -- 6. organization_members (user ↔ org com role)
105
- create table public.organization_members (
106
- id uuid primary key default gen_random_uuid(),
107
- org_id uuid not null references public.organizations(id) on delete cascade,
108
- user_id uuid not null references auth.users(id) on delete cascade,
109
- role_id uuid not null references public.roles(id) on delete restrict,
110
- status text not null default 'active' check (status in ('active', 'suspended', 'left')),
111
- joined_at timestamptz not null default now(),
112
- unique (org_id, user_id)
113
- );
114
-
115
- -- 7. department_members (user ↔ dept com role override opcional)
116
- create table public.department_members (
117
- id uuid primary key default gen_random_uuid(),
118
- dept_id uuid not null references public.departments(id) on delete cascade,
119
- user_id uuid not null references auth.users(id) on delete cascade,
120
- role_id uuid references public.roles(id) on delete set null, -- NULL herda do organization_members
121
- is_leader boolean not null default false,
122
- joined_at timestamptz not null default now(),
123
- unique (dept_id, user_id)
124
- );
125
-
126
- -- Slug history (suporte a redirect 301 quando slug é mutado)
127
- create table public.organization_slug_history (
128
- id uuid primary key default gen_random_uuid(),
129
- org_id uuid not null references public.organizations(id) on delete cascade,
130
- old_slug text not null,
131
- new_slug text not null,
132
- changed_at timestamptz not null default now(),
133
- unique (old_slug)
134
- );
135
- ```
136
-
137
- ### JWT claims minimal — Custom Access Token Hook
138
-
139
- ```sql
140
- -- Hook chamado pelo Supabase Auth a cada token emit
141
- -- Injeta apenas super_admin no app_metadata
142
- create or replace function public.custom_access_token_hook(event jsonb)
143
- returns jsonb
144
- language plpgsql
145
- security definer
146
- set search_path = ''
147
- as $$
148
- declare
149
- claims jsonb;
150
- is_super boolean;
151
- begin
152
- -- Buscar super_admin do app_metadata atual
153
- select coalesce((raw_app_meta_data->>'super_admin')::boolean, false)
154
- into is_super
155
- from auth.users
156
- where id = (event->>'user_id')::uuid;
157
-
158
- claims := event->'claims';
159
- claims := jsonb_set(claims, '{app_metadata}', coalesce(claims->'app_metadata', '{}'::jsonb));
160
- claims := jsonb_set(claims, '{app_metadata,super_admin}', to_jsonb(is_super));
161
-
162
- event := jsonb_set(event, '{claims}', claims);
163
- return event;
164
- end;
165
- $$;
166
-
167
- -- Registrar como hook em supabase/config.toml:
168
- -- [auth.hook.custom_access_token]
169
- -- enabled = true
170
- -- uri = "pg-functions://postgres/public/custom_access_token_hook"
171
- ```
172
-
173
- ### Set super_admin via service_role apenas
174
-
175
- ```typescript
176
- // Edge Function ou backend admin com service_role key
177
- import { createClient } from 'jsr:@supabase/supabase-js@2'
178
-
179
- const admin = createClient(
180
- Deno.env.get('SUPABASE_URL')!,
181
- Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')! // service role — nunca expor ao client
182
- )
183
-
184
- // Promover usuário a super_admin
185
- await admin.auth.admin.updateUserById(userId, {
186
- app_metadata: { super_admin: true }
187
- })
188
-
189
- // IMPORTANTE: usar updateUserById com app_metadata (não user_metadata)
190
- ```
191
-
192
- ### Slug com redirect trail
193
-
194
- ```sql
195
- -- Trigger que registra mudança de slug em organization_slug_history
196
- create or replace function public.track_org_slug_change()
197
- returns trigger
198
- language plpgsql
199
- security invoker
200
- set search_path = ''
201
- as $$
202
- begin
203
- if old.slug is distinct from new.slug then
204
- insert into public.organization_slug_history (org_id, old_slug, new_slug)
205
- values (new.id, old.slug, new.slug);
206
- end if;
207
- return new;
208
- end;
209
- $$;
210
-
211
- create trigger track_org_slug_change_trigger
212
- after update of slug on public.organizations
213
- for each row execute function public.track_org_slug_change();
214
- ```
215
-
216
- App side (Next.js middleware): se `slug` em URL não existe em `organizations`, consulta `organization_slug_history.old_slug` → 301 para `/orgs/{new_slug}/`.
217
-
218
- ## Anti-patterns
219
-
220
- ### Anti-pattern 1: Lista de orgs no JWT (claims bloat + stale)
221
-
222
- **Errado:**
223
- ```sql
224
- -- Hook injeta lista de orgs do user no JWT
225
- -- claims.app_metadata.orgs = [{id, role}, {id, role}, ...]
226
- ```
227
-
228
- **Por quê:**
229
- - JWT tem limite ~4KB — usuário em 50 orgs estoura
230
- - JWT cacheado por 1h — mudança de role demora até 1h pra propagar
231
- - Cada Edge Function paga overhead de parsing de claims grandes
232
-
233
- **Certo:** JWT só com `super_admin: bool`. Helper functions PG (`private.is_member_of`, `private.has_role`) consultam o banco — fonte de verdade sem stale.
234
-
235
- ### Anti-pattern 2: Slug mutável sem redirect trail
236
-
237
- **Errado:**
238
- ```sql
239
- update public.organizations set slug = 'new-name' where id = '...';
240
- -- Sem entry em organization_slug_history
241
- ```
242
-
243
- **Por quê:** bookmarks externos, webhooks Stripe/Slack, OAuth callbacks, Twitter cards, sitemaps — todos quebram silenciosamente. Cliente B2B descobre semanas depois quando recebe email "seu link parou de funcionar".
244
-
245
- **Certo:** trigger `track_org_slug_change` automático + middleware redirect 301 em rotas com slug.
246
-
247
- ### Anti-pattern 3: Schema-per-tenant sem justificativa de compliance
248
-
249
- **Errado:**
250
- ```sql
251
- -- Pra cada nova org, criar schema próprio
252
- create schema "org_acme";
253
- create table org_acme.members (...);
254
- -- ...repetir migration por org
255
- ```
256
-
257
- **Por quê:** N migrations por nova org, provisioning lento, queries cross-tenant impossíveis sem UNION manual, monitoring complexo. Sem ganho real para SaaS comum (RLS bem feita já isola).
258
-
259
- **Certo:** Single Schema + `org_id` + RLS. Schema-per-tenant só quando regulatório exige.
260
-
261
- ### Anti-pattern 4: `user_metadata` para super_admin
262
-
263
- **Errado:**
264
- ```sql
265
- -- Policy lê super_admin de user_metadata
266
- using ((auth.jwt()->'user_metadata'->>'super_admin')::boolean = true)
267
- ```
268
-
269
- **Por quê:** `user_metadata` é editável pelo cliente via `auth.updateUser({ data: { super_admin: true } })`. Privilege escalation imediato — qualquer usuário se torna super_admin. Documentado em [Supabase Splinter 0015](https://supabase.github.io/splinter/0015_rls_references_user_metadata/).
270
-
271
- **Certo:** `app_metadata.super_admin` (set apenas via service_role).
272
-
273
- ### Anti-pattern 5: FKs sem CASCADE/RESTRICT explícito
274
-
275
- **Errado:**
276
- ```sql
277
- references public.organizations(id) -- default ON DELETE NO ACTION
278
- ```
279
-
280
- **Por quê:** decisão importante (deletar org com 100k rows? bloquear?) fica implícita. NO ACTION pode falhar deleção sem mensagem clara. Comportamento varia por engine.
281
-
282
- **Certo:**
283
- ```sql
284
- references public.organizations(id) on delete cascade -- entidade dependente
285
- references auth.users(id) on delete restrict -- prevenir orfão
286
- references public.roles(id) on delete set null -- preservar histórico
287
- ```
288
-
289
- ## Ver também
290
-
291
- - [supabase-rls-policies](../supabase-rls-policies/SKILL.md) — anti-patterns RLS herdados (`(select auth.uid())` wrapper, no `user_metadata` em authz)
292
- - [supabase-database-functions](../supabase-database-functions/SKILL.md) — padrões PG functions (security invoker, search_path = '')
293
- - [supabase-postgres-style](../supabase-postgres-style/SKILL.md) — naming snake_case, lowercase reserved
294
- - [multi-tenant-rls-hierarchy](../multi-tenant-rls-hierarchy/SKILL.md) — 4 helper functions PG canônicas + policies hierárquicas (Phase 108)
295
- - [multi-tenant-performance-scaling](../multi-tenant-performance-scaling/SKILL.md) — Supavisor pooling + partitioning por `org_id` + MVs per-tenant (skill irmã)
296
- - [rbac-permissions-matrix-supabase](../rbac-permissions-matrix-supabase/SKILL.md) — modelagem permissions action × resource × scope (Phase 108)
297
- - [_shared-supabase/glossary.md](../_shared-supabase/glossary.md) — termos canônicos `app_metadata`, `service_role`
298
- - [_shared-multi-tenant/glossary.md](../_shared-multi-tenant/glossary.md) — termos novos `tenant`, `org_id`, `super_admin`, `RBAC`
299
- - [Supabase RLS Best Practices](https://makerkit.dev/blog/tutorials/supabase-rls-best-practices) — fonte external canônica
300
- - [Custom Access Token Hook — Supabase Docs](https://supabase.com/docs/guides/auth/auth-hooks/custom-access-token-hook)
1
+ ---
2
+ name: b2b-saas-architecture
3
+ description: Use ao desenhar app B2B multi-tenant (org→department→leader→collaborator) com Supabase + React…
4
+ ---
5
+
6
+ # B2B SaaS Multi-Tenant — Arquitetura Canônica
7
+
8
+ ## Quando usar
9
+
10
+ LLM carrega esta skill ao desenhar arquitetura de app B2B SaaS multi-tenant em Supabase. Trigger phrases:
11
+
12
+ - "B2B SaaS multi-tenant", "arquitetura multi-tenant", "isolation strategy"
13
+ - "single schema vs schema-per-tenant"
14
+ - "schema canônico organizations", "departments table", "members"
15
+ - "JWT claims multi-tenant", "app_metadata orgs"
16
+ - "slug org imutável", "tenant routing"
17
+
18
+ Esta skill define o **schema canônico** que `multi-tenant-rls-writer` (Phase 108), `org-onboarding-implementer` (Phase 107), `super-admin-implementer` (Phase 111), `audit-log-implementer` (Phase 109), e demais agents da suíte v1.21 consomem como entrada.
19
+
20
+ ## Regras absolutas
21
+
22
+ **REGRA #1 (estratégia default):** **Single Schema + `org_id` + RLS** é o caminho canônico para 90% dos B2B SaaS. Schema-per-tenant é justificado apenas em compliance extremo (saúde/jurídico com auditoria isolacional). Database-per-tenant é inviável economicamente fora de contratos enterprise.
23
+
24
+ **REGRA #2 (JWT minimal):** **APENAS** `super_admin: bool` em `app_metadata`. Lista de orgs no JWT é anti-pattern — bloat linear no token + stale de 1h após mudança de role. O banco (helper functions PG) é fonte de verdade.
25
+
26
+ **REGRA #3 (slug imutável):** `organizations.slug` é **append-only** após criação. Mutação requer tabela `slug_history` + redirect 301 em rotas afetadas. Quebra silenciosa de bookmarks/webhooks/OAuth callbacks é o pior bug que cliente B2B encontra.
27
+
28
+ **REGRA #4 (super_admin via service_role):** `app_metadata.super_admin = true` é setado **APENAS** via `auth.admin.updateUserById()` (service role). Cliente NUNCA consegue mutá-lo (≠ `user_metadata` que é editável).
29
+
30
+ **REGRA #5 (FKs com CASCADE explícito):** Todas as FKs têm `ON DELETE` explícito (CASCADE para entidades dependentes da org, RESTRICT para evitar deleção acidental). Sem default — força decisão consciente.
31
+
32
+ ## Patterns canônicos
33
+
34
+ ### Estratégia de isolation — tabela comparativa
35
+
36
+ | Estratégia | Isolation | Custo ops | Compliance | Quando usar |
37
+ |---|---|---|---|---|
38
+ | **Single Schema + `org_id` + RLS** ⭐ | Lógico (RLS) | Baixo | Padrão B2B SaaS | **DEFAULT 90% dos casos** — Stripe, Linear, Vercel, Notion |
39
+ | Schema-per-tenant | Físico (PG schemas) | Médio (N migrations) | Compliance auditável | Saúde/jurídico/governo com requisito explícito de isolamento |
40
+ | Database-per-tenant | Físico (DB separadas) | Alto (N projects Supabase) | Compliance extremo | Apenas contratos enterprise com SLA de isolamento físico |
41
+
42
+ **Recomendação:** comece sempre com Single Schema. Migração para schema-per-tenant é viável (script de fan-out por org_id). Migração reversa não é.
43
+
44
+ ### Schema canônico — 7 tabelas (DDL completo)
45
+
46
+ ```sql
47
+ -- Ordem de criação respeita dependências FK
48
+
49
+ -- 1. organizations (root tenant)
50
+ create table public.organizations (
51
+ id uuid primary key default gen_random_uuid(),
52
+ name text not null,
53
+ slug text unique not null check (slug ~ '^[a-z0-9-]+$' and length(slug) between 2 and 60),
54
+ owner_id uuid not null references auth.users(id) on delete restrict,
55
+ plan text not null default 'free' check (plan in ('free', 'pro', 'enterprise')),
56
+ status text not null default 'active' check (status in ('active', 'suspended', 'archived')),
57
+ metadata jsonb not null default '{}'::jsonb,
58
+ created_at timestamptz not null default now(),
59
+ updated_at timestamptz not null default now()
60
+ );
61
+
62
+ -- 2. departments (sub-tenant opcional)
63
+ create table public.departments (
64
+ id uuid primary key default gen_random_uuid(),
65
+ org_id uuid not null references public.organizations(id) on delete cascade,
66
+ parent_id uuid references public.departments(id) on delete set null,
67
+ name text not null,
68
+ slug text not null check (slug ~ '^[a-z0-9-]+$'),
69
+ metadata jsonb not null default '{}'::jsonb,
70
+ created_at timestamptz not null default now(),
71
+ updated_at timestamptz not null default now(),
72
+ unique (org_id, slug)
73
+ );
74
+
75
+ -- 3. roles (org-scoped, custom roles permitidos)
76
+ create table public.roles (
77
+ id uuid primary key default gen_random_uuid(),
78
+ org_id uuid not null references public.organizations(id) on delete cascade,
79
+ name text not null check (name ~ '^[a-z_]+$'),
80
+ description text,
81
+ is_built_in boolean not null default false,
82
+ created_at timestamptz not null default now(),
83
+ unique (org_id, name)
84
+ );
85
+
86
+ -- 4. permissions (catálogo global)
87
+ create table public.permissions (
88
+ id uuid primary key default gen_random_uuid(),
89
+ action text not null check (action ~ '^[a-z_]+$'),
90
+ resource text not null check (resource ~ '^[a-z_]+$'),
91
+ description text,
92
+ created_at timestamptz not null default now(),
93
+ unique (action, resource)
94
+ );
95
+
96
+ -- 5. role_permissions (M:N — roles ganham permissions)
97
+ create table public.role_permissions (
98
+ role_id uuid not null references public.roles(id) on delete cascade,
99
+ permission_id uuid not null references public.permissions(id) on delete restrict,
100
+ created_at timestamptz not null default now(),
101
+ primary key (role_id, permission_id)
102
+ );
103
+
104
+ -- 6. organization_members (user ↔ org com role)
105
+ create table public.organization_members (
106
+ id uuid primary key default gen_random_uuid(),
107
+ org_id uuid not null references public.organizations(id) on delete cascade,
108
+ user_id uuid not null references auth.users(id) on delete cascade,
109
+ role_id uuid not null references public.roles(id) on delete restrict,
110
+ status text not null default 'active' check (status in ('active', 'suspended', 'left')),
111
+ joined_at timestamptz not null default now(),
112
+ unique (org_id, user_id)
113
+ );
114
+
115
+ -- 7. department_members (user ↔ dept com role override opcional)
116
+ create table public.department_members (
117
+ id uuid primary key default gen_random_uuid(),
118
+ dept_id uuid not null references public.departments(id) on delete cascade,
119
+ user_id uuid not null references auth.users(id) on delete cascade,
120
+ role_id uuid references public.roles(id) on delete set null, -- NULL herda do organization_members
121
+ is_leader boolean not null default false,
122
+ joined_at timestamptz not null default now(),
123
+ unique (dept_id, user_id)
124
+ );
125
+
126
+ -- Slug history (suporte a redirect 301 quando slug é mutado)
127
+ create table public.organization_slug_history (
128
+ id uuid primary key default gen_random_uuid(),
129
+ org_id uuid not null references public.organizations(id) on delete cascade,
130
+ old_slug text not null,
131
+ new_slug text not null,
132
+ changed_at timestamptz not null default now(),
133
+ unique (old_slug)
134
+ );
135
+ ```
136
+
137
+ ### JWT claims minimal — Custom Access Token Hook
138
+
139
+ ```sql
140
+ -- Hook chamado pelo Supabase Auth a cada token emit
141
+ -- Injeta apenas super_admin no app_metadata
142
+ create or replace function public.custom_access_token_hook(event jsonb)
143
+ returns jsonb
144
+ language plpgsql
145
+ security definer
146
+ set search_path = ''
147
+ as $$
148
+ declare
149
+ claims jsonb;
150
+ is_super boolean;
151
+ begin
152
+ -- Buscar super_admin do app_metadata atual
153
+ select coalesce((raw_app_meta_data->>'super_admin')::boolean, false)
154
+ into is_super
155
+ from auth.users
156
+ where id = (event->>'user_id')::uuid;
157
+
158
+ claims := event->'claims';
159
+ claims := jsonb_set(claims, '{app_metadata}', coalesce(claims->'app_metadata', '{}'::jsonb));
160
+ claims := jsonb_set(claims, '{app_metadata,super_admin}', to_jsonb(is_super));
161
+
162
+ event := jsonb_set(event, '{claims}', claims);
163
+ return event;
164
+ end;
165
+ $$;
166
+
167
+ -- Registrar como hook em supabase/config.toml:
168
+ -- [auth.hook.custom_access_token]
169
+ -- enabled = true
170
+ -- uri = "pg-functions://postgres/public/custom_access_token_hook"
171
+ ```
172
+
173
+ ### Set super_admin via service_role apenas
174
+
175
+ ```typescript
176
+ // Edge Function ou backend admin com service_role key
177
+ import { createClient } from 'jsr:@supabase/supabase-js@2'
178
+
179
+ const admin = createClient(
180
+ Deno.env.get('SUPABASE_URL')!,
181
+ Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')! // service role — nunca expor ao client
182
+ )
183
+
184
+ // Promover usuário a super_admin
185
+ await admin.auth.admin.updateUserById(userId, {
186
+ app_metadata: { super_admin: true }
187
+ })
188
+
189
+ // IMPORTANTE: usar updateUserById com app_metadata (não user_metadata)
190
+ ```
191
+
192
+ ### Slug com redirect trail
193
+
194
+ ```sql
195
+ -- Trigger que registra mudança de slug em organization_slug_history
196
+ create or replace function public.track_org_slug_change()
197
+ returns trigger
198
+ language plpgsql
199
+ security invoker
200
+ set search_path = ''
201
+ as $$
202
+ begin
203
+ if old.slug is distinct from new.slug then
204
+ insert into public.organization_slug_history (org_id, old_slug, new_slug)
205
+ values (new.id, old.slug, new.slug);
206
+ end if;
207
+ return new;
208
+ end;
209
+ $$;
210
+
211
+ create trigger track_org_slug_change_trigger
212
+ after update of slug on public.organizations
213
+ for each row execute function public.track_org_slug_change();
214
+ ```
215
+
216
+ App side (Next.js middleware): se `slug` em URL não existe em `organizations`, consulta `organization_slug_history.old_slug` → 301 para `/orgs/{new_slug}/`.
217
+
218
+ ## Anti-patterns
219
+
220
+ ### Anti-pattern 1: Lista de orgs no JWT (claims bloat + stale)
221
+
222
+ **Errado:**
223
+ ```sql
224
+ -- Hook injeta lista de orgs do user no JWT
225
+ -- claims.app_metadata.orgs = [{id, role}, {id, role}, ...]
226
+ ```
227
+
228
+ **Por quê:**
229
+ - JWT tem limite ~4KB — usuário em 50 orgs estoura
230
+ - JWT cacheado por 1h — mudança de role demora até 1h pra propagar
231
+ - Cada Edge Function paga overhead de parsing de claims grandes
232
+
233
+ **Certo:** JWT só com `super_admin: bool`. Helper functions PG (`private.is_member_of`, `private.has_role`) consultam o banco — fonte de verdade sem stale.
234
+
235
+ ### Anti-pattern 2: Slug mutável sem redirect trail
236
+
237
+ **Errado:**
238
+ ```sql
239
+ update public.organizations set slug = 'new-name' where id = '...';
240
+ -- Sem entry em organization_slug_history
241
+ ```
242
+
243
+ **Por quê:** bookmarks externos, webhooks Stripe/Slack, OAuth callbacks, Twitter cards, sitemaps — todos quebram silenciosamente. Cliente B2B descobre semanas depois quando recebe email "seu link parou de funcionar".
244
+
245
+ **Certo:** trigger `track_org_slug_change` automático + middleware redirect 301 em rotas com slug.
246
+
247
+ ### Anti-pattern 3: Schema-per-tenant sem justificativa de compliance
248
+
249
+ **Errado:**
250
+ ```sql
251
+ -- Pra cada nova org, criar schema próprio
252
+ create schema "org_acme";
253
+ create table org_acme.members (...);
254
+ -- ...repetir migration por org
255
+ ```
256
+
257
+ **Por quê:** N migrations por nova org, provisioning lento, queries cross-tenant impossíveis sem UNION manual, monitoring complexo. Sem ganho real para SaaS comum (RLS bem feita já isola).
258
+
259
+ **Certo:** Single Schema + `org_id` + RLS. Schema-per-tenant só quando regulatório exige.
260
+
261
+ ### Anti-pattern 4: `user_metadata` para super_admin
262
+
263
+ **Errado:**
264
+ ```sql
265
+ -- Policy lê super_admin de user_metadata
266
+ using ((auth.jwt()->'user_metadata'->>'super_admin')::boolean = true)
267
+ ```
268
+
269
+ **Por quê:** `user_metadata` é editável pelo cliente via `auth.updateUser({ data: { super_admin: true } })`. Privilege escalation imediato — qualquer usuário se torna super_admin. Documentado em [Supabase Splinter 0015](https://supabase.github.io/splinter/0015_rls_references_user_metadata/).
270
+
271
+ **Certo:** `app_metadata.super_admin` (set apenas via service_role).
272
+
273
+ ### Anti-pattern 5: FKs sem CASCADE/RESTRICT explícito
274
+
275
+ **Errado:**
276
+ ```sql
277
+ references public.organizations(id) -- default ON DELETE NO ACTION
278
+ ```
279
+
280
+ **Por quê:** decisão importante (deletar org com 100k rows? bloquear?) fica implícita. NO ACTION pode falhar deleção sem mensagem clara. Comportamento varia por engine.
281
+
282
+ **Certo:**
283
+ ```sql
284
+ references public.organizations(id) on delete cascade -- entidade dependente
285
+ references auth.users(id) on delete restrict -- prevenir orfão
286
+ references public.roles(id) on delete set null -- preservar histórico
287
+ ```
288
+
289
+ ## Ver também
290
+
291
+ - [supabase-rls-policies](../supabase-rls-policies/SKILL.md) — anti-patterns RLS herdados (`(select auth.uid())` wrapper, no `user_metadata` em authz)
292
+ - [supabase-database-functions](../supabase-database-functions/SKILL.md) — padrões PG functions (security invoker, search_path = '')
293
+ - [supabase-postgres-style](../supabase-postgres-style/SKILL.md) — naming snake_case, lowercase reserved
294
+ - [multi-tenant-rls-hierarchy](../multi-tenant-rls-hierarchy/SKILL.md) — 4 helper functions PG canônicas + policies hierárquicas (Phase 108)
295
+ - [multi-tenant-performance-scaling](../multi-tenant-performance-scaling/SKILL.md) — Supavisor pooling + partitioning por `org_id` + MVs per-tenant (skill irmã)
296
+ - [rbac-permissions-matrix-supabase](../rbac-permissions-matrix-supabase/SKILL.md) — modelagem permissions action × resource × scope (Phase 108)
297
+ - [_shared-supabase/glossary.md](../_shared-supabase/glossary.md) — termos canônicos `app_metadata`, `service_role`
298
+ - [_shared-multi-tenant/glossary.md](../_shared-multi-tenant/glossary.md) — termos novos `tenant`, `org_id`, `super_admin`, `RBAC`
299
+ - [Supabase RLS Best Practices](https://makerkit.dev/blog/tutorials/supabase-rls-best-practices) — fonte external canônica
300
+ - [Custom Access Token Hook — Supabase Docs](https://supabase.com/docs/guides/auth/auth-hooks/custom-access-token-hook)