@luanpdd/kit-mcp 1.22.0 → 1.27.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 (41) hide show
  1. package/README.md +267 -1
  2. package/kit/agents/audit-log-implementer.md +138 -0
  3. package/kit/agents/auditor-consistencia-isolamento.md +33 -0
  4. package/kit/agents/crm-pipeline-implementer.md +89 -0
  5. package/kit/agents/debugger.md +41 -0
  6. package/kit/agents/evolution-go-integrator.md +21 -0
  7. package/kit/agents/executor.md +41 -0
  8. package/kit/agents/invite-flow-implementer.md +52 -0
  9. package/kit/agents/lgpd-compliance-auditor.md +89 -0
  10. package/kit/agents/multi-tenant-rls-writer.md +78 -0
  11. package/kit/agents/org-onboarding-implementer.md +21 -0
  12. package/kit/agents/planner.md +31 -0
  13. package/kit/agents/release-pipeline-auditor.md +11 -0
  14. package/kit/agents/supabase-architect.md +31 -0
  15. package/kit/agents/supabase-auth-bootstrapper.md +80 -0
  16. package/kit/agents/supabase-branching-architect.md +562 -0
  17. package/kit/agents/supabase-cicd-pipeline-implementer.md +777 -0
  18. package/kit/agents/supabase-column-privileges-writer.md +399 -0
  19. package/kit/agents/supabase-migration-writer.md +141 -14
  20. package/kit/agents/supabase-rbac-implementer.md +392 -0
  21. package/kit/agents/supabase-rls-hardener.md +521 -0
  22. package/kit/agents/supabase-rls-writer.md +105 -9
  23. package/kit/agents/supabase-roles-implementer.md +355 -0
  24. package/kit/agents/super-admin-implementer.md +99 -0
  25. package/kit/commands/supabase.md +55 -8
  26. package/kit/file-manifest.json +40 -25
  27. package/kit/skills/_shared-supabase/glossary.md +37 -0
  28. package/kit/skills/rbac-permissions-matrix-supabase/SKILL.md +37 -0
  29. package/kit/skills/supabase-branching-workflow/SKILL.md +544 -0
  30. package/kit/skills/supabase-ci-cd-github-actions/SKILL.md +880 -0
  31. package/kit/skills/supabase-column-level-security/SKILL.md +426 -0
  32. package/kit/skills/supabase-config-toml-remotes/SKILL.md +807 -0
  33. package/kit/skills/supabase-custom-claims-rbac/SKILL.md +472 -0
  34. package/kit/skills/supabase-database-functions/SKILL.md +85 -0
  35. package/kit/skills/supabase-migration-repair/SKILL.md +823 -0
  36. package/kit/skills/supabase-migrations/SKILL.md +123 -11
  37. package/kit/skills/supabase-pgtap-testing/SKILL.md +1053 -0
  38. package/kit/skills/supabase-postgres-roles/SKILL.md +392 -0
  39. package/kit/skills/supabase-rls-defense-in-depth/SKILL.md +418 -0
  40. package/kit/skills/supabase-rls-policies/SKILL.md +462 -12
  41. package/package.json +1 -1
@@ -521,3 +521,44 @@ Separado dos commits por tarefa — captura apenas os resultados de execução.
521
521
 
522
522
  Inclua TODOS os commits (anteriores + novos se agente de continuação).
523
523
  </completion_format>
