Skip to content

Pilar 1 — Fundo Fiduciário de Dados

A tese. Construir o fundo fiduciário de dados da região: uma infraestrutura de contribuição em que instituições, empresas e pessoas aportam dados sob consentimento granular e revogável, recebem um recibo de procedência verificável e se tornam partes interessadas de primeira classe. Direitos, não propriedade. Compensação imediata em reputação, não promessas diferidas.

Este é o primeiro pilar do ciclo dos quatro pilares: o corpus com procedência é o único ativo que torna possível um modelo soberano que ninguém mais pode replicar.

Por que um fundo fiduciário e não uma compra de dados

Comprar ou raspar dados produz um corpus sem consentimento, sem licença clara e sem ninguém investido na sua qualidade. Um fundo fiduciário inverte a relação: o contribuinte é parte interessada, não fornecedor. Recebe um recibo verificável na hora, vê exatamente por que sua contribuição valeu o que valeu e conserva o direito de revogar. O ativo que cresce não é uma tabela — é uma rede de contribuintes com incentivo para que os dados sejam bons.

Como funciona /contribuir, de ponta a ponta

A superfície ao vivo é /contribuir. O formulário do cliente (src/routes/contribuir.tsx) envia a promessa à função POST /api/contribute, um transporte fino sobre um núcleo puro e coberto por testes (server/trust/ledger.ts). O fluxo, de ponta a ponta:

1. Validação com trava de consentimento

validateContribution() normaliza o corpo não confiável — nunca lança exceção — e rejeita toda promessa sem consentimento explícito: se consent !== true, a contribuição não é criada. Valida o email por regex, exige título (3–160 caracteres) e descrição (10–1.200), e filtra as geografias contra o conjunto canônico de 27 ISO3 da região (LATAM_ISO3), deduplicadas e com teto — um ledger de procedência não admite códigos de país lixo. Os pilares passam por regex de slug ([a-z0-9-], teto 12); um idioma não reconhecido cai para es.

2. Pontuação com uma rubrica transparente

scoreContribution() atribui pontos com uma rubrica determinística e explicada — não um Shapley opaco (seu custo combinatório foi descartado no lançamento). Os pontos se decompõem em: base (20; +8 de bônus se a promessa é explicitamente regional, com geografias vazias), cobertura geográfica (3 por ISO3, teto 30), amplitude de pilares (3 por pilar, teto 12), abertura da licença (open 15 · cc-by 12 · share-alike 9 · non-commercial 5 · cite-only 2) e modo de privacidade (aberto, sala limpa e computação privada 10 igualmente; apenas-agregados 7). A decomposição (points_breakdown) viaja no recibo, para que o contribuinte veja exatamente por que ganhou o que ganhou.

A privacidade é premiada, não penalizada

Uma contribuição que preserva a privacidade (sala limpa ou computação privada) desbloqueia dados que de outro modo não poderiam ser compartilhados — por isso é recompensada no mesmo nível dos dados brutos abertos, não abaixo. É o princípio de "computar sem possuir": o valor sem a exposição.

3. Recibo de procedência verificável por hash, pronto para blockchain

makeReceipt() emite um Receipt cujo nível de garantia depende de um interruptor de ambiente, e o próprio recibo declara qual recebeu em seu campo version:

  • v1 — verificável por hash (padrão). O receipt_hash prova integridade do conteúdo, não autenticidade do emissor; a prova de emissão é a presença do recibo no ledger do servidor.
  • v2 — assinado pelo emissor. Com TRUST_RECEIPT_HMAC_KEY configurada, o recibo passa a version: 2 e acrescenta sig_alg: "hmac-sha256" mais signature = HMAC-SHA256(chave, receipt_hash). Isso autentica o emissor, mas não é verificável por terceiros: verificar exige a chave secreta.

A verificabilidade pública por terceiros precisa de uma assinatura Ed25519 sobre o corpo canônico, e segue no roadmap — ver Proveniência avançada. Suas propriedades verificáveis:

  • O email nunca é armazenado. O registro público carrega um contributor_id pseudônimo — um hash do email com sal. O mesmo email produz o mesmo id, mas o email bruto não é recuperável nem jamais entra no ledger persistente. Um pré-requisito operacional sustenta essa irreversibilidade: TRUST_ID_SALT deve ser configurada com um valor secreto, porque o sal de reserva incluído no código é público, e com um sal público o id deixa de ser irreversível diante de quem testar emails candidatos. O recibo também estampa um salt_version público, para que uma rotação de sal nunca quebre a revogabilidade (ver abaixo).
  • O recibo é reproduzível. O receipt_hash é um SHA-256 sobre o corpo canônico (chaves ordenadas recursivamente com stableStringify), de modo que o mesmo valor lógico sempre produz o mesmo digest. Qualquer um pode recomputar o hash a partir das entradas e verificá-lo.
  • Pronto para blockchain por construção. O esquema mapeia 1:1 para uma atestação on-chain futura: contributor_id, contribution_id e receipt_hash são as colunas dessa atestação, e chain_anchor é o slot reservado para o hash de transação quando chegar a liquidação on-chain (fase posterior). Hoje: chain_ready: true, chain_anchor: null — pronto fora da cadeia.

