Documentação/Catálogo v2
FEATURE ROLLOUT · DOCUMENTAÇÃO

Reconcilie features e prontidão como código

O catálogo v2 é o contrato remoto para features, tarefas, cenários, evidências declarativas, riscos, rollout, checklist e sign-offs. Ele valida o grafo completo antes da primeira escrita.

O que uma reconciliação controla

O destino — projeto, portfólio e repositório — precisa existir. Para cada feature enviada, o servidor faz upsert da feature e substitui suas dimensões, checklist, tarefas, vínculos, cenários, evidências de origem catalog, riscos, rollout e sign-offs.

replaceApplicationCatalog=trueTambém remove features do portfólio ausentes no payload
replaceApplicationCatalog=falsePreserva outras features, mas ainda reconcilia integralmente as features presentes
evidência catalogSubstituída pela declaração atual
evidência ciPreservada porque pertence a uma execução imutável
limite4 MB, 1–200 features por requisição
Faça review do diff

O PUT não é um PATCH. Gere o arquivo completo de cada feature incluída e revise remoções antes de enviar.

Exemplo completo de entrada

O exemplo abaixo é semanticamente válido: pesos somam 100, score calculado é 60, tarefas possuem contexto e todo cenário está mapeado.

json
{
  "version": 2,
  "project": "lb-pay",
  "application": "pix-automatico",
  "repository": "conta-facil/lb-pay",
  "replaceApplicationCatalog": false,
  "features": [
    {
      "id": "LBP-PIX-001",
      "useCase": "Pagamento recorrente",
      "name": "Autorização de recorrência",
      "description": "Permite autorizar e revogar pagamentos recorrentes.",
      "status": "EM PROGRESSO",
      "score": 60,
      "deployWindow": "2026-08-14T22:00:00-03:00",
      "dimensions": [
        {
          "label": "Implementação",
          "score": 60,
          "position": 1
        },
        {
          "label": "Qualidade",
          "score": 50,
          "position": 2
        }
      ],
      "checklist": [
        {
          "id": "CHK-PIX-001",
          "label": "Runbook revisado por Operações",
          "meta": "Responsável: SRE",
          "blocking": true,
          "completed": false,
          "position": 1
        }
      ],
      "tasks": [
        {
          "id": "TSK-PIX-001",
          "title": "Criar autorização de recorrência",
          "description": "Implementar a criação da autorização pelo recebedor.",
          "implementationDetails": "Persistir consentimento, limite e frequência.",
          "acceptanceCriteria": [
            "Retornar 201",
            "Registrar auditoria"
          ],
          "scenarioRefs": [
            "CT-PIX-001"
          ],
          "testRefs": [
            "e2e/pix-recorrente.spec.ts"
          ],
          "readinessWeight": 60,
          "progress": 100,
          "remainingWork": "",
          "area": "Backend",
          "status": "CONCLUÍDA",
          "tests": "2/2",
          "updatedLabel": "commit a4f21c9",
          "position": 1
        },
        {
          "id": "TSK-PIX-002",
          "title": "Revogar autorização",
          "description": "Impedir novas cobranças após a revogação.",
          "implementationDetails": "Invalidar autorização e publicar evento.",
          "acceptanceCriteria": [
            "Não gerar cobranças futuras",
            "Operação idempotente"
          ],
          "scenarioRefs": [
            "CT-PIX-002"
          ],
          "testRefs": [],
          "readinessWeight": 40,
          "progress": 0,
          "remainingWork": "Implementar endpoint, evento e testes E2E.",
          "area": "Backend",
          "status": "NÃO INICIADA",
          "tests": "0/2",
          "updatedLabel": "catálogo",
          "position": 2
        }
      ],
      "scenarios": [
        {
          "id": "CT-PIX-001",
          "title": "Criar autorização válida",
          "result": "PASS",
          "meta": "E2E · homologação",
          "position": 1
        },
        {
          "id": "CT-PIX-002",
          "title": "Revogar autorização ativa",
          "result": "PEND",
          "meta": "Aguardando implementação",
          "position": 2
        }
      ],
      "evidences": [
        {
          "kind": "JSON",
          "title": "Resposta da criação da autorização",
          "description": "Comprova o contrato HTTP e o identificador persistido.",
          "doubleChecked": true,
          "scenarioRef": "CT-PIX-001",
          "meta": "homolog · a4f21c9",
          "payloadType": "text",
          "contentType": "application/json",
          "content": "{\"status\":\"ATIVA\",\"authorizationId\":\"auth_123\"}",
          "encoding": "utf8",
          "sourcePath": "artifacts/authorization.json",
          "position": 1
        }
      ],
      "risks": [
        {
          "title": "Cobrança após revogação",
          "severity": "ALTO",
          "mitigation": "Bloquear no ledger e monitorar eventos órfãos.",
          "meta": "owner: time Pix",
          "position": 1
        }
      ],
      "rollout": [
        {
          "phase": "Canário 5%",
          "scheduledFor": "2026-08-14T22:00:00-03:00",
          "active": false,
          "environment": "production",
          "status": "planned",
          "trafficPercentage": 5,
          "gateStatus": "pending",
          "description": "Recebedores internos por 24 horas.",
          "rollbackPlan": "Desativar flag pix_recurring_authorization.",
          "position": 1
        }
      ],
      "signoffs": [
        {
          "id": "SIGN-PIX-OPS",
          "area": "Operações",
          "status": "PENDENTE",
          "owner": "sre@empresa.com",
          "note": "Aguardando runbook.",
          "decidedAt": null,
          "position": 1
        }
      ]
    }
  ]
}

