@luanpdd/kit-mcp 1.20.0 → 1.21.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 (259) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +648 -648
  3. package/gates/dept-cycle-prevention.md +179 -0
  4. package/gates/multi-tenant-rls-coverage.md +102 -0
  5. package/gates/service-role-not-in-user-facing.md +113 -0
  6. package/kit/COMANDOS.md +138 -138
  7. package/kit/README.md +52 -52
  8. package/kit/agents/advisor-researcher.md +106 -106
  9. package/kit/agents/assumptions-analyzer.md +107 -107
  10. package/kit/agents/audit-log-implementer.md +175 -0
  11. package/kit/agents/b2b-saas-architect.md +156 -0
  12. package/kit/agents/codebase-mapper.md +768 -768
  13. package/kit/agents/crm-pipeline-implementer.md +150 -0
  14. package/kit/agents/debugger.md +772 -772
  15. package/kit/agents/evolution-go-integrator.md +179 -0
  16. package/kit/agents/example-reviewer.md +21 -21
  17. package/kit/agents/executor.md +523 -523
  18. package/kit/agents/integration-checker.md +200 -200
  19. package/kit/agents/invite-flow-implementer.md +137 -0
  20. package/kit/agents/lgpd-compliance-auditor.md +206 -0
  21. package/kit/agents/multi-tenant-isolation-auditor.md +243 -0
  22. package/kit/agents/multi-tenant-rls-writer.md +262 -0
  23. package/kit/agents/nyquist-auditor.md +178 -178
  24. package/kit/agents/org-onboarding-implementer.md +202 -0
  25. package/kit/agents/phase-researcher.md +696 -696
  26. package/kit/agents/plan-checker.md +272 -272
  27. package/kit/agents/planner.md +891 -891
  28. package/kit/agents/project-researcher.md +652 -652
  29. package/kit/agents/research-synthesizer.md +245 -245
  30. package/kit/agents/roadmapper.md +677 -677
  31. package/kit/agents/super-admin-implementer.md +182 -0
  32. package/kit/agents/ui-auditor.md +437 -437
  33. package/kit/agents/ui-checker.md +302 -302
  34. package/kit/agents/ui-researcher.md +355 -355
  35. package/kit/agents/user-profiler.md +175 -175
  36. package/kit/agents/verifier.md +728 -728
  37. package/kit/commands/adicionar-backlog.md +75 -75
  38. package/kit/commands/adicionar-fase.md +42 -42
  39. package/kit/commands/adicionar-tarefa.md +45 -45
  40. package/kit/commands/adicionar-testes.md +41 -41
  41. package/kit/commands/ajuda.md +21 -21
  42. package/kit/commands/atualizar.md +37 -37
  43. package/kit/commands/auditar-marco.md +179 -179
  44. package/kit/commands/auditar-uat.md +23 -23
  45. package/kit/commands/autonomo.md +40 -40
  46. package/kit/commands/branch-pr.md +24 -24
  47. package/kit/commands/concluir-marco.md +247 -247
  48. package/kit/commands/configuracoes.md +36 -36
  49. package/kit/commands/definir-perfil.md +10 -10
  50. package/kit/commands/depurar.md +190 -190
  51. package/kit/commands/discutir-fase.md +131 -131
  52. package/kit/commands/entrar-discord.md +17 -17
  53. package/kit/commands/estatisticas.md +18 -18
  54. package/kit/commands/example-greeting.md +33 -33
  55. package/kit/commands/executar-fase.md +58 -58
  56. package/kit/commands/expresso.md +56 -56
  57. package/kit/commands/fase-ui.md +34 -34
  58. package/kit/commands/fazer.md +57 -57
  59. package/kit/commands/fio.md +125 -125
  60. package/kit/commands/fluxos-trabalho.md +64 -64
  61. package/kit/commands/forense.md +176 -176
  62. package/kit/commands/gerenciador.md +38 -38
  63. package/kit/commands/inserir-fase.md +31 -31
  64. package/kit/commands/limpeza.md +17 -17
  65. package/kit/commands/listar-hipoteses-fase.md +45 -45
  66. package/kit/commands/listar-workspaces.md +18 -18
  67. package/kit/commands/mapear-codebase.md +70 -70
  68. package/kit/commands/multi-tenant.md +163 -0
  69. package/kit/commands/nota.md +33 -33
  70. package/kit/commands/novo-marco.md +43 -43
  71. package/kit/commands/novo-projeto.md +41 -41
  72. package/kit/commands/novo-workspace.md +43 -43
  73. package/kit/commands/pausar-trabalho.md +37 -37
  74. package/kit/commands/perfil-usuario.md +45 -45
  75. package/kit/commands/pesquisar-fase.md +195 -195
  76. package/kit/commands/planejar-fase.md +67 -67
  77. package/kit/commands/planejar-lacunas.md +33 -33
  78. package/kit/commands/plantar-ideia.md +25 -25
  79. package/kit/commands/progresso.md +24 -24
  80. package/kit/commands/proximo.md +30 -30
  81. package/kit/commands/publicar.md +490 -490
  82. package/kit/commands/rapido.md +35 -35
  83. package/kit/commands/reaplicar-patches.md +124 -124
  84. package/kit/commands/relatorio-sessao.md +19 -19
  85. package/kit/commands/remover-fase.md +31 -31
  86. package/kit/commands/remover-workspace.md +26 -26
  87. package/kit/commands/resumo-marco.md +50 -50
  88. package/kit/commands/retomar-trabalho.md +40 -40
  89. package/kit/commands/revisar-backlog.md +60 -60
  90. package/kit/commands/revisar-ui.md +32 -32
  91. package/kit/commands/revisar.md +37 -37
  92. package/kit/commands/saude.md +21 -21
  93. package/kit/commands/setup-notion.md +93 -93
  94. package/kit/commands/sync-main.md +68 -68
  95. package/kit/commands/validar-fase.md +35 -35
  96. package/kit/commands/verificar-tarefas.md +44 -44
  97. package/kit/commands/verificar-trabalho.md +64 -64
  98. package/kit/file-manifest.json +30 -3
  99. package/kit/framework/bin/lib/commands.cjs +959 -959
  100. package/kit/framework/bin/lib/config.cjs +442 -442
  101. package/kit/framework/bin/lib/core.cjs +1230 -1230
  102. package/kit/framework/bin/lib/frontmatter.cjs +336 -336
  103. package/kit/framework/bin/lib/init.cjs +1442 -1442
  104. package/kit/framework/bin/lib/milestone.cjs +252 -252
  105. package/kit/framework/bin/lib/model-profiles.cjs +68 -68
  106. package/kit/framework/bin/lib/phase.cjs +888 -888
  107. package/kit/framework/bin/lib/profile-output.cjs +952 -952
  108. package/kit/framework/bin/lib/profile-pipeline.cjs +539 -539
  109. package/kit/framework/bin/lib/roadmap.cjs +329 -329
  110. package/kit/framework/bin/lib/security.cjs +382 -382
  111. package/kit/framework/bin/lib/state.cjs +1031 -1031
  112. package/kit/framework/bin/lib/template.cjs +222 -222
  113. package/kit/framework/bin/lib/uat.cjs +282 -282
  114. package/kit/framework/bin/lib/verify.cjs +888 -888
  115. package/kit/framework/bin/lib/workstream.cjs +491 -491
  116. package/kit/framework/bin/tools.cjs +918 -918
  117. package/kit/framework/commands/workstreams.md +63 -63
  118. package/kit/framework/references/checkpoints.md +778 -778
  119. package/kit/framework/references/continuation-format.md +249 -249
  120. package/kit/framework/references/decimal-phase-calculation.md +64 -64
  121. package/kit/framework/references/git-integration.md +295 -295
  122. package/kit/framework/references/git-planning-commit.md +38 -38
  123. package/kit/framework/references/model-profile-resolution.md +36 -36
  124. package/kit/framework/references/model-profiles.md +139 -139
  125. package/kit/framework/references/phase-argument-parsing.md +61 -61
  126. package/kit/framework/references/planning-config.md +202 -202
  127. package/kit/framework/references/questioning.md +162 -162
  128. package/kit/framework/references/tdd.md +263 -263
  129. package/kit/framework/references/ui-brand.md +160 -160
  130. package/kit/framework/references/user-profiling.md +657 -657
  131. package/kit/framework/references/verification-patterns.md +612 -612
  132. package/kit/framework/references/workstream-flag.md +58 -58
  133. package/kit/framework/templates/DEBUG.md +164 -164
  134. package/kit/framework/templates/UAT.md +265 -265
  135. package/kit/framework/templates/UI-SPEC.md +100 -100
  136. package/kit/framework/templates/VALIDATION.md +76 -76
  137. package/kit/framework/templates/claude-md.md +122 -122
  138. package/kit/framework/templates/codebase/architecture.md +185 -185
  139. package/kit/framework/templates/codebase/concerns.md +205 -205
  140. package/kit/framework/templates/codebase/conventions.md +204 -204
  141. package/kit/framework/templates/codebase/integrations.md +192 -192
  142. package/kit/framework/templates/codebase/stack.md +158 -158
  143. package/kit/framework/templates/codebase/structure.md +199 -199
  144. package/kit/framework/templates/codebase/testing.md +301 -301
  145. package/kit/framework/templates/config.json +44 -44
  146. package/kit/framework/templates/context.md +352 -352
  147. package/kit/framework/templates/continue-here.md +78 -78
  148. package/kit/framework/templates/copilot-instructions.md +7 -7
  149. package/kit/framework/templates/debug-subagent-prompt.md +91 -91
  150. package/kit/framework/templates/dev-preferences.md +20 -20
  151. package/kit/framework/templates/discovery.md +146 -146
  152. package/kit/framework/templates/discussion-log.md +63 -63
  153. package/kit/framework/templates/milestone-archive.md +123 -123
  154. package/kit/framework/templates/milestone.md +115 -115
  155. package/kit/framework/templates/phase-prompt.md +610 -610
  156. package/kit/framework/templates/planner-subagent-prompt.md +117 -117
  157. package/kit/framework/templates/project.md +186 -186
  158. package/kit/framework/templates/requirements.md +231 -231
  159. package/kit/framework/templates/research-project/ARCHITECTURE.md +204 -204
  160. package/kit/framework/templates/research-project/FEATURES.md +147 -147
  161. package/kit/framework/templates/research-project/PITFALLS.md +200 -200
  162. package/kit/framework/templates/research-project/STACK.md +120 -120
  163. package/kit/framework/templates/research-project/SUMMARY.md +170 -170
  164. package/kit/framework/templates/research.md +419 -419
  165. package/kit/framework/templates/retrospective.md +54 -54
  166. package/kit/framework/templates/roadmap.md +202 -202
  167. package/kit/framework/templates/state.md +176 -176
  168. package/kit/framework/templates/summary-complex.md +59 -59
  169. package/kit/framework/templates/summary-minimal.md +41 -41
  170. package/kit/framework/templates/summary-standard.md +48 -48
  171. package/kit/framework/templates/summary.md +209 -209
  172. package/kit/framework/templates/user-profile.md +146 -146
  173. package/kit/framework/templates/user-setup.md +256 -256
  174. package/kit/framework/templates/verification-report.md +258 -258
  175. package/kit/framework/workflows/add-phase.md +112 -112
  176. package/kit/framework/workflows/add-tests.md +351 -351
  177. package/kit/framework/workflows/add-todo.md +158 -158
  178. package/kit/framework/workflows/audit-milestone.md +340 -340
  179. package/kit/framework/workflows/audit-uat.md +109 -109
  180. package/kit/framework/workflows/autonomous.md +891 -891
  181. package/kit/framework/workflows/check-todos.md +177 -177
  182. package/kit/framework/workflows/cleanup.md +152 -152
  183. package/kit/framework/workflows/complete-milestone.md +696 -696
  184. package/kit/framework/workflows/diagnose-issues.md +231 -231
  185. package/kit/framework/workflows/discovery-phase.md +289 -289
  186. package/kit/framework/workflows/discuss-phase-assumptions.md +653 -653
  187. package/kit/framework/workflows/discuss-phase.md +784 -784
  188. package/kit/framework/workflows/do.md +104 -104
  189. package/kit/framework/workflows/execute-phase.md +838 -838
  190. package/kit/framework/workflows/execute-plan.md +510 -510
  191. package/kit/framework/workflows/fast.md +102 -102
  192. package/kit/framework/workflows/forensics.md +265 -265
  193. package/kit/framework/workflows/health.md +181 -181
  194. package/kit/framework/workflows/help.md +619 -619
  195. package/kit/framework/workflows/insert-phase.md +130 -130
  196. package/kit/framework/workflows/list-phase-assumptions.md +178 -178
  197. package/kit/framework/workflows/list-workspaces.md +56 -56
  198. package/kit/framework/workflows/manager.md +362 -362
  199. package/kit/framework/workflows/map-codebase.md +377 -377
  200. package/kit/framework/workflows/milestone-summary.md +223 -223
  201. package/kit/framework/workflows/new-milestone.md +486 -486
  202. package/kit/framework/workflows/new-project.md +1159 -1159
  203. package/kit/framework/workflows/new-workspace.md +237 -237
  204. package/kit/framework/workflows/next.md +97 -97
  205. package/kit/framework/workflows/node-repair.md +92 -92
  206. package/kit/framework/workflows/note.md +156 -156
  207. package/kit/framework/workflows/pause-work.md +176 -176
  208. package/kit/framework/workflows/plan-milestone-gaps.md +273 -273
  209. package/kit/framework/workflows/plan-phase.md +765 -765
  210. package/kit/framework/workflows/plant-seed.md +169 -169
  211. package/kit/framework/workflows/pr-branch.md +129 -129
  212. package/kit/framework/workflows/profile-user.md +450 -450
  213. package/kit/framework/workflows/progress.md +507 -507
  214. package/kit/framework/workflows/quick.md +757 -757
  215. package/kit/framework/workflows/remove-phase.md +155 -155
  216. package/kit/framework/workflows/remove-workspace.md +90 -90
  217. package/kit/framework/workflows/research-phase.md +82 -82
  218. package/kit/framework/workflows/resume-project.md +326 -326
  219. package/kit/framework/workflows/review.md +228 -228
  220. package/kit/framework/workflows/session-report.md +146 -146
  221. package/kit/framework/workflows/settings.md +283 -283
  222. package/kit/framework/workflows/ship.md +228 -228
  223. package/kit/framework/workflows/stats.md +60 -60
  224. package/kit/framework/workflows/transition.md +671 -671
  225. package/kit/framework/workflows/ui-phase.md +302 -302
  226. package/kit/framework/workflows/ui-review.md +165 -165
  227. package/kit/framework/workflows/update.md +323 -323
  228. package/kit/framework/workflows/validate-phase.md +174 -174
  229. package/kit/framework/workflows/verify-phase.md +252 -252
  230. package/kit/framework/workflows/verify-work.md +637 -637
  231. package/kit/hooks/check-update.js +118 -118
  232. package/kit/hooks/context-monitor.js +163 -163
  233. package/kit/hooks/prompt-guard.js +103 -103
  234. package/kit/hooks/statusline.js +125 -125
  235. package/kit/hooks/workflow-guard.js +101 -101
  236. package/kit/settings.json +45 -45
  237. package/kit/skills/_shared-multi-tenant/glossary.md +186 -0
  238. package/kit/skills/audit-log-multi-tenant/SKILL.md +334 -0
  239. package/kit/skills/b2b-saas-architecture/SKILL.md +300 -0
  240. package/kit/skills/crm-lead-pipeline-patterns/SKILL.md +326 -0
  241. package/kit/skills/evolution-go-whatsapp-integration/SKILL.md +322 -0
  242. package/kit/skills/example-skill/SKILL.md +42 -42
  243. package/kit/skills/lgpd-multi-tenant-compliance/SKILL.md +340 -0
  244. package/kit/skills/member-invite-flow/SKILL.md +305 -0
  245. package/kit/skills/member-management-react-shadcn/SKILL.md +328 -0
  246. package/kit/skills/multi-tenant-performance-scaling/SKILL.md +312 -0
  247. package/kit/skills/multi-tenant-rls-hierarchy/SKILL.md +338 -0
  248. package/kit/skills/org-onboarding-flow/SKILL.md +257 -0
  249. package/kit/skills/org-switcher-react-pattern/SKILL.md +349 -0
  250. package/kit/skills/permission-gate-react-pattern/SKILL.md +271 -0
  251. package/kit/skills/rbac-permissions-matrix-supabase/SKILL.md +301 -0
  252. package/kit/skills/super-admin-platform-pattern/SKILL.md +322 -0
  253. package/kit/skills/whatsapp-conversation-state-machine/SKILL.md +287 -0
  254. package/package.json +63 -63
  255. package/src/core/kit.js +216 -216
  256. package/src/core/reflect.js +247 -247
  257. package/src/core/reverse-sync.js +372 -372
  258. package/src/core/sync.js +418 -418
  259. package/src/core/watch.js +121 -121
