Arquitetura de produção
O Sombra nasce com a topologia definitiva e reduz inicialmente o volume. O snapshot CNPJ normalizado é um adaptador inicial; a publicação usa os mesmos contratos, idempotência, lotes, snapshots e índices previstos para uma fonte integral.
flowchart LR
IBGE["IBGE · CNAE 2.3"] --> W["Worker de ingestão"]
RFB["Receita Federal · CNPJ"] --> W
P["Documentos de patente"] --> W
W --> B["Blob raw / curated"]
W --> QI["Fila de ingestão"]
W --> QM["Fila de cruzamento"]
W --> SQL["Azure SQL · fonte canônica"]
W --> IDX["AI Search · índice por geração + alias"]
IDX -. indisponível .-> SQL
S["Sombra Angular · público"] --> API["API Functions + autorização por rota"]
F["Safari Angular + Lapis External ID"] --> API
API --> SQL
API --> IDX
API --> QI
API --> QM
Componentes
| Componente | Responsabilidade | Produção inicial |
|---|---|---|
| Web App | hospedar os dois builds Angular por hostname | plano seniorprev existente |
| API Functions | consultas, comandos e fronteira de autorização | .NET isolado, processo único |
| Worker Functions | CNAE, CNPJ, PDF, índices e cruzamentos | uma execução por tipo de carga |
| Azure SQL | estado canônico, execuções e auditoria | Basic DTU |
| Storage | arquivos brutos/curados, resultados e filas | Standard LRS dedicado |
| AI Search | recuperação textual e publicação atômica por alias | Free, com fallback SQL |
| Entra External ID | login e access tokens exclusivos do Safari | tenant Lapis dedicado |
Não há Application Insights neste release. Execuções persistem no SQL estado,
tentativas, contagens, erro e artefatos; snapshots publicados são imutáveis. API
e worker emitem logs estruturados no filesystem para diagnóstico imediato e as
categorias FunctionAppLogs e AppServiceAuthenticationLogs são arquivadas no
Storage por 30 dias. A API expõe liveness e readiness; o worker expõe liveness.
O estado operacional não depende da retenção desses logs.
A readiness exige que o bootstrap da edição CNAE, do snapshot CNPJ e da política de cobertura configurados já tenha sido concluído. Uma publicação administrativa posterior pelo Safari pode se tornar a geração corrente sem invalidar essa base; a API então confere a geração corrente e sua contagem exata no Search.
O CNPJ de entrada usa um blob imutável por conteúdo. Uma carga grava no SQL um
snapshot de publicação identificado pelo runId, constrói um índice físico
novo no Search e só então troca o alias consultado pela API. O runId só passa
a Completed depois da promoção. Enquanto isso, a API filtra pelo último
snapshot concluído e recorre ao SQL se o alias já tiver avançado; assim uma
falha intermediária não expõe dados parciais. Uma repetição conclui a mesma
geração idempotentemente. Índices aposentados são removidos sem apagar o índice
ainda apontado pelo alias.
Ingestão (ingestion-commands) e cruzamento (matching-commands) usam filas e
leases independentes. Há no máximo uma carga
de cada tipo em execução, mas uma análise de patente não fica bloqueada por uma
carga longa do catálogo CNAE.
Cada cruzamento concluído também grava um artefato JSON imutável de rastreabilidade. A trilha registra a versão do matcher, a edição CNAE, a publicação de receptores, os termos técnicos normalizados, as atividades inferidas ou explícitas e a evidência individual de cada candidato. A API reassocia essa evidência ao resultado persistido; o Sombra a apresenta ao abrir um possível comprador. Assim a explicação usa o mesmo snapshot e os mesmos sinais que produziram o ranking, sem recalcular o passado com uma versão futura do motor.
Disponibilidade e custo
O plano seniorprev é P0v3 com uma instância e não oferece alta disponibilidade
regional. O worker inicia com streaming, concorrência unitária por tipo de carga
e limites rígidos porque o plano já apresentou picos de memória. SQL Basic
mantém a fonte canônica com baixo custo; Search Free pode ser removido e
reconstruído sem perda de dados. Receptores são persistidos em lotes e o
documento do índice é lido do SQL como stream, sem materializar toda a
publicação no worker.
Uma segunda instância do plano é o primeiro passo quando memória sustentada ultrapassar 75–80%, sem mudança nos contratos de ingestão. A configuração atual, com uma única instância, aceita indisponibilidade durante reinícios e não deve ser descrita como alta disponibilidade.
Segurança
- apenas HTTPS/TLS 1.2; FTPS desativado;
- Safari usa Authorization Code + PKCE e não contém segredos; Sombra não carrega biblioteca, guardas, callback ou configuração de autenticação;
- Easy Auth aceita a entrada anônima necessária ao Sombra e valida tokens do
tenant
Lapis; cada função aplica a política de autorização correspondente; - criação e leitura de análise pública exigem uma chave anônima aleatória do navegador, armazenada no backend apenas como hash e isolada por visitante;
- o bootstrap administrativo reconhece os e-mails verificados configurados no backend e também permite migrar para papéis do aplicativo;
- o backend também entende
Safari.Reader,Safari.OperatoreSafari.Adminquando esses papéis estiverem presentes no token; - leituras operacionais aceitam uma identidade de leitura ou administrativa; mutações exigem identidade administrativa;
- Functions acessam Storage e Search por identidade gerenciada;
- a conexão SQL fica no Key Vault e é resolvida por referência do App Service;
- blobs não têm acesso público e possuem retenção/versão curta.