@luanpdd/kit-mcp 1.35.0 → 1.36.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 (117) hide show
  1. package/bin/cli.js +2 -2
  2. package/bin/mcp.js +6 -6
  3. package/bin/ui.js +74 -74
  4. package/gates/ai-prompt-stability.md +120 -120
  5. package/gates/budget-description.md +68 -68
  6. package/gates/confidence.md +29 -29
  7. package/gates/dependency-check.md +33 -33
  8. package/gates/dept-cycle-prevention.md +179 -179
  9. package/gates/golden-signals-coverage.md +133 -133
  10. package/gates/legacy-refactor-safety.md +178 -178
  11. package/gates/multi-tenant-rls-coverage.md +102 -102
  12. package/gates/no-personal-uuid.md +72 -72
  13. package/gates/obs-agents-mcp-supabase.md +86 -86
  14. package/gates/obs-skills-frontmatter.md +76 -76
  15. package/gates/observability-coverage.md +151 -151
  16. package/gates/omm-no-regression.md +83 -83
  17. package/gates/postmortem-template-required.md +127 -127
  18. package/gates/prr-checklist-coverage.md +128 -128
  19. package/gates/regression.md +32 -32
  20. package/gates/release-pipeline-policy.md +132 -132
  21. package/gates/secrets-scan.md +33 -33
  22. package/gates/service-role-not-in-user-facing.md +113 -113
  23. package/gates/skill-must-include.md +71 -71
  24. package/gates/sync-idempotent.md +62 -62
  25. package/gates/verify-phase-goal.md +34 -34
  26. package/kit/agents/designer-ui.md +216 -216
  27. package/kit/agents/workflow-generator.md +537 -167
  28. package/kit/commands/adicionar-backlog.md +1 -1
  29. package/kit/commands/adicionar-fase.md +1 -1
  30. package/kit/commands/adicionar-tarefa.md +1 -1
  31. package/kit/commands/auditar-observabilidade.md +103 -103
  32. package/kit/commands/auditar-toil.md +129 -129
  33. package/kit/commands/caracterizar-prompt.md +195 -195
  34. package/kit/commands/criar-workflow.md +158 -158
  35. package/kit/commands/definir-perfil.md +1 -1
  36. package/kit/commands/definir-slo.md +108 -108
  37. package/kit/commands/fio.md +1 -1
  38. package/kit/commands/golden-signals.md +142 -142
  39. package/kit/commands/instrumentar-fase.md +200 -200
  40. package/kit/commands/investigar-producao.md +162 -162
  41. package/kit/commands/observabilidade.md +118 -118
  42. package/kit/commands/postmortem.md +179 -179
  43. package/kit/commands/prr.md +205 -205
  44. package/kit/commands/publicar-rapido.md +207 -207
  45. package/kit/commands/risk-budget.md +220 -220
  46. package/kit/commands/sre.md +230 -230
  47. package/kit/file-manifest.json +424 -424
  48. package/kit/framework/references/output-style.md +22 -22
  49. package/kit/hooks/post-apply-migration.js +199 -199
  50. package/kit/hooks/sidecar-tool-publisher.js +210 -210
  51. package/kit/skills/_shared-dados-distribuidos/glossary.md +224 -224
  52. package/kit/skills/_shared-legacy/glossary.md +389 -389
  53. package/kit/skills/_shared-multi-tenant/glossary.md +186 -186
  54. package/kit/skills/_shared-observability/glossary.md +396 -396
  55. package/kit/skills/_shared-sre/glossary.md +712 -712
  56. package/kit/skills/_shared-supabase/glossary.md +234 -234
  57. package/kit/skills/blameless-postmortems/SKILL.md +340 -340
  58. package/kit/skills/burn-rate-alerting/SKILL.md +258 -258
  59. package/kit/skills/cascading-failures/SKILL.md +311 -311
  60. package/kit/skills/core-analysis-loop/SKILL.md +352 -352
  61. package/kit/skills/distributed-tracing/SKILL.md +362 -362
  62. package/kit/skills/dynamic-workflow-authoring/SKILL.md +327 -223
  63. package/kit/skills/eliminating-toil/SKILL.md +243 -243
  64. package/kit/skills/event-based-slos/SKILL.md +296 -296
  65. package/kit/skills/four-golden-signals/SKILL.md +314 -314
  66. package/kit/skills/hermetic-builds/SKILL.md +323 -323
  67. package/kit/skills/legacy-monster-methods/SKILL.md +444 -444
  68. package/kit/skills/llm-as-dependency/SKILL.md +436 -436
  69. package/kit/skills/load-shedding-graceful-degradation/SKILL.md +396 -396
  70. package/kit/skills/observability-driven-development/SKILL.md +315 -315
  71. package/kit/skills/observability-maturity-model/SKILL.md +222 -222
  72. package/kit/skills/opentelemetry-standard/SKILL.md +351 -351
  73. package/kit/skills/production-readiness-review/SKILL.md +305 -305
  74. package/kit/skills/release-engineering/SKILL.md +367 -367
  75. package/kit/skills/retry-strategies/SKILL.md +372 -372
  76. package/kit/skills/sre-risk-management/SKILL.md +221 -221
  77. package/kit/skills/structured-events/SKILL.md +265 -265
  78. package/kit/skills/supabase-cron-queues/SKILL.md +275 -275
  79. package/kit/skills/supabase-database-functions/SKILL.md +332 -332
  80. package/kit/skills/supabase-declarative-schema/SKILL.md +183 -183
  81. package/kit/skills/supabase-pgvector-rag/SKILL.md +253 -253
  82. package/kit/skills/supabase-postgres-style/SKILL.md +138 -138
  83. package/kit/skills/supabase-storage/SKILL.md +234 -234
  84. package/kit/skills/telemetry-pipelines/SKILL.md +259 -259
  85. package/kit/skills/telemetry-sampling/SKILL.md +256 -256
  86. package/kit/skills/ui-anti-padroes-ia/SKILL.md +261 -261
  87. package/kit/skills/ui-contexto-produto/SKILL.md +248 -248
  88. package/kit/skills/ui-cor-estrategia/SKILL.md +213 -213
  89. package/kit/skills/ui-critica-auditoria/SKILL.md +260 -260
  90. package/kit/skills/ui-motion-funcional/SKILL.md +264 -264
  91. package/kit/skills/ui-ritmo-espacial/SKILL.md +259 -259
  92. package/kit/skills/ui-tipografia/SKILL.md +211 -211
  93. package/package.json +1 -1
  94. package/src/cli/index.js +1114 -1114
  95. package/src/cli/render.js +194 -194
  96. package/src/cli/upgrade-check.js +135 -135
  97. package/src/core/error-redaction.js +76 -76
  98. package/src/core/failures.js +153 -153
  99. package/src/core/gate-runner.js +205 -205
  100. package/src/core/gates.js +82 -82
  101. package/src/core/logger.js +170 -170
  102. package/src/core/manifest-verify.js +174 -174
  103. package/src/core/metrics.js +268 -268
  104. package/src/core/notify.js +60 -60
  105. package/src/core/path-safety.js +141 -141
  106. package/src/core/replays.js +120 -120
  107. package/src/core/ui.js +185 -185
  108. package/src/mcp-server/install.js +149 -149
  109. package/src/mcp-server/roots.js +124 -124
  110. package/src/ui/auto-spawn.js +113 -113
  111. package/src/ui/browser.js +78 -78
  112. package/src/ui/client.js +130 -130
  113. package/src/ui/events.js +65 -65
  114. package/src/ui/lockfile.js +191 -191
  115. package/src/ui/port.js +67 -67
  116. package/src/ui/server.js +547 -547
  117. package/src/ui/wrapper.js +129 -129
