Consultation request
A consumer posts a consultation with the borrower document, the client type, and a range of reference dates. The request also declares the holder’s authorization under LC 105/2001. That declaration is a required flag, and the consent record stays with the institution. The call is synchronous. The decoded result arrives in the response body of the same request, and there is no create-then-poll flow. The response carries an identifier for a later re-read. BACEN charges per client and per reference date, so a narrow range costs less. A consumer that retries a request sends an idempotency key, and the retry pays no second tariff.
Credential resolution and channel protections
Lerian SCR resolves the institution’s channel credential before it opens the circuit breaker path. A credential failure is a local failure, and a vault outage never trips the channel breaker. The adapter then issues an HTTPS
GET to BACEN’s /wsscr2n/cliente/resumo operation and sets HTTP Basic on the request. The channel authenticates the server only, through the host system certificate pool, with TLS 1.2 as the floor and no client certificate.
Three guards stand in front of the call, in this order. Single-flight coalescing merges identical concurrent consultations into one upstream call. A per-institution circuit breaker then decides whether the call proceeds. Inside the breaker, a semaphore caps concurrent connections at two per institution. By default, the breaker trips after five consecutive failures, or after a failure ratio of 0.5 over at least ten requests. It then cools down for 30 seconds.
Only a transport failure or a BACEN platform error trips the breaker. A “no position” answer and a client-side rejection do not. An open breaker returns SCR-1002 at once and contacts no upstream.
Result cache and tariff
Lerian SCR reads a Redis cache before it calls BACEN. The cache holds one entry per reference month under the key
scr:pos:{tenantID}:{blindIndexHex}:{AAAAMM}. The institution comes first, and the borrower appears only as a blind index. Each value carries the same AES-256-GCM at-rest envelope as the audit row.
A full hit skips the BACEN call and the tariff, and it still audits and emits. A partial hit fetches only the missing months. A request that asks for fresh data skips the read and pays the tariff.
By default an entry for the current month lives four hours, and an entry for a closed month lives 720 hours. A month that BACEN omits becomes a no-position marker, so a repeat of the same range does not pay for that month again.
An unreadable entry counts as a miss. A deployment without Redis misses every time. A cache write is best-effort and never fails a consultation.
Decoding
BACEN answers with codes for modality, funding source, indexer, currency variation, creditor segment, guarantee type, additional-information type, and client type. Lerian SCR resolves each code against the SCR annex tables, which ship inside the service, and returns a
{ code, description } pair.
An unknown code keeps the code, returns a null description, and increments an unknown-code metric. It never fails the consultation. An empty code returns an empty code with no description and fires no metric.
The decoder reads domain codes only. It never sees the borrower document.
Audit and events
Every terminal outcome writes one audit row. The row and its outbox event commit in one transaction, so no consultation leaves without its trail. A failed write fails the consultation with
SCR-9001, a retryable 503. The consumer never receives an un-audited credit position. The row keeps its personal data under AES-256-GCM encryption and an HMAC-SHA256 blind index, with two independent keys.
The outbox carries two event types: studio.lerian.br-scr.consulta.completed for a served consultation, and studio.lerian.br-scr.consulta.failed for a failed one. The dispatcher publishes both on the topic lerian.streaming.br-scr, with lerian.streaming.br-scr.dlq for poison messages.
An operator can turn emission off. The rows then stay pending in the outbox and ship once a broker is available.