524
+
525
+ <sql_auto_handoff_cooperativo>
526
+ ## SQL auto-handoff cooperativo (v1.23 — CROSS-10)
527
+
528
+ Ao executar PLAN.md que produz SQL/DDL (CREATE TABLE, CREATE POLICY, etc.), **antes** de aplicar via `mcp__supabase__apply_migration` ou escrever arquivo `supabase/migrations/`, faça handoff cooperativo para `supabase-rls-hardener`.
529
+
530
+ **Heurística de detecção (regex no SQL gerado):**
531
+
532
+ ```regex
533
+ (create\s+table|create\s+policy|create\s+view|alter\s+table|create\s+function.*security\s+definer|grant\s+.*on|enable\s+row\s+level\s+security)
534
+ ```
535
+
536
+ Se ≥ 1 match → invoca handoff:
537
+
538
+ ```python
539
+ hardener_result = Task(
540
+ subagent_type="supabase-rls-hardener",
541
+ prompt=f"""
542
+ <upstream_intent>
543
+ Source agent: executor
544
+ Original goal: aplicar SQL definido em {plan_file}
545
+ Constraints: {plan_constraints if available else 'follow plan as-is'}
546
+ </upstream_intent>
547
+
548
+ <draft_sql>{generated_sql}</draft_sql>
549
+
550
+ <user_facing_caller>true</user_facing_caller>
551
+ """
552
+ )
553
+ ```
554
+
555
+ **Processamento de verdict:**
556
+ - **GO** → aplica SQL direto sem mudanças
557
+ - **STRENGTHEN** → aplica diff sugerido (ajustes mantendo intent); registra no commit message + SUMMARY.md
558
+ - **REWRITE** → se user_facing_caller=true, PAUSA execução e pede confirmação ao usuário; sem confirmação, não aplica
559
+
560
+ **Princípio canônico v1.23:** Executor faz (aplica plan); supabase-rls-hardener hardena (valida defense-in-depth). Conflitos viram diff explícito, nunca abortos silenciosos.
561
+
562
+ **Registro em SUMMARY.md:** se hardener veredict ≠ GO, SUMMARY.md inclui section "## RLS Hardener Trace" com verdict + diff aplicado + justificativa.
563
+
564
+ </sql_auto_handoff_cooperativo>
@@ -128,8 +128,60 @@ INVITE-FLOW-IMPLEMENTER · output integrado
128
128
  - Histogram `invite.accept_latency_ms` (tempo entre create e accept)
129
129
  - Alarme se `invite.created.count > bulk_limit_per_hour` por org → suspeita de abuso
130
130
 
131
+ ## Cooperative handoff to supabase-rls-hardener (v1.23)
132
+
133
+ Após gerar CREATE TABLE org_invites + RPC create_invite/accept_invite + cron expire pending, faça handoff cooperativo para SQL bloco:
134
+
135
+ ```python
136
+ Task(subagent_type="supabase-rls-hardener", prompt=f"""
137
+ <upstream_intent>
138
+ Source agent: invite-flow-implementer
139
+ Original goal: implementar invite flow B2B com token-based para {org_context}
140
+ Constraints: token SHA-256 (raw enviado por email, hash no banco); TTL 7d single-use; state machine 5 estados (pending→accepted|rejected|cancelled|expired); email-lock obrigatório; idempotência via FOR UPDATE em transação
141
+ </upstream_intent>
142
+
143
+ <draft_sql>{generated_invites_sql}</draft_sql>
144
+
145
+ <user_facing_caller>true</user_facing_caller>
146
+ """)
147
+ ```
148
+
149
+ Hardener valida token security (hash apenas no DB), RPC com SECURITY DEFINER em schema private, RLS por org_id. **NUNCA descarte intent upstream silenciosamente**.
150
+
151
+ ## Cooperative handoff column-level (v1.24 — CROSS-15)
152
+
153
+ `org_invites.token_raw` é gerado durante create do invite (raw enviado por email, hash armazenado). Após email enviado, **nenhum role além de service_role** deve poder ler o raw — é segredo de uso único. Aplique handoff cooperativo column-level:
154
+
155
+ ```python
156
+ Task(subagent_type="supabase-column-privileges-writer", prompt=f"""
157
+ <upstream_intent>
158
+ Source agent: invite-flow-implementer
159
+ Original goal: token raw column (org_invites.token_raw) legível APENAS para service_role pós-criação
160
+ Constraints: token_raw é segredo único, enviado por email durante create; hash armazenado para validation em accept; raw NUNCA visível em REST API; member_invited audit event não logga token_raw
161
+ </upstream_intent>
162
+
163
+ <table>schema: public, name: org_invites</table>
164
+
165
+ <sensitive_columns>
166
+ - token_raw (text — segredo, apenas service_role)
167
+ </sensitive_columns>
168
+
169
+ <allowed_roles>
170
+ - service_role: SELECT all (incluindo token_raw — usado durante envio de email)
171
+ - authenticated: SELECT (id, org_id, email, role, status, expires_at, created_at, accepted_at) — sem token_raw
172
+ - anon: SELECT (status) — minimal, para "this invite is still valid?" check pre-login
173
+ </allowed_roles>
174
+
175
+ <user_facing_caller>true</user_facing_caller>
176
+ """)
177
+ ```
178
+
179
+ **Caveat:** mesmo com column-level, considere também armazenar APENAS o hash do token (não o raw) na tabela. token_raw fica em memory durante envio do email e descartado. Isso é defense-in-depth Camada 9 (não armazenar segredos).
180
+
131
181
  ## Ver também
