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_hashprova 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_KEYconfigurada, o recibo passa aversion: 2e acrescentasig_alg: "hmac-sha256"maissignature= 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_idpseudô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_SALTdeve 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 umsalt_versionpú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 comstableStringify), 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_idereceipt_hashsão as colunas dessa atestação, echain_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):
| Campo | Derivação |
|---|---|
receipt_hash | SHA-256 hex sobre o corpo canônico — todos os demais campos, com chaves ordenadas. |
contribution_id | d_ + 24 hex: hash de (contributor_id, título, descrição, geografias, pilares, licença, privacidade, issuedAt, nonce UUID). Único por promessa. |
contributor_id | c_ + 24 hex: sha256(sal + ":" + email). Estável, pseudônimo, irreversível. |
points / points_breakdown | Total + decomposição {base, coverage, breadth, license, privacy}. |
corpus_posture | O que a licença permite no corpus (o gate de licença, estampado de antemão). |
salt_version | s_ + 12 hex: etiqueta pública de qual sal produziu o id — um hash unidirecional que nada revela do sal. |
issued_at / version | ISO-8601 de emissão · versão de esquema: 1 (só hash) ou 2 (assinado pelo emissor com HMAC). |
chain_ready / chain_anchor | true · 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:
| Chave | Estrutura | Papel |
|---|---|---|
trust:ledger:v1 | LIST | Fonte de verdade append-only (RPUSH / LRANGE). |
trust:revocations:v1 | LIST | Tombstones, em lista irmã — cada lista é mono-tipo, a leitura tipada nunca confunde uma linha. |
trust:ledger:index:v1 | HASH id→registro | Busca O(1) para revogar (HGET); best-effort — se falha, o append não falha. |
trust:revocations:index:v1 | SET | Revogação idempotente: SADD = 0 → já revogada, no-op. |
trust:ledger:dedupe:v1 | SET | Chaves 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 viaSADD; 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 devolvefresh: true— um tropeço do Redis jamais bloqueia uma contribuição genuína. - Limite de taxa e de corpo.
POST /api/contributeaceita 10 solicitações/minuto por IP e um corpo de no máximo 64 KB com guarda em duas etapas (rejeição imediata porContent-Lengthe contagem de bytes durante a leitura contra umContent-Lengthmentiroso); 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/contributepublica agregados sobre uma janela limitada de 500 registros, rotulada como tal (stats.window {limit, complete}), e a lista pública omite deliberadamente ocontribution_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+matchingSaltemledger.ts): os sais candidatos são oTRUST_ID_SALTvigente, depois cada entrada separada por vírgulas deTRUST_ID_SALT_PREVIOUS, com o sal padrão do código como reserva. Se o registro trazsalt_versionestampado, busca-se o candidato cuja etiqueta coincide e somente esse deve reproduzir ocontributor_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 umHGETsem 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ça | Ação no corpus | O que permite |
|---|---|---|
open / cc-by / share-alike | indicator | Os valores podem ser embutidos no corpus e na API pública. |
non-commercial | aggregates_only | Apenas agregados derivados; nunca republicação linha a linha. |
cite-only | citation_only | Apenas 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 consentimento | No ar — /contribuir |
| Recibo verificável por hash (SHA-256 reproduzível) | No ar |
| Ledger append-only + revogação por tombstone | No 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 transparente | No 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 terceiros | No roadmap — sem ela, a emissão é provada por presença no ledger |
| Custódia por um fiduciário independente | Por fase — no longo prazo a administração sai do operador |
| Níveis de privacidade / salas limpas operacionais | Por fase — o esquema já os modela; a execução vem depois |
| Liquidação on-chain | Por fase — esquema pronto (chain_anchor reservado); sem chain ainda |
| Níveis de sensibilidade + criptografia de registros | Por 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ções | Por fase: sem código ainda |
| Carta de incentivos do contribuinte | Por 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.