Skip to content

Procedência e citações

A procedência é o fosso competitivo do Futuros. Qualquer um pode exibir números; o raro é que cada número remonte a um registro de fonte primária específico em dois cliques, e que o sistema falhe na compilação se não conseguir. Este documento explica a maquinaria que sustenta esse contrato. Ele serve tanto ao Pilar 1 — Fundo Fiduciário de Dados (a procedência é o que torna o corpus verificável) quanto ao Pilar 2 — Modelo Soberano (os fatos vivem nas citações, nunca assados nos pesos).

O contrato de dois cliques

Todo número em tela carrega sua citação no próprio número: um sublinhado leve, não um chip [WB] depois da cifra. Um clique abre a referência (título, editor, ano); um segundo clique leva você ao registro exato da fonte — o país e o indicador precisos, não uma landing genérica. Essa especificidade é uma regra de build: o gate check-source-links faz o build falhar se um link aponta para uma fonte genérica em vez do registro país + indicador.

A exceção é explícita, não tácita: o próprio gate carrega uma lista LANDING_OK de fontes cujas citações resolvem legitimamente para uma página de landing ou de metodologia — camadas curadas e internas (gov-, event-, calc-, agg-, idx-), camadas documentais (EXA, GDELT, RSS, diários oficiais, sinais) e umas poucas fontes sem URL por registro (benchmarks da OCDE, IDEA, UNODC, V-Dem, FSI, INFORM, IMF PortWatch, FAOSTAT) — cada uma com sua justificativa comentada no código. É um opt-out consciente e auditável, não um buraco: tudo o que não está nessa lista deve carregar deep link ou o build não compila. Se um dado não pode ser rastreado assim, não é publicado como valor.

Duas redes a mais fecham as brechas. GENERIC_URLS enumera páginas "genéricas de dataset" que diferem da raiz só por um path ou um fragmento (o dashboard do FSI, o formulário de busca vazio do USGS…): uma citação não isenta sobre uma delas é violação igual a uma landing nua. E os agregados regionais (-latam, -world, -subregion, -oecd no id) ficam isentos porque não existe um registro país+indicador para uma média supranacional. O desenho é fail-closed: uma fonte nova sem template de deep link cai para sua url_root e o build morre no prebuild; a mensagem de erro imprime as duas saídas válidas — escrever a url_template e rodar fix-source-deeplinks.ts, ou documentar a isenção em LANDING_OK com justificativa de uma linha.

Convenções de citation_id

O registro central de citações é public/data/citations.json15.098 registros com a forma {id, source, title, url, retrieved_at, year}. As células de dados e os componentes apontam para um registro por esse id (o campo que as células chamam de citation_id). O id carrega um prefixo que codifica sua origem: wb- (Banco Mundial, o mais numeroso), oecd-, who-, gov- (fonte governamental), event-, web- (busca web externa), etc.; corr- (correlação) existe como convenção reservada no código, hoje sem citações vivas. O prefixo não é cosmético: é o que permite resolver uma citação até sua fonte mesmo que a citação não esteja no registro em memória (ver reconstrução sintética).

A gramática do id é mecânica, e por isso parseável: <prefixo>-<geo>-<ano>, consumida da direita para a esquerda por parseMultiId() — se o último token são 4 dígitos, é o ano; se o seguinte é um ISO3 em minúsculas (ou latam, a média regional derivada pelo Futuros), é a geografia; tudo o que sobra é o prefixo. extractYear() aplica a mesma convenção com a regex -(\d{4})(?:[-_]|$). Exemplo real do registro: wb-si-pov-gini-arg-2024 → fonte WB, indicador SI.POV.GINI, Argentina, 2024.

O registro de fontes

src/lib/source-registry.ts mapeia mais de 200 SourceKey (acrônimos como WB, WHO, IMF) para seu SourceMeta: acrônimo, nome completo, agência, jurisdição, raiz de URL, template de URL, cadência, metodologia (com variantes _en / _pt), tier e licença. As peças-chave:

  • inferSourceKey() resolve um citation_id até sua fonte pelo prefixo.
  • deepLinkFor() constrói o link para o registro específico.
  • 43 funções url_template reconstroem o deep link por indicador e por país a partir do id sozinho — ou seja, dado um citation_id, o sistema pode regenerar a URL exata da fonte sem depender de que alguém a tenha salvado à mão.