132
182
 
183
+ - [supabase-rls-hardener](./supabase-rls-hardener.md) — canonical handoff target v1.23
184
+ - [supabase-column-privileges-writer](./supabase-column-privileges-writer.md) — canonical handoff target v1.24 (column-level token raw)
133
185
  - [member-invite-flow](../skills/member-invite-flow/SKILL.md) — base de conhecimento
134
186
  - [supabase-migration-writer](./supabase-migration-writer.md) — invoked via Task() para SQL
135
187
  - [supabase-edge-fn-writer](./supabase-edge-fn-writer.md) — invoked via Task() para Edge Function
@@ -197,8 +197,97 @@ Se ausente OU regions diferentes de `gru1` / `sa-east-1` → P2 informacional.
197
197
  - Counter `lgpd.audit.gaps.found{severity}` por execução
198
198
  - Histogram `lgpd.audit.duration_ms`
199
199
 
200
+ ## Cooperative handoff to supabase-rls-hardener (v1.23)
201
+
202
+ Após gerar DSR table + Art. 18 right workflows + erasure via anonymization, faça handoff cooperativo para SQL bloco:
203
+
204
+ ```python
205
+ Task(subagent_type="supabase-rls-hardener", prompt=f"""
206
+ <upstream_intent>
207
+ Source agent: lgpd-compliance-auditor
208
+ Original goal: implementar LGPD compliance per-tenant (9 direitos Art. 18) para {org_context}
209
+ Constraints: DSR SLA 15 dias (Art. 19) com alert pg_cron D-3; consent default opt-out (Art. 8 §5); erasure via anonymization (UUID preserved + PII NULL/hash); cross-border config (gru1 Vercel + sa-east-1 Supabase); PII sanitization em audit_logs (cross-ref Phase 109)
210
+ </upstream_intent>
211
+
212
+ <draft_sql>{generated_dsr_sql}</draft_sql>
213
+
214
+ <user_facing_caller>true</user_facing_caller>
215
+ """)
216
+ ```
217
+
218
+ Hardener valida pseudonymization correto, retention policies via pg_cron, PII sanitization em audit_logs. **NUNCA descarte intent upstream silenciosamente**.
219
+
220
+ ## Cooperative handoff Postgres Roles (v1.26 — CROSS-20)
221
+
222
+ Crie role `dpo_role` (Data Protection Officer) para acessar DSR requests + erasure operations. Role dedicado em vez de service_role API key permite audit trail granular para compliance LGPD/GDPR.
223
+
224
+ ```python
225
+ Task(subagent_type="supabase-roles-implementer", prompt=f"""
226
+ <upstream_intent>
227
+ Source agent: lgpd-compliance-auditor
228
+ Original goal: criar role dpo_role para DSR access + erasure operations (LGPD Art. 18 compliance)
229
+ Constraints: BYPASSRLS necessário (DPO precisa ver todos requests cross-org); column-level GRANT em PII columns (cross-ref v1.24 CROSS-12); login com password forte; audit obrigatório
230
+ </upstream_intent>
231
+
232
+ <roles_to_create>
233
+ - name: dpo_role
234
+ type: user
235
+ login: true
236
+ password_source: vault
237
+ bypassrls: true
238
+ inherit: false
239
+ description: "Data Protection Officer. Acesso DSR requests + erasure operations. LGPD Art. 18."
240
+ owner: "dpo@company.com"
241
+ </roles_to_create>
242
+
243
+ <grants>
244
+ dpo_role:
245
+ - schema: public, usage: true
246
+ - table: public.dsr_requests, ops: [SELECT, INSERT, UPDATE]
247
+ - table: public.audit_log, ops: [SELECT] # column-level já em payload
248
+ </grants>
249
+
250
+ <use_case>system_access</use_case>
251
+ <user_facing_caller>true</user_facing_caller>
252
+ """)
253
+ ```
254
+
255
+ ## Cooperative handoff column-level (v1.24 — CROSS-12)
256
+
257
+ DSR (Data Subject Request) workflow precisa de erasure granular por coluna — não só DELETE row, mas anonymize PII columns específicas. Cross-border PII restriction (gru1 Vercel + sa-east-1 Supabase) também requer column-level audit. Aplique handoff cooperativo:
258
+
259
+ ```python
260
+ Task(subagent_type="supabase-column-privileges-writer", prompt=f"""
261
+ <upstream_intent>
262
+ Source agent: lgpd-compliance-auditor
263
+ Original goal: implementar DSR + erasure por coluna + cross-border PII restriction para LGPD Art. 18 compliance
264
+ Constraints: DSR table tem colunas PII (subject_email, subject_phone, subject_address); erasure via anonymization (não DELETE); legível só por dpo_role + service_role; cross-border config sa-east-1 obrigatório
265
+ </upstream_intent>
266
+
267
+ <table>schema: public, name: dsr_requests</table>
268
+
269
+ <sensitive_columns>
270
+ - subject_email
271
+ - subject_phone
272
+ - subject_address
273
+ - subject_metadata (jsonb — pode ter info sensível adicional)
274
+ </sensitive_columns>
275
+
276
+ <allowed_roles>
277
+ - service_role: SELECT all (admin tasks)
278
+ - dpo_role: SELECT all (Data Protection Officer — quem processa DSR)
279
+ - authenticated: SELECT (id, request_type, status, created_at, resolved_at) — minimal
280
+ - anon: denied (sem GRANT)
281
+ </allowed_roles>
282
+
283
+ <user_facing_caller>true</user_facing_caller>
284
+ """)
285
+ ```
286
+
200
287
  ## Ver também
