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
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. Lê as mesmas variáveis que o rate limiter: KV_REST_API_URL/TOKEN (Vercel KV) ou UPSTASH_REDIS_REST_URL/TOKEN, com KV_* primeiro (server/http/redis-env.ts). Em produção o armazenamento está configurado (conferido em 2026-10-16: GET /api/contribute responde configured: true e o registro público está vazio, stats.count 0). Se o par de variáveis falta, 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/contributelimita por dois eixos: 10 solicitações/minuto por IP e 8 promessas/hora por contribuinte. O segundo eixo existe porque um IP se troca de graça e a chave de dedupe cobre (contribuinte, título, descrição), então um caractere diferente no título torna "nova" cada promessa e o eixo por IP sozinho não limita quem troca de IP contra um endpoint que escreve o ledger durável e avisa o operador por e-mail. Esse segundo limite é cobrado sobre ocontributor_idpseudônimo (chavecontribute-addr:<contributor_id>), nunca sobre o e-mail cru: as chaves de limite de taxa são escritas em um Redis de terceiros e aparecem em rotas de erro, e o desenho do fideicomisso exige que o endereço de um contribuinte não saia desta solicitação. É computado depois da porta deTRUST_ID_SALT, então nenhum deploy pode indexar com o sal público de reserva. O corpo aceita 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).
O registro vazio é o estado honesto
O artefato público publica hoje { "count": 0, "contributions": [] } — e esse zero é uma garantia do produto, não um erro nem um stub à espera de dados falsos. O ledger acumula apenas compromissos reais sob consentimento explícito e revogável: não existem contribuições de demonstração, semeadas ou inventadas — o mesmo padrão de honestidade do registro de correções vazio de /confianza.
A interface revela esse estado na tela em vez de escondê-lo. Tanto o registro público de /contribuir quanto o bloco do fundo fiduciário em /confianza mostram um painel de diligência legível em uma única captura: o count: 0 explícito, o portão de licença que fixa no que cada contribuição pode se tornar (apenas-citação → só referência de citação; não comercial → só agregados; open/cc-by/share-alike → indicadores embutíveis) e o link vivo ao artefato que o comprova (GET /api/v1/contributions.json). O painel também distingue dois estados que não devem se confundir: o ledger compartilhado não configurado em um deploy (os recibos são emitidos mesmo assim, e isso é dito) versus o ledger configurado e honestamente vazio. Para uma revisão de diligência, vazio e verificável é a demonstração: qualquer linha que apareça depois será um compromisso real. Ambas as superfícies leem o mesmo artefato público (GET /api/v1/contributions.json), então o numeral na tela está ligado ao seu campo count e não a um literal do código, e quando o artefato os traz o painel mostra também sua data generated_at e sua nota license_gate literal — o portão como a máquina o publica, ao lado dos três postulados que são nossa leitura dele. Se o artefato omite um desses campos, nada é renderizado em seu lugar: nunca uma data nem um portão inventados.
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 (Redis KV configurado em produção; registro público vazio, count 0 em 2026-10-16; se o armazenamento falta, persisted: false) |
| 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.