É isso que garante o segundo clique do contrato: o deep link não é armazenado, é derivado, e por isso não pode ficar desatualizado em relação ao id. Dois detalhes do resolvedor importam na prática:

  • A ordem dos prefixos é semântica. inferSourceKey() é uma cadeia de regras startsWith em que vence a primeira coincidência, então os prefixos mais longos vêm antes (mepyd- deve preceder mep-; o comentário no código avisa isso). Os bancos centrais ilustram a disciplina de nomes: bcb- é o Brasil, bcbol- a Bolívia, bch- Honduras, bcch- o Chile, bccr- a Costa Rica — tokens únicos e terminados em hífen para que nenhum sombreie outro. Um prefixo não mapeado devolve UNKNOWN, que deliberadamente não está isento no gate de deep links: um prefixo novo sem registrar é uma regressão, não um caso permitido.
  • A licença viaja na fonte. SourceMeta.license (open, cc-by, non-commercial, share-alike, cite-only; ausente ⇒ aberta/permissiva) controla o bake: uma fonte cite-only pode ser citada sem redistribuir seus valores.

Marcadores CiteRef

src/components/citations/CiteRef.tsx é a âncora de citação de toda a plataforma: o número ou o sintagma citado é o link, com um sublinhado leve. Não há chips [CEPAL] / [INEC] / [WB] depois da cifra. Ao passar o cursor (ou ao focar / tocar) mostra o mesmo popover de sempre (título, editor, ano); ao clicar leva à fonte externa. Se um trecho tem várias fontes, o popover as lista. A resolução segue esta ordem:

  1. Registro de citações em memória (citations.json).
  2. Se não estiver lá, reconstrução sintética a partir do registro de fontes.

Há um terceiro estado, deliberado: o modo strict. As superfícies que sabem que suas citações foram registradas (por exemplo, a página de um indicador) passam strict; ali, um id que não resolve é renderizado como um marcador solto e sem link, em vez de fabricar para ele um título, uma URL ou um vintage sintéticos. É o contrapeso exato de syntheticCitation(): a reconstrução existe para embeds que nunca carregaram o registro, nunca para maquiar um id quebrado onde o registro estava disponível. A condição é dupla por design: um marcador só é considerado dangling quando há um registro montado na página e o chamador passou strict — um miss simples numa superfície que nunca registra (embeds, chat, mini-cards) é normal e cai para a sintética. E quando um id resolve para fonte mas não para uma URL externa útil, o clique não navega para lugar nenhum morto: abre a gaveta SourceTrace com a metodologia. Cada clique sobre um marcador emite ainda o evento de telemetria source_click com {citação, fonte, ano} — o uso da procedência também é medido.

Ao redor do CiteRef vivem CitationChip (um invólucro que exige o texto a sublinhar), CitationDrawer e SourceTrace (uma gaveta de respaldo com metodologia e o log de falsificações). A marca de evidência externa não é um componente à parte: vive dentro do próprio CiteRef, que pinta o sublinhado em ouro tracejado quando o citation_id leva o prefixo web-. O percurso de ponta a ponta é: valor gerado no bake → citation_idCiteRef → registro → deep link.

Reconstrução sintética para embeds

As superfícies embutíveis (/embed/stat, /embed/chart, /embed/board) nem sempre carregam o registro completo de citações — pesaria demais. Para isso existe syntheticCitation(): reconstrói a citação a partir do citation_id e do registro de fontes (prefixo → SourceKeyurl_template). Resultado: um card embutido num site de terceiros conserva sua citação e seu deep link, sem carregar os megabytes do registro. A procedência viaja com o dado, não com a página.

Três invariantes de honestidade na sintética: devolve null se o prefixo resolve para UNKNOWN — nunca inventa uma instituição; retrieved_at fica vazio — não fabrica uma data de recuperação que não ocorreu; e o ano só é incluído se for derivável do próprio id.

Badging de citações web externas

Nem todo fato vem do corpus gerado no bake. Quando o assistente usa busca web como último recurso (ver O assistente), essas citações carregam o prefixo web- e são marcadas visivelmente como externas: o sublinhado da cifra é ouro e tracejado, e o cartão de hover antepõe a etiqueta de dado não verificado. A razão é honestidade: um fato trazido da web aberta nunca deve se confundir com um dado do corpus verificado. O badging separa as duas classes de evidência na própria interface, para que o leitor saiba sempre quão firme é o piso sob cada número.

Log de falsificações

public/data/falsifications.json é o registro de afirmações que foram postas à prova — o reverso de "cada citação é uma fonte": cada falsificação é um compromisso auditável de que a plataforma corrige o que se mostra insustentável. SourceTrace o expõe junto à metodologia da fonte. É parte do contrato de honestidade detalhado em Metodologia e honestidade.


Em resumo, a procedência no Futuros é derivável, não prometida: o deep link é reconstruído do id, a citação sintética viaja até o embed, e o build se recusa a compilar se algum link fora do opt-out documentado (LANDING_OK) aponta para uma fonte genérica. Siga para O assistente para ver como o chat herda essa mesma disciplina — cada figura ancorada a um [[cite:id]]. E para a próxima fronteira — de procedência derivável a procedência criptograficamente verificável por terceiros — ver o roadmap técnico de otimização.

Cada número com sua fonte — a rastreabilidade é o contrato.