201
288
 
289
+ - [supabase-rls-hardener](./supabase-rls-hardener.md) — canonical handoff target v1.23
290
+ - [supabase-column-privileges-writer](./supabase-column-privileges-writer.md) — canonical handoff target v1.24 (column-level DSR/erasure)
202
291
  - [lgpd-multi-tenant-compliance](../skills/lgpd-multi-tenant-compliance/SKILL.md) — base de conhecimento
203
292
  - [audit-log-multi-tenant](../skills/audit-log-multi-tenant/SKILL.md) — Phase 109, PII sanitization + legal_hold
204
293
  - [multi-tenant-isolation-auditor](./multi-tenant-isolation-auditor.md) — agent sibling padrão de audit
@@ -252,8 +252,86 @@ NOTAS
252
252
  - super_admin actions emitem evento `super_admin_action` em `audit_logs` (Phase 109)
253
253
  - Counter `rls.deny.count{tenant_id, policy}` (cross-ref [`four-golden-signals`](../skills/four-golden-signals/SKILL.md))
254
254
 
255
+ ## Cooperative handoff to supabase-rls-hardener (v1.23)
256
+
257
+ Após gerar policies RLS hierárquicas, faça handoff cooperativo para `supabase-rls-hardener` validar defense-in-depth:
258
+
259
+ ```python
260
+ Task(subagent_type="supabase-rls-hardener", prompt=f"""
261
+ <upstream_intent>
262
+ Source agent: multi-tenant-rls-writer
263
+ Original goal: gerar policies RLS hierárquicas org→dept→role→permission para {table_name}
264
+ Constraints: helper functions já existem em schema private (is_member_of, has_role, has_permission, is_super_admin); STABLE; partial index em organization_members
265
+ </upstream_intent>
266
+
267
+ <draft_sql>{generated_policies_sql}</draft_sql>
268
+
269
+ <user_facing_caller>true</user_facing_caller>
270
+ """)
271
+ ```
272
+
273
+ Hardener processa verdict GO/STRENGTHEN/REWRITE-com-confirmação. **NUNCA descarte intent upstream silenciosamente** — conflitos viram diff explícito. Princípio canônico v1.23: agents não-Supabase pensam/planejam; agents Supabase materializam/hardenam; ninguém descarta o outro.
274
+
275
+ ## Cooperative handoff column-level (v1.24 — CROSS-14)
276
+
277
+ Em hierarquia multi-tenant org→dept→role→permission, column-level pode ser aplicado para restringir acesso granular a colunas sensíveis dentro de tabelas multi-tenant. Casos típicos: department_settings com colunas configurações sensíveis visíveis apenas para department_lead; org_billing com colunas credit_card_token visíveis apenas para org_owner.
278
+
279
+ ```python
280
+ Task(subagent_type="supabase-column-privileges-writer", prompt=f"""
281
+ <upstream_intent>
282
+ Source agent: multi-tenant-rls-writer
283
+ Original goal: column-level privileges dentro de hierarquia org/dept/role/permission
284
+ Constraints: tabela {table_name} tem coluna(s) sensível(eis) {sensitive_cols} que devem ser legíveis apenas para role específico na hierarquia; helper functions existem em schema private (private.is_member_of, private.has_role, private.has_permission)
285
+ </upstream_intent>
286
+
287
+ <table>schema: public, name: {table_name}</table>
288
+
289
+ <sensitive_columns>
290
+ {sensitive_cols_list}
291
+ </sensitive_columns>
292
+
293
+ <allowed_roles>
294
+ - service_role: SELECT all
295
+ - {specific_role}: SELECT all (via private.has_role check em RLS combinada)
296
+ - authenticated: SELECT non-sensitive columns
297
+ </allowed_roles>
298
+
299
+ <user_facing_caller>true</user_facing_caller>
300
+ """)
301
+ ```
302
+
303
+ **Caveat hierarquia:** column-level é Postgres role-level (não muda baseado em RLS row context). Para casos onde acesso depende de hierarquia *dinâmica* (membership ativa em dept específico), prefira RLS policy + dedicated role table (mais flexível). Use column-level apenas para casos estáticos com role Postgres separado.
304
+
305
+ ## Cooperative handoff RBAC via Custom Claims (v1.25 — CROSS-16)
306
+
307
+ Para RBAC em B2B multi-tenant, **combine** Custom Access Token Auth Hook (claim global para role) com helper functions PG STABLE (context-aware per-org). Pattern v1.25 é zero-JOIN para role global, helper function continua para per-org context. Aplique handoff cooperativo:
308
+
309
+ ```python
310
+ Task(subagent_type="supabase-rbac-implementer", prompt=f"""
311
+ <upstream_intent>
312
+ Source agent: multi-tenant-rls-writer
313
+ Original goal: implementar RBAC híbrido (claim global + helper function per-org) para B2B multi-tenant
314
+ Constraints: roles globais (super_admin, billing_admin) via custom claim; roles per-org (org_admin, org_member) via helper function STABLE; combinar em policies via OR
315
+ </upstream_intent>
316
+
317
+ <roles>super_admin, billing_admin, support</roles>
318
+ <permissions_matrix>
319
+ super_admin: [orgs.*, users.*, audit.read]
320
+ billing_admin: [billing.*, subscriptions.read]
321
+ support: [users.read, support_tickets.*]
322
+ </permissions_matrix>
323
+ <multi_tenant>true</multi_tenant>
324
+ <user_facing_caller>true</user_facing_caller>
325
+ """)
326
+ ```
327
+
328
+ Hardener processa verdict; output combina custom claim (zero-JOIN para super_admin) + helper functions PG existentes (per-org context). Princípio canônico v1.23 (herdado): nenhum lado descarta upstream.
329
+
255
330
  ## Ver também