@@ -1,132 +1,132 @@
1
- ---
2
- id: release-pipeline-policy
3
- stage: pre-milestone-close
4
- blocking: false
5
- description: Valida release pipeline scored ≥ X/30 (default 20 = ADEQUATE) em hermeticidade + reprodutibilidade + policy enforcement. Opt-in via workflow.complete_milestone_release_pipeline_gate. Cap 8 livro Google SRE.
6
- ---
7
-
8
- # Release pipeline policy gate
9
-
10
- **When to run:** pre-milestone-close (consultive default; blocking se `workflow.complete_milestone_release_pipeline_gate=true`).
11
-
12
- **Skill canônica:** [`release-engineering`](../kit/skills/release-engineering/SKILL.md) + [`hermetic-builds`](../kit/skills/hermetic-builds/SKILL.md)
13
-
14
- **Agent invocado:** [`release-pipeline-auditor`](../kit/agents/release-pipeline-auditor.md)
15
-
16
- ## Check
17
-
18
- ```bash
19
- #!/usr/bin/env bash
20
- # PT-BR: validar release pipeline scored >= threshold
21
- set -e
22
-
23
- # threshold do gate
24
- THRESHOLD=20 # default: ADEQUATE
25
- GATE_BLOCKING=false
26
-
27
- if [ -f ".planning/config.json" ] && command -v jq >/dev/null; then
28
- CFG=$(jq -r '.workflow.complete_milestone_release_pipeline_gate // empty' .planning/config.json 2>/dev/null)
29
- if [ "$CFG" = "true" ]; then
30
- GATE_BLOCKING=true
31
- fi
32
- CFG_THRESH=$(jq -r '.workflow.release_pipeline_threshold // empty' .planning/config.json 2>/dev/null)
33
- [ -n "$CFG_THRESH" ] && [ "$CFG_THRESH" != "null" ] && THRESHOLD=$CFG_THRESH
34
- fi
35
-
36
- # se não opt-in, gate skip
37
- if [ "$GATE_BLOCKING" = false ] && [ -z "$RELEASE_PIPELINE_POLICY_FORCE" ]; then
38
- echo "INFO: release-pipeline-policy gate is opt-in (workflow.complete_milestone_release_pipeline_gate=false). Skip."
39
- exit 0
40
- fi
41
-
42
- # ler RELEASE-AUDIT.md OR delegar via Task se ausente/stale
43
- AUDIT_FILE=".planning/RELEASE-AUDIT.md"
44
- SCORE=""
45
-
46
- if [ -f "$AUDIT_FILE" ]; then
47
- # check se fresh (≤ 30 dias)
48
- if [ "$(uname)" = "Darwin" ]; then
49
- AUDIT_DATE=$(stat -f %m "$AUDIT_FILE")
50
- else
51
- AUDIT_DATE=$(stat -c %Y "$AUDIT_FILE")
52
- fi
53
- AGE_DAYS=$(( ($(date +%s) - AUDIT_DATE) / 86400 ))
54
-
55
- if [ "$AGE_DAYS" -gt 30 ]; then
56
- echo "⚠ RELEASE-AUDIT.md stale (${AGE_DAYS}d). Re-rodar /auditar-release antes de close."
57
- [ "$GATE_BLOCKING" = true ] && exit 1
58
- fi
59
-
60
- # parse score
61
- SCORE=$(grep -oE "Score:\*\*\s*[0-9]+/30" "$AUDIT_FILE" | grep -oE "[0-9]+" | head -1)
62
- fi
63
-
64
- if [ -z "$SCORE" ]; then
65
- echo "⚠ RELEASE-AUDIT.md ausente OR sem score parseável."
66
- echo "Rode: /auditar-release (gera relatório fresh)"
67
- [ "$GATE_BLOCKING" = true ] && exit 1
68
- exit 0
69
- fi
70
-
71
- echo ""
72
- echo "release-pipeline-policy gate — threshold: ${THRESHOLD}/30"
73
- echo " RELEASE-AUDIT.md score: ${SCORE}/30"
74
- echo ""
75
-
76
- # decisão
77
- if [ "$SCORE" -ge "$THRESHOLD" ]; then
78
- if [ "$SCORE" -ge 25 ]; then
79
- echo "✓ ROBUST (≥ 25/30) — milestone arquivável."
80
- else
81
- echo "✓ ADEQUATE (20-24) — milestone arquivável com warnings."
82
- fi
83
- exit 0
84
- fi
85
-
86
- if [ "$SCORE" -lt 15 ]; then
87
- echo "✗ BROKEN (< 15/30) — pipeline não pode ser fonte de verdade. ESCALAR."
88
- elif [ "$SCORE" -lt 20 ]; then
89
- echo "✗ FRAGILE (15-19/30) — gaps significativos."
90
- fi
91
-
92
- echo ""
93
- echo "Próximas ações:"
94
- echo " 1. Aplicar top 5 fixes do RELEASE-AUDIT.md"
95
- echo " 2. Re-rodar /auditar-release"
96
- echo " 3. Re-tentar /concluir-marco após score >= ${THRESHOLD}"
97
- echo ""
98
-
99
- [ "$GATE_BLOCKING" = true ] && exit 1
100
- exit 0
101
- ```
102
-
103
- ## Configuração
104
-
105
- ```json
106
- {
107
- "workflow": {
108
- "complete_milestone_release_pipeline_gate": false,
109
- "release_pipeline_threshold": 20
110
- }
111
- }
112
- ```
113
-
114
- **Default:** `complete_milestone_release_pipeline_gate=false` (opt-in). Threshold 20 = ADEQUATE; promove para 25 (ROBUST) em projetos tier-1.
115
-
116
- ## Quando NÃO rodar
117
-
118
- - Projeto < 6 meses (pipeline ainda imatura)
119
- - Releases manuais (sem CI/CD complexo)
120
- - Solo dev side project
121
- - Projeto puramente experimental
122
-
123
- ## Ver também
124
-
125
- - [`release-pipeline-auditor`](../kit/agents/release-pipeline-auditor.md) — agent canônico
126
- - [`/auditar-release`](../kit/commands/auditar-release.md) — comando dedicado
127
- - [`hermetic-builds`](../kit/skills/hermetic-builds/SKILL.md)
128
- - [`release-engineering`](../kit/skills/release-engineering/SKILL.md)
129
- - [`prr-checklist-coverage`](./prr-checklist-coverage.md) — gate análogo PRR (v1.10)
130
- - [`legacy-refactor-safety`](./legacy-refactor-safety.md) — gate análogo Legacy (v1.12)
131
-
132
- *Material-fonte: cap 8 livro Google SRE.*
1
+ ---
2
+ id: release-pipeline-policy
3
+ stage: pre-milestone-close
4
+ blocking: false
5
+ description: Valida release pipeline scored ≥ X/30 (default 20 = ADEQUATE) em hermeticidade + reprodutibilidade + policy enforcement. Opt-in via workflow.complete_milestone_release_pipeline_gate. Cap 8 livro Google SRE.
6
+ ---
7
+
8
+ # Release pipeline policy gate
9
+
10
+ **When to run:** pre-milestone-close (consultive default; blocking se `workflow.complete_milestone_release_pipeline_gate=true`).
11
+
12
+ **Skill canônica:** [`release-engineering`](../kit/skills/release-engineering/SKILL.md) + [`hermetic-builds`](../kit/skills/hermetic-builds/SKILL.md)
13
+
14
+ **Agent invocado:** [`release-pipeline-auditor`](../kit/agents/release-pipeline-auditor.md)
15
+
16
+ ## Check
17
+
18
+ ```bash
19
+ #!/usr/bin/env bash
20
+ # PT-BR: validar release pipeline scored >= threshold
21
+ set -e
22
+
23
+ # threshold do gate
24
+ THRESHOLD=20 # default: ADEQUATE
25
+ GATE_BLOCKING=false
26
+
27
+ if [ -f ".planning/config.json" ] && command -v jq >/dev/null; then
28
+ CFG=$(jq -r '.workflow.complete_milestone_release_pipeline_gate // empty' .planning/config.json 2>/dev/null)
29
+ if [ "$CFG" = "true" ]; then
30
+ GATE_BLOCKING=true
31
+ fi
32
+ CFG_THRESH=$(jq -r '.workflow.release_pipeline_threshold // empty' .planning/config.json 2>/dev/null)
33
+ [ -n "$CFG_THRESH" ] && [ "$CFG_THRESH" != "null" ] && THRESHOLD=$CFG_THRESH
34
+ fi
35
+
36
+ # se não opt-in, gate skip
37
+ if [ "$GATE_BLOCKING" = false ] && [ -z "$RELEASE_PIPELINE_POLICY_FORCE" ]; then
38
+ echo "INFO: release-pipeline-policy gate is opt-in (workflow.complete_milestone_release_pipeline_gate=false). Skip."
39
+ exit 0
40
+ fi
41
+
42
+ # ler RELEASE-AUDIT.md OR delegar via Task se ausente/stale
43
+ AUDIT_FILE=".planning/RELEASE-AUDIT.md"
44
+ SCORE=""
45
+
46
+ if [ -f "$AUDIT_FILE" ]; then
47
+ # check se fresh (≤ 30 dias)
48
+ if [ "$(uname)" = "Darwin" ]; then
49
+ AUDIT_DATE=$(stat -f %m "$AUDIT_FILE")
50
+ else
51
+ AUDIT_DATE=$(stat -c %Y "$AUDIT_FILE")
52
+ fi
53
+ AGE_DAYS=$(( ($(date +%s) - AUDIT_DATE) / 86400 ))
54
+
55
+ if [ "$AGE_DAYS" -gt 30 ]; then
56
+ echo "⚠ RELEASE-AUDIT.md stale (${AGE_DAYS}d). Re-rodar /auditar-release antes de close."
57
+ [ "$GATE_BLOCKING" = true ] && exit 1
58
+ fi
59
+
60
+ # parse score
61
+ SCORE=$(grep -oE "Score:\*\*\s*[0-9]+/30" "$AUDIT_FILE" | grep -oE "[0-9]+" | head -1)
62
+ fi
63
+
64
+ if [ -z "$SCORE" ]; then
65
+ echo "⚠ RELEASE-AUDIT.md ausente OR sem score parseável."
66
+ echo "Rode: /auditar-release (gera relatório fresh)"
67
+ [ "$GATE_BLOCKING" = true ] && exit 1
68
+ exit 0
69
+ fi
70
+
71
+ echo ""
72
+ echo "release-pipeline-policy gate — threshold: ${THRESHOLD}/30"
73
+ echo " RELEASE-AUDIT.md score: ${SCORE}/30"
74
+ echo ""
75
+
76
+ # decisão
77
+ if [ "$SCORE" -ge "$THRESHOLD" ]; then
78
+ if [ "$SCORE" -ge 25 ]; then
79
+ echo "✓ ROBUST (≥ 25/30) — milestone arquivável."
80
+ else
81
+ echo "✓ ADEQUATE (20-24) — milestone arquivável com warnings."
82
+ fi
83
+ exit 0
84
+ fi
85
+
86
+ if [ "$SCORE" -lt 15 ]; then
87
+ echo "✗ BROKEN (< 15/30) — pipeline não pode ser fonte de verdade. ESCALAR."
88
+ elif [ "$SCORE" -lt 20 ]; then
89
+ echo "✗ FRAGILE (15-19/30) — gaps significativos."
90
+ fi
91
+
92
+ echo ""
93
+ echo "Próximas ações:"
94
+ echo " 1. Aplicar top 5 fixes do RELEASE-AUDIT.md"
95
+ echo " 2. Re-rodar /auditar-release"
96
+ echo " 3. Re-tentar /concluir-marco após score >= ${THRESHOLD}"
97
+ echo ""
98
+
99
+ [ "$GATE_BLOCKING" = true ] && exit 1
100
+ exit 0
101
+ ```
102
+
103
+ ## Configuração
104
+
105
+ ```json
106
+ {
107
+ "workflow": {
108
+ "complete_milestone_release_pipeline_gate": false,
109
+ "release_pipeline_threshold": 20
110
+ }
111
+ }
112
+ ```
113
+
114
+ **Default:** `complete_milestone_release_pipeline_gate=false` (opt-in). Threshold 20 = ADEQUATE; promove para 25 (ROBUST) em projetos tier-1.
115
+
116
+ ## Quando NÃO rodar
117
+
118
+ - Projeto < 6 meses (pipeline ainda imatura)
119
+ - Releases manuais (sem CI/CD complexo)
120
+ - Solo dev side project
121
+ - Projeto puramente experimental
122
+
123
+ ## Ver também
124
+
125
+ - [`release-pipeline-auditor`](../kit/agents/release-pipeline-auditor.md) — agent canônico
126
+ - [`/auditar-release`](../kit/commands/auditar-release.md) — comando dedicado
127
+ - [`hermetic-builds`](../kit/skills/hermetic-builds/SKILL.md)
128
+ - [`release-engineering`](../kit/skills/release-engineering/SKILL.md)
129
+ - [`prr-checklist-coverage`](./prr-checklist-coverage.md) — gate análogo PRR (v1.10)
130
+ - [`legacy-refactor-safety`](./legacy-refactor-safety.md) — gate análogo Legacy (v1.12)
131
+
132
+ *Material-fonte: cap 8 livro Google SRE.*
@@ -1,33 +1,33 @@
1
- ---
2
- id: secrets-scan
3
- stage: any
4
- blocking: true
5
- description: Block commits that introduce common secret patterns. Bonus gate, not in original kit.
6
- ---
7
-
8
- # Secrets scan gate
9
-
10
- **When to run:** before any commit that touches files outside `.planning/`. Optional;
11
- opt in via project `config.json` → `gates.secrets_scan: true`.
12
-
13
- ## Check
14
-
15
- Grep staged diff for high-confidence secret patterns:
16
-
17
- - `AKIA[0-9A-Z]{16}` (AWS access key)
18
- - `sk-(proj-|ant-)?[A-Za-z0-9]{20,}` (OpenAI / Anthropic key)
19
- - `ghp_[A-Za-z0-9]{36}` (GitHub PAT)
20
- - `xox[baprs]-[A-Za-z0-9-]{10,}` (Slack token)
21
- - `-----BEGIN (RSA |EC )?PRIVATE KEY-----`
22
-
23
- ## Verdict
24
-
25
- - **passed** — no matches → proceed
26
- - **block** — match found → list file + line, refuse commit. Suggest `git restore --staged <file>`
27
-
28
- ## Notes
29
-
30
- This gate intentionally has zero ML / heuristics. It catches the common-format
31
- keys that humans accidentally paste; it does not catch base64-encoded secrets
32
- or custom token formats. Pair with a real secrets scanner (gitleaks, trufflehog)
33
- for production projects.
1
+ ---
2
+ id: secrets-scan
3
+ stage: any
4
+ blocking: true
5
+ description: Block commits that introduce common secret patterns. Bonus gate, not in original kit.
6
+ ---
7
+
8
+ # Secrets scan gate
9
+
10
+ **When to run:** before any commit that touches files outside `.planning/`. Optional;
11
+ opt in via project `config.json` → `gates.secrets_scan: true`.
12
+
13
+ ## Check
14
+
15
+ Grep staged diff for high-confidence secret patterns:
16
+
17
+ - `AKIA[0-9A-Z]{16}` (AWS access key)
18
+ - `sk-(proj-|ant-)?[A-Za-z0-9]{20,}` (OpenAI / Anthropic key)
19
+ - `ghp_[A-Za-z0-9]{36}` (GitHub PAT)
20
+ - `xox[baprs]-[A-Za-z0-9-]{10,}` (Slack token)
21
+ - `-----BEGIN (RSA |EC )?PRIVATE KEY-----`
22
+
23
+ ## Verdict
24
+
25
+ - **passed** — no matches → proceed
26
+ - **block** — match found → list file + line, refuse commit. Suggest `git restore --staged <file>`
27
+
28
+ ## Notes
29
+
30
+ This gate intentionally has zero ML / heuristics. It catches the common-format
31
+ keys that humans accidentally paste; it does not catch base64-encoded secrets
32
+ or custom token formats. Pair with a real secrets scanner (gitleaks, trufflehog)
33
+ for production projects.
@@ -1,113 +1,113 @@
1
- ---
2
- id: service-role-not-in-user-facing
3
- stage: pre-verify
4
- blocking: true
5
- description: Detecta uso de SUPABASE_SERVICE_ROLE_KEY em Edge Functions com verify_jwt:true (user-facing). Service role bypassa RLS — uso em rota acessível a usuário desliga toda autorização. Skip se projeto não tem supabase/functions/.
6
- ---
7
-
8
- # Service Role Not In User-Facing gate
9
-
10
- **When to run:** pre-verify (blocking — anti-pitfall P0 multi-tenant).
11
-
12
- ## Check
13
-
14
- ```bash
15
- #!/usr/bin/env bash
16
- # PT-BR: detecta uso de SUPABASE_SERVICE_ROLE_KEY em Edge Functions com verify_jwt:true.
17
- # Anti-pitfall #2 multi-tenant: service role em rota user-facing = bypass total de RLS.
18
- # Bash 3.2-portable (macOS default).
19
- set -e
20
-
21
- FUNCTIONS_DIR="supabase/functions"
22
- CONFIG_FILE="supabase/config.toml"
23
-
24
- if [ ! -d "$FUNCTIONS_DIR" ]; then
25
- echo "INFO: $FUNCTIONS_DIR não existe — projeto não usa Supabase Edge Functions. Gate skipped."
26
- exit 0
27
- fi
28
-
29
- # PT-BR: env vars que indicam uso de service role
30
- SERVICE_ROLE_PATTERNS="SUPABASE_SERVICE_ROLE_KEY|SERVICE_ROLE_KEY|service_role_key|serviceRoleKey"
31
-
32
- VIOLATIONS=0
33
- VIOLATIONS_DETAIL=""
34
-
35
- # PT-BR: iterar cada Edge Function (cada subdir em functions/)
36
- FUNCTION_DIRS=$(find "$FUNCTIONS_DIR" -mindepth 1 -maxdepth 1 -type d 2>/dev/null)
37
-
38
- if [ -z "$FUNCTION_DIRS" ]; then
39
- echo "INFO: nenhuma Edge Function em $FUNCTIONS_DIR — gate skipped."
40
- exit 0
41
- fi
42
-
43
- for fn_dir in $FUNCTION_DIRS; do
44
- fn_name=$(basename "$fn_dir")
45
-
46
- # PT-BR: skip _shared (não é Edge Function deployable)
47
- [ "$fn_name" = "_shared" ] && continue
48
-
49
- # PT-BR: descobrir verify_jwt setting da função (default: true se ausente)
50
- VERIFY_JWT="true" # default Supabase
51
- if [ -f "$CONFIG_FILE" ]; then
52
- # PT-BR: parsing leve — procurar [functions.<name>] block + verify_jwt
53
- SECTION_VERIFY=$(awk -v fn="$fn_name" '
54
- $0 ~ "^\\[functions\\." fn "\\]" { in_section = 1; next }
55
- in_section && /^\[/ { in_section = 0 }
56
- in_section && /verify_jwt/ {
57
- gsub(/[ \t]/, "")
58
- split($0, a, "=")
59
- print a[2]
60
- exit
61
- }
62
- ' "$CONFIG_FILE" 2>/dev/null)
63
-
64
- if [ -n "$SECTION_VERIFY" ]; then
65
- VERIFY_JWT="$SECTION_VERIFY"
66
- fi
67
- fi
68
-
69
- # PT-BR: se verify_jwt=false (webhook/internal), skip — service role é OK aqui
70
- if [ "$VERIFY_JWT" = "false" ]; then
71
- continue
72
- fi
73
-
74
- # PT-BR: buscar uso de service role em arquivos .ts/.js da function
75
- SERVICE_ROLE_FILES=$(grep -rlE "$SERVICE_ROLE_PATTERNS" "$fn_dir" --include="*.ts" --include="*.js" --include="*.mjs" 2>/dev/null || true)
76
-
77
- if [ -n "$SERVICE_ROLE_FILES" ]; then
78
- VIOLATIONS=$((VIOLATIONS + 1))
79
- VIOLATIONS_DETAIL="${VIOLATIONS_DETAIL}
80
- Edge Function '$fn_name' (verify_jwt=$VERIFY_JWT) usa service role:
81
- $(echo "$SERVICE_ROLE_FILES" | sed 's/^/ /')"
82
- fi
83
- done
84
-
85
- if [ "$VIOLATIONS" -eq 0 ]; then
86
- echo "PASS: nenhuma Edge Function user-facing (verify_jwt=true) usa SERVICE_ROLE_KEY."
87
- exit 0
88
- else
89
- echo "FAIL: $VIOLATIONS Edge Function(s) user-facing usam SERVICE_ROLE_KEY:$VIOLATIONS_DETAIL"
90
- echo ""
91
- echo "Fix: use ANON_KEY com JWT do user para preservar RLS. Se realmente precisa de service role:"
92
- echo " - Mover lógica privilegiada para Edge Function separada com verify_jwt=false (webhook ou cron-only)"
93
- echo " - OU validar manualmente quem está chamando antes de usar service role (anti-pattern, mas explícito)"
94
- echo "Ref: kit/skills/_shared-multi-tenant/glossary.md (sub-seção super_admin) + kit/skills/supabase-rls-policies/SKILL.md"
95
- exit 1
96
- fi
97
- ```
98
-
99
- ## Verdict
100
-
101
- - **passed** — nenhum service role em Edge Function user-facing → continuar
102
- - **block** — apresentar lista de Edge Functions violadoras + fix recomendado
103
-
104
- ## Notes
105
-
106
- Edge Functions com `verify_jwt = false` (webhooks Evolution Go, Stripe, schedulers internos via pg_cron) podem usar service role legitimamente — gate skippa essas.
107
-
108
- Detecção pode produzir falso-positivo se code referencia o nome da var em comentário ou string literal (ex: documentação dentro do code). Para suprimir, mover documentação para arquivo externo ou usar comentário JSDoc fora do regex match.
109
-
110
- Para super-admin operations user-facing (impersonation, cross-tenant queries), pattern correto é:
111
- 1. Endpoint user-facing valida `super_admin: true` em JWT app_metadata
112
- 2. Endpoint chama segunda Edge Function interna (verify_jwt=false) que usa service role
113
- 3. Audit log obrigatório no caminho
1
+ ---
2
+ id: service-role-not-in-user-facing
3
+ stage: pre-verify
4
+ blocking: true
5
+ description: Detecta uso de SUPABASE_SERVICE_ROLE_KEY em Edge Functions com verify_jwt:true (user-facing). Service role bypassa RLS — uso em rota acessível a usuário desliga toda autorização. Skip se projeto não tem supabase/functions/.
6
+ ---
7
+
8
+ # Service Role Not In User-Facing gate
9
+
10
+ **When to run:** pre-verify (blocking — anti-pitfall P0 multi-tenant).
11
+
12
+ ## Check
13
+
14
+ ```bash
15
+ #!/usr/bin/env bash
16
+ # PT-BR: detecta uso de SUPABASE_SERVICE_ROLE_KEY em Edge Functions com verify_jwt:true.
17
+ # Anti-pitfall #2 multi-tenant: service role em rota user-facing = bypass total de RLS.
18
+ # Bash 3.2-portable (macOS default).
19
+ set -e
20
+
21
+ FUNCTIONS_DIR="supabase/functions"
22
+ CONFIG_FILE="supabase/config.toml"
23
+
24
+ if [ ! -d "$FUNCTIONS_DIR" ]; then
25
+ echo "INFO: $FUNCTIONS_DIR não existe — projeto não usa Supabase Edge Functions. Gate skipped."
26
+ exit 0
27
+ fi
28
+
29
+ # PT-BR: env vars que indicam uso de service role
30
+ SERVICE_ROLE_PATTERNS="SUPABASE_SERVICE_ROLE_KEY|SERVICE_ROLE_KEY|service_role_key|serviceRoleKey"
31
+
32
+ VIOLATIONS=0
33
+ VIOLATIONS_DETAIL=""
34
+
35
+ # PT-BR: iterar cada Edge Function (cada subdir em functions/)
36
+ FUNCTION_DIRS=$(find "$FUNCTIONS_DIR" -mindepth 1 -maxdepth 1 -type d 2>/dev/null)
37
+
38
+ if [ -z "$FUNCTION_DIRS" ]; then
39
+ echo "INFO: nenhuma Edge Function em $FUNCTIONS_DIR — gate skipped."
40
+ exit 0
41
+ fi
42
+
43
+ for fn_dir in $FUNCTION_DIRS; do
44
+ fn_name=$(basename "$fn_dir")
45
+
46
+ # PT-BR: skip _shared (não é Edge Function deployable)
47
+ [ "$fn_name" = "_shared" ] && continue
48
+
49
+ # PT-BR: descobrir verify_jwt setting da função (default: true se ausente)
50
+ VERIFY_JWT="true" # default Supabase
51
+ if [ -f "$CONFIG_FILE" ]; then
52
+ # PT-BR: parsing leve — procurar [functions.<name>] block + verify_jwt
53
+ SECTION_VERIFY=$(awk -v fn="$fn_name" '
54
+ $0 ~ "^\\[functions\\." fn "\\]" { in_section = 1; next }
55
+ in_section && /^\[/ { in_section = 0 }
56
+ in_section && /verify_jwt/ {
57
+ gsub(/[ \t]/, "")
58
+ split($0, a, "=")
59
+ print a[2]
60
+ exit
61
+ }
62
+ ' "$CONFIG_FILE" 2>/dev/null)
63
+
64
+ if [ -n "$SECTION_VERIFY" ]; then
65
+ VERIFY_JWT="$SECTION_VERIFY"
66
+ fi
67
+ fi
68
+
69
+ # PT-BR: se verify_jwt=false (webhook/internal), skip — service role é OK aqui
70
+ if [ "$VERIFY_JWT" = "false" ]; then
71
+ continue
72
+ fi
73
+
74
+ # PT-BR: buscar uso de service role em arquivos .ts/.js da function
75
+ SERVICE_ROLE_FILES=$(grep -rlE "$SERVICE_ROLE_PATTERNS" "$fn_dir" --include="*.ts" --include="*.js" --include="*.mjs" 2>/dev/null || true)
76
+
77
+ if [ -n "$SERVICE_ROLE_FILES" ]; then
78
+ VIOLATIONS=$((VIOLATIONS + 1))
79
+ VIOLATIONS_DETAIL="${VIOLATIONS_DETAIL}
80
+ Edge Function '$fn_name' (verify_jwt=$VERIFY_JWT) usa service role:
81
+ $(echo "$SERVICE_ROLE_FILES" | sed 's/^/ /')"
82
+ fi
83
+ done
84
+
85
+ if [ "$VIOLATIONS" -eq 0 ]; then
86
+ echo "PASS: nenhuma Edge Function user-facing (verify_jwt=true) usa SERVICE_ROLE_KEY."
87
+ exit 0
88
+ else
89
+ echo "FAIL: $VIOLATIONS Edge Function(s) user-facing usam SERVICE_ROLE_KEY:$VIOLATIONS_DETAIL"
90
+ echo ""
91
+ echo "Fix: use ANON_KEY com JWT do user para preservar RLS. Se realmente precisa de service role:"
92
+ echo " - Mover lógica privilegiada para Edge Function separada com verify_jwt=false (webhook ou cron-only)"
93
+ echo " - OU validar manualmente quem está chamando antes de usar service role (anti-pattern, mas explícito)"
94
+ echo "Ref: kit/skills/_shared-multi-tenant/glossary.md (sub-seção super_admin) + kit/skills/supabase-rls-policies/SKILL.md"
95
+ exit 1
96
+ fi
97
+ ```
98
+
99
+ ## Verdict
100
+
101
+ - **passed** — nenhum service role em Edge Function user-facing → continuar
102
+ - **block** — apresentar lista de Edge Functions violadoras + fix recomendado
103
+
104
+ ## Notes
105
+
106
+ Edge Functions com `verify_jwt = false` (webhooks Evolution Go, Stripe, schedulers internos via pg_cron) podem usar service role legitimamente — gate skippa essas.
107
+
108
+ Detecção pode produzir falso-positivo se code referencia o nome da var em comentário ou string literal (ex: documentação dentro do code). Para suprimir, mover documentação para arquivo externo ou usar comentário JSDoc fora do regex match.
109
+
110
+ Para super-admin operations user-facing (impersonation, cross-tenant queries), pattern correto é:
111
+ 1. Endpoint user-facing valida `super_admin: true` em JWT app_metadata
112
+ 2. Endpoint chama segunda Edge Function interna (verify_jwt=false) que usa service role
113
+ 3. Audit log obrigatório no caminho