{
  "openapi": "3.1.0",
  "jsonSchemaDialect": "https://json-schema.org/draft/2020-12/schema",
  "info": {
    "title": "BORA Transport API",
    "version": "1.0.0-draft.2",
    "summary": "Autenticação pela palma para catracas de transporte (BORA for Transport).",
    "contact": {
      "name": "BORA (Unflat Studio)",
      "url": "https://bora.id/transport/documentation",
      "email": "oi@unflat.studio"
    },
    "x-bora-test-keys": {
      "description": "Chaves PÚBLICAS de teste que assinaram os exemplos deste documento (seeds = sha256 de rótulos fixos em bora_transport/contract/README.md). Nunca valem em produção.",
      "device_verdict": {
        "kid": "300290aeb182952c1337b227be5fe728",
        "pub_b64": "0mZcYF+l54oAZ/8dAsbliiXUbumVlpIjXGc8EDb6qO0="
      },
      "device_http": {
        "kid": "d1ab5521bfd29c9326bcc0912595d2d2",
        "pub_b64": "CLzpCHai01JSj//uXz9cRosfTUlCtBFwvoOQGcrV+c8="
      },
      "dbd_sign": {
        "kid": "4678808aef484c079515f89dbe4e1ef3",
        "pub_b64": "/EorC2SHripynSbtWpO3y0kvagTLyjyo+9rKeg/+YGs="
      },
      "backend": {
        "kid": "abb9ff726ba8ffb31638d59e7fcfb820",
        "pub_b64": "4SXx18WKcMv5f/KQIYBA/EbMcJ06DFPAXSTV6JaDcak="
      }
    },
    "description": "Recorte da prova de conceito da API BORA: só as operações marcadas com `x-bora-poc`. Documentação: https://docs.bora.id/api/ (tudo em Markdown em https://docs.bora.id/llms-full.txt).\n\n## Autenticação\n\nToda rota de parceiro usa `Authorization: Bearer <API key>`, no formato `bora_<live|test>_<key_id>_<secret>`. Cada rota diz o escopo que precisa. As rotas do aparelho não fazem parte deste recorte.\n\n## Como o produto funciona\n\nO aparelho BORA ACCESS (Orange Pi + módulo Deptrum) fica na catraca, reconhece a pessoa offline na galeria\nlocal e manda pelo cabo USB um veredito assinado (Ed25519) ao DBD da operadora. O DBD decide a permissão\n(saldo, bloqueio, categoria) e aciona a catraca. A nuvem BORA guarda os cadastros, atualiza a galeria dos\naparelhos e guarda o log de vereditos para conciliação. O cabo usa o BORA-LINK/1, descrito em\n`bora_link_v1.schema.json`; esta API não passa pelo cabo.\n\n## Identificadores\n\n- `subject_id`: UUID v4 aleatório gerado pela BORA. Nunca derivado do CPF.\n- `external_ref`: o ID da conta do cliente no sistema DELE (matrícula, número da conta). É a chave que o\n  parceiro usa para achar a pessoa. Único por tenant. A API recusa um `external_ref` que seja um CPF válido\n  (`422 external_ref_looks_like_cpf`).\n- `cpf`: opcional, só para KYC e deduplicação. Entra só no corpo do `POST /v1/subjects`, nunca volta em\n  resposta, nunca vai para log nem URL. Guardado como HMAC-SHA256 com chave por tenant (dedup) e cifrado\n  com AES-256-GCM sob chave de KMS (KYC).\n- `subject_ref`: pseudônimo `HMAC-SHA256(k_tenant, subject_id)[:16]` em 32 hex. É o que viaja no veredito\n  do cabo. O parceiro pode guardar o mapa `subject_ref -> conta` no BDOS para o DBD resolver offline.\n  Continua sendo dado pessoal pela LGPD.\n- `onboard_ref`: token opaco opcional do operador que viaja no veredito de `accept` (nome herdado do POC\n  ONBOARD, mantido para casar com o BORA-LINK/1).\n- `device_id`: ASCII `[A-Za-z0-9._:-]{1,64}`, definido no provisionamento. `self`, `register` e `attest`\n  são reservados.\n- `verdict_id`: o próprio `verdict_ref` do BORA-LINK/1 (`hex(sha256(canonical(SignedVerdict)))[:32]`).\n\n## Tempo\n\nSuperfície do parceiro: RFC 3339 em UTC com milissegundos (`2026-10-01T10:20:00.840Z`). Superfície do\naparelho e objetos assinados: epoch ms inteiro (`*_ms`), como no cabo.\n\n## Idempotência\n\nTodo `POST` exige `Idempotency-Key` (1 a 255 caracteres ASCII imprimíveis; recomendado UUID v4). A chave vale\npor 24 h, no escopo (credencial, método, rota). Mesma chave e mesmo corpo devolvem a resposta gravada com\n`Idempotent-Replayed: true`; mesma chave com corpo diferente dá `422 idempotency_key_mismatch`; a primeira\nainda em andamento dá `409 idempotency_in_progress` (se ela morreu no meio, depois de 60 s a próxima\nrequisição com a mesma chave assume e executa de novo); sem a chave, `428 idempotency_key_required`.\nRespostas 5xx não são gravadas (o cliente pode repetir). `DELETE /v1/subjects/{subject_id}` aceita a chave\ncomo opcional. A BORA guarda só um HMAC do corpo e a resposta cifrada, e apaga as respostas gravadas que\nfalam de uma pessoa quando ela é apagada.\n\n## Paginação\n\nPor cursor opaco (até 512 caracteres): `?limit=` (1 a 200, padrão 50) e `?cursor=` com o `next_cursor` da\npágina anterior, repetindo os mesmos filtros (o cursor leva só um hash deles).\nResposta `{data, has_more, next_cursor}`. Cursor inválido = `400 invalid_cursor`; cursor velho demais\n(fora da retenção) = `410 cursor_expired`. Nunca por offset nem por timestamp.\n\n## Erros\n\nRFC 9457 (`application/problem+json`) com `code` estável (tabela em `components.schemas.ReasonCode`). O\n`detail` é para humanos e pode mudar; o `code` não. Nenhum erro ecoa valor recebido. Recurso de outro\ntenant responde igual a recurso inexistente (`404`).\n\n## Versionamento\n\nVersão maior no caminho (`/v1`). Dentro do v1 só entram mudanças aditivas: campo opcional novo, rota nova,\nvalor novo em enum marcado `x-extensible-enum`. O cliente ignora campo desconhecido. Quebra de contrato vai\npara `/v2` com pelo menos 12 meses de convivência, anunciada por `Deprecation` (RFC 9745) e `Sunset`\n(RFC 8594). O `info.version` versiona este documento; o BORA-LINK/1 tem versão própria (`v` no envelope).\n\n## Limites de taxa (proposta, ajustar com carga real)\n\n| quem | limite |\n|---|---|\n| API key, leitura | 100 req/s, rajada 200 |\n| API key, escrita | 20 req/s, rajada 40 |\n| `POST /v1/enrollment-sessions` | 60 por minuto por tenant |\n| aparelho | 10 req/s, rajada 20; `GET /v1/gallery/snapshot` sem cursor conta 5 |\n| long-poll de galeria | 1 por aparelho (o novo encerra o anterior, que responde na hora) |\n| `POST /v1/enrollment-sessions/redeem` | 10 por 10 minutos por aparelho e 60 por minuto por tenant |\n| registro e atestação | 10 por minuto por token de provisionamento |\n\nRespostas trazem `RateLimit-Limit`, `RateLimit-Remaining` e `RateLimit-Reset`; o `429` traz `Retry-After`.\n\n## LGPD\n\nNenhuma rota recebe ou devolve imagem da mão. O único dado biométrico na API é o vetor 512-d, e só na\nsuperfície do aparelho (totem sobe no cadastro, nuvem desce na galeria), sempre dentro de TLS. CPF só entra,\nnunca sai. `DELETE /v1/subjects/{subject_id}` apaga com recibo assinado. O que passa da retenção (eventos 30\ndias, Idempotency-Key 24 h, deltas 7 dias, vereditos 13 meses) é apagado de fato, não só escondido.\n"
  },
  "externalDocs": {
    "description": "Referência da API BORA",
    "url": "https://docs.bora.id/api/"
  },
  "servers": [
    {
      "url": "https://api.bora.id",
      "description": "Produção (proposta)"
    },
    {
      "url": "https://sandbox.api.bora.id",
      "description": "Sandbox, só com API key bora_test_ (proposta)"
    },
    {
      "url": "http://127.0.0.1:8710",
      "description": "Servidor de referência local (FastAPI)"
    }
  ],
  "tags": [
    {
      "name": "Health",
      "description": "Estado do serviço. Público."
    },
    {
      "name": "Keys",
      "description": "Chaves públicas da BORA para verificar recibos, cabeças de galeria e webhooks. Público."
    },
    {
      "name": "Subjects",
      "description": "Pessoas cadastradas, identificadas pelo external_ref do parceiro."
    },
    {
      "name": "Consents",
      "description": "Consentimento por finalidade (LGPD art. 11)."
    },
    {
      "name": "Enrollment sessions",
      "description": "Abre um cadastro de palma num totem ou BORA ACCESS e acompanha o resultado."
    },
    {
      "name": "Devices",
      "description": "Aparelhos do tenant (visão do parceiro)."
    },
    {
      "name": "Verdicts",
      "description": "Log de passagens com prova assinada, para conciliar com o BDOS."
    },
    {
      "name": "Mail",
      "description": "Carteiro. Registros selados entre a BORA e o aparelho, levados pelo BDOS e pelo DBD sem abrir."
    }
  ],
  "x-tagGroups": [
    {
      "name": "Público",
      "tags": [
        "Health",
        "Keys"
      ]
    },
    {
      "name": "Parceiro",
      "tags": [
        "Subjects",
        "Consents",
        "Enrollment sessions",
        "Devices",
        "Mail",
        "Verdicts"
      ]
    }
  ],
  "security": [],
  "paths": {
    "/v1/health": {
      "get": {
        "tags": [
          "Health"
        ],
        "operationId": "getHealth",
        "x-bora-poc": true,
        "summary": "Estado do serviço",
        "security": [],
        "responses": {
          "200": {
            "description": "Serviço no ar.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "Bora-Server-Time": {
                "$ref": "#/components/headers/Bora-Server-Time"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Health"
                },
                "examples": {
                  "ok": {
                    "value": {
                      "status": "ok",
                      "api_version": "v1",
                      "contract_version": "1.0.0-draft.1",
                      "server_time": "2026-10-01T10:20:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        }
      }
    },
    "/v1/keys": {
      "get": {
        "tags": [
          "Keys"
        ],
        "operationId": "listSigningKeys",
        "x-bora-poc": true,
        "summary": "Chaves públicas de assinatura da BORA",
        "description": "Chaves Ed25519 que a BORA usa para assinar recibos de apagamento, cabeças e deltas de galeria, status de\naparelho e webhooks. O cliente deve fixar (pin) estas chaves por `kid` e aceitar rotação só quando a nova\nchave aparecer aqui antes do `not_before`.\n",
        "security": [],
        "responses": {
          "200": {
            "description": "Lista de chaves.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SigningKeyList"
                },
                "examples": {
                  "keys": {
                    "value": {
                      "keys": [
                        {
                          "kid": "abb9ff726ba8ffb31638d59e7fcfb820",
                          "alg": "ed25519",
                          "use": [
                            "erasure_receipt",
                            "gallery",
                            "device_status",
                            "webhook"
                          ],
                          "pub_b64": "4SXx18WKcMv5f/KQIYBA/EbMcJ06DFPAXSTV6JaDcak=",
                          "not_before": "2026-09-01T00:00:00.000Z",
                          "not_after": null
                        }
                      ]
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/subjects": {
      "get": {
        "tags": [
          "Subjects"
        ],
        "operationId": "listSubjects",
        "x-bora-poc": true,
        "summary": "Lista pessoas (ou busca pelo external_ref)",
        "description": "Com `external_ref`, devolve 0 ou 1 item. Não existe busca por CPF (CPF nunca vai em URL).",
        "security": [
          {
            "PartnerApiKey": [
              "subjects:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "external_ref",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/ExternalRef"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/SubjectStatus"
            }
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "Página de pessoas.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SubjectPage"
                },
                "examples": {
                  "busca": {
                    "value": {
                      "data": [
                        {
                          "subject_id": "3f6c2a9e-8b1d-4e7a-9c3f-5d2e1a0b7c64",
                          "external_ref": "MBH-000482913",
                          "subject_ref": "2a16ce69bc964deda2b740bfe43edf4b",
                          "onboard_ref": "obr-7Q2m9X",
                          "status": "active",
                          "block": null,
                          "enrollment": {
                            "hands": [
                              "L",
                              "R"
                            ],
                            "model_id": "deptrum-onnx-2026.09",
                            "enrolled_at": "2026-10-01T10:02:41.120Z"
                          },
                          "consents": [
                            {
                              "purpose": "enrollment",
                              "status": "granted"
                            },
                            {
                              "purpose": "identification",
                              "status": "granted"
                            }
                          ],
                          "kyc": {
                            "cpf_on_file": true
                          },
                          "gallery_seq": 15873,
                          "created_at": "2026-10-01T09:55:00.000Z",
                          "updated_at": "2026-10-01T10:02:41.120Z",
                          "livemode": true
                        }
                      ],
                      "has_more": false,
                      "next_cursor": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "410": {
            "$ref": "#/components/responses/Gone"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "post": {
        "tags": [
          "Subjects"
        ],
        "operationId": "createSubject",
        "x-bora-poc": true,
        "summary": "Cria uma pessoa pelo external_ref",
        "description": "Cria a pessoa sem biometria (status `pending_enrollment`). O cadastro da palma vem depois por\n`POST /v1/enrollment-sessions`. `cpf` é opcional e só serve para KYC e deduplicação dentro do tenant: já\nexistir outra pessoa ativa com o mesmo CPF dá `409 cpf_conflict` (sem revelar qual).\n",
        "security": [
          {
            "PartnerApiKey": [
              "subjects:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/ClientRequestId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubjectCreate"
              },
              "examples": {
                "minimo": {
                  "summary": "Só o ID da conta do cliente",
                  "value": {
                    "external_ref": "MBH-000482913"
                  }
                },
                "com_cpf": {
                  "summary": "Com CPF para KYC e token opaco do operador",
                  "value": {
                    "external_ref": "MBH-000482913",
                    "cpf": "52998224725",
                    "onboard_ref": "obr-7Q2m9X"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Pessoa criada.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Subject"
                },
                "examples": {
                  "criado": {
                    "$ref": "#/components/examples/SubjectPending"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "415": {
            "$ref": "#/components/responses/UnsupportedMediaType"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "428": {
            "$ref": "#/components/responses/IdempotencyKeyRequired"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/subjects/{subject_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/SubjectId"
        }
      ],
      "get": {
        "tags": [
          "Subjects"
        ],
        "operationId": "getSubject",
        "x-bora-poc": true,
        "summary": "Consulta uma pessoa",
        "security": [
          {
            "PartnerApiKey": [
              "subjects:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "A pessoa.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Subject"
                },
                "examples": {
                  "ativo": {
                    "$ref": "#/components/examples/SubjectActive"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      },
      "delete": {
        "tags": [
          "Subjects"
        ],
        "operationId": "eraseSubject",
        "x-bora-poc": true,
        "summary": "Apaga a pessoa (LGPD) e devolve recibo assinado",
        "description": "Apagamento definitivo (LGPD art. 18, VI). Na nuvem, na hora: crypto-shred da DEK do template, remoção do\nHMAC e da cifra do CPF, do `external_ref` e do `onboard_ref`, tombstone no próximo delta e compactação do\nlog de deltas (o vetor some também do histórico servido). Nos aparelhos: o tombstone chega pelo delta;\naparelho offline aplica no próximo sync e, se passar do TTL de 6 h da galeria, para de reconhecer todo\nmundo (fail-closed). O recibo é assinado pela BORA (`bora.erasure.receipt.v1`) e o andamento da\npropagação fica em `GET /v1/erasure-receipts/{receipt_id}`. Depois do apagamento, `GET` da pessoa dá 404.\n\nNa mesma transação saem também: o `external_ref` dos eventos da pessoa (e o `subject_id` dos eventos\n`verdict.recorded`), o vínculo dos vereditos com o `subject_id` (o filtro `?subject_id=` deixa de achar\nas passagens dela), o `onboard_ref` dos deltas guardados e as respostas gravadas de `Idempotency-Key`\nque falavam dela.\n\nO que fica, sem biometria:\n- o recibo assinado e o pedido (auditoria do próprio apagamento);\n- a prova assinada das passagens já registradas (`signed_verdict`, com o pseudônimo `subject_ref` e, se\n  havia, o `onboard_ref` que andaram no cabo), até o fim da retenção de vereditos (13 meses), porque\n  a assinatura cobre esses bytes e reescrever quebraria a prova. Base legal proposta: conciliação\n  tarifária e defesa em disputa (LGPD art. 16, I e art. 7º, VI), a validar com o jurídico. Quando há\n  prova retida, o recibo diz isso em `retained: [verdict_proofs]`.\n",
        "security": [
          {
            "PartnerApiKey": [
              "subjects:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKeyOptional"
          }
        ],
        "responses": {
          "200": {
            "description": "Apagado na nuvem; recibo assinado e estado da propagação.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErasureReceipt"
                },
                "examples": {
                  "recibo": {
                    "$ref": "#/components/examples/ErasureReceipt"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          }
        }
      }
    },
    "/v1/subjects/{subject_id}/consents": {
      "parameters": [
        {
          "$ref": "#/components/parameters/SubjectId"
        }
      ],
      "post": {
        "tags": [
          "Consents"
        ],
        "operationId": "grantConsent",
        "x-bora-poc": true,
        "summary": "Registra consentimento para uma finalidade",
        "description": "Registra o consentimento coletado pelo parceiro (por exemplo, no app dele) com a evidência. O consentimento\ndado na tela do totem durante o cadastro é registrado pelo próprio `POST /v1/enrollments`. Repetir a mesma\nfinalidade com consentimento vigente devolve o registro existente (200).\n",
        "security": [
          {
            "PartnerApiKey": [
              "subjects:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ConsentGrant"
              },
              "examples": {
                "app": {
                  "value": {
                    "purpose": "identification",
                    "evidence": {
                      "method": "partner_app",
                      "terms_version": "termos-bora-transport-2026-10",
                      "accepted_at": "2026-10-01T09:58:12.000Z",
                      "evidence_sha256": "5d41402abc4b2a76b9719d911017c592ae2f1c8e9b1f7a5b3c2d1e0f9a8b7c6d"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Consentimento registrado.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Consent"
                },
                "examples": {
                  "registrado": {
                    "$ref": "#/components/examples/ConsentGranted"
                  }
                }
              }
            }
          },
          "200": {
            "description": "Já havia consentimento vigente para a finalidade; devolve o registro.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Consent"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "428": {
            "$ref": "#/components/responses/IdempotencyKeyRequired"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/subjects/{subject_id}/consents/{purpose}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/SubjectId"
        },
        {
          "name": "purpose",
          "in": "path",
          "required": true,
          "schema": {
            "$ref": "#/components/schemas/ConsentPurpose"
          }
        }
      ],
      "delete": {
        "tags": [
          "Consents"
        ],
        "operationId": "revokeConsent",
        "x-bora-poc": true,
        "summary": "Revoga o consentimento de uma finalidade",
        "description": "Efeitos: `identification` revogado suspende o reconhecimento (mesmo efeito do `block`); `enrollment`\nrevogado apaga o template (crypto-shred) e a pessoa volta a `pending_enrollment`; `dataset_collection`\nrevogado apaga as amostras coletadas para treino. Para apagar a pessoa inteira, use `DELETE /v1/subjects/{subject_id}`.\n",
        "security": [
          {
            "PartnerApiKey": [
              "subjects:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKeyOptional"
          }
        ],
        "responses": {
          "200": {
            "description": "Consentimento revogado.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Consent"
                },
                "examples": {
                  "revogado": {
                    "value": {
                      "consent_id": "6e1d2c3b-4a59-4f68-8a7b-9c0d1e2f3a4b",
                      "subject_id": "3f6c2a9e-8b1d-4e7a-9c3f-5d2e1a0b7c64",
                      "purpose": "identification",
                      "status": "revoked",
                      "terms_version": "termos-bora-transport-2026-10",
                      "method": "partner_app",
                      "granted_at": "2026-10-01T09:58:12.000Z",
                      "revoked_at": "2026-10-02T08:00:00.000Z"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/enrollment-sessions": {
      "post": {
        "tags": [
          "Enrollment sessions"
        ],
        "operationId": "createEnrollmentSession",
        "x-bora-poc": true,
        "summary": "Abre um cadastro de palma",
        "description": "Abre uma sessão de cadastro para uma pessoa já criada. Devolve um `token` de uso único e um `qr_payload`\npara o totem ou o BORA ACCESS ler. Aparelho sem leitor de QR: o operador digita o `short_code` e o aparelho\ntroca o código pelo token em `POST /v1/enrollment-sessions/redeem`. O token aparece só nesta resposta,\na BORA guarda só o hash dele. O aparelho conclui com `POST /v1/enrollments`. O consentimento é mostrado e\naceito na tela do totem antes da captura. Limite: 60 sessões por minuto por tenant.\n",
        "security": [
          {
            "PartnerApiKey": [
              "subjects:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EnrollmentSessionCreate"
              },
              "examples": {
                "duas_maos": {
                  "value": {
                    "subject_id": "3f6c2a9e-8b1d-4e7a-9c3f-5d2e1a0b7c64",
                    "hands_required": [
                      "L",
                      "R"
                    ],
                    "expires_in_s": 300
                  }
                },
                "por_external_ref": {
                  "value": {
                    "external_ref": "MBH-000482913",
                    "hands_required": [
                      "L",
                      "R"
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Sessão aberta.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "Location": {
                "$ref": "#/components/headers/Location"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnrollmentSession"
                },
                "examples": {
                  "aberta": {
                    "$ref": "#/components/examples/EnrollmentSessionOpen"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "428": {
            "$ref": "#/components/responses/IdempotencyKeyRequired"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/enrollment-sessions/{session_id}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/SessionId"
        }
      ],
      "get": {
        "tags": [
          "Enrollment sessions"
        ],
        "operationId": "getEnrollmentSession",
        "x-bora-poc": true,
        "summary": "Consulta o estado de um cadastro",
        "description": "Nunca devolve o token. Falha de captura aparece só como `capture_rejected` (sem dizer se foi qualidade ou liveness, para não virar oráculo de ataque de apresentação).",
        "security": [
          {
            "PartnerApiKey": [
              "subjects:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Estado da sessão.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EnrollmentSession"
                },
                "examples": {
                  "concluida": {
                    "$ref": "#/components/examples/EnrollmentSessionCompleted"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/devices": {
      "get": {
        "tags": [
          "Devices"
        ],
        "operationId": "listDevices",
        "x-bora-poc": true,
        "summary": "Lista os aparelhos do tenant",
        "security": [
          {
            "PartnerApiKey": [
              "devices:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "status",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/DeviceStatus"
            }
          },
          {
            "name": "gate_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/AsciiRef"
            }
          },
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/DeviceKind"
            }
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "Página de aparelhos.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DevicePage"
                },
                "examples": {
                  "um_aparelho": {
                    "value": {
                      "data": [
                        {
                          "device_id": "access-bh-eldorado-03",
                          "kind": "access",
                          "status": "active",
                          "gate_id": "bh-eldorado-cat-03",
                          "dbd_id": "dbd-bh-eldorado-03",
                          "app": {
                            "pkg": "studio.unflat.boradeptrum.dbd",
                            "version": "2.1.4"
                          },
                          "model_id": "deptrum-onnx-2026.09",
                          "gallery": {
                            "stream": "main",
                            "epoch": 3,
                            "seq": 15873,
                            "synced_at": "2026-10-01T10:19:58.000Z"
                          },
                          "keys": [
                            {
                              "purpose": "verdict",
                              "alg": "ed25519",
                              "kid": "300290aeb182952c1337b227be5fe728"
                            },
                            {
                              "purpose": "http",
                              "alg": "ed25519",
                              "kid": "d1ab5521bfd29c9326bcc0912595d2d2"
                            }
                          ],
                          "trust": {
                            "attest_level": "none",
                            "verified": false
                          },
                          "health": [
                            "KEY_UNATTESTED"
                          ],
                          "last_seen_at": "2026-10-01T10:20:01.000Z",
                          "registered_at": "2026-09-30T18:00:00.000Z",
                          "revoked_at": null,
                          "livemode": true
                        }
                      ],
                      "has_more": false,
                      "next_cursor": null
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/devices/{device_id}/revoke": {
      "parameters": [
        {
          "$ref": "#/components/parameters/DeviceIdPath"
        }
      ],
      "post": {
        "tags": [
          "Devices"
        ],
        "operationId": "revokeDevice",
        "x-bora-poc": true,
        "summary": "Revoga um aparelho (kill remoto)",
        "description": "Mata as chaves do aparelho (o kill é da chave, não do nome). Na próxima consulta a\n`GET /v1/devices/self/status` o aparelho recebe `wipe` assinado e apaga galeria, DEKs e seeds; depois disso\ntoda rota de aparelho responde 401 para essas chaves. Com o DBD offline, a revogação chega pelo\n`trust.bundle` (v1.1). Irreversível para estas chaves: para pôr o aparelho de volta, o admin BORA emite um\ntoken de provisionamento novo para o MESMO `device_id` e o aparelho se registra com chaves novas (as\nantigas ficam arquivadas, só para verificar vereditos antigos).\n",
        "security": [
          {
            "PartnerApiKey": [
              "devices:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DeviceRevoke"
              },
              "examples": {
                "roubado": {
                  "value": {
                    "reason": "stolen"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Aparelho revogado.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Device"
                },
                "examples": {
                  "revogado": {
                    "value": {
                      "device_id": "access-bh-eldorado-03",
                      "kind": "access",
                      "status": "revoked",
                      "gate_id": "bh-eldorado-cat-03",
                      "dbd_id": "dbd-bh-eldorado-03",
                      "app": {
                        "pkg": "studio.unflat.boradeptrum.dbd",
                        "version": "2.1.4"
                      },
                      "model_id": "deptrum-onnx-2026.09",
                      "gallery": {
                        "stream": "main",
                        "epoch": 3,
                        "seq": 15873,
                        "synced_at": "2026-10-01T10:19:58.000Z"
                      },
                      "keys": [
                        {
                          "purpose": "verdict",
                          "alg": "ed25519",
                          "kid": "300290aeb182952c1337b227be5fe728"
                        },
                        {
                          "purpose": "http",
                          "alg": "ed25519",
                          "kid": "d1ab5521bfd29c9326bcc0912595d2d2"
                        }
                      ],
                      "trust": {
                        "attest_level": "none",
                        "verified": false
                      },
                      "health": [
                        "KEY_UNATTESTED"
                      ],
                      "last_seen_at": "2026-10-01T10:20:01.000Z",
                      "registered_at": "2026-09-30T18:00:00.000Z",
                      "revoked_at": "2026-10-01T11:00:00.000Z",
                      "livemode": true
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "428": {
            "$ref": "#/components/responses/IdempotencyKeyRequired"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/devices/{device_id}/inbox": {
      "parameters": [
        {
          "$ref": "#/components/parameters/DeviceIdPath"
        }
      ],
      "get": {
        "tags": [
          "Mail"
        ],
        "operationId": "listDeviceInbox",
        "x-bora-poc": true,
        "summary": "Registros selados para levar ao aparelho",
        "description": "Carteiro, ida. Registros que a BORA selou para este aparelho: atualização da base,\nrevogações, config assinada, `trust.bundle` e atualizações de app ou modelo. O BDOS busca aqui e entrega ao\nDBD, que oferece ao aparelho pelo cabo (`file.offer kind post.in`). Nem o BDOS nem o DBD conseguem abrir,\nforjar ou escolher o que levam: o conteúdo vai cifrado para a chave de selo do aparelho e assinado pela BORA.\nPeça sempre a partir do último `seq` entregue (`after_seq`); o aparelho aplica em ordem estrita.\n",
        "security": [
          {
            "PartnerApiKey": [
              "devices:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "after_seq",
            "in": "query",
            "required": false,
            "description": "Devolve só registros com `seq` maior que este. Padrão 0 (desde o início).",
            "schema": {
              "type": "integer",
              "minimum": 0,
              "maximum": 9007199254740991,
              "default": 0
            }
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "Registros pendentes para o aparelho, em ordem de `seq`.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeviceInbox"
                },
                "examples": {
                  "um_registro": {
                    "value": {
                      "device_id": "access-bh-eldorado-03",
                      "data": [
                        {
                          "post": {
                            "v": 1,
                            "rid": "c41f2a9be07d4d3f9a6e5b2c1d0e8f7a",
                            "box": "in",
                            "src": "bora",
                            "dst": "access-bh-eldorado-03",
                            "seq": 88,
                            "created_ms": 1790849000000,
                            "suite": "hpke-x25519-sha256-chacha20poly1305",
                            "ct_len": 144,
                            "ct_sha256": "7d8bbc540bbbfc01881f4becb42f2ff14c72d372a889bf04e3e0a07019e365fc"
                          },
                          "ct_b64": "TAc0sssnInErGpzmvTRKQb1f5wNinoQEfZvKHfG8DrjbuN1sZ3oAIPAOl1u/UG3lbMMpi9l756LtnMyruTrLn9PYmK5g1C7F3rI3xTWKOR5sbbVg+L2Z6V7MNLDnKKqxiPclJu5KxrYKxErFd1yleZcuCnC4aWnex4JcyE+D3UupqQN8hyyjLD4mJWsuIWBo",
                          "alg": "ed25519",
                          "signer_kid": "d9bf8bfe11bc109cb5687c77a5bf6581",
                          "sig_b64": "3rt1LWthsu8S4Qr4eGPNGTmfqMda3mm1/YzeaSjKdbsDLNsUOhxj0jkDcCpKJIZYiZUOTKhl6drZF61PH1ZzDg==",
                          "signer_cert_b64": "kvCBJCkO7mgC+XHfZDDByN6Nkz2+zpLxXeQBnT3vemEAAAGixmd6QBQuCyvnDKjwbNqTrEAThAEsCj79FV04k648hrD4XcsbBS9kg8rvOZ6GUMWK38vKc0BIqjHSvQ8MeJ9UXLkoeAw="
                        }
                      ],
                      "has_more": false,
                      "next_after_seq": 88
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/devices/{device_id}/outbox": {
      "parameters": [
        {
          "$ref": "#/components/parameters/DeviceIdPath"
        }
      ],
      "post": {
        "tags": [
          "Mail"
        ],
        "operationId": "submitDeviceOutbox",
        "x-bora-poc": true,
        "summary": "Entrega registros selados que saíram do aparelho",
        "description": "Carteiro, volta. O aparelho sela para a BORA os vereditos, recibos e eventos\n(`post.out`); o DBD puxa pelo cabo e o BDOS entrega aqui do jeito que recebeu, sem abrir. A BORA confere a\nassinatura do aparelho, o destino e o `sha256` de cada registro e guarda. `acked_upto_seq` é o maior `seq`\ncontíguo já recebido: o recibo assinado (`bora.post.receipt`) volta pela caixa de entrada e é ele que libera\no aparelho para apagar a cópia local. Reenviar o mesmo registro é seguro (sai em `duplicates`).\n",
        "security": [
          {
            "PartnerApiKey": [
              "devices:write"
            ]
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OutboxSubmit"
              },
              "examples": {
                "um_registro": {
                  "value": {
                    "records": [
                      {
                        "post": {
                          "v": 1,
                          "rid": "43f942747a684f61764a6b589e5a0557",
                          "box": "out",
                          "src": "access-bh-eldorado-03",
                          "dst": "bora",
                          "seq": 41,
                          "created_ms": 1790849100000,
                          "suite": "hpke-x25519-sha256-chacha20poly1305",
                          "ct_len": 96,
                          "ct_sha256": "86f4584fac1a57bdd67f82b98d8da05a97c715571097f7c70167b4deeefe0629"
                        },
                        "ct_b64": "NL6ht3TgTTzJjPh8cwUgSiJ+0fEHSRs0zGT8ItLRnJE0vqG3dOBNPMmM+HxzBSBKIn7R8QdJGzTMZPwi0tGckTS+obd04E08yYz4fHMFIEoiftHxB0kbNMxk/CLS0ZyR",
                        "alg": "ed25519",
                        "signer_kid": "300290aeb182952c1337b227be5fe728",
                        "sig_b64": "vEyNjy1+G698fP8FuJz/lItjTQyV7SI6wcGy9B9YHrSUCfYNjs1WzpvydW2bz0bY9Crd05IIC05b1KctU0peCg=="
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Resultado por registro.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/Idempotent-Replayed"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OutboxResult"
                },
                "examples": {
                  "aceito": {
                    "value": {
                      "device_id": "access-bh-eldorado-03",
                      "accepted": [
                        41
                      ],
                      "duplicates": [],
                      "rejected": [],
                      "acked_upto_seq": 41
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "422": {
            "$ref": "#/components/responses/ValidationFailed"
          },
          "428": {
            "$ref": "#/components/responses/IdempotencyKeyRequired"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/verdicts": {
      "get": {
        "tags": [
          "Verdicts"
        ],
        "operationId": "listVerdicts",
        "x-bora-poc": true,
        "summary": "Log de passagens",
        "description": "Vereditos que os aparelhos subiram (`POST /v1/verdicts/batch`), já resolvidos para `subject_id` e\n`external_ref` (só em `accept`), com a decisão e a passagem do DBD quando chegaram. Ordem padrão:\nmais recente primeiro por `decided_at`. Retenção: 13 meses (proposta).\n",
        "security": [
          {
            "PartnerApiKey": [
              "verdicts:read"
            ]
          }
        ],
        "parameters": [
          {
            "name": "device_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/AsciiRef"
            }
          },
          {
            "name": "gate_id",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/AsciiRef"
            }
          },
          {
            "name": "subject_id",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          },
          {
            "name": "decision",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/LinkDecision"
            }
          },
          {
            "name": "reconciliation",
            "in": "query",
            "required": false,
            "schema": {
              "$ref": "#/components/schemas/ReconciliationStatus"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "Início inclusivo (decided_at).",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Fim exclusivo (decided_at).",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "order",
            "in": "query",
            "required": false,
            "schema": {
              "type": "string",
              "enum": [
                "desc",
                "asc"
              ],
              "default": "desc"
            }
          },
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          }
        ],
        "responses": {
          "200": {
            "description": "Página de vereditos.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerdictPage"
                },
                "examples": {
                  "pagina": {
                    "value": {
                      "data": [
                        {
                          "verdict_id": "bae244c9d453584320e97cf6b06fb432",
                          "txn_id": "7f3c9a1e5b2d4c6f8a0b1c2d3e4f5a6b",
                          "device_id": "access-bh-eldorado-03",
                          "gate_id": "bh-eldorado-cat-03",
                          "dbd_id": "dbd-bh-eldorado-03",
                          "verdict_seq": 1042,
                          "decision": "accept",
                          "result": "MATCH",
                          "subject_id": "3f6c2a9e-8b1d-4e7a-9c3f-5d2e1a0b7c64",
                          "external_ref": "MBH-000482913",
                          "hand": "R",
                          "pad_res": "pass",
                          "quality_q": 9120,
                          "model_id": "deptrum-onnx-2026.09",
                          "decided_at": "2026-10-01T10:20:00.840Z",
                          "received_at": "2026-10-01T10:20:03.112Z",
                          "dbd": {
                            "reason": "ok",
                            "outcome": "LIBERAR",
                            "actuated": true,
                            "decision_seq": 88123,
                            "decided_at": "2026-10-01T10:20:00.861Z"
                          },
                          "passage": {
                            "passed": true,
                            "cause": "giro",
                            "at": "2026-10-01T10:20:02.400Z"
                          },
                          "reconciliation": "complete"
                        }
                      ],
                      "has_more": true,
                      "next_cursor": "eyJrIjoiZGVjaWRlZF9hdCIsInYiOjE3OTA4NTAwMDA4NDB9"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "410": {
            "$ref": "#/components/responses/Gone"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/v1/verdicts/{verdict_id}": {
      "parameters": [
        {
          "name": "verdict_id",
          "in": "path",
          "required": true,
          "description": "O verdict_ref do BORA-LINK/1.",
          "schema": {
            "$ref": "#/components/schemas/LinkHex32"
          }
        }
      ],
      "get": {
        "tags": [
          "Verdicts"
        ],
        "operationId": "getVerdict",
        "x-bora-poc": true,
        "summary": "Veredito com prova assinada",
        "description": "Devolve o `SignedVerdict` exato que o aparelho mandou ao DBD, a `SignedDecision` e a `SignedPassage` do DBD\n(quando chegaram) e o material para verificar fora da BORA: chaves públicas e prefixos de domínio. Serve\npara contestação de cobrança e conciliação com o BDOS.\n",
        "security": [
          {
            "PartnerApiKey": [
              "verdicts:read"
            ]
          }
        ],
        "responses": {
          "200": {
            "description": "Prova.",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/X-Request-Id"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/VerdictProof"
                },
                "examples": {
                  "aprovado": {
                    "$ref": "#/components/examples/VerdictProof"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthenticated"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "PartnerApiKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "bora_<live|test>_<key_id>_<secret>",
        "description": "API key do tenant. Escopos na lista do requisito de segurança de cada rota."
      }
    },
    "parameters": {
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": true,
        "description": "Chave única da operação. Use um UUID v4 novo por operação (veja Idempotência).",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255,
          "pattern": "^[\\x21-\\x7E]+$"
        },
        "example": "0f8b2c7e-4a1d-4b9e-8c3f-2d1e0a9b8c7d"
      },
      "IdempotencyKeyOptional": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255,
          "pattern": "^[\\x21-\\x7E]+$"
        }
      },
      "ClientRequestId": {
        "name": "X-Request-Id",
        "in": "header",
        "required": false,
        "description": "Id de correlação do cliente (ecoado na resposta). Se ausente, a BORA gera um.",
        "schema": {
          "type": "string",
          "maxLength": 64,
          "pattern": "^[A-Za-z0-9._:-]{1,64}$"
        }
      },
      "SubjectId": {
        "name": "subject_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "SessionId": {
        "name": "session_id",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "DeviceIdPath": {
        "name": "device_id",
        "in": "path",
        "required": true,
        "schema": {
          "$ref": "#/components/schemas/DeviceId"
        }
      },
      "Limit": {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 200,
          "default": 50
        }
      },
      "Cursor": {
        "name": "cursor",
        "in": "query",
        "required": false,
        "description": "Cursor opaco (next_cursor da página anterior).",
        "schema": {
          "type": "string",
          "maxLength": 512,
          "pattern": "^[A-Za-z0-9_=-]+$"
        }
      }
    },
    "headers": {
      "X-Request-Id": {
        "description": "Id da requisição (o do cliente ou um gerado). Também vai no `instance` dos erros.",
        "schema": {
          "type": "string"
        }
      },
      "Location": {
        "description": "URL do recurso criado.",
        "schema": {
          "type": "string"
        }
      },
      "Idempotent-Replayed": {
        "description": "`true` quando a resposta é a gravada para a mesma Idempotency-Key.",
        "schema": {
          "type": "string",
          "enum": [
            "true"
          ]
        }
      },
      "Bora-Server-Time": {
        "description": "Hora do servidor em epoch ms (para o aparelho medir desvio de relógio).",
        "schema": {
          "type": "string",
          "pattern": "^[0-9]{13}$"
        }
      },
      "RateLimit-Limit": {
        "schema": {
          "type": "integer"
        }
      },
      "RateLimit-Remaining": {
        "schema": {
          "type": "integer"
        }
      },
      "RateLimit-Reset": {
        "description": "Segundos até a janela reabrir.",
        "schema": {
          "type": "integer"
        }
      },
      "Retry-After": {
        "description": "Segundos para tentar de novo.",
        "schema": {
          "type": "integer"
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Requisição malformada (JSON inválido, cursor inválido, parâmetro com formato errado).",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "examples": {
              "json": {
                "value": {
                  "type": "https://bora.id/transport/documentation#erro-malformed_json",
                  "title": "JSON malformado",
                  "status": 400,
                  "code": "malformed_json",
                  "detail": "O corpo não é um JSON válido.",
                  "instance": "req_01J9Z8X7W6V5",
                  "retryable": false
                }
              }
            }
          }
        }
      },
      "Unauthenticated": {
        "description": "Credencial ausente ou inválida. Sempre a mesma resposta, sem dizer o motivo (sem oráculo).",
        "headers": {
          "Bora-Server-Time": {
            "$ref": "#/components/headers/Bora-Server-Time"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "examples": {
              "generico": {
                "value": {
                  "type": "https://bora.id/transport/documentation#erro-unauthenticated",
                  "title": "Não autenticado",
                  "status": 401,
                  "code": "unauthenticated",
                  "instance": "req_01J9Z8X7W6V6",
                  "retryable": false
                }
              }
            }
          }
        }
      },
      "Forbidden": {
        "description": "Autenticado, mas sem permissão (escopo, ambiente test/live, token de cadastro inválido).",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "examples": {
              "escopo": {
                "value": {
                  "type": "https://bora.id/transport/documentation#erro-insufficient_scope",
                  "title": "Escopo insuficiente",
                  "status": 403,
                  "code": "insufficient_scope",
                  "detail": "A API key não tem o escopo subjects:write.",
                  "instance": "req_01J9Z8X7W6V7",
                  "retryable": false
                }
              }
            }
          }
        }
      },
      "NotFound": {
        "description": "Recurso inexistente ou de outro tenant (mesma resposta).",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "examples": {
              "pessoa": {
                "value": {
                  "type": "https://bora.id/transport/documentation#erro-subject_not_found",
                  "title": "Pessoa não encontrada",
                  "status": 404,
                  "code": "subject_not_found",
                  "instance": "req_01J9Z8X7W6V8",
                  "retryable": false
                }
              }
            }
          }
        }
      },
      "Conflict": {
        "description": "Conflito com o estado atual.",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "examples": {
              "external_ref": {
                "value": {
                  "type": "https://bora.id/transport/documentation#erro-external_ref_conflict",
                  "title": "external_ref já usado",
                  "status": 409,
                  "code": "external_ref_conflict",
                  "detail": "Já existe uma pessoa com este external_ref no tenant.",
                  "instance": "req_01J9Z8X7W6V9",
                  "retryable": false
                }
              }
            }
          }
        }
      },
      "Gone": {
        "description": "Recurso ou histórico fora da retenção.",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "examples": {
              "galeria": {
                "value": {
                  "type": "https://bora.id/transport/documentation#erro-history_expired",
                  "title": "Histórico de deltas expirado",
                  "status": 410,
                  "code": "history_expired",
                  "detail": "Refaça a base por GET /v1/gallery/snapshot.",
                  "instance": "req_01J9Z8X7W6VA",
                  "retryable": false,
                  "snapshot_seq": 15872
                }
              }
            }
          }
        }
      },
      "UnsupportedMediaType": {
        "description": "Content-Type diferente de application/json.",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "ValidationFailed": {
        "description": "JSON válido, mas fora do contrato.",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "examples": {
              "cpf_como_ref": {
                "value": {
                  "type": "https://bora.id/transport/documentation#erro-external_ref_looks_like_cpf",
                  "title": "external_ref parece um CPF",
                  "status": 422,
                  "code": "external_ref_looks_like_cpf",
                  "detail": "Use o ID da conta no seu sistema; o CPF vai só no campo cpf.",
                  "instance": "req_01J9Z8X7W6VB",
                  "retryable": false,
                  "errors": [
                    {
                      "pointer": "/external_ref",
                      "code": "external_ref_looks_like_cpf"
                    }
                  ]
                }
              }
            }
          }
        }
      },
      "IdempotencyKeyRequired": {
        "description": "POST sem Idempotency-Key.",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "examples": {
              "sem_chave": {
                "value": {
                  "type": "https://bora.id/transport/documentation#erro-idempotency_key_required",
                  "title": "Idempotency-Key obrigatória",
                  "status": 428,
                  "code": "idempotency_key_required",
                  "instance": "req_01J9Z8X7W6VC",
                  "retryable": false
                }
              }
            }
          }
        }
      },
      "RateLimited": {
        "description": "Limite de taxa estourado.",
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/Retry-After"
          },
          "RateLimit-Limit": {
            "$ref": "#/components/headers/RateLimit-Limit"
          },
          "RateLimit-Remaining": {
            "$ref": "#/components/headers/RateLimit-Remaining"
          },
          "RateLimit-Reset": {
            "$ref": "#/components/headers/RateLimit-Reset"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            },
            "examples": {
              "limite": {
                "value": {
                  "type": "https://bora.id/transport/documentation#erro-rate_limited",
                  "title": "Muitas requisições",
                  "status": 429,
                  "code": "rate_limited",
                  "instance": "req_01J9Z8X7W6VD",
                  "retryable": true
                }
              }
            }
          }
        }
      },
      "InternalError": {
        "description": "Erro interno. Pode repetir com a mesma Idempotency-Key.",
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      },
      "ServiceUnavailable": {
        "description": "Serviço indisponível.",
        "headers": {
          "Retry-After": {
            "$ref": "#/components/headers/Retry-After"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/Problem"
            }
          }
        }
      }
    },
    "schemas": {
      "AsciiRef": {
        "type": "string",
        "pattern": "^[A-Za-z0-9._:-]{1,64}$"
      },
      "DeviceId": {
        "description": "Id do aparelho. `self`, `register` e `attest` são reservados.",
        "type": "string",
        "pattern": "^[A-Za-z0-9._:-]{1,64}$",
        "not": {
          "enum": [
            "self",
            "register",
            "attest"
          ]
        }
      },
      "ExternalRef": {
        "description": "ID da conta da pessoa no sistema do parceiro (matrícula, número da conta). Único por tenant. Nunca CPF.",
        "type": "string",
        "pattern": "^[A-Za-z0-9._:@-]{1,128}$"
      },
      "Timestamp": {
        "type": "string",
        "format": "date-time"
      },
      "Hex64": {
        "type": "string",
        "pattern": "^[0-9a-f]{64}$"
      },
      "PageMeta": {
        "type": "object",
        "required": [
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "ReasonCode": {
        "description": "Códigos estáveis de erro HTTP (campo `code` do problem+json). Novos códigos podem entrar no v1; o cliente\ntrata código desconhecido pelo `status`.\n\n| code | status | quando | repetir? |\n|---|---|---|---|\n| `malformed_json` | 400 | corpo não é JSON válido | não |\n| `invalid_request` | 400 | parâmetro de query ou header com formato errado | não |\n| `invalid_cursor` | 400 | cursor adulterado ou de outra lista | não |\n| `unauthenticated` | 401 | qualquer falha de credencial (key, assinatura, mTLS, relógio) | não |\n| `forbidden` | 403 | credencial válida sem acesso ao recurso (ex.: totem em rota de galeria) | não |\n| `insufficient_scope` | 403 | API key sem o escopo da rota | não |\n| `livemode_mismatch` | 403 | key `test` em recurso `live` ou o contrário | não |\n| `enrollment_session_invalid` | 403 | token de cadastro errado, usado, vencido ou de outro aparelho | não |\n| `subject_not_found` | 404 | pessoa inexistente, apagada ou de outro tenant | não |\n| `device_not_found` | 404 | aparelho inexistente ou de outro tenant | não |\n| `verdict_not_found` | 404 | veredito inexistente ou de outro tenant | não |\n| `enrollment_session_not_found` | 404 | sessão inexistente ou de outro tenant | não |\n| `erasure_receipt_not_found` | 404 | recibo inexistente ou de outro tenant | não |\n| `external_ref_conflict` | 409 | external_ref já usado no tenant | não |\n| `cpf_conflict` | 409 | CPF já ligado a outra pessoa ativa do tenant (sem dizer qual) | não |\n| `subject_state_conflict` | 409 | operação inválida no estado atual (ex.: unblock de quem não está bloqueado) | não |\n| `enrollment_session_state_conflict` | 409 | sessão não está aberta | não |\n| `device_state_conflict` | 409 | device_id ativo com outras chaves, ou chave já de outro aparelho | não |\n| `idempotency_in_progress` | 409 | a primeira requisição com a mesma chave ainda roda | sim |\n| `history_expired` | 410 | delta pedido fora da retenção; corpo traz `snapshot_seq` | não, refazer por snapshot |\n| `cursor_expired` | 410 | cursor fora da retenção | não |\n| `payload_too_large` | 413 | corpo acima do limite | não |\n| `unsupported_media_type` | 415 | Content-Type errado | não |\n| `validation_failed` | 422 | JSON fora do contrato; detalhes em `errors[]` | não |\n| `external_ref_looks_like_cpf` | 422 | external_ref carrega um CPF válido (11 dígitos seguidos, com ou sem separador) | não |\n| `onboard_ref_looks_like_cpf` | 422 | onboard_ref carrega um CPF válido (ele viaja no cabo e na base dos aparelhos) | não |\n| `cpf_invalid` | 422 | CPF com dígito verificador errado | não |\n| `consent_required` | 422 | operação exige consentimento vigente da finalidade | não |\n| `model_unsupported` | 422 | vetor de `model_id` que a galeria do tenant não usa | não |\n| `idempotency_key_mismatch` | 422 | mesma Idempotency-Key com corpo diferente | não |\n| `idempotency_key_required` | 428 | POST sem Idempotency-Key | não |\n| `rate_limited` | 429 | limite de taxa | sim, depois do Retry-After |\n| `internal_error` | 500 | erro interno | sim |\n| `not_implemented` | 501 | recurso planejado (webhooks no v1.0) | não |\n| `service_unavailable` | 503 | manutenção ou sobrecarga | sim, depois do Retry-After |\n",
        "type": "string",
        "x-extensible-enum": true,
        "enum": [
          "malformed_json",
          "invalid_request",
          "invalid_cursor",
          "unauthenticated",
          "forbidden",
          "insufficient_scope",
          "livemode_mismatch",
          "enrollment_session_invalid",
          "subject_not_found",
          "device_not_found",
          "verdict_not_found",
          "enrollment_session_not_found",
          "erasure_receipt_not_found",
          "external_ref_conflict",
          "cpf_conflict",
          "subject_state_conflict",
          "enrollment_session_state_conflict",
          "device_state_conflict",
          "idempotency_in_progress",
          "history_expired",
          "cursor_expired",
          "payload_too_large",
          "unsupported_media_type",
          "validation_failed",
          "external_ref_looks_like_cpf",
          "onboard_ref_looks_like_cpf",
          "cpf_invalid",
          "consent_required",
          "model_unsupported",
          "idempotency_key_mismatch",
          "idempotency_key_required",
          "rate_limited",
          "internal_error",
          "not_implemented",
          "service_unavailable"
        ]
      },
      "DeviceInbox": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "device_id",
          "data",
          "has_more",
          "next_after_seq"
        ],
        "properties": {
          "device_id": {
            "$ref": "#/components/schemas/DeviceId"
          },
          "data": {
            "type": "array",
            "maxItems": 100,
            "items": {
              "$ref": "#/components/schemas/LinkSealedRecord"
            }
          },
          "has_more": {
            "type": "boolean"
          },
          "next_after_seq": {
            "description": "Passe em `after_seq` na próxima chamada.",
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991
          }
        }
      },
      "OutboxSubmit": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "records"
        ],
        "properties": {
          "records": {
            "type": "array",
            "minItems": 1,
            "maxItems": 32,
            "items": {
              "$ref": "#/components/schemas/LinkSealedRecord"
            }
          }
        }
      },
      "OutboxResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "device_id",
          "accepted",
          "duplicates",
          "rejected",
          "acked_upto_seq"
        ],
        "properties": {
          "device_id": {
            "$ref": "#/components/schemas/DeviceId"
          },
          "accepted": {
            "type": "array",
            "items": {
              "type": "integer",
              "minimum": 1,
              "maximum": 9007199254740991
            }
          },
          "duplicates": {
            "type": "array",
            "items": {
              "type": "integer",
              "minimum": 1,
              "maximum": 9007199254740991
            }
          },
          "rejected": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "seq",
                "code"
              ],
              "properties": {
                "seq": {
                  "type": "integer",
                  "minimum": 0,
                  "maximum": 9007199254740991
                },
                "code": {
                  "type": "string",
                  "enum": [
                    "wrong_box",
                    "wrong_device",
                    "unknown_signer",
                    "bad_signature",
                    "bad_hash",
                    "seq_conflict"
                  ]
                }
              }
            }
          },
          "acked_upto_seq": {
            "description": "Maior `seq` contíguo (a partir de 1) já guardado pela BORA para este aparelho.",
            "type": "integer",
            "minimum": 0,
            "maximum": 9007199254740991
          }
        }
      },
      "Problem": {
        "description": "RFC 9457. `type` aponta para o código na página de documentação (`https://bora.id/transport/documentation#erro-<code>`). Nunca ecoa valor recebido.",
        "type": "object",
        "required": [
          "type",
          "title",
          "status",
          "code",
          "instance",
          "retryable"
        ],
        "properties": {
          "type": {
            "type": "string",
            "format": "uri"
          },
          "title": {
            "type": "string",
            "maxLength": 120
          },
          "status": {
            "type": "integer",
            "minimum": 400,
            "maximum": 599
          },
          "code": {
            "$ref": "#/components/schemas/ReasonCode"
          },
          "detail": {
            "type": "string",
            "maxLength": 300
          },
          "instance": {
            "description": "Id da requisição (mesmo do X-Request-Id).",
            "type": "string"
          },
          "retryable": {
            "type": "boolean"
          },
          "errors": {
            "description": "Só em 422 validation_failed e afins. `pointer` = JSON Pointer (RFC 6901) do campo.",
            "type": "array",
            "maxItems": 50,
            "items": {
              "type": "object",
              "required": [
                "pointer",
                "code"
              ],
              "properties": {
                "pointer": {
                  "type": "string",
                  "maxLength": 200
                },
                "code": {
                  "type": "string",
                  "pattern": "^[a-z0-9_]{1,64}$"
                }
              }
            }
          },
          "snapshot_seq": {
            "description": "Só em 410 history_expired.",
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "Health": {
        "type": "object",
        "required": [
          "status",
          "api_version",
          "contract_version",
          "server_time"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ok",
              "degraded"
            ]
          },
          "api_version": {
            "const": "v1"
          },
          "contract_version": {
            "type": "string"
          },
          "server_time": {
            "$ref": "#/components/schemas/Timestamp"
          }
        }
      },
      "SigningKeyList": {
        "type": "object",
        "required": [
          "keys"
        ],
        "properties": {
          "keys": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "kid",
                "alg",
                "use",
                "pub_b64",
                "not_before",
                "not_after"
              ],
              "properties": {
                "kid": {
                  "$ref": "#/components/schemas/LinkHex32"
                },
                "alg": {
                  "const": "ed25519"
                },
                "use": {
                  "type": "array",
                  "items": {
                    "type": "string",
                    "enum": [
                      "erasure_receipt",
                      "gallery",
                      "device_status",
                      "webhook"
                    ]
                  }
                },
                "pub_b64": {
                  "$ref": "#/components/schemas/Ed25519Pub"
                },
                "not_before": {
                  "$ref": "#/components/schemas/Timestamp"
                },
                "not_after": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time"
                }
              }
            }
          }
        }
      },
      "Ed25519Pub": {
        "description": "Chave pública de 32 bytes em base64 padrão.",
        "type": "string",
        "pattern": "^[A-Za-z0-9+/]{43}=$"
      },
      "SubjectStatus": {
        "type": "string",
        "enum": [
          "pending_enrollment",
          "active",
          "blocked"
        ]
      },
      "Subject": {
        "type": "object",
        "required": [
          "subject_id",
          "external_ref",
          "subject_ref",
          "status",
          "enrollment",
          "kyc",
          "created_at",
          "updated_at",
          "livemode"
        ],
        "properties": {
          "subject_id": {
            "type": "string",
            "format": "uuid",
            "readOnly": true
          },
          "external_ref": {
            "$ref": "#/components/schemas/ExternalRef"
          },
          "subject_ref": {
            "description": "Pseudônimo HMAC por tenant que viaja no veredito do cabo. Dado pessoal pela LGPD.",
            "allOf": [
              {
                "$ref": "#/components/schemas/LinkHex32"
              }
            ],
            "readOnly": true
          },
          "onboard_ref": {
            "$ref": "#/components/schemas/OnboardRef"
          },
          "status": {
            "$ref": "#/components/schemas/SubjectStatus"
          },
          "block": {
            "type": [
              "object",
              "null"
            ],
            "required": [
              "reason",
              "blocked_at"
            ],
            "properties": {
              "reason": {
                "$ref": "#/components/schemas/BlockReason"
              },
              "blocked_at": {
                "$ref": "#/components/schemas/Timestamp"
              }
            }
          },
          "enrollment": {
            "type": [
              "object",
              "null"
            ],
            "required": [
              "hands",
              "model_id",
              "enrolled_at"
            ],
            "properties": {
              "hands": {
                "type": "array",
                "minItems": 1,
                "maxItems": 2,
                "uniqueItems": true,
                "items": {
                  "type": "string",
                  "enum": [
                    "L",
                    "R"
                  ]
                }
              },
              "model_id": {
                "$ref": "#/components/schemas/AsciiRef"
              },
              "enrolled_at": {
                "$ref": "#/components/schemas/Timestamp"
              }
            }
          },
          "consents": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "purpose",
                "status"
              ],
              "properties": {
                "purpose": {
                  "$ref": "#/components/schemas/ConsentPurpose"
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "granted",
                    "revoked"
                  ]
                }
              }
            }
          },
          "kyc": {
            "type": "object",
            "required": [
              "cpf_on_file"
            ],
            "properties": {
              "cpf_on_file": {
                "type": "boolean"
              }
            }
          },
          "gallery_seq": {
            "description": "seq do último delta da galeria que levou uma mudança desta pessoa (para acompanhar propagação).",
            "type": [
              "integer",
              "null"
            ]
          },
          "created_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "updated_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "livemode": {
            "type": "boolean"
          }
        }
      },
      "OnboardRef": {
        "description": "Token opaco opcional do operador que viaja no veredito de accept (campo onboard_ref do BORA-LINK/1) e na base de todos os aparelhos. Não use CPF nem nome; um valor que carrega CPF válido dá 422 onboard_ref_looks_like_cpf.",
        "type": "string",
        "pattern": "^[A-Za-z0-9._:+/=-]{1,128}$"
      },
      "SubjectCreate": {
        "type": "object",
        "required": [
          "external_ref"
        ],
        "additionalProperties": false,
        "properties": {
          "external_ref": {
            "$ref": "#/components/schemas/ExternalRef"
          },
          "cpf": {
            "description": "Opcional, só para KYC e dedup. Só dígitos. Nunca devolvido.",
            "type": "string",
            "pattern": "^[0-9]{11}$",
            "writeOnly": true
          },
          "onboard_ref": {
            "$ref": "#/components/schemas/OnboardRef"
          }
        }
      },
      "SubjectPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/PageMeta"
          },
          {
            "type": "object",
            "required": [
              "data"
            ],
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Subject"
                }
              }
            }
          }
        ]
      },
      "BlockReason": {
        "type": "string",
        "enum": [
          "partner_request",
          "suspected_fraud",
          "account_closed",
          "lost_access",
          "other"
        ]
      },
      "ErasureReceipt": {
        "type": "object",
        "required": [
          "receipt_id",
          "subject_id",
          "signed_receipt",
          "propagation"
        ],
        "properties": {
          "receipt_id": {
            "type": "string",
            "format": "uuid"
          },
          "subject_id": {
            "type": "string",
            "format": "uuid"
          },
          "signed_receipt": {
            "$ref": "#/components/schemas/SignedErasureReceipt"
          },
          "propagation": {
            "type": "object",
            "required": [
              "status",
              "devices_total",
              "devices_acknowledged"
            ],
            "properties": {
              "status": {
                "type": "string",
                "enum": [
                  "pending",
                  "complete"
                ]
              },
              "devices_total": {
                "type": "integer",
                "minimum": 0
              },
              "devices_acknowledged": {
                "type": "integer",
                "minimum": 0
              },
              "fail_closed_at": {
                "description": "Instante em que todo aparelho que ainda não aplicou o tombstone para de reconhecer qualquer pessoa (TTL da galeria).",
                "$ref": "#/components/schemas/Timestamp"
              }
            }
          }
        }
      },
      "SignedErasureReceipt": {
        "description": "Bytes assinados = \"bora.erasure.receipt.v1\" || 0x00 || canonical(receipt), chave da BORA listada em GET /v1/keys.",
        "type": "object",
        "required": [
          "receipt",
          "alg",
          "signer_kid",
          "sig_b64"
        ],
        "properties": {
          "receipt": {
            "type": "object",
            "required": [
              "v",
              "receipt_id",
              "tenant_id",
              "subject_id",
              "requested_at_ms",
              "erased_at_ms",
              "erased",
              "gallery"
            ],
            "properties": {
              "v": {
                "const": 1
              },
              "receipt_id": {
                "type": "string",
                "format": "uuid"
              },
              "tenant_id": {
                "$ref": "#/components/schemas/AsciiRef"
              },
              "subject_id": {
                "type": "string",
                "format": "uuid"
              },
              "requested_at_ms": {
                "$ref": "#/components/schemas/LinkEpochMs"
              },
              "erased_at_ms": {
                "$ref": "#/components/schemas/LinkEpochMs"
              },
              "erased": {
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "templates",
                    "cpf_hmac",
                    "cpf_ciphertext",
                    "external_ref",
                    "onboard_ref",
                    "consents_data",
                    "dataset_samples"
                  ]
                }
              },
              "retained": {
                "description": "Só quando algo fica retido por exceção legal. verdict_proofs = prova assinada das passagens já registradas (signed_verdict com subject_ref e, se havia, onboard_ref), até o fim da retenção de vereditos.",
                "type": "array",
                "items": {
                  "type": "string",
                  "enum": [
                    "verdict_proofs"
                  ]
                }
              },
              "gallery": {
                "type": "object",
                "required": [
                  "stream",
                  "epoch",
                  "seq"
                ],
                "properties": {
                  "stream": {
                    "$ref": "#/components/schemas/AsciiRef"
                  },
                  "epoch": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "seq": {
                    "type": "integer",
                    "minimum": 0
                  }
                }
              }
            }
          },
          "alg": {
            "const": "ed25519"
          },
          "signer_kid": {
            "$ref": "#/components/schemas/LinkHex32"
          },
          "sig_b64": {
            "$ref": "#/components/schemas/LinkEd25519Sig"
          }
        }
      },
      "ConsentPurpose": {
        "description": "Finalidade: `enrollment` (guardar a palma cadastrada), `identification` (reconhecer na catraca) ou `dataset_collection` (coleta opcional para treino). `payment` fica para o v2.",
        "type": "string",
        "enum": [
          "enrollment",
          "identification",
          "dataset_collection"
        ]
      },
      "ConsentGrant": {
        "type": "object",
        "required": [
          "purpose",
          "evidence"
        ],
        "additionalProperties": false,
        "properties": {
          "purpose": {
            "$ref": "#/components/schemas/ConsentPurpose"
          },
          "evidence": {
            "$ref": "#/components/schemas/ConsentEvidence"
          }
        }
      },
      "ConsentEvidence": {
        "type": "object",
        "required": [
          "method",
          "terms_version",
          "accepted_at",
          "evidence_sha256"
        ],
        "properties": {
          "method": {
            "type": "string",
            "enum": [
              "device_screen",
              "partner_app",
              "paper"
            ]
          },
          "terms_version": {
            "$ref": "#/components/schemas/AsciiRef"
          },
          "accepted_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "evidence_sha256": {
            "description": "SHA-256 do artefato de evidência guardado pelo parceiro (termo assinado, log do app). A BORA não recebe o artefato.",
            "$ref": "#/components/schemas/Hex64"
          }
        }
      },
      "Consent": {
        "type": "object",
        "required": [
          "consent_id",
          "subject_id",
          "purpose",
          "status",
          "terms_version",
          "method",
          "granted_at",
          "revoked_at"
        ],
        "properties": {
          "consent_id": {
            "type": "string",
            "format": "uuid"
          },
          "subject_id": {
            "type": "string",
            "format": "uuid"
          },
          "purpose": {
            "$ref": "#/components/schemas/ConsentPurpose"
          },
          "status": {
            "type": "string",
            "enum": [
              "granted",
              "revoked"
            ]
          },
          "terms_version": {
            "$ref": "#/components/schemas/AsciiRef"
          },
          "method": {
            "type": "string",
            "enum": [
              "device_screen",
              "partner_app",
              "paper"
            ]
          },
          "granted_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "revoked_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "EnrollmentSessionCreate": {
        "type": "object",
        "additionalProperties": false,
        "oneOf": [
          {
            "required": [
              "subject_id"
            ]
          },
          {
            "required": [
              "external_ref"
            ]
          }
        ],
        "properties": {
          "subject_id": {
            "type": "string",
            "format": "uuid"
          },
          "external_ref": {
            "$ref": "#/components/schemas/ExternalRef"
          },
          "hands_required": {
            "type": "array",
            "minItems": 1,
            "maxItems": 2,
            "uniqueItems": true,
            "items": {
              "type": "string",
              "enum": [
                "L",
                "R"
              ]
            },
            "default": [
              "L",
              "R"
            ]
          },
          "device_id": {
            "description": "Restringe a sessão a um aparelho. Sem ele, qualquer totem ou BORA ACCESS do tenant que ler o token conclui.",
            "$ref": "#/components/schemas/DeviceId"
          },
          "expires_in_s": {
            "type": "integer",
            "minimum": 60,
            "maximum": 900,
            "default": 300
          },
          "dataset_collection": {
            "description": "Pede também o consentimento separado de coleta para treino (opt-in na tela do totem).",
            "type": "boolean",
            "default": false
          }
        }
      },
      "EnrollmentSessionStatus": {
        "type": "string",
        "enum": [
          "open",
          "in_progress",
          "completed",
          "review",
          "expired",
          "cancelled",
          "failed"
        ]
      },
      "EnrollmentSession": {
        "type": "object",
        "required": [
          "session_id",
          "subject_id",
          "status",
          "hands_required",
          "expires_at",
          "created_at"
        ],
        "properties": {
          "session_id": {
            "type": "string",
            "format": "uuid"
          },
          "subject_id": {
            "type": "string",
            "format": "uuid"
          },
          "status": {
            "$ref": "#/components/schemas/EnrollmentSessionStatus"
          },
          "failure_code": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "capture_rejected",
              "duplicate_rejected",
              null
            ]
          },
          "hands_required": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "L",
                "R"
              ]
            }
          },
          "device_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "completed_by_device_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "enrollment_id": {
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "token": {
            "description": "Segredo de uso único (32 B base64url). Só na resposta do POST.",
            "type": "string",
            "pattern": "^[A-Za-z0-9_-]{43}$",
            "readOnly": true
          },
          "qr_payload": {
            "description": "Conteúdo do QR para o aparelho ler. Não é URL http (não cai em log de navegador nem de proxy). Só na resposta do POST.",
            "type": "string",
            "pattern": "^BORA1:ENR:[0-9a-f-]{36}:[A-Za-z0-9_-]{43}$",
            "readOnly": true
          },
          "short_code": {
            "description": "Código de 8 caracteres para o operador digitar no aparelho sem leitor de QR; o aparelho troca por token em POST /v1/enrollment-sessions/redeem. Uso único, vale até expires_at. Só na resposta do POST.",
            "type": "string",
            "pattern": "^[A-HJ-NP-Z2-9]{8}$",
            "readOnly": true
          },
          "expires_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "created_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "completed_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "DeviceKind": {
        "type": "string",
        "enum": [
          "access",
          "totem"
        ]
      },
      "DeviceStatus": {
        "type": "string",
        "enum": [
          "active",
          "revoked",
          "wiped"
        ]
      },
      "DeviceHealthFlag": {
        "description": "Mesmos nomes do device.status do BORA-LINK/1.",
        "type": "string",
        "x-extensible-enum": true,
        "enum": [
          "SENSOR_MISSING",
          "GALLERY_STALE",
          "KEY_UNATTESTED",
          "CLOCK_UNTRUSTED",
          "PAD_OFF",
          "QUEUE_HIGH",
          "TEMP_HIGH",
          "ADB_ON",
          "SELINUX_PERMISSIVE",
          "SENSOR_CHANGED",
          "USB_FOREIGN",
          "LINK_DOWN",
          "LEASE_EXPIRED"
        ]
      },
      "Device": {
        "type": "object",
        "required": [
          "device_id",
          "kind",
          "status",
          "keys",
          "trust",
          "registered_at",
          "livemode"
        ],
        "properties": {
          "device_id": {
            "$ref": "#/components/schemas/DeviceId"
          },
          "kind": {
            "$ref": "#/components/schemas/DeviceKind"
          },
          "status": {
            "$ref": "#/components/schemas/DeviceStatus"
          },
          "gate_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "dbd_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "app": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "pkg": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "model_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "gallery": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "stream": {
                "type": "string"
              },
              "epoch": {
                "type": "integer"
              },
              "seq": {
                "type": "integer"
              },
              "synced_at": {
                "$ref": "#/components/schemas/Timestamp"
              }
            }
          },
          "keys": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "purpose",
                "alg",
                "kid"
              ],
              "properties": {
                "purpose": {
                  "$ref": "#/components/schemas/DeviceKeyPurpose"
                },
                "alg": {
                  "$ref": "#/components/schemas/DeviceKeyAlg"
                },
                "kid": {
                  "$ref": "#/components/schemas/LinkHex32"
                }
              }
            }
          },
          "trust": {
            "$ref": "#/components/schemas/DeviceTrust"
          },
          "health": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/DeviceHealthFlag"
            }
          },
          "last_seen_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "registered_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "revoked_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "passage_sensor": {
            "description": "A catraca deste aparelho tem sensor de giro (definido no provisionamento). Com sensor, a conciliação espera a passagem assinada (awaiting_passage); sem sensor, acionar já fecha (complete).",
            "type": "boolean"
          },
          "livemode": {
            "type": "boolean"
          }
        }
      },
      "DeviceTrust": {
        "description": "attest_level vem da cadeia de atestação verificada pela BORA, nunca do autodeclarado. none/sw não fecha o achado F2.",
        "type": "object",
        "required": [
          "attest_level",
          "verified"
        ],
        "properties": {
          "attest_level": {
            "type": "string",
            "enum": [
              "none",
              "sw",
              "tee",
              "strongbox"
            ]
          },
          "verified": {
            "type": "boolean"
          }
        }
      },
      "DevicePage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/PageMeta"
          },
          {
            "type": "object",
            "required": [
              "data"
            ],
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/Device"
                }
              }
            }
          }
        ]
      },
      "DeviceRevoke": {
        "type": "object",
        "required": [
          "reason"
        ],
        "additionalProperties": false,
        "properties": {
          "reason": {
            "type": "string",
            "enum": [
              "lost",
              "stolen",
              "decommissioned",
              "compromised",
              "other"
            ]
          }
        }
      },
      "ReconciliationStatus": {
        "description": "complete = veredito, decisão e (se a catraca tem sensor de giro, `passage_sensor` do aparelho) passagem\nconciliados; awaiting_decision = veredito sem decisão do DBD ainda; awaiting_passage = acionou numa catraca\ncom sensor e falta o giro (sem sensor, acionar já dá complete); outcome_unknown = o aparelho ficou em\nOUTCOME_UNKNOWN (decisão perdida); conflict = objetos assinados que não fecham entre si (ex.: decisão\napontando para outro verdict_ref, LIBERAR sem actuated, lacuna de verdict_seq).\n",
        "type": "string",
        "enum": [
          "complete",
          "awaiting_decision",
          "awaiting_passage",
          "outcome_unknown",
          "conflict"
        ]
      },
      "VerdictRecord": {
        "type": "object",
        "required": [
          "verdict_id",
          "txn_id",
          "device_id",
          "gate_id",
          "dbd_id",
          "verdict_seq",
          "decision",
          "result",
          "decided_at",
          "received_at",
          "reconciliation"
        ],
        "properties": {
          "verdict_id": {
            "$ref": "#/components/schemas/LinkHex32"
          },
          "txn_id": {
            "$ref": "#/components/schemas/LinkHex32"
          },
          "device_id": {
            "$ref": "#/components/schemas/DeviceId"
          },
          "gate_id": {
            "$ref": "#/components/schemas/AsciiRef"
          },
          "dbd_id": {
            "$ref": "#/components/schemas/AsciiRef"
          },
          "verdict_seq": {
            "type": "integer",
            "minimum": 1
          },
          "decision": {
            "$ref": "#/components/schemas/LinkDecision"
          },
          "result": {
            "$ref": "#/components/schemas/LinkVerdictResult"
          },
          "subject_id": {
            "description": "Só em accept, resolvido pela BORA a partir do subject_ref.",
            "type": [
              "string",
              "null"
            ],
            "format": "uuid"
          },
          "external_ref": {
            "description": "Só em accept.",
            "type": [
              "string",
              "null"
            ]
          },
          "hand": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "L",
              "R",
              null
            ]
          },
          "pad_res": {
            "type": [
              "string",
              "null"
            ],
            "enum": [
              "pass",
              "fail",
              "off",
              "inconclusive",
              null
            ]
          },
          "quality_q": {
            "type": [
              "integer",
              "null"
            ],
            "minimum": 0,
            "maximum": 10000
          },
          "model_id": {
            "type": "string"
          },
          "decided_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "received_at": {
            "$ref": "#/components/schemas/Timestamp"
          },
          "dbd": {
            "type": [
              "object",
              "null"
            ],
            "required": [
              "reason",
              "outcome",
              "actuated",
              "decision_seq",
              "decided_at"
            ],
            "properties": {
              "reason": {
                "$ref": "#/components/schemas/LinkDecisionReason"
              },
              "outcome": {
                "$ref": "#/components/schemas/LinkDecisionOutcome"
              },
              "actuated": {
                "type": "boolean"
              },
              "decision_seq": {
                "type": "integer",
                "minimum": 0
              },
              "decided_at": {
                "$ref": "#/components/schemas/Timestamp"
              }
            }
          },
          "passage": {
            "type": [
              "object",
              "null"
            ],
            "required": [
              "passed",
              "cause",
              "at"
            ],
            "properties": {
              "passed": {
                "type": "boolean"
              },
              "cause": {
                "type": "string",
                "enum": [
                  "giro",
                  "timeout",
                  "reversao",
                  "forcada"
                ]
              },
              "at": {
                "$ref": "#/components/schemas/Timestamp"
              }
            }
          },
          "reconciliation": {
            "$ref": "#/components/schemas/ReconciliationStatus"
          }
        }
      },
      "VerdictPage": {
        "allOf": [
          {
            "$ref": "#/components/schemas/PageMeta"
          },
          {
            "type": "object",
            "required": [
              "data"
            ],
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/VerdictRecord"
                }
              }
            }
          }
        ]
      },
      "VerdictProof": {
        "type": "object",
        "required": [
          "record",
          "signed_verdict",
          "signed_decision",
          "signed_passage",
          "verification"
        ],
        "properties": {
          "record": {
            "$ref": "#/components/schemas/VerdictRecord"
          },
          "signed_verdict": {
            "$ref": "#/components/schemas/LinkSignedVerdict"
          },
          "signed_decision": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/LinkSignedDecision"
              },
              {
                "type": "null"
              }
            ]
          },
          "signed_passage": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/LinkSignedPassage"
              },
              {
                "type": "null"
              }
            ]
          },
          "verification": {
            "type": "object",
            "required": [
              "verdict_ref",
              "device_verdict_key",
              "prefixes"
            ],
            "properties": {
              "verdict_ref": {
                "description": "hex(sha256(canonical(signed_verdict)))[:32]; tem que ser igual ao verdict_id.",
                "$ref": "#/components/schemas/LinkHex32"
              },
              "device_verdict_key": {
                "type": "object",
                "required": [
                  "kid",
                  "alg",
                  "pub_b64"
                ],
                "properties": {
                  "kid": {
                    "$ref": "#/components/schemas/LinkHex32"
                  },
                  "alg": {
                    "const": "ed25519"
                  },
                  "pub_b64": {
                    "$ref": "#/components/schemas/Ed25519Pub"
                  }
                }
              },
              "dbd_sign_key": {
                "type": [
                  "object",
                  "null"
                ],
                "properties": {
                  "kid": {
                    "$ref": "#/components/schemas/LinkHex32"
                  },
                  "alg": {
                    "const": "ed25519"
                  },
                  "pub_b64": {
                    "$ref": "#/components/schemas/Ed25519Pub"
                  }
                }
              },
              "prefixes": {
                "type": "object",
                "properties": {
                  "verdict": {
                    "const": "bora.gate.verdict.v1"
                  },
                  "decision": {
                    "const": "bora.gate.decision.v1"
                  },
                  "passage": {
                    "const": "bora.gate.passage.v1"
                  }
                }
              }
            }
          }
        }
      },
      "DeviceKeyPurpose": {
        "description": "verdict assina o veredito do cabo; http assina requisições; noise_static é a estática X25519 do canal; identity (v1.1, ES256 no Keystore) assina o link_cert; tls (v1.1) é a chave do certificado mTLS.",
        "type": "string",
        "enum": [
          "verdict",
          "http",
          "noise_static",
          "identity",
          "tls"
        ]
      },
      "DeviceKeyAlg": {
        "type": "string",
        "enum": [
          "ed25519",
          "x25519",
          "es256"
        ]
      },
      "LinkUInt53": {
        "type": "integer",
        "minimum": 0,
        "maximum": 9007199254740991
      },
      "LinkEpochMs": {
        "description": "Instante em epoch ms inteiro, até 9999-12-31T23:59:59.999Z (o maior instante que RFC 3339 representa).",
        "type": "integer",
        "minimum": 0,
        "maximum": 253402300799999
      },
      "LinkQ": {
        "description": "Escala inteira 0..10000 (substitui float; 10000 = 1,0).",
        "type": "integer",
        "minimum": 0,
        "maximum": 10000
      },
      "LinkRef": {
        "description": "Identificador ASCII curto (device_id, gate_id, dbd_id, model_id, thr_id, stream).",
        "type": "string",
        "pattern": "^[A-Za-z0-9._:-]{1,64}$"
      },
      "LinkHex32": {
        "description": "Hash curto: 16 bytes em 32 hex minúsculos (txn_id, verdict_ref, prev_ref, subject_ref, kid, *16).",
        "type": "string",
        "pattern": "^[0-9a-f]{32}$"
      },
      "LinkNonce16": {
        "description": "Nonce de 16 bytes em base64 padrão (24 caracteres).",
        "type": "string",
        "pattern": "^[A-Za-z0-9+/]{22}==$"
      },
      "LinkEd25519Sig": {
        "description": "Assinatura Ed25519 de 64 bytes em base64 padrão (88 caracteres). Verificação estrita: S < L e ponto canônico.",
        "type": "string",
        "pattern": "^[A-Za-z0-9+/]{86}==$"
      },
      "LinkMsgId": {
        "description": "id do envelope: começa em 1 a cada sessão e cresce por emissor (nunca repete na sessão, nem no reenvio). re = id do req respondido.",
        "type": "integer",
        "minimum": 1,
        "maximum": 9007199254740991
      },
      "LinkHex64": {
        "description": "SHA-256 inteiro em 64 hex minúsculos (integridade de arquivo e de registro selado).",
        "type": "string",
        "pattern": "^[0-9a-f]{64}$"
      },
      "LinkB64": {
        "description": "Base64 padrão com padding.",
        "type": "string",
        "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"
      },
      "LinkSignerCertB64": {
        "description": "Certificado de 104 B de uma chave emissora BORA pela raiz, no formato do prelúdio do trust.bundle (7.6): signer_pub(32) | signer_not_after u64 BE | root_sig(64). O prefixo do root_sig separa a finalidade: \"bora.bundle.signer.v1\" para a chave de bundle (7.6) e \"bora.post.signer.v1\" para a chave do carteiro, que assina manifesto de file.* e registro selado box in (4.8.10); root_sig sobre prefixo || 0x00 || signer_pub || not_after. Em base64 (140 caracteres).",
        "type": "string",
        "pattern": "^[A-Za-z0-9+/]{139}=$"
      },
      "LinkDecision": {
        "description": "Decisão de identidade do BORA ACCESS.",
        "type": "string",
        "enum": [
          "accept",
          "reject",
          "abstain"
        ]
      },
      "LinkVerdictResult": {
        "description": "Motivo do veredito do BORA ACCESS (seção 4.5). Coerência com decision: MATCH só com accept; NO_MATCH, LIVENESS_FAIL e NOT_ENROLLED só com reject; o resto só com abstain. Nem a luz do aparelho nem o visor do DBD distinguem LIVENESS_FAIL de NO_MATCH.",
        "type": "string",
        "enum": [
          "MATCH",
          "NO_MATCH",
          "LIVENESS_FAIL",
          "NOT_ENROLLED",
          "AMBIGUOUS",
          "LOW_QUALITY",
          "TIMEOUT",
          "CANCELLED",
          "RATE_LIMITED",
          "BIOMETRIC_DISABLED",
          "GALLERY_STALE",
          "MODEL_MISMATCH",
          "DEVICE_NOT_READY"
        ]
      },
      "LinkDecisionReason": {
        "description": "Motivo da checagem do DBD sobre o veredito (vocabulário do DbdCore do David mais os novos do v1). device_unknown, device_untrusted e backend_unreachable não ocorrem no v1 (DBD sem backend). Da v1.1 (passo 4 da regra de acionamento, trust.bundle): bundle_expired (DBD em NO_TRUST: sem bundle ou vencido além da graça), device_killed (identidade revogada no bundle), kid_unknown (identidade não pinada), pin_expired, attest_below_min, proto_below_min, app_below_min e gallery_below_min; toda recusa do passo 4 sai com outcome USAR_OUTRO_MEIO.",
        "type": "string",
        "enum": [
          "ok",
          "malformed",
          "kid_unknown",
          "kid_mismatch",
          "device_killed",
          "bad_signature",
          "nonce_unknown",
          "nonce_reused",
          "nonce_expired",
          "gate_mismatch",
          "clock_skew",
          "bundle_expired",
          "result_incoherent",
          "cert_mismatch",
          "seq_rollback",
          "pin_expired",
          "attest_below_min",
          "proto_below_min",
          "app_below_min",
          "gallery_below_min"
        ]
      },
      "LinkDecisionOutcome": {
        "description": "Decisão de PERMISSÃO do DBD (saldo, bloqueio, categoria, antipassback, política offline). Valores em português herdados do BORA-LINK/1, mantidos para casar com o DBD.",
        "type": "string",
        "enum": [
          "LIBERAR",
          "REJEITAR_SALDO",
          "REJEITAR_BLOQUEADO",
          "REJEITAR_CATEGORIA",
          "REJEITAR_ANTIPASSBACK",
          "USAR_OUTRO_MEIO",
          "FALHA_TECNICA",
          "NAO_AVALIADO"
        ]
      },
      "LinkGalleryPos": {
        "description": "Versão da base local usada no 1:N.",
        "type": "object",
        "required": [
          "stream",
          "epoch",
          "seq",
          "head16"
        ],
        "properties": {
          "stream": {
            "$ref": "#/components/schemas/LinkRef"
          },
          "epoch": {
            "$ref": "#/components/schemas/LinkUInt53"
          },
          "seq": {
            "$ref": "#/components/schemas/LinkUInt53"
          },
          "head16": {
            "$ref": "#/components/schemas/LinkHex32"
          }
        }
      },
      "LinkPad": {
        "description": "Evidência de liveness (PAD) da captura.",
        "type": "object",
        "required": [
          "res"
        ],
        "properties": {
          "res": {
            "type": "string",
            "enum": [
              "pass",
              "fail",
              "off",
              "inconclusive"
            ]
          },
          "mech": {
            "type": "string",
            "pattern": "^[A-Za-z0-9._:+/=-]{1,24}$"
          },
          "score_q": {
            "$ref": "#/components/schemas/LinkQ"
          }
        }
      },
      "LinkVerdict": {
        "description": "GateVerdict v1: o que o BORA ACCESS assina. Bytes assinados = \"bora.gate.verdict.v1\" || 0x00 || canonical(verdict).",
        "type": "object",
        "required": [
          "v",
          "txn_id",
          "gate_id",
          "dbd_id",
          "nonce_b64",
          "issued_at_ms",
          "ttl_ms",
          "decided_at_ms",
          "device_id",
          "decision",
          "result",
          "verdict_seq",
          "prev_ref",
          "model_id",
          "thr_id",
          "gallery"
        ],
        "properties": {
          "v": {
            "const": 1
          },
          "txn_id": {
            "$ref": "#/components/schemas/LinkHex32"
          },
          "gate_id": {
            "$ref": "#/components/schemas/LinkRef"
          },
          "dbd_id": {
            "$ref": "#/components/schemas/LinkRef"
          },
          "nonce_b64": {
            "$ref": "#/components/schemas/LinkNonce16"
          },
          "issued_at_ms": {
            "$ref": "#/components/schemas/LinkEpochMs"
          },
          "ttl_ms": {
            "type": "integer",
            "minimum": 2000,
            "maximum": 10000
          },
          "decided_at_ms": {
            "$ref": "#/components/schemas/LinkEpochMs",
            "description": "issued_at_ms + (monotônico agora - monotônico no recebimento do desafio). Base de tempo do DBD."
          },
          "device_id": {
            "$ref": "#/components/schemas/LinkRef"
          },
          "decision": {
            "$ref": "#/components/schemas/LinkDecision"
          },
          "result": {
            "$ref": "#/components/schemas/LinkVerdictResult"
          },
          "verdict_seq": {
            "description": "Contador global persistido, sem lacuna, inclui reject e abstain; escopo (device_id, verdict_kid).",
            "type": "integer",
            "minimum": 1,
            "maximum": 9007199254740991
          },
          "prev_ref": {
            "$ref": "#/components/schemas/LinkHex32",
            "description": "verdict_ref do veredito anterior (32 zeros no primeiro)."
          },
          "subject_ref": {
            "$ref": "#/components/schemas/LinkHex32",
            "description": "Só em accept: HMAC-SHA256(k_tenant, subject_id)[:16] em hex, calculado na nuvem e entregue pronto na galeria. Nunca derivado do CPF."
          },
          "onboard_ref": {
            "description": "Só em accept, opcional: token opaco do operador (no API: subjects.onboard_ref).",
            "type": "string",
            "pattern": "^[A-Za-z0-9._:+/=-]{1,128}$"
          },
          "hand": {
            "type": "string",
            "enum": [
              "L",
              "R"
            ]
          },
          "score_q": {
            "$ref": "#/components/schemas/LinkQ"
          },
          "margin_q": {
            "$ref": "#/components/schemas/LinkQ"
          },
          "quality_q": {
            "$ref": "#/components/schemas/LinkQ"
          },
          "pad": {
            "$ref": "#/components/schemas/LinkPad"
          },
          "attempts": {
            "type": "integer",
            "minimum": 1,
            "maximum": 255
          },
          "model_id": {
            "$ref": "#/components/schemas/LinkRef"
          },
          "thr_id": {
            "$ref": "#/components/schemas/LinkRef"
          },
          "gallery": {
            "$ref": "#/components/schemas/LinkGalleryPos"
          },
          "bundle_seq": {
            "$ref": "#/components/schemas/LinkUInt53",
            "description": "v1.1."
          },
          "cert_ref": {
            "$ref": "#/components/schemas/LinkHex32",
            "description": "v1.1: hash do link_cert da sessão."
          },
          "reasons": {
            "type": "array",
            "maxItems": 8,
            "items": {
              "type": "string",
              "pattern": "^[A-Za-z0-9._:+/=-]{1,64}$"
            }
          }
        },
        "allOf": [
          {
            "if": {
              "properties": {
                "decision": {
                  "const": "accept"
                }
              },
              "required": [
                "decision"
              ]
            },
            "then": {
              "required": [
                "subject_ref"
              ],
              "properties": {
                "result": {
                  "const": "MATCH"
                }
              }
            }
          },
          {
            "if": {
              "properties": {
                "decision": {
                  "const": "reject"
                }
              },
              "required": [
                "decision"
              ]
            },
            "then": {
              "properties": {
                "result": {
                  "enum": [
                    "NO_MATCH",
                    "LIVENESS_FAIL",
                    "NOT_ENROLLED"
                  ]
                }
              },
              "not": {
                "anyOf": [
                  {
                    "required": [
                      "subject_ref"
                    ]
                  },
                  {
                    "required": [
                      "onboard_ref"
                    ]
                  }
                ]
              }
            }
          },
          {
            "if": {
              "properties": {
                "decision": {
                  "const": "abstain"
                }
              },
              "required": [
                "decision"
              ]
            },
            "then": {
              "properties": {
                "result": {
                  "enum": [
                    "AMBIGUOUS",
                    "LOW_QUALITY",
                    "TIMEOUT",
                    "CANCELLED",
                    "RATE_LIMITED",
                    "BIOMETRIC_DISABLED",
                    "GALLERY_STALE",
                    "MODEL_MISMATCH",
                    "DEVICE_NOT_READY"
                  ]
                }
              },
              "not": {
                "anyOf": [
                  {
                    "required": [
                      "subject_ref"
                    ]
                  },
                  {
                    "required": [
                      "onboard_ref"
                    ]
                  }
                ]
              }
            }
          }
        ]
      },
      "LinkSignedVerdict": {
        "description": "Veredito assinado. verdict_ref = hex(sha256(canonical(SignedVerdict)))[:32].",
        "type": "object",
        "required": [
          "verdict",
          "alg",
          "signer_kid",
          "sig_b64"
        ],
        "properties": {
          "verdict": {
            "$ref": "#/components/schemas/LinkVerdict"
          },
          "alg": {
            "const": "ed25519"
          },
          "signer_kid": {
            "$ref": "#/components/schemas/LinkHex32"
          },
          "sig_b64": {
            "$ref": "#/components/schemas/LinkEd25519Sig"
          }
        }
      },
      "LinkDecisionObj": {
        "description": "Decisão do DBD amarrada ao veredito exato. Bytes assinados = \"bora.gate.decision.v1\" || 0x00 || canonical(decision_obj).",
        "type": "object",
        "required": [
          "v",
          "txn_id",
          "gate_id",
          "dbd_id",
          "nonce_b64",
          "verdict_ref",
          "reason",
          "outcome",
          "actuated",
          "decision_seq",
          "decided_at_ms"
        ],
        "properties": {
          "v": {
            "const": 1
          },
          "txn_id": {
            "$ref": "#/components/schemas/LinkHex32"
          },
          "gate_id": {
            "$ref": "#/components/schemas/LinkRef"
          },
          "dbd_id": {
            "$ref": "#/components/schemas/LinkRef"
          },
          "nonce_b64": {
            "$ref": "#/components/schemas/LinkNonce16"
          },
          "verdict_ref": {
            "$ref": "#/components/schemas/LinkHex32"
          },
          "reason": {
            "$ref": "#/components/schemas/LinkDecisionReason"
          },
          "outcome": {
            "$ref": "#/components/schemas/LinkDecisionOutcome"
          },
          "actuated": {
            "type": "boolean"
          },
          "decision_seq": {
            "$ref": "#/components/schemas/LinkUInt53"
          },
          "decided_at_ms": {
            "$ref": "#/components/schemas/LinkEpochMs"
          }
        },
        "if": {
          "properties": {
            "actuated": {
              "const": true
            }
          },
          "required": [
            "actuated"
          ]
        },
        "then": {
          "properties": {
            "reason": {
              "const": "ok"
            },
            "outcome": {
              "const": "LIBERAR"
            }
          }
        }
      },
      "LinkSignedDecision": {
        "type": "object",
        "required": [
          "decision_obj",
          "alg",
          "signer_kid",
          "sig_b64"
        ],
        "properties": {
          "decision_obj": {
            "$ref": "#/components/schemas/LinkDecisionObj"
          },
          "alg": {
            "const": "ed25519"
          },
          "signer_kid": {
            "$ref": "#/components/schemas/LinkHex32"
          },
          "sig_b64": {
            "$ref": "#/components/schemas/LinkEd25519Sig"
          }
        }
      },
      "LinkPassage": {
        "description": "Confirmação de giro da catraca. Bytes assinados = \"bora.gate.passage.v1\" || 0x00 || canonical(passage).",
        "type": "object",
        "required": [
          "v",
          "txn_id",
          "dbd_id",
          "gate_id",
          "verdict_ref",
          "passed",
          "cause",
          "at_ms",
          "dbd_event_seq"
        ],
        "properties": {
          "v": {
            "const": 1
          },
          "txn_id": {
            "$ref": "#/components/schemas/LinkHex32"
          },
          "dbd_id": {
            "$ref": "#/components/schemas/LinkRef"
          },
          "gate_id": {
            "$ref": "#/components/schemas/LinkRef"
          },
          "verdict_ref": {
            "$ref": "#/components/schemas/LinkHex32"
          },
          "passed": {
            "type": "boolean"
          },
          "cause": {
            "type": "string",
            "enum": [
              "giro",
              "timeout",
              "reversao",
              "forcada"
            ]
          },
          "at_ms": {
            "$ref": "#/components/schemas/LinkEpochMs"
          },
          "dbd_event_seq": {
            "$ref": "#/components/schemas/LinkUInt53"
          }
        }
      },
      "LinkSignedPassage": {
        "type": "object",
        "required": [
          "passage",
          "alg",
          "signer_kid",
          "sig_b64"
        ],
        "properties": {
          "passage": {
            "$ref": "#/components/schemas/LinkPassage"
          },
          "alg": {
            "const": "ed25519"
          },
          "signer_kid": {
            "$ref": "#/components/schemas/LinkHex32"
          },
          "sig_b64": {
            "$ref": "#/components/schemas/LinkEd25519Sig"
          }
        }
      },
      "LinkSealedRecord": {
        "description": "Registro do carteiro (4.8.10). box in: da nuvem BORA para um BORA ACCESS, pelo BDOS e pelo DBD, em file.* com kind post.in. box out: do A para a nuvem BORA, pelo fluxo post.out (até 1472 B de ct) ou file.* kind post.out, e o DBD repassa ao BDOS. O DBD carrega sem abrir e sem saber o que é: o kind vai DENTRO do texto cifrado (PostPlain); por fora só v, rid, box, src, dst, seq, created_ms, suite, ct_len e ct_sha256. ct = enc(32) || ciphertext || tag(16) do HPKE (RFC 9180, modo base, suite em post.suite) para a chave de selo do destinatário, info \"bora.post.v1\", aad = canonical(post sem ct_len e ct_sha256); ct_sha256 = sha256 dos bytes de ct decodificados. Bytes assinados = (\"bora.post.in.v1\" pela chave do carteiro, com signer_cert_b64, ou \"bora.post.out.v1\" pela chave de veredito do A) || 0x00 || canonical(post). seq por (box, src, dst): na entrada, igual a um já aplicado ou abaixo do último aplicado = 430 post.rejected; lacuna = os seguintes esperam numa janela de 64 e o frescor da galeria não é renovado até a lacuna fechar (fail-closed). O DBD consegue atrasar ou sumir com registros (vira GALLERY_STALE), nunca abrir, forjar, escolher pelo tipo nem reordenar. O exemplo NÃO é vetor de HPKE (o ct é de enchimento).",
        "type": "object",
        "required": [
          "post",
          "ct_b64",
          "alg",
          "signer_kid",
          "sig_b64"
        ],
        "properties": {
          "post": {
            "type": "object",
            "required": [
              "v",
              "rid",
              "box",
              "src",
              "dst",
              "seq",
              "created_ms",
              "suite",
              "ct_len",
              "ct_sha256"
            ],
            "properties": {
              "v": {
                "const": 1
              },
              "rid": {
                "$ref": "#/components/schemas/LinkHex32"
              },
              "box": {
                "type": "string",
                "enum": [
                  "in",
                  "out"
                ]
              },
              "src": {
                "$ref": "#/components/schemas/LinkRef"
              },
              "dst": {
                "$ref": "#/components/schemas/LinkRef"
              },
              "seq": {
                "$ref": "#/components/schemas/LinkMsgId"
              },
              "created_ms": {
                "$ref": "#/components/schemas/LinkEpochMs"
              },
              "suite": {
                "type": "string",
                "enum": [
                  "hpke-x25519-sha256-chacha20poly1305"
                ]
              },
              "ct_len": {
                "type": "integer",
                "minimum": 48,
                "maximum": 67108864
              },
              "ct_sha256": {
                "$ref": "#/components/schemas/LinkHex64"
              }
            }
          },
          "ct_b64": {
            "$ref": "#/components/schemas/LinkB64"
          },
          "alg": {
            "const": "ed25519"
          },
          "signer_kid": {
            "$ref": "#/components/schemas/LinkHex32"
          },
          "sig_b64": {
            "$ref": "#/components/schemas/LinkEd25519Sig"
          },
          "signer_cert_b64": {
            "$ref": "#/components/schemas/LinkSignerCertB64"
          }
        },
        "allOf": [
          {
            "if": {
              "required": [
                "post"
              ],
              "properties": {
                "post": {
                  "required": [
                    "box"
                  ],
                  "properties": {
                    "box": {
                      "const": "in"
                    }
                  }
                }
              }
            },
            "then": {
              "required": [
                "signer_cert_b64"
              ],
              "properties": {
                "post": {
                  "properties": {
                    "src": {
                      "const": "bora"
                    }
                  }
                }
              }
            }
          },
          {
            "if": {
              "required": [
                "post"
              ],
              "properties": {
                "post": {
                  "required": [
                    "box"
                  ],
                  "properties": {
                    "box": {
                      "const": "out"
                    }
                  }
                }
              }
            },
            "then": {
              "not": {
                "required": [
                  "signer_cert_b64"
                ]
              },
              "properties": {
                "post": {
                  "properties": {
                    "dst": {
                      "const": "bora"
                    }
                  }
                }
              }
            }
          }
        ],
        "examples": [
          {
            "post": {
              "v": 1,
              "rid": "c41f2a9be07d4d3f9a6e5b2c1d0e8f7a",
              "box": "in",
              "src": "bora",
              "dst": "access-bh-eldorado-03",
              "seq": 88,
              "created_ms": 1790849000000,
              "suite": "hpke-x25519-sha256-chacha20poly1305",
              "ct_len": 144,
              "ct_sha256": "7d8bbc540bbbfc01881f4becb42f2ff14c72d372a889bf04e3e0a07019e365fc"
            },
            "ct_b64": "TAc0sssnInErGpzmvTRKQb1f5wNinoQEfZvKHfG8DrjbuN1sZ3oAIPAOl1u/UG3lbMMpi9l756LtnMyruTrLn9PYmK5g1C7F3rI3xTWKOR5sbbVg+L2Z6V7MNLDnKKqxiPclJu5KxrYKxErFd1yleZcuCnC4aWnex4JcyE+D3UupqQN8hyyjLD4mJWsuIWBo",
            "alg": "ed25519",
            "signer_kid": "d9bf8bfe11bc109cb5687c77a5bf6581",
            "sig_b64": "3rt1LWthsu8S4Qr4eGPNGTmfqMda3mm1/YzeaSjKdbsDLNsUOhxj0jkDcCpKJIZYiZUOTKhl6drZF61PH1ZzDg==",
            "signer_cert_b64": "kvCBJCkO7mgC+XHfZDDByN6Nkz2+zpLxXeQBnT3vemEAAAGixmd6QBQuCyvnDKjwbNqTrEAThAEsCj79FV04k648hrD4XcsbBS9kg8rvOZ6GUMWK38vKc0BIqjHSvQ8MeJ9UXLkoeAw="
          }
        ]
      }
    },
    "examples": {
      "SubjectPending": {
        "value": {
          "subject_id": "3f6c2a9e-8b1d-4e7a-9c3f-5d2e1a0b7c64",
          "external_ref": "MBH-000482913",
          "subject_ref": "2a16ce69bc964deda2b740bfe43edf4b",
          "onboard_ref": "obr-7Q2m9X",
          "status": "pending_enrollment",
          "block": null,
          "enrollment": null,
          "consents": [],
          "kyc": {
            "cpf_on_file": true
          },
          "gallery_seq": null,
          "created_at": "2026-10-01T09:55:00.000Z",
          "updated_at": "2026-10-01T09:55:00.000Z",
          "livemode": true
        }
      },
      "SubjectActive": {
        "value": {
          "subject_id": "3f6c2a9e-8b1d-4e7a-9c3f-5d2e1a0b7c64",
          "external_ref": "MBH-000482913",
          "subject_ref": "2a16ce69bc964deda2b740bfe43edf4b",
          "onboard_ref": "obr-7Q2m9X",
          "status": "active",
          "block": null,
          "enrollment": {
            "hands": [
              "L",
              "R"
            ],
            "model_id": "deptrum-onnx-2026.09",
            "enrolled_at": "2026-10-01T10:02:41.120Z"
          },
          "consents": [
            {
              "purpose": "enrollment",
              "status": "granted"
            },
            {
              "purpose": "identification",
              "status": "granted"
            }
          ],
          "kyc": {
            "cpf_on_file": true
          },
          "gallery_seq": 15873,
          "created_at": "2026-10-01T09:55:00.000Z",
          "updated_at": "2026-10-01T10:02:41.120Z",
          "livemode": true
        }
      },
      "ConsentGranted": {
        "value": {
          "consent_id": "6e1d2c3b-4a59-4f68-8a7b-9c0d1e2f3a4b",
          "subject_id": "3f6c2a9e-8b1d-4e7a-9c3f-5d2e1a0b7c64",
          "purpose": "identification",
          "status": "granted",
          "terms_version": "termos-bora-transport-2026-10",
          "method": "partner_app",
          "granted_at": "2026-10-01T09:58:12.000Z",
          "revoked_at": null
        }
      },
      "ErasureReceipt": {
        "value": {
          "receipt_id": "c0a8f2d4-1b3e-4f5a-8c7d-9e0f1a2b3c4d",
          "subject_id": "3f6c2a9e-8b1d-4e7a-9c3f-5d2e1a0b7c64",
          "signed_receipt": {
            "receipt": {
              "v": 1,
              "receipt_id": "c0a8f2d4-1b3e-4f5a-8c7d-9e0f1a2b3c4d",
              "tenant_id": "tnt-metro-bh",
              "subject_id": "3f6c2a9e-8b1d-4e7a-9c3f-5d2e1a0b7c64",
              "requested_at_ms": 1790853600000,
              "erased_at_ms": 1790853600120,
              "erased": [
                "templates",
                "cpf_hmac",
                "cpf_ciphertext",
                "external_ref",
                "onboard_ref"
              ],
              "gallery": {
                "stream": "main",
                "epoch": 4,
                "seq": 15901
              }
            },
            "alg": "ed25519",
            "signer_kid": "abb9ff726ba8ffb31638d59e7fcfb820",
            "sig_b64": "qr+/q4EU9D99x0ne4JPlwxemRgrnSSAh1WQcQidnsIfXjl6VlJJIhR5KvbYJGmc3tAqy6Y14GmgmSM7bVae1CQ=="
          },
          "propagation": {
            "status": "pending",
            "devices_total": 12,
            "devices_acknowledged": 9,
            "fail_closed_at": "2026-10-01T17:20:00.120Z"
          }
        }
      },
      "EnrollmentSessionOpen": {
        "value": {
          "session_id": "51d3e9a2-7c4b-4f1e-9a8d-2b3c4d5e6f70",
          "subject_id": "3f6c2a9e-8b1d-4e7a-9c3f-5d2e1a0b7c64",
          "status": "open",
          "failure_code": null,
          "hands_required": [
            "L",
            "R"
          ],
          "device_id": null,
          "completed_by_device_id": null,
          "enrollment_id": null,
          "token": "kJ3n9Qx2Lm8Vb7Rt5Yp1Zc4Wd6Fh0Gs2Aa9Ee3Ii7Oo",
          "qr_payload": "BORA1:ENR:51d3e9a2-7c4b-4f1e-9a8d-2b3c4d5e6f70:kJ3n9Qx2Lm8Vb7Rt5Yp1Zc4Wd6Fh0Gs2Aa9Ee3Ii7Oo",
          "short_code": "K7M2Q9XA",
          "expires_at": "2026-10-01T10:05:00.000Z",
          "created_at": "2026-10-01T10:00:00.000Z",
          "completed_at": null
        }
      },
      "EnrollmentSessionCompleted": {
        "value": {
          "session_id": "51d3e9a2-7c4b-4f1e-9a8d-2b3c4d5e6f70",
          "subject_id": "3f6c2a9e-8b1d-4e7a-9c3f-5d2e1a0b7c64",
          "status": "completed",
          "failure_code": null,
          "hands_required": [
            "L",
            "R"
          ],
          "device_id": null,
          "completed_by_device_id": "totem-bh-central-01",
          "enrollment_id": "9b2f4c1e-7a3d-4e8b-a1c2-3d4e5f6a7b8c",
          "expires_at": "2026-10-01T10:05:00.000Z",
          "created_at": "2026-10-01T10:00:00.000Z",
          "completed_at": "2026-10-01T10:02:41.120Z"
        }
      },
      "VerdictProof": {
        "value": {
          "record": {
            "verdict_id": "bae244c9d453584320e97cf6b06fb432",
            "txn_id": "7f3c9a1e5b2d4c6f8a0b1c2d3e4f5a6b",
            "device_id": "access-bh-eldorado-03",
            "gate_id": "bh-eldorado-cat-03",
            "dbd_id": "dbd-bh-eldorado-03",
            "verdict_seq": 1042,
            "decision": "accept",
            "result": "MATCH",
            "subject_id": "3f6c2a9e-8b1d-4e7a-9c3f-5d2e1a0b7c64",
            "external_ref": "MBH-000482913",
            "hand": "R",
            "pad_res": "pass",
            "quality_q": 9120,
            "model_id": "deptrum-onnx-2026.09",
            "decided_at": "2026-10-01T10:20:00.840Z",
            "received_at": "2026-10-01T10:20:03.112Z",
            "dbd": {
              "reason": "ok",
              "outcome": "LIBERAR",
              "actuated": true,
              "decision_seq": 88123,
              "decided_at": "2026-10-01T10:20:00.861Z"
            },
            "passage": {
              "passed": true,
              "cause": "giro",
              "at": "2026-10-01T10:20:02.400Z"
            },
            "reconciliation": "complete"
          },
          "signed_verdict": {
            "verdict": {
              "v": 1,
              "txn_id": "7f3c9a1e5b2d4c6f8a0b1c2d3e4f5a6b",
              "gate_id": "bh-eldorado-cat-03",
              "dbd_id": "dbd-bh-eldorado-03",
              "nonce_b64": "nj8VYyTULw6ktvT86B1W+w==",
              "issued_at_ms": 1790850000000,
              "ttl_ms": 5000,
              "decided_at_ms": 1790850000840,
              "device_id": "access-bh-eldorado-03",
              "decision": "accept",
              "result": "MATCH",
              "verdict_seq": 1042,
              "prev_ref": "be1ccf680c02a5ca3847db9540093045",
              "subject_ref": "2a16ce69bc964deda2b740bfe43edf4b",
              "onboard_ref": "obr-7Q2m9X",
              "hand": "R",
              "score_q": 8712,
              "margin_q": 2104,
              "quality_q": 9120,
              "pad": {
                "res": "pass",
                "mech": "ir-depth-v1",
                "score_q": 9650
              },
              "attempts": 1,
              "model_id": "deptrum-onnx-2026.09",
              "thr_id": "thr-2026-09-a",
              "gallery": {
                "stream": "main",
                "epoch": 3,
                "seq": 15872,
                "head16": "9f2e6d33a3717ee826353a404ba4618d"
              }
            },
            "alg": "ed25519",
            "signer_kid": "300290aeb182952c1337b227be5fe728",
            "sig_b64": "U7SHmogLJ+JjGP4QcyMxSqscfiDUMB08y0potQvGdp/0HjnGdtl8JvmZA9nafAdhp0PtTv/6nkTNW0y4iF/dBg=="
          },
          "signed_decision": {
            "decision_obj": {
              "v": 1,
              "txn_id": "7f3c9a1e5b2d4c6f8a0b1c2d3e4f5a6b",
              "gate_id": "bh-eldorado-cat-03",
              "dbd_id": "dbd-bh-eldorado-03",
              "nonce_b64": "nj8VYyTULw6ktvT86B1W+w==",
              "verdict_ref": "bae244c9d453584320e97cf6b06fb432",
              "reason": "ok",
              "outcome": "LIBERAR",
              "actuated": true,
              "decision_seq": 88123,
              "decided_at_ms": 1790850000861
            },
            "alg": "ed25519",
            "signer_kid": "4678808aef484c079515f89dbe4e1ef3",
            "sig_b64": "JgbRq9m69X6O36Ys/Xn8amTrXYl6SJHK2PO8ERYeMVVOrwW1qWNwJMHIGT9832/4kax6+nxogBFSUQMMAJgXAg=="
          },
          "signed_passage": {
            "passage": {
              "v": 1,
              "txn_id": "7f3c9a1e5b2d4c6f8a0b1c2d3e4f5a6b",
              "dbd_id": "dbd-bh-eldorado-03",
              "gate_id": "bh-eldorado-cat-03",
              "verdict_ref": "bae244c9d453584320e97cf6b06fb432",
              "passed": true,
              "cause": "giro",
              "at_ms": 1790850002400,
              "dbd_event_seq": 401220
            },
            "alg": "ed25519",
            "signer_kid": "4678808aef484c079515f89dbe4e1ef3",
            "sig_b64": "0mOVxqp5SWykiWKAvKOoUKKH7juWTSwQVoY40oRoZY4UqVT13S3iecxPNcFHjPV5m2D/ceCUP+j6+tdeZj20Cg=="
          },
          "verification": {
            "verdict_ref": "bae244c9d453584320e97cf6b06fb432",
            "device_verdict_key": {
              "kid": "300290aeb182952c1337b227be5fe728",
              "alg": "ed25519",
              "pub_b64": "0mZcYF+l54oAZ/8dAsbliiXUbumVlpIjXGc8EDb6qO0="
            },
            "dbd_sign_key": {
              "kid": "4678808aef484c079515f89dbe4e1ef3",
              "alg": "ed25519",
              "pub_b64": "/EorC2SHripynSbtWpO3y0kvagTLyjyo+9rKeg/+YGs="
            },
            "prefixes": {
              "verdict": "bora.gate.verdict.v1",
              "decision": "bora.gate.decision.v1",
              "passage": "bora.gate.passage.v1"
            }
          }
        }
      }
    }
  }
}