256
331
 
332
+ - [supabase-rls-hardener](./supabase-rls-hardener.md) — canonical handoff target v1.23 (verdicts GO/STRENGTHEN/REWRITE)
333
+ - [supabase-column-privileges-writer](./supabase-column-privileges-writer.md) — canonical handoff target v1.24 (column-level hierarquia)
334
+ - [supabase-rbac-implementer](./supabase-rbac-implementer.md) — canonical handoff target v1.25 (Custom Claims + Auth Hook)
257
335
  - [supabase-rls-writer](./supabase-rls-writer.md) — agent base v1.8 que herda anti-pitfalls
258
336
  - [supabase-rls-policies](../skills/supabase-rls-policies/SKILL.md) — base de conhecimento canônica v1.8
259
337
  - [multi-tenant-rls-hierarchy](../skills/multi-tenant-rls-hierarchy/SKILL.md) — base de conhecimento desta agent
@@ -192,8 +192,29 @@ Onboarding é hot path crítico — emite eventos canônicos:
192
192
  3. **Counter:** `signup.org_created.count` (skill [`four-golden-signals`](../skills/four-golden-signals/SKILL.md))
193
193
  4. **Histogram:** `signup.duration_ms` (latência total signup → dashboard)
194
194
 
195
+ ## Cooperative handoff to supabase-rls-hardener (v1.23)
196
+
197
+ Após gerar migration atômica (org + members em 1 trx) + Edge Function setup wizard async, faça handoff cooperativo para SQL bloco:
198
+
199
+ ```python
200
+ Task(subagent_type="supabase-rls-hardener", prompt=f"""
201
+ <upstream_intent>
202
+ Source agent: org-onboarding-implementer
203
+ Original goal: signup → criar org → primeiro admin → setup wizard para nova org
204
+ Constraints: atomicidade (org + first_member em 1 trx); slug imutável + único cross-tenant (uniqueness constraint); RLS desde dia 1; first admin sem invite (admin direto via signup)
205
+ </upstream_intent>
206
+
207
+ <draft_sql>{generated_signup_migration_sql}</draft_sql>
208
+
209
+ <user_facing_caller>true</user_facing_caller>
210
+ """)
211
+ ```
212
+
213
+ Hardener valida que RLS está ativo já na primeira migration, GRANTs corretos para anon (durante signup) e authenticated (pós-login). **NUNCA descarte intent upstream silenciosamente**.
214
+
195
215
  ## Ver também
