|
| 1 | +# Enderecos de Sede dos Bancos (headquarters_address) |
| 2 | + |
| 3 | +## 1. Contexto e objetivo |
| 4 | + |
| 5 | +Este documento descreve a implementacao do enriquecimento de endereco da sede para o endpoint de bancos, incluindo: |
| 6 | + |
| 7 | +- enriquecimento em camadas com fontes externas |
| 8 | +- regras de confianca dos dados |
| 9 | +- resiliencia para nao quebrar o endpoint |
| 10 | +- geracao de snapshots versionados |
| 11 | +- automacao periodica via GitHub Actions |
| 12 | +- metricas operacionais (cobertura, novos nulos e conflitos) |
| 13 | + |
| 14 | +Implementacao pensada para manter compatibilidade retroativa: os campos antigos seguem existindo e os novos campos sao opcionais. |
| 15 | + |
| 16 | +--- |
| 17 | + |
| 18 | +## 2. Campos adicionados no payload de bancos |
| 19 | + |
| 20 | +Cada banco passou a poder retornar os campos abaixo: |
| 21 | + |
| 22 | +- `cnpj`: string ou `null` |
| 23 | +- `headquarters_address`: objeto ou `null` |
| 24 | +- `address_source`: string ou `null` |
| 25 | +- `address_last_sync`: datetime ISO-8601 |
| 26 | +- `address_confidence`: `high | medium | low | none` |
| 27 | + |
| 28 | +Estrutura de `headquarters_address`: |
| 29 | + |
| 30 | +- `street` |
| 31 | +- `number` |
| 32 | +- `complement` |
| 33 | +- `district` |
| 34 | +- `city` |
| 35 | +- `state` |
| 36 | +- `zipCode` |
| 37 | + |
| 38 | +Todos os campos internos de `headquarters_address` podem ser `string` ou `null`. |
| 39 | + |
| 40 | +--- |
| 41 | + |
| 42 | +## 3. Fontes de dados utilizadas |
| 43 | + |
| 44 | +### 3.1 Fonte base de bancos |
| 45 | + |
| 46 | +- CSV oficial de participantes STR (BCB) |
| 47 | +- URL: `https://www.bcb.gov.br/content/estabilidadefinanceira/str1/ParticipantesSTR.csv` |
| 48 | + |
| 49 | +### 3.2 Fonte primaria de enderecos (BCB OData) |
| 50 | + |
| 51 | +Colecoes consultadas: |
| 52 | + |
| 53 | +- `SedesBancoComMultCE` |
| 54 | +- `SedesCooperativas` |
| 55 | +- `SedesSociedades` |
| 56 | +- `SedesConsorcios` |
| 57 | + |
| 58 | +Todas no servico: |
| 59 | + |
| 60 | +- `https://olinda.bcb.gov.br/olinda/servico/Instituicoes_em_funcionamento/versao/v1/odata/` |
| 61 | + |
| 62 | +### 3.3 Fonte secundaria de enderecos por CNPJ |
| 63 | + |
| 64 | +- API: `https://minhareceita.org/{cnpj}` |
| 65 | +- usada para bancos sem endereco apos etapa BCB, quando houver CNPJ valido (14 digitos) |
| 66 | + |
| 67 | +--- |
| 68 | + |
| 69 | +## 4. Regras de matching e confianca |
| 70 | + |
| 71 | +### 4.1 Normalizacao de texto |
| 72 | + |
| 73 | +Antes de comparar nomes: |
| 74 | + |
| 75 | +- remove acentos |
| 76 | +- transforma em uppercase |
| 77 | +- remove caracteres nao alfanumericos |
| 78 | +- compacta espacos |
| 79 | + |
| 80 | +### 4.2 Ordem de matching |
| 81 | + |
| 82 | +1. `bcb_sedes_exact_match` por nome normalizado (`fullName`) |
| 83 | +2. `bcb_sedes_exact_match` por nome normalizado (`name`) |
| 84 | +3. `name_based_match` (fuzzy unico por inclusao de string) |
| 85 | +4. sem match |
| 86 | + |
| 87 | +### 4.3 Regra de confianca |
| 88 | + |
| 89 | +- `bcb_sedes_exact_match` -> `high` |
| 90 | +- `cnpj_exact_match` -> `medium` |
| 91 | +- `name_based_match` -> `low` |
| 92 | +- sem match -> `none` |
| 93 | + |
| 94 | +### 4.4 Regra de CNPJ |
| 95 | + |
| 96 | +CNPJ so e considerado valido quando possui 14 digitos. |
| 97 | + |
| 98 | +- CNPJ com tamanho diferente de 14 e descartado (`null`) |
| 99 | +- essa regra evita usar raiz de CNPJ (8 digitos) como se fosse CNPJ completo |
| 100 | + |
| 101 | +--- |
| 102 | + |
| 103 | +## 5. Comportamento de resiliencia no endpoint |
| 104 | + |
| 105 | +Implementado no servico de bancos para evitar indisponibilidade ou regressao forte de dados. |
| 106 | + |
| 107 | +### 5.1 Cache em memoria (runtime) |
| 108 | + |
| 109 | +- TTL de 6 horas |
| 110 | +- evita reprocessamento pesado a cada requisicao |
| 111 | + |
| 112 | +### 5.2 Fallback de snapshot local |
| 113 | + |
| 114 | +Se houver falha na coleta da base STR ou falha geral no enriquecimento: |
| 115 | + |
| 116 | +- usa `services/banco-central/snapshots/latest.json`, quando disponivel |
| 117 | +- caso contrario, usa fallback estatico local (`banksList.json`) |
| 118 | + |
| 119 | +### 5.3 Guardrail de cobertura |
| 120 | + |
| 121 | +Se o enriquecimento atual vier com cobertura zerada e o snapshot anterior tiver cobertura positiva: |
| 122 | + |
| 123 | +- mantem snapshot anterior como resposta |
| 124 | +- evita regressao brusca para clientes |
| 125 | + |
| 126 | +--- |
| 127 | + |
| 128 | +## 6. Snapshot versionado e metricas |
| 129 | + |
| 130 | +### 6.1 Script de geracao |
| 131 | + |
| 132 | +Arquivo: |
| 133 | + |
| 134 | +- `scripts/generate-bank-headquarters-snapshot.js` |
| 135 | + |
| 136 | +Comando: |
| 137 | + |
| 138 | +- `npm run snapshot:banks` |
| 139 | + |
| 140 | +### 6.2 Arquivos gerados |
| 141 | + |
| 142 | +Diretorio: |
| 143 | + |
| 144 | +- `services/banco-central/snapshots/` |
| 145 | + |
| 146 | +Arquivos: |
| 147 | + |
| 148 | +- `banks-headquarters-<run-id>.json` (historico versionado) |
| 149 | +- `latest.json` (snapshot promovido para producao) |
| 150 | +- `metrics-latest.json` (metricas da ultima execucao) |
| 151 | + |
| 152 | +### 6.3 Regras de promocao de latest |
| 153 | + |
| 154 | +O script sempre gera snapshot versionado, mas so promove para `latest.json` quando: |
| 155 | + |
| 156 | +- existe cobertura (`with_address > 0`) |
| 157 | +- cobertura atual respeita guardrail minimo: |
| 158 | + - se houver historico: cobertura atual >= 80% da cobertura anterior |
| 159 | + - sem historico: cobertura minima absoluta de 20% |
| 160 | + |
| 161 | +Se nao passar no guardrail: |
| 162 | + |
| 163 | +- `latest.json` anterior e preservado |
| 164 | +- metrica registra fallback com motivo `coverage_guardrail` |
| 165 | + |
| 166 | +### 6.4 Metricas emitidas |
| 167 | + |
| 168 | +Em `metrics-latest.json`: |
| 169 | + |
| 170 | +- `totals.banks` |
| 171 | +- `totals.with_address` |
| 172 | +- `totals.without_address` |
| 173 | +- `totals.coverage_total` |
| 174 | +- `deltas.new_nulls` |
| 175 | +- `deltas.recovered_addresses` |
| 176 | +- `conflicts.count` |
| 177 | +- `sources.bcb_failed_sources` |
| 178 | +- `sources.cnpj_lookup_candidates` |
| 179 | +- `sources.cnpj_failed_lookups` |
| 180 | + |
| 181 | +#### Definicao de conflito |
| 182 | + |
| 183 | +Conflito = mesmo nome normalizado com fontes de endereco diferentes (`address_source` distintos) no conjunto final. |
| 184 | + |
| 185 | +--- |
| 186 | + |
| 187 | +## 7. Automacao periodica (GitHub Actions) |
| 188 | + |
| 189 | +Workflow: |
| 190 | + |
| 191 | +- `.github/workflows/banks-headquarters-snapshot.yml` |
| 192 | + |
| 193 | +Triggers: |
| 194 | + |
| 195 | +- agendado semanalmente (`cron: 0 6 * * 1`) |
| 196 | +- execucao manual (`workflow_dispatch`) |
| 197 | + |
| 198 | +Fluxo: |
| 199 | + |
| 200 | +1. checkout do repositorio |
| 201 | +2. setup Node 20 |
| 202 | +3. cache/install de dependencias |
| 203 | +4. execucao de `npm run snapshot:banks` |
| 204 | +5. upload de artefatos JSON |
| 205 | +6. commit/push de snapshots alterados |
| 206 | + |
| 207 | +Permissao necessaria: |
| 208 | + |
| 209 | +- `contents: write` |
| 210 | + |
| 211 | +--- |
| 212 | + |
| 213 | +## 8. Compatibilidade e contrato de API |
| 214 | + |
| 215 | +- campos antigos foram mantidos |
| 216 | +- novos campos sao opcionais |
| 217 | +- quando nao houver dado confiavel, retorno deve ser `null` (nao erro) |
| 218 | +- endpoint continua respondendo mesmo com falha parcial/total de fontes externas |
| 219 | + |
| 220 | +--- |
| 221 | + |
| 222 | +## 9. Observacoes importantes do estado atual |
| 223 | + |
| 224 | +1. O pipeline esta ativo e funcional localmente. |
| 225 | +2. Quantidade atual de enderecos obtidos (metrics-latest): |
| 226 | + - total de bancos processados: 480 |
| 227 | + - bancos com endereco: 458 |
| 228 | + - bancos sem endereco: 22 |
| 229 | + - cobertura total: 95,42% |
| 230 | +3. `cnpj_lookup_candidates` pode ficar em zero dependendo da disponibilidade/formato de CNPJ vindo do matching BCB. |
| 231 | +4. Mesmo com falha de fontes externas, o endpoint nao deve quebrar por causa do fallback em `latest.json`. |
| 232 | + |
| 233 | +--- |
| 234 | + |
| 235 | +## 10. Arquivos envolvidos |
| 236 | + |
| 237 | +Implementacao principal: |
| 238 | + |
| 239 | +- `services/banco-central/index.js` |
| 240 | +- `scripts/generate-bank-headquarters-snapshot.js` |
| 241 | +- `.github/workflows/banks-headquarters-snapshot.yml` |
| 242 | +- `package.json` |
| 243 | + |
| 244 | +Dados gerados: |
| 245 | + |
| 246 | +- `services/banco-central/snapshots/latest.json` |
| 247 | +- `services/banco-central/snapshots/metrics-latest.json` |
| 248 | +- `services/banco-central/snapshots/banks-headquarters-<run-id>.json` |
| 249 | + |
| 250 | +Testes/documentacao relacionados: |
| 251 | + |
| 252 | +- `tests/banks-v1.test.js` |
| 253 | +- `pages/docs/doc/bank.json` |
| 254 | + |
| 255 | +--- |
| 256 | + |
| 257 | +## 11. Execucao manual (operacao) |
| 258 | + |
| 259 | +Para rodar localmente: |
| 260 | + |
| 261 | +```bash |
| 262 | +npm run snapshot:banks |
| 263 | +``` |
| 264 | + |
| 265 | +Para verificar resultados: |
| 266 | + |
| 267 | +- abrir `services/banco-central/snapshots/metrics-latest.json` |
| 268 | +- confirmar se `fallback.used_previous_snapshot` e `false` para promocao normal |
| 269 | +- validar `totals.coverage_total`, `deltas.new_nulls` e `conflicts.count` |
| 270 | + |
| 271 | +--- |
| 272 | + |
| 273 | +## 12. Decisao sobre historico |
| 274 | + |
| 275 | +No momento, o historico versionado e mantido sem politica de retencao automatica. |
| 276 | +A retencao pode ser adicionada futuramente, mas foi explicitamente deixada fora desta etapa. |
0 commit comments