API linting e análise estática
1) Porquê alinhar API
API - contrato entre equipes e integradores externos. Linting e análise estática:- impede alterações incompatíveis e implícitas;
- uniformizam estatais, erros, paginação, segurança;
- tornam as especificações de máquina-verificável e os lançamentos previsíveis;
- reduzem o custo com o revezamento e o tempo de troca.
Princípio: "Os contratos são verificados automaticamente; O PR sem a linting verde não vai morrer".
2) Objetos de linting
1. Contratos: OpenAPI/AsyncAPI/GraphQL SDL, Protobuf/Avro/JSON Schema.
2. Implementação: REST/gRPC, middleware, códigos de status/cabeçalhos.
3. Infraestrutura: cabeçalhos de segurança, limites, políticas de armazenamento.
4. Artefatos associados: exemplos (examples), coleções Postman, esquemas de erros.
3) Regras básicas para HTTP API (perfil recomendado)
3. 1 Notação e URL
snake _ case nos corpos JSON, kebab-case nos caminhos ou kebab-case uniforme/'/v1/... '.
Os recursos são múltiplos: '/v1/payments ', e os recursos aninhados são '/v1/wallets/Se.
Identificadores como path-params: '/v1/payments/< payment _ id a.' (tipo: string, formato: uuid).
3. 2 Métodos e estatais
'GET' - 200/206; 'POST' - 201 (+ 'Location'), conflitos - 409; validação - 422; os limites são 429 (+ 'Retry-After').
Não devolver 200 para erros. Solicitações condicional - 304 por 'If-None-Match'.
3. 3 Erros (formato único)
json
{ "code":"validation_error", "message":"amount must be ≥ 1", "trace_id":"...", "details":[{"field":"amount","reason":"min:1"}] }
Obrigatório: «código», «mensagem», «trace _ id»; local - através de 'Conteúdo-Language'.
3. 4 Paginação/filtros
Cursor-based: `page_size`, `page_token`, ответ: `next_page_token`.
Filtros e triagem - whitelists documentados em 'parameters'.
3. 5 Segurança
Esquema unificado de segurança: OAuth2/OIDC scopes ou mTLS; proibir 'http' (apenas 'https').
Não devolva títulos sensíveis, disfarce tokens em exemplos.
3. 6 Limitações e tamanhos
Limites de cabeçalho/corpo: 413/414/431; documente o valor máximo permitido.
4) Ferramentas e ecossistemas
4. 1 OpenAPI
Espectral (JSON/YAML lint), Redocly linter, oas-diff/openapi-diff (semantic diff), schemathesis/dreedd (verificações em curso).
4. 2 Protobuf/gRPC
buf (lint + breaking check), protolint, geradores SDK; gnostic para análise.
4. 3 GraphQL
graphql-schema-linter, graphql-inspector (breaking).
4. 4 Lentes de código e SAST
ESLint, golangci-lint, Detekt/Ktlint, Pylint/Flake8, Semgrep (modelos de API e segurança).
5) Exemplos de regras: Espectral/Redocly
5. 1 Espectral (exemplo de 'espectral. yaml`)
yaml extends: ["spectral:oas", "spectral:asyncapi"]
rules:
openapi-tags: off info-contact: error no-http: error path-kebab-case:
description: "Paths must be kebab-case"
given: "$.paths[]~"
severity: error then:
function: pattern functionOptions: { match: "^/(?:[a-z0-9]+(?--[a-z0-9]+)/?)+$" }
response-error-schema:
description: "Error responses must use standard schema"
given: "$.paths[][].responses[?(@property >= '400')]"
then:
field: "content.application/json.schema.$ref"
function: truthy id-as-uuid:
given: "$..parameters[?(@.name =~ /.id$/i)]"
then:
field: schema.format function: enumeration functionOptions: { values: ["uuid"] }
5. 2 Redocly (fragmento '.redocly. yaml`)
yaml apis:
main: openapi.yaml lint:
extends:
- recommended rules:
no-ambiguous-paths: error operation-2xx-only: off operation-success-response:
severity: error where:
subject: response filterInParentKeys: ["200","201","204"]
operation-security-defined: error no-plain-http: error
6) Protobuf/gRPC: perfil buf
6. 1 `buf. yaml`
yaml version: v2 modules:
- path: proto lint:
use:
- DEFAULT except:
- PACKAGE_VERSION_SUFFIX # используем v1 в package breaking:
use:
- WIRE_JSON deps: []
Recomendações:
- Não reutilizar números de campo; removíveis - em 'reserved'.
- Novos campos - 'optional' ou em default; não alterar tipos/semântica.
7) Diff semântico e alterações «quebra»
7. 1 HTTP
Exemplos de breaking:- alterar o tipo/obrigatoriedade do campo;
- remover status/rota/parâmetro;
- estreitamento do enum/intervalo;
- mudança de formato de id (uuid → string).
- adicionar campos opcionais;
- novos estados que não afetam o happy-path (por exemplo, documentado '422');
- extensão enum.
7. 2 gRPC/Protobuf
Remover o campo sem 'reserved '/mudar de número - breaking.
Alterar o tipo (int32 → string) - breaking.
Adicione uma nova marca como optional - normalmente safe.
8) Ligação entre contratos de linting e código
A coerência é garantida por dois fluxos:1. Contrato de código: geração de SDK/braços de servidor, exemplos negativos em testes.
2. Código → contrato: testes de especificação, verificação automática de estatais/cabeçalhos.
Ideias semgrep:- a proibição de 'return 200' com 'erro! = nil';
- obrigatório 'Idempotency-Key' nas rotas de pagamento write;
- camuflar os tokens nos logs.
9) CI/CD pipline (árbitro)
pre-commit: spectral lint, redocly lint
PR gate: openapi-diff (base..PR), buf breaking-check, graphql-inspector build: schemathesis smoke, unit/integration linters (ESLint/golangci-lint)
release: publish contracts (artifact/broker), sign & tag
O PR deve cair se:
- há breaking-diff;
- Regras básicas violadas (estatais/segurança/erros);
- não há exemplos ou descrições de parâmetros.
10) Diretório de regras (modelo para sua organização)
Identificadores e tipos
`_id` — `string`, `format: uuid`.
Campos de dinheiro - 'string '/' decimal' com scale; A moeda é ISO-4217.
Erros
Esquema unificado (consulte no parágrafo 3. 3), códigos: '400/401/403/404/409/422/429/5xx'.
Sempre 'trace _ id'; 'Retry-After' para 429/503.
Paginação
Apenas cursor; max 'page _ size' documentado.
Segurança
Todas as operações são 'security'. descrito como 'scopes'.
Não há links 'http:'; TLS 1. 2+.
Armazenamento em dinheiro/idempotação
Для GET — `ETag/Last-Modified`; para write - 'Idempotency-Key' (quando aplicável).
Documentação
'summary', 'descrição', exemplos de solicitações/respostas (validadas).
11) Exemplos de verificação automatizada
11. 1 Verificação de cabeçalhos de segurança obrigatórios (Spectral)
yaml security-headers:
given: "$.paths[][].responses['200'].headers"
then:
function: truthy
11. 2 openapi-diff (pseudo-passo CI)
openapi-diff --fail-on-incompatible base.yaml pr.yaml
11. 3 buf breaking-check
buf breaking --against '.git#branch=main'
12) Observabilidade da qualidade dos contratos
Métricas: RP com erros de linting, tempo de fixe, número de tentativas breaking, «dívidas» de acordo com as regras.
Dashboards: progressão da migração para um padrão unificado de erros, cobertura de exemplos, estabilidade de versões.
13) Antipattern
O Doc está separado do código → a secreção. Mantenha o contrato junto ao serviço e libere o artefacto versionizado.
O Linter é só manual. Preciso de um PR-gate rígido.
Exemplos aleatórios (não-deterministic) - flocos em verificações.
Não há exemplos negativos ou códigos de erro.
Reestabelecer esquema de erro para cada serviço.
Ignorar as verificações de Protobuf breaking (altera as marcas de formatação para olho).
14) Especificidades do iGaming/Finanças
Campos de dinheiro - escala fixa/arredondamento; a proibição do float.
Títulos obrigatórios de 'X-Tenant', 'X-Region' e 'traceparent'.
Canetas de pagamento write: Verificação da presença de 'Idempotency-Key', 'Retry-After' e correta 409/201 semânticos.
Webhooks PSP/KYC: HMAC/mTLS descritos em 'securitySchemes'; anti-replay ('X-Timestamp', janela).
Limitações regionais e localização de erros.
15) Folha de cheque pró-prontidão
- Espectral/Redocly perfis são personalizados e conectados em pré-commit e PR-gate.
- Um único padrão de erros e estatais - são registrados e verificados.
- openapi-diff/GraphQL Inspector/buf - bloqueiam as alterações breaking.
- Os exemplos de solicitação/resposta são válidos; paginação/filtros documentados.
- SecuritySchemes e scopes estão cheios; não há links http.
- Para Protobuf: 'reserved' em marcas remotas; novos campos - optional.
- Semgrep/lentes de código estão ativados; camuflar segredos nos logs.
- A CI publica artefatos de contratos e relatórios de linting.
- Playbook: Como agir com breaking-diffe (rollback, hotfix, notificações aos integradores).
16) TL; DR
Implemente linting automático de contratos (Spectral/Redocly, buf/GraphQL Inspector) e diff semântico, instale um único padrão de erros/status/paginação/segurança, conecta o PR-gate e a publicação dos contratos como artefatos. Qualquer «breaking-diff» é um «stop». Para dinheiro/pagamento - regras especiais (idempotidade, 'Retry-After', HMAC/mTLS).