Anatomia exata do Receipt (interface em server/trust/ledger.ts):

CampoDerivação
receipt_hashSHA-256 hex sobre o corpo canônico — todos os demais campos, com chaves ordenadas.
contribution_idd_ + 24 hex: hash de (contributor_id, título, descrição, geografias, pilares, licença, privacidade, issuedAt, nonce UUID). Único por promessa.
contributor_idc_ + 24 hex: sha256(sal + ":" + email). Estável, pseudônimo, irreversível.
points / points_breakdownTotal + decomposição {base, coverage, breadth, license, privacy}.
corpus_postureO que a licença permite no corpus (o gate de licença, estampado de antemão).
salt_versions_ + 12 hex: etiqueta pública de qual sal produziu o id — um hash unidirecional que nada revela do sal.
issued_at / versionISO-8601 de emissão · versão de esquema: 1 (só hash) ou 2 (assinado pelo emissor com HMAC).
chain_ready / chain_anchortrue · null (slot reservado ao tx hash).

Os campos declarativos (tier, dataset_title, geographies, pillars, license, privacy, indigenous_data) viajam tal como foram validados. makeReceipt() é determinístico dadas (promessa, issuedAt, nonce, sal): o mesmo insumo sempre produz o mesmo recibo — a base da verificação independente.

4. Registro append-only e honestidade quando não está configurado

O ledger é append-only: server/trust/store.ts faz RPUSH no Upstash Redis via REST (comandos como arrays JSON com fetch puro, sem dependência npm). Um recibo nunca é mutado. Se o Upstash não está configurado, a função é honesta: devolve o recibo com persisted: false em vez de fingir persistência. O append é resiliente sem deixar de ser honesto: é retentado com backoff limitado (3 tentativas, 100·n ms) antes de degradar para persisted: false, e as leituras pulam linhas corrompidas em vez de derrubar o registro.

A disposição de chaves no Redis separa fonte de verdade de otimizações:

ChaveEstruturaPapel
trust:ledger:v1LISTFonte de verdade append-only (RPUSH / LRANGE).
trust:revocations:v1LISTTombstones, em lista irmã — cada lista é mono-tipo, a leitura tipada nunca confunde uma linha.
trust:ledger:index:v1HASH id→registroBusca O(1) para revogar (HGET); best-effort — se falha, o append não falha.
trust:revocations:index:v1SETRevogação idempotente: SADD = 0 → já revogada, no-op.
trust:ledger:dedupe:v1SETChaves de dedupe de promessas.

O ledger também se defende sozinho:

  • Dedupe de promessas idênticas. A chave é endereçada por conteúdo: dk_ + 32 hex do hash de {contributor_id com sal, título, descrição} — nunca contém o email bruto. Duas promessas idênticas colapsam em uma linha via SADD; o contribuinte ainda assim recebe um recibo válido, com a nota de que não houve duplicação. E o dedupe falha aberto (fail-open): um erro do store devolve fresh: true — um tropeço do Redis jamais bloqueia uma contribuição genuína.
  • Limite de taxa e de corpo. POST /api/contribute aceita 10 solicitações/minuto por IP e um corpo de no máximo 64 KB com guarda em duas etapas (rejeição imediata por Content-Length e contagem de bytes durante a leitura contra um Content-Length mentiroso); os índices e sets do Redis têm teto de crescimento (500.000 entradas) — passado o teto, deixa-se de indexar, mas a lista e a varredura seguem funcionando.
  • Registro público com janela honesta. GET /api/contribute publica agregados sobre uma janela limitada de 500 registros, rotulada como tal (stats.window {limit, complete}), e a lista pública omite deliberadamente o contribution_id — assim uma revogação não pode ser forjada de fora, nem o mapeamento email→registro confirmado.

5. Revogação por tombstone

O consentimento foi prometido revogável; api/revoke.ts é o mecanismo. makeRevocation() escreve um tombstone append-only que computeStats subtrai no momento da leitura — o recibo original permanece no ledger para sempre (pronto para blockchain, nunca mutado), mas a contribuição fica excluída dos agregados e da lista pública. A propriedade é provada recomputando o contributor_id com sal a partir do email (matchingSalt, do qual verifyRevocation é o invólucro): como o email bruto nunca foi guardado, só quem controla esse email pode provar controle da contribuição.

