Saltar al contenido
BeryX
Volver a las respuestas para RFP

Documentación de BeryX

Este documento técnico está disponible en portugués.

Versionamento e depreciação da API v1

Para quem integra com a API pública do BeryX: o que é estável, o que conta como quebra e como avisamos antes de mudar. Publicada no site em /datavault/docs/versionamento-api; o resumo é a secção «Estabilidade» do portal (/datavault/developers#estabilidade, export em docs/api/public/api-stability.json, gerado por backend/scripts/api_portal.py — os prazos vêm do código). English version below.

1. O que está coberto

  • O contrato é o spec público do portal (/datavault/developers/openapi.json no site; cópia versionada em public/openapi.json): as operações de /api/v1 que um token de API dvk_* consegue chamar — os GET e as escritas explicitamente abertas a tokens (gate RAG, disparo de scans, runs de orquestradores, data-diff e decisão de confiança em lote) —, com os parâmetros, os schemas de pedido e de resposta, os códigos de estado e os headers que lá estão documentados.
  • O que não está no portal não tem garantias e pode mudar sem aviso: os endpoints que só a app web usa (sessão de utilizador), a administração da conta, dos tokens e da faturação, a consola BeryxTech, o chat e os streams da UI, e o /openapi.json completo que a app serve fora de produção.
  • Texto não é contrato: descrições, resumos, exemplos e as mensagens legíveis dos erros (message, detail em texto) podem mudar em qualquer versão. O que é contrato é o code.

2. Versões

  • A API tem semver próprio, separado da versão do produto; a regra (minor = adições compatíveis, major = quebra anunciada) e a razão de ser separada estão em PRODUTO.md §8 — esta política aplica-a, não a redefine. A versão em vigor é a entrada mais recente de changelog.json e sai em GET /api/v1/version e GET /api/v1/health (api_version) e no info.version do spec.
  • Patch (X.Y.z): correções que repõem o comportamento documentado.
  • Minor (X.y.0): só adições (§3).
  • Major (X.0.0): quebras (§4), sempre depois de uma depreciação (§5).
  • O prefixo /api/v1 não acompanha o semver: uma major pode retirar o que foi depreciado sem mudar de prefixo. Se um dia existir /api/v2, o /api/v1 continua a responder pelo menos durante a janela de depreciação.

3. Mudanças compatíveis (minor)

Uma versão minor só acrescenta:

  • operações novas, parâmetros opcionais novos e headers de resposta novos;
  • campos novos nas respostas — o teu cliente deve ignorar campos que não conhece (o SDK Python já o faz);
  • valores novos em enums de resposta — trata um valor desconhecido como «outro» em vez de falhar;
  • code novos (razões, bloqueadores, erros).

code estáveis. Os code das razões da decisão de confiança (GET /datasets/{dataset_id}/trust-decision), dos bloqueadores e avisos da readiness (GET /domains/{domain_id}/readiness) e dos erros com detail = {code, message} são estáveis: o mesmo code quer sempre dizer o mesmo; só o texto pode mudar.

Envelopes com schema_version — os factos de confiança (trust-facts.md) e os feeds de BI: campos novos só no fim; o schema_version só sobe numa quebra, e essa quebra segue esta política.

4. O que é uma quebra (major)

  • remover ou renomear uma operação, um parâmetro, um campo ou um valor de enum;
  • mudar o tipo ou o formato de um campo ou parâmetro (ex.: string → integer, data → data-hora);
  • tornar obrigatório um parâmetro ou campo de pedido que era opcional, ou apertar a validação de modo que um pedido antes aceite passe a ser recusado (limites menores, padrões mais estritos);
  • mudar o significado de um campo, de um code ou do estado HTTP de uma situação (ex.: 404 → 403);
  • baixar o máximo de limit ou mudar a ordenação por omissão de uma listagem;
  • passar a exigir autenticação numa operação pública, ou retirar a um token uma operação que ele podia chamar.

Uma quebra só sai de duas formas: numa versão de caminho nova (/api/v2, §2), com /api/v1 sem mudanças, ou numa versão major depois do processo de depreciação (§5).

Exceção de segurança. Se manter um comportamento expõe dados ou permite abuso, podemos mudá-lo sem janela. Fica no changelog com o tipo security e é comunicado aos admins dos workspaces com tokens de API ativos.

O que o CI verifica. api_portal.py build --check falha se o export do portal não corresponder às rotas. api_portal.py guard compara o contrato com o da base e classifica cada diferença em compatível ou quebra (backend/app/domain/api_contract/diff.py, cartão #367): remoções, tipos e formatos mudados, campos de resposta que podem vir null, pedidos que passam a obrigatórios, valores de enum removidos, validação mais estrita, valores por omissão mudados, códigos de estado removidos e autenticação nova. Falha se o contrato mudar sem uma versão nova no topo do changelog, e se uma quebra não vier numa major (ou com uma entrada security), listada em docs/api/BREAKING.md e, num PR, com o label api-breaking. Uma mudança de significado (de um campo, de um code ou de um estado HTTP) não se vê no spec e fica para a revisão.

5. Depreciação

  1. Anúncio no changelog — entrada do tipo deprecated numa versão minor, com o que é depreciado, a alternativa e a data de fim.

  2. Anúncio nas respostas — a operação passa a deprecated: true no spec e responde com (helper deprecate() em app/api/deps.py):

    • Deprecation: @<segundos desde a época> (RFC 9745) — desde quando está depreciada;
    • Sunset: <data HTTP> (RFC 8594) — a partir de quando deixa de responder;
    • Link: <url da nota de migração>; rel="deprecation"; type="text/html" (RFC 9745).
    Deprecation: @1790812800
    Sunset: Thu, 01 Apr 2027 00:00:00 GMT
    Link: <https://praxis.lbostuff.tech/datavault/developers#estabilidade>; rel="deprecation"; type="text/html"
    

    O CORS expõe os três headers, por isso um cliente no browser também os vê.

  3. Janela mínima de 180 dias entre o anúncio e o Sunset (o deprecate() recusa uma janela menor). Durante a janela a operação continua a responder como antes.

  4. Comunicação direta aos admins dos workspaces com tokens de API ativos, no anúncio e antes do fim.

  5. Fim — no Sunset, a remoção sai numa major, com uma entrada removed no changelog.

6. SDK

O SDK Python (beryx-sdk, sdk/README.md) tem versões e tags próprias (sdk-v*). Suportamos as duas minor mais recentes (N e N-1): recebem correções e acompanham a API. Versões mais antigas continuam a funcionar enquanto a API não tiver quebras — os tipos do SDK toleram campos novos —, mas sem correções. Uma depreciação na API que afete o SDK sai numa minor do SDK dentro da janela de 180 dias.

7. Rate limits e quotas

  • Cada token tem um limite de pedidos próprio, além do limite por IP. Os valores em vigor vêm nas respostas (X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset; os endpoints de saúde estão isentos); acima do limite a API responde 429 com Retry-After (segundos). Os valores são configuração do serviço (app/api/ratelimit.py), não contrato fixo.
  • As quotas do plano (fontes, datasets, scans e relatórios por mês) estão na página de preços e no catálogo de planos (app/domain/billing/plans.py); acima de uma quota a API responde 402 com {detail, plan, limit}.
  • Os limites e as quotas podem mudar: um aumento aplica-se logo; uma redução é anunciada com pelo menos 30 dias de antecedência (changelog e comunicação aos admins), exceto medidas contra abuso, que podem ser imediatas.

8. Reportar um problema

  • Uma resposta que contradiga o contrato é um bug nosso. Escreve para suporte@praxis.lbostuff.tech (assunto «API») com o método e o caminho, o estado HTTP, a hora (UTC), o X-Request-ID da resposta (nos erros vem também em request_id) e a resposta de GET /api/v1/version (version, build_sha, api_version). Nunca envies o token; se o expuseste, revoga-o em Definições → Tokens de API.
  • Corrigimos o comportamento para cumprir o contrato (patch, tipo fixed); se o erro estava no contrato, a correção segue esta política.
  • Vulnerabilidades: o contacto em /.well-known/security.txt (SEGURANCA.md).

Para quem mantém a API

  1. Mudaste algo no spec público? python scripts/api_portal.py diff (compara com o export versionado e classifica cada diferença em breaking ou compatible) → entrada nova no topo de changelog.json → API_VERSION em backend/app/version.py → make openapi na raiz (o mesmo que python scripts/api_portal.py build, regenera docs/api/public/) → commit. No CI correm build --check e guard. Uma quebra pede ainda a versão major, a secção dessa versão em docs/api/BREAKING.md com cada rota partida entre crases e o label api-breaking no PR.
  2. Depreciar: deprecated=True na rota, deprecate(response, sunset, link, since=…) no endpoint e a entrada deprecated no changelog.
  3. O praxis-site copia docs/api/public/ para content/developers/ e este documento para content/docs/api/ (pnpm sync:docs). O pnpm build do site corre scripts/check_developers.mjs: valida a cópia (versão do spec = topo do changelog, secções pt/en, política publicada com os mesmos prazos) e, com PRAXIS_PRODUTO_DIR, recusa-a se não for igual, byte a byte, a docs/api/public/.
  4. Uma operação pública nova responde com um modelo *Out (response_model=), nunca com um -> dict sem schema: o guard não vê dentro de uma resposta sem schema, por isso não dá por um campo removido. backend/tests/test_api_untyped_ratchet.py chumba a operação nova. As que ainda não têm schema estão em backend/tests/api_untyped_allowlist.json, e essa lista só encolhe. O modelo declara todas as chaves que o dict devolve, porque o response_model corta as que não conhece.

English

For those integrating with the BeryX public API: what is stable, what counts as a breaking change and how we warn before changing. The summary of this policy is the «Stability» section of the /datavault/developers portal (/datavault/developers#estabilidade).

1. What is covered

  • The contract is the portal's public spec (/datavault/developers/openapi.json): the /api/v1 operations an API token dvk_* can call — the GETs and the writes explicitly open to tokens (RAG gate, triggering scans, orchestrator runs, data-diff and batch trust decisions) — with the parameters, request and response schemas, status codes and headers documented there.
  • Whatever is not in the portal has no guarantees and may change without notice: endpoints only the web app uses, account, token and billing administration, the BeryxTech console, chat and UI streams, and the full /openapi.json served outside production.
  • Text is not contract: descriptions, summaries, examples and human-readable error messages may change in any version. The code is the contract.

2. Versions

  • The API has its own semver, separate from the product version (rule and rationale in PRODUTO.md §8: minor = compatible additions, major = announced breaking change). The version in force is the latest entry of the API changelog and is returned by GET /api/v1/version, GET /api/v1/health (api_version) and the spec's info.version.
  • Patch: fixes that restore documented behaviour. Minor: additions only. Major: breaking changes, always after a deprecation.
  • The /api/v1 prefix does not follow semver: a major may drop what was deprecated without changing prefix. If an /api/v2 ever exists, /api/v1 keeps responding at least during the deprecation window.

3. Compatible changes (minor)

New operations, optional parameters, response headers, response fields (ignore fields you do not know), enum values (handle unknown values) and new codes. The codes of trust-decision reasons, readiness blockers and warnings, and errors with detail = {code, message} are stable. Envelopes with schema_version (trust facts, BI feeds) add fields only at the end and only bump schema_version in a breaking change.

4. What a breaking change is (major)

Removing or renaming an operation, parameter, field or enum value; changing a type or format; making something optional required or rejecting a request that used to be accepted; changing the meaning of a field, a code or an HTTP status; lowering the maximum limit or changing a listing's default order; requiring authentication on a public operation or taking an operation away from tokens. Breaking changes only ship in one of two ways: under a new path version (/api/v2), leaving /api/v1 unchanged, or in a major after deprecation. Security exception: if keeping a behaviour exposes data or enables abuse we may change it without a window, logged with type security. CI compares the contract with the base and classifies every difference as compatible or breaking. It fails when the public contract changes without a new changelog version, and when a breaking change is not in a major (or a security entry), listed in docs/api/BREAKING.md and, on a pull request, labelled api-breaking. A change of meaning does not show in the spec and is left to review.

5. Deprecation

  1. A deprecated entry in the changelog (minor version) with what is deprecated, the alternative and the end date.
  2. The operation is marked deprecated: true in the spec and responds with Deprecation (RFC 9745), Sunset (RFC 8594) and Link with rel="deprecation" pointing to the migration note. CORS exposes the three headers.
  3. At least 180 days between the announcement and Sunset; the operation keeps working during the window.
  4. Direct communication to the admins of workspaces with active API tokens, at the announcement and before the end.
  5. At Sunset, the removal ships in a major with a removed changelog entry.

6. SDK

The Python SDK (beryx-sdk) has its own versions (sdk-v* tags). We support the two most recent minors (N and N-1): they get fixes and track the API. Older versions keep working while the API has no breaking changes, but get no fixes.

7. Rate limits and quotas

Per-token and per-IP request limits are reported in X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset; above the limit the API responds 429 with Retry-After. Plan quotas are on the pricing page; above a quota the API responds 402. Limits and quotas may change: an increase applies at once; a reduction is announced at least 30 days in advance, except anti-abuse measures.

8. Reporting a problem

Write to suporte@praxis.lbostuff.tech (subject «API») with the method and path, HTTP status, time (UTC), the X-Request-ID of the response (errors also carry it in request_id) and the response of GET /api/v1/version — never the token. Vulnerabilities: the contact in /.well-known/security.txt.