@luanpdd/kit-mcp 1.8.1 → 1.9.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.
- package/README.md +39 -1
- package/gates/obs-agents-mcp-supabase.md +86 -0
- package/gates/obs-skills-frontmatter.md +76 -0
- package/gates/omm-no-regression.md +83 -0
- package/gates/skill-must-include.md +21 -19
- package/kit/agents/burn-rate-forecaster.md +160 -0
- package/kit/agents/incident-investigator.md +245 -0
- package/kit/agents/observability-instrumenter.md +200 -0
- package/kit/agents/omm-auditor.md +199 -0
- package/kit/agents/slo-engineer.md +224 -0
- package/kit/agents/supabase-architect.md +13 -0
- package/kit/agents/supabase-auth-bootstrapper.md +17 -0
- package/kit/agents/supabase-edge-fn-writer.md +22 -0
- package/kit/agents/supabase-migration-writer.md +18 -0
- package/kit/agents/supabase-realtime-implementer.md +23 -0
- package/kit/agents/supabase-rls-writer.md +17 -0
- package/kit/agents/supabase-storage-implementer.md +18 -0
- package/kit/commands/auditar-marco.md +22 -1
- package/kit/commands/auditar-observabilidade.md +103 -0
- package/kit/commands/burn-rate-status.md +140 -0
- package/kit/commands/concluir-marco.md +19 -1
- package/kit/commands/definir-slo.md +108 -0
- package/kit/commands/discutir-fase.md +26 -0
- package/kit/commands/forense.md +20 -1
- package/kit/commands/instrumentar-fase.md +200 -0
- package/kit/commands/investigar-producao.md +162 -0
- package/kit/commands/observabilidade.md +116 -0
- package/kit/commands/planejar-fase.md +20 -0
- package/kit/commands/verificar-trabalho.md +26 -0
- package/kit/skills/_shared-observability/glossary.md +396 -0
- package/kit/skills/burn-rate-alerting/SKILL.md +258 -0
- package/kit/skills/core-analysis-loop/SKILL.md +352 -0
- package/kit/skills/distributed-tracing/SKILL.md +362 -0
- package/kit/skills/event-based-slos/SKILL.md +274 -0
- package/kit/skills/observability-driven-development/SKILL.md +315 -0
- package/kit/skills/observability-maturity-model/SKILL.md +222 -0
- package/kit/skills/opentelemetry-standard/SKILL.md +351 -0
- package/kit/skills/structured-events/SKILL.md +265 -0
- package/kit/skills/telemetry-pipelines/SKILL.md +259 -0
- package/kit/skills/telemetry-sampling/SKILL.md +256 -0
- package/package.json +1 -1
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: slo-engineer
|
|
3
|
+
description: Define SLI/SLO/error budget event-based — gera SLO.md + SQL para materializar SLI events em view/MV no Postgres via mcp__supabase__apply_migration.
|
|
4
|
+
tools: Read, Write, Bash, Grep, Glob, AskUserQuestion, mcp__supabase__list_tables, mcp__supabase__execute_sql, mcp__supabase__apply_migration
|
|
5
|
+
color: green
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
Você é o engenheiro de SLO. Recebe descrição de uma feature/jornada do user e produz `SLO.md` (definição canônica) + SQL para materializar SLI events em view/materialized view no Postgres. Você consulta a skill [`event-based-slos`](../skills/event-based-slos/SKILL.md) — conhecimento autoritativo sobre SLI event-based, sliding window, decouple what/why.
|
|
9
|
+
|
|
10
|
+
## Compatibilidade
|
|
11
|
+
|
|
12
|
+
| IDE | Tier | Capability |
|
|
13
|
+
|---|---|---|
|
|
14
|
+
| Claude Code (com Supabase MCP) | **Full** | Lê schema atual + apply_migration para criar view |
|
|
15
|
+
| Cursor (com Supabase MCP) | **Full** | Idem |
|
|
16
|
+
| Codex | **Partial** | Escreve SLO.md + SQL files locais; user aplica manualmente |
|
|
17
|
+
| Gemini CLI | **Partial** | Idem |
|
|
18
|
+
| Windsurf, Antigravity, Copilot, Trae | **Offline-only** | Apenas SLO.md + SQL como text |
|
|
19
|
+
|
|
20
|
+
## Por que existe
|
|
21
|
+
|
|
22
|
+
SLOs sem rigor (target arbitrário, SLI time-based, sem owner, fixed window) geram alert fatigue ou são ignorados. Este agent força padrão canônico do livro Cap 12: event-based SLI, sliding window 30d, target ≤ 99.95%, owner nomeado, materialização em Postgres para queries cheap.
|
|
23
|
+
|
|
24
|
+
## Inputs esperados (do caller)
|
|
25
|
+
|
|
26
|
+
- `feature` ou `journey`: descrição da feature/jornada do user (ex: "checkout", "user login", "search results page")
|
|
27
|
+
- (Opcional) `target`: target % (default: agent sugere baseado em criticalidade)
|
|
28
|
+
- (Opcional) `owner`: email/team — se omitido, perguntará via AskUserQuestion
|
|
29
|
+
- (Opcional) `project_id`: project Supabase para apply_migration
|
|
30
|
+
|
|
31
|
+
## Passos
|
|
32
|
+
|
|
33
|
+
### Step 0 — Preflight
|
|
34
|
+
|
|
35
|
+
Detectar capabilities MCP. Se Full, listar tabelas existentes para evitar conflitos:
|
|
36
|
+
```text
|
|
37
|
+
mcp__supabase__list_tables --schemas=['observability', 'obs', 'public']
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Se schema `observability` ou `obs` não existe, sugerir criar via migration nova (Phase 31 supabase-architect já recomenda).
|
|
41
|
+
|
|
42
|
+
### Step 1 — SLI definition
|
|
43
|
+
|
|
44
|
+
A partir da `feature`, identificar:
|
|
45
|
+
|
|
46
|
+
1. **Event filter** — que requests/events compõem o SLI?
|
|
47
|
+
- `service`: nome do service/Edge Function
|
|
48
|
+
- `endpoint`: rota específica
|
|
49
|
+
- `http.method`: opcional, filtrar GET vs POST
|
|
50
|
+
2. **Good event predicate** — quando o event é "bom"?
|
|
51
|
+
- `result.success: true` (sempre)
|
|
52
|
+
- `duration_ms < N` (latência aceitável customer-facing)
|
|
53
|
+
- Outros campos críticos por feature
|
|
54
|
+
3. **Customer perception** — o que o cliente sente nessa feature?
|
|
55
|
+
- "checkout completes in < 800ms" — não "DB query < 100ms" (interno)
|
|
56
|
+
- "search returns within 200ms" — não "indexer latency < 50ms"
|
|
57
|
+
|
|
58
|
+
Apresentar SLI proposto via AskUserQuestion para confirmação:
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
SLI proposto para "{feature}":
|
|
62
|
+
|
|
63
|
+
Filtro: service={X}, endpoint={Y}, http.method={Z}
|
|
64
|
+
Good event: result.success=true AND duration_ms < {N}ms
|
|
65
|
+
|
|
66
|
+
Confirmar?
|
|
67
|
+
- Aceitar
|
|
68
|
+
- Ajustar threshold
|
|
69
|
+
- Discutir mais fundo
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Step 2 — Target
|
|
73
|
+
|
|
74
|
+
Sugerir target baseado em criticalidade da feature:
|
|
75
|
+
|
|
76
|
+
| Feature | Sugestão de target | Por quê |
|
|
77
|
+
|---|---|---|
|
|
78
|
+
| Login, signup | 99.95% | High-stakes; falha = perda de receita imediata |
|
|
79
|
+
| Checkout, payment | 99.9% | High; falha = revenue impact |
|
|
80
|
+
| Browse, search | 99.5% | Moderate; tolerância maior |
|
|
81
|
+
| Internal admin | (sem SLO) | Baixo volume, latência aceitável |
|
|
82
|
+
|
|
83
|
+
**Regra absoluta:** target ≤ 99.95%. Se feature parece exigir 99.99%+, é métrica/dashboard informativo, NÃO SLO.
|
|
84
|
+
|
|
85
|
+
Confirmar target via AskUserQuestion.
|
|
86
|
+
|
|
87
|
+
### Step 3 — Window
|
|
88
|
+
|
|
89
|
+
Default: **30d sliding window** (skill [`event-based-slos`](../skills/event-based-slos/SKILL.md) — fixed window é anti-pattern).
|
|
90
|
+
|
|
91
|
+
### Step 4 — Owner
|
|
92
|
+
|
|
93
|
+
Se não fornecido, AskUserQuestion:
|
|
94
|
+
|
|
95
|
+
```
|
|
96
|
+
Quem é o owner desse SLO?
|
|
97
|
+
- {team-email-1}
|
|
98
|
+
- {team-email-2}
|
|
99
|
+
- Outro (texto livre)
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Step 5 — Gerar SLO.md
|
|
103
|
+
|
|
104
|
+
Path canônico: `.planning/slos/{slo_name}.md` (criar diretório se não existe)
|
|
105
|
+
|
|
106
|
+
```markdown
|
|
107
|
+
---
|
|
108
|
+
name: {slo_name}
|
|
109
|
+
description: {feature description}
|
|
110
|
+
owner: {owner}
|
|
111
|
+
created: {date}
|
|
112
|
+
status: draft # PT-BR: draft → test_channel → primary → deprecated
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
# SLO: {slo_name}
|
|
116
|
+
|
|
117
|
+
## SLI
|
|
118
|
+
|
|
119
|
+
**Type:** event-based
|
|
120
|
+
**Filter:**
|
|
121
|
+
- service: `{X}`
|
|
122
|
+
- endpoint: `{Y}`
|
|
123
|
+
- http.method: `{Z}`
|
|
124
|
+
|
|
125
|
+
**Good event predicate:**
|
|
126
|
+
```sql
|
|
127
|
+
result_success = true
|
|
128
|
+
AND duration_ms < {N}
|
|
129
|
+
{outras condições}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
## SLO
|
|
133
|
+
|
|
134
|
+
- **Target:** {target}% ({target_decimal})
|
|
135
|
+
- **Window:** 30d sliding
|
|
136
|
+
- **Error budget:** {budget_pct}% = {budget_events_per_30d}_events_at_baseline_volume
|
|
137
|
+
|
|
138
|
+
## Alerts
|
|
139
|
+
|
|
140
|
+
(Configurar via `/burn-rate-status` ou agente burn-rate-forecaster — ver skill `burn-rate-alerting`)
|
|
141
|
+
|
|
142
|
+
- **Short-term (page):** lookahead 4h, baseline 1h, burn rate ≥ 14.4
|
|
143
|
+
- **Long-term (ticket):** lookahead 3d, baseline 18h, burn rate ≥ 1.0
|
|
144
|
+
|
|
145
|
+
## Materialization SQL
|
|
146
|
+
|
|
147
|
+
Ver `migrations/{date}_create_sli_{slo_name}.sql`
|
|
148
|
+
|
|
149
|
+
## Runbook
|
|
150
|
+
|
|
151
|
+
(TBD — adicionar pre-mitigations + investigation steps quando alert dispara)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Step 6 — Gerar migration SQL
|
|
155
|
+
|
|
156
|
+
Path canônico: `supabase/migrations/{timestamp}_create_sli_{slo_name}.sql`
|
|
157
|
+
|
|
158
|
+
```sql
|
|
159
|
+
-- PT-BR: SLI materialized view para SLO {slo_name}
|
|
160
|
+
-- Refresh via pg_cron a cada 30s; query para burn rate é barata
|
|
161
|
+
|
|
162
|
+
create materialized view if not exists obs.sli_{slo_name} as
|
|
163
|
+
select
|
|
164
|
+
date_trunc('minute', timestamp) as bucket,
|
|
165
|
+
count(*) filter (where {good_predicate}) as good,
|
|
166
|
+
count(*) filter (where not ({good_predicate})) as bad,
|
|
167
|
+
count(*) as total
|
|
168
|
+
from observability.events
|
|
169
|
+
where
|
|
170
|
+
service = '{X}'
|
|
171
|
+
and endpoint = '{Y}'
|
|
172
|
+
{and http_method = '{Z}'}
|
|
173
|
+
and timestamp > now() - interval '35 days' -- 30d + buffer
|
|
174
|
+
group by 1
|
|
175
|
+
with no data;
|
|
176
|
+
|
|
177
|
+
create unique index on obs.sli_{slo_name} (bucket);
|
|
178
|
+
|
|
179
|
+
-- PT-BR: refresh schedule via pg_cron
|
|
180
|
+
select cron.schedule(
|
|
181
|
+
'refresh_sli_{slo_name}',
|
|
182
|
+
'*/30 * * * * *',
|
|
183
|
+
$$ refresh materialized view concurrently obs.sli_{slo_name} $$
|
|
184
|
+
);
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Step 7 — Apply (Full mode) ou Output (Offline mode)
|
|
188
|
+
|
|
189
|
+
**Full mode:** invoke `mcp__supabase__apply_migration` com o SQL.
|
|
190
|
+
|
|
191
|
+
**Offline mode:** print SLO.md + SQL ao caller, instruir aplicação manual.
|
|
192
|
+
|
|
193
|
+
### Step 8 — Output
|
|
194
|
+
|
|
195
|
+
```
|
|
196
|
+
═══════════════════════════════════════════════════════════
|
|
197
|
+
SLO-ENGINEER · {slo_name}
|
|
198
|
+
═══════════════════════════════════════════════════════════
|
|
199
|
+
|
|
200
|
+
## SLO criado
|
|
201
|
+
- Name: {slo_name}
|
|
202
|
+
- Owner: {owner}
|
|
203
|
+
- Target: {target}%
|
|
204
|
+
- Window: 30d sliding
|
|
205
|
+
- Files:
|
|
206
|
+
- .planning/slos/{slo_name}.md
|
|
207
|
+
- supabase/migrations/{timestamp}_create_sli_{slo_name}.sql
|
|
208
|
+
|
|
209
|
+
## SLI materialization
|
|
210
|
+
- View: obs.sli_{slo_name}
|
|
211
|
+
- Refresh: pg_cron 30s
|
|
212
|
+
{Status: applied via MCP / requires manual apply}
|
|
213
|
+
|
|
214
|
+
## Próximos passos
|
|
215
|
+
1. `/burn-rate-status` — verificar baseline atual (sem incident histórico)
|
|
216
|
+
2. Configurar alerts via `burn-rate-forecaster`
|
|
217
|
+
3. Test channel por 1+ semana antes de promover a primary
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Quando NÃO invocar
|
|
221
|
+
|
|
222
|
+
- Métrica informativa (não SLO real) — use Grafana/dashboards
|
|
223
|
+
- Feature interna sem usuário externo — overhead
|
|
224
|
+
- Target > 99.95% solicitado — explicar que é métrica, não SLO; recusar
|
|
@@ -151,3 +151,16 @@ Sem preâmbulo. Sem "vou analisar agora". O caller precisa do plano para delegar
|
|
|
151
151
|
- Migrations já decididas e o user só quer escrever — delegar direto a `/supabase migration` (sem architect).
|
|
152
152
|
- Mudança trivial em tabela existente (adicionar coluna) — overhead.
|
|
153
153
|
- Apps com 1 tabela e 1 user — overkill.
|
|
154
|
+
|
|
155
|
+
## Observabilidade integrada
|
|
156
|
+
|
|
157
|
+
Schema nasce com observabilidade — não é addon. Este agent SEMPRE projeta:
|
|
158
|
+
|
|
159
|
+
1. **Tabela `observability.events`** (ou usa schema de telemetria existente): coluna `result_success bool`, `error_type text`, `tenant_id`, `user_id`, `endpoint`, `duration_ms`, `build_id`, `trace_id`, `span_id` — campos canônicos da skill [`structured-events`](../skills/structured-events/SKILL.md).
|
|
160
|
+
2. **Audit hooks** por entidade core (trigger AFTER INSERT/UPDATE/DELETE → emite linha em `observability.audit_log`) — base para [`core-analysis-loop`](../skills/core-analysis-loop/SKILL.md).
|
|
161
|
+
3. **SLI tables**: para cada feature crítica, view materialized `obs.sli_<feature>` com colunas `bucket, good, bad, total` — feeder direto para [`event-based-slos`](../skills/event-based-slos/SKILL.md) *(skill da Phase 32)*.
|
|
162
|
+
4. **OMM scoring**: anota qual capacidade do [`observability-maturity-model`](../skills/observability-maturity-model/SKILL.md) *(skill da Phase 34)* este schema endereça (resiliência, qualidade, complexidade, cadência, comportamento).
|
|
163
|
+
|
|
164
|
+
**Output adicionado:** seção "## 9. Observabilidade" no plano com tabela de `obs.events` + audit triggers + SLI views.
|
|
165
|
+
|
|
166
|
+
**Validação ODD** (skill [`observability-driven-development`](../skills/observability-driven-development/SKILL.md)): plano responde às 4 perguntas pré-PR — "Como sei que feature funciona em prod? Como comparo versões? Como sei quem está usando? Como detecto anomalias?"
|
|
@@ -292,7 +292,24 @@ Anti-patterns prevenidos:
|
|
|
292
292
|
- Projeto já tem `@supabase/ssr` configurado e funcionando — overhead
|
|
293
293
|
- Projeto não é Next.js (Expo, SvelteKit, Nuxt) — defer para skills `supabase-expo` etc. (v1.9+)
|
|
294
294
|
|
|
295
|
+
## Observabilidade integrada
|
|
296
|
+
|
|
297
|
+
Auth events são SLI primário — "successful login %" é métrica de saúde direta para o usuário final.
|
|
298
|
+
|
|
299
|
+
1. **Auth events estruturados** (skill [`structured-events`](../skills/structured-events/SKILL.md)) — instrumentar handlers em `app/auth/*/route.ts`:
|
|
300
|
+
- `event_name`: `auth_signup` | `auth_login` | `auth_mfa_challenge` | `auth_logout` | `auth_password_reset` | `auth_oauth_callback`
|
|
301
|
+
- `result.success`: bool
|
|
302
|
+
- `error.type` enum: `'invalid_credentials'` | `'email_unconfirmed'` | `'mfa_required'` | `'rate_limit'` | `'oauth_provider_error'`
|
|
303
|
+
- `auth.method`: `'password'` | `'magic_link'` | `'oauth_google'` | `'oauth_github'` | `'sso'`
|
|
304
|
+
- `user.id` (após sucesso), `customer.tier`, `tenant_id` (se multi-tenant)
|
|
305
|
+
2. **SLO de auth** (skill [`event-based-slos`](../skills/event-based-slos/SKILL.md) *Phase 32*): "99.5% dos login attempts retornam OK em < 800ms", janela deslizante 30d. SLI: `count(*) WHERE event_name='auth_login' AND result_success=true AND duration_ms<800`.
|
|
306
|
+
3. **Audit trail**: signup/password_reset/mfa_setup viajam para `observability.audit_log` com IP, user_agent, geo (se disponível) — base para detectar fraud patterns via [`core-analysis-loop`](../skills/core-analysis-loop/SKILL.md).
|
|
307
|
+
|
|
308
|
+
**Output adicionado:** seção "## Observability hooks" com snippet de span wrapper em handlers `/auth/*`.
|
|
309
|
+
|
|
295
310
|
## Ver também
|
|
296
311
|
|
|
297
312
|
- [supabase-auth-ssr](../skills/supabase-auth-ssr/SKILL.md) — base de conhecimento canônica
|
|
298
313
|
- [supabase-rls-policies](../skills/supabase-rls-policies/SKILL.md) — RLS aplicado quando user autenticado consulta tabelas
|
|
314
|
+
- [structured-events](../skills/structured-events/SKILL.md) — campos canônicos para auth events
|
|
315
|
+
- [event-based-slos](../skills/event-based-slos/SKILL.md) *(Phase 32)* — SLO de "successful login %"
|
|
@@ -178,8 +178,30 @@ Test local:
|
|
|
178
178
|
- Função existente que precisa de pequeno ajuste → use Edit direto
|
|
179
179
|
- Lógica que pode rodar em DB function (`security definer`) → considera `supabase-database-functions` (mais barato que Edge)
|
|
180
180
|
|
|
181
|
+
## Observabilidade integrada
|
|
182
|
+
|
|
183
|
+
Edge Function nasce instrumentada com OTel — não é addon. Beneficia mais que qualquer outro agent dado que é entry-point externo.
|
|
184
|
+
|
|
185
|
+
1. **OTel SDK no topo do `index.ts`** (skill [`opentelemetry-standard`](../skills/opentelemetry-standard/SKILL.md)):
|
|
186
|
+
```ts
|
|
187
|
+
import { trace } from 'npm:@opentelemetry/api@1.9.0'
|
|
188
|
+
import { NodeSDK } from 'npm:@opentelemetry/sdk-node@0.55.0'
|
|
189
|
+
import { OTLPTraceExporter } from 'npm:@opentelemetry/exporter-trace-otlp-http@0.55.0'
|
|
190
|
+
const sdk = new NodeSDK({ /* service.name, OTLP endpoint */ })
|
|
191
|
+
sdk.start()
|
|
192
|
+
```
|
|
193
|
+
2. **Span por handler** com kind `SERVER` envolvendo `Deno.serve`. Atributos canônicos: `request.id`, `user.id`, `tenant_id`, `endpoint`, `result.success`, `error.type`, `build_id` (`Deno.env.get('SUPABASE_GIT_SHA')`) — skill [`structured-events`](../skills/structured-events/SKILL.md).
|
|
194
|
+
3. **Context propagation** via header `traceparent` para outbound calls a Postgres/PostgREST/external (skill [`distributed-tracing`](../skills/distributed-tracing/SKILL.md)).
|
|
195
|
+
4. **Sampling head-based** baseado em `customer.tier` ou `feature_flag.<name>` (skill [`telemetry-sampling`](../skills/telemetry-sampling/SKILL.md) *Phase 34*) — 100% errors, 100% enterprise, 10% baseline.
|
|
196
|
+
|
|
197
|
+
**Output adicionado:** template completo de Edge Function inclui SDK setup + span wrapper + propagação outbound + classificador de error.type. ODD-compliant (4 perguntas pré-PR endereçadas).
|
|
198
|
+
|
|
181
199
|
## Ver também
|
|
182
200
|
|
|
183
201
|
- [supabase-edge-functions](../skills/supabase-edge-functions/SKILL.md) — base de conhecimento canônica
|
|
184
202
|
- [supabase-cron-queues](../skills/supabase-cron-queues/SKILL.md) — pattern `cron → pgmq → Edge Function`
|
|
185
203
|
- [supabase-auth-ssr](../skills/supabase-auth-ssr/SKILL.md) — clients Supabase
|
|
204
|
+
- [opentelemetry-standard](../skills/opentelemetry-standard/SKILL.md) — SDK setup para Deno
|
|
205
|
+
- [distributed-tracing](../skills/distributed-tracing/SKILL.md) — context propagation
|
|
206
|
+
- [structured-events](../skills/structured-events/SKILL.md) — campos canônicos
|
|
207
|
+
- [observability-driven-development](../skills/observability-driven-development/SKILL.md) — 4 perguntas pré-PR
|
|
@@ -154,3 +154,21 @@ Próximos passos:
|
|
|
154
154
|
- `auth.uid()` sem `(select)` → SEMPRE wrapper
|
|
155
155
|
- Schema-qualifier ausente em DB functions → SEMPRE `public.<name>`
|
|
156
156
|
- Comandos destrutivos sem comentário → BLOQUEIA até user adicionar Risk/Validation/Rollback
|
|
157
|
+
|
|
158
|
+
## Observabilidade integrada
|
|
159
|
+
|
|
160
|
+
Toda migration emite evento estruturado e cria audit hooks por default — não é addon, é parte do contrato (skill [`observability-driven-development`](../skills/observability-driven-development/SKILL.md)).
|
|
161
|
+
|
|
162
|
+
1. **Migration event** (auto-gerado no fim da migration):
|
|
163
|
+
```sql
|
|
164
|
+
-- PT-BR: emite linha em observability.migration_events
|
|
165
|
+
insert into observability.migration_events (
|
|
166
|
+
migration_id, sql_hash, applied_at, build_id, result_success, duration_ms
|
|
167
|
+
) values (
|
|
168
|
+
'20260506120000_create_orders', md5(...), now(), '{{BUILD_ID}}', true, {{ELAPSED_MS}}
|
|
169
|
+
);
|
|
170
|
+
```
|
|
171
|
+
2. **Audit triggers em tabelas sensíveis** (pagamentos, auth, dados pessoais): trigger `after insert/update/delete` que insere `audit_log` com `tenant_id`, `user_id`, `op`, `old_row`, `new_row`, `actor`, `timestamp`.
|
|
172
|
+
3. **Atributos canônicos** em qualquer função criada: `set search_path = ''` + comments com `result.success`, `error.type` enum esperado (skill [`structured-events`](../skills/structured-events/SKILL.md)).
|
|
173
|
+
|
|
174
|
+
**Output adicionado:** seção "## Audit hooks" + "## Migration event emit" no SQL gerado, comentadas em PT-BR.
|
|
@@ -245,8 +245,31 @@ PRÓXIMOS PASSOS
|
|
|
245
245
|
- Presence para listas de objetos → ALERTA explícito (use queries normais)
|
|
246
246
|
- Naming inconsistente → SEMPRE `scope:entity:id`
|
|
247
247
|
|
|
248
|
+
## Observabilidade integrada
|
|
249
|
+
|
|
250
|
+
Realtime é tipicamente fora-de-trace porque WebSocket não usa header `traceparent` por default. Patches:
|
|
251
|
+
|
|
252
|
+
1. **Trace context no payload do broadcast** (skill [`distributed-tracing`](../skills/distributed-tracing/SKILL.md)):
|
|
253
|
+
```ts
|
|
254
|
+
// PT-BR: producer — anexa traceparent ao payload do broadcast
|
|
255
|
+
const carrier: Record<string, string> = {}
|
|
256
|
+
propagation.inject(context.active(), carrier)
|
|
257
|
+
await channel.send({
|
|
258
|
+
type: 'broadcast',
|
|
259
|
+
event: 'message_inserted',
|
|
260
|
+
payload: { ...originalPayload, _trace_context: carrier }
|
|
261
|
+
})
|
|
262
|
+
```
|
|
263
|
+
2. **Consumer extrai contexto** ao receber broadcast e abre span filho — stitching cross-WebSocket fica completo.
|
|
264
|
+
3. **Atributos canônicos** em todo span de subscribe/unsubscribe (skill [`structured-events`](../skills/structured-events/SKILL.md)): `channel.name`, `channel.private`, `subscribe.status` (`SUBSCRIBED` | `CHANNEL_ERROR` | `TIMED_OUT`), `user.id`, `tenant_id`.
|
|
265
|
+
4. **Trigger DB** (`realtime.broadcast_changes`) emite evento estruturado em `observability.events` com `event_name = 'realtime_broadcast'`, `result_success`, `tenant_id`.
|
|
266
|
+
|
|
267
|
+
**Output adicionado:** template inclui propagation.inject no payload + span wrapper em subscribe + atributos canônicos no callback.
|
|
268
|
+
|
|
248
269
|
## Ver também
|
|
249
270
|
|
|
250
271
|
- [supabase-realtime](../skills/supabase-realtime/SKILL.md) — base de conhecimento canônica
|
|
251
272
|
- [supabase-rls-writer](./supabase-rls-writer.md) — invocar para policies adicionais em tabelas do app
|
|
252
273
|
- [supabase-database-functions](../skills/supabase-database-functions/SKILL.md) — trigger function pattern
|
|
274
|
+
- [distributed-tracing](../skills/distributed-tracing/SKILL.md) — context propagation cross-WebSocket
|
|
275
|
+
- [structured-events](../skills/structured-events/SKILL.md) — atributos canônicos para channels
|
|
@@ -212,7 +212,24 @@ NOTAS
|
|
|
212
212
|
- Tabela já tem policies estabelecidas e user só quer 1 ajuste pequeno → use Edit direto
|
|
213
213
|
- Tabela é puramente read-only para `anon` (ex: catalog público) → policy trivial, overhead
|
|
214
214
|
|
|
215
|
+
## Observabilidade integrada
|
|
216
|
+
|
|
217
|
+
RLS denials são sinal de segurança e debug — emite evento estruturado SEMPRE.
|
|
218
|
+
|
|
219
|
+
1. **RLS deny logging**: no entry-point do app (Edge Function ou backend), capturar `42501 insufficient_privilege` errors e emitir span com:
|
|
220
|
+
- `policy.name` (qual policy negou)
|
|
221
|
+
- `attempted_op` (`select` | `insert` | `update` | `delete`)
|
|
222
|
+
- `user.id` (de `auth.uid()` na sessão)
|
|
223
|
+
- `tenant_id` (de `app_metadata` quando aplicável)
|
|
224
|
+
- `resource.table` (qual tabela/view tentada)
|
|
225
|
+
- `error.type = 'authz'` (skill [`structured-events`](../skills/structured-events/SKILL.md))
|
|
226
|
+
2. **Investigação via Core Analysis Loop** (skill [`core-analysis-loop`](../skills/core-analysis-loop/SKILL.md)): pergunta canônica "qual policy + qual tenant + qual op + quando começou?" → query agrupando por essas 4 dimensões para identificar pattern.
|
|
227
|
+
|
|
228
|
+
**Output adicionado:** seção "## Observability hooks" com snippet de error handler que classifica RLS denial e emite span.
|
|
229
|
+
|
|
215
230
|
## Ver também
|
|
216
231
|
|
|
217
232
|
- [supabase-rls-policies](../skills/supabase-rls-policies/SKILL.md) — base de conhecimento canônica das regras
|
|
218
233
|
- [supabase-migration-writer](./supabase-migration-writer.md) — invocar quando user quer policies dentro de migration nova
|
|
234
|
+
- [structured-events](../skills/structured-events/SKILL.md) — campos canônicos para RLS denial logging
|
|
235
|
+
- [core-analysis-loop](../skills/core-analysis-loop/SKILL.md) — investigar denial patterns
|
|
@@ -233,8 +233,26 @@ ALERTAS
|
|
|
233
233
|
- **Vector Buckets / Analytics Buckets** ainda alpha em 2026-05-06 — não detalhar
|
|
234
234
|
- **Smart CDN** para egress optimization — fora deste agent (config no Dashboard)
|
|
235
235
|
|
|
236
|
+
## Observabilidade integrada
|
|
237
|
+
|
|
238
|
+
Upload events são quentes em custo (egress + storage) e em UX (lentidão de upload = abandono). Instrumentar SEMPRE.
|
|
239
|
+
|
|
240
|
+
1. **Span por upload/download** (skill [`structured-events`](../skills/structured-events/SKILL.md)) com atributos:
|
|
241
|
+
- `bucket.name`, `bucket.public` (bool)
|
|
242
|
+
- `file.size_bytes`, `file.mime_type`, `file.path`
|
|
243
|
+
- `operation`: `upload` | `download` | `signed_url` | `delete`
|
|
244
|
+
- `result.success`, `error.type` (enum: `quota_exceeded`, `unauthorized`, `mime_blocked`, `size_exceeded`, `network`)
|
|
245
|
+
- `duration_ms`, `transfer.bytes_per_second` (calculado)
|
|
246
|
+
- `user.id`, `tenant_id` (do `auth.uid()`)
|
|
247
|
+
2. **Sampling** (skill [`telemetry-sampling`](../skills/telemetry-sampling/SKILL.md) *Phase 34*): 100% errors, 100% uploads > 10 MB (cardinalidade baixa, valor alto), 5% baseline para downloads pequenos (alto volume).
|
|
248
|
+
3. **Audit log** para uploads em buckets sensíveis (`audit_log` table com `actor`, `op`, `resource`, `geo`, `user_agent`).
|
|
249
|
+
|
|
250
|
+
**Output adicionado:** seção "## Observability hooks" com snippet de upload/download wrapper.
|
|
251
|
+
|
|
236
252
|
## Ver também
|
|
237
253
|
|
|
238
254
|
- [supabase-storage](../skills/supabase-storage/SKILL.md) — base de conhecimento canônica
|
|
239
255
|
- [supabase-rls-writer](./supabase-rls-writer.md) — invocar para policies adicionais
|
|
240
256
|
- [supabase-auth-ssr](../skills/supabase-auth-ssr/SKILL.md) — usuário autenticado obtém `auth.uid()`
|
|
257
|
+
- [structured-events](../skills/structured-events/SKILL.md) — campos canônicos para upload/download events
|
|
258
|
+
- [telemetry-sampling](../skills/telemetry-sampling/SKILL.md) *(Phase 34)* — head-based sampling por size_bytes
|
|
@@ -33,4 +33,25 @@ Glob: .planning/phases/*/*-VERIFICATION.md
|
|
|
33
33
|
<process>
|
|
34
34
|
Execute o workflow audit-milestone de @./.claude/framework/workflows/audit-milestone.md do início ao fim.
|
|
35
35
|
Preserve todos os checkpoints do workflow (determinação de escopo, leitura de verificações, checagem de integração, cobertura de requisitos, roteamento).
|
|
36
|
-
</process>
|
|
36
|
+
</process>
|
|
37
|
+
|
|
38
|
+
<observability_integration>
|
|
39
|
+
**OMM scoring (v1.9 — INT-FW-04):**
|
|
40
|
+
|
|
41
|
+
Quando `workflow.audit_milestone_omm = true` (default), o workflow inclui passo OMM scoring:
|
|
42
|
+
|
|
43
|
+
```text
|
|
44
|
+
Skill(skill="framework:auditar-observabilidade")
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
O comando `/auditar-observabilidade` invoca o agente [`omm-auditor`](../agents/omm-auditor.md) que pontua as 5 capacidades (resiliência, qualidade, complexidade, cadência, comportamento) contra o marco anterior. O OMM-REPORT.md gerado é incluído como anexo no MILESTONE-AUDIT.md.
|
|
48
|
+
|
|
49
|
+
Resultado de regression OMM:
|
|
50
|
+
- **0 regressions:** audit aprovado
|
|
51
|
+
- **1+ regressions, blocking=false:** warn explícito; audit aprovado com nota
|
|
52
|
+
- **1+ regressions, blocking=true (`workflow.omm_no_regression=true`):** audit fail → user escolha entre fix lacunas ou aceitar
|
|
53
|
+
|
|
54
|
+
Skill consultada: [`observability-maturity-model`](../skills/observability-maturity-model/SKILL.md).
|
|
55
|
+
|
|
56
|
+
**REQ:** INT-FW-04.
|
|
57
|
+
</observability_integration>
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: auditar-observabilidade
|
|
3
|
+
description: Invoca omm-auditor para gerar OMM-REPORT.md scored. 5 capacidades com trend vs marco anterior. Action items priorizados P0-P3.
|
|
4
|
+
argument-hint: "[--previous <marco>] [--ci]"
|
|
5
|
+
allowed-tools:
|
|
6
|
+
- Read
|
|
7
|
+
- Write
|
|
8
|
+
- Bash
|
|
9
|
+
- Task
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<objective>
|
|
13
|
+
Gerar OMM-REPORT.md com snapshot scored das 5 capacidades de observabilidade. Aplica skill [`observability-maturity-model`](../skills/observability-maturity-model/SKILL.md) — sintomas qualitativos doing well/poorly por capacidade.
|
|
14
|
+
|
|
15
|
+
**Cria/Atualiza:**
|
|
16
|
+
- `.planning/OMM-REPORT.md` — snapshot atual
|
|
17
|
+
- (Em `/concluir-marco`) `.planning/milestones/<v>/OMM-REPORT.md` — snapshot arquivado
|
|
18
|
+
|
|
19
|
+
**Após:** time tem 5 scores + trend + action items priorizados.
|
|
20
|
+
</objective>
|
|
21
|
+
|
|
22
|
+
<context>
|
|
23
|
+
**Argumentos:** `$ARGUMENTS`
|
|
24
|
+
|
|
25
|
+
**Flags:**
|
|
26
|
+
- `--previous <marco>` — comparar com marco específico (default: detecta automaticamente do MILESTONES.md)
|
|
27
|
+
- `--ci` — modo CI: exit code 0 se OK, 1 se regression em qualquer capacidade
|
|
28
|
+
|
|
29
|
+
**Quando rodar:**
|
|
30
|
+
- Manualmente para snapshot informal
|
|
31
|
+
- Em `/auditar-marco` (audit pre-conclusion) — Phase 35 INT-FW-04
|
|
32
|
+
- Em `/concluir-marco` (gate de regression) — Phase 35 INT-FW-05
|
|
33
|
+
</context>
|
|
34
|
+
|
|
35
|
+
<process>
|
|
36
|
+
|
|
37
|
+
## 1. Parsear argumentos
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
PREVIOUS=$(echo "$ARGUMENTS" | grep -oE -- '--previous [^ ]+' | awk '{print $2}')
|
|
41
|
+
CI_MODE=$(echo "$ARGUMENTS" | grep -c -- '--ci' || true)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## 2. Detectar previous milestone
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
if [ -z "$PREVIOUS" ]; then
|
|
48
|
+
# PT-BR: extrair último concluído de MILESTONES.md
|
|
49
|
+
PREVIOUS=$(grep -E '^### v[0-9.]+\b' .planning/MILESTONES.md | head -2 | tail -1 | grep -oE 'v[0-9.]+')
|
|
50
|
+
fi
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## 3. Dispatch para `omm-auditor`
|
|
54
|
+
|
|
55
|
+
```text
|
|
56
|
+
Task(
|
|
57
|
+
subagent_type="omm-auditor",
|
|
58
|
+
prompt="
|
|
59
|
+
${PREVIOUS:+previous_milestone: ${PREVIOUS}}
|
|
60
|
+
mode: ${CI_MODE:+ci}snapshot
|
|
61
|
+
|
|
62
|
+
Gerar OMM-REPORT.md com:
|
|
63
|
+
1. Score 1-5 por capacidade (5 capacidades)
|
|
64
|
+
2. Trend vs ${PREVIOUS:-último marco}
|
|
65
|
+
3. Action items priorizados P0-P3
|
|
66
|
+
4. Regression alerts (se alguma capacidade regrediu)
|
|
67
|
+
5. Comparação por marco
|
|
68
|
+
"
|
|
69
|
+
)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## 4. Pós-output
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
═══════════════════════════════════════════════════════════
|
|
76
|
+
framework ► AUDITAR-OBSERVABILIDADE
|
|
77
|
+
═══════════════════════════════════════════════════════════
|
|
78
|
+
|
|
79
|
+
[output do omm-auditor — snapshot inline]
|
|
80
|
+
|
|
81
|
+
OMM-REPORT.md: .planning/OMM-REPORT.md
|
|
82
|
+
|
|
83
|
+
${CI_MODE:+## CI Mode}
|
|
84
|
+
${CI_MODE:+Exit code: 0 (OK) / 1 (regression detectada)}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## 5. Modo `--ci`
|
|
88
|
+
|
|
89
|
+
Se `--ci` setado:
|
|
90
|
+
- Parse OMM-REPORT.md para detectar regression alerts
|
|
91
|
+
- Se ≥ 1 regression → exit 1 (CI fails)
|
|
92
|
+
- Senão → exit 0 (OK)
|
|
93
|
+
|
|
94
|
+
</process>
|
|
95
|
+
|
|
96
|
+
<success_criteria>
|
|
97
|
+
- [ ] omm-auditor invocado via Task
|
|
98
|
+
- [ ] OMM-REPORT.md gerado em `.planning/OMM-REPORT.md`
|
|
99
|
+
- [ ] 5 capacidades scored
|
|
100
|
+
- [ ] Trend calculado vs `--previous` ou auto-detectado
|
|
101
|
+
- [ ] Action items P0-P3 listados
|
|
102
|
+
- [ ] Modo `--ci` exit code apropriado se regression
|
|
103
|
+
</success_criteria>
|