Envie o arquivo

A chamada exige catalog:write, confiança trusted e vínculo com o mesmo workspace/aplicação/repositório. Uma chave criada manualmente no painel possui apenas test-runs:write; para catálogo remoto use o token OIDC curto do GitHub.

shell
curl --fail-with-body --request PUT   "$FEATURE_ROLLOUT_URL/api/v2/catalog"   --header "Authorization: Bearer $FEATURE_ROLLOUT_TOKEN"   --header 'Content-Type: application/json'   --data-binary '@feature-rollout.catalog.json'

Interprete a saída

As contagens são do payload reconciliado e podem ser usadas como verificação do pipeline. applicationId é o UUID necessário para APIs de documentação.

json
{
  "kind": "synced",
  "applicationId": "2cbb9638-67d5-4c23-90ce-c84fa1f45418",
  "featureCount": 1,
  "taskCount": 2,
  "scenarioCount": 2,
  "riskCount": 1,
  "rolloutCount": 1
}

Corrija violações antes de gravar

DUPLICATE_IDFeature, tarefa ou cenário repetido
READINESS_UNMAPPEDPesos das tarefas não somam 100
SCORE_MISMATCHScore não corresponde a peso × progresso
TASK_CONTEXT_MISSINGDescrição, implementação ou aceite ausente
TASK_PROGRESS_INCONSISTENTStatus conclusivo e progresso discordam
TASK_REMAINING_WORK_MISSINGTarefa incompleta sem remainingWork
SCENARIO_REFERENCE_NOT_FOUNDTarefa aponta para cenário inexistente
SCENARIO_UNMAPPEDCenário não pertence a nenhuma tarefa
READY_WITH_OPEN_GATEScore 100 com checklist bloqueante aberto
json
{
  "error": "Sync recusado: o catálogo não mapeia 100% da prontidão.",
  "code": "CATALOG_COMPLETENESS_FAILED",
  "violations": [{
    "code": "READINESS_UNMAPPED",
    "featureId": "LBP-PIX-001",
    "missingPoints": 40,
    "message": "40 ponto(s) de prontidão não estão mapeados; os pesos somam 60/100."
  }]
}

Obtenha o token remoto por GitHub OIDC

A política OIDC do repositório valida issuer, audience, repositório, evento, ref e workflow. O token retornado expira em 10 minutos e recebe test-runs:write, catalog:write e rollout:write. Pull requests recebem confiança untrusted e não podem reconciliar catálogo ou avaliar gate.

yaml
permissions:
  contents: read
  id-token: write

steps:
  - name: Obter identidade OIDC do GitHub
    id: oidc
    shell: bash
    run: |
      oidc_jwt="$(curl --fail --silent         -H "Authorization: bearer $ACTIONS_ID_TOKEN_REQUEST_TOKEN"         "$ACTIONS_ID_TOKEN_REQUEST_URL&audience=https://feature-rollout.dev"         | jq -r .value)"
      response="$(curl --fail-with-body --request POST         https://feature-rollout.dev/api/v2/auth/github         -H "Authorization: Bearer $oidc_jwt")"
      echo "token=$(jq -r .token <<<"$response")" >> "$GITHUB_OUTPUT"

  - name: Reconciliar catálogo
    env:
      FEATURE_ROLLOUT_TOKEN: ${{ steps.oidc.outputs.token }}
    run: |
      curl --fail-with-body --request PUT         https://feature-rollout.dev/api/v2/catalog         -H "Authorization: Bearer $FEATURE_ROLLOUT_TOKEN"         -H "Content-Type: application/json"         --data-binary @feature-rollout.catalog.json

Pipeline recomendado

01Validar JSON e regras de completude no pull request
02Obter token OIDC em evento/ref confiável
03PUT /api/v2/catalog
04Executar testes contra o mesmo commit
05POST /api/v2/test-runs com X-Run-ID idempotente
06POST /api/v2/gates/evaluate
07Promover somente com HTTP 200 e passed=true