196
216
 
217
+ - [supabase-rls-hardener](./supabase-rls-hardener.md) — canonical handoff target v1.23
197
218
  - [org-onboarding-flow](../skills/org-onboarding-flow/SKILL.md) — base de conhecimento (regras + patterns + anti-patterns)
198
219
  - [b2b-saas-architecture](../skills/b2b-saas-architecture/SKILL.md) — schema canônico (Phase 106)
199
220
  - [supabase-migration-writer](./supabase-migration-writer.md) — invoked via Task() para SQL
@@ -889,3 +889,34 @@ Siga os templates nas seções checkpoints e revision_mode respectivamente.
889
889
  - [ ] Usuário sabe rodar `/executar-fase {X} --gaps-only`
890
890
 
891
891
  </success_criteria>
892
+
893
+ <sql_auto_handoff_cooperativo>
894
+ ## SQL auto-handoff cooperativo (v1.23 — CROSS-10)
895
+
896
+ Ao gerar PLAN.md que inclui tarefas com SQL/DDL (CREATE TABLE, CREATE POLICY, CREATE VIEW, ALTER TABLE adicionando column, etc.), **automaticamente** adiciona ao plan uma tarefa final de handoff cooperativo para `supabase-rls-hardener`.
897
+
898
+ **Heurística de detecção (regex):**
899
+
900
+ ```regex
901
+ (create\s+table|create\s+policy|create\s+view|alter\s+table|create\s+function.*security\s+definer|grant\s+.*on|enable\s+row\s+level\s+security)
902
+ ```
903
+
904
+ Se ≥ 1 match em qualquer tarefa do plan → injetar tarefa final:
905
+
906
+ ```markdown
907
+ ### Tarefa: Handoff cooperativo SQL para supabase-rls-hardener (v1.23)
908
+
909
+ **Tipo:** Validation
910
+ **Arquivos:** N/A (validation only)
911
+ **Ação:** Invocar `Task(subagent_type=supabase-rls-hardener, prompt=<draft+intent>)` para cada bloco SQL gerado na fase. Processar verdict GO/STRENGTHEN/REWRITE.
912
+
913
+ **Verify:** Output do hardener inclui verdict + SQL hardenado. Em STRENGTHEN/REWRITE, aplicar diff sugerido (se aceito pelo executor ou usuário humano).
914
+
915
+ **Done:** Verdict GO atingido OU diff aplicado com sucesso OU REWRITE confirmado pelo usuário.
916
+ ```
917
+
918
+ **Princípio canônico v1.23:** Planner pensa/planeja (estrutura do plan, decomposition, deps); supabase-rls-hardener materializa/hardena (SQL final). Plan não descarta intent — só adiciona camada de validação cooperativa.
919
+
920
+ **Não bloqueia execução:** se hardener responde STRENGTHEN/REWRITE, executor absorve o feedback e aplica diff. Aborto silencioso é proibido.
921
+
922
+ </sql_auto_handoff_cooperativo>
@@ -335,6 +335,17 @@ Policy Enforcement: <N>/10
335
335
  3. Re-audit em 30d para verificar progresso
