@luanpdd/kit-mcp 1.34.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 (118) hide show
  1. package/README.md +1 -1
  2. package/bin/cli.js +2 -2
  3. package/bin/mcp.js +6 -6
  4. package/bin/ui.js +74 -74
  5. package/gates/ai-prompt-stability.md +120 -120
  6. package/gates/budget-description.md +68 -68
  7. package/gates/confidence.md +29 -29
  8. package/gates/dependency-check.md +33 -33
  9. package/gates/dept-cycle-prevention.md +179 -179
  10. package/gates/golden-signals-coverage.md +133 -133
  11. package/gates/legacy-refactor-safety.md +178 -178
  12. package/gates/multi-tenant-rls-coverage.md +102 -102
  13. package/gates/no-personal-uuid.md +72 -72
  14. package/gates/obs-agents-mcp-supabase.md +86 -86
  15. package/gates/obs-skills-frontmatter.md +76 -76
  16. package/gates/observability-coverage.md +151 -151
  17. package/gates/omm-no-regression.md +83 -83
  18. package/gates/postmortem-template-required.md +127 -127
  19. package/gates/prr-checklist-coverage.md +128 -128
  20. package/gates/regression.md +32 -32
  21. package/gates/release-pipeline-policy.md +132 -132
  22. package/gates/secrets-scan.md +33 -33
  23. package/gates/service-role-not-in-user-facing.md +113 -113
  24. package/gates/skill-must-include.md +71 -71
  25. package/gates/sync-idempotent.md +62 -62
  26. package/gates/verify-phase-goal.md +34 -34
  27. package/kit/agents/designer-ui.md +216 -216
  28. package/kit/agents/workflow-generator.md +537 -0
  29. package/kit/commands/adicionar-backlog.md +1 -1
  30. package/kit/commands/adicionar-fase.md +1 -1
  31. package/kit/commands/adicionar-tarefa.md +1 -1
  32. package/kit/commands/auditar-observabilidade.md +103 -103
  33. package/kit/commands/auditar-toil.md +129 -129
  34. package/kit/commands/caracterizar-prompt.md +195 -195
  35. package/kit/commands/criar-workflow.md +158 -0
  36. package/kit/commands/definir-perfil.md +1 -1
  37. package/kit/commands/definir-slo.md +108 -108
  38. package/kit/commands/fio.md +1 -1
  39. package/kit/commands/golden-signals.md +142 -142
  40. package/kit/commands/instrumentar-fase.md +200 -200
  41. package/kit/commands/investigar-producao.md +162 -162
  42. package/kit/commands/observabilidade.md +118 -118
  43. package/kit/commands/postmortem.md +179 -179
  44. package/kit/commands/prr.md +205 -205
  45. package/kit/commands/publicar-rapido.md +207 -207
  46. package/kit/commands/risk-budget.md +220 -220
  47. package/kit/commands/sre.md +230 -230
  48. package/kit/file-manifest.json +5 -2
  49. package/kit/framework/references/output-style.md +22 -22
  50. package/kit/hooks/post-apply-migration.js +199 -199
  51. package/kit/hooks/sidecar-tool-publisher.js +210 -210
  52. package/kit/skills/_shared-dados-distribuidos/glossary.md +224 -224
  53. package/kit/skills/_shared-legacy/glossary.md +389 -389
  54. package/kit/skills/_shared-multi-tenant/glossary.md +186 -186
  55. package/kit/skills/_shared-observability/glossary.md +396 -396
  56. package/kit/skills/_shared-sre/glossary.md +712 -712
  57. package/kit/skills/_shared-supabase/glossary.md +234 -234
  58. package/kit/skills/blameless-postmortems/SKILL.md +340 -340
  59. package/kit/skills/burn-rate-alerting/SKILL.md +258 -258
  60. package/kit/skills/cascading-failures/SKILL.md +311 -311
  61. package/kit/skills/core-analysis-loop/SKILL.md +352 -352
  62. package/kit/skills/distributed-tracing/SKILL.md +362 -362
  63. package/kit/skills/dynamic-workflow-authoring/SKILL.md +327 -0
  64. package/kit/skills/eliminating-toil/SKILL.md +243 -243
  65. package/kit/skills/event-based-slos/SKILL.md +296 -296
  66. package/kit/skills/four-golden-signals/SKILL.md +314 -314
  67. package/kit/skills/hermetic-builds/SKILL.md +323 -323
  68. package/kit/skills/legacy-monster-methods/SKILL.md +444 -444
  69. package/kit/skills/llm-as-dependency/SKILL.md +436 -436
  70. package/kit/skills/load-shedding-graceful-degradation/SKILL.md +396 -396
  71. package/kit/skills/observability-driven-development/SKILL.md +315 -315
  72. package/kit/skills/observability-maturity-model/SKILL.md +222 -222
  73. package/kit/skills/opentelemetry-standard/SKILL.md +351 -351
  74. package/kit/skills/production-readiness-review/SKILL.md +305 -305
  75. package/kit/skills/release-engineering/SKILL.md +367 -367
  76. package/kit/skills/retry-strategies/SKILL.md +372 -372
  77. package/kit/skills/sre-risk-management/SKILL.md +221 -221
  78. package/kit/skills/structured-events/SKILL.md +265 -265
  79. package/kit/skills/supabase-cron-queues/SKILL.md +275 -275
  80. package/kit/skills/supabase-database-functions/SKILL.md +332 -332
  81. package/kit/skills/supabase-declarative-schema/SKILL.md +183 -183
  82. package/kit/skills/supabase-pgvector-rag/SKILL.md +253 -253
  83. package/kit/skills/supabase-postgres-style/SKILL.md +138 -138
  84. package/kit/skills/supabase-storage/SKILL.md +234 -234
  85. package/kit/skills/telemetry-pipelines/SKILL.md +259 -259
  86. package/kit/skills/telemetry-sampling/SKILL.md +256 -256
  87. package/kit/skills/ui-anti-padroes-ia/SKILL.md +261 -261
  88. package/kit/skills/ui-contexto-produto/SKILL.md +248 -248
  89. package/kit/skills/ui-cor-estrategia/SKILL.md +213 -213
  90. package/kit/skills/ui-critica-auditoria/SKILL.md +260 -260
  91. package/kit/skills/ui-motion-funcional/SKILL.md +264 -264
  92. package/kit/skills/ui-ritmo-espacial/SKILL.md +259 -259
  93. package/kit/skills/ui-tipografia/SKILL.md +211 -211
  94. package/package.json +1 -1
  95. package/src/cli/index.js +1114 -1114
  96. package/src/cli/render.js +194 -194
  97. package/src/cli/upgrade-check.js +135 -135
  98. package/src/core/error-redaction.js +76 -76
  99. package/src/core/failures.js +153 -153
  100. package/src/core/gate-runner.js +205 -205
  101. package/src/core/gates.js +82 -82
  102. package/src/core/logger.js +170 -170
  103. package/src/core/manifest-verify.js +174 -174
  104. package/src/core/metrics.js +268 -268
  105. package/src/core/notify.js +60 -60
  106. package/src/core/path-safety.js +141 -141
  107. package/src/core/replays.js +120 -120
  108. package/src/core/ui.js +185 -185
  109. package/src/mcp-server/install.js +149 -149
  110. package/src/mcp-server/roots.js +124 -124
  111. package/src/ui/auto-spawn.js +113 -113
  112. package/src/ui/browser.js +78 -78
  113. package/src/ui/client.js +130 -130
  114. package/src/ui/events.js +65 -65
  115. package/src/ui/lockfile.js +191 -191
  116. package/src/ui/port.js +67 -67
  117. package/src/ui/server.js +547 -547
  118. 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