@@ -0,0 +1,271 @@
1
+ ---
2
+ name: permission-gate-react-pattern
3
+ description: Use ao implementar permission gates React em B2B SaaS multi-tenant — CASL `@casl/ability` 6.8 + `@casl/react` 4.x para gates declarativos `<PermissionGate permission="leads:create">`, hook `usePermission(action, resource)`, anti-pattern explícito permission check só client (server-side enforcement obrigatório via RLS).
4
+ ---
5
+
6
+ # Permission Gate — React Pattern (CASL)
7
+
8
+ ## Quando usar
9
+
10
+ LLM carrega esta skill ao implementar gates de permissão UI em React. Trigger phrases:
11
+
12
+ - "permission gate React", "PermissionGate component"
13
+ - "CASL React permissions", "@casl/ability"
14
+ - "usePermission hook", "ability check React"
15
+ - "RBAC frontend gate"
16
+ - "client-side permission anti-pattern"
17
+
18
+ ## Regras absolutas
19
+
20
+ **REGRA #1 (UX-only, NUNCA segurança):** Permission gate React é **UX apenas**. Esconde botão para evitar erro 403 visível ao user. **Server-side enforcement obrigatório** via RLS (Phase 108) + `private.has_permission`.
21
+
22
+ **REGRA #2 (CASL canônico 2026):** `@casl/ability` v6.8+ + `@casl/react` v4.x é a biblioteca canônica para React. Isomorfica (frontend + backend), bundle pequeno (~5KB), API declarativa.
23
+
24
+ **REGRA #3 (build ability do JWT):** Construir `Ability` instance **uma vez** após login a partir das permissions do user (fetched via RPC). Re-build apenas após role change.
25
+
26
+ **REGRA #4 (Hook `usePermission` + componente `<PermissionGate>`):** Padrões canônicos:
27
+ - `usePermission(action, resource)` para condicionais inline
28
+ - `<PermissionGate permission="leads:create">{children}</PermissionGate>` para wrap declarativo
29
+
30
+ **REGRA #5 (sync com server após role change):** Após `assign_role` RPC, re-fetch permissions + rebuild Ability + update store. Sem isso, UI mostra cached state stale.
31
+
32
+ ## Patterns canônicos
33
+
34
+ ### Setup CASL — definir Ability
35
+
36
+ ```typescript
37
+ // lib/abilities/build-ability.ts
38
+ import { AbilityBuilder, Ability } from '@casl/ability'
39
+
40
+ export type Action = 'create' | 'read' | 'update' | 'delete' | 'invite' | 'remove' | 'export' | 'view' | 'process'
41
+ export type Subject = 'leads' | 'members' | 'org_settings' | 'audit_logs' | 'departments' | 'roles' | 'permissions' | 'dsr_requests' | 'all'
42
+
43
+ export type AppAbility = Ability<[Action, Subject]>
44
+
45
+ interface UserPermissions {
46
+ permissions: Array<{ action: Action; resource: Subject }>
47
+ isSuperAdmin: boolean
48
+ }
49
+
50
+ export function buildAbility({ permissions, isSuperAdmin }: UserPermissions): AppAbility {
51
+ const { can, build } = new AbilityBuilder<AppAbility>(Ability)
52
+
53
+ if (isSuperAdmin) {
54
+ can('manage' as any, 'all')
55
+ return build()
56
+ }
57
+
58
+ for (const p of permissions) {
59
+ can(p.action, p.resource)
60
+ }
61
+
62
+ return build()
63
+ }
64
+ ```
65
+
66
+ ### Buscar permissions do user (RPC)
67
+
68
+ ```sql
69
+ -- supabase RPC chamada após login
70
+ create or replace function public.get_user_permissions(p_org_id uuid)
71
+ returns table(action text, resource text)
72
+ language sql
73
+ stable
74
+ security invoker
75
+ set search_path = ''
76
+ as $$
77
+ select p.action, p.resource
78
+ from public.organization_members om
79
+ join public.role_permissions rp on rp.role_id = om.role_id
80
+ join public.permissions p on p.id = rp.permission_id
81
+ where om.org_id = p_org_id
82
+ and om.user_id = (select auth.uid())
83
+ and om.status = 'active';
84
+ $$;
85
+
86
+ grant execute on function public.get_user_permissions(uuid) to authenticated;
87
+ ```
88
+
89
+ ### Provider — Ability disponível em toda app
90
+
91
+ ```typescript
92
+ // app/providers/AbilityProvider.tsx
93
+ 'use client'
94
+
95
+ import { createContext, useEffect, useState } from 'react'
96
+ import { AppAbility, buildAbility } from '@/lib/abilities/build-ability'
97
+ import { useOrgStore } from '@/lib/stores/org-store'
98
+ import { supabase } from '@/lib/supabase'
99
+
100
+ export const AbilityContext = createContext<AppAbility | null>(null)
101
+
102
+ export function AbilityProvider({ children }: { children: React.ReactNode }) {
103
+ const [ability, setAbility] = useState<AppAbility | null>(null)
104
+ const activeOrgId = useOrgStore(s => s.activeOrgId)
105
+
106
+ useEffect(() => {
107
+ if (!activeOrgId) return
108
+
109
+ async function load() {
110
+ // REGRA #3: build ability do server data
111
+ const { data: { user } } = await supabase.auth.getUser()
112
+ const isSuperAdmin = user?.app_metadata.super_admin === true
113
+
114
+ const { data: permissions } = await supabase
115
+ .rpc('get_user_permissions', { p_org_id: activeOrgId })
116
+
117
+ setAbility(buildAbility({ permissions: permissions || [], isSuperAdmin }))
118
+ }
119
+ load()
120
+ }, [activeOrgId])
121
+
122
+ return <AbilityContext.Provider value={ability}>{children}</AbilityContext.Provider>
123
+ }
124
+
125
+ // Hook para acessar ability
126
+ import { useContext } from 'react'
127
+ export function useAbility() {
128
+ const ability = useContext(AbilityContext)
129
+ if (!ability) throw new Error('useAbility must be inside AbilityProvider')
130
+ return ability
131
+ }
132
+ ```
133
+
134
+ ### Hook `usePermission` (REGRA #4)
135
+
136
+ ```typescript
137
+ // lib/hooks/use-permission.ts
138
+ import { useAbility } from '@/app/providers/AbilityProvider'
139
+ import { Action, Subject } from '@/lib/abilities/build-ability'
140
+
141
+ export function usePermission(action: Action, resource: Subject): boolean {
142
+ const ability = useAbility()
143
+ return ability.can(action, resource)
144
+ }
145
+
146
+ // Usage:
147
+ function LeadsPage() {
148
+ const canCreateLead = usePermission('create', 'leads')
149
+ return (
150
+ <div>
151
+ <h1>Leads</h1>
152
+ {canCreateLead && <Button onClick={openCreateModal}>+ Novo Lead</Button>}
153
+ </div>
154
+ )
155
+ }
156
+ ```
157
+
158
+ ### Componente `<PermissionGate>` (REGRA #4)
159
+
160
+ ```typescript
161
+ // components/PermissionGate.tsx
162
+ import { useAbility } from '@/app/providers/AbilityProvider'
163
+ import type { Action, Subject } from '@/lib/abilities/build-ability'
164
+
165
+ interface Props {
166
+ permission: `${Action}:${Subject}`
167
+ fallback?: React.ReactNode
168
+ children: React.ReactNode
169
+ }
170
+
171
+ export function PermissionGate({ permission, fallback = null, children }: Props) {
172
+ const ability = useAbility()
173
+ const [action, subject] = permission.split(':') as [Action, Subject]
174
+
175
+ if (ability.can(action, subject)) {
176
+ return <>{children}</>
177
+ }
178
+ return <>{fallback}</>
179
+ }
180
+
181
+ // Usage:
182
+ <PermissionGate permission="leads:create">
183
+ <Button onClick={openCreateModal}>+ Novo Lead</Button>
184
+ </PermissionGate>
185
+
186
+ <PermissionGate
187
+ permission="org_settings:update"
188
+ fallback={<p>Você não tem permissão para alterar configurações.</p>}
189
+ >
190
+ <SettingsForm />
191
+ </PermissionGate>
192
+ ```
193
+
194
+ ### Refresh ability após role change (REGRA #5)
195
+
196
+ ```typescript
197
+ // Em algum lugar após mudança de role (admin UI)
198
+ async function changeRole(targetUserId: string, newRoleId: string) {
199
+ await supabase.rpc('assign_role', { ... })
200
+ await supabase.auth.refreshSession() // JWT (cross-ref org-switcher)
201
+
202
+ // REGRA #5: re-fetch + rebuild ability
203
+ // Trigger AbilityProvider re-fetch via mudança em activeOrgId timestamp
204
+ // (use store version increment)
205
+ useOrgStore.getState().bumpVersion()
206
+ }
207
+ ```
208
+
209
+ ## Anti-patterns
210
+
211
+ ### Anti-pattern 1: Permission check SÓ frontend (sem RLS)
212
+
213
+ **Errado:**
214
+ ```typescript
215
+ { ability.can('delete', 'leads') && <DeleteButton onClick={() => api.delete(`/leads/${id}`)} /> }
216
+ // Mas API endpoint não checa permission server-side
217
+ ```
218
+
219
+ **Por quê:** REGRA #1 — atacante chama `curl -X DELETE /leads/...` direto, ignora gate React. Frontend gate é segurança teatro.
220
+
221
+ **Certo:** RLS no Supabase com `private.has_permission` (Phase 108) + frontend gate como UX redundância.
222
+
223
+ ### Anti-pattern 2: Hard-coded role check em vez de permission
224
+
225
+ **Errado:**
226
+ ```typescript
227
+ { user.role === 'admin' && <Button>Convidar</Button> }
228
+ ```
229
+
230
+ **Por quê:** custom roles quebram. Custom role com permission `members:invite` deveria mostrar botão, mas não passa no check `=== 'admin'`. Acopla UI a role names.
231
+
232
+ **Certo:** `usePermission('invite', 'members')` — funciona com qualquer role que tenha a permission.
233
+
234
+ ### Anti-pattern 3: Re-fetch permissions a cada render
235
+
236
+ **Errado:**
237
+ ```typescript
238
+ function MyComponent() {
239
+ const [perms, setPerms] = useState([])
240
+ useEffect(() => {
241
+ supabase.rpc('get_user_permissions', { ... }).then(setPerms)
242
+ }) // sem deps array — re-fetch infinito
243
+ }
244
+ ```
245
+
246
+ **Por quê:** N requests/min para Supabase, performance terrível.
247
+
248
+ **Certo:** REGRA #3 — build Ability uma vez no Provider, consume via `useAbility()` hook.
249
+
250
+ ### Anti-pattern 4: Esquecer fallback em PermissionGate
251
+
252
+ **Errado:**
253
+ ```typescript
254
+ <PermissionGate permission="org_settings:update">
255
+ <SettingsForm />
256
+ </PermissionGate>
257
+ // User sem permission vê página vazia, sem feedback
258
+ ```
259
+
260
+ **Por quê:** UX confusa — user não entende por que página é em branco.
261
+
262
+ **Certo:** sempre passar `fallback` com mensagem clara ("Você não tem permissão...").
263
+
264
+ ## Ver também
265
+
266
+ - [org-switcher-react-pattern](../org-switcher-react-pattern/SKILL.md) — sibling, OrgProvider + zustand store
267
+ - [member-management-react-shadcn](../member-management-react-shadcn/SKILL.md) — sibling, usa PermissionGate
268
+ - [rbac-permissions-matrix-supabase](../rbac-permissions-matrix-supabase/SKILL.md) — Phase 108, modelagem permissions
269
+ - [multi-tenant-rls-hierarchy](../multi-tenant-rls-hierarchy/SKILL.md) — Phase 108, server-side RLS enforcement
270
+ - [_shared-multi-tenant/glossary.md](../_shared-multi-tenant/glossary.md) — `permission gate`, `CASL`, `JWT stale`
271
+ - [CASL Documentation](https://casl.js.org/)
@@ -0,0 +1,301 @@
1
+ ---
2
+ name: rbac-permissions-matrix-supabase
3
+ description: Use ao modelar RBAC granular em Supabase B2B — permission strings resource:action, matrix N:M roles ↔ permissions, regra "user só atribui roles ≤ ao próprio", 3 roles built-in (owner/admin/member) + custom permitidos.
4
+ ---
5
+
6
+ # RBAC Permissions Matrix — Supabase B2B Multi-Tenant
7
+
8
+ ## Quando usar
9
+
10
+ LLM carrega esta skill ao desenhar autorização granular em B2B SaaS multi-tenant. Trigger phrases:
11
+
12
+ - "RBAC granular", "permission matrix"
13
+ - "permission string resource:action", "leads:create", "members:invite"
14
+ - "custom roles", "role escalation rule"
15
+ - "owner admin member built-in"
16
+ - "role permissions table"
17
+
18
+ ## Regras absolutas
19
+
20
+ **REGRA #1 (permission string format):** Permissions são strings `<resource>:<action>` em snake_case (ex: `leads:create`, `members:invite`, `org_settings:update`). Padrão convergente 2026 (Stripe, Linear, Auth0).
21
+
22
+ **REGRA #2 (3 roles built-in mínimo):** Toda org tem 3 roles built-in com `is_built_in = true`:
23
+ - `owner` — full control (criação org, billing, transfer ownership, delete org)
24
+ - `admin` — manage members, settings, all data
25
+ - `member` — operações standard (CRUD nos recursos da org)
26
+
27
+ **REGRA #3 (role escalation rule):** Usuário só pode **criar/atribuir roles ≤ ao próprio role**. Member não pode criar admin. Admin não pode criar owner. Owner pode tudo. Enforced via policy + frontend gate.
28
+
29
+ **REGRA #4 (custom roles permitidos):** Custom roles via `is_built_in = false` na mesma tabela `roles`. Org-scoped (não globais). Built-in não podem ser deletados (constraint).
30
+
31
+ **REGRA #5 (NUNCA permission string em frontend hard-coded para enforce):** Permission gate React (skill [`permission-gate-react-pattern`](../permission-gate-react-pattern/SKILL.md)) é UX apenas. Server-side enforcement obrigatório via RLS + `private.has_permission`.
32
+
33
+ ## Patterns canônicos
34
+
35
+ ### Permission catalog — eventos canônicos
36
+
37
+ ```sql
38
+ -- Catálogo global (compartilhado entre orgs)
39
+ insert into public.permissions (action, resource, description) values
40
+ -- Members
41
+ ('invite', 'members', 'Convidar novos membros via email'),
42
+ ('remove', 'members', 'Remover membros existentes'),
43
+ ('update', 'members', 'Atualizar role/status de membros'),
44
+ ('list', 'members', 'Listar membros da org'),
45
+
46
+ -- Org settings
47
+ ('update', 'org_settings', 'Atualizar configurações gerais da org'),
48
+ ('update', 'org_billing', 'Acessar/alterar billing (Stripe)'),
49
+
50
+ -- Departments
51
+ ('create', 'departments', 'Criar departamentos'),
52
+ ('update', 'departments', 'Atualizar departamentos'),
53
+ ('delete', 'departments', 'Deletar departamentos'),
54
+
55
+ -- Roles + Permissions
56
+ ('create', 'roles', 'Criar custom roles'),
57
+ ('update', 'roles', 'Atualizar role permissions'),
58
+ ('delete', 'roles', 'Deletar custom roles (built-in protegidos)'),
59
+
60
+ -- Domain example: leads (CRM)
61
+ ('create', 'leads', 'Criar leads'),
62
+ ('update', 'leads', 'Atualizar leads'),
63
+ ('delete', 'leads', 'Deletar leads'),
64
+ ('export', 'leads', 'Exportar leads (CSV/JSON)'),
65
+
66
+ -- Audit
67
+ ('view', 'audit_logs', 'Ver audit logs'),
68
+ ('export', 'audit_logs', 'Exportar audit logs'),
69
+
70
+ -- LGPD
71
+ ('process', 'dsr_requests', 'Processar Data Subject Requests'),
72
+
73
+ on conflict (action, resource) do nothing;
74
+ ```
75
+
76
+ ### 3 roles built-in com permissions default
77
+
78
+ ```sql
79
+ -- Para cada nova org (idealmente em RPC create_organization), criar built-in roles
80
+ -- com permissions atribuídas.
81
+
82
+ -- OWNER — todas permissions
83
+ insert into public.role_permissions (role_id, permission_id)
84
+ select
85
+ r.id,
86
+ p.id
87
+ from public.roles r
88
+ cross join public.permissions p
89
+ where r.org_id = '<org_id>'
90
+ and r.name = 'owner';
91
+
92
+ -- ADMIN — tudo exceto org_billing + delete org
93
+ insert into public.role_permissions (role_id, permission_id)
94
+ select
95
+ r.id,
96
+ p.id
97
+ from public.roles r
98
+ cross join public.permissions p
99
+ where r.org_id = '<org_id>'
100
+ and r.name = 'admin'
101
+ and not (p.action = 'update' and p.resource = 'org_billing');
102
+
103
+ -- MEMBER — operações CRUD em domínio (sem members management)
104
+ insert into public.role_permissions (role_id, permission_id)
105
+ select
106
+ r.id,
107
+ p.id
108
+ from public.roles r
109
+ cross join public.permissions p
110
+ where r.org_id = '<org_id>'
111
+ and r.name = 'member'
112
+ and p.resource in ('leads', 'departments')
113
+ and p.action in ('create', 'update', 'list');
114
+ ```
115
+
116
+ ### Role escalation rule — enforcement via RPC + RLS
117
+
118
+ ```sql
119
+ -- Função que retorna o "rank" de uma role (owner=3, admin=2, member=1, custom=0)
120
+ create or replace function private.role_rank(p_role_name text)
121
+ returns int
122
+ language sql
123
+ stable
124
+ security invoker
125
+ set search_path = ''
126
+ as $$
127
+ select case p_role_name
128
+ when 'owner' then 3
129
+ when 'admin' then 2
130
+ when 'member' then 1
131
+ else 0 -- custom roles têm rank 0 (não comparáveis)
132
+ end;
133
+ $$;
134
+
135
+ -- RPC que assign role a um membro — só permite role ≤ ao próprio
136
+ create or replace function public.assign_role(
137
+ p_org_id uuid,
138
+ p_target_user_id uuid,
139
+ p_role_id uuid
140
+ )
141
+ returns void
142
+ language plpgsql
143
+ security invoker
144
+ set search_path = ''
145
+ as $$
146
+ declare
147
+ caller_role_name text;
148
+ target_role_name text;
149
+ begin
150
+ -- 1. Buscar role do caller na org
151
+ select r.name into caller_role_name
152
+ from public.organization_members om
153
+ join public.roles r on r.id = om.role_id
154
+ where om.org_id = p_org_id
155
+ and om.user_id = (select auth.uid())
156
+ and om.status = 'active';
157
+
158
+ if caller_role_name is null then
159
+ raise exception 'caller is not member of org';
160
+ end if;
161
+
162
+ -- 2. Buscar role alvo
163
+ select r.name into target_role_name
164
+ from public.roles r
165
+ where r.id = p_role_id and r.org_id = p_org_id;
166
+
167
+ if target_role_name is null then
168
+ raise exception 'role does not exist in org';
169
+ end if;
170
+
171
+ -- 3. REGRA #3: caller role rank >= target role rank
172
+ if private.role_rank(caller_role_name) < private.role_rank(target_role_name) then
173
+ raise exception
174
+ 'role escalation forbidden: caller is %, cannot assign %',
175
+ caller_role_name, target_role_name;
176
+ end if;
177
+
178
+ -- 4. Assign
179
+ update public.organization_members
180
+ set role_id = p_role_id
181
+ where org_id = p_org_id and user_id = p_target_user_id;
182
+ end;
183
+ $$;
184
+
185
+ grant execute on function public.assign_role(uuid, uuid, uuid) to authenticated;
186
+ ```
187
+
188
+ ### Frontend — listar roles que user pode atribuir
189
+
190
+ ```typescript
191
+ // Buscar roles que current user pode atribuir (rank ≤ próprio)
192
+ const { data: assignableRoles } = await supabase
193
+ .from('roles')
194
+ .select('id, name, description')
195
+ .eq('org_id', orgId)
196
+ // RPC retorna apenas roles que caller pode atribuir
197
+ .rpc('list_assignable_roles', { p_org_id: orgId })
198
+ ```
199
+
200
+ ### RLS policy usando `private.has_permission`
201
+
202
+ ```sql
203
+ -- Tabela leads — INSERT requer permission leads:create
204
+ create policy "leads_insert_with_permission"
205
+ on public.leads
206
+ for insert
207
+ to authenticated
208
+ with check (
209
+ private.has_permission('create', 'leads', org_id)
210
+ );
211
+
212
+ -- Tabela members management — UPDATE role requer permission members:update
213
+ create policy "members_update_role_with_permission"
214
+ on public.organization_members
215
+ for update
216
+ to authenticated
217
+ using (
218
+ private.has_permission('update', 'members', org_id)
219
+ )
220
+ with check (
221
+ private.has_permission('update', 'members', org_id)
222
+ );
223
+ ```
224
+
225
+ ## Anti-patterns
226
+
227
+ ### Anti-pattern 1: Permission string sem padrão
228
+
229
+ **Errado:**
230
+ ```sql
231
+ -- Mistura formats
232
+ 'canCreateLeads', 'leads.create', 'CREATE_LEAD', 'leads:write'
233
+ ```
234
+
235
+ **Por quê:** inconsistência confunde devs (qual é a forma certa?), quebra autocomplete, dificulta migração.
236
+
237
+ **Certo:** sempre `<resource>:<action>` em snake_case (REGRA #1). Pode usar enum em TypeScript:
238
+ ```typescript
239
+ type Permission = `${Resource}:${Action}`
240
+ ```
241
+
242
+ ### Anti-pattern 2: Hard-coded role check em vez de permission
243
+
244
+ **Errado:**
245
+ ```typescript
246
+ // Permission gate frontend
247
+ { user.role === 'admin' && <Button>Convidar</Button> }
248
+ ```
249
+
250
+ **Por quê:** custom roles quebram (custom role com permission `members:invite` não passa no check). Acopla UI a roles built-in.
251
+
252
+ **Certo:**
253
+ ```typescript
254
+ { usePermission('invite', 'members') && <Button>Convidar</Button> }
255
+ ```
256
+
257
+ E server-side: RLS com `private.has_permission`.
258
+
259
+ ### Anti-pattern 3: Built-in role pode ser deletada
260
+
261
+ **Errado:**
262
+ ```sql
263
+ -- Sem proteção
264
+ delete from public.roles where name = 'owner' and org_id = '...';
265
+ -- Org fica sem owner, ninguém consegue fazer nada
266
+ ```
267
+
268
+ **Por quê:** org sem owner é unrecoverable sem service_role intervention. Compromete recovery.
269
+
270
+ **Certo:** policy DELETE em `roles` que rejeita built-in:
271
+ ```sql
272
+ create policy "roles_delete_custom_only"
273
+ on public.roles
274
+ for delete
275
+ to authenticated
276
+ using (
277
+ not is_built_in
278
+ and private.has_permission('delete', 'roles', org_id)
279
+ );
280
+ ```
281
+
282
+ ### Anti-pattern 4: Frontend permission gate sem server-side enforce
283
+
284
+ **Errado:**
285
+ ```typescript
286
+ // Esconder botão UI = "segurança"
287
+ { usePermission('delete', 'leads') && <DeleteButton /> }
288
+ // Mas API endpoint /leads/{id} aceita DELETE sem checar permission
289
+ ```
290
+
291
+ **Por quê:** atacante chama API direto via curl — ignora gate frontend. Permission gate React é **UX**, não segurança.
292
+
293
+ **Certo:** REGRA #5. Server-side via RLS + `private.has_permission` é enforcement real.
294
+
295
+ ## Ver também
296
+
297
+ - [multi-tenant-rls-hierarchy](../multi-tenant-rls-hierarchy/SKILL.md) — `private.has_permission` é a função canônica usada em policies
298
+ - [b2b-saas-architecture](../b2b-saas-architecture/SKILL.md) — schema das tabelas `roles`, `permissions`, `role_permissions`
299
+ - [permission-gate-react-pattern](../permission-gate-react-pattern/SKILL.md) — Phase 115, permission gate UX em React
300
+ - [super-admin-platform-pattern](../super-admin-platform-pattern/SKILL.md) — Phase 111, super_admin bypassa RBAC normal
301
+ - [_shared-multi-tenant/glossary.md](../_shared-multi-tenant/glossary.md) — termos `RBAC`, `permission matrix`, `role escalation rule`