336
336
  ```
337
337
 
338
+ ## Branching Workflow Validation (v1.27)
339
+
340
+ Para projetos que adotaram Supabase Branching, o auditor verifica adicionalmente:
341
+
342
+ - [ ] **Required check enforced:** repository settings → branches → main → required status checks inclui "Supabase Preview"
343
+ - [ ] **Secrets stored:** SUPABASE_ACCESS_TOKEN, PRODUCTION_DB_PASSWORD, PRODUCTION_PROJECT_ID configurados em Settings → Secrets
344
+ - [ ] **Migration safety pre-merge:** preview branch é criado antes de merge para main (não há push direto na main)
345
+ - [ ] **Backup workflow não está em repo público:** se `backup.yml` existe E repo é público → BLOCK (warning canônico)
346
+
347
+ Ver skill canônica: `kit/skills/supabase-ci-cd-github-actions/SKILL.md`.
348
+
338
349
  ## Quando NÃO invocar
339
350
 
340
351
  - Repo recém-criado (< 1 mês) — pipeline ainda imatura
@@ -13,6 +13,20 @@ Você é o arquiteto Supabase. O caller (orquestrador, geralmente Claude) entreg
13
13
 
14
14
  Apps Supabase são fáceis de começar e difíceis de evoluir quando schema/RLS/topology realtime são improvisados. Decisões arquiteturais erradas no início (ex: tabela única vs particionada, RLS frouxa, broadcast vs postgres_changes) se tornam tech debt caro. Este agent força decisões explícitas **antes** da primeira migration.
15
15
 
16
+ ## Branching Strategy Decision (v1.27)
17
+
18
+ Antes de projetar schema/RLS/topology, considerar a estratégia de branching que será usada:
19
+
20
+ - **GitHub integration recomendada** vs Dashboard alpha (Dashboard tem caveats — ver skill `supabase-branching-workflow`)
21
+ - **Persistent (staging/QA long-lived) vs ephemeral (preview auto-pause)**
22
+ - **Cost alert:** Branching Compute Hours estão **FORA do Spend Cap** — Micro $0.01344/h, Compute Credits NÃO aplicam
23
+
24
+ Se a estratégia ainda não foi decidida, delegar para `supabase-branching-architect` (cross-suite handoff) ANTES de prosseguir com schema design.
25
+
26
+ Cross-suite handoff: invocar via `Task(subagent_type="supabase-branching-architect", ...)`.
27
+
28
+ Ver skill canônica: `kit/skills/supabase-branching-workflow/SKILL.md`.
29
+
16
30
  ## Inputs esperados (do caller)
17
31
 
18
32
  - `feature_description`: descrição em texto livre (ex: "app de chat multi-room com presence", "RAG sobre documentos privados").
@@ -124,6 +138,23 @@ projeto: {project_id ou "novo"} · tier: {tier} · gerado em {timestamp}
124
138
  ## 5. Edge Functions / Background (se aplicável)
125
139
  {functions + cron pattern}
126
140
 
141
+ ## 5.1 Postgres Roles (v1.26 — ARCH-PATCH-01)
142
+
143
+ **Pergunta canônica upfront:** Esta feature precisa de **service accounts internos** (custom Postgres roles)?
144
+
145
+ Casos típicos:
146
+ - Cron jobs com pg_cron (cleanup, retention) — recomenda role dedicado em vez de service_role API key
147
+ - BI tools (Metabase, dbt) conectando direto no DB — recomenda role read-only com BYPASSRLS
148
+ - ETL scripts (replication, backups) — recomenda role com permissions específicos
149
+ - Admin roles para column-level GRANTs (security_admin, dpo_role, lead_manager)
150
+
151
+ **Se sim, listar service accounts esperados:**
152
+ - {role_name}: {description}, owner: {team_email}, type: {group|user}, bypassrls: {bool}
153
+
154
+ **Cross-suite handoff:** delegar criação para `supabase-roles-implementer` (v1.26) na ordem de implementação.
155
+
156
+ Para application access (end-users), usar **RLS + Custom Claims** (skill `supabase-custom-claims-rbac` v1.25) — NÃO criar Postgres roles para "admin vs user" end-users.
157
+
127
158
  ## 6. Ordem de Implementação
128
159
  {sequence numerada com agent delegate}
129
160
 
@@ -297,9 +297,89 @@ Auth events são SLI primário — "successful login %" é métrica de saúde di
297
297
 
298
298
  **Output adicionado:** seção "## Observability hooks" com snippet de span wrapper em handlers `/auth/*`.
299
299
 
300
+ ## Custom Claims & RBAC integration (v1.25 — AUTH-PATCH-01)
301
+
302
+ Quando o projeto usa **RBAC via Custom Access Token Auth Hook** (skill `supabase-custom-claims-rbac` v1.25), este agent inclui no bootstrap:
303
+
304
+ ### 1. Dependency `jwt-decode`
305
+
306
+ Adicionar ao `package.json`:
307
+
308
+ ```bash
309
+ npm install jwt-decode
310
+ ```
311
+
312
+ ### 2. `utils/supabase/client.ts` — listener com decoder
313
+
314
+ ```ts
315
+ import { createBrowserClient } from '@supabase/ssr'
316
+ import { jwtDecode } from 'jwt-decode'
317
+
318
+ export function createClient() {
319
+ const supabase = createBrowserClient(
320
+ process.env.NEXT_PUBLIC_SUPABASE_URL!,
321
+ process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
322
+ )
323
+
324
+ // listener para decodificar custom claims após login/refresh
325
+ supabase.auth.onAuthStateChange(async (event, session) => {
326
+ if (session) {
327
+ const jwt = jwtDecode<{ user_role?: string }>(session.access_token)
328
+ // userRole disponível para UI conditional rendering
329
+ // (use context provider para propagar — não documentado aqui)
330
+ console.log('User role from JWT:', jwt.user_role)
331
+ }
332
+ })
333
+
334
+ return supabase
335
+ }
336
+ ```
337
+
338
+ ### 3. `utils/supabase/server.ts` — server-side decode
339
+
340
+ ```ts
341
+ import { jwtDecode } from 'jwt-decode'
342
+
343
+ export async function getUserRole() {
344
+ const supabase = await createClient()
345
+ const { data: { session } } = await supabase.auth.getSession()
346
+ if (!session) return null
347
+
348
+ const jwt = jwtDecode<{ user_role?: string }>(session.access_token)
349
+ return jwt.user_role ?? null
350
+ }
351
+ ```
352
+
353
+ ### 4. Handoff cooperativo para `supabase-rbac-implementer`
354
+
355
+ Quando caller sinaliza `enable_rbac: true` ou detecta tabela `user_roles` no projeto, faça handoff:
356
+
357
+ ```python
358
+ Task(subagent_type="supabase-rbac-implementer", prompt=f"""
359
+ <upstream_intent>
360
+ Source agent: supabase-auth-bootstrapper
361
+ Original goal: bootstrap Next.js v16 + Supabase Auth com RBAC via Custom Access Token Auth Hook
362
+ Constraints: projeto novo Next.js v16; jwt-decode adicionado ao package.json; listener jwt decode adicionado em client.ts; helper getUserRole() adicionado em server.ts
363
+ </upstream_intent>
364
+
365
+ <roles>{caller_provided_roles or default ['admin', 'user']}</roles>
366
+ <permissions_matrix>{caller_provided or default}</permissions_matrix>
367
+ <multi_tenant>{caller_provided}</multi_tenant>
368
+ <user_facing_caller>true</user_facing_caller>
369
+ """)
370
+ ```
371
+
372
+ **Caveats embutidos no bootstrap:**
373
+
374
+ - ⚠ JWT freshness: mudanças em user_roles refletem após refresh (TTL 1h). Para revogação imediata, usar `auth.admin.signOut(userId)` no server-side com service_role.
375
+ - ⚠ Auth hook deve ser habilitado no Dashboard (Authentication > Hooks Beta) ou config.toml local — esse setup não é automatizado pelo bootstrap (DDL do hook é feito pelo `supabase-rbac-implementer` mas o enable depende de UI/config).
376
+ - ⚠ `jwt-decode` é apenas decode (NÃO valida assinatura) — para validação server-side, use `@supabase/ssr` `getUser()` que valida.
377
+
300
378
  ## Ver também
301
379
 
302
380
  - [supabase-auth-ssr](../skills/supabase-auth-ssr/SKILL.md) — base de conhecimento canônica
303
381
  - [supabase-rls-policies](../skills/supabase-rls-policies/SKILL.md) — RLS aplicado quando user autenticado consulta tabelas
382
+ - [supabase-custom-claims-rbac](../skills/supabase-custom-claims-rbac/SKILL.md) (v1.25) — Custom Access Token Auth Hook + jwt-decode
383
+ - [supabase-rbac-implementer](./supabase-rbac-implementer.md) (v1.25) — canonical handoff target para RBAC setup
304
384
  - [structured-events](../skills/structured-events/SKILL.md) — campos canônicos para auth events
305
385
  - [event-based-slos](../skills/event-based-slos/SKILL.md) *(Phase 32)* — SLO de "successful login %"