Duas garantias de engenharia sustentam a promessa:

  • A rotação de sal não quebra a revogação. A ordem de resolução é precisa (saltCandidates + matchingSalt em ledger.ts): os sais candidatos são o TRUST_ID_SALT vigente, depois cada entrada separada por vírgulas de TRUST_ID_SALT_PREVIOUS, com o sal padrão do código como reserva. Se o registro traz salt_version estampado, busca-se o candidato cuja etiqueta coincide e somente esse deve reproduzir o contributor_id — uma versão desconhecida falha de forma segura (não se pode provar propriedade). Um registro legado sem estampa testa cada candidato diretamente.
  • A revogação é O(1) e idempotente. Um índice HSET (contribution_id → registro) resolve a busca com um HGET sem varrer o ledger completo — com uma varredura completa única como reserva para registros legados anteriores ao índice — e um índice de revogações (SADD) converte revogar duas vezes em um no-op barato. O endpoint valida a forma do id (d_ + 24 hex) antes de tocar o store, e responde 404 se a contribuição não existe e 403 se o email não prova propriedade.

O gate de licença: apenas-citação nunca vira valor

Este é o gate estrutural que deixa dados contribuídos fluírem para o corpus sem violar sua licença (server/trust/license-gate.ts). Espelha o gate de LicensePosture do registro de fontes: uma contribuição cuja licença proíbe a redistribuição só pode virar uma referência de citação, jamais um valor de indicador embutido no corpus.

LicençaAção no corpusO que permite
open / cc-by / share-alikeindicatorOs valores podem ser embutidos no corpus e na API pública.
non-commercialaggregates_onlyApenas agregados derivados; nunca republicação linha a linha.
cite-onlycitation_onlyApenas referência de citação; jamais um valor embutido.

O gate é aplicado em tempo de bake: scripts/bake-contributions.ts lê o export do ledger (public/data/contributions.json) e publica a projeção com licença aplicada (gateContribution()) em public/api/v1/contributions.json — a superfície de contribuições da API pública. Ao projetar uma contribuição apenas-citação para sua forma pública, suas geografias e pilares são esvaziados para [] — nenhuma cobertura é republicada (gateViolation() é o invariante coberto por testes por trás dessa regra). O recibo estampa a postura (corpus_posture) para que o contribuinte veja de antemão no que seu dado pode se converter.

O artefato declara seu próprio contrato: carrega a nota license_gate em texto simples e os contadores redistributable / citation_only, de modo que um consumidor da API vê quantos registros estão sob gate sem ler o código. O script só reescreve esse artefato e dois campos do manifesto — nunca regenera a árvore completa da API (bake-api.ts também o produz em um rebake total).

Direitos, não propriedade — e a ancoragem CARE / LGPD

O marco é direitos, não propriedade: o contribuinte não "vende" um ativo, retém direitos sobre seu uso — consentimento com propósito delimitado, revogável. Os dados rotulados como indígenas carregam uma flag explícita de autoridade-para-controlar, seguindo os princípios CARE (Collective Benefit, Authority to Control, Responsibility, Ethics). O manejo do email — usado apenas para uma notificação operacional fora de banda (Mailgun, best-effort), nunca persistido — segue a lógica de minimização de dados da LGPD brasileira e de marcos afins da região, não um template importado. A mesma disciplina alcança a analítica: o cliente identifica com um SHA-256 do email calculado no navegador; o endereço bruto nunca sai da página.

O que está no ar hoje vs. por fases

Estado
Contribuição com trava de consentimentoNo ar/contribuir
Recibo verificável por hash (SHA-256 reproduzível)No ar
Ledger append-only + revogação por tombstoneNo ar (Upstash; honesto se não está configurado)
Gate de licença (apenas-citação nunca é valor)No ar (regra de build)
Rubrica de pontos transparenteNo ar
Assinatura de emissor HMAC-SHA256 (recibo v2)No ar, por ambiente — ativada por TRUST_RECEIPT_HMAC_KEY; autentica o emissor, não verificável por terceiros
Assinatura Ed25519 verificável por terceirosNo roadmap — sem ela, a emissão é provada por presença no ledger
Custódia por um fiduciário independentePor fase — no longo prazo a administração sai do operador
Níveis de privacidade / salas limpas operacionaisPor fase — o esquema já os modela; a execução vem depois
Liquidação on-chainPor fase — esquema pronto (chain_anchor reservado); sem chain ainda
Níveis de sensibilidade + criptografia de registrosPor fase: hoje o modo de privacidade (PrivacyMode) é metadado declarado, não aplicado; os registros são guardados em texto simples
Prova de registro de conhecimento zero (ZK proof-of-record)Por fase: sem código ainda; provaria a presença de um registro no ledger sem revelá-lo
Notas comunitárias sobre contribuiçõesPor fase: sem código ainda
Carta de incentivos do contribuintePor fase: a rubrica transparente de pontos já está no ar; o que fica por fases é a carta que a governa e a liquidação em token

Superfícies relacionadas

  • /contribuir — o formulário de contribuição e o registro público de recibos.
  • /datos-abiertos — o corpus aberto com sua licença declarada.
  • /linaje — a linhagem de procedência das cifras.
  • /confianza — os selos de confiança e a rastreabilidade.

Siga o ciclo até o Pilar 2 — Modelo Soberano, o modelo que este corpus torna possível.

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