Exemplos de Bundles OKF
Três bundles completos pra você copiar, adaptar e sair usando. Nada de “hello world” — são exemplos com cross-links, frontmatter real e estrutura de pastas que funciona em produção.
Opinião: bundle bom é bundle que alguém abre o
index.mde entende o domínio em 30 segundos. Se precisa de manual pra navegar, a estrutura tá errada.
1. E-commerce Analytics
Bundle de um time de dados que documenta tabelas, métricas e dashboards de um e-commerce. Caso clássico: o analista novo chega e precisa saber onde fica o que.
Estrutura de pastas
ecommerce-analytics/
├── index.md
├── tables/
│ ├── index.md
│ ├── pedidos.md
│ └── clientes.md
├── metrics/
│ ├── index.md
│ └── receita-bruta.md
└── log.mdindex.md
# E-commerce Analytics
Bundle de conhecimento do domínio analytics do e-commerce Acme.
# Tabelas
* [Pedidos](tables/pedidos.md) - uma linha por pedido finalizado
* [Clientes](tables/clientes.md) - cadastro de clientes com segmentação
# Métricas
* [Receita Bruta](metrics/receita-bruta.md) - GMV sem descontos e devoluçõestables/pedidos.md
---
type: BigQuery Table
title: Pedidos
description: Uma linha por pedido finalizado em qualquer canal (app, web, marketplace).
resource: https://console.cloud.google.com/bigquery?p=acme-prod&d=ecommerce&t=pedidos
tags: [vendas, core, receita]
timestamp: 2026-06-10T14:00:00Z
owner: time-dados
sla_freshness: 30min
---
Tabela principal de faturamento. Toda métrica de receita começa aqui.
# Schema
| Coluna | Tipo | Descrição |
|-----------------|-----------|--------------------------------------------------|
| `pedido_id` | STRING | UUID do pedido. PK. |
| `cliente_id` | STRING | FK → [clientes](/tables/clientes.md). |
| `total_brl` | NUMERIC | Valor total em BRL (com impostos, sem frete). |
| `status` | STRING | `paid`, `refunded`, `cancelled`. |
| `canal` | STRING | `app`, `web`, `marketplace`. |
| `criado_em` | TIMESTAMP | Quando o pedido foi submetido. |
| `atualizado_em` | TIMESTAMP | Última mudança de status. |
# Joins
- [clientes](/tables/clientes.md) via `cliente_id`
- Usado pela métrica [Receita Bruta](/metrics/receita-bruta.md)
# Notas
- Pedidos com `status = cancelled` **não entram** no cálculo de receita.
- Particionado por `criado_em` (DAY). Queries sem filtro de data = conta alta.
# Citations
[1] [Documentação do pipeline de ingestão](https://wiki.acme.internal/data/pipeline-pedidos)tables/clientes.md
---
type: BigQuery Table
title: Clientes
description: Cadastro unificado de clientes com segmentação RFM e lifecycle.
resource: https://console.cloud.google.com/bigquery?p=acme-prod&d=ecommerce&t=clientes
tags: [clientes, segmentacao, core]
timestamp: 2026-06-08T10:00:00Z
owner: time-dados
---
Base canônica de clientes. Toda análise de cohort ou segmentação parte daqui.
# Schema
| Coluna | Tipo | Descrição |
|-------------------|-----------|---------------------------------------------|
| `cliente_id` | STRING | UUID. PK. |
| `email` | STRING | Email principal (PII — acesso restrito). |
| `segmento_rfm` | STRING | `champions`, `at_risk`, `hibernating`, etc. |
| `primeiro_pedido` | TIMESTAMP | Data do primeiro pedido. |
| `ltv_brl` | NUMERIC | Lifetime value acumulado. |
| `criado_em` | TIMESTAMP | Data de cadastro. |
# Joins
- [pedidos](/tables/pedidos.md) via `cliente_id`
# Notas
- Atualizado diariamente pelo job de segmentação RFM (6h UTC).
- `email` requer role `pii-reader` — não exponha em dashboards públicos.metrics/receita-bruta.md
---
type: Metric
title: Receita Bruta (GMV)
description: Soma de total_brl de pedidos pagos, sem descontar devoluções.
tags: [receita, kpi, finance]
timestamp: 2026-06-10T14:00:00Z
owner: time-finance
granularity: daily
---
KPI primário do negócio. Reportado no board mensal.
# Definição
```sql
SELECT
DATE(criado_em) AS dia,
SUM(total_brl) AS receita_bruta
FROM `acme-prod.ecommerce.pedidos`
WHERE status = 'paid'
GROUP BY 1Fonte de dados
Calculada a partir da tabela pedidos, filtrando status = 'paid'.
Cuidados
- Não inclui pedidos
refundedoucancelled. - Não desconta devoluções parciais (ver métrica
receita-liquidaquando existir). - Frete não está incluído no
total_brl.
Citations
[1] Definição aprovada pelo CFO — Confluence
---
## 2. SaaS Incident Playbooks
Bundle de um time de SRE/platform que documenta runbooks, alertas e processo de escalation. O cenário: são 3h da manhã, o PagerDuty tocou, e o engenheiro de plantão precisa saber o que fazer sem acordar ninguém (ainda).
### Estrutura de pastas
incident-playbooks/ ├── index.md ├── alerts/ │ ├── index.md │ ├── api-latency-p99.md │ └── db-connections-exhausted.md ├── runbooks/ │ ├── index.md │ └── escalar-incidente.md └── log.md
### `index.md`
```markdown
# Incident Playbooks
Conhecimento operacional do time Platform. Se o pager tocou, comece aqui.
# Alertas
* [API Latency P99](alerts/api-latency-p99.md) - latência acima do SLO no gateway
* [DB Connections Exhausted](alerts/db-connections-exhausted.md) - pool de conexões esgotado
# Runbooks
* [Escalar Incidente](runbooks/escalar-incidente.md) - quando e como escalar pra liderançaalerts/api-latency-p99.md
---
type: Alert
title: API Latency P99 > 2s
description: Dispara quando a latência P99 do API Gateway ultrapassa 2 segundos por 5 minutos.
tags: [oncall, api, latencia, sev2]
timestamp: 2026-05-20T09:00:00Z
owner: time-platform
severity: SEV2
slo: 99.5% requests < 2s
---
# Trigger
Prometheus alert rule:
```yaml
- alert: APILatencyP99High
expr: histogram_quantile(0.99, rate(http_duration_seconds_bucket[5m])) > 2
for: 5m
labels:
severity: sev2Diagnóstico
- Abra o Grafana — API Latency Dashboard.
- Verifique se é um endpoint específico ou generalizado.
- Cheque o pool de conexões — se esgotado, veja DB Connections Exhausted.
- Verifique deploys recentes:
kubectl rollout history deploy/api-gateway -n production.
Mitigação
- Se um endpoint específico: habilite circuit breaker via feature flag
cb_{endpoint}. - Se generalizado: escale pods
kubectl scale deploy/api-gateway --replicas=10 -n production. - Se persistir > 15min: siga Escalar Incidente.
Falsos positivos conhecidos
- Batch de reconciliação financeira (todo dia 2h UTC) causa spike de 3-4min. Ignore se resolver sozinho.
Citations
[1] SLO definition — internal wiki
### `alerts/db-connections-exhausted.md`
```markdown
---
type: Alert
title: DB Connections Exhausted
description: Pool de conexões PostgreSQL atingiu 95% da capacidade.
tags: [oncall, database, postgres, sev1]
timestamp: 2026-06-01T11:00:00Z
owner: time-platform
severity: SEV1
---
# Trigger
```yaml
- alert: DBConnectionPoolExhausted
expr: pg_stat_activity_count / pg_settings_max_connections > 0.95
for: 2m
labels:
severity: sev1Diagnóstico
- Identifique queries longas:
SELECT pid, now() - pg_stat_activity.query_start AS duration, query FROM pg_stat_activity WHERE state != 'idle' ORDER BY duration DESC; - Verifique se há leak de conexão (app não fechando connections).
- Cheque se API Latency P99 também disparou (efeito cascata comum).
Mitigação imediata
- Mate queries > 5min:
SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE duration > interval '5 minutes'; - Se não resolver: restart do PgBouncer
systemctl restart pgbouncer. - Não faça restart do Postgres sem escalar antes — veja Escalar Incidente.
Root causes comuns
- Deploy com migration pesada sem
statement_timeout. - Cronjob de relatório sem connection pooling.
- N+1 query em endpoint novo.
### `runbooks/escalar-incidente.md`
```markdown
---
type: Runbook
title: Escalar Incidente
description: Processo de escalation — quando sair do diagnóstico solo e acionar reforços.
tags: [oncall, processo, escalation]
timestamp: 2026-05-15T08:00:00Z
owner: time-platform
---
# Quando escalar
Escale **imediatamente** se:
- SEV1 sem mitigação após 10 minutos.
- SEV2 sem mitigação após 30 minutos.
- Qualquer incidente com impacto financeiro visível (pedidos falhando).
- Você não entende o que está acontecendo (isso é válido, não é vergonha).
# Como escalar
| Passo | Ação | Contato |
|-------|------|---------|
| 1 | Declare incidente no Slack `#incidents` | `@oncall-platform` |
| 2 | Acione engineering manager | PagerDuty escalation policy `platform-em` |
| 3 | Se impacto em clientes > 5min | Acione `@oncall-cs` para comunicação |
| 4 | Se revenue impactada | Acione `@oncall-finance` |
# Template de declaração
🚨 INCIDENTE DECLARADO Severidade: SEV{1|2} Alerta: {link para o alerta que disparou} Impacto: {o que o usuário está vendo} Status: Investigando / Mitigando / Resolvido IC: @{seu-nome}
# Pós-incidente
- Postmortem obrigatório para SEV1, opcional para SEV2.
- Prazo: 48h após resolução.
- Template: [Confluence — Postmortem Template](https://wiki.acme.internal/templates/postmortem).
# Links relacionados
- [API Latency P99](/alerts/api-latency-p99.md) — alerta mais comum que gera escalation.
- [DB Connections Exhausted](/alerts/db-connections-exhausted.md) — segundo mais comum.3. API Documentation
Bundle pra documentar uma API REST. Diferente do OpenAPI (que é spec de contrato), aqui o foco é conhecimento contextual: por que o endpoint existe, cuidados de uso, rate limits, exemplos que de fato funcionam.
Estrutura de pastas
api-docs/
├── index.md
├── auth/
│ ├── index.md
│ └── oauth2-flow.md
├── endpoints/
│ ├── index.md
│ ├── criar-pedido.md
│ └── listar-clientes.md
├── policies/
│ ├── index.md
│ └── rate-limits.md
└── log.mdindex.md
# API Docs — Acme Commerce API
Documentação contextual da API pública v2. Para a spec OpenAPI crua, veja o [Swagger UI](https://api.acme.com/docs).
# Autenticação
* [OAuth2 Flow](auth/oauth2-flow.md) - como obter e renovar tokens
# Endpoints
* [Criar Pedido](endpoints/criar-pedido.md) - POST /v2/orders
* [Listar Clientes](endpoints/listar-clientes.md) - GET /v2/customers
# Políticas
* [Rate Limits](policies/rate-limits.md) - limites por plano e headers de controleauth/oauth2-flow.md
---
type: Auth Flow
title: OAuth2 Client Credentials
description: Fluxo de autenticação machine-to-machine para a API Acme.
resource: https://api.acme.com/oauth/token
tags: [auth, oauth2, seguranca]
timestamp: 2026-06-05T16:00:00Z
owner: time-api
---
# Fluxo
```bash
curl -X POST https://api.acme.com/oauth/token \
-d grant_type=client_credentials \
-d client_id=$CLIENT_ID \
-d client_secret=$CLIENT_SECRET \
-d scope="orders:write customers:read"Resposta:
{
"access_token": "eyJhbGci...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "orders:write customers:read"
}Uso
Envie o token no header de todos os requests:
Authorization: Bearer {access_token}Scopes disponíveis
| Scope | Permite |
|---|---|
orders:read | Consultar pedidos |
orders:write | Criar e atualizar pedidos |
customers:read | Listar e buscar clientes |
customers:write | Criar e atualizar clientes |
Cuidados
- Token expira em 1 hora. Implemente refresh antes da expiração.
- Rate limit do endpoint
/oauth/token: 10 req/min por client_id — não peça token novo a cada request. - Respeite os rate limits gerais após autenticado.
Citations
[1] RFC 6749 — OAuth 2.0 Client Credentials
### `endpoints/criar-pedido.md`
```markdown
---
type: API Endpoint
title: Criar Pedido
description: Cria um novo pedido no sistema. Requer scope orders:write.
resource: https://api.acme.com/v2/orders
tags: [orders, write, core]
timestamp: 2026-06-10T10:00:00Z
owner: time-api
method: POST
path: /v2/orders
auth_scope: orders:write
---
# Request
```bash
curl -X POST https://api.acme.com/v2/orders \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"customer_id": "cust_abc123",
"items": [
{"sku": "WIDGET-01", "quantity": 2, "unit_price_brl": 49.90}
],
"shipping_address_id": "addr_xyz789"
}'Response (201 Created)
{
"order_id": "ord_def456",
"status": "pending_payment",
"total_brl": 99.80,
"created_at": "2026-06-10T10:30:00Z"
}Erros comuns
| Status | Código | Causa | Fix |
|---|---|---|---|
| 400 | invalid_sku | SKU não existe no catálogo | Valide antes via GET /v2/products |
| 401 | token_expired | Token expirado | Renove via OAuth2 flow |
| 429 | rate_limited | Excedeu rate limit | Veja Rate Limits |
| 422 | insufficient_stock | Sem estoque | Reduza quantidade ou aguarde reposição |
Idempotência
Envie Idempotency-Key: {uuid} no header para garantir que retries não dupliquem pedidos.
Notas
- O
total_brlé calculado server-side. Não confie no valor que você calcula client-side. - Pedidos ficam
pending_paymentpor 30min. Após isso, cancelamento automático. - Este endpoint alimenta a tabela documentada em contexto de dados — não é OKF linkável diretamente, mas é a mesma entidade.
### `policies/rate-limits.md`
```markdown
---
type: Policy
title: Rate Limits
description: Limites de requisição por plano, headers de controle e comportamento em throttle.
tags: [api, rate-limit, policy, infra]
timestamp: 2026-06-01T09:00:00Z
owner: time-api
---
# Limites por plano
| Plano | Requests/min | Requests/dia | Burst |
|------------|--------------|--------------|-------|
| Free | 60 | 10.000 | 10 |
| Pro | 600 | 100.000 | 50 |
| Enterprise | 6.000 | 1.000.000 | 200 |
# Headers de resposta
Toda response inclui:
X-RateLimit-Limit: 600 X-RateLimit-Remaining: 584 X-RateLimit-Reset: 1718020800
- `X-RateLimit-Reset` é Unix timestamp de quando o bucket reseta.
# Comportamento quando throttled
Response `429 Too Many Requests`:
```json
{
"error": "rate_limited",
"message": "Rate limit exceeded. Retry after 12 seconds.",
"retry_after": 12
}Implemente exponential backoff. Não fique em loop martelando a API — clientes que fazem isso são bloqueados por 24h.
Endpoints com limites especiais
| Endpoint | Limite | Motivo |
|---|---|---|
POST /oauth/token | 10/min | Prevenir brute force |
POST /v2/orders | 30/min | Prevenir spam de pedidos |
GET /v2/reports/* | 5/min | Queries pesadas |
Boas práticas
- Cache agressivo em GETs que não mudam frequentemente (clientes, produtos).
- Batch quando possível —
POST /v2/orders/batchaceita até 50 pedidos por request. - Monitore o header
X-RateLimit-Remaininge diminua throughput antes de bater no limite. - Precisa de mais? Fale com vendas ou veja o plano Enterprise.
Links
- OAuth2 Flow — rate limit específico do endpoint de token.
- Criar Pedido — endpoint com limite especial de 30/min.
Citations
[1] IETF RFC 6585 — 429 Too Many Requests [2] API Design Guidelines — interno
---
## Padrões que você vai notar nos 3 exemplos
1. **`type` é semântico pro domínio.** Não tem lista fixa. Use `BigQuery Table`, `Alert`, `Runbook`, `API Endpoint`, `Policy`, `Metric` — o que fizer sentido pro seu time.
2. **Cross-links são generosos.** Se um conceito referencia outro, linka. É barato e torna o bundle navegável como wiki.
3. **`index.md` é mapa, não lixeira.** Uma frase por item, link direto, sem enrolação.
4. **Campos extras no frontmatter? Pode meter.** A spec aceita qualquer chave adicional. `owner`, `severity`, `sla_freshness`, `method`, `auth_scope` — bota o que o consumidor (humano ou agente) precisa pra filtrar e rotear.
5. **`# Citations` no final.** Links externos que validam o conteúdo. Agentes usam pra checar claims.
6. **Body estruturado.** Headings, tabelas, code blocks. Quanto mais structure, melhor a retrieval por agentes. Textão de prosa corrida = ruído.