diff options
| author | murilo ijanc | 2026-03-24 21:45:05 -0300 |
|---|---|---|
| committer | murilo ijanc | 2026-03-24 21:45:05 -0300 |
| commit | 01c17c68277ff88fab812920732d9bbe9e6bb571 (patch) | |
| tree | 035398ae34263b981b621c6275835d2cc6847d57 /pt-br | |
| parent | f186b71ca51e83837db60de13322394bb5e6d348 (diff) | |
| download | website-01c17c68277ff88fab812920732d9bbe9e6bb571.tar.gz | |
Remove old Zola-generated content, keep only the essential
landing page with about, contact, and license sections.
Diffstat (limited to 'pt-br')
50 files changed, 0 insertions, 8000 deletions
diff --git a/pt-br/about/index.html b/pt-br/about/index.html deleted file mode 100644 index b9b425b..0000000 --- a/pt-br/about/index.html +++ /dev/null @@ -1,192 +0,0 @@ -<!DOCTYPE html> -<html lang="pt-br"> -<head> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <title>Sobre — Tesseras</title> - <meta name="description" content="Tesseras é uma rede peer-to-peer para preservar memórias humanas através dos milênios — porque sua história merece sobreviver a qualquer plataforma."> - <!-- Open Graph --> - <meta property="og:type" content="website"> - <meta property="og:title" content="Sobre"> - <meta property="og:description" content="Tesseras é uma rede peer-to-peer para preservar memórias humanas através dos milênios — porque sua história merece sobreviver a qualquer plataforma."> - <meta property="og:image" content="https://tesseras.net/images/social.jpg"> - <meta property="og:image:width" content="1200"> - <meta property="og:image:height" content="630"> - <meta property="og:site_name" content="Tesseras"> - <!-- Twitter Card --> - <meta name="twitter:card" content="summary_large_image"> - <meta name="twitter:title" content="Sobre"> - <meta name="twitter:description" content="Tesseras é uma rede peer-to-peer para preservar memórias humanas através dos milênios — porque sua história merece sobreviver a qualquer plataforma."> - <meta name="twitter:image" content="https://tesseras.net/images/social.jpg"> - <link rel="stylesheet" href="https://tesseras.net/style.css?h=21f0f32121928ee5c690"> - - - <link rel="alternate" type="application/atom+xml" title="Tesseras" href="https://tesseras.net/atom.xml"> - - - <link rel="icon" type="image/png" sizes="32x32" href="https://tesseras.net/images/favicon.png?h=be4e123a23393b1a027d"> - -</head> -<body> - <header> - <h1> - <a href="https://tesseras.net/pt-br/"> - <img src="https://tesseras.net/images/logo-64.png?h=c1b8d0c4c5f93b49d40b" alt="Tesseras" width="40" height="40" class="logo"> - Tesseras - </a> - </h1> - <nav> - - <a href="https://tesseras.net/pt-br/about/">Sobre</a> - <a href="https://tesseras.net/pt-br/news/">Notícias</a> - <a href="https://tesseras.net/pt-br/releases/">Lançamentos</a> - <a href="https://tesseras.net/pt-br/faq/">FAQ</a> - <a href="https://tesseras.net/pt-br/subscriptions/">Inscrições</a> - <a href="https://tesseras.net/pt-br/contact/">Contato</a> - - </nav> - <nav class="lang-switch"> - - <a href="https://tesseras.net/about/">English</a> | <strong>Português</strong> - - </nav> - </header> - - <main> - -<article> - <h2>Sobre</h2> - <p>Neste exato momento, em algum lugar, o álbum de fotos de uma avó está se -desfazendo em um porão inundado. As cartas de um soldado para casa existem -apenas em um serviço de e-mail que foi descontinuado. As primeiras palavras de -uma criança, gravadas em um celular, vão desaparecer quando a assinatura da -nuvem vencer.</p> -<p>Somos a primeira geração na história que produz mais memórias do que qualquer -civilização antes de nós — e as perde mais rápido do que qualquer civilização -antes de nós.</p> -<h2 id="o-problema-de-que-ninguem-fala">O Problema de Que Ninguém Fala</h2> -<p>Toda plataforma em que você confia suas memórias é temporária. Toda empresa que -promete "para sempre" está a um relatório trimestral de distância de mudar de -direção, ser vendida ou fechar as portas. Todo formato proprietário é um relógio -fazendo contagem regressiva.</p> -<ul> -<li><strong>Google Fotos, iCloud, OneDrive</strong> — suas memórias vivem no servidor de outra -pessoa, sob os termos de serviço de outra pessoa, atrás do paywall de outra -pessoa</li> -<li><strong>Redes sociais</strong> — a história da sua vida está espalhada por plataformas que -tratam suas memórias como inventário de publicidade</li> -<li><strong>HDs e pendrives</strong> — falham silenciosamente, sem aviso e sem backup</li> -<li><strong>DVDs e CDs</strong> — já são ilegíveis para a maioria das pessoas</li> -</ul> -<p>O padrão é sempre o mesmo: um formato se torna popular, uma empresa facilita o -uso, as pessoas despejam suas vidas nele, e então ele desaparece. GeoCities. -Vine. MySpace. Google+. Orkut. A lista cresce a cada ano.</p> -<p>Isso não é um problema de tecnologia. É um problema de design. Continuamos -construindo sistemas onde a preservação de memórias é um efeito colateral do -modelo de negócios de alguém, não o propósito.</p> -<h2 id="o-que-tesseras-faz-de-diferente">O Que Tesseras Faz de Diferente</h2> -<p>Tesseras parte de uma premissa radical: <strong>suas memórias pertencem a você, e elas -devem sobreviver a toda empresa, plataforma e formato que existe hoje.</strong></p> -<p>Uma tessera é uma cápsula do tempo autocontida — fotos, áudio, vídeo e texto — -empacotada em um formato projetado para ser compreendido séculos no futuro, sem -nenhum software especial.</p> -<h3 id="sem-servidores-sem-assinaturas-sem-empresa">Sem Servidores. Sem Assinaturas. Sem Empresa.</h3> -<p>Tesseras é uma rede peer-to-peer construída sobre ajuda mútua. Você armazena -fragmentos das memórias de outras pessoas, e elas armazenam as suas. Sem tokens, -sem blockchain, sem mensalidades. O incentivo é simples e humano: eu ajudo a -preservar a sua história, você ajuda a preservar a minha.</p> -<h3 id="sobrevive-a-tudo">Sobrevive a Tudo</h3> -<p>Sua tessera é protegida por codificação por apagamento — a mesma matemática que -mantém sondas espaciais se comunicando com a Terra. Seus dados são divididos em -fragmentos redundantes e distribuídos pela rede. Nós podem ficar offline, discos -rígidos podem falhar, regiões inteiras podem perder conectividade — e suas -memórias sobrevivem.</p> -<h3 id="formato-autodescritivo">Formato Autodescritivo</h3> -<p>Cada tessera carrega dentro de si as instruções para ser decodificada. Em texto -simples. Em múltiplos idiomas. Mesmo que todas as cópias do software Tesseras -desaparecessem amanhã, qualquer pessoa com um entendimento básico de computação -poderia ler sua tessera. É um formato de arquivo projetado para arqueólogos, não -apenas para programadores.</p> -<h3 id="criptografia-pos-quantica">Criptografia Pós-Quântica</h3> -<p>Tesseras usa assinaturas duplas — Ed25519 clássico e ML-DSA pós-quântico — para -que a autenticidade das suas memórias possa ser verificada mesmo depois que -computadores quânticos tornarem a criptografia de hoje obsoleta. Protegemos o -futuro, hoje.</p> -<h3 id="construido-para-o-longo-prazo">Construído para o Longo Prazo</h3> -<p>Cada decisão no Tesseras é tomada pensando em séculos:</p> -<ul> -<li><strong>Formatos de mídia mais simples</strong> — JPEG para fotos, WAV para áudio, WebM -para vídeo, texto simples para escrita. Não porque são os melhores, mas porque -serão legíveis por mais tempo.</li> -<li><strong>Sem criptografia por padrão</strong> — disponibilidade acima do sigilo. Uma memória -que não pode ser descriptografada é uma memória perdida. Memórias privadas -podem ser criptografadas, mas o padrão é a sobrevivência.</li> -<li><strong>Sem dependência da internet</strong> — tesseras podem ser armazenadas em pendrives, -mídias ópticas, Raspberry Pis em uma prateleira, até dispositivos IoT de baixo -consumo. Qualquer cópia é uma cópia válida.</li> -</ul> -<h2 id="a-necessidade-humana">A Necessidade Humana</h2> -<p>Seres humanos sempre preservaram memórias. Pinturas rupestres em Lascaux. Tábuas -de argila na Mesopotâmia. Cartas dobradas dentro de livros. Álbuns de fotos -passados de pai para filho.</p> -<p>O desejo de ser lembrado — de deixar prova de que estivemos aqui, de que amamos, -de que vivemos — está entre os impulsos humanos mais profundos. Toda cultura, em -toda era, encontrou formas de inscrever sua existência em algo mais durável que -uma única vida.</p> -<p>A era digital prometeu tornar isso mais fácil. Em vez disso, tornou frágil. -Trocamos durabilidade por conveniência, e o custo é medido em infâncias -perdidas, rostos esquecidos e histórias que ninguém jamais ouvirá.</p> -<p>Tesseras é uma tentativa de restaurar o contrato ancestral: <strong>o que você escolhe -lembrar deve perdurar.</strong></p> -<h2 id="por-que-tesseras">Por Que "Tesseras"?</h2> -<p>Uma <em>tessera</em> (plural <em>tesserae</em>) é uma pequena peça de pedra, vidro ou cerâmica -usada para compor um mosaico. A palavra vem do latim, emprestada do grego -<em>τέσσερα</em> — os pequenos quadrados que, peça por peça, construíram os grandes -mosaicos de Roma, Pompeia e Bizâncio.</p> -<p>Alguns desses mosaicos permanecem intactos depois de dois mil anos.</p> -<p>A metáfora é o projeto: cada tessera na nossa rede é um fragmento pequeno e -autocontido — individualmente simples, individualmente durável. Mas juntas, elas -compõem algo maior: um mosaico da memória humana, distribuído por milhares de -nós, resiliente o bastante para sobreviver a qualquer ponto único de falha.</p> -<p>Assim como as tesserae antigas não precisavam de manual para serem compreendidas -— um fragmento de pedra colorida fala por si — cada tessera digital carrega -dentro de si tudo o que é necessário para ser lida, em formatos simples, em -linguagem simples.</p> -<p>O nome também é um lembrete de escala. Um mosaico não se faz em um dia. É -montado peça por peça, com paciência, por muitas mãos. É assim que pretendemos -construir uma rede que dure.</p> -<h2 id="codigo-aberto-protocolo-aberto-futuro-aberto">Código Aberto, Protocolo Aberto, Futuro Aberto</h2> -<p>Tesseras é software livre sob a licença ISC. O protocolo é aberto. O formato é -documentado. Qualquer pessoa pode rodar um nó, construir um cliente ou bifurcar -o projeto inteiro.</p> -<p>Não há capital de risco por trás do Tesseras. Nenhuma métrica de crescimento -para atingir. Nenhuma estratégia de saída. Apenas uma convicção simples: a -tecnologia para preservar a memória humana não deveria pertencer a ninguém.</p> -<h2 id="status-atual">Status Atual</h2> -<p>Tesseras está na Fase 4 — Resiliência e Escala. O formato base, as fundações -criptográficas, a rede peer-to-peer, a replicação ativa com erasure coding, a -API GraphQL e o app Flutter estão construídos. Estamos agora trabalhando em -Shamir's Secret Sharing para recuperação de chaves por herdeiros, NAT traversal -avançado e ajuste de performance.</p> -<p>Este é um projeto de longo prazo. Medimos progresso em décadas, não em -trimestres.</p> -<h2 id="participe">Participe</h2> -<p>Se você acredita que a memória humana merece ser preservada — não como um -produto, não como um serviço, mas como um direito fundamental — adoraríamos sua -ajuda.</p> -<ul> -<li>Leia o <a href="/pt-br/faq/">FAQ</a> para saber mais</li> -<li>Entre nas <a href="/pt-br/subscriptions/">listas de discussão</a> para atualizações</li> -<li>Navegue pelo <a rel="external" href="https://git.sr.ht/~ijanc/tesseras">código-fonte</a></li> -<li><a href="/pt-br/contact/">Fale conosco</a> diretamente</li> -</ul> - -</article> - - </main> - - <footer> - <p>© 2026 Tesseras Project. <a href="/atom.xml">News Feed</a> · <a href="https://git.sr.ht/~ijanc/tesseras">Source</a></p> - </footer> -</body> -</html> diff --git a/pt-br/about/index.html.gz b/pt-br/about/index.html.gz Binary files differdeleted file mode 100644 index c89a5f4..0000000 --- a/pt-br/about/index.html.gz +++ /dev/null diff --git a/pt-br/atom.xml b/pt-br/atom.xml deleted file mode 100644 index bf61615..0000000 --- a/pt-br/atom.xml +++ /dev/null @@ -1,2101 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="pt-br"> - <title>Tesseras</title> - <subtitle>Rede P2P para preservar memórias humanas através dos milênios</subtitle> - <link rel="self" type="application/atom+xml" href="https://tesseras.net/pt-br/atom.xml"/> - <link rel="alternate" type="text/html" href="https://tesseras.net"/> - <generator uri="https://www.getzola.org/">Zola</generator> - <updated>2026-02-16T10:00:00+00:00</updated> - <id>https://tesseras.net/pt-br/atom.xml</id> - <entry xml:lang="pt-br"> - <title>Empacotando o Tesseras para Debian</title> - <published>2026-02-16T10:00:00+00:00</published> - <updated>2026-02-16T10:00:00+00:00</updated> - - <author> - <name> - - Unknown - - </name> - </author> - - <link rel="alternate" type="text/html" href="https://tesseras.net/pt-br/news/packaging-debian/"/> - <id>https://tesseras.net/pt-br/news/packaging-debian/</id> - - <content type="html" xml:base="https://tesseras.net/pt-br/news/packaging-debian/"><p>O Tesseras agora inclui um pacote <code>.deb</code> para Debian e Ubuntu. Este post explica -como compilar e instalar o pacote a partir do código-fonte usando <code>cargo-deb</code>.</p> -<h2 id="pre-requisitos">Pré-requisitos</h2> -<p>Você precisa de uma toolchain Rust funcional e das bibliotecas de sistema -necessárias:</p> -<pre><code data-lang="sh">sudo apt install build-essential pkg-config libsqlite3-dev -rustup toolchain install stable -cargo install cargo-deb -</code></pre> -<h2 id="compilando">Compilando</h2> -<p>Clone o repositório e execute a recipe <code>just deb</code>:</p> -<pre><code data-lang="sh">git clone https://git.sr.ht/~ijanc/tesseras -cd tesseras -just deb -</code></pre> -<p>Essa recipe faz três coisas:</p> -<ol> -<li><strong>Compila</strong> <code>tesd</code> (o daemon) e <code>tes</code> (o CLI) em modo release com -<code>cargo build --release</code></li> -<li><strong>Gera completions de shell</strong> para bash, zsh e fish a partir do binário <code>tes</code></li> -<li><strong>Empacota</strong> tudo em um arquivo <code>.deb</code> com -<code>cargo deb -p tesseras-daemon --no-build</code></li> -</ol> -<p>O resultado é um arquivo <code>.deb</code> em <code>target/debian/</code>.</p> -<h2 id="instalando">Instalando</h2> -<pre><code data-lang="sh">sudo dpkg -i target/debian/tesseras-daemon_*.deb -</code></pre> -<p>Se houver dependências faltando, corrija com:</p> -<pre><code data-lang="sh">sudo apt install -f -</code></pre> -<h2 id="configuracao-pos-instalacao">Configuração pós-instalação</h2> -<p>O script <code>postinst</code> cria automaticamente um usuário de sistema <code>tesseras</code> e o -diretório de dados <code>/var/lib/tesseras</code>. Para usar o CLI sem sudo, adicione seu -usuário ao grupo:</p> -<pre><code data-lang="sh">sudo usermod -aG tesseras $USER -</code></pre> -<p>Faça logout e login novamente, depois inicie o daemon:</p> -<pre><code data-lang="sh">sudo systemctl enable --now tesd -</code></pre> -<h2 id="o-que-o-pacote-inclui">O que o pacote inclui</h2> -<table><thead><tr><th>Caminho</th><th>Descrição</th></tr></thead><tbody> -<tr><td><code>/usr/bin/tesd</code></td><td>Daemon do nó completo</td></tr> -<tr><td><code>/usr/bin/tes</code></td><td>Cliente CLI</td></tr> -<tr><td><code>/etc/tesseras/config.toml</code></td><td>Configuração padrão (marcado como conffile)</td></tr> -<tr><td><code>/lib/systemd/system/tesd.service</code></td><td>Unit systemd com hardening de segurança</td></tr> -<tr><td>Completions de shell</td><td>bash, zsh e fish</td></tr> -</tbody></table> -<h2 id="como-o-cargo-deb-funciona">Como o cargo-deb funciona</h2> -<p>Os metadados de empacotamento ficam em <code>crates/tesseras-daemon/Cargo.toml</code> na -seção <code>[package.metadata.deb]</code>. Essa seção define:</p> -<ul> -<li><strong>depends</strong> — dependências em tempo de execução: <code>libc6</code> e <code>libsqlite3-0</code></li> -<li><strong>assets</strong> — arquivos incluídos no pacote (binários, config, unit systemd, -completions de shell)</li> -<li><strong>conf-files</strong> — arquivos tratados como configuração (preservados na -atualização)</li> -<li><strong>maintainer-scripts</strong> — scripts <code>postinst</code> e <code>postrm</code> em -<code>packaging/debian/scripts/</code></li> -<li><strong>systemd-units</strong> — integração automática com systemd</li> -</ul> -<p>O script <code>postinst</code> cria o usuário de sistema <code>tesseras</code> e o diretório de dados -na instalação. O script <code>postrm</code> remove o usuário, grupo e diretório de dados -apenas no <code>purge</code> (não na remoção simples).</p> -<h2 id="hardening-do-systemd">Hardening do systemd</h2> -<p>A unit <code>tesd.service</code> inclui diretivas de hardening de segurança:</p> -<pre><code data-lang="ini">NoNewPrivileges=true -ProtectSystem=strict -ProtectHome=true -ReadWritePaths=/var/lib/tesseras -PrivateTmp=true -PrivateDevices=true -ProtectKernelTunables=true -ProtectControlGroups=true -RestrictSUIDSGID=true -MemoryDenyWriteExecute=true -</code></pre> -<p>O daemon roda como o usuário não-privilegiado <code>tesseras</code> e só pode escrever em -<code>/var/lib/tesseras</code>.</p> -<h2 id="deploy-para-um-servidor-remoto">Deploy para um servidor remoto</h2> -<p>O justfile inclui uma recipe <code>deploy</code> para enviar o <code>.deb</code> a um host remoto:</p> -<pre><code data-lang="sh">just deploy bootstrap1.tesseras.net -</code></pre> -<p>Isso compila o <code>.deb</code>, copia via <code>scp</code>, instala com <code>dpkg -i</code> e reinicia o -serviço <code>tesd</code>.</p> -<h2 id="atualizando">Atualizando</h2> -<p>Depois de baixar novas mudanças, basta rodar <code>just deb</code> novamente e reinstalar:</p> -<pre><code data-lang="sh">git pull -just deb -sudo dpkg -i target/debian/tesseras-daemon_*.deb -</code></pre> -</content> - - </entry> - <entry xml:lang="pt-br"> - <title>Empacotando o Tesseras para Arch Linux</title> - <published>2026-02-16T09:00:00+00:00</published> - <updated>2026-02-16T09:00:00+00:00</updated> - - <author> - <name> - - Unknown - - </name> - </author> - - <link rel="alternate" type="text/html" href="https://tesseras.net/pt-br/news/packaging-archlinux/"/> - <id>https://tesseras.net/pt-br/news/packaging-archlinux/</id> - - <content type="html" xml:base="https://tesseras.net/pt-br/news/packaging-archlinux/"><p>O Tesseras agora inclui um PKGBUILD para Arch Linux. Este post explica como -compilar e instalar o pacote a partir do código-fonte.</p> -<h2 id="pre-requisitos">Pré-requisitos</h2> -<p>Você precisa de uma toolchain Rust funcional e do grupo base-devel:</p> -<pre><code data-lang="sh">sudo pacman -S --needed base-devel sqlite -rustup toolchain install stable -</code></pre> -<h2 id="compilando">Compilando</h2> -<p>Clone o repositório e execute a recipe <code>just arch</code>:</p> -<pre><code data-lang="sh">git clone https://git.sr.ht/~ijanc/tesseras -cd tesseras -just arch -</code></pre> -<p>Isso executa <code>makepkg -sf</code> dentro de <code>packaging/archlinux/</code>, que:</p> -<ol> -<li><strong>prepare</strong> — baixa as dependências Cargo com <code>cargo fetch --locked</code></li> -<li><strong>build</strong> — compila <code>tesd</code> e <code>tes</code> (o CLI) em modo release</li> -<li><strong>package</strong> — instala binários, serviço systemd, configs sysusers/tmpfiles, -completions de shell (bash, zsh, fish) e um arquivo de configuração padrão</li> -</ol> -<p>O resultado é um arquivo <code>.pkg.tar.zst</code> em <code>packaging/archlinux/</code>.</p> -<h2 id="instalando">Instalando</h2> -<pre><code data-lang="sh">sudo pacman -U packaging/archlinux/tesseras-*.pkg.tar.zst -</code></pre> -<h2 id="configuracao-pos-instalacao">Configuração pós-instalação</h2> -<p>O pacote cria automaticamente um usuário e grupo de sistema <code>tesseras</code> via -systemd-sysusers. Para usar o CLI sem sudo, adicione seu usuário ao grupo:</p> -<pre><code data-lang="sh">sudo usermod -aG tesseras $USER -</code></pre> -<p>Faça logout e login novamente, depois inicie o daemon:</p> -<pre><code data-lang="sh">sudo systemctl enable --now tesd -</code></pre> -<h2 id="o-que-o-pacote-inclui">O que o pacote inclui</h2> -<table><thead><tr><th>Caminho</th><th>Descrição</th></tr></thead><tbody> -<tr><td><code>/usr/bin/tesd</code></td><td>Daemon do nó completo</td></tr> -<tr><td><code>/usr/bin/tes</code></td><td>Cliente CLI</td></tr> -<tr><td><code>/etc/tesseras/config.toml</code></td><td>Configuração padrão (marcado como backup)</td></tr> -<tr><td><code>/usr/lib/systemd/system/tesd.service</code></td><td>Unit systemd com hardening de segurança</td></tr> -<tr><td><code>/usr/lib/sysusers.d/tesseras.conf</code></td><td>Definição do usuário de sistema</td></tr> -<tr><td><code>/usr/lib/tmpfiles.d/tesseras.conf</code></td><td>Diretório de dados <code>/var/lib/tesseras</code></td></tr> -<tr><td>Completions de shell</td><td>bash, zsh e fish</td></tr> -</tbody></table> -<h2 id="detalhes-do-pkgbuild">Detalhes do PKGBUILD</h2> -<p>O PKGBUILD compila diretamente a partir do checkout git local em vez de baixar -um tarball. A variável de ambiente <code>TESSERAS_ROOT</code> aponta o makepkg para a raiz -do workspace. O diretório target do Cargo é configurado para <code>$srcdir/target</code> -para manter os artefatos de build dentro do sandbox do makepkg.</p> -<p>O pacote depende apenas de <code>sqlite</code> em tempo de execução e <code>cargo</code> em tempo de -build.</p> -<h2 id="atualizando">Atualizando</h2> -<p>Depois de baixar novas mudanças, basta rodar <code>just arch</code> novamente e reinstalar:</p> -<pre><code data-lang="sh">git pull -just arch -sudo pacman -U packaging/archlinux/tesseras-*.pkg.tar.zst -</code></pre> -</content> - - </entry> - <entry xml:lang="pt-br"> - <title>Fase 4: Deduplicacao de Armazenamento</title> - <published>2026-02-15T23:00:00+00:00</published> - <updated>2026-02-15T23:00:00+00:00</updated> - - <author> - <name> - - Unknown - - </name> - </author> - - <link rel="alternate" type="text/html" href="https://tesseras.net/pt-br/news/phase4-storage-deduplication/"/> - <id>https://tesseras.net/pt-br/news/phase4-storage-deduplication/</id> - - <content type="html" xml:base="https://tesseras.net/pt-br/news/phase4-storage-deduplication/"><p>Quando multiplas tesseras compartilham a mesma foto, o mesmo clipe de audio ou -os mesmos dados de fragmento, a camada de armazenamento antiga mantinha copias -separadas de cada. Em um no armazenando milhares de tesseras para a rede, essa -duplicacao se acumula rapidamente. A Fase 4 continua com deduplicacao de -armazenamento: um armazenamento enderecavel por conteudo (CAS) que garante que -cada dado unico seja armazenado exatamente uma vez em disco, independentemente -de quantas tesseras o referenciam.</p> -<p>O design e simples e comprovado: hash do conteudo com BLAKE3, usar o hash como -nome do arquivo e manter uma contagem de referencias no SQLite. Quando duas -tesseras incluem a mesma foto de 5 MB, um arquivo existe em disco com -refcount 2. Quando uma tessera e deletada, o refcount cai para 1 e o arquivo -permanece. Quando a ultima referencia e liberada, uma varredura periodica limpa -o orfao.</p> -<h2 id="o-que-foi-construido">O que foi construido</h2> -<p><strong>Migracao do esquema CAS</strong> (<code>tesseras-storage/migrations/004_dedup.sql</code>) — Tres -novas tabelas:</p> -<ul> -<li><code>cas_objects</code> — rastreia cada objeto no armazenamento: hash BLAKE3 (chave -primaria), tamanho em bytes, contagem de referencias e timestamp de criacao</li> -<li><code>blob_refs</code> — mapeia identificadores logicos de blobs (hash da tessera + hash -da memoria + nome do arquivo) para hashes CAS, substituindo a convencao antiga -de caminhos no sistema de arquivos</li> -<li><code>fragment_refs</code> — mapeia identificadores logicos de fragmentos (hash da -tessera + indice do fragmento) para hashes CAS, substituindo o antigo layout -do diretorio <code>fragments/</code></li> -</ul> -<p>Indices nas colunas de hash garantem lookups O(1) durante leituras e contagem de -referencias.</p> -<p><strong>CasStore</strong> (<code>tesseras-storage/src/cas.rs</code>) — O motor central de armazenamento -enderecavel por conteudo. Arquivos sao armazenados sob um diretorio de prefixo -de dois niveis: <code>&lt;raiz&gt;/&lt;prefixo-hex-2-chars&gt;/&lt;hash-completo&gt;.blob</code>. O -armazenamento fornece cinco operacoes:</p> -<ul> -<li><code>put(hash, data)</code> — escreve dados em disco se ainda nao presente, incrementa o -refcount. Retorna se ocorreu um hit de deduplicacao.</li> -<li><code>get(hash)</code> — le dados do disco pelo hash</li> -<li><code>release(hash)</code> — decrementa o refcount. Se chegar a zero, o arquivo em disco -e deletado imediatamente.</li> -<li><code>contains(hash)</code> — verifica existencia sem ler</li> -<li><code>ref_count(hash)</code> — retorna a contagem de referencias atual</li> -</ul> -<p>Todas as operacoes sao atomicas dentro de uma unica transacao SQLite. O refcount -e a fonte de verdade — se o refcount diz que o objeto existe, o arquivo deve -estar em disco.</p> -<p><strong>FsBlobStore com CAS</strong> (<code>tesseras-storage/src/blob.rs</code>) — Reescrito para -delegar todo armazenamento ao CAS. Quando um blob e escrito, seu hash BLAKE3 e -computado e passado para <code>cas.put()</code>. Uma linha em <code>blob_refs</code> mapeia o caminho -logico (tessera + memoria + arquivo) para o hash CAS. Leituras buscam o hash CAS -via <code>blob_refs</code> e leem de <code>cas.get()</code>. Deletar uma tessera libera todas as suas -referencias de blob em uma unica transacao.</p> -<p><strong>FsFragmentStore com CAS</strong> (<code>tesseras-storage/src/fragment.rs</code>) — Mesmo padrao -para fragmentos codificados com erasure coding. O checksum BLAKE3 de cada -fragmento ja e computado durante a codificacao Reed-Solomon, entao e usado -diretamente como chave CAS. A verificacao de fragmentos agora checa o hash CAS -ao inves de recomputar do zero — se o CAS diz que os dados estao intactos, -estao.</p> -<p><strong>Coletor de lixo sweep</strong> (<code>cas.rs:sweep()</code>) — Uma passagem periodica de GC que -trata tres casos limite que o caminho normal de refcount nao consegue:</p> -<ol> -<li><strong>Arquivos orfaos</strong> — arquivos em disco sem linha correspondente em -<code>cas_objects</code>. Pode acontecer apos um crash durante escrita. Arquivos com -menos de 1 hora sao pulados (periodo de graca para escritas em andamento); -orfaos mais antigos sao deletados.</li> -<li><strong>Refcounts vazados</strong> — linhas em <code>cas_objects</code> com refcount zero que nao -foram limpas (ex: se o processo morreu entre decrementar e deletar). Essas -linhas sao removidas.</li> -<li><strong>Idempotente</strong> — executar sweep duas vezes produz o mesmo resultado.</li> -</ol> -<p>O sweep e conectado ao loop de reparo existente em <code>tesseras-replication</code>, entao -roda automaticamente a cada 24 horas junto com as verificacoes de saude dos -fragmentos.</p> -<p><strong>Migracao do layout antigo</strong> (<code>tesseras-storage/src/migration.rs</code>) — Uma -estrategia de migracao copy-first que move dados do layout antigo baseado em -diretorios (<code>blobs/&lt;tessera&gt;/&lt;memoria&gt;/&lt;arquivo&gt;</code> e -<code>fragments/&lt;tessera&gt;/&lt;indice&gt;.shard</code>) para o CAS. A migracao:</p> -<ol> -<li>Verifica a versao de armazenamento em <code>storage_meta</code> (versao 1 = layout -antigo, versao 2 = CAS)</li> -<li>Percorre os diretorios antigos <code>blobs/</code> e <code>fragments/</code></li> -<li>Computa hashes BLAKE3 e insere no CAS via <code>put()</code> — duplicatas sao -automaticamente deduplicadas</li> -<li>Cria entradas correspondentes em <code>blob_refs</code> / <code>fragment_refs</code></li> -<li>Remove diretorios antigos somente apos todos os dados estarem seguros no CAS</li> -<li>Atualiza a versao de armazenamento para 2</li> -</ol> -<p>A migracao roda na inicializacao do daemon, e idempotente (segura para -re-executar) e reporta estatisticas: arquivos migrados, duplicatas encontradas, -bytes economizados.</p> -<p><strong>Metricas Prometheus</strong> (<code>tesseras-storage/src/metrics.rs</code>) — Dez novas metricas -para observabilidade:</p> -<table><thead><tr><th>Metrica</th><th>Descricao</th></tr></thead><tbody> -<tr><td><code>cas_objects_total</code></td><td>Total de objetos unicos no CAS</td></tr> -<tr><td><code>cas_bytes_total</code></td><td>Total de bytes armazenados</td></tr> -<tr><td><code>cas_dedup_hits_total</code></td><td>Numero de escritas que encontraram um objeto existente</td></tr> -<tr><td><code>cas_bytes_saved_total</code></td><td>Bytes economizados por deduplicacao</td></tr> -<tr><td><code>cas_gc_refcount_deletions_total</code></td><td>Objetos deletados quando refcount chegou a zero</td></tr> -<tr><td><code>cas_gc_sweep_orphans_cleaned_total</code></td><td>Arquivos orfaos removidos pelo sweep</td></tr> -<tr><td><code>cas_gc_sweep_leaked_refs_cleaned_total</code></td><td>Linhas de refcount vazadas limpas</td></tr> -<tr><td><code>cas_gc_sweep_skipped_young_total</code></td><td>Orfaos jovens pulados (periodo de graca)</td></tr> -<tr><td><code>cas_gc_sweep_duration_seconds</code></td><td>Tempo gasto no sweep GC</td></tr> -</tbody></table> -<p><strong>Testes baseados em propriedades</strong> — Dois testes proptest verificam invariantes -do CAS sob entradas aleatorias:</p> -<ul> -<li><code>refcount_matches_actual_refs</code> — apos N operacoes aleatorias de put/release, o -refcount sempre corresponde ao numero real de referencias pendentes</li> -<li><code>cas_path_is_deterministic</code> — o mesmo hash sempre produz o mesmo caminho no -sistema de arquivos</li> -</ul> -<p><strong>Atualizacao de testes de integracao</strong> — Todos os testes de integracao em -<code>tesseras-core</code>, <code>tesseras-replication</code>, <code>tesseras-embedded</code> e <code>tesseras-cli</code> -atualizados para os novos construtores com CAS. Testes de deteccao de -adulteracao atualizados para funcionar com o layout de diretorio CAS.</p> -<p>347 testes passam em todo o workspace. Clippy limpo com <code>-D warnings</code>.</p> -<h2 id="decisoes-de-arquitetura">Decisoes de arquitetura</h2> -<ul> -<li><strong>BLAKE3 como chave CAS</strong>: o hash de conteudo que ja computamos para -verificacao de integridade serve tambem como chave de deduplicacao. Nenhuma -etapa adicional de hashing — o hash computado durante <code>create</code> ou <code>replicate</code> -e reutilizado como endereco CAS.</li> -<li><strong>Refcount SQLite ao inves de reflinks do sistema de arquivos</strong>: consideramos -usar copy-on-write no nivel do sistema de arquivos (reflinks em btrfs/XFS), -mas isso amarraria o Tesseras a sistemas de arquivos especificos. Refcounting -em SQLite funciona em qualquer sistema de arquivos, incluindo FAT32 em -pendrives baratos e ext4 em Raspberry Pis.</li> -<li><strong>Diretorios de prefixo hexadecimal de dois niveis</strong>: armazenar todos os -objetos CAS em um diretorio plano desaceleraria sistemas de arquivos com -milhoes de entradas. A divisao <code>&lt;prefixo 2 chars&gt;/</code> limita qualquer diretorio -individual a ~65k entradas antes de um segundo nivel ser necessario. Isso -segue a abordagem usada pelo object store do Git.</li> -<li><strong>Periodo de graca para arquivos orfaos</strong>: o sweep GC pula arquivos com menos -de 1 hora para evitar deletar objetos sendo escritos por uma operacao -concorrente. Esta e uma escolha pragmatica — troca uma pequena janela de -potenciais orfaos por seguranca contra crashes sem exigir fsync ou commit de -duas fases.</li> -<li><strong>Migracao copy-first</strong>: a migracao copia dados para o CAS antes de remover -diretorios antigos. Se o processo for interrompido, os dados antigos -permanecem intactos e a migracao pode ser re-executada. Isso e mais lento que -mover arquivos mas garante zero perda de dados.</li> -<li><strong>Sweep no loop de reparo</strong>: ao inves de adicionar um timer separado de GC, o -sweep CAS aproveita o loop de reparo existente de 24 horas. Isso mantem o -daemon simples — um unico ciclo de manutencao em segundo plano cuida tanto da -saude dos fragmentos quanto da limpeza de armazenamento.</li> -</ul> -<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2> -<ul> -<li><strong>Fase 4 continuacao</strong> — auditorias de seguranca, empacotamento para OS -(Alpine, Arch, Debian, OpenBSD, FreeBSD)</li> -<li><strong>Fase 5: Exploracao e Cultura</strong> — navegador publico de tesseras por -era/localizacao/tema/idioma, curadoria institucional, integracao genealogica -(FamilySearch, Ancestry), exportacao para midia fisica (M-DISC, microfilme, -papel livre de acido com QR), contexto assistido por IA</li> -</ul> -<p>A deduplicacao de armazenamento completa a historia de eficiencia de -armazenamento do Tesseras. Um no que armazena fragmentos para milhares de -usuarios — comum para nos institucionais e nos completos sempre ligados — agora -paga o custo de disco apenas por dados unicos. Combinado com codificacao de -apagamento Reed-Solomon (que ja minimiza redundancia no nivel da rede), o -sistema alcanca armazenamento eficiente tanto nas camadas local quanto -distribuida.</p> -</content> - - </entry> - <entry xml:lang="pt-br"> - <title>Fase 4: Onboarding de Nos Institucionais</title> - <published>2026-02-15T22:00:00+00:00</published> - <updated>2026-02-15T22:00:00+00:00</updated> - - <author> - <name> - - Unknown - - </name> - </author> - - <link rel="alternate" type="text/html" href="https://tesseras.net/pt-br/news/phase4-institutional-onboarding/"/> - <id>https://tesseras.net/pt-br/news/phase4-institutional-onboarding/</id> - - <content type="html" xml:base="https://tesseras.net/pt-br/news/phase4-institutional-onboarding/"><p>Uma rede P2P composta apenas por individuos e fragil. Discos rigidos morrem, -celulares sao perdidos, pessoas perdem interesse. A sobrevivencia a longo prazo -das memorias da humanidade depende de instituicoes — bibliotecas, arquivos, -museus, universidades — que medem seus tempos de vida em seculos. A Fase 4 -continua com o onboarding de nos institucionais: organizacoes verificadas agora -podem prometer armazenamento, manter indices de busca e participar da rede com -uma identidade distinta.</p> -<p>O design segue um principio de confiar mas verificar: instituicoes se -identificam via registros DNS TXT (o mesmo mecanismo usado por SPF, DKIM e DMARC -para email), prometem um orcamento de armazenamento e recebem isencoes de -reciprocidade para que possam armazenar fragmentos para outros sem esperar nada -em troca. Em contrapartida, a rede trata seus fragmentos como replicas de maior -qualidade e limita a dependencia excessiva de qualquer instituicao individual -atraves de restricoes de diversidade.</p> -<h2 id="o-que-foi-construido">O que foi construido</h2> -<p><strong>Bits de capacidade</strong> (<code>tesseras-core/src/network.rs</code>) — Dois novos flags -adicionados ao bitfield <code>Capabilities</code>: <code>INSTITUTIONAL</code> (bit 7) e <code>SEARCH_INDEX</code> -(bit 8). Um novo construtor <code>institutional_default()</code> retorna o conjunto -completo de capacidades da Fase 2 mais esses dois bits e <code>RELAY</code>. Nos normais -anunciam <code>phase2_default()</code> que nao inclui flags institucionais. Testes de -roundtrip de serializacao verificam que os novos bits sobrevivem a codificacao -MessagePack.</p> -<p><strong>Tipos de busca</strong> (<code>tesseras-core/src/search.rs</code>) — Tres novos tipos de dominio -para o subsistema de busca:</p> -<ul> -<li><code>SearchFilters</code> — parametros de consulta: <code>memory_type</code>, <code>visibility</code>, -<code>language</code>, <code>date_range</code>, <code>geo</code> (bounding box), <code>page</code>, <code>page_size</code></li> -<li><code>SearchHit</code> — um resultado individual: hash do conteudo mais um -<code>MetadataExcerpt</code> (titulo, descricao, tipo de memoria, data de criacao, -visibilidade, idioma, tags)</li> -<li><code>GeoFilter</code> — bounding box com <code>min_lat</code>, <code>max_lat</code>, <code>min_lon</code>, <code>max_lon</code> para -consultas espaciais</li> -</ul> -<p>Todos os tipos derivam <code>Serialize</code>/<code>Deserialize</code> para transporte e -<code>Clone</code>/<code>Debug</code> para diagnostico.</p> -<p><strong>Configuracao institucional do daemon</strong> (<code>tesd/src/config.rs</code>) — Uma nova secao -<code>[institutional]</code> no TOML com <code>domain</code> (o dominio DNS a verificar), -<code>pledge_bytes</code> (compromisso de armazenamento em bytes) e <code>search_enabled</code> -(toggle para o indice FTS5). O metodo <code>to_dht_config()</code> agora define -<code>Capabilities::institutional_default()</code> quando a configuracao institucional esta -presente, para que nos institucionais anunciem os bits de capacidade corretos em -respostas Pong.</p> -<p><strong>Verificacao DNS TXT</strong> (<code>tesd/src/institutional.rs</code>) — Resolucao DNS assincrona -usando <code>hickory-resolver</code> para verificar identidade institucional. O daemon -consulta registros TXT em <code>_tesseras.&lt;dominio&gt;</code> e analisa campos chave-valor: -<code>v</code> (versao), <code>node</code> (node ID em hexadecimal) e <code>pledge</code> (compromisso de -armazenamento em bytes). A verificacao checa:</p> -<ol> -<li>Um registro TXT existe em <code>_tesseras.&lt;dominio&gt;</code></li> -<li>O campo <code>node</code> corresponde ao node ID do proprio daemon</li> -<li>O campo <code>pledge</code> esta presente e e valido</li> -</ol> -<p>Na inicializacao, o daemon tenta a verificacao DNS. Se bem-sucedida, o no roda -com capacidades institucionais. Se falhar, o no registra um aviso e faz -downgrade para um no completo normal — sem crash, sem intervencao manual.</p> -<p><strong>Comando CLI de setup</strong> (<code>tesseras-cli/src/institutional.rs</code>) — Um novo -subcomando <code>institutional setup</code> que guia operadores pelo onboarding:</p> -<ol> -<li>Le a identidade do no a partir do diretorio de dados</li> -<li>Solicita nome de dominio e tamanho do pledge</li> -<li>Gera o registro DNS TXT exato a adicionar: -<code>v=tesseras1 node=&lt;hex&gt; pledge=&lt;bytes&gt;</code></li> -<li>Escreve a secao institucional no arquivo de configuracao do daemon</li> -<li>Imprime os proximos passos: adicionar o registro TXT, reiniciar o daemon</li> -</ol> -<p><strong>Indice de busca SQLite</strong> (<code>tesseras-storage</code>) — Uma migracao -(<code>003_institutional.sql</code>) que cria tres estruturas:</p> -<ul> -<li><code>search_content</code> — uma tabela virtual FTS5 para busca full-text sobre -metadados de tesseras (titulo, descricao, criador, tags, idioma)</li> -<li><code>geo_index</code> — uma tabela virtual R-tree para consultas espaciais de bounding -box sobre latitude/longitude</li> -<li><code>geo_map</code> — uma tabela de mapeamento ligando IDs de linhas do R-tree a hashes -de conteudo</li> -</ul> -<p>O adaptador <code>SqliteSearchIndex</code> implementa o port trait <code>SearchIndex</code> com -<code>index_tessera()</code> (inserir/atualizar) e <code>search()</code> (consultar com filtros). -Consultas FTS5 suportam busca em linguagem natural; consultas geo usam -<code>INTERSECT</code> do R-tree para lookups de bounding box. Resultados sao ranqueados -por score de relevancia do FTS5.</p> -<p>A migracao tambem adiciona uma coluna <code>is_institutional</code> a tabela <code>reciprocity</code>, -tratada de forma idempotente via checagens <code>pragma_table_info</code> (o -<code>ALTER TABLE ADD COLUMN</code> do SQLite nao tem <code>IF NOT EXISTS</code>).</p> -<p><strong>Bypass de reciprocidade</strong> (<code>tesseras-replication/src/service.rs</code>) — Nos -institucionais sao isentos de checagens de reciprocidade. Quando -<code>receive_fragment()</code> e chamado, se o node ID do remetente esta marcado como -institucional no ledger de reciprocidade, a checagem de saldo e ignorada -completamente. Isso significa que instituicoes podem armazenar fragmentos para -toda a rede sem precisar "ganhar" creditos primeiro — sua identidade verificada -por DNS e compromisso de armazenamento servem como credencial.</p> -<p><strong>Restricao de diversidade por tipo de no</strong> -(<code>tesseras-replication/src/distributor.rs</code>) — Uma nova funcao -<code>apply_institutional_diversity()</code> limita quantas replicas de uma unica tessera -podem ir para nos institucionais. O limite e <code>ceil(fator_replicacao / 3.5)</code> — -com o padrao <code>r=7</code>, no maximo 2 de 7 replicas vao para instituicoes. Isso impede -que a rede se torne dependente de um pequeno numero de grandes instituicoes: se -os servidores de uma universidade cairem, pelo menos 5 replicas permanecem em -nos independentes.</p> -<p><strong>Extensoes de mensagens DHT</strong> (<code>tesseras-dht/src/message.rs</code>) — Duas novas -variantes de mensagem:</p> -<table><thead><tr><th>Mensagem</th><th>Proposito</th></tr></thead><tbody> -<tr><td><code>Search</code></td><td>Cliente envia string de consulta, filtros e numero da pagina</td></tr> -<tr><td><code>SearchResult</code></td><td>No institucional responde com resultados e contagem total</td></tr> -</tbody></table> -<p>A funcao <code>encode()</code> foi trocada de serializacao MessagePack posicional para -nomeada (<code>rmp_serde::to_vec_named</code>) para lidar corretamente com campos opcionais -de <code>SearchFilters</code> — a codificacao posicional quebra quando -<code>skip_serializing_if</code> omite campos.</p> -<p><strong>Metricas Prometheus</strong> (<code>tesd/src/metrics.rs</code>) — Oito metricas especificas -institucionais:</p> -<ul> -<li><code>tesseras_institutional_pledge_bytes</code> — compromisso de armazenamento -configurado</li> -<li><code>tesseras_institutional_stored_bytes</code> — bytes realmente armazenados</li> -<li><code>tesseras_institutional_pledge_utilization_ratio</code> — razao armazenado/prometido</li> -<li><code>tesseras_institutional_peers_served</code> — peers unicos que receberam fragmentos</li> -<li><code>tesseras_institutional_search_index_total</code> — tesseras no indice de busca</li> -<li><code>tesseras_institutional_search_queries_total</code> — consultas de busca recebidas</li> -<li><code>tesseras_institutional_dns_verification_status</code> — 1 se verificado por DNS, 0 -caso contrario</li> -<li><code>tesseras_institutional_dns_verification_last</code> — timestamp Unix da ultima -verificacao</li> -</ul> -<p><strong>Testes de integracao</strong> — Dois testes em -<code>tesseras-replication/tests/integration.rs</code>:</p> -<ul> -<li><code>institutional_peer_bypasses_reciprocity</code> — verifica que um peer institucional -com deficit massivo (-999.999 de saldo) ainda pode armazenar fragmentos, -enquanto um peer nao institucional com o mesmo deficit e rejeitado</li> -<li><code>institutional_node_accepts_fragment_despite_deficit</code> — teste async completo -usando <code>ReplicationService</code> com DHT, fragment store, reciprocity ledger e blob -store mockados: envia um fragmento de um remetente institucional e verifica -que e aceito</li> -</ul> -<p>322 testes passam em todo o workspace. Clippy limpo com <code>-D warnings</code>.</p> -<h2 id="decisoes-de-arquitetura">Decisoes de arquitetura</h2> -<ul> -<li><strong>DNS TXT ao inves de PKI ou blockchain</strong>: DNS e universalmente implantado, -universalmente compreendido e ja usado para verificacao de dominio (SPF, DKIM, -Let's Encrypt). Instituicoes ja gerenciam DNS. Nenhuma autoridade -certificadora, nenhum token, nenhuma transacao on-chain — apenas um registro -TXT. Se uma instituicao perder controle de seu dominio, a verificacao -naturalmente falha na proxima checagem.</li> -<li><strong>Degradacao graciosa em falha DNS</strong>: se a verificacao DNS falha na -inicializacao, o daemon faz downgrade para um no completo normal ao inves de -recusar iniciar. Isso previne incidentes operacionais — uma misconfiguracao -DNS nao deveria tirar um no do ar.</li> -<li><strong>Limite de diversidade em <code>ceil(r / 3.5)</code></strong>: com <code>r=7</code>, no maximo 2 replicas -vao para instituicoes. Isso e conservador — garante que a rede nunca dependa -de instituicoes para quorum majoritario, enquanto ainda se beneficia de sua -capacidade de armazenamento e uptime.</li> -<li><strong>Codificacao MessagePack nomeada</strong>: trocar de codificacao posicional para -nomeada adiciona ~15% de overhead por mensagem mas elimina uma classe de bugs -de serializacao quando campos opcionais estao presentes. O DHT nao e limitado -por largura de banda no nivel de mensagem, entao o tradeoff vale a pena.</li> -<li><strong>Isencao de reciprocidade ao inves de concessao de creditos</strong>: ao inves de -dar as instituicoes um saldo inicial grande de creditos (que e arbitrario e -precisa de ajuste), isentamos completamente. Sua identidade verificada por DNS -e compromisso publico de armazenamento substituem o mecanismo de reciprocidade -bilateral.</li> -<li><strong>FTS5 + R-tree no SQLite</strong>: busca full-text e indexacao espacial sao -embutidas no SQLite como extensoes carregaveis. Nenhum motor de busca externo -(Elasticsearch, Meilisearch) necessario. Isso mantem o deploy como um unico -binario com um unico arquivo de banco de dados — critico para operadores -institucionais que podem nao ter uma equipe de DevOps.</li> -</ul> -<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2> -<ul> -<li><strong>Fase 4 continuacao</strong> — deduplicacao de armazenamento (armazenamento -enderecavel por conteudo com BLAKE3), auditorias de seguranca, empacotamento -para OS (Alpine, Arch, Debian, OpenBSD, FreeBSD)</li> -<li><strong>Fase 5: Exploracao e Cultura</strong> — navegador publico de tesseras por -era/localizacao/tema/idioma, curadoria institucional, integracao genealogica -(FamilySearch, Ancestry), exportacao para midia fisica (M-DISC, microfilme, -papel livre de acido com QR), contexto assistido por IA</li> -</ul> -<p>O onboarding institucional fecha uma lacuna critica no modelo de preservacao do -Tesseras. Nos individuais fornecem resiliencia de base — milhares de -dispositivos ao redor do globo, cada um armazenando alguns fragmentos. Nos -institucionais fornecem ancoragem — organizacoes com infraestrutura -profissional, armazenamento redundante e horizontes operacionais de multiplas -decadas. Juntos, formam uma rede onde memorias podem sobreviver tanto a -dispositivos individuais quanto a instituicoes individuais.</p> -</content> - - </entry> - <entry xml:lang="pt-br"> - <title>Fase 4: Tuning de Performance</title> - <published>2026-02-15T20:00:00+00:00</published> - <updated>2026-02-15T20:00:00+00:00</updated> - - <author> - <name> - - Unknown - - </name> - </author> - - <link rel="alternate" type="text/html" href="https://tesseras.net/pt-br/news/phase4-performance-tuning/"/> - <id>https://tesseras.net/pt-br/news/phase4-performance-tuning/</id> - - <content type="html" xml:base="https://tesseras.net/pt-br/news/phase4-performance-tuning/"><p>Uma rede P2P que atravessa NATs mas engasga com seu proprio I/O nao serve de -muito. A Fase 4 continua com tuning de performance: centralizacao da -configuracao do banco de dados, cache de blobs de fragmentos em memoria, -gerenciamento de ciclo de vida de conexoes QUIC e eliminacao de leituras -desnecessarias de disco no hot path de atestacao.</p> -<p>O principio orientador foi o mesmo do resto do Tesseras: fazer a coisa mais -simples que realmente funciona. Sem alocadores customizados, sem estruturas de -dados lock-free, sem complexidade prematura. Um <code>StorageConfig</code> centralizado, um -cache LRU, um reaper de conexoes e uma correcao pontual para evitar reler blobs -que ja tinham checksum calculado.</p> -<h2 id="o-que-foi-construido">O que foi construido</h2> -<p><strong>Configuracao SQLite centralizada</strong> (<code>tesseras-storage/src/database.rs</code>) — Um -novo struct <code>StorageConfig</code> e funcoes <code>open_database()</code> / <code>open_in_memory()</code> que -aplicam todos os pragmas SQLite em um unico lugar: journal mode WAL, foreign -keys, modo synchronous (NORMAL por padrao, FULL para hardware instavel como -RPi + cartao SD), busy timeout, tamanho do cache de paginas e intervalo de -autocheckpoint WAL. Anteriormente, cada ponto de chamada abria uma conexao e -aplicava pragmas ad hoc. Agora o daemon, CLI e testes passam todos pelo mesmo -caminho. 7 testes cobrindo foreign keys, busy timeout, journal mode, migracoes, -modos synchronous e criacao de arquivos WAL em disco.</p> -<p><strong>Cache LRU de fragmentos</strong> (<code>tesseras-storage/src/cache.rs</code>) — Um -<code>CachedFragmentStore</code> que envolve qualquer <code>FragmentStore</code> com um cache LRU -ciente de bytes. Blobs de fragmentos sao cacheados na leitura e invalidados na -escrita ou exclusao. Quando o cache excede seu limite de bytes configurado, as -entradas menos recentemente usadas sao removidas. O cache e transparente: ele -proprio implementa <code>FragmentStore</code>, entao o resto da pilha nao sabe que esta la. -Metricas Prometheus opcionais rastreiam hits, misses e uso atual de bytes. 3 -testes: hit no cache evita leitura interna, store invalida cache, remocao quando -excede bytes maximos.</p> -<p><strong>Metricas Prometheus de storage</strong> (<code>tesseras-storage/src/metrics.rs</code>) — Um -struct <code>StorageMetrics</code> com tres contadores/gauges: <code>fragment_cache_hits</code>, -<code>fragment_cache_misses</code> e <code>fragment_cache_bytes</code>. Registrado no registry -Prometheus e conectado ao cache de fragmentos via <code>with_metrics()</code>.</p> -<p><strong>Correcao do hot path de atestacao</strong> (<code>tesseras-replication/src/service.rs</code>) — -O fluxo de atestacao anteriormente lia cada blob de fragmento do disco e -recalculava seu checksum BLAKE3. Como <code>list_fragments()</code> ja retorna <code>FragmentId</code> -com um checksum armazenado, a correcao e trivial: usar <code>frag.checksum</code> ao inves -de <code>blake3::hash(&amp;data)</code>. Isso elimina uma leitura de disco por fragmento -durante atestacao — para uma tessera com 100 fragmentos, sao 100 leituras a -menos. Um teste com <code>expect_read_fragment().never()</code> verifica que nenhuma -leitura de blob acontece durante atestacao.</p> -<p><strong>Ciclo de vida do pool de conexoes QUIC</strong> -(<code>tesseras-net/src/quinn_transport.rs</code>) — Um struct <code>PoolConfig</code> controlando -maximo de conexoes, timeout de inatividade e intervalo do reaper. -<code>PooledConnection</code> envolve cada <code>quinn::Connection</code> com um timestamp -<code>last_used</code>. Quando o pool atinge capacidade maxima, a conexao inativa mais -antiga e removida antes de abrir uma nova. Uma tarefa reaper em background -(Tokio spawn) periodicamente fecha conexoes que ficaram inativas alem do -timeout. 4 novas metricas de pool: <code>tesseras_conn_pool_size</code>, <code>pool_hits_total</code>, -<code>pool_misses_total</code>, <code>pool_evictions_total</code>.</p> -<p><strong>Integracao no daemon</strong> (<code>tesd/src/config.rs</code>, <code>main.rs</code>) — Uma nova secao -<code>[performance]</code> na configuracao TOML com campos para tamanho de cache SQLite, -modo synchronous, busy timeout, tamanho de cache de fragmentos, maximo de -conexoes, timeout de inatividade e intervalo do reaper. O <code>main()</code> do daemon -agora chama <code>open_database()</code> com o <code>StorageConfig</code> configurado, envolve -<code>FsFragmentStore</code> com <code>CachedFragmentStore</code> e vincula QUIC com o <code>PoolConfig</code> -configurado. A dependencia direta de <code>rusqlite</code> foi removida do crate do daemon.</p> -<p><strong>Migracao do CLI</strong> (<code>tesseras-cli/src/commands/init.rs</code>, <code>create.rs</code>) — Ambos -os comandos <code>init</code> e <code>create</code> agora usam <code>tesseras_storage::open_database()</code> com -o <code>StorageConfig</code> padrao ao inves de abrir conexoes <code>rusqlite</code> diretamente. A -dependencia de <code>rusqlite</code> foi removida do crate do CLI.</p> -<h2 id="decisoes-de-arquitetura">Decisoes de arquitetura</h2> -<ul> -<li><strong>Padrao decorator para cache</strong>: <code>CachedFragmentStore</code> envolve -<code>Box&lt;dyn FragmentStore&gt;</code> e implementa <code>FragmentStore</code> ele proprio. Isso -significa que cache e opt-in, composavel e invisivel para consumidores. O -daemon habilita; testes podem pular.</li> -<li><strong>Remocao ciente de bytes</strong>: o cache LRU rastreia bytes totais, nao contagem -de entradas. Blobs de fragmentos variam muito em tamanho (um fragmento de -texto de 4KB vs um shard de foto de 2MB), entao contar entradas daria uma -visao enganosa do uso de memoria.</li> -<li><strong>Sem crate de pool de conexoes</strong>: ao inves de trazer uma biblioteca generica -de pool, o pool de conexoes e um wrapper fino sobre -<code>DashMap&lt;SocketAddr, PooledConnection&gt;</code> com um reaper Tokio. Conexoes QUIC sao -multiplexadas, entao o "pool" e realmente sobre gerenciamento de ciclo de vida -(limpeza de inativos, maximo de conexoes) e nao sobre emprestar/devolver.</li> -<li><strong>Checksums armazenados ao inves de releituras</strong>: a correcao de atestacao e -intencionalmente minima — uma linha alterada, uma leitura de disco removida -por fragmento. Os checksums ja estavam armazenados no SQLite por -<code>store_fragment()</code>, apenas nao estavam sendo usados.</li> -<li><strong>Configuracao centralizada de pragmas</strong>: um unico struct <code>StorageConfig</code> -substitui chamadas <code>PRAGMA</code> espalhadas. O flag <code>sqlite_synchronous_full</code> -existe especificamente para implantacoes em Raspberry Pi onde o kernel pode -crashar e perder transacoes WAL nao checkpointadas.</li> -</ul> -<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2> -<ul> -<li><strong>Fase 4 continuacao</strong> — Shamir's Secret Sharing para herdeiros, tesseras -seladas (criptografia time-lock), auditorias de seguranca, onboarding de nos -institucionais, deduplicacao de storage, empacotamento para OS</li> -<li><strong>Fase 5: Exploracao e Cultura</strong> — navegador publico de tesseras por -era/localizacao/tema/idioma, curadoria institucional, integracao genealogica, -exportacao para midia fisica (M-DISC, microfilme, papel livre de acido com QR)</li> -</ul> -<p>Com tuning de performance implementado, Tesseras lida com o caso comum de forma -eficiente: leituras de fragmentos acertam o cache LRU, atestacao pula I/O de -disco, conexoes QUIC inativas sao removidas automaticamente e o SQLite e -configurado consistentemente em toda a pilha. Os proximos passos focam em -funcionalidades criptograficas (Shamir, time-lock) e hardening para implantacao -em producao.</p> -</content> - - </entry> - <entry xml:lang="pt-br"> - <title>Fase 4: Verificar Sem Instalar Nada</title> - <published>2026-02-15T20:00:00+00:00</published> - <updated>2026-02-15T20:00:00+00:00</updated> - - <author> - <name> - - Unknown - - </name> - </author> - - <link rel="alternate" type="text/html" href="https://tesseras.net/pt-br/news/phase4-wasm-browser-verification/"/> - <id>https://tesseras.net/pt-br/news/phase4-wasm-browser-verification/</id> - - <content type="html" xml:base="https://tesseras.net/pt-br/news/phase4-wasm-browser-verification/"><p>Confiança não deveria exigir instalação de software. Se alguém te envia uma -tessera — um pacote de memórias preservadas — você deveria poder verificar que é -genuína e não foi modificada sem baixar um app, criar uma conta, ou confiar em -um servidor. É isso que o <code>tesseras-wasm</code> entrega: arraste um arquivo tessera -para uma página web, e a verificação criptográfica acontece inteiramente no seu -navegador.</p> -<h2 id="o-que-foi-construido">O que foi construído</h2> -<p><strong>tesseras-wasm</strong> — Um crate Rust que compila para WebAssembly via wasm-pack, -expondo quatro funções stateless para JavaScript. O crate depende do -<code>tesseras-core</code> para parsing do manifesto e chama primitivas criptográficas -diretamente (blake3, ed25519-dalek) ao invés de depender do <code>tesseras-crypto</code>, -que puxa bibliotecas pós-quânticas baseadas em C que não compilam para -<code>wasm32-unknown-unknown</code>.</p> -<p><code>parse_manifest</code> recebe os bytes brutos do MANIFEST (texto UTF-8 plano, não -MessagePack), delega para <code>tesseras_core::manifest::Manifest::parse()</code>, e -retorna uma string JSON com a chave pública Ed25519 do criador, caminhos dos -arquivos de assinatura, e uma lista de arquivos com seus hashes BLAKE3 -esperados, tamanhos e tipos MIME. Structs internas (<code>ManifestJson</code>, -<code>CreatorPubkey</code>, <code>SignatureFiles</code>, <code>FileEntry</code>) são serializadas com serde_json. -Os campos de chave pública ML-DSA e arquivo de assinatura estão presentes no -contrato JSON mas definidos como <code>null</code> — prontos para quando a assinatura -pós-quântica for implementada no lado nativo.</p> -<p><code>hash_blake3</code> computa um hash BLAKE3 de bytes arbitrários e retorna uma string -hexadecimal de 64 caracteres. É chamada uma vez por arquivo na tessera para -verificar integridade contra o MANIFEST.</p> -<p><code>verify_ed25519</code> recebe uma mensagem, uma assinatura de 64 bytes e uma chave -pública de 32 bytes, constrói uma <code>ed25519_dalek::VerifyingKey</code>, e retorna se a -assinatura é válida. A validação de comprimento retorna erros descritivos -("Ed25519 public key must be 32 bytes") ao invés de causar panic.</p> -<p><code>verify_ml_dsa</code> é um stub que retorna um erro explicando que verificação ML-DSA -ainda não está disponível. Isso é deliberado: o crate <code>ml-dsa</code> no crates.io está -na v0.1.0-rc.7 (pré-release), e o <code>tesseras-crypto</code> usa <code>pqcrypto-dilithium</code> -(CRYSTALS-Dilithium baseado em C) que é incompatível em nível de bytes com FIPS -204 ML-DSA. Ambos os lados precisam usar a mesma implementação em Rust puro -antes que a verificação cruzada funcione. Verificação Ed25519 é suficiente — -toda tessera é assinada com Ed25519.</p> -<p>Todas as quatro funções usam um padrão de duas camadas para testabilidade: -funções internas retornam <code>Result&lt;T, String&gt;</code> e são testadas nativamente, -enquanto wrappers finos <code>#[wasm_bindgen]</code> convertem erros para <code>JsError</code>. Isso -evita que <code>JsError::new()</code> cause panic em targets não-WASM durante os testes.</p> -<p>O binário WASM compilado tem 109 KB bruto e 44 KB com gzip — bem abaixo do -orçamento de 200 KB. O wasm-opt aplica otimização <code>-Oz</code> após o wasm-pack -compilar com <code>opt-level = "z"</code>, LTO e uma única unidade de codegen.</p> -<p><strong>@tesseras/verify</strong> — Um pacote npm TypeScript (<code>crates/tesseras-wasm/js/</code>) que -orquestra a verificação no lado do navegador. A API pública é uma única função:</p> -<pre><code data-lang="typescript">async function verifyTessera( - archive: Uint8Array, - onProgress?: (current: number, total: number, file: string) =&gt; void -): Promise&lt;VerificationResult&gt; -</code></pre> -<p>O tipo <code>VerificationResult</code> fornece tudo que uma UI precisa: validade geral, -hash da tessera, chaves públicas do criador, status das assinaturas -(valid/invalid/missing para Ed25519 e ML-DSA), resultados de integridade por -arquivo com hashes esperados e reais, uma lista de arquivos inesperados não -presentes no MANIFEST, e um array de erros.</p> -<p>A descompactação de arquivos (<code>unpack.ts</code>) lida com três formatos: tar -comprimido com gzip (detectado pelos magic bytes <code>\x1f\x8b</code>, descomprimido com -fflate e depois parseado como tar), ZIP (magic <code>PK\x03\x04</code>, descompactado com -<code>unzipSync</code> do fflate), e tar bruto (<code>ustar</code> no offset 257). Uma função -<code>normalizePath</code> remove o prefixo <code>tessera-&lt;hash&gt;/</code> para que os caminhos internos -correspondam às entradas do MANIFEST.</p> -<p>A verificação roda em um Web Worker (<code>worker.ts</code>) para manter a thread da UI -responsiva. O worker inicializa o módulo WASM, descompacta o arquivo, parseia o -MANIFEST, verifica a assinatura Ed25519 contra a chave pública do criador, -depois faz hash de cada arquivo com BLAKE3 e compara com os valores esperados. -Mensagens de progresso são transmitidas de volta para a thread principal após -cada arquivo. Se qualquer assinatura é inválida, a verificação para -imediatamente sem fazer hash dos arquivos — falhando rápido na verificação mais -crítica.</p> -<p>O arquivo é transferido para o worker com zero-copy -(<code>worker.postMessage({ type: "verify", archive }, [archive.buffer])</code>) para -evitar duplicar arquivos de tessera potencialmente grandes na memória.</p> -<p><strong>Pipeline de build</strong> — Três novos targets no justfile: <code>wasm-build</code> executa -wasm-pack com <code>--target web --release</code> e otimiza com wasm-opt; <code>wasm-size</code> -reporta o tamanho do binário bruto e com gzip; <code>test-wasm</code> executa a suíte de -testes nativos.</p> -<p><strong>Testes</strong> — 9 testes unitários nativos cobrem hashing BLAKE3 (entrada vazia, -valor conhecido), verificação Ed25519 (assinatura válida, assinatura inválida, -chave errada, comprimento de chave inválido), e parsing do MANIFEST (manifesto -válido, UTF-8 inválido, lixo). 3 testes de integração WASM rodam em Chrome -headless via <code>wasm-pack test --headless --chrome</code>, verificando que -<code>hash_blake3</code>, <code>verify_ed25519</code> e <code>parse_manifest</code> funcionam corretamente quando -compilados para <code>wasm32-unknown-unknown</code>.</p> -<h2 id="decisoes-de-arquitetura">Decisões de arquitetura</h2> -<ul> -<li><strong>Sem dependência do tesseras-crypto</strong>: o crate WASM chama blake3 e -ed25519-dalek diretamente. O <code>tesseras-crypto</code> depende do <code>pqcrypto-kyber</code> -(ML-KEM baseado em C via pqcrypto-traits) que requer um toolchain de -compilador C e não tem target wasm32. Dependendo apenas de crates Rust puros, -o build WASM tem zero dependências C e compila sem problemas para WebAssembly.</li> -<li><strong>ML-DSA adiado, não fingido</strong>: ao invés de silenciosamente pular a -verificação pós-quântica, o stub retorna um erro explícito. Isso garante que -se uma tessera contiver uma assinatura ML-DSA, o resultado da verificação -reportará <code>ml_dsa: "missing"</code> ao invés de fingir que foi verificada. O -orquestrador JS lida com isso graciosamente — uma tessera é válida se Ed25519 -passar e ML-DSA estiver ausente (ainda não implementado em nenhum dos lados).</li> -<li><strong>Padrão de função interna</strong>: <code>JsError</code> não pode ser construído em targets -não-WASM (causa panic). Dividir cada função em -<code>foo_inner() -&gt; Result&lt;T, String&gt;</code> e <code>foo() -&gt; Result&lt;T, JsError&gt;</code> permite que -a suíte de testes nativa exercite toda a lógica sem tocar em tipos JavaScript. -Os testes de integração WASM em Chrome headless testam a superfície completa -do <code>#[wasm_bindgen]</code>.</li> -<li><strong>Isolamento em Web Worker</strong>: operações criptográficas (especialmente BLAKE3 -sobre arquivos de mídia grandes) podem levar centenas de milissegundos. Rodar -em um Worker previne travamentos na UI. O protocolo de progresso com streaming -(<code>{ type: "progress", current, total, file }</code>) permite que a UI mostre uma -barra de progresso durante a verificação de tesseras com muitos arquivos.</li> -<li><strong>Transferência zero-copy</strong>: <code>archive.buffer</code> é transferido para o Worker, não -copiado. Para um arquivo tessera de 50 MB, isso evita dobrar o uso de memória -durante a verificação.</li> -<li><strong>MANIFEST em texto plano, não MessagePack</strong>: o crate WASM parseia o mesmo -formato de MANIFEST em texto plano que o CLI. Isso é por design — o MANIFEST é -a Pedra de Rosetta da tessera, legível por qualquer pessoa com um editor de -texto. A dependência <code>rmp-serde</code> no Cargo.toml não é usada e será removida.</li> -</ul> -<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2> -<ul> -<li><strong>Fase 4: Resiliência e Escala</strong> — Empacotamento para sistemas operacionais -(Alpine, Arch, Debian, FreeBSD, OpenBSD), CI no SourceHut e GitHub Actions, -auditorias de segurança, explorador de tesseras no navegador em tesseras.net -usando @tesseras/verify</li> -<li><strong>Fase 5: Exploração e Cultura</strong> — Navegador público de tesseras por -era/localização/tema/idioma, curadoria institucional, integração com -genealogia, exportação para mídia física (M-DISC, microfilme, papel livre de -ácido com QR)</li> -</ul> -<p>A verificação não exige mais confiança em software. Um arquivo tessera arrastado -para um navegador é verificado com o mesmo rigor criptográfico do CLI — mesmos -hashes BLAKE3, mesmas assinaturas Ed25519, mesmo parser de MANIFEST. A diferença -é que agora qualquer pessoa pode fazer isso.</p> -</content> - - </entry> - <entry xml:lang="pt-br"> - <title>Fase 4: Furando NATs</title> - <published>2026-02-15T18:00:00+00:00</published> - <updated>2026-02-15T18:00:00+00:00</updated> - - <author> - <name> - - Unknown - - </name> - </author> - - <link rel="alternate" type="text/html" href="https://tesseras.net/pt-br/news/phase4-nat-traversal/"/> - <id>https://tesseras.net/pt-br/news/phase4-nat-traversal/</id> - - <content type="html" xml:base="https://tesseras.net/pt-br/news/phase4-nat-traversal/"><p>A maioria dos dispositivos das pessoas ficam atras de um NAT — um tradutor de -enderecos de rede que permite acessar a internet mas impede conexoes de entrada. -Para uma rede P2P, isso e um problema existencial: se dois nos atras de NATs nao -conseguem se comunicar, a rede se fragmenta. A Fase 4 continua com uma pilha -completa de travessia de NAT: descoberta via STUN, hole punching coordenado e -fallback por relay.</p> -<p>A abordagem segue o mesmo padrao da maioria dos sistemas P2P consolidados -(WebRTC, BitTorrent, IPFS): tente a opcao mais barata primeiro, escale apenas -quando necessario. Conectividade direta nao custa nada. Hole punching custa -alguns pacotes coordenados. Relay custa largura de banda sustentada de um -terceiro. Tesseras tenta nessa ordem.</p> -<h2 id="o-que-foi-construido">O que foi construido</h2> -<p><strong>Classificacao NatType</strong> (<code>tesseras-core/src/network.rs</code>) — Um novo enum -<code>NatType</code> (Public, Cone, Symmetric, Unknown) adicionado a camada de dominio -core. Esse tipo e compartilhado por toda a pilha: o cliente STUN o escreve, o -DHT o divulga em mensagens Pong, e o coordenador de punch o le para decidir se -hole punching vale a pena tentar (Cone-para-Cone funciona ~80% das vezes; -Symmetric-para-Symmetric quase nunca funciona).</p> -<p><strong>Cliente STUN</strong> (<code>tesseras-net/src/stun.rs</code>) — Uma implementacao STUN minima -(RFC 5389 Binding Request/Response) que descobre o endereco externo de um no. O -codec codifica requisicoes de 20 bytes com um ID de transacao aleatorio e -decodifica respostas XOR-MAPPED-ADDRESS. A funcao <code>discover_nat()</code> consulta -multiplos servidores STUN em paralelo (Google, Cloudflare por padrao), compara -os enderecos mapeados e classifica o tipo de NAT:</p> -<ul> -<li>Mesmo IP e porta de todos os servidores → <strong>Public</strong> (sem NAT)</li> -<li>Mesmo endereco mapeado de todos os servidores → <strong>Cone</strong> (hole punching -funciona)</li> -<li>Enderecos mapeados diferentes → <strong>Symmetric</strong> (hole punching nao confiavel)</li> -<li>Sem respostas → <strong>Unknown</strong></li> -</ul> -<p>Retentativas com backoff exponencial e timeouts configuraveis. 12 testes -cobrindo roundtrips de codec, todos os caminhos de classificacao e consultas -async em loopback.</p> -<p><strong>Coordenacao de punch assinada</strong> (<code>tesseras-net/src/punch.rs</code>) — Assinatura e -verificacao Ed25519 para mensagens <code>PunchIntro</code>, <code>RelayRequest</code> e -<code>RelayMigrate</code>. Cada introducao e assinada pelo iniciador com uma janela de -timestamp de 30 segundos, prevenindo ataques de reflexao (onde um atacante -reproduz uma introducao antiga para redirecionar trafego). O formato do payload -e <code>target || external_addr || timestamp</code> — alterar qualquer campo invalida a -assinatura. 6 testes unitarios mais 3 testes baseados em propriedades com -proptest (IDs de no, portas e tokens de sessao arbitrarios).</p> -<p><strong>Gerenciador de sessoes de relay</strong> (<code>tesseras-net/src/relay.rs</code>) — Gerencia -sessoes de relay UDP transparente entre nos com NAT. Cada sessao tem um token -aleatorio de 16 bytes; os nos prefixam seus pacotes com o token, o relay remove -e encaminha. Funcionalidades:</p> -<ul> -<li>Encaminhamento bidirecional (A→R→B e B→R→A)</li> -<li>Limite de taxa: 256 KB/s para nos reciprocos, 64 KB/s para nao reciprocos</li> -<li>Duracao maxima de 10 minutos para sessoes bootstrap (nao reciprocas)</li> -<li>Migracao de endereco: quando o IP de um no muda (Wi-Fi para celular), um -<code>RelayMigrate</code> assinado atualiza a sessao sem derruba-la</li> -<li>Limpeza por inatividade com timeout configuravel</li> -<li>8 testes unitarios mais 2 testes baseados em propriedades</li> -</ul> -<p><strong>Extensoes de mensagens DHT</strong> (<code>tesseras-dht/src/message.rs</code>) — Sete novas -variantes de mensagem adicionadas ao protocolo DHT:</p> -<table><thead><tr><th>Mensagem</th><th>Proposito</th></tr></thead><tbody> -<tr><td><code>PunchIntro</code></td><td>"Quero conectar ao no X, aqui esta meu endereco externo assinado"</td></tr> -<tr><td><code>PunchRequest</code></td><td>O introdutor encaminha a requisicao ao destino</td></tr> -<tr><td><code>PunchReady</code></td><td>O destino confirma prontidao, envia seu endereco externo</td></tr> -<tr><td><code>RelayRequest</code></td><td>"Crie uma sessao de relay para o no X"</td></tr> -<tr><td><code>RelayOffer</code></td><td>O relay responde com seu endereco e token de sessao</td></tr> -<tr><td><code>RelayClose</code></td><td>Encerrar uma sessao de relay</td></tr> -<tr><td><code>RelayMigrate</code></td><td>Atualizar sessao apos mudanca de rede</td></tr> -</tbody></table> -<p>A mensagem <code>Pong</code> foi estendida com metadados NAT: <code>nat_type</code>, -<code>relay_slots_available</code> e <code>relay_bandwidth_used_kbps</code>. Todos os novos campos -usam <code>#[serde(default)]</code> para compatibilidade retroativa — nos antigos ignoram o -que nao reconhecem, nos novos usam defaults. 9 novos testes de roundtrip de -serializacao.</p> -<p><strong>Trait NatHandler e dispatch</strong> (<code>tesseras-dht/src/engine.rs</code>) — Uma nova trait -async <code>NatHandler</code> (5 metodos) injetada no engine DHT, seguindo o mesmo padrao -de injecao de dependencia do <code>ReplicationHandler</code> existente. O loop de dispatch -de mensagens do engine agora roteia todas as mensagens punch/relay para o -handler. Isso mantem o engine DHT agnóstico ao protocolo enquanto permite que a -logica de travessia de NAT viva em <code>tesseras-net</code>.</p> -<p><strong>Tipos de reconexao mobile</strong> (<code>tesseras-embedded/src/reconnect.rs</code>) — Uma -maquina de estados de reconexao em tres fases para dispositivos moveis:</p> -<ol> -<li><strong>QuicMigration</strong> (0-2s) — tenta migracao de conexao QUIC para todos os peers -ativos</li> -<li><strong>ReStun</strong> (2-5s) — redescobre endereco externo via STUN</li> -<li><strong>ReEstablish</strong> (5-10s) — reconecta peers que a migracao nao conseguiu salvar</li> -</ol> -<p>Peers sao reconectados em ordem de prioridade: nos bootstrap primeiro, depois -nos que guardam nossos fragmentos, depois nos cujos fragmentos guardamos, depois -vizinhos DHT gerais. Uma nova variante de evento <code>NetworkChanged</code> foi adicionada -ao stream de eventos FFI para que o app Flutter possa mostrar progresso de -reconexao.</p> -<p><strong>Configuracao NAT do daemon</strong> (<code>tesd/src/config.rs</code>) — Uma nova secao <code>[nat]</code> -na configuracao TOML com lista de servidores STUN, toggle de relay, maximo de -sessoes relay, limites de largura de banda (reciproco vs bootstrap) e timeout de -inatividade. Todos os campos tem defaults sensiveis; relay e desabilitado por -padrao.</p> -<p><strong>Metricas Prometheus</strong> (<code>tesseras-net/src/metrics.rs</code>) — 16 metricas em quatro -subsistemas:</p> -<ul> -<li><strong>STUN</strong>: requisicoes, falhas, histograma de latencia</li> -<li><strong>Punch</strong>: tentativas/sucessos/falhas (por par de tipo NAT), histograma de -latencia</li> -<li><strong>Relay</strong>: sessoes ativas, sessoes totais, bytes encaminhados, timeouts por -inatividade, hits de rate limit</li> -<li><strong>Reconexao</strong>: mudancas de rede, tentativas/sucessos por fase, histograma de -duracao</li> -</ul> -<p>6 testes verificando registro, incremento, cardinalidade de labels e deteccao de -registro duplo.</p> -<p><strong>Testes de integracao</strong> — Dois testes end-to-end usando <code>MemTransport</code> (rede -simulada em memoria):</p> -<ul> -<li><code>punch_integration.rs</code> — Fluxo completo de hole-punch com 3 nos: A envia -<code>PunchIntro</code> assinado ao introdutor I, I verifica e encaminha <code>PunchRequest</code> a -B, B verifica a assinatura original e envia <code>PunchReady</code> de volta, A e B -trocam mensagens diretamente. Tambem testa que uma assinatura invalida e -corretamente rejeitada.</li> -<li><code>relay_integration.rs</code> — Fluxo completo de relay com 3 nos: A solicita relay -de R, R cria sessao e envia <code>RelayOffer</code> a ambos os peers, A e B trocam -pacotes prefixados com token atraves de R, A migra para um novo endereco no -meio da sessao, A fecha a sessao, e o teste verifica que a sessao e encerrada -e encaminhamento posterior falha.</li> -</ul> -<p><strong>Testes de propriedade</strong> — 7 testes baseados em proptest cobrindo: roundtrips -de assinatura para todos os tres tipos de mensagem assinada (IDs de no, portas e -tokens arbitrarios), determinismo de classificacao NAT (mesmas entradas sempre -produzem mesma saida), validade de binding request STUN, unicidade de tokens de -sessao, e rejeicao de pacotes curtos pelo relay.</p> -<p><strong>Alvos Justfile</strong> — <code>just test-nat</code> executa todos os testes de travessia NAT em -<code>tesseras-net</code> e <code>tesseras-dht</code>. <code>just test-chaos</code> e um placeholder para futuros -testes de caos com Docker Compose e <code>tc netem</code>.</p> -<h2 id="decisoes-de-arquitetura">Decisoes de arquitetura</h2> -<ul> -<li><strong>STUN ao inves de TURN</strong>: implementamos STUN (descoberta) e relay customizado -ao inves de TURN completo. TURN requer alocacao autenticada e foi projetado -para relay de midia; nosso relay e mais simples — encaminhamento UDP com -prefixo de token e limites de taxa. Isso mantem o protocolo minimo e evita -depender de servidores TURN externos.</li> -<li><strong>Assinaturas em introducoes</strong>: cada <code>PunchIntro</code> e assinado pelo iniciador. -Sem isso, um atacante poderia enviar introducoes forjadas para redirecionar as -tentativas de hole-punch de um no para um endereco controlado pelo atacante -(ataque de reflexao). A janela de timestamp de 30 segundos limita replay.</li> -<li><strong>Tiers reciprocos de largura de banda</strong>: nos relay dao 4x mais largura de -banda (256 vs 64 KB/s) para peers com boas pontuacoes de reciprocidade. Isso -incentiva nos a armazenar fragmentos para outros — se voce contribui, recebe -melhor servico de relay quando precisa.</li> -<li><strong>Extensao Pong retrocompativel</strong>: novos campos NAT em <code>Pong</code> usam -<code>#[serde(default)]</code> e <code>Option&lt;T&gt;</code>. Nos antigos que nao entendem esses campos -simplesmente os pulam durante deserializacao. Nenhum bump de versao de -protocolo necessario.</li> -<li><strong>NatHandler como trait async</strong>: a logica de travessia NAT e injetada no -engine DHT via trait, assim como <code>ReplicationHandler</code>. Isso mantem o engine -DHT focado em roteamento e gerenciamento de peers, e permite que a -implementacao NAT seja trocada ou desabilitada sem tocar no codigo core do -DHT.</li> -</ul> -<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2> -<ul> -<li><strong>Fase 4 continuacao</strong> — tuning de performance (pooling de conexoes, cache de -fragmentos, SQLite WAL), auditorias de seguranca, onboarding de nos -institucionais, empacotamento para OS</li> -<li><strong>Fase 5: Exploracao e Cultura</strong> — navegador publico de tesseras por -era/localizacao/tema/idioma, curadoria institucional, integracao genealogica, -exportacao para midia fisica (M-DISC, microfilme, papel livre de acido com QR)</li> -</ul> -<p>Com travessia de NAT, Tesseras pode conectar nos independentemente de sua -topologia de rede. Nos publicos conversam diretamente. Nos com NAT Cone furam -com ajuda de um introdutor. Nos com NAT Symmetric ou firewalled usam relay -atraves de peers voluntarios. A rede se adapta ao mundo real, onde a maioria dos -dispositivos esta atras de um NAT e as condicoes de rede mudam constantemente.</p> -</content> - - </entry> - <entry xml:lang="pt-br"> - <title>CLI Encontra a Rede: Comandos Publish, Fetch e Status</title> - <published>2026-02-15T00:00:00+00:00</published> - <updated>2026-02-15T00:00:00+00:00</updated> - - <author> - <name> - - Unknown - - </name> - </author> - - <link rel="alternate" type="text/html" href="https://tesseras.net/pt-br/news/cli-daemon-rpc/"/> - <id>https://tesseras.net/pt-br/news/cli-daemon-rpc/</id> - - <content type="html" xml:base="https://tesseras.net/pt-br/news/cli-daemon-rpc/"><p>Até agora o CLI operava isoladamente: criar uma tessera, verificar, exportar, -listar o que você tem. Tudo ficava na sua máquina. Com esta atualização, o <code>tes</code> -ganha três comandos que fazem a ponte entre o armazenamento local e a rede P2P — -<code>publish</code>, <code>fetch</code> e <code>status</code> — comunicando-se com um <code>tesd</code> em execução através -de um socket Unix.</p> -<h2 id="o-que-foi-construido">O que foi construído</h2> -<p><strong>Crate <code>tesseras-rpc</code></strong> — Um novo crate compartilhado entre CLI e daemon. -Define o protocolo RPC usando serialização MessagePack com enquadramento -prefixado por tamanho (cabeçalho big-endian de 4 bytes, máximo de 64 MiB). Três -tipos de requisição (<code>Publish</code>, <code>Fetch</code>, <code>Status</code>) e suas respostas -correspondentes. Um <code>DaemonClient</code> síncrono gerencia a conexão do socket Unix -com timeouts configuráveis. O protocolo é deliberadamente simples — uma -requisição, uma resposta, conexão fechada — para manter a implementação -auditável.</p> -<p><strong><code>tes publish &lt;hash&gt;</code></strong> — Publica uma tessera na rede. Aceita hashes completos -ou prefixos curtos (ex.: <code>tes publish a1b2</code>), que são resolvidos no banco de -dados local. O daemon lê todos os arquivos da tessera do armazenamento, empacota -em um único buffer MessagePack e entrega ao motor de replicação. Tesseras -pequenas (&lt; 4 MB) são replicadas como um único fragmento; maiores passam por -codificação de apagamento Reed-Solomon. A saída mostra o hash curto e a contagem -de fragmentos:</p> -<pre><code>Published tessera 9f2c4a1b (24 fragments created) -Distribution in progress — use `tes status 9f2c4a1b` to track. -</code></pre> -<p><strong><code>tes fetch &lt;hash&gt;</code></strong> — Busca uma tessera da rede usando o hash de conteúdo -completo. O daemon coleta fragmentos disponíveis localmente, reconstrói os dados -originais via decodificação de apagamento se necessário, desempacota os arquivos -e armazena no CAS (content-addressable store). Retorna o número de memórias e o -tamanho total buscado.</p> -<p><strong><code>tes status &lt;hash&gt;</code></strong> — Exibe a saúde de replicação de uma tessera. A saída -mapeia diretamente o modelo interno de saúde do motor de replicação:</p> -<table><thead><tr><th>Estado</th><th>Significado</th></tr></thead><tbody> -<tr><td>Local</td><td>Ainda não publicada — existe apenas na sua máquina</td></tr> -<tr><td>Publishing</td><td>Fragmentos sendo distribuídos, redundância crítica</td></tr> -<tr><td>Replicated</td><td>Distribuída, mas abaixo da redundância alvo</td></tr> -<tr><td>Healthy</td><td>Redundância completa alcançada</td></tr> -</tbody></table> -<p><strong>Listener RPC no daemon</strong> — O daemon agora escuta em um socket Unix (padrão: -<code>$XDG_RUNTIME_DIR/tesseras/daemon.sock</code>) com permissões de diretório adequadas -(0700), limpeza de sockets obsoletos e shutdown gracioso. Cada conexão é tratada -em uma task Tokio — o listener converte o stream assíncrono para I/O síncrono -para a camada de enquadramento, despacha para o handler RPC e escreve a resposta -de volta.</p> -<p><strong>Pack/unpack no <code>tesseras-core</code></strong> — Um módulo pequeno que serializa uma lista -de entradas de arquivo (caminho + dados) em um único buffer MessagePack e -vice-versa. Esta é a ponte entre a estrutura de diretórios da tessera e os blobs -opacos do motor de replicação.</p> -<h2 id="decisoes-de-arquitetura">Decisões de arquitetura</h2> -<ul> -<li><strong>Socket Unix ao invés de TCP</strong>: a comunicação RPC entre CLI e daemon acontece -na mesma máquina. Sockets Unix são mais rápidos, não precisam de alocação de -porta, e as permissões do sistema de arquivos fornecem controle de acesso sem -TLS.</li> -<li><strong>MessagePack ao invés de JSON</strong>: o mesmo formato wire usado em todo o -Tesseras. Compacto, sem schema, e já é uma dependência do workspace. Uma -ida-e-volta típica de publish request/response ocupa menos de 200 bytes.</li> -<li><strong>Cliente síncrono, daemon assíncrono</strong>: o <code>DaemonClient</code> usa I/O bloqueante -porque o CLI não precisa de concorrência — envia uma requisição e espera. O -listener do daemon é assíncrono (Tokio) para tratar múltiplas conexões. A -camada de enquadramento funciona com qualquer impl <code>Read</code>/<code>Write</code>, conectando -ambos os mundos.</li> -<li><strong>Resolução de prefixo no lado do cliente</strong>: <code>publish</code> e <code>status</code> resolvem -prefixos curtos localmente antes de enviar o hash completo ao daemon. Isso -mantém o daemon stateless — ele não precisa acessar o banco de dados do CLI.</li> -<li><strong>Alinhamento do diretório de dados padrão</strong>: o padrão do CLI mudou de -<code>~/.tesseras</code> para <code>~/.local/share/tesseras</code> (via <code>dirs::data_dir()</code>) para -coincidir com o daemon. Um aviso de migração é exibido quando dados no caminho -antigo são detectados.</li> -</ul> -<h2 id="proximos-passos">Próximos passos</h2> -<ul> -<li><strong>Contagem de peers no DHT</strong>: o comando <code>status</code> atualmente reporta 0 peers — -conectar a contagem real do DHT é o próximo passo</li> -<li><strong><code>tes show</code></strong>: exibir o conteúdo de uma tessera (memórias, metadados) sem -exportar</li> -<li><strong>Fetch com streaming</strong>: para tesseras grandes, transmitir fragmentos conforme -chegam ao invés de esperar por todos</li> -</ul> -</content> - - </entry> - <entry xml:lang="pt-br"> - <title>Fase 4: Recuperação de Chaves por Herdeiros com Shamir's Secret Sharing</title> - <published>2026-02-15T00:00:00+00:00</published> - <updated>2026-02-15T00:00:00+00:00</updated> - - <author> - <name> - - Unknown - - </name> - </author> - - <link rel="alternate" type="text/html" href="https://tesseras.net/pt-br/news/phase4-shamir-heir-recovery/"/> - <id>https://tesseras.net/pt-br/news/phase4-shamir-heir-recovery/</id> - - <content type="html" xml:base="https://tesseras.net/pt-br/news/phase4-shamir-heir-recovery/"><p>O que acontece com suas memórias quando você morre? Até agora, Tesseras -conseguia preservar conteúdo ao longo de milênios — mas as chaves privadas e -seladas morriam com o dono. A Fase 4 continua com uma solução: Shamir's Secret -Sharing, um esquema criptográfico que permite dividir sua identidade em -fragmentos e distribuí-los para as pessoas em quem você mais confia.</p> -<p>A matemática é elegante: você escolhe um limiar T e um total N. Qualquer T -fragmentos reconstroem o segredo completo; T-1 fragmentos não revelam -absolutamente nada. Isso não é "quase nada" — é informação-teoricamente seguro. -Um atacante com um fragmento a menos que o limiar tem exatamente zero bits de -informação sobre o segredo, independentemente do poder computacional que tenha.</p> -<h2 id="o-que-foi-construido">O que foi construído</h2> -<p><strong>Aritmética de corpo finito GF(256)</strong> (<code>tesseras-crypto/src/shamir/gf256.rs</code>) — -Shamir's Secret Sharing requer aritmética em um corpo finito. Implementamos -GF(256) usando o mesmo polinômio irredutível do AES (x^8 + x^4 + x^3 + x + 1), -com tabelas de lookup para logaritmo e exponenciação computadas em tempo de -compilação. Todas as operações são em tempo constante via consulta a tabelas — -sem ramificações baseadas em dados secretos. O módulo inclui o método de Horner -para avaliação de polinômios e interpolação de Lagrange em x=0 para recuperação -do segredo. 233 linhas, exaustivamente testado: todos os 256 elementos para -propriedades de identidade/inverso, comutatividade e associatividade.</p> -<p><strong>ShamirSplitter</strong> (<code>tesseras-crypto/src/shamir/mod.rs</code>) — A API principal de -split/reconstruct. <code>split()</code> recebe uma fatia de bytes do segredo, uma -configuração (limiar T, total N) e a chave pública Ed25519 do dono. Para cada -byte do segredo, constrói um polinômio aleatório de grau T-1 sobre GF(256) com o -byte do segredo como termo constante, e então o avalia em N pontos distintos. -<code>reconstruct()</code> recebe T ou mais fragmentos e recupera o segredo via -interpolação de Lagrange. Ambas as operações incluem validação extensiva: -limites do limiar, consistência de sessão, correspondência de impressão digital -do dono e verificação de checksum BLAKE3.</p> -<p><strong>Formato HeirShare</strong> — Cada fragmento é um artefato autocontido e serializável -com:</p> -<ul> -<li>Versão do formato (v1) para compatibilidade futura</li> -<li>Índice do fragmento (1..N) e metadados de limiar/total</li> -<li>ID de sessão (8 bytes aleatórios) — impede mistura de fragmentos de sessões -diferentes</li> -<li>Impressão digital do dono (primeiros 8 bytes do hash BLAKE3 da chave pública -Ed25519)</li> -<li>Dados do fragmento (os y-values de Shamir, mesmo comprimento do segredo)</li> -<li>Checksum BLAKE3 sobre todos os campos anteriores</li> -</ul> -<p>Os fragmentos são serializados em dois formatos: <strong>MessagePack</strong> (binário -compacto, para uso programático) e <strong>texto base64</strong> (legível por humanos, para -impressão e armazenamento físico). O formato texto inclui um cabeçalho com -metadados e delimitadores:</p> -<pre><code>--- TESSERAS HEIR SHARE --- -Format: v1 -Owner: a1b2c3d4e5f6a7b8 (fingerprint) -Share: 1 of 3 (threshold: 2) -Session: 9f8e7d6c5b4a3210 -Created: 2026-02-15 - -&lt;dados MessagePack codificados em base64&gt; ---- END HEIR SHARE --- -</code></pre> -<p>Este formato é projetado para ser impresso em papel, armazenado em um cofre -bancário ou gravado em metal. O cabeçalho é informacional — apenas o payload -base64 é analisado durante a reconstrução.</p> -<p><strong>Integração com CLI</strong> (<code>tesseras-cli/src/commands/heir.rs</code>) — Três novos -subcomandos:</p> -<ul> -<li><code>tes heir create</code> — divide sua identidade Ed25519 em fragmentos de herdeiros. -Solicita confirmação (sua identidade completa está em jogo), gera arquivos -<code>.bin</code> e <code>.txt</code> para cada fragmento e escreve <code>heir_meta.json</code> no diretório de -identidade.</li> -<li><code>tes heir reconstruct</code> — carrega arquivos de fragmentos (detecta -automaticamente formato binário vs texto), valida consistência, reconstrói o -segredo, deriva o par de chaves Ed25519 e opcionalmente o instala em -<code>~/.tesseras/identity/</code> (com backup automático da identidade existente).</li> -<li><code>tes heir info</code> — exibe metadados do fragmento e verifica o checksum sem expor -nenhum material secreto.</li> -</ul> -<p><strong>Formato do blob secreto</strong> — As chaves de identidade são serializadas em um -blob versionado antes da divisão: um byte de versão (0x01), um byte de flags -(0x00 para somente Ed25519), seguido da chave secreta Ed25519 de 32 bytes. Isso -deixa espaço para expansão futura quando as chaves privadas X25519 e ML-KEM-768 -forem integradas ao sistema de fragmentos de herdeiros.</p> -<p><strong>Testes</strong> — 20 testes unitários para ShamirSplitter (roundtrip, todas as -combinações de fragmentos, fragmentos insuficientes, dono errado, sessão errada, -limite threshold-1, segredos grandes até o tamanho de chave ML-KEM-768). 7 -testes unitários para aritmética GF(256) (propriedades de campo exaustivas). 3 -testes baseados em propriedades com proptest (segredos arbitrários até 5000 -bytes, configurações T-de-N arbitrárias, verificação de segurança -informação-teórica). Testes de roundtrip de serialização para ambos os formatos -MessagePack e texto base64. 2 testes de integração cobrindo o ciclo de vida -completo de herdeiros: gerar identidade, dividir em fragmentos, serializar, -desserializar, reconstruir, verificar par de chaves e assinar/verificar com -chaves reconstruídas.</p> -<h2 id="decisoes-de-arquitetura">Decisões de arquitetura</h2> -<ul> -<li><strong>GF(256) ao invés de GF(primo)</strong>: usamos GF(256) ao invés de um corpo primo -porque ele mapeia naturalmente para bytes — cada elemento é um único byte, -cada fragmento tem o mesmo comprimento do segredo. Sem aritmética de inteiros -grandes, sem redução modular, sem padding. Esta é a mesma abordagem usada pela -maioria das implementações reais de Shamir, incluindo SSSS e Hashicorp Vault.</li> -<li><strong>Tabelas de lookup em tempo de compilação</strong>: as tabelas LOG e EXP para -GF(256) são computadas em tempo de compilação usando <code>const fn</code>. Isso -significa zero custo de inicialização em tempo de execução e operações em -tempo constante via consulta a tabelas ao invés de loops.</li> -<li><strong>ID de sessão previne mistura entre sessões</strong>: cada chamada a <code>split()</code> gera -um novo ID de sessão aleatório. Se um herdeiro acidentalmente usar fragmentos -de duas sessões diferentes de divisão (por exemplo, antes e depois de uma -rotação de chaves), a reconstrução falha de forma limpa com um erro de -validação ao invés de produzir dados corrompidos.</li> -<li><strong>Checksums BLAKE3 detectam corrupção</strong>: cada fragmento inclui um checksum -BLAKE3 sobre seu conteúdo. Isso captura degradação de bits, erros de -transmissão e truncamento acidental antes de qualquer tentativa de -reconstrução. Um fragmento impresso em papel e escaneado via OCR vai falhar no -checksum se um único caractere estiver errado.</li> -<li><strong>Impressão digital do dono para identificação</strong>: os fragmentos incluem os -primeiros 8 bytes de BLAKE3(chave pública Ed25519) como impressão digital. -Isso permite aos herdeiros verificar a qual identidade um fragmento pertence -sem revelar a chave pública completa. Durante a reconstrução, a impressão -digital é verificada contra a chave recuperada.</li> -<li><strong>Formato duplo para resiliência</strong>: ambos os formatos binário (MessagePack) e -texto (base64) são gerados porque mídias físicas têm modos de falha diferentes -de armazenamento digital. Um pendrive pode falhar; papel sobrevive. Um QR code -pode ficar ilegível; texto base64 pode ser digitado manualmente.</li> -<li><strong>Versionamento do blob</strong>: o segredo é envolvido em um blob versionado -(versão + flags + material de chave) para que versões futuras possam incluir -chaves adicionais (X25519, ML-KEM-768) sem quebrar compatibilidade com -fragmentos existentes.</li> -</ul> -<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2> -<ul> -<li><strong>Fase 4 continuada: Resiliência e Escala</strong> — NAT traversal avançado -(STUN/TURN), ajuste de performance (pool de conexões, cache de fragmentos, -SQLite WAL), auditorias de segurança, integração de nós institucionais, -empacotamento para sistemas operacionais</li> -<li><strong>Fase 5: Exploração e Cultura</strong> — navegador público de tesseras por -era/localização/tema/idioma, curadoria institucional, integração com -genealogia, exportação para mídia física (M-DISC, microfilme, papel livre de -ácido com QR)</li> -</ul> -<p>Com Shamir's Secret Sharing, Tesseras fecha a última lacuna crítica na -preservação a longo prazo. Suas memórias sobrevivem a falhas de infraestrutura -através de erasure coding. Sua privacidade sobrevive a computadores quânticos -através de criptografia híbrida. E agora, sua identidade sobrevive a você — -passada adiante para as pessoas que você escolheu, exigindo a cooperação delas -para desbloquear o que você deixou para trás.</p> -</content> - - </entry> - <entry xml:lang="pt-br"> - <title>Fase 4: Criptografia e Tesseras Seladas</title> - <published>2026-02-14T16:00:00+00:00</published> - <updated>2026-02-14T16:00:00+00:00</updated> - - <author> - <name> - - Unknown - - </name> - </author> - - <link rel="alternate" type="text/html" href="https://tesseras.net/pt-br/news/phase4-encryption-sealed/"/> - <id>https://tesseras.net/pt-br/news/phase4-encryption-sealed/</id> - - <content type="html" xml:base="https://tesseras.net/pt-br/news/phase4-encryption-sealed/"><p>Algumas memórias não são para todos. Um diário privado, uma carta para ser -aberta em 2050, um segredo de família selado até que os netos tenham idade -suficiente. Até agora, toda tessera na rede era aberta. A Fase 4 muda isso: -Tesseras agora criptografa conteúdo privado e selado com um esquema -criptográfico híbrido projetado para resistir tanto a ataques clássicos quanto -quânticos.</p> -<p>O princípio continua o mesmo — criptografar o mínimo possível. Memórias públicas -precisam de disponibilidade, não de sigilo. Mas quando alguém cria uma tessera -privada ou selada, o conteúdo agora é trancado por criptografia AES-256-GCM com -chaves protegidas por um mecanismo híbrido de encapsulamento de chaves -combinando X25519 e ML-KEM-768. Ambos os algoritmos precisam ser quebrados para -acessar o conteúdo.</p> -<h2 id="o-que-foi-construido">O que foi construído</h2> -<p><strong>Encriptador AES-256-GCM</strong> (<code>tesseras-crypto/src/encryption.rs</code>) — Criptografia -simétrica de conteúdo com nonces aleatórios de 12 bytes e dados autenticados -associados (AAD). O AAD vincula o texto cifrado ao seu contexto: para tesseras -privadas, o hash do conteúdo é incluído; para tesseras seladas, tanto o hash do -conteúdo quanto o timestamp <code>open_after</code> são vinculados no AAD. Isso significa -que mover texto cifrado entre tesseras com datas de abertura diferentes causa -falha na decriptação — você não consegue enganar o sistema para abrir uma -memória selada antecipadamente trocando o texto cifrado para uma tessera com uma -data de selo anterior.</p> -<p><strong>Mecanismo Híbrido de Encapsulamento de Chaves</strong> (<code>tesseras-crypto/src/kem.rs</code>) -— Troca de chaves usando X25519 (Diffie-Hellman clássico em curva elíptica) -combinado com ML-KEM-768 (o KEM pós-quântico baseado em reticulados padronizado -pelo NIST, anteriormente Kyber). Ambos os segredos compartilhados são combinados -via <code>blake3::derive_key</code> com uma string de contexto fixa ("tesseras hybrid kem -v1") para produzir uma única chave de criptografia de conteúdo de 256 bits. Isso -segue a mesma filosofia "dual desde o início" das assinaturas duplas do projeto -(Ed25519 + ML-DSA): se qualquer algoritmo for quebrado no futuro, o outro ainda -protege o conteúdo.</p> -<p><strong>Envelope de Chave Selada</strong> (<code>tesseras-crypto/src/sealed.rs</code>) — Encapsula uma -chave de criptografia de conteúdo usando o KEM híbrido, para que apenas o dono -da tessera possa recuperá-la. O KEM produz uma chave de transporte, que é XORed -com a chave de conteúdo para produzir uma chave encapsulada armazenada junto ao -texto cifrado do KEM. Ao desselar, o dono decapsula o texto cifrado do KEM para -recuperar a chave de transporte, depois faz XOR novamente para recuperar a chave -de conteúdo.</p> -<p><strong>Publicação de Chave</strong> (<code>tesseras-crypto/src/sealed.rs</code>) — Um artefato assinado -independente para publicar a chave de conteúdo de uma tessera selada após a data -<code>open_after</code> ter passado. O dono assina a chave de conteúdo, o hash da tessera e -o timestamp de publicação com suas chaves duais (Ed25519, com placeholder -ML-DSA). O manifesto permanece imutável — a publicação da chave é um documento -separado. Outros nós verificam a assinatura contra a chave pública do dono antes -de usar a chave publicada para decriptar o conteúdo.</p> -<p><strong>EncryptionContext</strong> (<code>tesseras-core/src/enums.rs</code>) — Um tipo de domínio que -representa o contexto AAD para criptografia. Ele vive em tesseras-core e não em -tesseras-crypto porque é um conceito de domínio (não um detalhe de implementação -criptográfica). O método <code>to_aad_bytes()</code> produz serialização determinística: um -byte de tag (0x00 para Private, 0x01 para Sealed), seguido do hash de conteúdo -e, para Sealed, o timestamp <code>open_after</code> como i64 little-endian.</p> -<p><strong>Validação de domínio</strong> (<code>tesseras-core/src/service.rs</code>) — -<code>TesseraService::create()</code> agora rejeita tesseras Sealed e Private que não -fornecem chaves de criptografia. Esta é uma validação no nível de domínio: a -camada de serviço garante que você não pode criar uma memória selada sem a -maquinaria criptográfica para protegê-la. A mensagem de erro é clara: "missing -encryption keys for visibility sealed until 2050-01-01."</p> -<p><strong>Atualizações de tipos do core</strong> — <code>TesseraIdentity</code> agora inclui um campo -opcional <code>encryption_public: Option&lt;HybridEncryptionPublic&gt;</code> contendo tanto as -chaves públicas X25519 quanto ML-KEM-768. <code>KeyAlgorithm</code> ganhou as variantes -<code>X25519</code> e <code>MlKem768</code>. O layout do sistema de arquivos de identidade agora -suporta <code>node.x25519.key</code>/<code>.pub</code> e <code>node.mlkem768.key</code>/<code>.pub</code>.</p> -<p><strong>Testes</strong> — 8 testes unitários para AES-256-GCM (roundtrip, chave errada, texto -cifrado adulterado, AAD errado, falha de decriptação cross-context, nonces -únicos, mais 2 testes baseados em propriedades para payloads arbitrários e -unicidade de nonces). 5 testes unitários para HybridKem (roundtrip, par de -chaves errado, X25519 adulterado, determinismo do KDF, mais 1 teste baseado em -propriedades). 4 testes unitários para SealedKeyEnvelope e KeyPublication. 2 -testes de integração cobrindo o ciclo de vida completo de tesseras seladas e -privadas: gerar chaves, criar chave de conteúdo, criptografar, selar, desselar, -decriptar, publicar chave e verificar — o ciclo completo.</p> -<h2 id="decisoes-de-arquitetura">Decisões de arquitetura</h2> -<ul> -<li><strong>KEM híbrido desde o início</strong>: X25519 + ML-KEM-768 segue a mesma filosofia -das assinaturas duplas. Não sabemos quais suposições criptográficas se -manterão ao longo dos milênios, então combinamos algoritmos clássicos e -pós-quânticos. O custo é ~1,2 KB de material de chave adicional por identidade -— trivial comparado às fotos e vídeos em uma tessera.</li> -<li><strong>BLAKE3 para KDF</strong>: ao invés de adicionar <code>hkdf</code> + <code>sha2</code> como novas -dependências, usamos <code>blake3::derive_key</code> com uma string de contexto fixa. O -modo de derivação de chaves do BLAKE3 é especificamente projetado para este -caso de uso, e o projeto já depende do BLAKE3 para hashing de conteúdo.</li> -<li><strong>Manifestos imutáveis</strong>: quando a data <code>open_after</code> de uma tessera selada -passa, a chave de conteúdo é publicada como um artefato assinado separado -(<code>KeyPublication</code>), não modificando o manifesto. Isso preserva a natureza -append-only e endereçada por conteúdo das tesseras. O manifesto foi assinado -no momento da criação e nunca muda.</li> -<li><strong>Vinculação AAD previne troca de texto cifrado</strong>: o <code>EncryptionContext</code> -vincula tanto o hash de conteúdo quanto (para tesseras seladas) o timestamp -<code>open_after</code> nos dados autenticados do AES-GCM. Um atacante que copie conteúdo -criptografado de uma tessera "selada até 2050" para uma tessera "selada até -2025" vai descobrir que a decriptação falha — o AAD não corresponde mais.</li> -<li><strong>Encapsulamento de chave por XOR</strong>: o envelope de chave selada usa um XOR -simples da chave de conteúdo com a chave de transporte derivada do KEM, ao -invés de uma camada adicional de AES-GCM. Como a chave de transporte é um -valor aleatório fresco do KEM e é usada exatamente uma vez, o XOR é -informação-teoricamente seguro para este caso de uso específico e evita -complexidade desnecessária.</li> -<li><strong>Validação de domínio, não validação de storage</strong>: a verificação de "chaves -de criptografia ausentes" vive em <code>TesseraService::create()</code>, não na camada de -storage. Isso segue o padrão de arquitetura hexagonal: regras de domínio são -aplicadas na fronteira de serviço, não espalhadas pelos adaptadores.</li> -</ul> -<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2> -<ul> -<li><strong>Fase 4 continuada: Resiliência e Escala</strong> — Shamir's Secret Sharing para -distribuição de chaves de herdeiros, NAT traversal avançado (STUN/TURN), -ajuste de performance, auditorias de segurança, empacotamento para sistemas -operacionais</li> -<li><strong>Fase 5: Exploração e Cultura</strong> — Navegador público de tesseras por -era/localização/tema/idioma, curadoria institucional, integração com -genealogia, exportação para mídia física (M-DISC, microfilme, papel livre de -ácido com QR)</li> -</ul> -<p>Tesseras seladas fazem do Tesseras uma verdadeira cápsula do tempo. Um pai agora -pode gravar uma mensagem para o neto que ainda não nasceu, selá-la até 2060 e -saber que o envelope criptográfico vai resistir — mesmo que os computadores -quânticos do futuro tentem abri-lo antes da hora.</p> -</content> - - </entry> - <entry xml:lang="pt-br"> - <title>Fase 3: Memórias nas Suas Mãos</title> - <published>2026-02-14T14:00:00+00:00</published> - <updated>2026-02-14T14:00:00+00:00</updated> - - <author> - <name> - - Unknown - - </name> - </author> - - <link rel="alternate" type="text/html" href="https://tesseras.net/pt-br/news/phase3-api-and-apps/"/> - <id>https://tesseras.net/pt-br/news/phase3-api-and-apps/</id> - - <content type="html" xml:base="https://tesseras.net/pt-br/news/phase3-api-and-apps/"><p>As pessoas agora podem segurar suas memórias nas próprias mãos. A Fase 3 entrega -o que as fases anteriores construíram: um app mobile onde alguém baixa o -Tesseras, cria uma identidade, tira uma foto, e aquela memória entra na rede de -preservação. Sem contas na nuvem, sem assinaturas, sem nenhuma empresa entre -você e suas memórias.</p> -<h2 id="o-que-foi-construido">O que foi construído</h2> -<p><strong>tesseras-embedded</strong> — Um nó P2P completo que roda dentro de um app mobile. A -struct <code>EmbeddedNode</code> é dona de um runtime Tokio, banco SQLite, transporte QUIC, -engine Kademlia DHT, serviço de replicação e serviço de tessera — a mesma stack -do daemon desktop, compilada como biblioteca compartilhada. Um padrão singleton -global (<code>Mutex&lt;Option&lt;EmbeddedNode&gt;&gt;</code>) garante um único nó por ciclo de vida do -app. Ao iniciar, ele abre o banco de dados, executa migrações, carrega ou gera -uma identidade Ed25519 com proof-of-work para o node ID, faz bind QUIC numa -porta efêmera, conecta DHT e replicação, e inicia o loop de reparo. Ao parar, -envia um sinal de shutdown e drena graciosamente.</p> -<p>Onze funções FFI são expostas para Dart via flutter_rust_bridge: ciclo de vida -(<code>node_start</code>, <code>node_stop</code>, <code>node_is_running</code>), identidade (<code>create_identity</code>, -<code>get_identity</code>), memórias (<code>create_memory</code>, <code>get_timeline</code>, <code>get_memory</code>) e -status da rede (<code>get_network_stats</code>, <code>get_replication_status</code>). Todos os tipos -que cruzam a fronteira FFI são structs planas com apenas <code>String</code>, -<code>Option&lt;String&gt;</code>, <code>Vec&lt;String&gt;</code> e primitivos — sem trait objects, sem generics, -sem lifetimes.</p> -<p>Quatro módulos adaptadores fazem a ponte entre as ports do core e as -implementações concretas: <code>Blake3HasherAdapter</code>, -<code>Ed25519SignerAdapter</code>/<code>Ed25519VerifierAdapter</code> para criptografia, -<code>DhtPortAdapter</code> para operações DHT, e <code>ReplicationHandlerAdapter</code> para RPCs de -fragmentos e atestação recebidos.</p> -<p>A feature flag <code>bundled-sqlite</code> compila o SQLite a partir do código-fonte, -necessário para Android e iOS onde a biblioteca do sistema pode não estar -disponível. A configuração do Cargokit passa essa flag automaticamente em builds -de debug e release.</p> -<p><strong>App Flutter</strong> — Uma aplicação Material Design 3 com gerenciamento de estado -Riverpod, direcionada para Android, iOS, Linux, macOS e Windows a partir de uma -única base de código.</p> -<p>O <em>fluxo de onboarding</em> são três telas: uma tela de boas-vindas explicando o -projeto em uma frase ("Preserve suas memórias através dos milênios. Sem nuvem. -Sem empresa."), uma tela de criação de identidade que dispara a geração do par -de chaves Ed25519 em Rust, e uma tela de confirmação mostrando o nome do usuário -e a identidade criptográfica.</p> -<p>A <em>tela de timeline</em> exibe memórias em ordem cronológica reversa com previews de -imagem, texto de contexto e chips para tipo de memória e visibilidade. -Pull-to-refresh recarrega a partir do nó Rust. Um floating action button abre a -<em>tela de criação de memória</em>, que suporta seleção de foto da galeria ou câmera -via <code>image_picker</code>, texto de contexto opcional, dropdowns de tipo de memória e -visibilidade, e tags separadas por vírgula. Criar uma memória chama o FFI Rust -sincronamente, depois retorna à timeline.</p> -<p>A <em>tela de rede</em> mostra dois cards: status do nó (contagem de peers, tamanho da -DHT, estado de bootstrap, uptime) e saúde da replicação (total de fragmentos, -fragmentos saudáveis, fragmentos em reparo, fator de replicação). A <em>tela de -configurações</em> exibe a identidade do usuário — nome, node ID truncado, chave -pública truncada e data de criação.</p> -<p>Três providers Riverpod gerenciam o estado: <code>nodeProvider</code> inicia o nó embarcado -ao abrir o app usando o diretório de documentos e para ao fazer dispose; -<code>identityProvider</code> carrega o perfil existente ou cria um novo; -<code>timelineProvider</code> busca a lista de memórias com paginação.</p> -<p><strong>Testes</strong> — 9 testes unitários Rust em tesseras-embedded cobrindo ciclo de vida -do nó (start/stop sem panic), persistência de identidade entre reinícios, ciclos -de reinício sem corrupção do SQLite, streaming de eventos de rede, recuperação -de estatísticas, criação de memória e recuperação da timeline, e busca de -memória individual por hash. 2 testes Flutter: um teste de integração -verificando inicialização do Rust e startup do app, e um smoke test de widget.</p> -<h2 id="decisoes-de-arquitetura">Decisões de arquitetura</h2> -<ul> -<li><strong>Nó embarcado, não cliente-servidor</strong>: o celular roda a stack P2P completa, -não um thin client conversando com um daemon remoto. Isso significa que -memórias são preservadas mesmo sem internet. Usuários com um Raspberry Pi ou -VPS podem opcionalmente conectar o app ao seu daemon via GraphQL para maior -disponibilidade, mas não é obrigatório.</li> -<li><strong>FFI síncrono</strong>: todas as funções flutter_rust_bridge são marcadas como -<code>#[frb(sync)]</code> e bloqueiam no runtime Tokio interno. Isso simplifica o lado -Dart (sem complexidade de bridge assíncrono) enquanto o lado Rust lida com -concorrência internamente. A UI thread do Flutter permanece responsiva porque -o Riverpod envolve as chamadas em providers assíncronos.</li> -<li><strong>Singleton global</strong>: um global <code>Mutex&lt;Option&lt;EmbeddedNode&gt;&gt;</code> garante que o -ciclo de vida do nó seja previsível — um start, um stop, sem race conditions. -Plataformas mobile matam processos agressivamente, então simplicidade no -gerenciamento de ciclo de vida é uma feature.</li> -<li><strong>Tipos FFI planos</strong>: nenhuma abstração Rust vaza pela fronteira FFI. Todo -tipo é uma struct plana com strings e números. Isso torna os bindings Dart -auto-gerados confiáveis e fáceis de debugar.</li> -<li><strong>Onboarding de três telas</strong>: a criação de identidade é o único passo -obrigatório. Sem email, sem senha, sem registro em servidor. O app gera uma -identidade criptográfica localmente e está pronto para uso.</li> -</ul> -<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2> -<ul> -<li><strong>Fase 4: Resiliência e Escala</strong> — NAT traversal avançado (STUN/TURN), -Shamir's Secret Sharing para herdeiros, tesseras seladas com criptografia -temporal, ajuste de performance, auditorias de segurança, empacotamento para -Alpine/Arch/Debian/FreeBSD/OpenBSD</li> -<li><strong>Fase 5: Exploração e Cultura</strong> — Navegador público de tesseras por -era/localização/tema/idioma, curadoria institucional, integração com -genealogia, exportação para mídia física (M-DISC, microfilme, papel livre de -ácido com QR)</li> -</ul> -<p>A infraestrutura está completa. A rede existe, a replicação funciona, e agora -qualquer pessoa com um celular pode participar. O que resta é fortalecer o que -temos e abrir para o mundo.</p> -</content> - - </entry> - <entry xml:lang="pt-br"> - <title>Reed-Solomon: Como o Tesseras Sobrevive à Perda de Dados</title> - <published>2026-02-14T14:00:00+00:00</published> - <updated>2026-02-14T14:00:00+00:00</updated> - - <author> - <name> - - Unknown - - </name> - </author> - - <link rel="alternate" type="text/html" href="https://tesseras.net/pt-br/news/reed-solomon/"/> - <id>https://tesseras.net/pt-br/news/reed-solomon/</id> - - <content type="html" xml:base="https://tesseras.net/pt-br/news/reed-solomon/"><p>Seu disco rígido vai morrer. Seu provedor de nuvem vai pivotar. O array RAID no -seu armário vai sobreviver ao controlador, mas não ao dono. Se uma memória está -armazenada em exatamente um lugar, ela tem exatamente uma forma de se perder -para sempre.</p> -<p>Tesseras é uma rede que mantém memórias humanas vivas através de ajuda mútua. O -mecanismo central de sobrevivência é a <strong>codificação de apagamento -Reed-Solomon</strong> — uma técnica emprestada da comunicação espacial profunda que nos -permite reconstruir dados mesmo quando pedaços desaparecem.</p> -<h2 id="o-que-e-reed-solomon">O que é Reed-Solomon?</h2> -<p>Reed-Solomon é uma família de códigos corretores de erros inventada por Irving -Reed e Gustave Solomon em 1960. O caso de uso original era corrigir erros em -dados transmitidos por canais ruidosos — pense na Voyager enviando fotos de -Júpiter, ou num CD tocando apesar de arranhões.</p> -<p>A ideia-chave: se você adicionar redundância cuidadosamente calculada aos seus -dados <em>antes</em> que algo dê errado, você pode recuperar o original mesmo depois de -perder alguns pedaços.</p> -<p>Eis a intuição. Suponha que você tenha um polinômio de grau 2 — uma parábola. -Você precisa de 3 pontos para defini-lo de forma única. Mas se você avaliá-lo em -5 pontos, pode perder quaisquer 2 desses 5 e ainda reconstruir o polinômio a -partir dos 3 restantes. Reed-Solomon generaliza essa ideia para trabalhar sobre -corpos finitos (corpos de Galois), onde o "polinômio" são seus dados e os -"pontos de avaliação" são seus fragmentos.</p> -<p>Em termos concretos:</p> -<ol> -<li><strong>Divida</strong> seus dados em <em>k</em> shards de dados</li> -<li><strong>Calcule</strong> <em>m</em> shards de paridade a partir dos shards de dados</li> -<li><strong>Distribua</strong> todos os <em>k + m</em> shards em diferentes locais</li> -<li><strong>Reconstrua</strong> os dados originais a partir de quaisquer <em>k</em> dos <em>k + m</em> -shards</li> -</ol> -<p>Você pode perder até <em>m</em> shards — quaisquer <em>m</em>, de dados ou paridade, em -qualquer combinação — e ainda recuperar tudo.</p> -<h2 id="por-que-nao-simplesmente-fazer-copias">Por que não simplesmente fazer cópias?</h2> -<p>A abordagem ingênua para redundância é a replicação: faça 3 cópias, armazene-as -em 3 lugares. Isso dá tolerância a 2 falhas ao custo de 3x o seu armazenamento.</p> -<p>Reed-Solomon é dramaticamente mais eficiente:</p> -<table><thead><tr><th>Estratégia</th><th style="text-align: right">Overhead de armazenamento</th><th style="text-align: right">Falhas toleradas</th></tr></thead><tbody> -<tr><td>Replicação 3x</td><td style="text-align: right">200%</td><td style="text-align: right">2 de 3</td></tr> -<tr><td>Reed-Solomon (16,8)</td><td style="text-align: right">50%</td><td style="text-align: right">8 de 24</td></tr> -<tr><td>Reed-Solomon (48,24)</td><td style="text-align: right">50%</td><td style="text-align: right">24 de 72</td></tr> -</tbody></table> -<p>Com 16 shards de dados e 8 de paridade, você usa 50% de armazenamento extra mas -pode sobreviver à perda de um terço de todos os fragmentos. Para alcançar a -mesma tolerância a falhas só com replicação, você precisaria de 3x o -armazenamento.</p> -<p>Para uma rede que visa preservar memórias ao longo de décadas e séculos, essa -eficiência não é um luxo — é a diferença entre um sistema viável e um que se -afoga no próprio overhead.</p> -<h2 id="como-o-tesseras-usa-reed-solomon">Como o Tesseras usa Reed-Solomon</h2> -<p>Nem todos os dados merecem o mesmo tratamento. Uma memória de texto de 500 bytes -e um vídeo de 100 MB têm necessidades de redundância muito diferentes. O -Tesseras usa uma estratégia de fragmentação em três camadas:</p> -<p><strong>Small (&lt; 4 MB)</strong> — Replicação do arquivo inteiro para 7 pares. Para tesseras -pequenas, o overhead da codificação de apagamento (tempo de codificação, -gerenciamento de fragmentos, lógica de reconstrução) supera seus benefícios. -Cópias simples são mais rápidas e mais simples.</p> -<p><strong>Medium (4–256 MB)</strong> — 16 shards de dados + 8 de paridade = 24 fragmentos no -total. Cada fragmento tem aproximadamente 1/16 do tamanho original. Quaisquer 16 -dos 24 fragmentos reconstroem o original. Distribuídos entre 7 pares.</p> -<p><strong>Large (≥ 256 MB)</strong> — 48 shards de dados + 24 de paridade = 72 fragmentos no -total. Maior contagem de shards significa fragmentos individuais menores (mais -fáceis de transferir e armazenar) e maior tolerância absoluta a falhas. Também -distribuídos entre 7 pares.</p> -<p>A implementação usa o crate <code>reed-solomon-erasure</code> operando sobre GF(2⁸) — o -mesmo corpo de Galois usado em códigos QR e CDs. Cada fragmento carrega um -checksum BLAKE3 para que a corrupção seja detectada imediatamente, não propagada -silenciosamente.</p> -<pre><code>Tessera (álbum de fotos de 120 MB) - ↓ codificar -16 shards de dados (7,5 MB cada) + 8 shards de paridade (7,5 MB cada) - ↓ distribuir -24 fragmentos entre 7 pares (diversidade de sub-rede) - ↓ quaisquer 16 fragmentos -Tessera original recuperada -</code></pre> -<h2 id="os-desafios">Os desafios</h2> -<p>Reed-Solomon resolve o problema matemático da redundância. Os desafios de -engenharia estão em tudo ao redor.</p> -<h3 id="rastreamento-de-fragmentos">Rastreamento de fragmentos</h3> -<p>Cada fragmento precisa ser localizável. O Tesseras usa uma DHT Kademlia para -descoberta de pares e mapeamento de fragmentos para pares. Quando um nó fica -offline, seus fragmentos precisam ser recriados e distribuídos para novos pares. -Isso significa rastrear quais fragmentos existem, onde estão e se ainda estão -intactos — numa rede sem autoridade central.</p> -<h3 id="corrupcao-silenciosa">Corrupção silenciosa</h3> -<p>Um fragmento que retorna dados errados é pior que um ausente — pelo menos um -fragmento ausente é honestamente ausente. O Tesseras aborda isso com -verificações de saúde baseadas em atestação: o loop de reparo periodicamente -pede aos detentores de fragmentos que provem posse retornando checksums BLAKE3. -Se um checksum não bater, o fragmento é tratado como perdido.</p> -<h3 id="falhas-correlacionadas">Falhas correlacionadas</h3> -<p>Se todos os 24 fragmentos de uma tessera caírem em máquinas no mesmo datacenter, -uma única queda de energia os elimina todos. A matemática do Reed-Solomon assume -falhas independentes. O Tesseras impõe <strong>diversidade de sub-rede</strong> durante a -distribuição: no máximo 2 fragmentos por sub-rede /24 IPv4 (ou prefixo /48 -IPv6). Isso espalha fragmentos por diferentes infraestruturas físicas.</p> -<h3 id="velocidade-de-reparo-vs-carga-na-rede">Velocidade de reparo vs. carga na rede</h3> -<p>Quando um par fica offline, o relógio começa a contar. Fragmentos perdidos -precisam ser recriados antes que mais falhas se acumulem. Mas reparo agressivo -inunda a rede. O Tesseras equilibra isso com um loop de reparo configurável -(padrão: a cada 24 horas com 2 horas de jitter) e limites de transferências -simultâneas (padrão: 4 transferências simultâneas). O jitter previne tempestades -de reparo onde cada nó verifica seus fragmentos no mesmo momento.</p> -<h3 id="gerenciamento-de-chaves-a-longo-prazo">Gerenciamento de chaves a longo prazo</h3> -<p>Reed-Solomon protege contra perda de dados, não contra perda de acesso. Se uma -tessera é criptografada (visibilidade privada ou selada), você precisa da chave -de descriptografia para tornar os dados recuperados úteis. O Tesseras separa -essas preocupações: codificação de apagamento cuida da disponibilidade, enquanto -o Compartilhamento de Segredo de Shamir (uma fase futura) cuidará da -distribuição de chaves entre herdeiros. A filosofia de design do projeto — -criptografar o mínimo possível — mantém o problema de gerenciamento de chaves -pequeno.</p> -<h3 id="limitacoes-do-corpo-de-galois">Limitações do corpo de Galois</h3> -<p>O corpo GF(2⁸) limita o número total de shards a 255 (dados + paridade -combinados). Para o Tesseras, isso não é uma restrição prática — mesmo a camada -Large usa apenas 72 shards. Mas significa que arquivos extremamente grandes com -milhares de fragmentos exigiriam um corpo diferente ou um esquema de codificação -em camadas.</p> -<h3 id="compatibilidade-evolutiva-do-codec">Compatibilidade evolutiva do codec</h3> -<p>Uma tessera codificada hoje precisa ser decodificável em 50 anos. Reed-Solomon -sobre GF(2⁸) é um dos algoritmos mais amplamente implementados na computação — -está em todo leitor de CD, em todo scanner de código QR, em toda sonda espacial. -Essa ubiquidade é em si uma estratégia de sobrevivência. O algoritmo não será -esquecido porque metade da infraestrutura do mundo depende dele.</p> -<h2 id="o-quadro-geral">O quadro geral</h2> -<p>Reed-Solomon é uma peça de um quebra-cabeça maior. Ele trabalha em conjunto com:</p> -<ul> -<li><strong>DHT Kademlia</strong> para encontrar pares e rotear fragmentos</li> -<li><strong>Checksums BLAKE3</strong> para verificação de integridade</li> -<li><strong>Reciprocidade bilateral</strong> para troca justa de armazenamento (sem blockchain)</li> -<li><strong>Diversidade de sub-rede</strong> para independência de falhas</li> -<li><strong>Reparo automático</strong> para manter a redundância ao longo do tempo</li> -</ul> -<p>Nenhuma técnica isolada faz memórias sobreviverem. Reed-Solomon garante que -dados <em>podem</em> ser recuperados. A DHT garante que fragmentos <em>podem ser -encontrados</em>. A reciprocidade garante que pares <em>querem ajudar</em>. O reparo -garante que nada disso se degrade com o tempo.</p> -<p>Uma tessera é uma aposta de que a soma desses mecanismos, rodando em muitas -máquinas independentes operadas por muitas pessoas independentes, é mais durável -que qualquer instituição isolada. Reed-Solomon é a fundação matemática dessa -aposta.</p> -</content> - - </entry> - <entry xml:lang="pt-br"> - <title>Fase 2: Memórias Sobrevivem</title> - <published>2026-02-14T12:00:00+00:00</published> - <updated>2026-02-14T12:00:00+00:00</updated> - - <author> - <name> - - Unknown - - </name> - </author> - - <link rel="alternate" type="text/html" href="https://tesseras.net/pt-br/news/phase2-replication/"/> - <id>https://tesseras.net/pt-br/news/phase2-replication/</id> - - <content type="html" xml:base="https://tesseras.net/pt-br/news/phase2-replication/"><p>Uma tessera não está mais presa a uma única máquina. A Fase 2 entrega a camada -de replicação: os dados são divididos em fragmentos com codificação de -apagamento, distribuídos entre múltiplos pares e reparados automaticamente -quando nós ficam offline. Um livro-razão de reciprocidade bilateral garante -troca justa de armazenamento — sem blockchain, sem tokens.</p> -<h2 id="o-que-foi-construido">O que foi construído</h2> -<p><strong>tesseras-core</strong> (atualizado) — Novos tipos de domínio de replicação: -<code>FragmentPlan</code> (seleciona a camada de fragmentação baseada no tamanho da -tessera), <code>FragmentId</code> (hash da tessera + índice + contagem de shards + -checksum), <code>FragmentEnvelope</code> (fragmento com seus metadados para transporte na -rede), <code>FragmentationTier</code> (Small/Medium/Large), <code>Attestation</code> (prova de que um -nó possui um fragmento em um dado momento) e <code>ReplicateAck</code> (confirmação de -recebimento de fragmento). Três novas traits de porta definem os limites -hexagonais: <code>DhtPort</code> (encontrar pares, replicar fragmentos, solicitar -atestações, ping), <code>FragmentStore</code> (armazenar/ler/deletar/listar/verificar -fragmentos) e <code>ReciprocityLedger</code> (registrar trocas de armazenamento, consultar -saldos, encontrar melhores pares). O tamanho máximo de uma tessera é 1 GB.</p> -<p><strong>tesseras-crypto</strong> (atualizado) — O <code>ReedSolomonCoder</code> existente agora alimenta -a codificação de fragmentos. Os dados são divididos em shards, shards de -paridade são computados, e qualquer combinação de shards de dados pode -reconstruir o original — desde que o número de shards ausentes não exceda a -contagem de paridade.</p> -<p><strong>tesseras-storage</strong> (atualizado) — Dois novos adaptadores:</p> -<ul> -<li><code>FsFragmentStore</code> — armazena dados de fragmentos como arquivos em disco -(<code>{raiz}/{hash_tessera}/{indice:03}.shard</code>) com um índice de metadados SQLite -rastreando hash da tessera, índice do shard, contagem de shards, checksum e -tamanho em bytes. A verificação recalcula o hash BLAKE3 e compara com o -checksum armazenado.</li> -<li><code>SqliteReciprocityLedger</code> — contabilidade bilateral de armazenamento em -SQLite. Cada par tem uma linha rastreando bytes armazenados para eles e bytes -que eles armazenam para nós. A coluna <code>balance</code> é uma coluna gerada -(<code>bytes_they_store_for_us - bytes_stored_for_them</code>). UPSERT garante incremento -atômico dos contadores.</li> -</ul> -<p>Nova migração (<code>002_replication.sql</code>) adiciona tabelas para fragmentos, planos -de fragmentação, detentores, mapeamentos detentor-fragmento e saldos de -reciprocidade.</p> -<p><strong>tesseras-dht</strong> (atualizado) — Quatro novas variantes de mensagem: <code>Replicate</code> -(enviar um envelope de fragmento), <code>ReplicateAck</code> (confirmar recebimento), -<code>AttestRequest</code> (pedir a um nó que prove que possui os fragmentos de uma -tessera) e <code>AttestResponse</code> (retornar atestação com checksums e timestamp). O -engine trata essas mensagens em seu loop de despacho.</p> -<p><strong>tesseras-replication</strong> — O novo crate, com cinco módulos:</p> -<ul> -<li> -<p><em>Codificação de fragmentos</em> (<code>fragment.rs</code>): <code>encode_tessera()</code> seleciona a -camada de fragmentação baseada no tamanho e então chama a codificação -Reed-Solomon para as camadas Medium e Large. Três camadas:</p> -<ul> -<li><strong>Small</strong> (&lt; 4 MB): replicação do arquivo inteiro para r=7 pares, sem -codificação de apagamento</li> -<li><strong>Medium</strong> (4–256 MB): 16 shards de dados + 8 de paridade, distribuídos -entre r=7 pares</li> -<li><strong>Large</strong> (≥ 256 MB): 48 shards de dados + 24 de paridade, distribuídos -entre r=7 pares</li> -</ul> -</li> -<li> -<p><em>Distribuição</em> (<code>distributor.rs</code>): filtragem de diversidade de sub-rede limita -pares por sub-rede /24 IPv4 (ou prefixo /48 IPv6) para evitar falhas -correlacionadas. Se todos os seus fragmentos caírem no mesmo rack, uma única -queda de energia os elimina.</p> -</li> -<li> -<p><em>Serviço</em> (<code>service.rs</code>): <code>ReplicationService</code> é o orquestrador. -<code>replicate_tessera()</code> codifica os dados, encontra os pares mais próximos via -DHT, aplica diversidade de sub-rede e distribui fragmentos em round-robin. -<code>receive_fragment()</code> valida o checksum BLAKE3, verifica o saldo de -reciprocidade (rejeita se o déficit do remetente exceder o limite -configurado), armazena o fragmento e atualiza o livro-razão. -<code>handle_attestation_request()</code> lista os fragmentos locais e calcula seus -checksums como prova de posse.</p> -</li> -<li> -<p><em>Reparo</em> (<code>repair.rs</code>): <code>check_tessera_health()</code> solicita atestações dos -detentores conhecidos, recorre ao ping para nós não responsivos, verifica a -integridade local dos fragmentos e retorna uma de três ações: <code>Healthy</code>, -<code>NeedsReplication { deficit }</code> ou <code>CorruptLocal { fragment_index }</code>. O loop de -reparo roda a cada 24 horas (com 2 horas de jitter) via <code>tokio::select!</code> com -integração de desligamento.</p> -</li> -<li> -<p><em>Configuração</em> (<code>config.rs</code>): <code>ReplicationConfig</code> com padrões para intervalo -de reparo (24h), jitter (2h), transferências simultâneas (4), espaço livre -mínimo (1 GB), tolerância de déficit (256 MB) e limite de armazenamento por -par (1 GB).</p> -</li> -</ul> -<p><strong>tesd</strong> (atualizado) — O daemon agora abre um banco de dados SQLite -(<code>db/tesseras.db</code>), executa migrações, cria instâncias de <code>FsFragmentStore</code>, -<code>SqliteReciprocityLedger</code> e <code>FsBlobStore</code>, envolve o engine DHT em um -<code>DhtPortAdapter</code>, constrói um <code>ReplicationService</code> e lança o loop de reparo como -tarefa em segundo plano com desligamento gracioso.</p> -<p><strong>Testes</strong> — 193 testes em todo o workspace:</p> -<ul> -<li>15 testes unitários em tesseras-replication (camadas de codificação de -fragmentos, validação de checksum, diversidade de sub-rede, verificações de -saúde do reparo, fluxos de recebimento/replicação do serviço)</li> -<li>3 testes de integração com armazenamento real (ciclo completo -codificar→distribuir→receber para tessera média, replicação de arquivo inteiro -para tessera pequena, rejeição de fragmento adulterado)</li> -<li>Testes usam SQLite em memória + diretório temporário para fragmentos com mocks -mockall para DHT e BlobStore</li> -<li>Zero avisos do clippy, formatação limpa</li> -</ul> -<h2 id="decisoes-de-arquitetura">Decisões de arquitetura</h2> -<ul> -<li><strong>Fragmentação em três camadas</strong>: arquivos pequenos não precisam de -codificação de apagamento — o overhead não compensa. Arquivos médios e grandes -recebem progressivamente mais shards de paridade. Isso evita desperdiçar -armazenamento em tesseras pequenas enquanto oferece redundância forte para as -grandes.</li> -<li><strong>Distribuição por push do dono</strong>: o dono da tessera codifica os fragmentos e -os envia aos pares, em vez dos pares puxarem. Isso simplifica o protocolo (sem -fase de negociação) e garante que os fragmentos são distribuídos -imediatamente.</li> -<li><strong>Reciprocidade bilateral sem consenso</strong>: cada nó rastreia seu próprio saldo -com cada par localmente. Sem livro-razão global, sem token, sem blockchain. Se -o par A armazena 500 MB para o par B, o par B deveria armazenar -aproximadamente 500 MB para o par A. Free riders perdem redundância -gradualmente — seus fragmentos são despriorizados para reparo, mas nunca -deletados.</li> -<li><strong>Diversidade de sub-rede</strong>: os fragmentos são espalhados por diferentes -sub-redes para sobreviver a falhas correlacionadas. Uma queda de datacenter -não deveria eliminar todas as cópias de uma tessera.</li> -<li><strong>Verificações de saúde por atestação primeiro</strong>: o loop de reparo pede aos -detentores que provem posse (atestação com checksums) antes de declarar uma -tessera degradada. Apenas quando a atestação falha é que ele recorre a um -simples ping. Isso detecta corrupção silenciosa de dados, não apenas partida -de nós.</li> -</ul> -<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2> -<ul> -<li><strong>Fase 3: API e Apps</strong> — App Flutter mobile/desktop via flutter_rust_bridge, -API GraphQL (async-graphql), nó WASM no navegador</li> -<li><strong>Fase 4: Resiliência e Escala</strong> — Assinaturas pós-quânticas ML-DSA, travessia -avançada de NAT, Compartilhamento de Segredo de Shamir para herdeiros, -empacotamento para Alpine/Arch/Debian/FreeBSD/OpenBSD, CI no SourceHut</li> -<li><strong>Fase 5: Exploração e Cultura</strong> — navegador público de tesseras, curadoria -institucional, integração genealógica, exportação para mídia física</li> -</ul> -<p>Os nós conseguem se encontrar e manter vivas as memórias uns dos outros. Em -seguida, damos às pessoas uma forma de segurar suas memórias nas mãos.</p> -</content> - - </entry> - <entry xml:lang="pt-br"> - <title>Fase 1: Nós Se Encontram</title> - <published>2026-02-14T11:00:00+00:00</published> - <updated>2026-02-14T11:00:00+00:00</updated> - - <author> - <name> - - Unknown - - </name> - </author> - - <link rel="alternate" type="text/html" href="https://tesseras.net/pt-br/news/phase1-basic-network/"/> - <id>https://tesseras.net/pt-br/news/phase1-basic-network/</id> - - <content type="html" xml:base="https://tesseras.net/pt-br/news/phase1-basic-network/"><p>Tesseras não é mais uma ferramenta apenas local. A Fase 1 entrega a camada de -rede: nós se descobrem através de uma DHT Kademlia, comunicam-se sobre QUIC e -publicam ponteiros de tesseras que qualquer par na rede pode encontrar. Uma -tessera criada no nó A agora pode ser encontrada a partir do nó C.</p> -<h2 id="o-que-foi-construido">O que foi construído</h2> -<p><strong>tesseras-core</strong> (atualizado) — Novos tipos de domínio de rede: -<code>TesseraPointer</code> (referência leve aos detentores de uma tessera e localização -dos fragmentos), <code>NodeIdentity</code> (ID do nó + chave pública + nonce de prova de -trabalho), <code>NodeInfo</code> (identidade + endereço + capacidades) e <code>Capabilities</code> -(bitflags do que um nó suporta: DHT, armazenamento, relay, replicação).</p> -<p><strong>tesseras-net</strong> — A camada de transporte, construída sobre QUIC via quinn. A -trait <code>Transport</code> define a porta: <code>send</code>, <code>recv</code>, <code>disconnect</code>, <code>local_addr</code>. -Dois adaptadores a implementam:</p> -<ul> -<li><code>QuinnTransport</code> — QUIC real com TLS auto-assinado, negociação ALPN -(<code>tesseras/1</code>), pool de conexões via DashMap e um loop de aceitação em -background que trata streams recebidas.</li> -<li><code>MemTransport</code> + <code>SimNetwork</code> — canais em memória para testes determinísticos -sem I/O de rede. Cada teste de integração no crate DHT roda contra este -adaptador.</li> -</ul> -<p>O protocolo de fio usa MessagePack com prefixo de comprimento: um cabeçalho de 4 -bytes big-endian seguido de um payload rmp-serde. <code>WireMessage</code> carrega um byte -de versão, ID de requisição e um corpo que pode ser requisição, resposta ou erro -de protocolo. Tamanho máximo de mensagem é 64 KiB.</p> -<p><strong>tesseras-dht</strong> — Uma implementação completa de Kademlia:</p> -<ul> -<li><em>Tabela de roteamento</em>: 160 k-buckets com k=20. Evicção do menos recentemente -visto, mover-para-trás ao atualizar, verificação por ping antes de substituir -a entrada mais antiga de um bucket cheio.</li> -<li><em>Distância XOR</em>: métrica XOR de 160 bits com indexação de bucket pelo bit mais -significativo diferente.</li> -<li><em>Prova de trabalho</em>: nós iteram um nonce até que -<code>BLAKE3(pubkey || nonce)[..20]</code> tenha 8 bits zero iniciais (~256 tentativas de -hash em média). Barato o suficiente para qualquer dispositivo, caro o -suficiente para tornar ataques Sybil impraticáveis em escala.</li> -<li><em>Mensagens de protocolo</em>: Ping/Pong, FindNode/FindNodeResponse, -FindValue/FindValueResult, Store — todos serializados com MessagePack via -serde.</li> -<li><em>Armazenamento de ponteiros</em>: armazenamento em memória limitado com TTL -configurável (24 horas padrão) e máximo de entradas (10.000 padrão). Quando -cheio, remove ponteiros mais distantes do ID do nó local, seguindo o modelo de -responsabilidade baseado em distância do Kademlia.</li> -<li><em>DhtEngine</em>: o orquestrador principal. Trata RPCs recebidos, executa buscas -iterativas (paralelismo alpha=3), bootstrap, publicação e busca. O método -<code>run()</code> dirige um loop <code>tokio::select!</code> com timers de manutenção: refresh da -tabela de roteamento a cada 60 segundos, expiração de ponteiros a cada 5 -minutos.</li> -</ul> -<p><strong>tesd</strong> — Um binário de nó completo. Analisa argumentos de CLI (endereço de -bind, pares de bootstrap, diretório de dados), gera uma identidade de nó válida -por PoW, abre um endpoint QUIC, faz bootstrap na rede e roda o motor DHT. -Desligamento gracioso com Ctrl+C via tratamento de sinais do tokio.</p> -<p><strong>Infraestrutura</strong> — Configuração OpenTofu para dois nós bootstrap no Hetzner -Cloud (instâncias cx22 em Falkenstein, Alemanha e Helsinki, Finlândia). Script -de provisionamento cloud-init cria um usuário dedicado <code>tesseras</code>, escreve um -arquivo de configuração e configura um serviço systemd. Regras de firewall abrem -UDP 4433 (QUIC) e restringem métricas a acesso interno.</p> -<p><strong>Testes</strong> — 139 testes em todo o workspace:</p> -<ul> -<li>47 testes unitários em tesseras-dht (tabela de roteamento, distância, PoW, -armazenamento de ponteiros, serialização de mensagens, RPCs do engine)</li> -<li>5 testes de integração multi-nó (bootstrap de 3 nós, convergência de lookup -com 10 nós, publicar-e-encontrar, detecção de partida de nó, rejeição de PoW)</li> -<li>14 testes em tesseras-net (roundtrips de codec, send/recv de transporte, -backpressure, disconnect)</li> -<li>Testes de fumaça com Docker Compose usando 3 nós containerizados comunicando -sobre QUIC real</li> -<li>Zero avisos do clippy, formatação limpa</li> -</ul> -<h2 id="decisoes-de-arquitetura">Decisões de arquitetura</h2> -<ul> -<li><strong>Transport como porta</strong>: a trait <code>Transport</code> é a única interface entre o -motor DHT e a rede. Trocar QUIC por qualquer outro protocolo significa -implementar quatro métodos. Todos os testes de DHT usam o adaptador em -memória, tornando-os rápidos e determinísticos.</li> -<li><strong>Um stream por RPC</strong>: cada par requisição-resposta DHT usa um stream -bidirecional QUIC novo. Sem complexidade de multiplexação, sem bloqueio -head-of-line entre operações independentes. O QUIC trata a multiplexação no -nível da conexão.</li> -<li><strong>MessagePack em vez de Protobuf</strong>: codificação binária compacta sem geração -de código ou arquivos de esquema. Integração com serde significa que adicionar -um campo a uma mensagem é uma mudança de uma linha. Trade-off: sem garantias -de evolução de esquema embutidas, mas neste estágio velocidade importa mais.</li> -<li><strong>PoW em vez de stake ou reputação</strong>: uma identidade de nó custa ~256 hashes -BLAKE3. Isso roda em menos de um segundo em qualquer hardware, incluindo um -Raspberry Pi, mas gerar milhares de identidades para um ataque Sybil se torna -caro. Sem tokens, sem blockchain, sem dependências externas.</li> -<li><strong>Busca iterativa com atualização da tabela de roteamento</strong>: nós descobertos -são adicionados à tabela de roteamento conforme encontrados durante buscas -iterativas, seguindo o comportamento padrão do Kademlia. Isso garante que a -tabela de roteamento melhore organicamente conforme os nós interagem.</li> -</ul> -<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2> -<ul> -<li><strong>Fase 2: Replicação</strong> — Codificação de apagamento Reed-Solomon pela rede, -distribuição de fragmentos, loops de reparo automáticos, livro-razão de -reciprocidade bilateral (sem blockchain, sem tokens)</li> -<li><strong>Fase 3: API e Apps</strong> — App Flutter mobile/desktop via flutter_rust_bridge, -API GraphQL (async-graphql), nó WASM no navegador</li> -<li><strong>Fase 4: Resiliência e Escala</strong> — Assinaturas pós-quânticas ML-DSA, travessia -avançada de NAT, Compartilhamento de Segredo de Shamir para herdeiros, -empacotamento para Alpine/Arch/Debian/FreeBSD/OpenBSD, CI no SourceHut</li> -<li><strong>Fase 5: Exploração e Cultura</strong> — navegador público de tesseras, curadoria -institucional, integração genealógica, exportação para mídia física</li> -</ul> -<p>Os nós conseguem se encontrar. Em seguida, aprendem a manter vivas as memórias -uns dos outros.</p> -</content> - - </entry> - <entry xml:lang="pt-br"> - <title>Fase 0: Fundação Construída</title> - <published>2026-02-14T10:00:00+00:00</published> - <updated>2026-02-14T10:00:00+00:00</updated> - - <author> - <name> - - Unknown - - </name> - </author> - - <link rel="alternate" type="text/html" href="https://tesseras.net/pt-br/news/phase0-foundation/"/> - <id>https://tesseras.net/pt-br/news/phase0-foundation/</id> - - <content type="html" xml:base="https://tesseras.net/pt-br/news/phase0-foundation/"><p>O primeiro marco do projeto Tesseras está completo. A Fase 0 estabelece a -fundação sobre a qual cada componente futuro será construído: tipos de domínio, -criptografia, armazenamento e uma interface de linha de comando funcional.</p> -<h2 id="o-que-foi-construido">O que foi construído</h2> -<p><strong>tesseras-core</strong> — A camada de domínio define o formato tessera: <code>ContentHash</code> -(BLAKE3, 32 bytes), <code>NodeId</code> (Kademlia, 20 bytes), tipos de memória (Moment, -Reflection, Daily, Relation, Object), modos de visibilidade (Private, Circle, -Public, PublicAfterDeath, Sealed) e um formato de manifesto em texto plano que -pode ser interpretado por qualquer linguagem de programação pelos próximos mil -anos. A camada de serviço (<code>TesseraService</code>) gerencia operações de criação, -verificação, exportação e listagem através de port traits, seguindo arquitetura -hexagonal.</p> -<p><strong>tesseras-crypto</strong> — Geração de chaves Ed25519, assinatura e verificação. Um -framework de assinatura dual (Ed25519 + placeholder ML-DSA) pronto para migração -pós-quântica. Hashing de conteúdo com BLAKE3. Codificação de apagamento -Reed-Solomon atrás de uma feature flag para futura replicação.</p> -<p><strong>tesseras-storage</strong> — Índice SQLite via rusqlite com migrações em SQL puro. -Blob store no sistema de arquivos com layout endereçável por conteúdo -(<code>blobs/&lt;tessera_hash&gt;/&lt;memory_hash&gt;/&lt;filename&gt;</code>). Persistência de chaves de -identidade em disco.</p> -<p><strong>tesseras-cli</strong> — Um binário <code>tesseras</code> funcional com cinco comandos:</p> -<ul> -<li><code>init</code> — gera identidade Ed25519, cria banco de dados SQLite</li> -<li><code>create &lt;dir&gt;</code> — varre um diretório por arquivos de mídia, cria uma tessera -assinada</li> -<li><code>verify &lt;hash&gt;</code> — verifica assinatura e integridade dos arquivos</li> -<li><code>export &lt;hash&gt; &lt;dest&gt;</code> — escreve um diretório tessera autocontido</li> -<li><code>list</code> — mostra uma tabela das tesseras armazenadas</li> -</ul> -<p><strong>Testes</strong> — 67+ testes em todo o workspace: testes unitários em cada módulo, -testes baseados em propriedades (proptest) para roundtrips hex e serialização de -manifesto, testes de integração cobrindo o ciclo completo de -criação-verificação-exportação incluindo detecção de arquivos adulterados e -assinaturas inválidas. Zero avisos do clippy.</p> -<h2 id="decisoes-de-arquitetura">Decisões de arquitetura</h2> -<ul> -<li><strong>Arquitetura hexagonal</strong>: operações criptográficas são injetadas via trait -objects (<code>Box&lt;dyn Hasher&gt;</code>, <code>Box&lt;dyn ManifestSigner&gt;</code>, -<code>Box&lt;dyn ManifestVerifier&gt;</code>), mantendo o crate core livre de dependências -criptográficas concretas.</li> -<li><strong>Feature flags</strong>: a feature <code>service</code> no tesseras-core controla a camada de -aplicação assíncrona. As features <code>classical</code> e <code>erasure</code> no tesseras-crypto -controlam quais algoritmos são compilados.</li> -<li><strong>Manifesto em texto plano</strong>: interpretável sem qualquer biblioteca de formato -binário, com prefixos de hash explícitos <code>blake3:</code> e layout legível por -humanos.</li> -</ul> -<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2> -<p>A Fase 0 é a fundação local. O caminho adiante:</p> -<ul> -<li><strong>Fase 1: Rede</strong> — Transporte QUIC (quinn), DHT Kademlia para descoberta de -pares, travessia de NAT</li> -<li><strong>Fase 2: Replicação</strong> — Codificação de apagamento Reed-Solomon pela rede, -loops de reparo, reciprocidade bilateral (sem blockchain, sem tokens)</li> -<li><strong>Fase 3: Clientes</strong> — App Flutter mobile/desktop via flutter_rust_bridge, API -GraphQL, nó WASM no navegador</li> -<li><strong>Fase 4: Endurecimento</strong> — Assinaturas pós-quânticas ML-DSA, empacotamento -para Alpine/Arch/Debian/FreeBSD/OpenBSD, CI no SourceHut</li> -</ul> -<p>O formato tessera é estável. Tudo construído a partir daqui se conecta e estende -o que existe hoje.</p> -</content> - - </entry> - <entry xml:lang="pt-br"> - <title>Olá, Mundo</title> - <published>2026-02-13T00:00:00+00:00</published> - <updated>2026-02-13T00:00:00+00:00</updated> - - <author> - <name> - - Unknown - - </name> - </author> - - <link rel="alternate" type="text/html" href="https://tesseras.net/pt-br/news/hello-world/"/> - <id>https://tesseras.net/pt-br/news/hello-world/</id> - - <content type="html" xml:base="https://tesseras.net/pt-br/news/hello-world/"><p>Hoje anunciamos o projeto Tesseras: uma rede peer-to-peer para preservar -memórias humanas através dos milênios.</p> -<p>Tesseras é construído sobre uma ideia simples — suas fotos, gravações e escritos -merecem sobreviver a qualquer empresa, plataforma ou formato de arquivo. Cada -pessoa cria uma tessera, uma cápsula do tempo autocontida que a rede mantém viva -através de ajuda mútua e redundância.</p> -<p>O projeto está em seu estágio mais inicial. Estamos construindo a fundação: -ferramentas para criar, verificar e exportar tesseras offline. A camada de rede, -replicação e aplicativos virão em seguida.</p> -<p>Se essa missão ressoa com você, -<a href="/pt-br/subscriptions/">entre na lista de discussão</a> ou navegue pelo -<a rel="external" href="https://git.sr.ht/~ijanc/tesseras">código-fonte</a>.</p> -</content> - - </entry> -</feed> diff --git a/pt-br/atom.xml.gz b/pt-br/atom.xml.gz Binary files differdeleted file mode 100644 index e577124..0000000 --- a/pt-br/atom.xml.gz +++ /dev/null diff --git a/pt-br/contact/index.html b/pt-br/contact/index.html deleted file mode 100644 index 24f4c23..0000000 --- a/pt-br/contact/index.html +++ /dev/null @@ -1,100 +0,0 @@ -<!DOCTYPE html> -<html lang="pt-br"> -<head> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <title>Contato — Tesseras</title> - <meta name="description" content="Entre em contato com o projeto Tesseras"> - <!-- Open Graph --> - <meta property="og:type" content="website"> - <meta property="og:title" content="Contato"> - <meta property="og:description" content="Entre em contato com o projeto Tesseras"> - <meta property="og:image" content="https://tesseras.net/images/social.jpg"> - <meta property="og:image:width" content="1200"> - <meta property="og:image:height" content="630"> - <meta property="og:site_name" content="Tesseras"> - <!-- Twitter Card --> - <meta name="twitter:card" content="summary_large_image"> - <meta name="twitter:title" content="Contato"> - <meta name="twitter:description" content="Entre em contato com o projeto Tesseras"> - <meta name="twitter:image" content="https://tesseras.net/images/social.jpg"> - <link rel="stylesheet" href="https://tesseras.net/style.css?h=21f0f32121928ee5c690"> - - - <link rel="alternate" type="application/atom+xml" title="Tesseras" href="https://tesseras.net/atom.xml"> - - - <link rel="icon" type="image/png" sizes="32x32" href="https://tesseras.net/images/favicon.png?h=be4e123a23393b1a027d"> - -</head> -<body> - <header> - <h1> - <a href="https://tesseras.net/pt-br/"> - <img src="https://tesseras.net/images/logo-64.png?h=c1b8d0c4c5f93b49d40b" alt="Tesseras" width="40" height="40" class="logo"> - Tesseras - </a> - </h1> - <nav> - - <a href="https://tesseras.net/pt-br/about/">Sobre</a> - <a href="https://tesseras.net/pt-br/news/">Notícias</a> - <a href="https://tesseras.net/pt-br/releases/">Lançamentos</a> - <a href="https://tesseras.net/pt-br/faq/">FAQ</a> - <a href="https://tesseras.net/pt-br/subscriptions/">Inscrições</a> - <a href="https://tesseras.net/pt-br/contact/">Contato</a> - - </nav> - <nav class="lang-switch"> - - <a href="https://tesseras.net/contact/">English</a> | <strong>Português</strong> - - </nav> - </header> - - <main> - -<article> - <h2>Contato</h2> - <h3 id="listas-de-discussao">Listas de Discussão</h3> -<p>A melhor forma de contatar o projeto é através das -<a href="/pt-br/subscriptions/">listas de discussão</a>:</p> -<ul> -<li><a rel="external" href="https://lists.sr.ht/~ijanc/tesseras-discuss">tesseras-discuss</a> — perguntas, -suporte, discussão geral</li> -<li><a rel="external" href="https://lists.sr.ht/~ijanc/tesseras-devel">tesseras-devel</a> — patches e -desenvolvimento</li> -<li><a rel="external" href="https://lists.sr.ht/~ijanc/tesseras-announce">tesseras-announce</a> — -lançamentos e marcos</li> -<li><a rel="external" href="https://lists.sr.ht/~ijanc/tesseras-security">tesseras-security</a> — relatos de -vulnerabilidades</li> -</ul> -<h3 id="irc">IRC</h3> -<p>Participe no <a rel="external" href="https://libera.chat/">Libera.Chat</a> no canal <strong>#tesseras</strong> -(<a rel="external" href="https://web.libera.chat/#tesseras">webchat</a>).</p> -<h3 id="relatorios-de-bugs">Relatórios de Bugs</h3> -<p>Registre bugs e pedidos de funcionalidades no -<a rel="external" href="https://todo.sr.ht/~ijanc/tesseras">ticket tracker</a>.</p> -<h3 id="codigo-fonte">Código-Fonte</h3> -<ul> -<li><a rel="external" href="https://git.sr.ht/~ijanc/tesseras">SourceHut</a> (primário)</li> -<li><a rel="external" href="https://github.com/ijanc/tesseras">GitHub</a> (espelho)</li> -</ul> -<h3 id="recursos">Recursos</h3> -<ul> -<li><a rel="external" href="https://tesseras.net/book/pt-br/">Livro</a> — documentação para usuários (em -breve)</li> -<li><a href="/pt-br/atom.xml">Feed Atom</a> — notícias do projeto</li> -<li><a rel="external" href="https://sr.ht/~ijanc/tesseras/feed.rss">Feed SourceHut</a> — commits, tickets e -atividade das listas</li> -</ul> - -</article> - - </main> - - <footer> - <p>© 2026 Tesseras Project. <a href="/atom.xml">News Feed</a> · <a href="https://git.sr.ht/~ijanc/tesseras">Source</a></p> - </footer> -</body> -</html> diff --git a/pt-br/contact/index.html.gz b/pt-br/contact/index.html.gz Binary files differdeleted file mode 100644 index 4bd847a..0000000 --- a/pt-br/contact/index.html.gz +++ /dev/null diff --git a/pt-br/faq/index.html b/pt-br/faq/index.html deleted file mode 100644 index 9c44e16..0000000 --- a/pt-br/faq/index.html +++ /dev/null @@ -1,121 +0,0 @@ -<!DOCTYPE html> -<html lang="pt-br"> -<head> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <title>FAQ — Tesseras</title> - <meta name="description" content="Perguntas frequentes sobre o Tesseras"> - <!-- Open Graph --> - <meta property="og:type" content="website"> - <meta property="og:title" content="FAQ"> - <meta property="og:description" content="Perguntas frequentes sobre o Tesseras"> - <meta property="og:image" content="https://tesseras.net/images/social.jpg"> - <meta property="og:image:width" content="1200"> - <meta property="og:image:height" content="630"> - <meta property="og:site_name" content="Tesseras"> - <!-- Twitter Card --> - <meta name="twitter:card" content="summary_large_image"> - <meta name="twitter:title" content="FAQ"> - <meta name="twitter:description" content="Perguntas frequentes sobre o Tesseras"> - <meta name="twitter:image" content="https://tesseras.net/images/social.jpg"> - <link rel="stylesheet" href="https://tesseras.net/style.css?h=21f0f32121928ee5c690"> - - - <link rel="alternate" type="application/atom+xml" title="Tesseras" href="https://tesseras.net/atom.xml"> - - - <link rel="icon" type="image/png" sizes="32x32" href="https://tesseras.net/images/favicon.png?h=be4e123a23393b1a027d"> - -</head> -<body> - <header> - <h1> - <a href="https://tesseras.net/pt-br/"> - <img src="https://tesseras.net/images/logo-64.png?h=c1b8d0c4c5f93b49d40b" alt="Tesseras" width="40" height="40" class="logo"> - Tesseras - </a> - </h1> - <nav> - - <a href="https://tesseras.net/pt-br/about/">Sobre</a> - <a href="https://tesseras.net/pt-br/news/">Notícias</a> - <a href="https://tesseras.net/pt-br/releases/">Lançamentos</a> - <a href="https://tesseras.net/pt-br/faq/">FAQ</a> - <a href="https://tesseras.net/pt-br/subscriptions/">Inscrições</a> - <a href="https://tesseras.net/pt-br/contact/">Contato</a> - - </nav> - <nav class="lang-switch"> - - <a href="https://tesseras.net/faq/">English</a> | <strong>Português</strong> - - </nav> - </header> - - <main> - -<article> - <h2>FAQ</h2> - <h3 id="o-que-e-uma-tessera">O que é uma tessera?</h3> -<p>Uma tessera é uma cápsula do tempo autocontida de memórias — fotos, gravações de -áudio, vídeo e texto — empacotada em um formato projetado para sobreviver -independentemente de qualquer software, empresa ou infraestrutura. O nome vem -das pequenas peças usadas em mosaicos romanos: cada peça é simples, mas juntas -formam algo que perdura.</p> -<h3 id="como-meus-dados-sobrevivem-se-meu-computador-morrer">Como meus dados sobrevivem se meu computador morrer?</h3> -<p>Sua tessera é replicada em múltiplos nós na rede peer-to-peer do Tesseras. -Utiliza codificação por apagamento (Reed-Solomon) para dividir seus dados em -fragmentos redundantes. Mesmo que vários nós fiquem offline permanentemente, sua -tessera pode ser reconstruída a partir dos fragmentos restantes.</p> -<h3 id="meus-dados-sao-criptografados">Meus dados são criptografados?</h3> -<p>Por padrão, não. O Tesseras prioriza disponibilidade sobre sigilo — o objetivo é -que suas memórias sobrevivam, mesmo que o software para descriptografá-las não -exista mais. Você pode marcar memórias individuais como privadas (criptografadas -com AES-256-GCM) ou seladas (para serem abertas após uma data específica), mas -memórias públicas e de círculo são armazenadas sem criptografia para maximizar -suas chances de sobrevivência a longo prazo.</p> -<h3 id="preciso-pagar-alguma-coisa">Preciso pagar alguma coisa?</h3> -<p>Não. A rede funciona com ajuda mútua: você armazena fragmentos das tesseras de -outras pessoas, e elas armazenam as suas. Não há tokens, blockchain ou taxas de -assinatura. O único custo é o espaço de armazenamento que você contribui para a -rede.</p> -<h3 id="em-quais-plataformas-funciona">Em quais plataformas funciona?</h3> -<p>Tesseras funciona em Linux, macOS, FreeBSD, OpenBSD, Windows, Android e iOS. -Também há um visualizador no navegador e suporte para dispositivos IoT de baixo -consumo (ESP32) como nós de armazenamento passivo.</p> -<h3 id="qual-a-diferenca-do-ipfs-filecoin-ou-arweave">Qual a diferença do IPFS, Filecoin ou Arweave?</h3> -<p>Tesseras é projetado especificamente para preservação de memórias pessoais, não -armazenamento de arquivos de propósito geral. Diferenças principais:</p> -<ul> -<li><strong>Sem criptomoeda ou tokens</strong> — incentivos são baseados em reciprocidade -bilateral, não mercados financeiros</li> -<li><strong>Formato autodescritivo</strong> — cada tessera inclui instruções para decodificar a -si mesma em múltiplos idiomas, para que possa ser compreendida séculos no -futuro sem nenhum software especial</li> -<li><strong>Disponibilidade sobre sigilo</strong> — a maioria dos dados é armazenada sem -criptografia para maximizar a sobrevivência a longo prazo</li> -<li><strong>Formatos de mídia mais simples possíveis</strong> — JPEG, WAV, WebM, texto puro — -escolhidos por durabilidade, não recursos</li> -</ul> -<h3 id="quais-formatos-de-midia-sao-suportados">Quais formatos de mídia são suportados?</h3> -<ul> -<li><strong>Fotos:</strong> JPEG</li> -<li><strong>Áudio:</strong> WAV PCM</li> -<li><strong>Vídeo:</strong> WebM</li> -<li><strong>Texto:</strong> UTF-8 texto puro</li> -</ul> -<p>Esses formatos foram escolhidos por máxima longevidade e amplo suporte.</p> -<h3 id="posso-exportar-minha-tessera">Posso exportar minha tessera?</h3> -<p>Sim. Uma tessera é um diretório padrão de arquivos. Você pode copiá-la para um -pendrive, gravar em mídia óptica ou imprimir as partes de texto. O formato é -projetado para ser legível sem nenhum software especial.</p> - -</article> - - </main> - - <footer> - <p>© 2026 Tesseras Project. <a href="/atom.xml">News Feed</a> · <a href="https://git.sr.ht/~ijanc/tesseras">Source</a></p> - </footer> -</body> -</html> diff --git a/pt-br/faq/index.html.gz b/pt-br/faq/index.html.gz Binary files differdeleted file mode 100644 index 9c826b1..0000000 --- a/pt-br/faq/index.html.gz +++ /dev/null diff --git a/pt-br/index.html b/pt-br/index.html deleted file mode 100644 index e9bb5d6..0000000 --- a/pt-br/index.html +++ /dev/null @@ -1,101 +0,0 @@ -<!DOCTYPE html> -<html lang="pt-br"> -<head> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <title>Tesseras — Preserve Your Memories Across Millennia</title> - <meta name="description" content="Rede P2P para preservar memórias humanas através dos milênios"> - <!-- Open Graph --> - <meta property="og:type" content="website"> - <meta property="og:title" content="Tesseras"> - <meta property="og:description" content="Rede P2P para preservar memórias humanas através dos milênios"> - <meta property="og:image" content="https://tesseras.net/images/social.jpg"> - <meta property="og:image:width" content="1200"> - <meta property="og:image:height" content="630"> - <meta property="og:site_name" content="Tesseras"> - <!-- Twitter Card --> - <meta name="twitter:card" content="summary_large_image"> - <meta name="twitter:title" content="Tesseras"> - <meta name="twitter:description" content="Rede P2P para preservar memórias humanas através dos milênios"> - <meta name="twitter:image" content="https://tesseras.net/images/social.jpg"> - <link rel="stylesheet" href="https://tesseras.net/style.css?h=21f0f32121928ee5c690"> - - - <link rel="alternate" type="application/atom+xml" title="Tesseras" href="https://tesseras.net/atom.xml"> - - - <link rel="icon" type="image/png" sizes="32x32" href="https://tesseras.net/images/favicon.png?h=be4e123a23393b1a027d"> - -</head> -<body> - <header> - <h1> - <a href="https://tesseras.net/pt-br/"> - <img src="https://tesseras.net/images/logo-64.png?h=c1b8d0c4c5f93b49d40b" alt="Tesseras" width="40" height="40" class="logo"> - Tesseras - </a> - </h1> - <nav> - - <a href="https://tesseras.net/pt-br/about/">Sobre</a> - <a href="https://tesseras.net/pt-br/news/">Notícias</a> - <a href="https://tesseras.net/pt-br/releases/">Lançamentos</a> - <a href="https://tesseras.net/pt-br/faq/">FAQ</a> - <a href="https://tesseras.net/pt-br/subscriptions/">Inscrições</a> - <a href="https://tesseras.net/pt-br/contact/">Contato</a> - - </nav> - <nav class="lang-switch"> - - <a href="https://tesseras.net/">English</a> | <strong>Português</strong> - - </nav> - </header> - - <main> - -<p>Tesseras é uma rede peer-to-peer para preservar memórias humanas através dos -milênios.</p> -<h2 id="por-que-tesseras-existe">Por Que Tesseras Existe</h2> -<p>Todos os anos, plataformas fecham, empresas falham e formatos de arquivo se -tornam ilegíveis. Fotos pessoais desaparecem quando um serviço de nuvem encerra. -Vídeos caseiros apodrecem em mídias obsoletas. Cartas se perdem em contas de -e-mail abandonadas. Nossas memórias merecem mais do que depender de qualquer -empresa, formato ou infraestrutura.</p> -<h2 id="como-funciona">Como Funciona</h2> -<p>Cada pessoa cria uma <strong>tessera</strong> — uma cápsula do tempo autocontida de memórias -(fotos, áudio, vídeo, texto) que sobrevive independentemente.</p> -<ul> -<li><strong>Peer-to-peer</strong> — sua tessera é replicada através de uma rede de voluntários, -não armazenada em servidores corporativos</li> -<li><strong>Codificação por apagamento</strong> — seus dados são divididos em fragmentos -redundantes para sobreviver a falhas de nós individuais</li> -<li><strong>Sem dependência de empresa</strong> — a rede funciona com protocolos abertos, -software livre e ajuda mútua</li> -<li><strong>Formato autodescritivo</strong> — cada tessera contém tudo necessário para -decodificar a si mesma, mesmo séculos no futuro</li> -<li><strong>Código aberto</strong> — licença ISC, construído em Rust</li> -</ul> -<h2 id="status-atual">Status Atual</h2> -<p>Tesseras está na Fase 4 — Resiliência e Escala. O formato base, as fundações -criptográficas, a rede peer-to-peer, a replicação, a API GraphQL e o app Flutter -estão construídos. Estamos agora trabalhando em Shamir's Secret Sharing para -recuperação de chaves por herdeiros, NAT traversal avançado e ajuste de -performance.</p> -<p>Veja <a href="/pt-br/releases/">Lançamentos</a> para informações de download.</p> -<h2 id="participe">Participe</h2> -<ul> -<li>Entre nas <a href="/pt-br/subscriptions/">listas de discussão</a></li> -<li>Navegue pelo <a rel="external" href="https://git.sr.ht/~ijanc/tesseras">código-fonte</a></li> -<li>Leia o <a href="/pt-br/faq/">FAQ</a></li> -<li><a href="/pt-br/contact/">Fale conosco</a></li> -</ul> - - - </main> - - <footer> - <p>© 2026 Tesseras Project. <a href="/atom.xml">News Feed</a> · <a href="https://git.sr.ht/~ijanc/tesseras">Source</a></p> - </footer> -</body> -</html> diff --git a/pt-br/index.html.gz b/pt-br/index.html.gz Binary files differdeleted file mode 100644 index cba8483..0000000 --- a/pt-br/index.html.gz +++ /dev/null diff --git a/pt-br/news/atom.xml b/pt-br/news/atom.xml deleted file mode 100644 index 99f3061..0000000 --- a/pt-br/news/atom.xml +++ /dev/null @@ -1,2101 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="pt-br"> - <title>Tesseras - Notícias</title> - <subtitle>Rede P2P para preservar memórias humanas através dos milênios</subtitle> - <link rel="self" type="application/atom+xml" href="https://tesseras.net/pt-br/news/atom.xml"/> - <link rel="alternate" type="text/html" href="https://tesseras.net/pt-br/news/"/> - <generator uri="https://www.getzola.org/">Zola</generator> - <updated>2026-02-16T10:00:00+00:00</updated> - <id>https://tesseras.net/pt-br/news/atom.xml</id> - <entry xml:lang="pt-br"> - <title>Empacotando o Tesseras para Debian</title> - <published>2026-02-16T10:00:00+00:00</published> - <updated>2026-02-16T10:00:00+00:00</updated> - - <author> - <name> - - Unknown - - </name> - </author> - - <link rel="alternate" type="text/html" href="https://tesseras.net/pt-br/news/packaging-debian/"/> - <id>https://tesseras.net/pt-br/news/packaging-debian/</id> - - <content type="html" xml:base="https://tesseras.net/pt-br/news/packaging-debian/"><p>O Tesseras agora inclui um pacote <code>.deb</code> para Debian e Ubuntu. Este post explica -como compilar e instalar o pacote a partir do código-fonte usando <code>cargo-deb</code>.</p> -<h2 id="pre-requisitos">Pré-requisitos</h2> -<p>Você precisa de uma toolchain Rust funcional e das bibliotecas de sistema -necessárias:</p> -<pre><code data-lang="sh">sudo apt install build-essential pkg-config libsqlite3-dev -rustup toolchain install stable -cargo install cargo-deb -</code></pre> -<h2 id="compilando">Compilando</h2> -<p>Clone o repositório e execute a recipe <code>just deb</code>:</p> -<pre><code data-lang="sh">git clone https://git.sr.ht/~ijanc/tesseras -cd tesseras -just deb -</code></pre> -<p>Essa recipe faz três coisas:</p> -<ol> -<li><strong>Compila</strong> <code>tesd</code> (o daemon) e <code>tes</code> (o CLI) em modo release com -<code>cargo build --release</code></li> -<li><strong>Gera completions de shell</strong> para bash, zsh e fish a partir do binário <code>tes</code></li> -<li><strong>Empacota</strong> tudo em um arquivo <code>.deb</code> com -<code>cargo deb -p tesseras-daemon --no-build</code></li> -</ol> -<p>O resultado é um arquivo <code>.deb</code> em <code>target/debian/</code>.</p> -<h2 id="instalando">Instalando</h2> -<pre><code data-lang="sh">sudo dpkg -i target/debian/tesseras-daemon_*.deb -</code></pre> -<p>Se houver dependências faltando, corrija com:</p> -<pre><code data-lang="sh">sudo apt install -f -</code></pre> -<h2 id="configuracao-pos-instalacao">Configuração pós-instalação</h2> -<p>O script <code>postinst</code> cria automaticamente um usuário de sistema <code>tesseras</code> e o -diretório de dados <code>/var/lib/tesseras</code>. Para usar o CLI sem sudo, adicione seu -usuário ao grupo:</p> -<pre><code data-lang="sh">sudo usermod -aG tesseras $USER -</code></pre> -<p>Faça logout e login novamente, depois inicie o daemon:</p> -<pre><code data-lang="sh">sudo systemctl enable --now tesd -</code></pre> -<h2 id="o-que-o-pacote-inclui">O que o pacote inclui</h2> -<table><thead><tr><th>Caminho</th><th>Descrição</th></tr></thead><tbody> -<tr><td><code>/usr/bin/tesd</code></td><td>Daemon do nó completo</td></tr> -<tr><td><code>/usr/bin/tes</code></td><td>Cliente CLI</td></tr> -<tr><td><code>/etc/tesseras/config.toml</code></td><td>Configuração padrão (marcado como conffile)</td></tr> -<tr><td><code>/lib/systemd/system/tesd.service</code></td><td>Unit systemd com hardening de segurança</td></tr> -<tr><td>Completions de shell</td><td>bash, zsh e fish</td></tr> -</tbody></table> -<h2 id="como-o-cargo-deb-funciona">Como o cargo-deb funciona</h2> -<p>Os metadados de empacotamento ficam em <code>crates/tesseras-daemon/Cargo.toml</code> na -seção <code>[package.metadata.deb]</code>. Essa seção define:</p> -<ul> -<li><strong>depends</strong> — dependências em tempo de execução: <code>libc6</code> e <code>libsqlite3-0</code></li> -<li><strong>assets</strong> — arquivos incluídos no pacote (binários, config, unit systemd, -completions de shell)</li> -<li><strong>conf-files</strong> — arquivos tratados como configuração (preservados na -atualização)</li> -<li><strong>maintainer-scripts</strong> — scripts <code>postinst</code> e <code>postrm</code> em -<code>packaging/debian/scripts/</code></li> -<li><strong>systemd-units</strong> — integração automática com systemd</li> -</ul> -<p>O script <code>postinst</code> cria o usuário de sistema <code>tesseras</code> e o diretório de dados -na instalação. O script <code>postrm</code> remove o usuário, grupo e diretório de dados -apenas no <code>purge</code> (não na remoção simples).</p> -<h2 id="hardening-do-systemd">Hardening do systemd</h2> -<p>A unit <code>tesd.service</code> inclui diretivas de hardening de segurança:</p> -<pre><code data-lang="ini">NoNewPrivileges=true -ProtectSystem=strict -ProtectHome=true -ReadWritePaths=/var/lib/tesseras -PrivateTmp=true -PrivateDevices=true -ProtectKernelTunables=true -ProtectControlGroups=true -RestrictSUIDSGID=true -MemoryDenyWriteExecute=true -</code></pre> -<p>O daemon roda como o usuário não-privilegiado <code>tesseras</code> e só pode escrever em -<code>/var/lib/tesseras</code>.</p> -<h2 id="deploy-para-um-servidor-remoto">Deploy para um servidor remoto</h2> -<p>O justfile inclui uma recipe <code>deploy</code> para enviar o <code>.deb</code> a um host remoto:</p> -<pre><code data-lang="sh">just deploy bootstrap1.tesseras.net -</code></pre> -<p>Isso compila o <code>.deb</code>, copia via <code>scp</code>, instala com <code>dpkg -i</code> e reinicia o -serviço <code>tesd</code>.</p> -<h2 id="atualizando">Atualizando</h2> -<p>Depois de baixar novas mudanças, basta rodar <code>just deb</code> novamente e reinstalar:</p> -<pre><code data-lang="sh">git pull -just deb -sudo dpkg -i target/debian/tesseras-daemon_*.deb -</code></pre> -</content> - - </entry> - <entry xml:lang="pt-br"> - <title>Empacotando o Tesseras para Arch Linux</title> - <published>2026-02-16T09:00:00+00:00</published> - <updated>2026-02-16T09:00:00+00:00</updated> - - <author> - <name> - - Unknown - - </name> - </author> - - <link rel="alternate" type="text/html" href="https://tesseras.net/pt-br/news/packaging-archlinux/"/> - <id>https://tesseras.net/pt-br/news/packaging-archlinux/</id> - - <content type="html" xml:base="https://tesseras.net/pt-br/news/packaging-archlinux/"><p>O Tesseras agora inclui um PKGBUILD para Arch Linux. Este post explica como -compilar e instalar o pacote a partir do código-fonte.</p> -<h2 id="pre-requisitos">Pré-requisitos</h2> -<p>Você precisa de uma toolchain Rust funcional e do grupo base-devel:</p> -<pre><code data-lang="sh">sudo pacman -S --needed base-devel sqlite -rustup toolchain install stable -</code></pre> -<h2 id="compilando">Compilando</h2> -<p>Clone o repositório e execute a recipe <code>just arch</code>:</p> -<pre><code data-lang="sh">git clone https://git.sr.ht/~ijanc/tesseras -cd tesseras -just arch -</code></pre> -<p>Isso executa <code>makepkg -sf</code> dentro de <code>packaging/archlinux/</code>, que:</p> -<ol> -<li><strong>prepare</strong> — baixa as dependências Cargo com <code>cargo fetch --locked</code></li> -<li><strong>build</strong> — compila <code>tesd</code> e <code>tes</code> (o CLI) em modo release</li> -<li><strong>package</strong> — instala binários, serviço systemd, configs sysusers/tmpfiles, -completions de shell (bash, zsh, fish) e um arquivo de configuração padrão</li> -</ol> -<p>O resultado é um arquivo <code>.pkg.tar.zst</code> em <code>packaging/archlinux/</code>.</p> -<h2 id="instalando">Instalando</h2> -<pre><code data-lang="sh">sudo pacman -U packaging/archlinux/tesseras-*.pkg.tar.zst -</code></pre> -<h2 id="configuracao-pos-instalacao">Configuração pós-instalação</h2> -<p>O pacote cria automaticamente um usuário e grupo de sistema <code>tesseras</code> via -systemd-sysusers. Para usar o CLI sem sudo, adicione seu usuário ao grupo:</p> -<pre><code data-lang="sh">sudo usermod -aG tesseras $USER -</code></pre> -<p>Faça logout e login novamente, depois inicie o daemon:</p> -<pre><code data-lang="sh">sudo systemctl enable --now tesd -</code></pre> -<h2 id="o-que-o-pacote-inclui">O que o pacote inclui</h2> -<table><thead><tr><th>Caminho</th><th>Descrição</th></tr></thead><tbody> -<tr><td><code>/usr/bin/tesd</code></td><td>Daemon do nó completo</td></tr> -<tr><td><code>/usr/bin/tes</code></td><td>Cliente CLI</td></tr> -<tr><td><code>/etc/tesseras/config.toml</code></td><td>Configuração padrão (marcado como backup)</td></tr> -<tr><td><code>/usr/lib/systemd/system/tesd.service</code></td><td>Unit systemd com hardening de segurança</td></tr> -<tr><td><code>/usr/lib/sysusers.d/tesseras.conf</code></td><td>Definição do usuário de sistema</td></tr> -<tr><td><code>/usr/lib/tmpfiles.d/tesseras.conf</code></td><td>Diretório de dados <code>/var/lib/tesseras</code></td></tr> -<tr><td>Completions de shell</td><td>bash, zsh e fish</td></tr> -</tbody></table> -<h2 id="detalhes-do-pkgbuild">Detalhes do PKGBUILD</h2> -<p>O PKGBUILD compila diretamente a partir do checkout git local em vez de baixar -um tarball. A variável de ambiente <code>TESSERAS_ROOT</code> aponta o makepkg para a raiz -do workspace. O diretório target do Cargo é configurado para <code>$srcdir/target</code> -para manter os artefatos de build dentro do sandbox do makepkg.</p> -<p>O pacote depende apenas de <code>sqlite</code> em tempo de execução e <code>cargo</code> em tempo de -build.</p> -<h2 id="atualizando">Atualizando</h2> -<p>Depois de baixar novas mudanças, basta rodar <code>just arch</code> novamente e reinstalar:</p> -<pre><code data-lang="sh">git pull -just arch -sudo pacman -U packaging/archlinux/tesseras-*.pkg.tar.zst -</code></pre> -</content> - - </entry> - <entry xml:lang="pt-br"> - <title>Fase 4: Deduplicacao de Armazenamento</title> - <published>2026-02-15T23:00:00+00:00</published> - <updated>2026-02-15T23:00:00+00:00</updated> - - <author> - <name> - - Unknown - - </name> - </author> - - <link rel="alternate" type="text/html" href="https://tesseras.net/pt-br/news/phase4-storage-deduplication/"/> - <id>https://tesseras.net/pt-br/news/phase4-storage-deduplication/</id> - - <content type="html" xml:base="https://tesseras.net/pt-br/news/phase4-storage-deduplication/"><p>Quando multiplas tesseras compartilham a mesma foto, o mesmo clipe de audio ou -os mesmos dados de fragmento, a camada de armazenamento antiga mantinha copias -separadas de cada. Em um no armazenando milhares de tesseras para a rede, essa -duplicacao se acumula rapidamente. A Fase 4 continua com deduplicacao de -armazenamento: um armazenamento enderecavel por conteudo (CAS) que garante que -cada dado unico seja armazenado exatamente uma vez em disco, independentemente -de quantas tesseras o referenciam.</p> -<p>O design e simples e comprovado: hash do conteudo com BLAKE3, usar o hash como -nome do arquivo e manter uma contagem de referencias no SQLite. Quando duas -tesseras incluem a mesma foto de 5 MB, um arquivo existe em disco com -refcount 2. Quando uma tessera e deletada, o refcount cai para 1 e o arquivo -permanece. Quando a ultima referencia e liberada, uma varredura periodica limpa -o orfao.</p> -<h2 id="o-que-foi-construido">O que foi construido</h2> -<p><strong>Migracao do esquema CAS</strong> (<code>tesseras-storage/migrations/004_dedup.sql</code>) — Tres -novas tabelas:</p> -<ul> -<li><code>cas_objects</code> — rastreia cada objeto no armazenamento: hash BLAKE3 (chave -primaria), tamanho em bytes, contagem de referencias e timestamp de criacao</li> -<li><code>blob_refs</code> — mapeia identificadores logicos de blobs (hash da tessera + hash -da memoria + nome do arquivo) para hashes CAS, substituindo a convencao antiga -de caminhos no sistema de arquivos</li> -<li><code>fragment_refs</code> — mapeia identificadores logicos de fragmentos (hash da -tessera + indice do fragmento) para hashes CAS, substituindo o antigo layout -do diretorio <code>fragments/</code></li> -</ul> -<p>Indices nas colunas de hash garantem lookups O(1) durante leituras e contagem de -referencias.</p> -<p><strong>CasStore</strong> (<code>tesseras-storage/src/cas.rs</code>) — O motor central de armazenamento -enderecavel por conteudo. Arquivos sao armazenados sob um diretorio de prefixo -de dois niveis: <code>&lt;raiz&gt;/&lt;prefixo-hex-2-chars&gt;/&lt;hash-completo&gt;.blob</code>. O -armazenamento fornece cinco operacoes:</p> -<ul> -<li><code>put(hash, data)</code> — escreve dados em disco se ainda nao presente, incrementa o -refcount. Retorna se ocorreu um hit de deduplicacao.</li> -<li><code>get(hash)</code> — le dados do disco pelo hash</li> -<li><code>release(hash)</code> — decrementa o refcount. Se chegar a zero, o arquivo em disco -e deletado imediatamente.</li> -<li><code>contains(hash)</code> — verifica existencia sem ler</li> -<li><code>ref_count(hash)</code> — retorna a contagem de referencias atual</li> -</ul> -<p>Todas as operacoes sao atomicas dentro de uma unica transacao SQLite. O refcount -e a fonte de verdade — se o refcount diz que o objeto existe, o arquivo deve -estar em disco.</p> -<p><strong>FsBlobStore com CAS</strong> (<code>tesseras-storage/src/blob.rs</code>) — Reescrito para -delegar todo armazenamento ao CAS. Quando um blob e escrito, seu hash BLAKE3 e -computado e passado para <code>cas.put()</code>. Uma linha em <code>blob_refs</code> mapeia o caminho -logico (tessera + memoria + arquivo) para o hash CAS. Leituras buscam o hash CAS -via <code>blob_refs</code> e leem de <code>cas.get()</code>. Deletar uma tessera libera todas as suas -referencias de blob em uma unica transacao.</p> -<p><strong>FsFragmentStore com CAS</strong> (<code>tesseras-storage/src/fragment.rs</code>) — Mesmo padrao -para fragmentos codificados com erasure coding. O checksum BLAKE3 de cada -fragmento ja e computado durante a codificacao Reed-Solomon, entao e usado -diretamente como chave CAS. A verificacao de fragmentos agora checa o hash CAS -ao inves de recomputar do zero — se o CAS diz que os dados estao intactos, -estao.</p> -<p><strong>Coletor de lixo sweep</strong> (<code>cas.rs:sweep()</code>) — Uma passagem periodica de GC que -trata tres casos limite que o caminho normal de refcount nao consegue:</p> -<ol> -<li><strong>Arquivos orfaos</strong> — arquivos em disco sem linha correspondente em -<code>cas_objects</code>. Pode acontecer apos um crash durante escrita. Arquivos com -menos de 1 hora sao pulados (periodo de graca para escritas em andamento); -orfaos mais antigos sao deletados.</li> -<li><strong>Refcounts vazados</strong> — linhas em <code>cas_objects</code> com refcount zero que nao -foram limpas (ex: se o processo morreu entre decrementar e deletar). Essas -linhas sao removidas.</li> -<li><strong>Idempotente</strong> — executar sweep duas vezes produz o mesmo resultado.</li> -</ol> -<p>O sweep e conectado ao loop de reparo existente em <code>tesseras-replication</code>, entao -roda automaticamente a cada 24 horas junto com as verificacoes de saude dos -fragmentos.</p> -<p><strong>Migracao do layout antigo</strong> (<code>tesseras-storage/src/migration.rs</code>) — Uma -estrategia de migracao copy-first que move dados do layout antigo baseado em -diretorios (<code>blobs/&lt;tessera&gt;/&lt;memoria&gt;/&lt;arquivo&gt;</code> e -<code>fragments/&lt;tessera&gt;/&lt;indice&gt;.shard</code>) para o CAS. A migracao:</p> -<ol> -<li>Verifica a versao de armazenamento em <code>storage_meta</code> (versao 1 = layout -antigo, versao 2 = CAS)</li> -<li>Percorre os diretorios antigos <code>blobs/</code> e <code>fragments/</code></li> -<li>Computa hashes BLAKE3 e insere no CAS via <code>put()</code> — duplicatas sao -automaticamente deduplicadas</li> -<li>Cria entradas correspondentes em <code>blob_refs</code> / <code>fragment_refs</code></li> -<li>Remove diretorios antigos somente apos todos os dados estarem seguros no CAS</li> -<li>Atualiza a versao de armazenamento para 2</li> -</ol> -<p>A migracao roda na inicializacao do daemon, e idempotente (segura para -re-executar) e reporta estatisticas: arquivos migrados, duplicatas encontradas, -bytes economizados.</p> -<p><strong>Metricas Prometheus</strong> (<code>tesseras-storage/src/metrics.rs</code>) — Dez novas metricas -para observabilidade:</p> -<table><thead><tr><th>Metrica</th><th>Descricao</th></tr></thead><tbody> -<tr><td><code>cas_objects_total</code></td><td>Total de objetos unicos no CAS</td></tr> -<tr><td><code>cas_bytes_total</code></td><td>Total de bytes armazenados</td></tr> -<tr><td><code>cas_dedup_hits_total</code></td><td>Numero de escritas que encontraram um objeto existente</td></tr> -<tr><td><code>cas_bytes_saved_total</code></td><td>Bytes economizados por deduplicacao</td></tr> -<tr><td><code>cas_gc_refcount_deletions_total</code></td><td>Objetos deletados quando refcount chegou a zero</td></tr> -<tr><td><code>cas_gc_sweep_orphans_cleaned_total</code></td><td>Arquivos orfaos removidos pelo sweep</td></tr> -<tr><td><code>cas_gc_sweep_leaked_refs_cleaned_total</code></td><td>Linhas de refcount vazadas limpas</td></tr> -<tr><td><code>cas_gc_sweep_skipped_young_total</code></td><td>Orfaos jovens pulados (periodo de graca)</td></tr> -<tr><td><code>cas_gc_sweep_duration_seconds</code></td><td>Tempo gasto no sweep GC</td></tr> -</tbody></table> -<p><strong>Testes baseados em propriedades</strong> — Dois testes proptest verificam invariantes -do CAS sob entradas aleatorias:</p> -<ul> -<li><code>refcount_matches_actual_refs</code> — apos N operacoes aleatorias de put/release, o -refcount sempre corresponde ao numero real de referencias pendentes</li> -<li><code>cas_path_is_deterministic</code> — o mesmo hash sempre produz o mesmo caminho no -sistema de arquivos</li> -</ul> -<p><strong>Atualizacao de testes de integracao</strong> — Todos os testes de integracao em -<code>tesseras-core</code>, <code>tesseras-replication</code>, <code>tesseras-embedded</code> e <code>tesseras-cli</code> -atualizados para os novos construtores com CAS. Testes de deteccao de -adulteracao atualizados para funcionar com o layout de diretorio CAS.</p> -<p>347 testes passam em todo o workspace. Clippy limpo com <code>-D warnings</code>.</p> -<h2 id="decisoes-de-arquitetura">Decisoes de arquitetura</h2> -<ul> -<li><strong>BLAKE3 como chave CAS</strong>: o hash de conteudo que ja computamos para -verificacao de integridade serve tambem como chave de deduplicacao. Nenhuma -etapa adicional de hashing — o hash computado durante <code>create</code> ou <code>replicate</code> -e reutilizado como endereco CAS.</li> -<li><strong>Refcount SQLite ao inves de reflinks do sistema de arquivos</strong>: consideramos -usar copy-on-write no nivel do sistema de arquivos (reflinks em btrfs/XFS), -mas isso amarraria o Tesseras a sistemas de arquivos especificos. Refcounting -em SQLite funciona em qualquer sistema de arquivos, incluindo FAT32 em -pendrives baratos e ext4 em Raspberry Pis.</li> -<li><strong>Diretorios de prefixo hexadecimal de dois niveis</strong>: armazenar todos os -objetos CAS em um diretorio plano desaceleraria sistemas de arquivos com -milhoes de entradas. A divisao <code>&lt;prefixo 2 chars&gt;/</code> limita qualquer diretorio -individual a ~65k entradas antes de um segundo nivel ser necessario. Isso -segue a abordagem usada pelo object store do Git.</li> -<li><strong>Periodo de graca para arquivos orfaos</strong>: o sweep GC pula arquivos com menos -de 1 hora para evitar deletar objetos sendo escritos por uma operacao -concorrente. Esta e uma escolha pragmatica — troca uma pequena janela de -potenciais orfaos por seguranca contra crashes sem exigir fsync ou commit de -duas fases.</li> -<li><strong>Migracao copy-first</strong>: a migracao copia dados para o CAS antes de remover -diretorios antigos. Se o processo for interrompido, os dados antigos -permanecem intactos e a migracao pode ser re-executada. Isso e mais lento que -mover arquivos mas garante zero perda de dados.</li> -<li><strong>Sweep no loop de reparo</strong>: ao inves de adicionar um timer separado de GC, o -sweep CAS aproveita o loop de reparo existente de 24 horas. Isso mantem o -daemon simples — um unico ciclo de manutencao em segundo plano cuida tanto da -saude dos fragmentos quanto da limpeza de armazenamento.</li> -</ul> -<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2> -<ul> -<li><strong>Fase 4 continuacao</strong> — auditorias de seguranca, empacotamento para OS -(Alpine, Arch, Debian, OpenBSD, FreeBSD)</li> -<li><strong>Fase 5: Exploracao e Cultura</strong> — navegador publico de tesseras por -era/localizacao/tema/idioma, curadoria institucional, integracao genealogica -(FamilySearch, Ancestry), exportacao para midia fisica (M-DISC, microfilme, -papel livre de acido com QR), contexto assistido por IA</li> -</ul> -<p>A deduplicacao de armazenamento completa a historia de eficiencia de -armazenamento do Tesseras. Um no que armazena fragmentos para milhares de -usuarios — comum para nos institucionais e nos completos sempre ligados — agora -paga o custo de disco apenas por dados unicos. Combinado com codificacao de -apagamento Reed-Solomon (que ja minimiza redundancia no nivel da rede), o -sistema alcanca armazenamento eficiente tanto nas camadas local quanto -distribuida.</p> -</content> - - </entry> - <entry xml:lang="pt-br"> - <title>Fase 4: Onboarding de Nos Institucionais</title> - <published>2026-02-15T22:00:00+00:00</published> - <updated>2026-02-15T22:00:00+00:00</updated> - - <author> - <name> - - Unknown - - </name> - </author> - - <link rel="alternate" type="text/html" href="https://tesseras.net/pt-br/news/phase4-institutional-onboarding/"/> - <id>https://tesseras.net/pt-br/news/phase4-institutional-onboarding/</id> - - <content type="html" xml:base="https://tesseras.net/pt-br/news/phase4-institutional-onboarding/"><p>Uma rede P2P composta apenas por individuos e fragil. Discos rigidos morrem, -celulares sao perdidos, pessoas perdem interesse. A sobrevivencia a longo prazo -das memorias da humanidade depende de instituicoes — bibliotecas, arquivos, -museus, universidades — que medem seus tempos de vida em seculos. A Fase 4 -continua com o onboarding de nos institucionais: organizacoes verificadas agora -podem prometer armazenamento, manter indices de busca e participar da rede com -uma identidade distinta.</p> -<p>O design segue um principio de confiar mas verificar: instituicoes se -identificam via registros DNS TXT (o mesmo mecanismo usado por SPF, DKIM e DMARC -para email), prometem um orcamento de armazenamento e recebem isencoes de -reciprocidade para que possam armazenar fragmentos para outros sem esperar nada -em troca. Em contrapartida, a rede trata seus fragmentos como replicas de maior -qualidade e limita a dependencia excessiva de qualquer instituicao individual -atraves de restricoes de diversidade.</p> -<h2 id="o-que-foi-construido">O que foi construido</h2> -<p><strong>Bits de capacidade</strong> (<code>tesseras-core/src/network.rs</code>) — Dois novos flags -adicionados ao bitfield <code>Capabilities</code>: <code>INSTITUTIONAL</code> (bit 7) e <code>SEARCH_INDEX</code> -(bit 8). Um novo construtor <code>institutional_default()</code> retorna o conjunto -completo de capacidades da Fase 2 mais esses dois bits e <code>RELAY</code>. Nos normais -anunciam <code>phase2_default()</code> que nao inclui flags institucionais. Testes de -roundtrip de serializacao verificam que os novos bits sobrevivem a codificacao -MessagePack.</p> -<p><strong>Tipos de busca</strong> (<code>tesseras-core/src/search.rs</code>) — Tres novos tipos de dominio -para o subsistema de busca:</p> -<ul> -<li><code>SearchFilters</code> — parametros de consulta: <code>memory_type</code>, <code>visibility</code>, -<code>language</code>, <code>date_range</code>, <code>geo</code> (bounding box), <code>page</code>, <code>page_size</code></li> -<li><code>SearchHit</code> — um resultado individual: hash do conteudo mais um -<code>MetadataExcerpt</code> (titulo, descricao, tipo de memoria, data de criacao, -visibilidade, idioma, tags)</li> -<li><code>GeoFilter</code> — bounding box com <code>min_lat</code>, <code>max_lat</code>, <code>min_lon</code>, <code>max_lon</code> para -consultas espaciais</li> -</ul> -<p>Todos os tipos derivam <code>Serialize</code>/<code>Deserialize</code> para transporte e -<code>Clone</code>/<code>Debug</code> para diagnostico.</p> -<p><strong>Configuracao institucional do daemon</strong> (<code>tesd/src/config.rs</code>) — Uma nova secao -<code>[institutional]</code> no TOML com <code>domain</code> (o dominio DNS a verificar), -<code>pledge_bytes</code> (compromisso de armazenamento em bytes) e <code>search_enabled</code> -(toggle para o indice FTS5). O metodo <code>to_dht_config()</code> agora define -<code>Capabilities::institutional_default()</code> quando a configuracao institucional esta -presente, para que nos institucionais anunciem os bits de capacidade corretos em -respostas Pong.</p> -<p><strong>Verificacao DNS TXT</strong> (<code>tesd/src/institutional.rs</code>) — Resolucao DNS assincrona -usando <code>hickory-resolver</code> para verificar identidade institucional. O daemon -consulta registros TXT em <code>_tesseras.&lt;dominio&gt;</code> e analisa campos chave-valor: -<code>v</code> (versao), <code>node</code> (node ID em hexadecimal) e <code>pledge</code> (compromisso de -armazenamento em bytes). A verificacao checa:</p> -<ol> -<li>Um registro TXT existe em <code>_tesseras.&lt;dominio&gt;</code></li> -<li>O campo <code>node</code> corresponde ao node ID do proprio daemon</li> -<li>O campo <code>pledge</code> esta presente e e valido</li> -</ol> -<p>Na inicializacao, o daemon tenta a verificacao DNS. Se bem-sucedida, o no roda -com capacidades institucionais. Se falhar, o no registra um aviso e faz -downgrade para um no completo normal — sem crash, sem intervencao manual.</p> -<p><strong>Comando CLI de setup</strong> (<code>tesseras-cli/src/institutional.rs</code>) — Um novo -subcomando <code>institutional setup</code> que guia operadores pelo onboarding:</p> -<ol> -<li>Le a identidade do no a partir do diretorio de dados</li> -<li>Solicita nome de dominio e tamanho do pledge</li> -<li>Gera o registro DNS TXT exato a adicionar: -<code>v=tesseras1 node=&lt;hex&gt; pledge=&lt;bytes&gt;</code></li> -<li>Escreve a secao institucional no arquivo de configuracao do daemon</li> -<li>Imprime os proximos passos: adicionar o registro TXT, reiniciar o daemon</li> -</ol> -<p><strong>Indice de busca SQLite</strong> (<code>tesseras-storage</code>) — Uma migracao -(<code>003_institutional.sql</code>) que cria tres estruturas:</p> -<ul> -<li><code>search_content</code> — uma tabela virtual FTS5 para busca full-text sobre -metadados de tesseras (titulo, descricao, criador, tags, idioma)</li> -<li><code>geo_index</code> — uma tabela virtual R-tree para consultas espaciais de bounding -box sobre latitude/longitude</li> -<li><code>geo_map</code> — uma tabela de mapeamento ligando IDs de linhas do R-tree a hashes -de conteudo</li> -</ul> -<p>O adaptador <code>SqliteSearchIndex</code> implementa o port trait <code>SearchIndex</code> com -<code>index_tessera()</code> (inserir/atualizar) e <code>search()</code> (consultar com filtros). -Consultas FTS5 suportam busca em linguagem natural; consultas geo usam -<code>INTERSECT</code> do R-tree para lookups de bounding box. Resultados sao ranqueados -por score de relevancia do FTS5.</p> -<p>A migracao tambem adiciona uma coluna <code>is_institutional</code> a tabela <code>reciprocity</code>, -tratada de forma idempotente via checagens <code>pragma_table_info</code> (o -<code>ALTER TABLE ADD COLUMN</code> do SQLite nao tem <code>IF NOT EXISTS</code>).</p> -<p><strong>Bypass de reciprocidade</strong> (<code>tesseras-replication/src/service.rs</code>) — Nos -institucionais sao isentos de checagens de reciprocidade. Quando -<code>receive_fragment()</code> e chamado, se o node ID do remetente esta marcado como -institucional no ledger de reciprocidade, a checagem de saldo e ignorada -completamente. Isso significa que instituicoes podem armazenar fragmentos para -toda a rede sem precisar "ganhar" creditos primeiro — sua identidade verificada -por DNS e compromisso de armazenamento servem como credencial.</p> -<p><strong>Restricao de diversidade por tipo de no</strong> -(<code>tesseras-replication/src/distributor.rs</code>) — Uma nova funcao -<code>apply_institutional_diversity()</code> limita quantas replicas de uma unica tessera -podem ir para nos institucionais. O limite e <code>ceil(fator_replicacao / 3.5)</code> — -com o padrao <code>r=7</code>, no maximo 2 de 7 replicas vao para instituicoes. Isso impede -que a rede se torne dependente de um pequeno numero de grandes instituicoes: se -os servidores de uma universidade cairem, pelo menos 5 replicas permanecem em -nos independentes.</p> -<p><strong>Extensoes de mensagens DHT</strong> (<code>tesseras-dht/src/message.rs</code>) — Duas novas -variantes de mensagem:</p> -<table><thead><tr><th>Mensagem</th><th>Proposito</th></tr></thead><tbody> -<tr><td><code>Search</code></td><td>Cliente envia string de consulta, filtros e numero da pagina</td></tr> -<tr><td><code>SearchResult</code></td><td>No institucional responde com resultados e contagem total</td></tr> -</tbody></table> -<p>A funcao <code>encode()</code> foi trocada de serializacao MessagePack posicional para -nomeada (<code>rmp_serde::to_vec_named</code>) para lidar corretamente com campos opcionais -de <code>SearchFilters</code> — a codificacao posicional quebra quando -<code>skip_serializing_if</code> omite campos.</p> -<p><strong>Metricas Prometheus</strong> (<code>tesd/src/metrics.rs</code>) — Oito metricas especificas -institucionais:</p> -<ul> -<li><code>tesseras_institutional_pledge_bytes</code> — compromisso de armazenamento -configurado</li> -<li><code>tesseras_institutional_stored_bytes</code> — bytes realmente armazenados</li> -<li><code>tesseras_institutional_pledge_utilization_ratio</code> — razao armazenado/prometido</li> -<li><code>tesseras_institutional_peers_served</code> — peers unicos que receberam fragmentos</li> -<li><code>tesseras_institutional_search_index_total</code> — tesseras no indice de busca</li> -<li><code>tesseras_institutional_search_queries_total</code> — consultas de busca recebidas</li> -<li><code>tesseras_institutional_dns_verification_status</code> — 1 se verificado por DNS, 0 -caso contrario</li> -<li><code>tesseras_institutional_dns_verification_last</code> — timestamp Unix da ultima -verificacao</li> -</ul> -<p><strong>Testes de integracao</strong> — Dois testes em -<code>tesseras-replication/tests/integration.rs</code>:</p> -<ul> -<li><code>institutional_peer_bypasses_reciprocity</code> — verifica que um peer institucional -com deficit massivo (-999.999 de saldo) ainda pode armazenar fragmentos, -enquanto um peer nao institucional com o mesmo deficit e rejeitado</li> -<li><code>institutional_node_accepts_fragment_despite_deficit</code> — teste async completo -usando <code>ReplicationService</code> com DHT, fragment store, reciprocity ledger e blob -store mockados: envia um fragmento de um remetente institucional e verifica -que e aceito</li> -</ul> -<p>322 testes passam em todo o workspace. Clippy limpo com <code>-D warnings</code>.</p> -<h2 id="decisoes-de-arquitetura">Decisoes de arquitetura</h2> -<ul> -<li><strong>DNS TXT ao inves de PKI ou blockchain</strong>: DNS e universalmente implantado, -universalmente compreendido e ja usado para verificacao de dominio (SPF, DKIM, -Let's Encrypt). Instituicoes ja gerenciam DNS. Nenhuma autoridade -certificadora, nenhum token, nenhuma transacao on-chain — apenas um registro -TXT. Se uma instituicao perder controle de seu dominio, a verificacao -naturalmente falha na proxima checagem.</li> -<li><strong>Degradacao graciosa em falha DNS</strong>: se a verificacao DNS falha na -inicializacao, o daemon faz downgrade para um no completo normal ao inves de -recusar iniciar. Isso previne incidentes operacionais — uma misconfiguracao -DNS nao deveria tirar um no do ar.</li> -<li><strong>Limite de diversidade em <code>ceil(r / 3.5)</code></strong>: com <code>r=7</code>, no maximo 2 replicas -vao para instituicoes. Isso e conservador — garante que a rede nunca dependa -de instituicoes para quorum majoritario, enquanto ainda se beneficia de sua -capacidade de armazenamento e uptime.</li> -<li><strong>Codificacao MessagePack nomeada</strong>: trocar de codificacao posicional para -nomeada adiciona ~15% de overhead por mensagem mas elimina uma classe de bugs -de serializacao quando campos opcionais estao presentes. O DHT nao e limitado -por largura de banda no nivel de mensagem, entao o tradeoff vale a pena.</li> -<li><strong>Isencao de reciprocidade ao inves de concessao de creditos</strong>: ao inves de -dar as instituicoes um saldo inicial grande de creditos (que e arbitrario e -precisa de ajuste), isentamos completamente. Sua identidade verificada por DNS -e compromisso publico de armazenamento substituem o mecanismo de reciprocidade -bilateral.</li> -<li><strong>FTS5 + R-tree no SQLite</strong>: busca full-text e indexacao espacial sao -embutidas no SQLite como extensoes carregaveis. Nenhum motor de busca externo -(Elasticsearch, Meilisearch) necessario. Isso mantem o deploy como um unico -binario com um unico arquivo de banco de dados — critico para operadores -institucionais que podem nao ter uma equipe de DevOps.</li> -</ul> -<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2> -<ul> -<li><strong>Fase 4 continuacao</strong> — deduplicacao de armazenamento (armazenamento -enderecavel por conteudo com BLAKE3), auditorias de seguranca, empacotamento -para OS (Alpine, Arch, Debian, OpenBSD, FreeBSD)</li> -<li><strong>Fase 5: Exploracao e Cultura</strong> — navegador publico de tesseras por -era/localizacao/tema/idioma, curadoria institucional, integracao genealogica -(FamilySearch, Ancestry), exportacao para midia fisica (M-DISC, microfilme, -papel livre de acido com QR), contexto assistido por IA</li> -</ul> -<p>O onboarding institucional fecha uma lacuna critica no modelo de preservacao do -Tesseras. Nos individuais fornecem resiliencia de base — milhares de -dispositivos ao redor do globo, cada um armazenando alguns fragmentos. Nos -institucionais fornecem ancoragem — organizacoes com infraestrutura -profissional, armazenamento redundante e horizontes operacionais de multiplas -decadas. Juntos, formam uma rede onde memorias podem sobreviver tanto a -dispositivos individuais quanto a instituicoes individuais.</p> -</content> - - </entry> - <entry xml:lang="pt-br"> - <title>Fase 4: Tuning de Performance</title> - <published>2026-02-15T20:00:00+00:00</published> - <updated>2026-02-15T20:00:00+00:00</updated> - - <author> - <name> - - Unknown - - </name> - </author> - - <link rel="alternate" type="text/html" href="https://tesseras.net/pt-br/news/phase4-performance-tuning/"/> - <id>https://tesseras.net/pt-br/news/phase4-performance-tuning/</id> - - <content type="html" xml:base="https://tesseras.net/pt-br/news/phase4-performance-tuning/"><p>Uma rede P2P que atravessa NATs mas engasga com seu proprio I/O nao serve de -muito. A Fase 4 continua com tuning de performance: centralizacao da -configuracao do banco de dados, cache de blobs de fragmentos em memoria, -gerenciamento de ciclo de vida de conexoes QUIC e eliminacao de leituras -desnecessarias de disco no hot path de atestacao.</p> -<p>O principio orientador foi o mesmo do resto do Tesseras: fazer a coisa mais -simples que realmente funciona. Sem alocadores customizados, sem estruturas de -dados lock-free, sem complexidade prematura. Um <code>StorageConfig</code> centralizado, um -cache LRU, um reaper de conexoes e uma correcao pontual para evitar reler blobs -que ja tinham checksum calculado.</p> -<h2 id="o-que-foi-construido">O que foi construido</h2> -<p><strong>Configuracao SQLite centralizada</strong> (<code>tesseras-storage/src/database.rs</code>) — Um -novo struct <code>StorageConfig</code> e funcoes <code>open_database()</code> / <code>open_in_memory()</code> que -aplicam todos os pragmas SQLite em um unico lugar: journal mode WAL, foreign -keys, modo synchronous (NORMAL por padrao, FULL para hardware instavel como -RPi + cartao SD), busy timeout, tamanho do cache de paginas e intervalo de -autocheckpoint WAL. Anteriormente, cada ponto de chamada abria uma conexao e -aplicava pragmas ad hoc. Agora o daemon, CLI e testes passam todos pelo mesmo -caminho. 7 testes cobrindo foreign keys, busy timeout, journal mode, migracoes, -modos synchronous e criacao de arquivos WAL em disco.</p> -<p><strong>Cache LRU de fragmentos</strong> (<code>tesseras-storage/src/cache.rs</code>) — Um -<code>CachedFragmentStore</code> que envolve qualquer <code>FragmentStore</code> com um cache LRU -ciente de bytes. Blobs de fragmentos sao cacheados na leitura e invalidados na -escrita ou exclusao. Quando o cache excede seu limite de bytes configurado, as -entradas menos recentemente usadas sao removidas. O cache e transparente: ele -proprio implementa <code>FragmentStore</code>, entao o resto da pilha nao sabe que esta la. -Metricas Prometheus opcionais rastreiam hits, misses e uso atual de bytes. 3 -testes: hit no cache evita leitura interna, store invalida cache, remocao quando -excede bytes maximos.</p> -<p><strong>Metricas Prometheus de storage</strong> (<code>tesseras-storage/src/metrics.rs</code>) — Um -struct <code>StorageMetrics</code> com tres contadores/gauges: <code>fragment_cache_hits</code>, -<code>fragment_cache_misses</code> e <code>fragment_cache_bytes</code>. Registrado no registry -Prometheus e conectado ao cache de fragmentos via <code>with_metrics()</code>.</p> -<p><strong>Correcao do hot path de atestacao</strong> (<code>tesseras-replication/src/service.rs</code>) — -O fluxo de atestacao anteriormente lia cada blob de fragmento do disco e -recalculava seu checksum BLAKE3. Como <code>list_fragments()</code> ja retorna <code>FragmentId</code> -com um checksum armazenado, a correcao e trivial: usar <code>frag.checksum</code> ao inves -de <code>blake3::hash(&amp;data)</code>. Isso elimina uma leitura de disco por fragmento -durante atestacao — para uma tessera com 100 fragmentos, sao 100 leituras a -menos. Um teste com <code>expect_read_fragment().never()</code> verifica que nenhuma -leitura de blob acontece durante atestacao.</p> -<p><strong>Ciclo de vida do pool de conexoes QUIC</strong> -(<code>tesseras-net/src/quinn_transport.rs</code>) — Um struct <code>PoolConfig</code> controlando -maximo de conexoes, timeout de inatividade e intervalo do reaper. -<code>PooledConnection</code> envolve cada <code>quinn::Connection</code> com um timestamp -<code>last_used</code>. Quando o pool atinge capacidade maxima, a conexao inativa mais -antiga e removida antes de abrir uma nova. Uma tarefa reaper em background -(Tokio spawn) periodicamente fecha conexoes que ficaram inativas alem do -timeout. 4 novas metricas de pool: <code>tesseras_conn_pool_size</code>, <code>pool_hits_total</code>, -<code>pool_misses_total</code>, <code>pool_evictions_total</code>.</p> -<p><strong>Integracao no daemon</strong> (<code>tesd/src/config.rs</code>, <code>main.rs</code>) — Uma nova secao -<code>[performance]</code> na configuracao TOML com campos para tamanho de cache SQLite, -modo synchronous, busy timeout, tamanho de cache de fragmentos, maximo de -conexoes, timeout de inatividade e intervalo do reaper. O <code>main()</code> do daemon -agora chama <code>open_database()</code> com o <code>StorageConfig</code> configurado, envolve -<code>FsFragmentStore</code> com <code>CachedFragmentStore</code> e vincula QUIC com o <code>PoolConfig</code> -configurado. A dependencia direta de <code>rusqlite</code> foi removida do crate do daemon.</p> -<p><strong>Migracao do CLI</strong> (<code>tesseras-cli/src/commands/init.rs</code>, <code>create.rs</code>) — Ambos -os comandos <code>init</code> e <code>create</code> agora usam <code>tesseras_storage::open_database()</code> com -o <code>StorageConfig</code> padrao ao inves de abrir conexoes <code>rusqlite</code> diretamente. A -dependencia de <code>rusqlite</code> foi removida do crate do CLI.</p> -<h2 id="decisoes-de-arquitetura">Decisoes de arquitetura</h2> -<ul> -<li><strong>Padrao decorator para cache</strong>: <code>CachedFragmentStore</code> envolve -<code>Box&lt;dyn FragmentStore&gt;</code> e implementa <code>FragmentStore</code> ele proprio. Isso -significa que cache e opt-in, composavel e invisivel para consumidores. O -daemon habilita; testes podem pular.</li> -<li><strong>Remocao ciente de bytes</strong>: o cache LRU rastreia bytes totais, nao contagem -de entradas. Blobs de fragmentos variam muito em tamanho (um fragmento de -texto de 4KB vs um shard de foto de 2MB), entao contar entradas daria uma -visao enganosa do uso de memoria.</li> -<li><strong>Sem crate de pool de conexoes</strong>: ao inves de trazer uma biblioteca generica -de pool, o pool de conexoes e um wrapper fino sobre -<code>DashMap&lt;SocketAddr, PooledConnection&gt;</code> com um reaper Tokio. Conexoes QUIC sao -multiplexadas, entao o "pool" e realmente sobre gerenciamento de ciclo de vida -(limpeza de inativos, maximo de conexoes) e nao sobre emprestar/devolver.</li> -<li><strong>Checksums armazenados ao inves de releituras</strong>: a correcao de atestacao e -intencionalmente minima — uma linha alterada, uma leitura de disco removida -por fragmento. Os checksums ja estavam armazenados no SQLite por -<code>store_fragment()</code>, apenas nao estavam sendo usados.</li> -<li><strong>Configuracao centralizada de pragmas</strong>: um unico struct <code>StorageConfig</code> -substitui chamadas <code>PRAGMA</code> espalhadas. O flag <code>sqlite_synchronous_full</code> -existe especificamente para implantacoes em Raspberry Pi onde o kernel pode -crashar e perder transacoes WAL nao checkpointadas.</li> -</ul> -<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2> -<ul> -<li><strong>Fase 4 continuacao</strong> — Shamir's Secret Sharing para herdeiros, tesseras -seladas (criptografia time-lock), auditorias de seguranca, onboarding de nos -institucionais, deduplicacao de storage, empacotamento para OS</li> -<li><strong>Fase 5: Exploracao e Cultura</strong> — navegador publico de tesseras por -era/localizacao/tema/idioma, curadoria institucional, integracao genealogica, -exportacao para midia fisica (M-DISC, microfilme, papel livre de acido com QR)</li> -</ul> -<p>Com tuning de performance implementado, Tesseras lida com o caso comum de forma -eficiente: leituras de fragmentos acertam o cache LRU, atestacao pula I/O de -disco, conexoes QUIC inativas sao removidas automaticamente e o SQLite e -configurado consistentemente em toda a pilha. Os proximos passos focam em -funcionalidades criptograficas (Shamir, time-lock) e hardening para implantacao -em producao.</p> -</content> - - </entry> - <entry xml:lang="pt-br"> - <title>Fase 4: Verificar Sem Instalar Nada</title> - <published>2026-02-15T20:00:00+00:00</published> - <updated>2026-02-15T20:00:00+00:00</updated> - - <author> - <name> - - Unknown - - </name> - </author> - - <link rel="alternate" type="text/html" href="https://tesseras.net/pt-br/news/phase4-wasm-browser-verification/"/> - <id>https://tesseras.net/pt-br/news/phase4-wasm-browser-verification/</id> - - <content type="html" xml:base="https://tesseras.net/pt-br/news/phase4-wasm-browser-verification/"><p>Confiança não deveria exigir instalação de software. Se alguém te envia uma -tessera — um pacote de memórias preservadas — você deveria poder verificar que é -genuína e não foi modificada sem baixar um app, criar uma conta, ou confiar em -um servidor. É isso que o <code>tesseras-wasm</code> entrega: arraste um arquivo tessera -para uma página web, e a verificação criptográfica acontece inteiramente no seu -navegador.</p> -<h2 id="o-que-foi-construido">O que foi construído</h2> -<p><strong>tesseras-wasm</strong> — Um crate Rust que compila para WebAssembly via wasm-pack, -expondo quatro funções stateless para JavaScript. O crate depende do -<code>tesseras-core</code> para parsing do manifesto e chama primitivas criptográficas -diretamente (blake3, ed25519-dalek) ao invés de depender do <code>tesseras-crypto</code>, -que puxa bibliotecas pós-quânticas baseadas em C que não compilam para -<code>wasm32-unknown-unknown</code>.</p> -<p><code>parse_manifest</code> recebe os bytes brutos do MANIFEST (texto UTF-8 plano, não -MessagePack), delega para <code>tesseras_core::manifest::Manifest::parse()</code>, e -retorna uma string JSON com a chave pública Ed25519 do criador, caminhos dos -arquivos de assinatura, e uma lista de arquivos com seus hashes BLAKE3 -esperados, tamanhos e tipos MIME. Structs internas (<code>ManifestJson</code>, -<code>CreatorPubkey</code>, <code>SignatureFiles</code>, <code>FileEntry</code>) são serializadas com serde_json. -Os campos de chave pública ML-DSA e arquivo de assinatura estão presentes no -contrato JSON mas definidos como <code>null</code> — prontos para quando a assinatura -pós-quântica for implementada no lado nativo.</p> -<p><code>hash_blake3</code> computa um hash BLAKE3 de bytes arbitrários e retorna uma string -hexadecimal de 64 caracteres. É chamada uma vez por arquivo na tessera para -verificar integridade contra o MANIFEST.</p> -<p><code>verify_ed25519</code> recebe uma mensagem, uma assinatura de 64 bytes e uma chave -pública de 32 bytes, constrói uma <code>ed25519_dalek::VerifyingKey</code>, e retorna se a -assinatura é válida. A validação de comprimento retorna erros descritivos -("Ed25519 public key must be 32 bytes") ao invés de causar panic.</p> -<p><code>verify_ml_dsa</code> é um stub que retorna um erro explicando que verificação ML-DSA -ainda não está disponível. Isso é deliberado: o crate <code>ml-dsa</code> no crates.io está -na v0.1.0-rc.7 (pré-release), e o <code>tesseras-crypto</code> usa <code>pqcrypto-dilithium</code> -(CRYSTALS-Dilithium baseado em C) que é incompatível em nível de bytes com FIPS -204 ML-DSA. Ambos os lados precisam usar a mesma implementação em Rust puro -antes que a verificação cruzada funcione. Verificação Ed25519 é suficiente — -toda tessera é assinada com Ed25519.</p> -<p>Todas as quatro funções usam um padrão de duas camadas para testabilidade: -funções internas retornam <code>Result&lt;T, String&gt;</code> e são testadas nativamente, -enquanto wrappers finos <code>#[wasm_bindgen]</code> convertem erros para <code>JsError</code>. Isso -evita que <code>JsError::new()</code> cause panic em targets não-WASM durante os testes.</p> -<p>O binário WASM compilado tem 109 KB bruto e 44 KB com gzip — bem abaixo do -orçamento de 200 KB. O wasm-opt aplica otimização <code>-Oz</code> após o wasm-pack -compilar com <code>opt-level = "z"</code>, LTO e uma única unidade de codegen.</p> -<p><strong>@tesseras/verify</strong> — Um pacote npm TypeScript (<code>crates/tesseras-wasm/js/</code>) que -orquestra a verificação no lado do navegador. A API pública é uma única função:</p> -<pre><code data-lang="typescript">async function verifyTessera( - archive: Uint8Array, - onProgress?: (current: number, total: number, file: string) =&gt; void -): Promise&lt;VerificationResult&gt; -</code></pre> -<p>O tipo <code>VerificationResult</code> fornece tudo que uma UI precisa: validade geral, -hash da tessera, chaves públicas do criador, status das assinaturas -(valid/invalid/missing para Ed25519 e ML-DSA), resultados de integridade por -arquivo com hashes esperados e reais, uma lista de arquivos inesperados não -presentes no MANIFEST, e um array de erros.</p> -<p>A descompactação de arquivos (<code>unpack.ts</code>) lida com três formatos: tar -comprimido com gzip (detectado pelos magic bytes <code>\x1f\x8b</code>, descomprimido com -fflate e depois parseado como tar), ZIP (magic <code>PK\x03\x04</code>, descompactado com -<code>unzipSync</code> do fflate), e tar bruto (<code>ustar</code> no offset 257). Uma função -<code>normalizePath</code> remove o prefixo <code>tessera-&lt;hash&gt;/</code> para que os caminhos internos -correspondam às entradas do MANIFEST.</p> -<p>A verificação roda em um Web Worker (<code>worker.ts</code>) para manter a thread da UI -responsiva. O worker inicializa o módulo WASM, descompacta o arquivo, parseia o -MANIFEST, verifica a assinatura Ed25519 contra a chave pública do criador, -depois faz hash de cada arquivo com BLAKE3 e compara com os valores esperados. -Mensagens de progresso são transmitidas de volta para a thread principal após -cada arquivo. Se qualquer assinatura é inválida, a verificação para -imediatamente sem fazer hash dos arquivos — falhando rápido na verificação mais -crítica.</p> -<p>O arquivo é transferido para o worker com zero-copy -(<code>worker.postMessage({ type: "verify", archive }, [archive.buffer])</code>) para -evitar duplicar arquivos de tessera potencialmente grandes na memória.</p> -<p><strong>Pipeline de build</strong> — Três novos targets no justfile: <code>wasm-build</code> executa -wasm-pack com <code>--target web --release</code> e otimiza com wasm-opt; <code>wasm-size</code> -reporta o tamanho do binário bruto e com gzip; <code>test-wasm</code> executa a suíte de -testes nativos.</p> -<p><strong>Testes</strong> — 9 testes unitários nativos cobrem hashing BLAKE3 (entrada vazia, -valor conhecido), verificação Ed25519 (assinatura válida, assinatura inválida, -chave errada, comprimento de chave inválido), e parsing do MANIFEST (manifesto -válido, UTF-8 inválido, lixo). 3 testes de integração WASM rodam em Chrome -headless via <code>wasm-pack test --headless --chrome</code>, verificando que -<code>hash_blake3</code>, <code>verify_ed25519</code> e <code>parse_manifest</code> funcionam corretamente quando -compilados para <code>wasm32-unknown-unknown</code>.</p> -<h2 id="decisoes-de-arquitetura">Decisões de arquitetura</h2> -<ul> -<li><strong>Sem dependência do tesseras-crypto</strong>: o crate WASM chama blake3 e -ed25519-dalek diretamente. O <code>tesseras-crypto</code> depende do <code>pqcrypto-kyber</code> -(ML-KEM baseado em C via pqcrypto-traits) que requer um toolchain de -compilador C e não tem target wasm32. Dependendo apenas de crates Rust puros, -o build WASM tem zero dependências C e compila sem problemas para WebAssembly.</li> -<li><strong>ML-DSA adiado, não fingido</strong>: ao invés de silenciosamente pular a -verificação pós-quântica, o stub retorna um erro explícito. Isso garante que -se uma tessera contiver uma assinatura ML-DSA, o resultado da verificação -reportará <code>ml_dsa: "missing"</code> ao invés de fingir que foi verificada. O -orquestrador JS lida com isso graciosamente — uma tessera é válida se Ed25519 -passar e ML-DSA estiver ausente (ainda não implementado em nenhum dos lados).</li> -<li><strong>Padrão de função interna</strong>: <code>JsError</code> não pode ser construído em targets -não-WASM (causa panic). Dividir cada função em -<code>foo_inner() -&gt; Result&lt;T, String&gt;</code> e <code>foo() -&gt; Result&lt;T, JsError&gt;</code> permite que -a suíte de testes nativa exercite toda a lógica sem tocar em tipos JavaScript. -Os testes de integração WASM em Chrome headless testam a superfície completa -do <code>#[wasm_bindgen]</code>.</li> -<li><strong>Isolamento em Web Worker</strong>: operações criptográficas (especialmente BLAKE3 -sobre arquivos de mídia grandes) podem levar centenas de milissegundos. Rodar -em um Worker previne travamentos na UI. O protocolo de progresso com streaming -(<code>{ type: "progress", current, total, file }</code>) permite que a UI mostre uma -barra de progresso durante a verificação de tesseras com muitos arquivos.</li> -<li><strong>Transferência zero-copy</strong>: <code>archive.buffer</code> é transferido para o Worker, não -copiado. Para um arquivo tessera de 50 MB, isso evita dobrar o uso de memória -durante a verificação.</li> -<li><strong>MANIFEST em texto plano, não MessagePack</strong>: o crate WASM parseia o mesmo -formato de MANIFEST em texto plano que o CLI. Isso é por design — o MANIFEST é -a Pedra de Rosetta da tessera, legível por qualquer pessoa com um editor de -texto. A dependência <code>rmp-serde</code> no Cargo.toml não é usada e será removida.</li> -</ul> -<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2> -<ul> -<li><strong>Fase 4: Resiliência e Escala</strong> — Empacotamento para sistemas operacionais -(Alpine, Arch, Debian, FreeBSD, OpenBSD), CI no SourceHut e GitHub Actions, -auditorias de segurança, explorador de tesseras no navegador em tesseras.net -usando @tesseras/verify</li> -<li><strong>Fase 5: Exploração e Cultura</strong> — Navegador público de tesseras por -era/localização/tema/idioma, curadoria institucional, integração com -genealogia, exportação para mídia física (M-DISC, microfilme, papel livre de -ácido com QR)</li> -</ul> -<p>A verificação não exige mais confiança em software. Um arquivo tessera arrastado -para um navegador é verificado com o mesmo rigor criptográfico do CLI — mesmos -hashes BLAKE3, mesmas assinaturas Ed25519, mesmo parser de MANIFEST. A diferença -é que agora qualquer pessoa pode fazer isso.</p> -</content> - - </entry> - <entry xml:lang="pt-br"> - <title>Fase 4: Furando NATs</title> - <published>2026-02-15T18:00:00+00:00</published> - <updated>2026-02-15T18:00:00+00:00</updated> - - <author> - <name> - - Unknown - - </name> - </author> - - <link rel="alternate" type="text/html" href="https://tesseras.net/pt-br/news/phase4-nat-traversal/"/> - <id>https://tesseras.net/pt-br/news/phase4-nat-traversal/</id> - - <content type="html" xml:base="https://tesseras.net/pt-br/news/phase4-nat-traversal/"><p>A maioria dos dispositivos das pessoas ficam atras de um NAT — um tradutor de -enderecos de rede que permite acessar a internet mas impede conexoes de entrada. -Para uma rede P2P, isso e um problema existencial: se dois nos atras de NATs nao -conseguem se comunicar, a rede se fragmenta. A Fase 4 continua com uma pilha -completa de travessia de NAT: descoberta via STUN, hole punching coordenado e -fallback por relay.</p> -<p>A abordagem segue o mesmo padrao da maioria dos sistemas P2P consolidados -(WebRTC, BitTorrent, IPFS): tente a opcao mais barata primeiro, escale apenas -quando necessario. Conectividade direta nao custa nada. Hole punching custa -alguns pacotes coordenados. Relay custa largura de banda sustentada de um -terceiro. Tesseras tenta nessa ordem.</p> -<h2 id="o-que-foi-construido">O que foi construido</h2> -<p><strong>Classificacao NatType</strong> (<code>tesseras-core/src/network.rs</code>) — Um novo enum -<code>NatType</code> (Public, Cone, Symmetric, Unknown) adicionado a camada de dominio -core. Esse tipo e compartilhado por toda a pilha: o cliente STUN o escreve, o -DHT o divulga em mensagens Pong, e o coordenador de punch o le para decidir se -hole punching vale a pena tentar (Cone-para-Cone funciona ~80% das vezes; -Symmetric-para-Symmetric quase nunca funciona).</p> -<p><strong>Cliente STUN</strong> (<code>tesseras-net/src/stun.rs</code>) — Uma implementacao STUN minima -(RFC 5389 Binding Request/Response) que descobre o endereco externo de um no. O -codec codifica requisicoes de 20 bytes com um ID de transacao aleatorio e -decodifica respostas XOR-MAPPED-ADDRESS. A funcao <code>discover_nat()</code> consulta -multiplos servidores STUN em paralelo (Google, Cloudflare por padrao), compara -os enderecos mapeados e classifica o tipo de NAT:</p> -<ul> -<li>Mesmo IP e porta de todos os servidores → <strong>Public</strong> (sem NAT)</li> -<li>Mesmo endereco mapeado de todos os servidores → <strong>Cone</strong> (hole punching -funciona)</li> -<li>Enderecos mapeados diferentes → <strong>Symmetric</strong> (hole punching nao confiavel)</li> -<li>Sem respostas → <strong>Unknown</strong></li> -</ul> -<p>Retentativas com backoff exponencial e timeouts configuraveis. 12 testes -cobrindo roundtrips de codec, todos os caminhos de classificacao e consultas -async em loopback.</p> -<p><strong>Coordenacao de punch assinada</strong> (<code>tesseras-net/src/punch.rs</code>) — Assinatura e -verificacao Ed25519 para mensagens <code>PunchIntro</code>, <code>RelayRequest</code> e -<code>RelayMigrate</code>. Cada introducao e assinada pelo iniciador com uma janela de -timestamp de 30 segundos, prevenindo ataques de reflexao (onde um atacante -reproduz uma introducao antiga para redirecionar trafego). O formato do payload -e <code>target || external_addr || timestamp</code> — alterar qualquer campo invalida a -assinatura. 6 testes unitarios mais 3 testes baseados em propriedades com -proptest (IDs de no, portas e tokens de sessao arbitrarios).</p> -<p><strong>Gerenciador de sessoes de relay</strong> (<code>tesseras-net/src/relay.rs</code>) — Gerencia -sessoes de relay UDP transparente entre nos com NAT. Cada sessao tem um token -aleatorio de 16 bytes; os nos prefixam seus pacotes com o token, o relay remove -e encaminha. Funcionalidades:</p> -<ul> -<li>Encaminhamento bidirecional (A→R→B e B→R→A)</li> -<li>Limite de taxa: 256 KB/s para nos reciprocos, 64 KB/s para nao reciprocos</li> -<li>Duracao maxima de 10 minutos para sessoes bootstrap (nao reciprocas)</li> -<li>Migracao de endereco: quando o IP de um no muda (Wi-Fi para celular), um -<code>RelayMigrate</code> assinado atualiza a sessao sem derruba-la</li> -<li>Limpeza por inatividade com timeout configuravel</li> -<li>8 testes unitarios mais 2 testes baseados em propriedades</li> -</ul> -<p><strong>Extensoes de mensagens DHT</strong> (<code>tesseras-dht/src/message.rs</code>) — Sete novas -variantes de mensagem adicionadas ao protocolo DHT:</p> -<table><thead><tr><th>Mensagem</th><th>Proposito</th></tr></thead><tbody> -<tr><td><code>PunchIntro</code></td><td>"Quero conectar ao no X, aqui esta meu endereco externo assinado"</td></tr> -<tr><td><code>PunchRequest</code></td><td>O introdutor encaminha a requisicao ao destino</td></tr> -<tr><td><code>PunchReady</code></td><td>O destino confirma prontidao, envia seu endereco externo</td></tr> -<tr><td><code>RelayRequest</code></td><td>"Crie uma sessao de relay para o no X"</td></tr> -<tr><td><code>RelayOffer</code></td><td>O relay responde com seu endereco e token de sessao</td></tr> -<tr><td><code>RelayClose</code></td><td>Encerrar uma sessao de relay</td></tr> -<tr><td><code>RelayMigrate</code></td><td>Atualizar sessao apos mudanca de rede</td></tr> -</tbody></table> -<p>A mensagem <code>Pong</code> foi estendida com metadados NAT: <code>nat_type</code>, -<code>relay_slots_available</code> e <code>relay_bandwidth_used_kbps</code>. Todos os novos campos -usam <code>#[serde(default)]</code> para compatibilidade retroativa — nos antigos ignoram o -que nao reconhecem, nos novos usam defaults. 9 novos testes de roundtrip de -serializacao.</p> -<p><strong>Trait NatHandler e dispatch</strong> (<code>tesseras-dht/src/engine.rs</code>) — Uma nova trait -async <code>NatHandler</code> (5 metodos) injetada no engine DHT, seguindo o mesmo padrao -de injecao de dependencia do <code>ReplicationHandler</code> existente. O loop de dispatch -de mensagens do engine agora roteia todas as mensagens punch/relay para o -handler. Isso mantem o engine DHT agnóstico ao protocolo enquanto permite que a -logica de travessia de NAT viva em <code>tesseras-net</code>.</p> -<p><strong>Tipos de reconexao mobile</strong> (<code>tesseras-embedded/src/reconnect.rs</code>) — Uma -maquina de estados de reconexao em tres fases para dispositivos moveis:</p> -<ol> -<li><strong>QuicMigration</strong> (0-2s) — tenta migracao de conexao QUIC para todos os peers -ativos</li> -<li><strong>ReStun</strong> (2-5s) — redescobre endereco externo via STUN</li> -<li><strong>ReEstablish</strong> (5-10s) — reconecta peers que a migracao nao conseguiu salvar</li> -</ol> -<p>Peers sao reconectados em ordem de prioridade: nos bootstrap primeiro, depois -nos que guardam nossos fragmentos, depois nos cujos fragmentos guardamos, depois -vizinhos DHT gerais. Uma nova variante de evento <code>NetworkChanged</code> foi adicionada -ao stream de eventos FFI para que o app Flutter possa mostrar progresso de -reconexao.</p> -<p><strong>Configuracao NAT do daemon</strong> (<code>tesd/src/config.rs</code>) — Uma nova secao <code>[nat]</code> -na configuracao TOML com lista de servidores STUN, toggle de relay, maximo de -sessoes relay, limites de largura de banda (reciproco vs bootstrap) e timeout de -inatividade. Todos os campos tem defaults sensiveis; relay e desabilitado por -padrao.</p> -<p><strong>Metricas Prometheus</strong> (<code>tesseras-net/src/metrics.rs</code>) — 16 metricas em quatro -subsistemas:</p> -<ul> -<li><strong>STUN</strong>: requisicoes, falhas, histograma de latencia</li> -<li><strong>Punch</strong>: tentativas/sucessos/falhas (por par de tipo NAT), histograma de -latencia</li> -<li><strong>Relay</strong>: sessoes ativas, sessoes totais, bytes encaminhados, timeouts por -inatividade, hits de rate limit</li> -<li><strong>Reconexao</strong>: mudancas de rede, tentativas/sucessos por fase, histograma de -duracao</li> -</ul> -<p>6 testes verificando registro, incremento, cardinalidade de labels e deteccao de -registro duplo.</p> -<p><strong>Testes de integracao</strong> — Dois testes end-to-end usando <code>MemTransport</code> (rede -simulada em memoria):</p> -<ul> -<li><code>punch_integration.rs</code> — Fluxo completo de hole-punch com 3 nos: A envia -<code>PunchIntro</code> assinado ao introdutor I, I verifica e encaminha <code>PunchRequest</code> a -B, B verifica a assinatura original e envia <code>PunchReady</code> de volta, A e B -trocam mensagens diretamente. Tambem testa que uma assinatura invalida e -corretamente rejeitada.</li> -<li><code>relay_integration.rs</code> — Fluxo completo de relay com 3 nos: A solicita relay -de R, R cria sessao e envia <code>RelayOffer</code> a ambos os peers, A e B trocam -pacotes prefixados com token atraves de R, A migra para um novo endereco no -meio da sessao, A fecha a sessao, e o teste verifica que a sessao e encerrada -e encaminhamento posterior falha.</li> -</ul> -<p><strong>Testes de propriedade</strong> — 7 testes baseados em proptest cobrindo: roundtrips -de assinatura para todos os tres tipos de mensagem assinada (IDs de no, portas e -tokens arbitrarios), determinismo de classificacao NAT (mesmas entradas sempre -produzem mesma saida), validade de binding request STUN, unicidade de tokens de -sessao, e rejeicao de pacotes curtos pelo relay.</p> -<p><strong>Alvos Justfile</strong> — <code>just test-nat</code> executa todos os testes de travessia NAT em -<code>tesseras-net</code> e <code>tesseras-dht</code>. <code>just test-chaos</code> e um placeholder para futuros -testes de caos com Docker Compose e <code>tc netem</code>.</p> -<h2 id="decisoes-de-arquitetura">Decisoes de arquitetura</h2> -<ul> -<li><strong>STUN ao inves de TURN</strong>: implementamos STUN (descoberta) e relay customizado -ao inves de TURN completo. TURN requer alocacao autenticada e foi projetado -para relay de midia; nosso relay e mais simples — encaminhamento UDP com -prefixo de token e limites de taxa. Isso mantem o protocolo minimo e evita -depender de servidores TURN externos.</li> -<li><strong>Assinaturas em introducoes</strong>: cada <code>PunchIntro</code> e assinado pelo iniciador. -Sem isso, um atacante poderia enviar introducoes forjadas para redirecionar as -tentativas de hole-punch de um no para um endereco controlado pelo atacante -(ataque de reflexao). A janela de timestamp de 30 segundos limita replay.</li> -<li><strong>Tiers reciprocos de largura de banda</strong>: nos relay dao 4x mais largura de -banda (256 vs 64 KB/s) para peers com boas pontuacoes de reciprocidade. Isso -incentiva nos a armazenar fragmentos para outros — se voce contribui, recebe -melhor servico de relay quando precisa.</li> -<li><strong>Extensao Pong retrocompativel</strong>: novos campos NAT em <code>Pong</code> usam -<code>#[serde(default)]</code> e <code>Option&lt;T&gt;</code>. Nos antigos que nao entendem esses campos -simplesmente os pulam durante deserializacao. Nenhum bump de versao de -protocolo necessario.</li> -<li><strong>NatHandler como trait async</strong>: a logica de travessia NAT e injetada no -engine DHT via trait, assim como <code>ReplicationHandler</code>. Isso mantem o engine -DHT focado em roteamento e gerenciamento de peers, e permite que a -implementacao NAT seja trocada ou desabilitada sem tocar no codigo core do -DHT.</li> -</ul> -<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2> -<ul> -<li><strong>Fase 4 continuacao</strong> — tuning de performance (pooling de conexoes, cache de -fragmentos, SQLite WAL), auditorias de seguranca, onboarding de nos -institucionais, empacotamento para OS</li> -<li><strong>Fase 5: Exploracao e Cultura</strong> — navegador publico de tesseras por -era/localizacao/tema/idioma, curadoria institucional, integracao genealogica, -exportacao para midia fisica (M-DISC, microfilme, papel livre de acido com QR)</li> -</ul> -<p>Com travessia de NAT, Tesseras pode conectar nos independentemente de sua -topologia de rede. Nos publicos conversam diretamente. Nos com NAT Cone furam -com ajuda de um introdutor. Nos com NAT Symmetric ou firewalled usam relay -atraves de peers voluntarios. A rede se adapta ao mundo real, onde a maioria dos -dispositivos esta atras de um NAT e as condicoes de rede mudam constantemente.</p> -</content> - - </entry> - <entry xml:lang="pt-br"> - <title>CLI Encontra a Rede: Comandos Publish, Fetch e Status</title> - <published>2026-02-15T00:00:00+00:00</published> - <updated>2026-02-15T00:00:00+00:00</updated> - - <author> - <name> - - Unknown - - </name> - </author> - - <link rel="alternate" type="text/html" href="https://tesseras.net/pt-br/news/cli-daemon-rpc/"/> - <id>https://tesseras.net/pt-br/news/cli-daemon-rpc/</id> - - <content type="html" xml:base="https://tesseras.net/pt-br/news/cli-daemon-rpc/"><p>Até agora o CLI operava isoladamente: criar uma tessera, verificar, exportar, -listar o que você tem. Tudo ficava na sua máquina. Com esta atualização, o <code>tes</code> -ganha três comandos que fazem a ponte entre o armazenamento local e a rede P2P — -<code>publish</code>, <code>fetch</code> e <code>status</code> — comunicando-se com um <code>tesd</code> em execução através -de um socket Unix.</p> -<h2 id="o-que-foi-construido">O que foi construído</h2> -<p><strong>Crate <code>tesseras-rpc</code></strong> — Um novo crate compartilhado entre CLI e daemon. -Define o protocolo RPC usando serialização MessagePack com enquadramento -prefixado por tamanho (cabeçalho big-endian de 4 bytes, máximo de 64 MiB). Três -tipos de requisição (<code>Publish</code>, <code>Fetch</code>, <code>Status</code>) e suas respostas -correspondentes. Um <code>DaemonClient</code> síncrono gerencia a conexão do socket Unix -com timeouts configuráveis. O protocolo é deliberadamente simples — uma -requisição, uma resposta, conexão fechada — para manter a implementação -auditável.</p> -<p><strong><code>tes publish &lt;hash&gt;</code></strong> — Publica uma tessera na rede. Aceita hashes completos -ou prefixos curtos (ex.: <code>tes publish a1b2</code>), que são resolvidos no banco de -dados local. O daemon lê todos os arquivos da tessera do armazenamento, empacota -em um único buffer MessagePack e entrega ao motor de replicação. Tesseras -pequenas (&lt; 4 MB) são replicadas como um único fragmento; maiores passam por -codificação de apagamento Reed-Solomon. A saída mostra o hash curto e a contagem -de fragmentos:</p> -<pre><code>Published tessera 9f2c4a1b (24 fragments created) -Distribution in progress — use `tes status 9f2c4a1b` to track. -</code></pre> -<p><strong><code>tes fetch &lt;hash&gt;</code></strong> — Busca uma tessera da rede usando o hash de conteúdo -completo. O daemon coleta fragmentos disponíveis localmente, reconstrói os dados -originais via decodificação de apagamento se necessário, desempacota os arquivos -e armazena no CAS (content-addressable store). Retorna o número de memórias e o -tamanho total buscado.</p> -<p><strong><code>tes status &lt;hash&gt;</code></strong> — Exibe a saúde de replicação de uma tessera. A saída -mapeia diretamente o modelo interno de saúde do motor de replicação:</p> -<table><thead><tr><th>Estado</th><th>Significado</th></tr></thead><tbody> -<tr><td>Local</td><td>Ainda não publicada — existe apenas na sua máquina</td></tr> -<tr><td>Publishing</td><td>Fragmentos sendo distribuídos, redundância crítica</td></tr> -<tr><td>Replicated</td><td>Distribuída, mas abaixo da redundância alvo</td></tr> -<tr><td>Healthy</td><td>Redundância completa alcançada</td></tr> -</tbody></table> -<p><strong>Listener RPC no daemon</strong> — O daemon agora escuta em um socket Unix (padrão: -<code>$XDG_RUNTIME_DIR/tesseras/daemon.sock</code>) com permissões de diretório adequadas -(0700), limpeza de sockets obsoletos e shutdown gracioso. Cada conexão é tratada -em uma task Tokio — o listener converte o stream assíncrono para I/O síncrono -para a camada de enquadramento, despacha para o handler RPC e escreve a resposta -de volta.</p> -<p><strong>Pack/unpack no <code>tesseras-core</code></strong> — Um módulo pequeno que serializa uma lista -de entradas de arquivo (caminho + dados) em um único buffer MessagePack e -vice-versa. Esta é a ponte entre a estrutura de diretórios da tessera e os blobs -opacos do motor de replicação.</p> -<h2 id="decisoes-de-arquitetura">Decisões de arquitetura</h2> -<ul> -<li><strong>Socket Unix ao invés de TCP</strong>: a comunicação RPC entre CLI e daemon acontece -na mesma máquina. Sockets Unix são mais rápidos, não precisam de alocação de -porta, e as permissões do sistema de arquivos fornecem controle de acesso sem -TLS.</li> -<li><strong>MessagePack ao invés de JSON</strong>: o mesmo formato wire usado em todo o -Tesseras. Compacto, sem schema, e já é uma dependência do workspace. Uma -ida-e-volta típica de publish request/response ocupa menos de 200 bytes.</li> -<li><strong>Cliente síncrono, daemon assíncrono</strong>: o <code>DaemonClient</code> usa I/O bloqueante -porque o CLI não precisa de concorrência — envia uma requisição e espera. O -listener do daemon é assíncrono (Tokio) para tratar múltiplas conexões. A -camada de enquadramento funciona com qualquer impl <code>Read</code>/<code>Write</code>, conectando -ambos os mundos.</li> -<li><strong>Resolução de prefixo no lado do cliente</strong>: <code>publish</code> e <code>status</code> resolvem -prefixos curtos localmente antes de enviar o hash completo ao daemon. Isso -mantém o daemon stateless — ele não precisa acessar o banco de dados do CLI.</li> -<li><strong>Alinhamento do diretório de dados padrão</strong>: o padrão do CLI mudou de -<code>~/.tesseras</code> para <code>~/.local/share/tesseras</code> (via <code>dirs::data_dir()</code>) para -coincidir com o daemon. Um aviso de migração é exibido quando dados no caminho -antigo são detectados.</li> -</ul> -<h2 id="proximos-passos">Próximos passos</h2> -<ul> -<li><strong>Contagem de peers no DHT</strong>: o comando <code>status</code> atualmente reporta 0 peers — -conectar a contagem real do DHT é o próximo passo</li> -<li><strong><code>tes show</code></strong>: exibir o conteúdo de uma tessera (memórias, metadados) sem -exportar</li> -<li><strong>Fetch com streaming</strong>: para tesseras grandes, transmitir fragmentos conforme -chegam ao invés de esperar por todos</li> -</ul> -</content> - - </entry> - <entry xml:lang="pt-br"> - <title>Fase 4: Recuperação de Chaves por Herdeiros com Shamir's Secret Sharing</title> - <published>2026-02-15T00:00:00+00:00</published> - <updated>2026-02-15T00:00:00+00:00</updated> - - <author> - <name> - - Unknown - - </name> - </author> - - <link rel="alternate" type="text/html" href="https://tesseras.net/pt-br/news/phase4-shamir-heir-recovery/"/> - <id>https://tesseras.net/pt-br/news/phase4-shamir-heir-recovery/</id> - - <content type="html" xml:base="https://tesseras.net/pt-br/news/phase4-shamir-heir-recovery/"><p>O que acontece com suas memórias quando você morre? Até agora, Tesseras -conseguia preservar conteúdo ao longo de milênios — mas as chaves privadas e -seladas morriam com o dono. A Fase 4 continua com uma solução: Shamir's Secret -Sharing, um esquema criptográfico que permite dividir sua identidade em -fragmentos e distribuí-los para as pessoas em quem você mais confia.</p> -<p>A matemática é elegante: você escolhe um limiar T e um total N. Qualquer T -fragmentos reconstroem o segredo completo; T-1 fragmentos não revelam -absolutamente nada. Isso não é "quase nada" — é informação-teoricamente seguro. -Um atacante com um fragmento a menos que o limiar tem exatamente zero bits de -informação sobre o segredo, independentemente do poder computacional que tenha.</p> -<h2 id="o-que-foi-construido">O que foi construído</h2> -<p><strong>Aritmética de corpo finito GF(256)</strong> (<code>tesseras-crypto/src/shamir/gf256.rs</code>) — -Shamir's Secret Sharing requer aritmética em um corpo finito. Implementamos -GF(256) usando o mesmo polinômio irredutível do AES (x^8 + x^4 + x^3 + x + 1), -com tabelas de lookup para logaritmo e exponenciação computadas em tempo de -compilação. Todas as operações são em tempo constante via consulta a tabelas — -sem ramificações baseadas em dados secretos. O módulo inclui o método de Horner -para avaliação de polinômios e interpolação de Lagrange em x=0 para recuperação -do segredo. 233 linhas, exaustivamente testado: todos os 256 elementos para -propriedades de identidade/inverso, comutatividade e associatividade.</p> -<p><strong>ShamirSplitter</strong> (<code>tesseras-crypto/src/shamir/mod.rs</code>) — A API principal de -split/reconstruct. <code>split()</code> recebe uma fatia de bytes do segredo, uma -configuração (limiar T, total N) e a chave pública Ed25519 do dono. Para cada -byte do segredo, constrói um polinômio aleatório de grau T-1 sobre GF(256) com o -byte do segredo como termo constante, e então o avalia em N pontos distintos. -<code>reconstruct()</code> recebe T ou mais fragmentos e recupera o segredo via -interpolação de Lagrange. Ambas as operações incluem validação extensiva: -limites do limiar, consistência de sessão, correspondência de impressão digital -do dono e verificação de checksum BLAKE3.</p> -<p><strong>Formato HeirShare</strong> — Cada fragmento é um artefato autocontido e serializável -com:</p> -<ul> -<li>Versão do formato (v1) para compatibilidade futura</li> -<li>Índice do fragmento (1..N) e metadados de limiar/total</li> -<li>ID de sessão (8 bytes aleatórios) — impede mistura de fragmentos de sessões -diferentes</li> -<li>Impressão digital do dono (primeiros 8 bytes do hash BLAKE3 da chave pública -Ed25519)</li> -<li>Dados do fragmento (os y-values de Shamir, mesmo comprimento do segredo)</li> -<li>Checksum BLAKE3 sobre todos os campos anteriores</li> -</ul> -<p>Os fragmentos são serializados em dois formatos: <strong>MessagePack</strong> (binário -compacto, para uso programático) e <strong>texto base64</strong> (legível por humanos, para -impressão e armazenamento físico). O formato texto inclui um cabeçalho com -metadados e delimitadores:</p> -<pre><code>--- TESSERAS HEIR SHARE --- -Format: v1 -Owner: a1b2c3d4e5f6a7b8 (fingerprint) -Share: 1 of 3 (threshold: 2) -Session: 9f8e7d6c5b4a3210 -Created: 2026-02-15 - -&lt;dados MessagePack codificados em base64&gt; ---- END HEIR SHARE --- -</code></pre> -<p>Este formato é projetado para ser impresso em papel, armazenado em um cofre -bancário ou gravado em metal. O cabeçalho é informacional — apenas o payload -base64 é analisado durante a reconstrução.</p> -<p><strong>Integração com CLI</strong> (<code>tesseras-cli/src/commands/heir.rs</code>) — Três novos -subcomandos:</p> -<ul> -<li><code>tes heir create</code> — divide sua identidade Ed25519 em fragmentos de herdeiros. -Solicita confirmação (sua identidade completa está em jogo), gera arquivos -<code>.bin</code> e <code>.txt</code> para cada fragmento e escreve <code>heir_meta.json</code> no diretório de -identidade.</li> -<li><code>tes heir reconstruct</code> — carrega arquivos de fragmentos (detecta -automaticamente formato binário vs texto), valida consistência, reconstrói o -segredo, deriva o par de chaves Ed25519 e opcionalmente o instala em -<code>~/.tesseras/identity/</code> (com backup automático da identidade existente).</li> -<li><code>tes heir info</code> — exibe metadados do fragmento e verifica o checksum sem expor -nenhum material secreto.</li> -</ul> -<p><strong>Formato do blob secreto</strong> — As chaves de identidade são serializadas em um -blob versionado antes da divisão: um byte de versão (0x01), um byte de flags -(0x00 para somente Ed25519), seguido da chave secreta Ed25519 de 32 bytes. Isso -deixa espaço para expansão futura quando as chaves privadas X25519 e ML-KEM-768 -forem integradas ao sistema de fragmentos de herdeiros.</p> -<p><strong>Testes</strong> — 20 testes unitários para ShamirSplitter (roundtrip, todas as -combinações de fragmentos, fragmentos insuficientes, dono errado, sessão errada, -limite threshold-1, segredos grandes até o tamanho de chave ML-KEM-768). 7 -testes unitários para aritmética GF(256) (propriedades de campo exaustivas). 3 -testes baseados em propriedades com proptest (segredos arbitrários até 5000 -bytes, configurações T-de-N arbitrárias, verificação de segurança -informação-teórica). Testes de roundtrip de serialização para ambos os formatos -MessagePack e texto base64. 2 testes de integração cobrindo o ciclo de vida -completo de herdeiros: gerar identidade, dividir em fragmentos, serializar, -desserializar, reconstruir, verificar par de chaves e assinar/verificar com -chaves reconstruídas.</p> -<h2 id="decisoes-de-arquitetura">Decisões de arquitetura</h2> -<ul> -<li><strong>GF(256) ao invés de GF(primo)</strong>: usamos GF(256) ao invés de um corpo primo -porque ele mapeia naturalmente para bytes — cada elemento é um único byte, -cada fragmento tem o mesmo comprimento do segredo. Sem aritmética de inteiros -grandes, sem redução modular, sem padding. Esta é a mesma abordagem usada pela -maioria das implementações reais de Shamir, incluindo SSSS e Hashicorp Vault.</li> -<li><strong>Tabelas de lookup em tempo de compilação</strong>: as tabelas LOG e EXP para -GF(256) são computadas em tempo de compilação usando <code>const fn</code>. Isso -significa zero custo de inicialização em tempo de execução e operações em -tempo constante via consulta a tabelas ao invés de loops.</li> -<li><strong>ID de sessão previne mistura entre sessões</strong>: cada chamada a <code>split()</code> gera -um novo ID de sessão aleatório. Se um herdeiro acidentalmente usar fragmentos -de duas sessões diferentes de divisão (por exemplo, antes e depois de uma -rotação de chaves), a reconstrução falha de forma limpa com um erro de -validação ao invés de produzir dados corrompidos.</li> -<li><strong>Checksums BLAKE3 detectam corrupção</strong>: cada fragmento inclui um checksum -BLAKE3 sobre seu conteúdo. Isso captura degradação de bits, erros de -transmissão e truncamento acidental antes de qualquer tentativa de -reconstrução. Um fragmento impresso em papel e escaneado via OCR vai falhar no -checksum se um único caractere estiver errado.</li> -<li><strong>Impressão digital do dono para identificação</strong>: os fragmentos incluem os -primeiros 8 bytes de BLAKE3(chave pública Ed25519) como impressão digital. -Isso permite aos herdeiros verificar a qual identidade um fragmento pertence -sem revelar a chave pública completa. Durante a reconstrução, a impressão -digital é verificada contra a chave recuperada.</li> -<li><strong>Formato duplo para resiliência</strong>: ambos os formatos binário (MessagePack) e -texto (base64) são gerados porque mídias físicas têm modos de falha diferentes -de armazenamento digital. Um pendrive pode falhar; papel sobrevive. Um QR code -pode ficar ilegível; texto base64 pode ser digitado manualmente.</li> -<li><strong>Versionamento do blob</strong>: o segredo é envolvido em um blob versionado -(versão + flags + material de chave) para que versões futuras possam incluir -chaves adicionais (X25519, ML-KEM-768) sem quebrar compatibilidade com -fragmentos existentes.</li> -</ul> -<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2> -<ul> -<li><strong>Fase 4 continuada: Resiliência e Escala</strong> — NAT traversal avançado -(STUN/TURN), ajuste de performance (pool de conexões, cache de fragmentos, -SQLite WAL), auditorias de segurança, integração de nós institucionais, -empacotamento para sistemas operacionais</li> -<li><strong>Fase 5: Exploração e Cultura</strong> — navegador público de tesseras por -era/localização/tema/idioma, curadoria institucional, integração com -genealogia, exportação para mídia física (M-DISC, microfilme, papel livre de -ácido com QR)</li> -</ul> -<p>Com Shamir's Secret Sharing, Tesseras fecha a última lacuna crítica na -preservação a longo prazo. Suas memórias sobrevivem a falhas de infraestrutura -através de erasure coding. Sua privacidade sobrevive a computadores quânticos -através de criptografia híbrida. E agora, sua identidade sobrevive a você — -passada adiante para as pessoas que você escolheu, exigindo a cooperação delas -para desbloquear o que você deixou para trás.</p> -</content> - - </entry> - <entry xml:lang="pt-br"> - <title>Fase 4: Criptografia e Tesseras Seladas</title> - <published>2026-02-14T16:00:00+00:00</published> - <updated>2026-02-14T16:00:00+00:00</updated> - - <author> - <name> - - Unknown - - </name> - </author> - - <link rel="alternate" type="text/html" href="https://tesseras.net/pt-br/news/phase4-encryption-sealed/"/> - <id>https://tesseras.net/pt-br/news/phase4-encryption-sealed/</id> - - <content type="html" xml:base="https://tesseras.net/pt-br/news/phase4-encryption-sealed/"><p>Algumas memórias não são para todos. Um diário privado, uma carta para ser -aberta em 2050, um segredo de família selado até que os netos tenham idade -suficiente. Até agora, toda tessera na rede era aberta. A Fase 4 muda isso: -Tesseras agora criptografa conteúdo privado e selado com um esquema -criptográfico híbrido projetado para resistir tanto a ataques clássicos quanto -quânticos.</p> -<p>O princípio continua o mesmo — criptografar o mínimo possível. Memórias públicas -precisam de disponibilidade, não de sigilo. Mas quando alguém cria uma tessera -privada ou selada, o conteúdo agora é trancado por criptografia AES-256-GCM com -chaves protegidas por um mecanismo híbrido de encapsulamento de chaves -combinando X25519 e ML-KEM-768. Ambos os algoritmos precisam ser quebrados para -acessar o conteúdo.</p> -<h2 id="o-que-foi-construido">O que foi construído</h2> -<p><strong>Encriptador AES-256-GCM</strong> (<code>tesseras-crypto/src/encryption.rs</code>) — Criptografia -simétrica de conteúdo com nonces aleatórios de 12 bytes e dados autenticados -associados (AAD). O AAD vincula o texto cifrado ao seu contexto: para tesseras -privadas, o hash do conteúdo é incluído; para tesseras seladas, tanto o hash do -conteúdo quanto o timestamp <code>open_after</code> são vinculados no AAD. Isso significa -que mover texto cifrado entre tesseras com datas de abertura diferentes causa -falha na decriptação — você não consegue enganar o sistema para abrir uma -memória selada antecipadamente trocando o texto cifrado para uma tessera com uma -data de selo anterior.</p> -<p><strong>Mecanismo Híbrido de Encapsulamento de Chaves</strong> (<code>tesseras-crypto/src/kem.rs</code>) -— Troca de chaves usando X25519 (Diffie-Hellman clássico em curva elíptica) -combinado com ML-KEM-768 (o KEM pós-quântico baseado em reticulados padronizado -pelo NIST, anteriormente Kyber). Ambos os segredos compartilhados são combinados -via <code>blake3::derive_key</code> com uma string de contexto fixa ("tesseras hybrid kem -v1") para produzir uma única chave de criptografia de conteúdo de 256 bits. Isso -segue a mesma filosofia "dual desde o início" das assinaturas duplas do projeto -(Ed25519 + ML-DSA): se qualquer algoritmo for quebrado no futuro, o outro ainda -protege o conteúdo.</p> -<p><strong>Envelope de Chave Selada</strong> (<code>tesseras-crypto/src/sealed.rs</code>) — Encapsula uma -chave de criptografia de conteúdo usando o KEM híbrido, para que apenas o dono -da tessera possa recuperá-la. O KEM produz uma chave de transporte, que é XORed -com a chave de conteúdo para produzir uma chave encapsulada armazenada junto ao -texto cifrado do KEM. Ao desselar, o dono decapsula o texto cifrado do KEM para -recuperar a chave de transporte, depois faz XOR novamente para recuperar a chave -de conteúdo.</p> -<p><strong>Publicação de Chave</strong> (<code>tesseras-crypto/src/sealed.rs</code>) — Um artefato assinado -independente para publicar a chave de conteúdo de uma tessera selada após a data -<code>open_after</code> ter passado. O dono assina a chave de conteúdo, o hash da tessera e -o timestamp de publicação com suas chaves duais (Ed25519, com placeholder -ML-DSA). O manifesto permanece imutável — a publicação da chave é um documento -separado. Outros nós verificam a assinatura contra a chave pública do dono antes -de usar a chave publicada para decriptar o conteúdo.</p> -<p><strong>EncryptionContext</strong> (<code>tesseras-core/src/enums.rs</code>) — Um tipo de domínio que -representa o contexto AAD para criptografia. Ele vive em tesseras-core e não em -tesseras-crypto porque é um conceito de domínio (não um detalhe de implementação -criptográfica). O método <code>to_aad_bytes()</code> produz serialização determinística: um -byte de tag (0x00 para Private, 0x01 para Sealed), seguido do hash de conteúdo -e, para Sealed, o timestamp <code>open_after</code> como i64 little-endian.</p> -<p><strong>Validação de domínio</strong> (<code>tesseras-core/src/service.rs</code>) — -<code>TesseraService::create()</code> agora rejeita tesseras Sealed e Private que não -fornecem chaves de criptografia. Esta é uma validação no nível de domínio: a -camada de serviço garante que você não pode criar uma memória selada sem a -maquinaria criptográfica para protegê-la. A mensagem de erro é clara: "missing -encryption keys for visibility sealed until 2050-01-01."</p> -<p><strong>Atualizações de tipos do core</strong> — <code>TesseraIdentity</code> agora inclui um campo -opcional <code>encryption_public: Option&lt;HybridEncryptionPublic&gt;</code> contendo tanto as -chaves públicas X25519 quanto ML-KEM-768. <code>KeyAlgorithm</code> ganhou as variantes -<code>X25519</code> e <code>MlKem768</code>. O layout do sistema de arquivos de identidade agora -suporta <code>node.x25519.key</code>/<code>.pub</code> e <code>node.mlkem768.key</code>/<code>.pub</code>.</p> -<p><strong>Testes</strong> — 8 testes unitários para AES-256-GCM (roundtrip, chave errada, texto -cifrado adulterado, AAD errado, falha de decriptação cross-context, nonces -únicos, mais 2 testes baseados em propriedades para payloads arbitrários e -unicidade de nonces). 5 testes unitários para HybridKem (roundtrip, par de -chaves errado, X25519 adulterado, determinismo do KDF, mais 1 teste baseado em -propriedades). 4 testes unitários para SealedKeyEnvelope e KeyPublication. 2 -testes de integração cobrindo o ciclo de vida completo de tesseras seladas e -privadas: gerar chaves, criar chave de conteúdo, criptografar, selar, desselar, -decriptar, publicar chave e verificar — o ciclo completo.</p> -<h2 id="decisoes-de-arquitetura">Decisões de arquitetura</h2> -<ul> -<li><strong>KEM híbrido desde o início</strong>: X25519 + ML-KEM-768 segue a mesma filosofia -das assinaturas duplas. Não sabemos quais suposições criptográficas se -manterão ao longo dos milênios, então combinamos algoritmos clássicos e -pós-quânticos. O custo é ~1,2 KB de material de chave adicional por identidade -— trivial comparado às fotos e vídeos em uma tessera.</li> -<li><strong>BLAKE3 para KDF</strong>: ao invés de adicionar <code>hkdf</code> + <code>sha2</code> como novas -dependências, usamos <code>blake3::derive_key</code> com uma string de contexto fixa. O -modo de derivação de chaves do BLAKE3 é especificamente projetado para este -caso de uso, e o projeto já depende do BLAKE3 para hashing de conteúdo.</li> -<li><strong>Manifestos imutáveis</strong>: quando a data <code>open_after</code> de uma tessera selada -passa, a chave de conteúdo é publicada como um artefato assinado separado -(<code>KeyPublication</code>), não modificando o manifesto. Isso preserva a natureza -append-only e endereçada por conteúdo das tesseras. O manifesto foi assinado -no momento da criação e nunca muda.</li> -<li><strong>Vinculação AAD previne troca de texto cifrado</strong>: o <code>EncryptionContext</code> -vincula tanto o hash de conteúdo quanto (para tesseras seladas) o timestamp -<code>open_after</code> nos dados autenticados do AES-GCM. Um atacante que copie conteúdo -criptografado de uma tessera "selada até 2050" para uma tessera "selada até -2025" vai descobrir que a decriptação falha — o AAD não corresponde mais.</li> -<li><strong>Encapsulamento de chave por XOR</strong>: o envelope de chave selada usa um XOR -simples da chave de conteúdo com a chave de transporte derivada do KEM, ao -invés de uma camada adicional de AES-GCM. Como a chave de transporte é um -valor aleatório fresco do KEM e é usada exatamente uma vez, o XOR é -informação-teoricamente seguro para este caso de uso específico e evita -complexidade desnecessária.</li> -<li><strong>Validação de domínio, não validação de storage</strong>: a verificação de "chaves -de criptografia ausentes" vive em <code>TesseraService::create()</code>, não na camada de -storage. Isso segue o padrão de arquitetura hexagonal: regras de domínio são -aplicadas na fronteira de serviço, não espalhadas pelos adaptadores.</li> -</ul> -<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2> -<ul> -<li><strong>Fase 4 continuada: Resiliência e Escala</strong> — Shamir's Secret Sharing para -distribuição de chaves de herdeiros, NAT traversal avançado (STUN/TURN), -ajuste de performance, auditorias de segurança, empacotamento para sistemas -operacionais</li> -<li><strong>Fase 5: Exploração e Cultura</strong> — Navegador público de tesseras por -era/localização/tema/idioma, curadoria institucional, integração com -genealogia, exportação para mídia física (M-DISC, microfilme, papel livre de -ácido com QR)</li> -</ul> -<p>Tesseras seladas fazem do Tesseras uma verdadeira cápsula do tempo. Um pai agora -pode gravar uma mensagem para o neto que ainda não nasceu, selá-la até 2060 e -saber que o envelope criptográfico vai resistir — mesmo que os computadores -quânticos do futuro tentem abri-lo antes da hora.</p> -</content> - - </entry> - <entry xml:lang="pt-br"> - <title>Fase 3: Memórias nas Suas Mãos</title> - <published>2026-02-14T14:00:00+00:00</published> - <updated>2026-02-14T14:00:00+00:00</updated> - - <author> - <name> - - Unknown - - </name> - </author> - - <link rel="alternate" type="text/html" href="https://tesseras.net/pt-br/news/phase3-api-and-apps/"/> - <id>https://tesseras.net/pt-br/news/phase3-api-and-apps/</id> - - <content type="html" xml:base="https://tesseras.net/pt-br/news/phase3-api-and-apps/"><p>As pessoas agora podem segurar suas memórias nas próprias mãos. A Fase 3 entrega -o que as fases anteriores construíram: um app mobile onde alguém baixa o -Tesseras, cria uma identidade, tira uma foto, e aquela memória entra na rede de -preservação. Sem contas na nuvem, sem assinaturas, sem nenhuma empresa entre -você e suas memórias.</p> -<h2 id="o-que-foi-construido">O que foi construído</h2> -<p><strong>tesseras-embedded</strong> — Um nó P2P completo que roda dentro de um app mobile. A -struct <code>EmbeddedNode</code> é dona de um runtime Tokio, banco SQLite, transporte QUIC, -engine Kademlia DHT, serviço de replicação e serviço de tessera — a mesma stack -do daemon desktop, compilada como biblioteca compartilhada. Um padrão singleton -global (<code>Mutex&lt;Option&lt;EmbeddedNode&gt;&gt;</code>) garante um único nó por ciclo de vida do -app. Ao iniciar, ele abre o banco de dados, executa migrações, carrega ou gera -uma identidade Ed25519 com proof-of-work para o node ID, faz bind QUIC numa -porta efêmera, conecta DHT e replicação, e inicia o loop de reparo. Ao parar, -envia um sinal de shutdown e drena graciosamente.</p> -<p>Onze funções FFI são expostas para Dart via flutter_rust_bridge: ciclo de vida -(<code>node_start</code>, <code>node_stop</code>, <code>node_is_running</code>), identidade (<code>create_identity</code>, -<code>get_identity</code>), memórias (<code>create_memory</code>, <code>get_timeline</code>, <code>get_memory</code>) e -status da rede (<code>get_network_stats</code>, <code>get_replication_status</code>). Todos os tipos -que cruzam a fronteira FFI são structs planas com apenas <code>String</code>, -<code>Option&lt;String&gt;</code>, <code>Vec&lt;String&gt;</code> e primitivos — sem trait objects, sem generics, -sem lifetimes.</p> -<p>Quatro módulos adaptadores fazem a ponte entre as ports do core e as -implementações concretas: <code>Blake3HasherAdapter</code>, -<code>Ed25519SignerAdapter</code>/<code>Ed25519VerifierAdapter</code> para criptografia, -<code>DhtPortAdapter</code> para operações DHT, e <code>ReplicationHandlerAdapter</code> para RPCs de -fragmentos e atestação recebidos.</p> -<p>A feature flag <code>bundled-sqlite</code> compila o SQLite a partir do código-fonte, -necessário para Android e iOS onde a biblioteca do sistema pode não estar -disponível. A configuração do Cargokit passa essa flag automaticamente em builds -de debug e release.</p> -<p><strong>App Flutter</strong> — Uma aplicação Material Design 3 com gerenciamento de estado -Riverpod, direcionada para Android, iOS, Linux, macOS e Windows a partir de uma -única base de código.</p> -<p>O <em>fluxo de onboarding</em> são três telas: uma tela de boas-vindas explicando o -projeto em uma frase ("Preserve suas memórias através dos milênios. Sem nuvem. -Sem empresa."), uma tela de criação de identidade que dispara a geração do par -de chaves Ed25519 em Rust, e uma tela de confirmação mostrando o nome do usuário -e a identidade criptográfica.</p> -<p>A <em>tela de timeline</em> exibe memórias em ordem cronológica reversa com previews de -imagem, texto de contexto e chips para tipo de memória e visibilidade. -Pull-to-refresh recarrega a partir do nó Rust. Um floating action button abre a -<em>tela de criação de memória</em>, que suporta seleção de foto da galeria ou câmera -via <code>image_picker</code>, texto de contexto opcional, dropdowns de tipo de memória e -visibilidade, e tags separadas por vírgula. Criar uma memória chama o FFI Rust -sincronamente, depois retorna à timeline.</p> -<p>A <em>tela de rede</em> mostra dois cards: status do nó (contagem de peers, tamanho da -DHT, estado de bootstrap, uptime) e saúde da replicação (total de fragmentos, -fragmentos saudáveis, fragmentos em reparo, fator de replicação). A <em>tela de -configurações</em> exibe a identidade do usuário — nome, node ID truncado, chave -pública truncada e data de criação.</p> -<p>Três providers Riverpod gerenciam o estado: <code>nodeProvider</code> inicia o nó embarcado -ao abrir o app usando o diretório de documentos e para ao fazer dispose; -<code>identityProvider</code> carrega o perfil existente ou cria um novo; -<code>timelineProvider</code> busca a lista de memórias com paginação.</p> -<p><strong>Testes</strong> — 9 testes unitários Rust em tesseras-embedded cobrindo ciclo de vida -do nó (start/stop sem panic), persistência de identidade entre reinícios, ciclos -de reinício sem corrupção do SQLite, streaming de eventos de rede, recuperação -de estatísticas, criação de memória e recuperação da timeline, e busca de -memória individual por hash. 2 testes Flutter: um teste de integração -verificando inicialização do Rust e startup do app, e um smoke test de widget.</p> -<h2 id="decisoes-de-arquitetura">Decisões de arquitetura</h2> -<ul> -<li><strong>Nó embarcado, não cliente-servidor</strong>: o celular roda a stack P2P completa, -não um thin client conversando com um daemon remoto. Isso significa que -memórias são preservadas mesmo sem internet. Usuários com um Raspberry Pi ou -VPS podem opcionalmente conectar o app ao seu daemon via GraphQL para maior -disponibilidade, mas não é obrigatório.</li> -<li><strong>FFI síncrono</strong>: todas as funções flutter_rust_bridge são marcadas como -<code>#[frb(sync)]</code> e bloqueiam no runtime Tokio interno. Isso simplifica o lado -Dart (sem complexidade de bridge assíncrono) enquanto o lado Rust lida com -concorrência internamente. A UI thread do Flutter permanece responsiva porque -o Riverpod envolve as chamadas em providers assíncronos.</li> -<li><strong>Singleton global</strong>: um global <code>Mutex&lt;Option&lt;EmbeddedNode&gt;&gt;</code> garante que o -ciclo de vida do nó seja previsível — um start, um stop, sem race conditions. -Plataformas mobile matam processos agressivamente, então simplicidade no -gerenciamento de ciclo de vida é uma feature.</li> -<li><strong>Tipos FFI planos</strong>: nenhuma abstração Rust vaza pela fronteira FFI. Todo -tipo é uma struct plana com strings e números. Isso torna os bindings Dart -auto-gerados confiáveis e fáceis de debugar.</li> -<li><strong>Onboarding de três telas</strong>: a criação de identidade é o único passo -obrigatório. Sem email, sem senha, sem registro em servidor. O app gera uma -identidade criptográfica localmente e está pronto para uso.</li> -</ul> -<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2> -<ul> -<li><strong>Fase 4: Resiliência e Escala</strong> — NAT traversal avançado (STUN/TURN), -Shamir's Secret Sharing para herdeiros, tesseras seladas com criptografia -temporal, ajuste de performance, auditorias de segurança, empacotamento para -Alpine/Arch/Debian/FreeBSD/OpenBSD</li> -<li><strong>Fase 5: Exploração e Cultura</strong> — Navegador público de tesseras por -era/localização/tema/idioma, curadoria institucional, integração com -genealogia, exportação para mídia física (M-DISC, microfilme, papel livre de -ácido com QR)</li> -</ul> -<p>A infraestrutura está completa. A rede existe, a replicação funciona, e agora -qualquer pessoa com um celular pode participar. O que resta é fortalecer o que -temos e abrir para o mundo.</p> -</content> - - </entry> - <entry xml:lang="pt-br"> - <title>Reed-Solomon: Como o Tesseras Sobrevive à Perda de Dados</title> - <published>2026-02-14T14:00:00+00:00</published> - <updated>2026-02-14T14:00:00+00:00</updated> - - <author> - <name> - - Unknown - - </name> - </author> - - <link rel="alternate" type="text/html" href="https://tesseras.net/pt-br/news/reed-solomon/"/> - <id>https://tesseras.net/pt-br/news/reed-solomon/</id> - - <content type="html" xml:base="https://tesseras.net/pt-br/news/reed-solomon/"><p>Seu disco rígido vai morrer. Seu provedor de nuvem vai pivotar. O array RAID no -seu armário vai sobreviver ao controlador, mas não ao dono. Se uma memória está -armazenada em exatamente um lugar, ela tem exatamente uma forma de se perder -para sempre.</p> -<p>Tesseras é uma rede que mantém memórias humanas vivas através de ajuda mútua. O -mecanismo central de sobrevivência é a <strong>codificação de apagamento -Reed-Solomon</strong> — uma técnica emprestada da comunicação espacial profunda que nos -permite reconstruir dados mesmo quando pedaços desaparecem.</p> -<h2 id="o-que-e-reed-solomon">O que é Reed-Solomon?</h2> -<p>Reed-Solomon é uma família de códigos corretores de erros inventada por Irving -Reed e Gustave Solomon em 1960. O caso de uso original era corrigir erros em -dados transmitidos por canais ruidosos — pense na Voyager enviando fotos de -Júpiter, ou num CD tocando apesar de arranhões.</p> -<p>A ideia-chave: se você adicionar redundância cuidadosamente calculada aos seus -dados <em>antes</em> que algo dê errado, você pode recuperar o original mesmo depois de -perder alguns pedaços.</p> -<p>Eis a intuição. Suponha que você tenha um polinômio de grau 2 — uma parábola. -Você precisa de 3 pontos para defini-lo de forma única. Mas se você avaliá-lo em -5 pontos, pode perder quaisquer 2 desses 5 e ainda reconstruir o polinômio a -partir dos 3 restantes. Reed-Solomon generaliza essa ideia para trabalhar sobre -corpos finitos (corpos de Galois), onde o "polinômio" são seus dados e os -"pontos de avaliação" são seus fragmentos.</p> -<p>Em termos concretos:</p> -<ol> -<li><strong>Divida</strong> seus dados em <em>k</em> shards de dados</li> -<li><strong>Calcule</strong> <em>m</em> shards de paridade a partir dos shards de dados</li> -<li><strong>Distribua</strong> todos os <em>k + m</em> shards em diferentes locais</li> -<li><strong>Reconstrua</strong> os dados originais a partir de quaisquer <em>k</em> dos <em>k + m</em> -shards</li> -</ol> -<p>Você pode perder até <em>m</em> shards — quaisquer <em>m</em>, de dados ou paridade, em -qualquer combinação — e ainda recuperar tudo.</p> -<h2 id="por-que-nao-simplesmente-fazer-copias">Por que não simplesmente fazer cópias?</h2> -<p>A abordagem ingênua para redundância é a replicação: faça 3 cópias, armazene-as -em 3 lugares. Isso dá tolerância a 2 falhas ao custo de 3x o seu armazenamento.</p> -<p>Reed-Solomon é dramaticamente mais eficiente:</p> -<table><thead><tr><th>Estratégia</th><th style="text-align: right">Overhead de armazenamento</th><th style="text-align: right">Falhas toleradas</th></tr></thead><tbody> -<tr><td>Replicação 3x</td><td style="text-align: right">200%</td><td style="text-align: right">2 de 3</td></tr> -<tr><td>Reed-Solomon (16,8)</td><td style="text-align: right">50%</td><td style="text-align: right">8 de 24</td></tr> -<tr><td>Reed-Solomon (48,24)</td><td style="text-align: right">50%</td><td style="text-align: right">24 de 72</td></tr> -</tbody></table> -<p>Com 16 shards de dados e 8 de paridade, você usa 50% de armazenamento extra mas -pode sobreviver à perda de um terço de todos os fragmentos. Para alcançar a -mesma tolerância a falhas só com replicação, você precisaria de 3x o -armazenamento.</p> -<p>Para uma rede que visa preservar memórias ao longo de décadas e séculos, essa -eficiência não é um luxo — é a diferença entre um sistema viável e um que se -afoga no próprio overhead.</p> -<h2 id="como-o-tesseras-usa-reed-solomon">Como o Tesseras usa Reed-Solomon</h2> -<p>Nem todos os dados merecem o mesmo tratamento. Uma memória de texto de 500 bytes -e um vídeo de 100 MB têm necessidades de redundância muito diferentes. O -Tesseras usa uma estratégia de fragmentação em três camadas:</p> -<p><strong>Small (&lt; 4 MB)</strong> — Replicação do arquivo inteiro para 7 pares. Para tesseras -pequenas, o overhead da codificação de apagamento (tempo de codificação, -gerenciamento de fragmentos, lógica de reconstrução) supera seus benefícios. -Cópias simples são mais rápidas e mais simples.</p> -<p><strong>Medium (4–256 MB)</strong> — 16 shards de dados + 8 de paridade = 24 fragmentos no -total. Cada fragmento tem aproximadamente 1/16 do tamanho original. Quaisquer 16 -dos 24 fragmentos reconstroem o original. Distribuídos entre 7 pares.</p> -<p><strong>Large (≥ 256 MB)</strong> — 48 shards de dados + 24 de paridade = 72 fragmentos no -total. Maior contagem de shards significa fragmentos individuais menores (mais -fáceis de transferir e armazenar) e maior tolerância absoluta a falhas. Também -distribuídos entre 7 pares.</p> -<p>A implementação usa o crate <code>reed-solomon-erasure</code> operando sobre GF(2⁸) — o -mesmo corpo de Galois usado em códigos QR e CDs. Cada fragmento carrega um -checksum BLAKE3 para que a corrupção seja detectada imediatamente, não propagada -silenciosamente.</p> -<pre><code>Tessera (álbum de fotos de 120 MB) - ↓ codificar -16 shards de dados (7,5 MB cada) + 8 shards de paridade (7,5 MB cada) - ↓ distribuir -24 fragmentos entre 7 pares (diversidade de sub-rede) - ↓ quaisquer 16 fragmentos -Tessera original recuperada -</code></pre> -<h2 id="os-desafios">Os desafios</h2> -<p>Reed-Solomon resolve o problema matemático da redundância. Os desafios de -engenharia estão em tudo ao redor.</p> -<h3 id="rastreamento-de-fragmentos">Rastreamento de fragmentos</h3> -<p>Cada fragmento precisa ser localizável. O Tesseras usa uma DHT Kademlia para -descoberta de pares e mapeamento de fragmentos para pares. Quando um nó fica -offline, seus fragmentos precisam ser recriados e distribuídos para novos pares. -Isso significa rastrear quais fragmentos existem, onde estão e se ainda estão -intactos — numa rede sem autoridade central.</p> -<h3 id="corrupcao-silenciosa">Corrupção silenciosa</h3> -<p>Um fragmento que retorna dados errados é pior que um ausente — pelo menos um -fragmento ausente é honestamente ausente. O Tesseras aborda isso com -verificações de saúde baseadas em atestação: o loop de reparo periodicamente -pede aos detentores de fragmentos que provem posse retornando checksums BLAKE3. -Se um checksum não bater, o fragmento é tratado como perdido.</p> -<h3 id="falhas-correlacionadas">Falhas correlacionadas</h3> -<p>Se todos os 24 fragmentos de uma tessera caírem em máquinas no mesmo datacenter, -uma única queda de energia os elimina todos. A matemática do Reed-Solomon assume -falhas independentes. O Tesseras impõe <strong>diversidade de sub-rede</strong> durante a -distribuição: no máximo 2 fragmentos por sub-rede /24 IPv4 (ou prefixo /48 -IPv6). Isso espalha fragmentos por diferentes infraestruturas físicas.</p> -<h3 id="velocidade-de-reparo-vs-carga-na-rede">Velocidade de reparo vs. carga na rede</h3> -<p>Quando um par fica offline, o relógio começa a contar. Fragmentos perdidos -precisam ser recriados antes que mais falhas se acumulem. Mas reparo agressivo -inunda a rede. O Tesseras equilibra isso com um loop de reparo configurável -(padrão: a cada 24 horas com 2 horas de jitter) e limites de transferências -simultâneas (padrão: 4 transferências simultâneas). O jitter previne tempestades -de reparo onde cada nó verifica seus fragmentos no mesmo momento.</p> -<h3 id="gerenciamento-de-chaves-a-longo-prazo">Gerenciamento de chaves a longo prazo</h3> -<p>Reed-Solomon protege contra perda de dados, não contra perda de acesso. Se uma -tessera é criptografada (visibilidade privada ou selada), você precisa da chave -de descriptografia para tornar os dados recuperados úteis. O Tesseras separa -essas preocupações: codificação de apagamento cuida da disponibilidade, enquanto -o Compartilhamento de Segredo de Shamir (uma fase futura) cuidará da -distribuição de chaves entre herdeiros. A filosofia de design do projeto — -criptografar o mínimo possível — mantém o problema de gerenciamento de chaves -pequeno.</p> -<h3 id="limitacoes-do-corpo-de-galois">Limitações do corpo de Galois</h3> -<p>O corpo GF(2⁸) limita o número total de shards a 255 (dados + paridade -combinados). Para o Tesseras, isso não é uma restrição prática — mesmo a camada -Large usa apenas 72 shards. Mas significa que arquivos extremamente grandes com -milhares de fragmentos exigiriam um corpo diferente ou um esquema de codificação -em camadas.</p> -<h3 id="compatibilidade-evolutiva-do-codec">Compatibilidade evolutiva do codec</h3> -<p>Uma tessera codificada hoje precisa ser decodificável em 50 anos. Reed-Solomon -sobre GF(2⁸) é um dos algoritmos mais amplamente implementados na computação — -está em todo leitor de CD, em todo scanner de código QR, em toda sonda espacial. -Essa ubiquidade é em si uma estratégia de sobrevivência. O algoritmo não será -esquecido porque metade da infraestrutura do mundo depende dele.</p> -<h2 id="o-quadro-geral">O quadro geral</h2> -<p>Reed-Solomon é uma peça de um quebra-cabeça maior. Ele trabalha em conjunto com:</p> -<ul> -<li><strong>DHT Kademlia</strong> para encontrar pares e rotear fragmentos</li> -<li><strong>Checksums BLAKE3</strong> para verificação de integridade</li> -<li><strong>Reciprocidade bilateral</strong> para troca justa de armazenamento (sem blockchain)</li> -<li><strong>Diversidade de sub-rede</strong> para independência de falhas</li> -<li><strong>Reparo automático</strong> para manter a redundância ao longo do tempo</li> -</ul> -<p>Nenhuma técnica isolada faz memórias sobreviverem. Reed-Solomon garante que -dados <em>podem</em> ser recuperados. A DHT garante que fragmentos <em>podem ser -encontrados</em>. A reciprocidade garante que pares <em>querem ajudar</em>. O reparo -garante que nada disso se degrade com o tempo.</p> -<p>Uma tessera é uma aposta de que a soma desses mecanismos, rodando em muitas -máquinas independentes operadas por muitas pessoas independentes, é mais durável -que qualquer instituição isolada. Reed-Solomon é a fundação matemática dessa -aposta.</p> -</content> - - </entry> - <entry xml:lang="pt-br"> - <title>Fase 2: Memórias Sobrevivem</title> - <published>2026-02-14T12:00:00+00:00</published> - <updated>2026-02-14T12:00:00+00:00</updated> - - <author> - <name> - - Unknown - - </name> - </author> - - <link rel="alternate" type="text/html" href="https://tesseras.net/pt-br/news/phase2-replication/"/> - <id>https://tesseras.net/pt-br/news/phase2-replication/</id> - - <content type="html" xml:base="https://tesseras.net/pt-br/news/phase2-replication/"><p>Uma tessera não está mais presa a uma única máquina. A Fase 2 entrega a camada -de replicação: os dados são divididos em fragmentos com codificação de -apagamento, distribuídos entre múltiplos pares e reparados automaticamente -quando nós ficam offline. Um livro-razão de reciprocidade bilateral garante -troca justa de armazenamento — sem blockchain, sem tokens.</p> -<h2 id="o-que-foi-construido">O que foi construído</h2> -<p><strong>tesseras-core</strong> (atualizado) — Novos tipos de domínio de replicação: -<code>FragmentPlan</code> (seleciona a camada de fragmentação baseada no tamanho da -tessera), <code>FragmentId</code> (hash da tessera + índice + contagem de shards + -checksum), <code>FragmentEnvelope</code> (fragmento com seus metadados para transporte na -rede), <code>FragmentationTier</code> (Small/Medium/Large), <code>Attestation</code> (prova de que um -nó possui um fragmento em um dado momento) e <code>ReplicateAck</code> (confirmação de -recebimento de fragmento). Três novas traits de porta definem os limites -hexagonais: <code>DhtPort</code> (encontrar pares, replicar fragmentos, solicitar -atestações, ping), <code>FragmentStore</code> (armazenar/ler/deletar/listar/verificar -fragmentos) e <code>ReciprocityLedger</code> (registrar trocas de armazenamento, consultar -saldos, encontrar melhores pares). O tamanho máximo de uma tessera é 1 GB.</p> -<p><strong>tesseras-crypto</strong> (atualizado) — O <code>ReedSolomonCoder</code> existente agora alimenta -a codificação de fragmentos. Os dados são divididos em shards, shards de -paridade são computados, e qualquer combinação de shards de dados pode -reconstruir o original — desde que o número de shards ausentes não exceda a -contagem de paridade.</p> -<p><strong>tesseras-storage</strong> (atualizado) — Dois novos adaptadores:</p> -<ul> -<li><code>FsFragmentStore</code> — armazena dados de fragmentos como arquivos em disco -(<code>{raiz}/{hash_tessera}/{indice:03}.shard</code>) com um índice de metadados SQLite -rastreando hash da tessera, índice do shard, contagem de shards, checksum e -tamanho em bytes. A verificação recalcula o hash BLAKE3 e compara com o -checksum armazenado.</li> -<li><code>SqliteReciprocityLedger</code> — contabilidade bilateral de armazenamento em -SQLite. Cada par tem uma linha rastreando bytes armazenados para eles e bytes -que eles armazenam para nós. A coluna <code>balance</code> é uma coluna gerada -(<code>bytes_they_store_for_us - bytes_stored_for_them</code>). UPSERT garante incremento -atômico dos contadores.</li> -</ul> -<p>Nova migração (<code>002_replication.sql</code>) adiciona tabelas para fragmentos, planos -de fragmentação, detentores, mapeamentos detentor-fragmento e saldos de -reciprocidade.</p> -<p><strong>tesseras-dht</strong> (atualizado) — Quatro novas variantes de mensagem: <code>Replicate</code> -(enviar um envelope de fragmento), <code>ReplicateAck</code> (confirmar recebimento), -<code>AttestRequest</code> (pedir a um nó que prove que possui os fragmentos de uma -tessera) e <code>AttestResponse</code> (retornar atestação com checksums e timestamp). O -engine trata essas mensagens em seu loop de despacho.</p> -<p><strong>tesseras-replication</strong> — O novo crate, com cinco módulos:</p> -<ul> -<li> -<p><em>Codificação de fragmentos</em> (<code>fragment.rs</code>): <code>encode_tessera()</code> seleciona a -camada de fragmentação baseada no tamanho e então chama a codificação -Reed-Solomon para as camadas Medium e Large. Três camadas:</p> -<ul> -<li><strong>Small</strong> (&lt; 4 MB): replicação do arquivo inteiro para r=7 pares, sem -codificação de apagamento</li> -<li><strong>Medium</strong> (4–256 MB): 16 shards de dados + 8 de paridade, distribuídos -entre r=7 pares</li> -<li><strong>Large</strong> (≥ 256 MB): 48 shards de dados + 24 de paridade, distribuídos -entre r=7 pares</li> -</ul> -</li> -<li> -<p><em>Distribuição</em> (<code>distributor.rs</code>): filtragem de diversidade de sub-rede limita -pares por sub-rede /24 IPv4 (ou prefixo /48 IPv6) para evitar falhas -correlacionadas. Se todos os seus fragmentos caírem no mesmo rack, uma única -queda de energia os elimina.</p> -</li> -<li> -<p><em>Serviço</em> (<code>service.rs</code>): <code>ReplicationService</code> é o orquestrador. -<code>replicate_tessera()</code> codifica os dados, encontra os pares mais próximos via -DHT, aplica diversidade de sub-rede e distribui fragmentos em round-robin. -<code>receive_fragment()</code> valida o checksum BLAKE3, verifica o saldo de -reciprocidade (rejeita se o déficit do remetente exceder o limite -configurado), armazena o fragmento e atualiza o livro-razão. -<code>handle_attestation_request()</code> lista os fragmentos locais e calcula seus -checksums como prova de posse.</p> -</li> -<li> -<p><em>Reparo</em> (<code>repair.rs</code>): <code>check_tessera_health()</code> solicita atestações dos -detentores conhecidos, recorre ao ping para nós não responsivos, verifica a -integridade local dos fragmentos e retorna uma de três ações: <code>Healthy</code>, -<code>NeedsReplication { deficit }</code> ou <code>CorruptLocal { fragment_index }</code>. O loop de -reparo roda a cada 24 horas (com 2 horas de jitter) via <code>tokio::select!</code> com -integração de desligamento.</p> -</li> -<li> -<p><em>Configuração</em> (<code>config.rs</code>): <code>ReplicationConfig</code> com padrões para intervalo -de reparo (24h), jitter (2h), transferências simultâneas (4), espaço livre -mínimo (1 GB), tolerância de déficit (256 MB) e limite de armazenamento por -par (1 GB).</p> -</li> -</ul> -<p><strong>tesd</strong> (atualizado) — O daemon agora abre um banco de dados SQLite -(<code>db/tesseras.db</code>), executa migrações, cria instâncias de <code>FsFragmentStore</code>, -<code>SqliteReciprocityLedger</code> e <code>FsBlobStore</code>, envolve o engine DHT em um -<code>DhtPortAdapter</code>, constrói um <code>ReplicationService</code> e lança o loop de reparo como -tarefa em segundo plano com desligamento gracioso.</p> -<p><strong>Testes</strong> — 193 testes em todo o workspace:</p> -<ul> -<li>15 testes unitários em tesseras-replication (camadas de codificação de -fragmentos, validação de checksum, diversidade de sub-rede, verificações de -saúde do reparo, fluxos de recebimento/replicação do serviço)</li> -<li>3 testes de integração com armazenamento real (ciclo completo -codificar→distribuir→receber para tessera média, replicação de arquivo inteiro -para tessera pequena, rejeição de fragmento adulterado)</li> -<li>Testes usam SQLite em memória + diretório temporário para fragmentos com mocks -mockall para DHT e BlobStore</li> -<li>Zero avisos do clippy, formatação limpa</li> -</ul> -<h2 id="decisoes-de-arquitetura">Decisões de arquitetura</h2> -<ul> -<li><strong>Fragmentação em três camadas</strong>: arquivos pequenos não precisam de -codificação de apagamento — o overhead não compensa. Arquivos médios e grandes -recebem progressivamente mais shards de paridade. Isso evita desperdiçar -armazenamento em tesseras pequenas enquanto oferece redundância forte para as -grandes.</li> -<li><strong>Distribuição por push do dono</strong>: o dono da tessera codifica os fragmentos e -os envia aos pares, em vez dos pares puxarem. Isso simplifica o protocolo (sem -fase de negociação) e garante que os fragmentos são distribuídos -imediatamente.</li> -<li><strong>Reciprocidade bilateral sem consenso</strong>: cada nó rastreia seu próprio saldo -com cada par localmente. Sem livro-razão global, sem token, sem blockchain. Se -o par A armazena 500 MB para o par B, o par B deveria armazenar -aproximadamente 500 MB para o par A. Free riders perdem redundância -gradualmente — seus fragmentos são despriorizados para reparo, mas nunca -deletados.</li> -<li><strong>Diversidade de sub-rede</strong>: os fragmentos são espalhados por diferentes -sub-redes para sobreviver a falhas correlacionadas. Uma queda de datacenter -não deveria eliminar todas as cópias de uma tessera.</li> -<li><strong>Verificações de saúde por atestação primeiro</strong>: o loop de reparo pede aos -detentores que provem posse (atestação com checksums) antes de declarar uma -tessera degradada. Apenas quando a atestação falha é que ele recorre a um -simples ping. Isso detecta corrupção silenciosa de dados, não apenas partida -de nós.</li> -</ul> -<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2> -<ul> -<li><strong>Fase 3: API e Apps</strong> — App Flutter mobile/desktop via flutter_rust_bridge, -API GraphQL (async-graphql), nó WASM no navegador</li> -<li><strong>Fase 4: Resiliência e Escala</strong> — Assinaturas pós-quânticas ML-DSA, travessia -avançada de NAT, Compartilhamento de Segredo de Shamir para herdeiros, -empacotamento para Alpine/Arch/Debian/FreeBSD/OpenBSD, CI no SourceHut</li> -<li><strong>Fase 5: Exploração e Cultura</strong> — navegador público de tesseras, curadoria -institucional, integração genealógica, exportação para mídia física</li> -</ul> -<p>Os nós conseguem se encontrar e manter vivas as memórias uns dos outros. Em -seguida, damos às pessoas uma forma de segurar suas memórias nas mãos.</p> -</content> - - </entry> - <entry xml:lang="pt-br"> - <title>Fase 1: Nós Se Encontram</title> - <published>2026-02-14T11:00:00+00:00</published> - <updated>2026-02-14T11:00:00+00:00</updated> - - <author> - <name> - - Unknown - - </name> - </author> - - <link rel="alternate" type="text/html" href="https://tesseras.net/pt-br/news/phase1-basic-network/"/> - <id>https://tesseras.net/pt-br/news/phase1-basic-network/</id> - - <content type="html" xml:base="https://tesseras.net/pt-br/news/phase1-basic-network/"><p>Tesseras não é mais uma ferramenta apenas local. A Fase 1 entrega a camada de -rede: nós se descobrem através de uma DHT Kademlia, comunicam-se sobre QUIC e -publicam ponteiros de tesseras que qualquer par na rede pode encontrar. Uma -tessera criada no nó A agora pode ser encontrada a partir do nó C.</p> -<h2 id="o-que-foi-construido">O que foi construído</h2> -<p><strong>tesseras-core</strong> (atualizado) — Novos tipos de domínio de rede: -<code>TesseraPointer</code> (referência leve aos detentores de uma tessera e localização -dos fragmentos), <code>NodeIdentity</code> (ID do nó + chave pública + nonce de prova de -trabalho), <code>NodeInfo</code> (identidade + endereço + capacidades) e <code>Capabilities</code> -(bitflags do que um nó suporta: DHT, armazenamento, relay, replicação).</p> -<p><strong>tesseras-net</strong> — A camada de transporte, construída sobre QUIC via quinn. A -trait <code>Transport</code> define a porta: <code>send</code>, <code>recv</code>, <code>disconnect</code>, <code>local_addr</code>. -Dois adaptadores a implementam:</p> -<ul> -<li><code>QuinnTransport</code> — QUIC real com TLS auto-assinado, negociação ALPN -(<code>tesseras/1</code>), pool de conexões via DashMap e um loop de aceitação em -background que trata streams recebidas.</li> -<li><code>MemTransport</code> + <code>SimNetwork</code> — canais em memória para testes determinísticos -sem I/O de rede. Cada teste de integração no crate DHT roda contra este -adaptador.</li> -</ul> -<p>O protocolo de fio usa MessagePack com prefixo de comprimento: um cabeçalho de 4 -bytes big-endian seguido de um payload rmp-serde. <code>WireMessage</code> carrega um byte -de versão, ID de requisição e um corpo que pode ser requisição, resposta ou erro -de protocolo. Tamanho máximo de mensagem é 64 KiB.</p> -<p><strong>tesseras-dht</strong> — Uma implementação completa de Kademlia:</p> -<ul> -<li><em>Tabela de roteamento</em>: 160 k-buckets com k=20. Evicção do menos recentemente -visto, mover-para-trás ao atualizar, verificação por ping antes de substituir -a entrada mais antiga de um bucket cheio.</li> -<li><em>Distância XOR</em>: métrica XOR de 160 bits com indexação de bucket pelo bit mais -significativo diferente.</li> -<li><em>Prova de trabalho</em>: nós iteram um nonce até que -<code>BLAKE3(pubkey || nonce)[..20]</code> tenha 8 bits zero iniciais (~256 tentativas de -hash em média). Barato o suficiente para qualquer dispositivo, caro o -suficiente para tornar ataques Sybil impraticáveis em escala.</li> -<li><em>Mensagens de protocolo</em>: Ping/Pong, FindNode/FindNodeResponse, -FindValue/FindValueResult, Store — todos serializados com MessagePack via -serde.</li> -<li><em>Armazenamento de ponteiros</em>: armazenamento em memória limitado com TTL -configurável (24 horas padrão) e máximo de entradas (10.000 padrão). Quando -cheio, remove ponteiros mais distantes do ID do nó local, seguindo o modelo de -responsabilidade baseado em distância do Kademlia.</li> -<li><em>DhtEngine</em>: o orquestrador principal. Trata RPCs recebidos, executa buscas -iterativas (paralelismo alpha=3), bootstrap, publicação e busca. O método -<code>run()</code> dirige um loop <code>tokio::select!</code> com timers de manutenção: refresh da -tabela de roteamento a cada 60 segundos, expiração de ponteiros a cada 5 -minutos.</li> -</ul> -<p><strong>tesd</strong> — Um binário de nó completo. Analisa argumentos de CLI (endereço de -bind, pares de bootstrap, diretório de dados), gera uma identidade de nó válida -por PoW, abre um endpoint QUIC, faz bootstrap na rede e roda o motor DHT. -Desligamento gracioso com Ctrl+C via tratamento de sinais do tokio.</p> -<p><strong>Infraestrutura</strong> — Configuração OpenTofu para dois nós bootstrap no Hetzner -Cloud (instâncias cx22 em Falkenstein, Alemanha e Helsinki, Finlândia). Script -de provisionamento cloud-init cria um usuário dedicado <code>tesseras</code>, escreve um -arquivo de configuração e configura um serviço systemd. Regras de firewall abrem -UDP 4433 (QUIC) e restringem métricas a acesso interno.</p> -<p><strong>Testes</strong> — 139 testes em todo o workspace:</p> -<ul> -<li>47 testes unitários em tesseras-dht (tabela de roteamento, distância, PoW, -armazenamento de ponteiros, serialização de mensagens, RPCs do engine)</li> -<li>5 testes de integração multi-nó (bootstrap de 3 nós, convergência de lookup -com 10 nós, publicar-e-encontrar, detecção de partida de nó, rejeição de PoW)</li> -<li>14 testes em tesseras-net (roundtrips de codec, send/recv de transporte, -backpressure, disconnect)</li> -<li>Testes de fumaça com Docker Compose usando 3 nós containerizados comunicando -sobre QUIC real</li> -<li>Zero avisos do clippy, formatação limpa</li> -</ul> -<h2 id="decisoes-de-arquitetura">Decisões de arquitetura</h2> -<ul> -<li><strong>Transport como porta</strong>: a trait <code>Transport</code> é a única interface entre o -motor DHT e a rede. Trocar QUIC por qualquer outro protocolo significa -implementar quatro métodos. Todos os testes de DHT usam o adaptador em -memória, tornando-os rápidos e determinísticos.</li> -<li><strong>Um stream por RPC</strong>: cada par requisição-resposta DHT usa um stream -bidirecional QUIC novo. Sem complexidade de multiplexação, sem bloqueio -head-of-line entre operações independentes. O QUIC trata a multiplexação no -nível da conexão.</li> -<li><strong>MessagePack em vez de Protobuf</strong>: codificação binária compacta sem geração -de código ou arquivos de esquema. Integração com serde significa que adicionar -um campo a uma mensagem é uma mudança de uma linha. Trade-off: sem garantias -de evolução de esquema embutidas, mas neste estágio velocidade importa mais.</li> -<li><strong>PoW em vez de stake ou reputação</strong>: uma identidade de nó custa ~256 hashes -BLAKE3. Isso roda em menos de um segundo em qualquer hardware, incluindo um -Raspberry Pi, mas gerar milhares de identidades para um ataque Sybil se torna -caro. Sem tokens, sem blockchain, sem dependências externas.</li> -<li><strong>Busca iterativa com atualização da tabela de roteamento</strong>: nós descobertos -são adicionados à tabela de roteamento conforme encontrados durante buscas -iterativas, seguindo o comportamento padrão do Kademlia. Isso garante que a -tabela de roteamento melhore organicamente conforme os nós interagem.</li> -</ul> -<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2> -<ul> -<li><strong>Fase 2: Replicação</strong> — Codificação de apagamento Reed-Solomon pela rede, -distribuição de fragmentos, loops de reparo automáticos, livro-razão de -reciprocidade bilateral (sem blockchain, sem tokens)</li> -<li><strong>Fase 3: API e Apps</strong> — App Flutter mobile/desktop via flutter_rust_bridge, -API GraphQL (async-graphql), nó WASM no navegador</li> -<li><strong>Fase 4: Resiliência e Escala</strong> — Assinaturas pós-quânticas ML-DSA, travessia -avançada de NAT, Compartilhamento de Segredo de Shamir para herdeiros, -empacotamento para Alpine/Arch/Debian/FreeBSD/OpenBSD, CI no SourceHut</li> -<li><strong>Fase 5: Exploração e Cultura</strong> — navegador público de tesseras, curadoria -institucional, integração genealógica, exportação para mídia física</li> -</ul> -<p>Os nós conseguem se encontrar. Em seguida, aprendem a manter vivas as memórias -uns dos outros.</p> -</content> - - </entry> - <entry xml:lang="pt-br"> - <title>Fase 0: Fundação Construída</title> - <published>2026-02-14T10:00:00+00:00</published> - <updated>2026-02-14T10:00:00+00:00</updated> - - <author> - <name> - - Unknown - - </name> - </author> - - <link rel="alternate" type="text/html" href="https://tesseras.net/pt-br/news/phase0-foundation/"/> - <id>https://tesseras.net/pt-br/news/phase0-foundation/</id> - - <content type="html" xml:base="https://tesseras.net/pt-br/news/phase0-foundation/"><p>O primeiro marco do projeto Tesseras está completo. A Fase 0 estabelece a -fundação sobre a qual cada componente futuro será construído: tipos de domínio, -criptografia, armazenamento e uma interface de linha de comando funcional.</p> -<h2 id="o-que-foi-construido">O que foi construído</h2> -<p><strong>tesseras-core</strong> — A camada de domínio define o formato tessera: <code>ContentHash</code> -(BLAKE3, 32 bytes), <code>NodeId</code> (Kademlia, 20 bytes), tipos de memória (Moment, -Reflection, Daily, Relation, Object), modos de visibilidade (Private, Circle, -Public, PublicAfterDeath, Sealed) e um formato de manifesto em texto plano que -pode ser interpretado por qualquer linguagem de programação pelos próximos mil -anos. A camada de serviço (<code>TesseraService</code>) gerencia operações de criação, -verificação, exportação e listagem através de port traits, seguindo arquitetura -hexagonal.</p> -<p><strong>tesseras-crypto</strong> — Geração de chaves Ed25519, assinatura e verificação. Um -framework de assinatura dual (Ed25519 + placeholder ML-DSA) pronto para migração -pós-quântica. Hashing de conteúdo com BLAKE3. Codificação de apagamento -Reed-Solomon atrás de uma feature flag para futura replicação.</p> -<p><strong>tesseras-storage</strong> — Índice SQLite via rusqlite com migrações em SQL puro. -Blob store no sistema de arquivos com layout endereçável por conteúdo -(<code>blobs/&lt;tessera_hash&gt;/&lt;memory_hash&gt;/&lt;filename&gt;</code>). Persistência de chaves de -identidade em disco.</p> -<p><strong>tesseras-cli</strong> — Um binário <code>tesseras</code> funcional com cinco comandos:</p> -<ul> -<li><code>init</code> — gera identidade Ed25519, cria banco de dados SQLite</li> -<li><code>create &lt;dir&gt;</code> — varre um diretório por arquivos de mídia, cria uma tessera -assinada</li> -<li><code>verify &lt;hash&gt;</code> — verifica assinatura e integridade dos arquivos</li> -<li><code>export &lt;hash&gt; &lt;dest&gt;</code> — escreve um diretório tessera autocontido</li> -<li><code>list</code> — mostra uma tabela das tesseras armazenadas</li> -</ul> -<p><strong>Testes</strong> — 67+ testes em todo o workspace: testes unitários em cada módulo, -testes baseados em propriedades (proptest) para roundtrips hex e serialização de -manifesto, testes de integração cobrindo o ciclo completo de -criação-verificação-exportação incluindo detecção de arquivos adulterados e -assinaturas inválidas. Zero avisos do clippy.</p> -<h2 id="decisoes-de-arquitetura">Decisões de arquitetura</h2> -<ul> -<li><strong>Arquitetura hexagonal</strong>: operações criptográficas são injetadas via trait -objects (<code>Box&lt;dyn Hasher&gt;</code>, <code>Box&lt;dyn ManifestSigner&gt;</code>, -<code>Box&lt;dyn ManifestVerifier&gt;</code>), mantendo o crate core livre de dependências -criptográficas concretas.</li> -<li><strong>Feature flags</strong>: a feature <code>service</code> no tesseras-core controla a camada de -aplicação assíncrona. As features <code>classical</code> e <code>erasure</code> no tesseras-crypto -controlam quais algoritmos são compilados.</li> -<li><strong>Manifesto em texto plano</strong>: interpretável sem qualquer biblioteca de formato -binário, com prefixos de hash explícitos <code>blake3:</code> e layout legível por -humanos.</li> -</ul> -<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2> -<p>A Fase 0 é a fundação local. O caminho adiante:</p> -<ul> -<li><strong>Fase 1: Rede</strong> — Transporte QUIC (quinn), DHT Kademlia para descoberta de -pares, travessia de NAT</li> -<li><strong>Fase 2: Replicação</strong> — Codificação de apagamento Reed-Solomon pela rede, -loops de reparo, reciprocidade bilateral (sem blockchain, sem tokens)</li> -<li><strong>Fase 3: Clientes</strong> — App Flutter mobile/desktop via flutter_rust_bridge, API -GraphQL, nó WASM no navegador</li> -<li><strong>Fase 4: Endurecimento</strong> — Assinaturas pós-quânticas ML-DSA, empacotamento -para Alpine/Arch/Debian/FreeBSD/OpenBSD, CI no SourceHut</li> -</ul> -<p>O formato tessera é estável. Tudo construído a partir daqui se conecta e estende -o que existe hoje.</p> -</content> - - </entry> - <entry xml:lang="pt-br"> - <title>Olá, Mundo</title> - <published>2026-02-13T00:00:00+00:00</published> - <updated>2026-02-13T00:00:00+00:00</updated> - - <author> - <name> - - Unknown - - </name> - </author> - - <link rel="alternate" type="text/html" href="https://tesseras.net/pt-br/news/hello-world/"/> - <id>https://tesseras.net/pt-br/news/hello-world/</id> - - <content type="html" xml:base="https://tesseras.net/pt-br/news/hello-world/"><p>Hoje anunciamos o projeto Tesseras: uma rede peer-to-peer para preservar -memórias humanas através dos milênios.</p> -<p>Tesseras é construído sobre uma ideia simples — suas fotos, gravações e escritos -merecem sobreviver a qualquer empresa, plataforma ou formato de arquivo. Cada -pessoa cria uma tessera, uma cápsula do tempo autocontida que a rede mantém viva -através de ajuda mútua e redundância.</p> -<p>O projeto está em seu estágio mais inicial. Estamos construindo a fundação: -ferramentas para criar, verificar e exportar tesseras offline. A camada de rede, -replicação e aplicativos virão em seguida.</p> -<p>Se essa missão ressoa com você, -<a href="/pt-br/subscriptions/">entre na lista de discussão</a> ou navegue pelo -<a rel="external" href="https://git.sr.ht/~ijanc/tesseras">código-fonte</a>.</p> -</content> - - </entry> -</feed> diff --git a/pt-br/news/atom.xml.gz b/pt-br/news/atom.xml.gz Binary files differdeleted file mode 100644 index 2870951..0000000 --- a/pt-br/news/atom.xml.gz +++ /dev/null diff --git a/pt-br/news/cli-daemon-rpc/index.html b/pt-br/news/cli-daemon-rpc/index.html deleted file mode 100644 index 3b43961..0000000 --- a/pt-br/news/cli-daemon-rpc/index.html +++ /dev/null @@ -1,147 +0,0 @@ -<!DOCTYPE html> -<html lang="pt-br"> -<head> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <title>CLI Encontra a Rede: Comandos Publish, Fetch e Status — Tesseras</title> - <meta name="description" content="O CLI do tesseras agora pode publicar tesseras na rede, buscá-las de peers e monitorar o estado de replicação — tudo através de uma nova ponte RPC via socket Unix para o daemon."> - <!-- Open Graph --> - <meta property="og:type" content="article"> - <meta property="og:title" content="CLI Encontra a Rede: Comandos Publish, Fetch e Status"> - <meta property="og:description" content="O CLI do tesseras agora pode publicar tesseras na rede, buscá-las de peers e monitorar o estado de replicação — tudo através de uma nova ponte RPC via socket Unix para o daemon."> - <meta property="og:image" content="https://tesseras.net/images/social.jpg"> - <meta property="og:image:width" content="1200"> - <meta property="og:image:height" content="630"> - <meta property="og:site_name" content="Tesseras"> - <!-- Twitter Card --> - <meta name="twitter:card" content="summary_large_image"> - <meta name="twitter:title" content="CLI Encontra a Rede: Comandos Publish, Fetch e Status"> - <meta name="twitter:description" content="O CLI do tesseras agora pode publicar tesseras na rede, buscá-las de peers e monitorar o estado de replicação — tudo através de uma nova ponte RPC via socket Unix para o daemon."> - <meta name="twitter:image" content="https://tesseras.net/images/social.jpg"> - <link rel="stylesheet" href="https://tesseras.net/style.css?h=21f0f32121928ee5c690"> - - - <link rel="alternate" type="application/atom+xml" title="Tesseras" href="https://tesseras.net/atom.xml"> - - - <link rel="icon" type="image/png" sizes="32x32" href="https://tesseras.net/images/favicon.png?h=be4e123a23393b1a027d"> - -</head> -<body> - <header> - <h1> - <a href="https://tesseras.net/pt-br/"> - <img src="https://tesseras.net/images/logo-64.png?h=c1b8d0c4c5f93b49d40b" alt="Tesseras" width="40" height="40" class="logo"> - Tesseras - </a> - </h1> - <nav> - - <a href="https://tesseras.net/pt-br/about/">Sobre</a> - <a href="https://tesseras.net/pt-br/news/">Notícias</a> - <a href="https://tesseras.net/pt-br/releases/">Lançamentos</a> - <a href="https://tesseras.net/pt-br/faq/">FAQ</a> - <a href="https://tesseras.net/pt-br/subscriptions/">Inscrições</a> - <a href="https://tesseras.net/pt-br/contact/">Contato</a> - - </nav> - <nav class="lang-switch"> - - <a href="https://tesseras.net/news/cli-daemon-rpc/">English</a> | <strong>Português</strong> - - </nav> - </header> - - <main> - -<article> - <h2>CLI Encontra a Rede: Comandos Publish, Fetch e Status</h2> - <p class="news-date">2026-02-15</p> - <p>Até agora o CLI operava isoladamente: criar uma tessera, verificar, exportar, -listar o que você tem. Tudo ficava na sua máquina. Com esta atualização, o <code>tes</code> -ganha três comandos que fazem a ponte entre o armazenamento local e a rede P2P — -<code>publish</code>, <code>fetch</code> e <code>status</code> — comunicando-se com um <code>tesd</code> em execução através -de um socket Unix.</p> -<h2 id="o-que-foi-construido">O que foi construído</h2> -<p><strong>Crate <code>tesseras-rpc</code></strong> — Um novo crate compartilhado entre CLI e daemon. -Define o protocolo RPC usando serialização MessagePack com enquadramento -prefixado por tamanho (cabeçalho big-endian de 4 bytes, máximo de 64 MiB). Três -tipos de requisição (<code>Publish</code>, <code>Fetch</code>, <code>Status</code>) e suas respostas -correspondentes. Um <code>DaemonClient</code> síncrono gerencia a conexão do socket Unix -com timeouts configuráveis. O protocolo é deliberadamente simples — uma -requisição, uma resposta, conexão fechada — para manter a implementação -auditável.</p> -<p><strong><code>tes publish <hash></code></strong> — Publica uma tessera na rede. Aceita hashes completos -ou prefixos curtos (ex.: <code>tes publish a1b2</code>), que são resolvidos no banco de -dados local. O daemon lê todos os arquivos da tessera do armazenamento, empacota -em um único buffer MessagePack e entrega ao motor de replicação. Tesseras -pequenas (< 4 MB) são replicadas como um único fragmento; maiores passam por -codificação de apagamento Reed-Solomon. A saída mostra o hash curto e a contagem -de fragmentos:</p> -<pre><code>Published tessera 9f2c4a1b (24 fragments created) -Distribution in progress — use `tes status 9f2c4a1b` to track. -</code></pre> -<p><strong><code>tes fetch <hash></code></strong> — Busca uma tessera da rede usando o hash de conteúdo -completo. O daemon coleta fragmentos disponíveis localmente, reconstrói os dados -originais via decodificação de apagamento se necessário, desempacota os arquivos -e armazena no CAS (content-addressable store). Retorna o número de memórias e o -tamanho total buscado.</p> -<p><strong><code>tes status <hash></code></strong> — Exibe a saúde de replicação de uma tessera. A saída -mapeia diretamente o modelo interno de saúde do motor de replicação:</p> -<table><thead><tr><th>Estado</th><th>Significado</th></tr></thead><tbody> -<tr><td>Local</td><td>Ainda não publicada — existe apenas na sua máquina</td></tr> -<tr><td>Publishing</td><td>Fragmentos sendo distribuídos, redundância crítica</td></tr> -<tr><td>Replicated</td><td>Distribuída, mas abaixo da redundância alvo</td></tr> -<tr><td>Healthy</td><td>Redundância completa alcançada</td></tr> -</tbody></table> -<p><strong>Listener RPC no daemon</strong> — O daemon agora escuta em um socket Unix (padrão: -<code>$XDG_RUNTIME_DIR/tesseras/daemon.sock</code>) com permissões de diretório adequadas -(0700), limpeza de sockets obsoletos e shutdown gracioso. Cada conexão é tratada -em uma task Tokio — o listener converte o stream assíncrono para I/O síncrono -para a camada de enquadramento, despacha para o handler RPC e escreve a resposta -de volta.</p> -<p><strong>Pack/unpack no <code>tesseras-core</code></strong> — Um módulo pequeno que serializa uma lista -de entradas de arquivo (caminho + dados) em um único buffer MessagePack e -vice-versa. Esta é a ponte entre a estrutura de diretórios da tessera e os blobs -opacos do motor de replicação.</p> -<h2 id="decisoes-de-arquitetura">Decisões de arquitetura</h2> -<ul> -<li><strong>Socket Unix ao invés de TCP</strong>: a comunicação RPC entre CLI e daemon acontece -na mesma máquina. Sockets Unix são mais rápidos, não precisam de alocação de -porta, e as permissões do sistema de arquivos fornecem controle de acesso sem -TLS.</li> -<li><strong>MessagePack ao invés de JSON</strong>: o mesmo formato wire usado em todo o -Tesseras. Compacto, sem schema, e já é uma dependência do workspace. Uma -ida-e-volta típica de publish request/response ocupa menos de 200 bytes.</li> -<li><strong>Cliente síncrono, daemon assíncrono</strong>: o <code>DaemonClient</code> usa I/O bloqueante -porque o CLI não precisa de concorrência — envia uma requisição e espera. O -listener do daemon é assíncrono (Tokio) para tratar múltiplas conexões. A -camada de enquadramento funciona com qualquer impl <code>Read</code>/<code>Write</code>, conectando -ambos os mundos.</li> -<li><strong>Resolução de prefixo no lado do cliente</strong>: <code>publish</code> e <code>status</code> resolvem -prefixos curtos localmente antes de enviar o hash completo ao daemon. Isso -mantém o daemon stateless — ele não precisa acessar o banco de dados do CLI.</li> -<li><strong>Alinhamento do diretório de dados padrão</strong>: o padrão do CLI mudou de -<code>~/.tesseras</code> para <code>~/.local/share/tesseras</code> (via <code>dirs::data_dir()</code>) para -coincidir com o daemon. Um aviso de migração é exibido quando dados no caminho -antigo são detectados.</li> -</ul> -<h2 id="proximos-passos">Próximos passos</h2> -<ul> -<li><strong>Contagem de peers no DHT</strong>: o comando <code>status</code> atualmente reporta 0 peers — -conectar a contagem real do DHT é o próximo passo</li> -<li><strong><code>tes show</code></strong>: exibir o conteúdo de uma tessera (memórias, metadados) sem -exportar</li> -<li><strong>Fetch com streaming</strong>: para tesseras grandes, transmitir fragmentos conforme -chegam ao invés de esperar por todos</li> -</ul> - -</article> - - </main> - - <footer> - <p>© 2026 Tesseras Project. <a href="/atom.xml">News Feed</a> · <a href="https://git.sr.ht/~ijanc/tesseras">Source</a></p> - </footer> -</body> -</html> diff --git a/pt-br/news/cli-daemon-rpc/index.html.gz b/pt-br/news/cli-daemon-rpc/index.html.gz Binary files differdeleted file mode 100644 index a3c51bf..0000000 --- a/pt-br/news/cli-daemon-rpc/index.html.gz +++ /dev/null diff --git a/pt-br/news/hello-world/index.html b/pt-br/news/hello-world/index.html deleted file mode 100644 index 5e8fcec..0000000 --- a/pt-br/news/hello-world/index.html +++ /dev/null @@ -1,81 +0,0 @@ -<!DOCTYPE html> -<html lang="pt-br"> -<head> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <title>Olá, Mundo — Tesseras</title> - <meta name="description" content="Apresentando o projeto Tesseras — uma rede P2P para preservar memórias humanas."> - <!-- Open Graph --> - <meta property="og:type" content="article"> - <meta property="og:title" content="Olá, Mundo"> - <meta property="og:description" content="Apresentando o projeto Tesseras — uma rede P2P para preservar memórias humanas."> - <meta property="og:image" content="https://tesseras.net/images/social.jpg"> - <meta property="og:image:width" content="1200"> - <meta property="og:image:height" content="630"> - <meta property="og:site_name" content="Tesseras"> - <!-- Twitter Card --> - <meta name="twitter:card" content="summary_large_image"> - <meta name="twitter:title" content="Olá, Mundo"> - <meta name="twitter:description" content="Apresentando o projeto Tesseras — uma rede P2P para preservar memórias humanas."> - <meta name="twitter:image" content="https://tesseras.net/images/social.jpg"> - <link rel="stylesheet" href="https://tesseras.net/style.css?h=21f0f32121928ee5c690"> - - - <link rel="alternate" type="application/atom+xml" title="Tesseras" href="https://tesseras.net/atom.xml"> - - - <link rel="icon" type="image/png" sizes="32x32" href="https://tesseras.net/images/favicon.png?h=be4e123a23393b1a027d"> - -</head> -<body> - <header> - <h1> - <a href="https://tesseras.net/pt-br/"> - <img src="https://tesseras.net/images/logo-64.png?h=c1b8d0c4c5f93b49d40b" alt="Tesseras" width="40" height="40" class="logo"> - Tesseras - </a> - </h1> - <nav> - - <a href="https://tesseras.net/pt-br/about/">Sobre</a> - <a href="https://tesseras.net/pt-br/news/">Notícias</a> - <a href="https://tesseras.net/pt-br/releases/">Lançamentos</a> - <a href="https://tesseras.net/pt-br/faq/">FAQ</a> - <a href="https://tesseras.net/pt-br/subscriptions/">Inscrições</a> - <a href="https://tesseras.net/pt-br/contact/">Contato</a> - - </nav> - <nav class="lang-switch"> - - <a href="https://tesseras.net/news/hello-world/">English</a> | <strong>Português</strong> - - </nav> - </header> - - <main> - -<article> - <h2>Olá, Mundo</h2> - <p class="news-date">2026-02-13</p> - <p>Hoje anunciamos o projeto Tesseras: uma rede peer-to-peer para preservar -memórias humanas através dos milênios.</p> -<p>Tesseras é construído sobre uma ideia simples — suas fotos, gravações e escritos -merecem sobreviver a qualquer empresa, plataforma ou formato de arquivo. Cada -pessoa cria uma tessera, uma cápsula do tempo autocontida que a rede mantém viva -através de ajuda mútua e redundância.</p> -<p>O projeto está em seu estágio mais inicial. Estamos construindo a fundação: -ferramentas para criar, verificar e exportar tesseras offline. A camada de rede, -replicação e aplicativos virão em seguida.</p> -<p>Se essa missão ressoa com você, -<a href="/pt-br/subscriptions/">entre na lista de discussão</a> ou navegue pelo -<a rel="external" href="https://git.sr.ht/~ijanc/tesseras">código-fonte</a>.</p> - -</article> - - </main> - - <footer> - <p>© 2026 Tesseras Project. <a href="/atom.xml">News Feed</a> · <a href="https://git.sr.ht/~ijanc/tesseras">Source</a></p> - </footer> -</body> -</html> diff --git a/pt-br/news/hello-world/index.html.gz b/pt-br/news/hello-world/index.html.gz Binary files differdeleted file mode 100644 index e4322b4..0000000 --- a/pt-br/news/hello-world/index.html.gz +++ /dev/null diff --git a/pt-br/news/index.html b/pt-br/news/index.html deleted file mode 100644 index 155b8fa..0000000 --- a/pt-br/news/index.html +++ /dev/null @@ -1,198 +0,0 @@ -<!DOCTYPE html> -<html lang="pt-br"> -<head> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <title>Notícias — Tesseras</title> - <meta name="description" content="Notícias e anúncios do projeto Tesseras"> - <!-- Open Graph --> - <meta property="og:type" content="website"> - <meta property="og:title" content="Tesseras"> - <meta property="og:description" content="Rede P2P para preservar memórias humanas através dos milênios"> - <meta property="og:image" content="https://tesseras.net/images/social.jpg"> - <meta property="og:image:width" content="1200"> - <meta property="og:image:height" content="630"> - <meta property="og:site_name" content="Tesseras"> - <!-- Twitter Card --> - <meta name="twitter:card" content="summary_large_image"> - <meta name="twitter:title" content="Tesseras"> - <meta name="twitter:description" content="Rede P2P para preservar memórias humanas através dos milênios"> - <meta name="twitter:image" content="https://tesseras.net/images/social.jpg"> - <link rel="stylesheet" href="https://tesseras.net/style.css?h=21f0f32121928ee5c690"> - - - <link rel="alternate" type="application/atom+xml" title="Tesseras" href="https://tesseras.net/atom.xml"> - - - <link rel="icon" type="image/png" sizes="32x32" href="https://tesseras.net/images/favicon.png?h=be4e123a23393b1a027d"> - -</head> -<body> - <header> - <h1> - <a href="https://tesseras.net/pt-br/"> - <img src="https://tesseras.net/images/logo-64.png?h=c1b8d0c4c5f93b49d40b" alt="Tesseras" width="40" height="40" class="logo"> - Tesseras - </a> - </h1> - <nav> - - <a href="https://tesseras.net/pt-br/about/">Sobre</a> - <a href="https://tesseras.net/pt-br/news/">Notícias</a> - <a href="https://tesseras.net/pt-br/releases/">Lançamentos</a> - <a href="https://tesseras.net/pt-br/faq/">FAQ</a> - <a href="https://tesseras.net/pt-br/subscriptions/">Inscrições</a> - <a href="https://tesseras.net/pt-br/contact/">Contato</a> - - </nav> - <nav class="lang-switch"> - - <a href="https://tesseras.net/news/">English</a> | <strong>Português</strong> - - </nav> - </header> - - <main> - -<h2>Notícias</h2> - -<ul class="news-list"> - - <li> - <a href="https://tesseras.net/pt-br/news/packaging-debian/">Empacotando o Tesseras para Debian</a> - <span class="news-date">2026-02-16</span> - - <p>Como compilar e instalar o pacote .deb do Tesseras no Debian/Ubuntu usando cargo-deb.</p> - - </li> - - <li> - <a href="https://tesseras.net/pt-br/news/packaging-archlinux/">Empacotando o Tesseras para Arch Linux</a> - <span class="news-date">2026-02-16</span> - - <p>Como compilar e instalar o pacote Tesseras no Arch Linux a partir do código-fonte usando makepkg.</p> - - </li> - - <li> - <a href="https://tesseras.net/pt-br/news/phase4-storage-deduplication/">Fase 4: Deduplicacao de Armazenamento</a> - <span class="news-date">2026-02-15</span> - - <p>Uma nova camada de armazenamento enderecavel por conteudo elimina dados duplicados entre tesseras, reduzindo uso de disco e habilitando coleta de lixo automatica.</p> - - </li> - - <li> - <a href="https://tesseras.net/pt-br/news/phase4-institutional-onboarding/">Fase 4: Onboarding de Nos Institucionais</a> - <span class="news-date">2026-02-15</span> - - <p>Bibliotecas, arquivos e museus agora podem ingressar na rede Tesseras como nos institucionais verificados com identidade baseada em DNS, indices de busca full-text e compromissos configuraveis de armazenamento.</p> - - </li> - - <li> - <a href="https://tesseras.net/pt-br/news/phase4-performance-tuning/">Fase 4: Tuning de Performance</a> - <span class="news-date">2026-02-15</span> - - <p>SQLite em modo WAL com configuracao centralizada de pragmas, cache LRU de fragmentos, gerenciamento de ciclo de vida do pool de conexoes QUIC e otimizacao do hot path de atestacao.</p> - - </li> - - <li> - <a href="https://tesseras.net/pt-br/news/phase4-wasm-browser-verification/">Fase 4: Verificar Sem Instalar Nada</a> - <span class="news-date">2026-02-15</span> - - <p>Tesseras agora compila para WebAssembly — qualquer pessoa pode verificar integridade e autenticidade de uma tessera diretamente no navegador, sem instalar nenhum software.</p> - - </li> - - <li> - <a href="https://tesseras.net/pt-br/news/phase4-nat-traversal/">Fase 4: Furando NATs</a> - <span class="news-date">2026-02-15</span> - - <p>Os nos Tesseras agora podem descobrir seu tipo de NAT via STUN, coordenar UDP hole punching atraves de introdutores e usar relay transparente quando a conectividade direta falha.</p> - - </li> - - <li> - <a href="https://tesseras.net/pt-br/news/cli-daemon-rpc/">CLI Encontra a Rede: Comandos Publish, Fetch e Status</a> - <span class="news-date">2026-02-15</span> - - <p>O CLI do tesseras agora pode publicar tesseras na rede, buscá-las de peers e monitorar o estado de replicação — tudo através de uma nova ponte RPC via socket Unix para o daemon.</p> - - </li> - - <li> - <a href="https://tesseras.net/pt-br/news/phase4-shamir-heir-recovery/">Fase 4: Recuperação de Chaves por Herdeiros com Shamir's Secret Sharing</a> - <span class="news-date">2026-02-15</span> - - <p>Tesseras agora permite dividir sua identidade criptográfica em fragmentos distribuídos a herdeiros de confiança — qualquer limiar deles pode reconstruir suas chaves, mas menos que isso não revela nada.</p> - - </li> - - <li> - <a href="https://tesseras.net/pt-br/news/phase4-encryption-sealed/">Fase 4: Criptografia e Tesseras Seladas</a> - <span class="news-date">2026-02-14</span> - - <p>Tesseras agora suporta memórias privadas e seladas com criptografia híbrida pós-quântica — AES-256-GCM, X25519 + ML-KEM-768 e publicação de chaves com bloqueio temporal.</p> - - </li> - - <li> - <a href="https://tesseras.net/pt-br/news/phase3-api-and-apps/">Fase 3: Memórias nas Suas Mãos</a> - <span class="news-date">2026-02-14</span> - - <p>Tesseras agora tem um app Flutter e um nó Rust embarcado — qualquer pessoa pode criar e preservar memórias pelo celular.</p> - - </li> - - <li> - <a href="https://tesseras.net/pt-br/news/reed-solomon/">Reed-Solomon: Como o Tesseras Sobrevive à Perda de Dados</a> - <span class="news-date">2026-02-14</span> - - <p>Um mergulho profundo na codificação de apagamento Reed-Solomon — o que é, por que o Tesseras a utiliza e os desafios de manter memórias vivas ao longo dos séculos.</p> - - </li> - - <li> - <a href="https://tesseras.net/pt-br/news/phase2-replication/">Fase 2: Memórias Sobrevivem</a> - <span class="news-date">2026-02-14</span> - - <p>Tesseras agora fragmenta, distribui e repara dados automaticamente pela rede usando codificação de apagamento Reed-Solomon e um livro-razão de reciprocidade bilateral.</p> - - </li> - - <li> - <a href="https://tesseras.net/pt-br/news/phase1-basic-network/">Fase 1: Nós Se Encontram</a> - <span class="news-date">2026-02-14</span> - - <p>Os nós do Tesseras agora descobrem pares, formam uma DHT Kademlia sobre QUIC e publicam e encontram ponteiros de tesseras pela rede.</p> - - </li> - - <li> - <a href="https://tesseras.net/pt-br/news/phase0-foundation/">Fase 0: Fundação Construída</a> - <span class="news-date">2026-02-14</span> - - <p>Os crates fundamentais do Tesseras estão prontos — tipos de domínio, primitivas criptográficas, armazenamento SQLite e uma CLI funcional.</p> - - </li> - - <li> - <a href="https://tesseras.net/pt-br/news/hello-world/">Olá, Mundo</a> - <span class="news-date">2026-02-13</span> - - <p>Apresentando o projeto Tesseras — uma rede P2P para preservar memórias humanas.</p> - - </li> - -</ul> - - - </main> - - <footer> - <p>© 2026 Tesseras Project. <a href="/atom.xml">News Feed</a> · <a href="https://git.sr.ht/~ijanc/tesseras">Source</a></p> - </footer> -</body> -</html> diff --git a/pt-br/news/index.html.gz b/pt-br/news/index.html.gz Binary files differdeleted file mode 100644 index 8aede06..0000000 --- a/pt-br/news/index.html.gz +++ /dev/null diff --git a/pt-br/news/packaging-archlinux/index.html b/pt-br/news/packaging-archlinux/index.html deleted file mode 100644 index fb3f918..0000000 --- a/pt-br/news/packaging-archlinux/index.html +++ /dev/null @@ -1,124 +0,0 @@ -<!DOCTYPE html> -<html lang="pt-br"> -<head> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <title>Empacotando o Tesseras para Arch Linux — Tesseras</title> - <meta name="description" content="Como compilar e instalar o pacote Tesseras no Arch Linux a partir do código-fonte usando makepkg."> - <!-- Open Graph --> - <meta property="og:type" content="article"> - <meta property="og:title" content="Empacotando o Tesseras para Arch Linux"> - <meta property="og:description" content="Como compilar e instalar o pacote Tesseras no Arch Linux a partir do código-fonte usando makepkg."> - <meta property="og:image" content="https://tesseras.net/images/social.jpg"> - <meta property="og:image:width" content="1200"> - <meta property="og:image:height" content="630"> - <meta property="og:site_name" content="Tesseras"> - <!-- Twitter Card --> - <meta name="twitter:card" content="summary_large_image"> - <meta name="twitter:title" content="Empacotando o Tesseras para Arch Linux"> - <meta name="twitter:description" content="Como compilar e instalar o pacote Tesseras no Arch Linux a partir do código-fonte usando makepkg."> - <meta name="twitter:image" content="https://tesseras.net/images/social.jpg"> - <link rel="stylesheet" href="https://tesseras.net/style.css?h=21f0f32121928ee5c690"> - - - <link rel="alternate" type="application/atom+xml" title="Tesseras" href="https://tesseras.net/atom.xml"> - - - <link rel="icon" type="image/png" sizes="32x32" href="https://tesseras.net/images/favicon.png?h=be4e123a23393b1a027d"> - -</head> -<body> - <header> - <h1> - <a href="https://tesseras.net/pt-br/"> - <img src="https://tesseras.net/images/logo-64.png?h=c1b8d0c4c5f93b49d40b" alt="Tesseras" width="40" height="40" class="logo"> - Tesseras - </a> - </h1> - <nav> - - <a href="https://tesseras.net/pt-br/about/">Sobre</a> - <a href="https://tesseras.net/pt-br/news/">Notícias</a> - <a href="https://tesseras.net/pt-br/releases/">Lançamentos</a> - <a href="https://tesseras.net/pt-br/faq/">FAQ</a> - <a href="https://tesseras.net/pt-br/subscriptions/">Inscrições</a> - <a href="https://tesseras.net/pt-br/contact/">Contato</a> - - </nav> - <nav class="lang-switch"> - - <a href="https://tesseras.net/news/packaging-archlinux/">English</a> | <strong>Português</strong> - - </nav> - </header> - - <main> - -<article> - <h2>Empacotando o Tesseras para Arch Linux</h2> - <p class="news-date">2026-02-16</p> - <p>O Tesseras agora inclui um PKGBUILD para Arch Linux. Este post explica como -compilar e instalar o pacote a partir do código-fonte.</p> -<h2 id="pre-requisitos">Pré-requisitos</h2> -<p>Você precisa de uma toolchain Rust funcional e do grupo base-devel:</p> -<pre><code data-lang="sh">sudo pacman -S --needed base-devel sqlite -rustup toolchain install stable -</code></pre> -<h2 id="compilando">Compilando</h2> -<p>Clone o repositório e execute a recipe <code>just arch</code>:</p> -<pre><code data-lang="sh">git clone https://git.sr.ht/~ijanc/tesseras -cd tesseras -just arch -</code></pre> -<p>Isso executa <code>makepkg -sf</code> dentro de <code>packaging/archlinux/</code>, que:</p> -<ol> -<li><strong>prepare</strong> — baixa as dependências Cargo com <code>cargo fetch --locked</code></li> -<li><strong>build</strong> — compila <code>tesd</code> e <code>tes</code> (o CLI) em modo release</li> -<li><strong>package</strong> — instala binários, serviço systemd, configs sysusers/tmpfiles, -completions de shell (bash, zsh, fish) e um arquivo de configuração padrão</li> -</ol> -<p>O resultado é um arquivo <code>.pkg.tar.zst</code> em <code>packaging/archlinux/</code>.</p> -<h2 id="instalando">Instalando</h2> -<pre><code data-lang="sh">sudo pacman -U packaging/archlinux/tesseras-*.pkg.tar.zst -</code></pre> -<h2 id="configuracao-pos-instalacao">Configuração pós-instalação</h2> -<p>O pacote cria automaticamente um usuário e grupo de sistema <code>tesseras</code> via -systemd-sysusers. Para usar o CLI sem sudo, adicione seu usuário ao grupo:</p> -<pre><code data-lang="sh">sudo usermod -aG tesseras $USER -</code></pre> -<p>Faça logout e login novamente, depois inicie o daemon:</p> -<pre><code data-lang="sh">sudo systemctl enable --now tesd -</code></pre> -<h2 id="o-que-o-pacote-inclui">O que o pacote inclui</h2> -<table><thead><tr><th>Caminho</th><th>Descrição</th></tr></thead><tbody> -<tr><td><code>/usr/bin/tesd</code></td><td>Daemon do nó completo</td></tr> -<tr><td><code>/usr/bin/tes</code></td><td>Cliente CLI</td></tr> -<tr><td><code>/etc/tesseras/config.toml</code></td><td>Configuração padrão (marcado como backup)</td></tr> -<tr><td><code>/usr/lib/systemd/system/tesd.service</code></td><td>Unit systemd com hardening de segurança</td></tr> -<tr><td><code>/usr/lib/sysusers.d/tesseras.conf</code></td><td>Definição do usuário de sistema</td></tr> -<tr><td><code>/usr/lib/tmpfiles.d/tesseras.conf</code></td><td>Diretório de dados <code>/var/lib/tesseras</code></td></tr> -<tr><td>Completions de shell</td><td>bash, zsh e fish</td></tr> -</tbody></table> -<h2 id="detalhes-do-pkgbuild">Detalhes do PKGBUILD</h2> -<p>O PKGBUILD compila diretamente a partir do checkout git local em vez de baixar -um tarball. A variável de ambiente <code>TESSERAS_ROOT</code> aponta o makepkg para a raiz -do workspace. O diretório target do Cargo é configurado para <code>$srcdir/target</code> -para manter os artefatos de build dentro do sandbox do makepkg.</p> -<p>O pacote depende apenas de <code>sqlite</code> em tempo de execução e <code>cargo</code> em tempo de -build.</p> -<h2 id="atualizando">Atualizando</h2> -<p>Depois de baixar novas mudanças, basta rodar <code>just arch</code> novamente e reinstalar:</p> -<pre><code data-lang="sh">git pull -just arch -sudo pacman -U packaging/archlinux/tesseras-*.pkg.tar.zst -</code></pre> - -</article> - - </main> - - <footer> - <p>© 2026 Tesseras Project. <a href="/atom.xml">News Feed</a> · <a href="https://git.sr.ht/~ijanc/tesseras">Source</a></p> - </footer> -</body> -</html> diff --git a/pt-br/news/packaging-archlinux/index.html.gz b/pt-br/news/packaging-archlinux/index.html.gz Binary files differdeleted file mode 100644 index 3161854..0000000 --- a/pt-br/news/packaging-archlinux/index.html.gz +++ /dev/null diff --git a/pt-br/news/packaging-debian/index.html b/pt-br/news/packaging-debian/index.html deleted file mode 100644 index 815152a..0000000 --- a/pt-br/news/packaging-debian/index.html +++ /dev/null @@ -1,159 +0,0 @@ -<!DOCTYPE html> -<html lang="pt-br"> -<head> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <title>Empacotando o Tesseras para Debian — Tesseras</title> - <meta name="description" content="Como compilar e instalar o pacote .deb do Tesseras no Debian/Ubuntu usando cargo-deb."> - <!-- Open Graph --> - <meta property="og:type" content="article"> - <meta property="og:title" content="Empacotando o Tesseras para Debian"> - <meta property="og:description" content="Como compilar e instalar o pacote .deb do Tesseras no Debian/Ubuntu usando cargo-deb."> - <meta property="og:image" content="https://tesseras.net/images/social.jpg"> - <meta property="og:image:width" content="1200"> - <meta property="og:image:height" content="630"> - <meta property="og:site_name" content="Tesseras"> - <!-- Twitter Card --> - <meta name="twitter:card" content="summary_large_image"> - <meta name="twitter:title" content="Empacotando o Tesseras para Debian"> - <meta name="twitter:description" content="Como compilar e instalar o pacote .deb do Tesseras no Debian/Ubuntu usando cargo-deb."> - <meta name="twitter:image" content="https://tesseras.net/images/social.jpg"> - <link rel="stylesheet" href="https://tesseras.net/style.css?h=21f0f32121928ee5c690"> - - - <link rel="alternate" type="application/atom+xml" title="Tesseras" href="https://tesseras.net/atom.xml"> - - - <link rel="icon" type="image/png" sizes="32x32" href="https://tesseras.net/images/favicon.png?h=be4e123a23393b1a027d"> - -</head> -<body> - <header> - <h1> - <a href="https://tesseras.net/pt-br/"> - <img src="https://tesseras.net/images/logo-64.png?h=c1b8d0c4c5f93b49d40b" alt="Tesseras" width="40" height="40" class="logo"> - Tesseras - </a> - </h1> - <nav> - - <a href="https://tesseras.net/pt-br/about/">Sobre</a> - <a href="https://tesseras.net/pt-br/news/">Notícias</a> - <a href="https://tesseras.net/pt-br/releases/">Lançamentos</a> - <a href="https://tesseras.net/pt-br/faq/">FAQ</a> - <a href="https://tesseras.net/pt-br/subscriptions/">Inscrições</a> - <a href="https://tesseras.net/pt-br/contact/">Contato</a> - - </nav> - <nav class="lang-switch"> - - <a href="https://tesseras.net/news/packaging-debian/">English</a> | <strong>Português</strong> - - </nav> - </header> - - <main> - -<article> - <h2>Empacotando o Tesseras para Debian</h2> - <p class="news-date">2026-02-16</p> - <p>O Tesseras agora inclui um pacote <code>.deb</code> para Debian e Ubuntu. Este post explica -como compilar e instalar o pacote a partir do código-fonte usando <code>cargo-deb</code>.</p> -<h2 id="pre-requisitos">Pré-requisitos</h2> -<p>Você precisa de uma toolchain Rust funcional e das bibliotecas de sistema -necessárias:</p> -<pre><code data-lang="sh">sudo apt install build-essential pkg-config libsqlite3-dev -rustup toolchain install stable -cargo install cargo-deb -</code></pre> -<h2 id="compilando">Compilando</h2> -<p>Clone o repositório e execute a recipe <code>just deb</code>:</p> -<pre><code data-lang="sh">git clone https://git.sr.ht/~ijanc/tesseras -cd tesseras -just deb -</code></pre> -<p>Essa recipe faz três coisas:</p> -<ol> -<li><strong>Compila</strong> <code>tesd</code> (o daemon) e <code>tes</code> (o CLI) em modo release com -<code>cargo build --release</code></li> -<li><strong>Gera completions de shell</strong> para bash, zsh e fish a partir do binário <code>tes</code></li> -<li><strong>Empacota</strong> tudo em um arquivo <code>.deb</code> com -<code>cargo deb -p tesseras-daemon --no-build</code></li> -</ol> -<p>O resultado é um arquivo <code>.deb</code> em <code>target/debian/</code>.</p> -<h2 id="instalando">Instalando</h2> -<pre><code data-lang="sh">sudo dpkg -i target/debian/tesseras-daemon_*.deb -</code></pre> -<p>Se houver dependências faltando, corrija com:</p> -<pre><code data-lang="sh">sudo apt install -f -</code></pre> -<h2 id="configuracao-pos-instalacao">Configuração pós-instalação</h2> -<p>O script <code>postinst</code> cria automaticamente um usuário de sistema <code>tesseras</code> e o -diretório de dados <code>/var/lib/tesseras</code>. Para usar o CLI sem sudo, adicione seu -usuário ao grupo:</p> -<pre><code data-lang="sh">sudo usermod -aG tesseras $USER -</code></pre> -<p>Faça logout e login novamente, depois inicie o daemon:</p> -<pre><code data-lang="sh">sudo systemctl enable --now tesd -</code></pre> -<h2 id="o-que-o-pacote-inclui">O que o pacote inclui</h2> -<table><thead><tr><th>Caminho</th><th>Descrição</th></tr></thead><tbody> -<tr><td><code>/usr/bin/tesd</code></td><td>Daemon do nó completo</td></tr> -<tr><td><code>/usr/bin/tes</code></td><td>Cliente CLI</td></tr> -<tr><td><code>/etc/tesseras/config.toml</code></td><td>Configuração padrão (marcado como conffile)</td></tr> -<tr><td><code>/lib/systemd/system/tesd.service</code></td><td>Unit systemd com hardening de segurança</td></tr> -<tr><td>Completions de shell</td><td>bash, zsh e fish</td></tr> -</tbody></table> -<h2 id="como-o-cargo-deb-funciona">Como o cargo-deb funciona</h2> -<p>Os metadados de empacotamento ficam em <code>crates/tesseras-daemon/Cargo.toml</code> na -seção <code>[package.metadata.deb]</code>. Essa seção define:</p> -<ul> -<li><strong>depends</strong> — dependências em tempo de execução: <code>libc6</code> e <code>libsqlite3-0</code></li> -<li><strong>assets</strong> — arquivos incluídos no pacote (binários, config, unit systemd, -completions de shell)</li> -<li><strong>conf-files</strong> — arquivos tratados como configuração (preservados na -atualização)</li> -<li><strong>maintainer-scripts</strong> — scripts <code>postinst</code> e <code>postrm</code> em -<code>packaging/debian/scripts/</code></li> -<li><strong>systemd-units</strong> — integração automática com systemd</li> -</ul> -<p>O script <code>postinst</code> cria o usuário de sistema <code>tesseras</code> e o diretório de dados -na instalação. O script <code>postrm</code> remove o usuário, grupo e diretório de dados -apenas no <code>purge</code> (não na remoção simples).</p> -<h2 id="hardening-do-systemd">Hardening do systemd</h2> -<p>A unit <code>tesd.service</code> inclui diretivas de hardening de segurança:</p> -<pre><code data-lang="ini">NoNewPrivileges=true -ProtectSystem=strict -ProtectHome=true -ReadWritePaths=/var/lib/tesseras -PrivateTmp=true -PrivateDevices=true -ProtectKernelTunables=true -ProtectControlGroups=true -RestrictSUIDSGID=true -MemoryDenyWriteExecute=true -</code></pre> -<p>O daemon roda como o usuário não-privilegiado <code>tesseras</code> e só pode escrever em -<code>/var/lib/tesseras</code>.</p> -<h2 id="deploy-para-um-servidor-remoto">Deploy para um servidor remoto</h2> -<p>O justfile inclui uma recipe <code>deploy</code> para enviar o <code>.deb</code> a um host remoto:</p> -<pre><code data-lang="sh">just deploy bootstrap1.tesseras.net -</code></pre> -<p>Isso compila o <code>.deb</code>, copia via <code>scp</code>, instala com <code>dpkg -i</code> e reinicia o -serviço <code>tesd</code>.</p> -<h2 id="atualizando">Atualizando</h2> -<p>Depois de baixar novas mudanças, basta rodar <code>just deb</code> novamente e reinstalar:</p> -<pre><code data-lang="sh">git pull -just deb -sudo dpkg -i target/debian/tesseras-daemon_*.deb -</code></pre> - -</article> - - </main> - - <footer> - <p>© 2026 Tesseras Project. <a href="/atom.xml">News Feed</a> · <a href="https://git.sr.ht/~ijanc/tesseras">Source</a></p> - </footer> -</body> -</html> diff --git a/pt-br/news/packaging-debian/index.html.gz b/pt-br/news/packaging-debian/index.html.gz Binary files differdeleted file mode 100644 index 1e8d0a0..0000000 --- a/pt-br/news/packaging-debian/index.html.gz +++ /dev/null diff --git a/pt-br/news/phase0-foundation/index.html b/pt-br/news/phase0-foundation/index.html deleted file mode 100644 index ab4b679..0000000 --- a/pt-br/news/phase0-foundation/index.html +++ /dev/null @@ -1,130 +0,0 @@ -<!DOCTYPE html> -<html lang="pt-br"> -<head> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <title>Fase 0: Fundação Construída — Tesseras</title> - <meta name="description" content="Os crates fundamentais do Tesseras estão prontos — tipos de domínio, primitivas criptográficas, armazenamento SQLite e uma CLI funcional."> - <!-- Open Graph --> - <meta property="og:type" content="article"> - <meta property="og:title" content="Fase 0: Fundação Construída"> - <meta property="og:description" content="Os crates fundamentais do Tesseras estão prontos — tipos de domínio, primitivas criptográficas, armazenamento SQLite e uma CLI funcional."> - <meta property="og:image" content="https://tesseras.net/images/social.jpg"> - <meta property="og:image:width" content="1200"> - <meta property="og:image:height" content="630"> - <meta property="og:site_name" content="Tesseras"> - <!-- Twitter Card --> - <meta name="twitter:card" content="summary_large_image"> - <meta name="twitter:title" content="Fase 0: Fundação Construída"> - <meta name="twitter:description" content="Os crates fundamentais do Tesseras estão prontos — tipos de domínio, primitivas criptográficas, armazenamento SQLite e uma CLI funcional."> - <meta name="twitter:image" content="https://tesseras.net/images/social.jpg"> - <link rel="stylesheet" href="https://tesseras.net/style.css?h=21f0f32121928ee5c690"> - - - <link rel="alternate" type="application/atom+xml" title="Tesseras" href="https://tesseras.net/atom.xml"> - - - <link rel="icon" type="image/png" sizes="32x32" href="https://tesseras.net/images/favicon.png?h=be4e123a23393b1a027d"> - -</head> -<body> - <header> - <h1> - <a href="https://tesseras.net/pt-br/"> - <img src="https://tesseras.net/images/logo-64.png?h=c1b8d0c4c5f93b49d40b" alt="Tesseras" width="40" height="40" class="logo"> - Tesseras - </a> - </h1> - <nav> - - <a href="https://tesseras.net/pt-br/about/">Sobre</a> - <a href="https://tesseras.net/pt-br/news/">Notícias</a> - <a href="https://tesseras.net/pt-br/releases/">Lançamentos</a> - <a href="https://tesseras.net/pt-br/faq/">FAQ</a> - <a href="https://tesseras.net/pt-br/subscriptions/">Inscrições</a> - <a href="https://tesseras.net/pt-br/contact/">Contato</a> - - </nav> - <nav class="lang-switch"> - - <a href="https://tesseras.net/news/phase0-foundation/">English</a> | <strong>Português</strong> - - </nav> - </header> - - <main> - -<article> - <h2>Fase 0: Fundação Construída</h2> - <p class="news-date">2026-02-14</p> - <p>O primeiro marco do projeto Tesseras está completo. A Fase 0 estabelece a -fundação sobre a qual cada componente futuro será construído: tipos de domínio, -criptografia, armazenamento e uma interface de linha de comando funcional.</p> -<h2 id="o-que-foi-construido">O que foi construído</h2> -<p><strong>tesseras-core</strong> — A camada de domínio define o formato tessera: <code>ContentHash</code> -(BLAKE3, 32 bytes), <code>NodeId</code> (Kademlia, 20 bytes), tipos de memória (Moment, -Reflection, Daily, Relation, Object), modos de visibilidade (Private, Circle, -Public, PublicAfterDeath, Sealed) e um formato de manifesto em texto plano que -pode ser interpretado por qualquer linguagem de programação pelos próximos mil -anos. A camada de serviço (<code>TesseraService</code>) gerencia operações de criação, -verificação, exportação e listagem através de port traits, seguindo arquitetura -hexagonal.</p> -<p><strong>tesseras-crypto</strong> — Geração de chaves Ed25519, assinatura e verificação. Um -framework de assinatura dual (Ed25519 + placeholder ML-DSA) pronto para migração -pós-quântica. Hashing de conteúdo com BLAKE3. Codificação de apagamento -Reed-Solomon atrás de uma feature flag para futura replicação.</p> -<p><strong>tesseras-storage</strong> — Índice SQLite via rusqlite com migrações em SQL puro. -Blob store no sistema de arquivos com layout endereçável por conteúdo -(<code>blobs/<tessera_hash>/<memory_hash>/<filename></code>). Persistência de chaves de -identidade em disco.</p> -<p><strong>tesseras-cli</strong> — Um binário <code>tesseras</code> funcional com cinco comandos:</p> -<ul> -<li><code>init</code> — gera identidade Ed25519, cria banco de dados SQLite</li> -<li><code>create <dir></code> — varre um diretório por arquivos de mídia, cria uma tessera -assinada</li> -<li><code>verify <hash></code> — verifica assinatura e integridade dos arquivos</li> -<li><code>export <hash> <dest></code> — escreve um diretório tessera autocontido</li> -<li><code>list</code> — mostra uma tabela das tesseras armazenadas</li> -</ul> -<p><strong>Testes</strong> — 67+ testes em todo o workspace: testes unitários em cada módulo, -testes baseados em propriedades (proptest) para roundtrips hex e serialização de -manifesto, testes de integração cobrindo o ciclo completo de -criação-verificação-exportação incluindo detecção de arquivos adulterados e -assinaturas inválidas. Zero avisos do clippy.</p> -<h2 id="decisoes-de-arquitetura">Decisões de arquitetura</h2> -<ul> -<li><strong>Arquitetura hexagonal</strong>: operações criptográficas são injetadas via trait -objects (<code>Box<dyn Hasher></code>, <code>Box<dyn ManifestSigner></code>, -<code>Box<dyn ManifestVerifier></code>), mantendo o crate core livre de dependências -criptográficas concretas.</li> -<li><strong>Feature flags</strong>: a feature <code>service</code> no tesseras-core controla a camada de -aplicação assíncrona. As features <code>classical</code> e <code>erasure</code> no tesseras-crypto -controlam quais algoritmos são compilados.</li> -<li><strong>Manifesto em texto plano</strong>: interpretável sem qualquer biblioteca de formato -binário, com prefixos de hash explícitos <code>blake3:</code> e layout legível por -humanos.</li> -</ul> -<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2> -<p>A Fase 0 é a fundação local. O caminho adiante:</p> -<ul> -<li><strong>Fase 1: Rede</strong> — Transporte QUIC (quinn), DHT Kademlia para descoberta de -pares, travessia de NAT</li> -<li><strong>Fase 2: Replicação</strong> — Codificação de apagamento Reed-Solomon pela rede, -loops de reparo, reciprocidade bilateral (sem blockchain, sem tokens)</li> -<li><strong>Fase 3: Clientes</strong> — App Flutter mobile/desktop via flutter_rust_bridge, API -GraphQL, nó WASM no navegador</li> -<li><strong>Fase 4: Endurecimento</strong> — Assinaturas pós-quânticas ML-DSA, empacotamento -para Alpine/Arch/Debian/FreeBSD/OpenBSD, CI no SourceHut</li> -</ul> -<p>O formato tessera é estável. Tudo construído a partir daqui se conecta e estende -o que existe hoje.</p> - -</article> - - </main> - - <footer> - <p>© 2026 Tesseras Project. <a href="/atom.xml">News Feed</a> · <a href="https://git.sr.ht/~ijanc/tesseras">Source</a></p> - </footer> -</body> -</html> diff --git a/pt-br/news/phase0-foundation/index.html.gz b/pt-br/news/phase0-foundation/index.html.gz Binary files differdeleted file mode 100644 index fc10aa5..0000000 --- a/pt-br/news/phase0-foundation/index.html.gz +++ /dev/null diff --git a/pt-br/news/phase1-basic-network/index.html b/pt-br/news/phase1-basic-network/index.html deleted file mode 100644 index 1dbbf62..0000000 --- a/pt-br/news/phase1-basic-network/index.html +++ /dev/null @@ -1,177 +0,0 @@ -<!DOCTYPE html> -<html lang="pt-br"> -<head> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <title>Fase 1: Nós Se Encontram — Tesseras</title> - <meta name="description" content="Os nós do Tesseras agora descobrem pares, formam uma DHT Kademlia sobre QUIC e publicam e encontram ponteiros de tesseras pela rede."> - <!-- Open Graph --> - <meta property="og:type" content="article"> - <meta property="og:title" content="Fase 1: Nós Se Encontram"> - <meta property="og:description" content="Os nós do Tesseras agora descobrem pares, formam uma DHT Kademlia sobre QUIC e publicam e encontram ponteiros de tesseras pela rede."> - <meta property="og:image" content="https://tesseras.net/images/social.jpg"> - <meta property="og:image:width" content="1200"> - <meta property="og:image:height" content="630"> - <meta property="og:site_name" content="Tesseras"> - <!-- Twitter Card --> - <meta name="twitter:card" content="summary_large_image"> - <meta name="twitter:title" content="Fase 1: Nós Se Encontram"> - <meta name="twitter:description" content="Os nós do Tesseras agora descobrem pares, formam uma DHT Kademlia sobre QUIC e publicam e encontram ponteiros de tesseras pela rede."> - <meta name="twitter:image" content="https://tesseras.net/images/social.jpg"> - <link rel="stylesheet" href="https://tesseras.net/style.css?h=21f0f32121928ee5c690"> - - - <link rel="alternate" type="application/atom+xml" title="Tesseras" href="https://tesseras.net/atom.xml"> - - - <link rel="icon" type="image/png" sizes="32x32" href="https://tesseras.net/images/favicon.png?h=be4e123a23393b1a027d"> - -</head> -<body> - <header> - <h1> - <a href="https://tesseras.net/pt-br/"> - <img src="https://tesseras.net/images/logo-64.png?h=c1b8d0c4c5f93b49d40b" alt="Tesseras" width="40" height="40" class="logo"> - Tesseras - </a> - </h1> - <nav> - - <a href="https://tesseras.net/pt-br/about/">Sobre</a> - <a href="https://tesseras.net/pt-br/news/">Notícias</a> - <a href="https://tesseras.net/pt-br/releases/">Lançamentos</a> - <a href="https://tesseras.net/pt-br/faq/">FAQ</a> - <a href="https://tesseras.net/pt-br/subscriptions/">Inscrições</a> - <a href="https://tesseras.net/pt-br/contact/">Contato</a> - - </nav> - <nav class="lang-switch"> - - <a href="https://tesseras.net/news/phase1-basic-network/">English</a> | <strong>Português</strong> - - </nav> - </header> - - <main> - -<article> - <h2>Fase 1: Nós Se Encontram</h2> - <p class="news-date">2026-02-14</p> - <p>Tesseras não é mais uma ferramenta apenas local. A Fase 1 entrega a camada de -rede: nós se descobrem através de uma DHT Kademlia, comunicam-se sobre QUIC e -publicam ponteiros de tesseras que qualquer par na rede pode encontrar. Uma -tessera criada no nó A agora pode ser encontrada a partir do nó C.</p> -<h2 id="o-que-foi-construido">O que foi construído</h2> -<p><strong>tesseras-core</strong> (atualizado) — Novos tipos de domínio de rede: -<code>TesseraPointer</code> (referência leve aos detentores de uma tessera e localização -dos fragmentos), <code>NodeIdentity</code> (ID do nó + chave pública + nonce de prova de -trabalho), <code>NodeInfo</code> (identidade + endereço + capacidades) e <code>Capabilities</code> -(bitflags do que um nó suporta: DHT, armazenamento, relay, replicação).</p> -<p><strong>tesseras-net</strong> — A camada de transporte, construída sobre QUIC via quinn. A -trait <code>Transport</code> define a porta: <code>send</code>, <code>recv</code>, <code>disconnect</code>, <code>local_addr</code>. -Dois adaptadores a implementam:</p> -<ul> -<li><code>QuinnTransport</code> — QUIC real com TLS auto-assinado, negociação ALPN -(<code>tesseras/1</code>), pool de conexões via DashMap e um loop de aceitação em -background que trata streams recebidas.</li> -<li><code>MemTransport</code> + <code>SimNetwork</code> — canais em memória para testes determinísticos -sem I/O de rede. Cada teste de integração no crate DHT roda contra este -adaptador.</li> -</ul> -<p>O protocolo de fio usa MessagePack com prefixo de comprimento: um cabeçalho de 4 -bytes big-endian seguido de um payload rmp-serde. <code>WireMessage</code> carrega um byte -de versão, ID de requisição e um corpo que pode ser requisição, resposta ou erro -de protocolo. Tamanho máximo de mensagem é 64 KiB.</p> -<p><strong>tesseras-dht</strong> — Uma implementação completa de Kademlia:</p> -<ul> -<li><em>Tabela de roteamento</em>: 160 k-buckets com k=20. Evicção do menos recentemente -visto, mover-para-trás ao atualizar, verificação por ping antes de substituir -a entrada mais antiga de um bucket cheio.</li> -<li><em>Distância XOR</em>: métrica XOR de 160 bits com indexação de bucket pelo bit mais -significativo diferente.</li> -<li><em>Prova de trabalho</em>: nós iteram um nonce até que -<code>BLAKE3(pubkey || nonce)[..20]</code> tenha 8 bits zero iniciais (~256 tentativas de -hash em média). Barato o suficiente para qualquer dispositivo, caro o -suficiente para tornar ataques Sybil impraticáveis em escala.</li> -<li><em>Mensagens de protocolo</em>: Ping/Pong, FindNode/FindNodeResponse, -FindValue/FindValueResult, Store — todos serializados com MessagePack via -serde.</li> -<li><em>Armazenamento de ponteiros</em>: armazenamento em memória limitado com TTL -configurável (24 horas padrão) e máximo de entradas (10.000 padrão). Quando -cheio, remove ponteiros mais distantes do ID do nó local, seguindo o modelo de -responsabilidade baseado em distância do Kademlia.</li> -<li><em>DhtEngine</em>: o orquestrador principal. Trata RPCs recebidos, executa buscas -iterativas (paralelismo alpha=3), bootstrap, publicação e busca. O método -<code>run()</code> dirige um loop <code>tokio::select!</code> com timers de manutenção: refresh da -tabela de roteamento a cada 60 segundos, expiração de ponteiros a cada 5 -minutos.</li> -</ul> -<p><strong>tesd</strong> — Um binário de nó completo. Analisa argumentos de CLI (endereço de -bind, pares de bootstrap, diretório de dados), gera uma identidade de nó válida -por PoW, abre um endpoint QUIC, faz bootstrap na rede e roda o motor DHT. -Desligamento gracioso com Ctrl+C via tratamento de sinais do tokio.</p> -<p><strong>Infraestrutura</strong> — Configuração OpenTofu para dois nós bootstrap no Hetzner -Cloud (instâncias cx22 em Falkenstein, Alemanha e Helsinki, Finlândia). Script -de provisionamento cloud-init cria um usuário dedicado <code>tesseras</code>, escreve um -arquivo de configuração e configura um serviço systemd. Regras de firewall abrem -UDP 4433 (QUIC) e restringem métricas a acesso interno.</p> -<p><strong>Testes</strong> — 139 testes em todo o workspace:</p> -<ul> -<li>47 testes unitários em tesseras-dht (tabela de roteamento, distância, PoW, -armazenamento de ponteiros, serialização de mensagens, RPCs do engine)</li> -<li>5 testes de integração multi-nó (bootstrap de 3 nós, convergência de lookup -com 10 nós, publicar-e-encontrar, detecção de partida de nó, rejeição de PoW)</li> -<li>14 testes em tesseras-net (roundtrips de codec, send/recv de transporte, -backpressure, disconnect)</li> -<li>Testes de fumaça com Docker Compose usando 3 nós containerizados comunicando -sobre QUIC real</li> -<li>Zero avisos do clippy, formatação limpa</li> -</ul> -<h2 id="decisoes-de-arquitetura">Decisões de arquitetura</h2> -<ul> -<li><strong>Transport como porta</strong>: a trait <code>Transport</code> é a única interface entre o -motor DHT e a rede. Trocar QUIC por qualquer outro protocolo significa -implementar quatro métodos. Todos os testes de DHT usam o adaptador em -memória, tornando-os rápidos e determinísticos.</li> -<li><strong>Um stream por RPC</strong>: cada par requisição-resposta DHT usa um stream -bidirecional QUIC novo. Sem complexidade de multiplexação, sem bloqueio -head-of-line entre operações independentes. O QUIC trata a multiplexação no -nível da conexão.</li> -<li><strong>MessagePack em vez de Protobuf</strong>: codificação binária compacta sem geração -de código ou arquivos de esquema. Integração com serde significa que adicionar -um campo a uma mensagem é uma mudança de uma linha. Trade-off: sem garantias -de evolução de esquema embutidas, mas neste estágio velocidade importa mais.</li> -<li><strong>PoW em vez de stake ou reputação</strong>: uma identidade de nó custa ~256 hashes -BLAKE3. Isso roda em menos de um segundo em qualquer hardware, incluindo um -Raspberry Pi, mas gerar milhares de identidades para um ataque Sybil se torna -caro. Sem tokens, sem blockchain, sem dependências externas.</li> -<li><strong>Busca iterativa com atualização da tabela de roteamento</strong>: nós descobertos -são adicionados à tabela de roteamento conforme encontrados durante buscas -iterativas, seguindo o comportamento padrão do Kademlia. Isso garante que a -tabela de roteamento melhore organicamente conforme os nós interagem.</li> -</ul> -<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2> -<ul> -<li><strong>Fase 2: Replicação</strong> — Codificação de apagamento Reed-Solomon pela rede, -distribuição de fragmentos, loops de reparo automáticos, livro-razão de -reciprocidade bilateral (sem blockchain, sem tokens)</li> -<li><strong>Fase 3: API e Apps</strong> — App Flutter mobile/desktop via flutter_rust_bridge, -API GraphQL (async-graphql), nó WASM no navegador</li> -<li><strong>Fase 4: Resiliência e Escala</strong> — Assinaturas pós-quânticas ML-DSA, travessia -avançada de NAT, Compartilhamento de Segredo de Shamir para herdeiros, -empacotamento para Alpine/Arch/Debian/FreeBSD/OpenBSD, CI no SourceHut</li> -<li><strong>Fase 5: Exploração e Cultura</strong> — navegador público de tesseras, curadoria -institucional, integração genealógica, exportação para mídia física</li> -</ul> -<p>Os nós conseguem se encontrar. Em seguida, aprendem a manter vivas as memórias -uns dos outros.</p> - -</article> - - </main> - - <footer> - <p>© 2026 Tesseras Project. <a href="/atom.xml">News Feed</a> · <a href="https://git.sr.ht/~ijanc/tesseras">Source</a></p> - </footer> -</body> -</html> diff --git a/pt-br/news/phase1-basic-network/index.html.gz b/pt-br/news/phase1-basic-network/index.html.gz Binary files differdeleted file mode 100644 index 39240bd..0000000 --- a/pt-br/news/phase1-basic-network/index.html.gz +++ /dev/null diff --git a/pt-br/news/phase2-replication/index.html b/pt-br/news/phase2-replication/index.html deleted file mode 100644 index 40320b8..0000000 --- a/pt-br/news/phase2-replication/index.html +++ /dev/null @@ -1,213 +0,0 @@ -<!DOCTYPE html> -<html lang="pt-br"> -<head> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <title>Fase 2: Memórias Sobrevivem — Tesseras</title> - <meta name="description" content="Tesseras agora fragmenta, distribui e repara dados automaticamente pela rede usando codificação de apagamento Reed-Solomon e um livro-razão de reciprocidade bilateral."> - <!-- Open Graph --> - <meta property="og:type" content="article"> - <meta property="og:title" content="Fase 2: Memórias Sobrevivem"> - <meta property="og:description" content="Tesseras agora fragmenta, distribui e repara dados automaticamente pela rede usando codificação de apagamento Reed-Solomon e um livro-razão de reciprocidade bilateral."> - <meta property="og:image" content="https://tesseras.net/images/social.jpg"> - <meta property="og:image:width" content="1200"> - <meta property="og:image:height" content="630"> - <meta property="og:site_name" content="Tesseras"> - <!-- Twitter Card --> - <meta name="twitter:card" content="summary_large_image"> - <meta name="twitter:title" content="Fase 2: Memórias Sobrevivem"> - <meta name="twitter:description" content="Tesseras agora fragmenta, distribui e repara dados automaticamente pela rede usando codificação de apagamento Reed-Solomon e um livro-razão de reciprocidade bilateral."> - <meta name="twitter:image" content="https://tesseras.net/images/social.jpg"> - <link rel="stylesheet" href="https://tesseras.net/style.css?h=21f0f32121928ee5c690"> - - - <link rel="alternate" type="application/atom+xml" title="Tesseras" href="https://tesseras.net/atom.xml"> - - - <link rel="icon" type="image/png" sizes="32x32" href="https://tesseras.net/images/favicon.png?h=be4e123a23393b1a027d"> - -</head> -<body> - <header> - <h1> - <a href="https://tesseras.net/pt-br/"> - <img src="https://tesseras.net/images/logo-64.png?h=c1b8d0c4c5f93b49d40b" alt="Tesseras" width="40" height="40" class="logo"> - Tesseras - </a> - </h1> - <nav> - - <a href="https://tesseras.net/pt-br/about/">Sobre</a> - <a href="https://tesseras.net/pt-br/news/">Notícias</a> - <a href="https://tesseras.net/pt-br/releases/">Lançamentos</a> - <a href="https://tesseras.net/pt-br/faq/">FAQ</a> - <a href="https://tesseras.net/pt-br/subscriptions/">Inscrições</a> - <a href="https://tesseras.net/pt-br/contact/">Contato</a> - - </nav> - <nav class="lang-switch"> - - <a href="https://tesseras.net/news/phase2-replication/">English</a> | <strong>Português</strong> - - </nav> - </header> - - <main> - -<article> - <h2>Fase 2: Memórias Sobrevivem</h2> - <p class="news-date">2026-02-14</p> - <p>Uma tessera não está mais presa a uma única máquina. A Fase 2 entrega a camada -de replicação: os dados são divididos em fragmentos com codificação de -apagamento, distribuídos entre múltiplos pares e reparados automaticamente -quando nós ficam offline. Um livro-razão de reciprocidade bilateral garante -troca justa de armazenamento — sem blockchain, sem tokens.</p> -<h2 id="o-que-foi-construido">O que foi construído</h2> -<p><strong>tesseras-core</strong> (atualizado) — Novos tipos de domínio de replicação: -<code>FragmentPlan</code> (seleciona a camada de fragmentação baseada no tamanho da -tessera), <code>FragmentId</code> (hash da tessera + índice + contagem de shards + -checksum), <code>FragmentEnvelope</code> (fragmento com seus metadados para transporte na -rede), <code>FragmentationTier</code> (Small/Medium/Large), <code>Attestation</code> (prova de que um -nó possui um fragmento em um dado momento) e <code>ReplicateAck</code> (confirmação de -recebimento de fragmento). Três novas traits de porta definem os limites -hexagonais: <code>DhtPort</code> (encontrar pares, replicar fragmentos, solicitar -atestações, ping), <code>FragmentStore</code> (armazenar/ler/deletar/listar/verificar -fragmentos) e <code>ReciprocityLedger</code> (registrar trocas de armazenamento, consultar -saldos, encontrar melhores pares). O tamanho máximo de uma tessera é 1 GB.</p> -<p><strong>tesseras-crypto</strong> (atualizado) — O <code>ReedSolomonCoder</code> existente agora alimenta -a codificação de fragmentos. Os dados são divididos em shards, shards de -paridade são computados, e qualquer combinação de shards de dados pode -reconstruir o original — desde que o número de shards ausentes não exceda a -contagem de paridade.</p> -<p><strong>tesseras-storage</strong> (atualizado) — Dois novos adaptadores:</p> -<ul> -<li><code>FsFragmentStore</code> — armazena dados de fragmentos como arquivos em disco -(<code>{raiz}/{hash_tessera}/{indice:03}.shard</code>) com um índice de metadados SQLite -rastreando hash da tessera, índice do shard, contagem de shards, checksum e -tamanho em bytes. A verificação recalcula o hash BLAKE3 e compara com o -checksum armazenado.</li> -<li><code>SqliteReciprocityLedger</code> — contabilidade bilateral de armazenamento em -SQLite. Cada par tem uma linha rastreando bytes armazenados para eles e bytes -que eles armazenam para nós. A coluna <code>balance</code> é uma coluna gerada -(<code>bytes_they_store_for_us - bytes_stored_for_them</code>). UPSERT garante incremento -atômico dos contadores.</li> -</ul> -<p>Nova migração (<code>002_replication.sql</code>) adiciona tabelas para fragmentos, planos -de fragmentação, detentores, mapeamentos detentor-fragmento e saldos de -reciprocidade.</p> -<p><strong>tesseras-dht</strong> (atualizado) — Quatro novas variantes de mensagem: <code>Replicate</code> -(enviar um envelope de fragmento), <code>ReplicateAck</code> (confirmar recebimento), -<code>AttestRequest</code> (pedir a um nó que prove que possui os fragmentos de uma -tessera) e <code>AttestResponse</code> (retornar atestação com checksums e timestamp). O -engine trata essas mensagens em seu loop de despacho.</p> -<p><strong>tesseras-replication</strong> — O novo crate, com cinco módulos:</p> -<ul> -<li> -<p><em>Codificação de fragmentos</em> (<code>fragment.rs</code>): <code>encode_tessera()</code> seleciona a -camada de fragmentação baseada no tamanho e então chama a codificação -Reed-Solomon para as camadas Medium e Large. Três camadas:</p> -<ul> -<li><strong>Small</strong> (< 4 MB): replicação do arquivo inteiro para r=7 pares, sem -codificação de apagamento</li> -<li><strong>Medium</strong> (4–256 MB): 16 shards de dados + 8 de paridade, distribuídos -entre r=7 pares</li> -<li><strong>Large</strong> (≥ 256 MB): 48 shards de dados + 24 de paridade, distribuídos -entre r=7 pares</li> -</ul> -</li> -<li> -<p><em>Distribuição</em> (<code>distributor.rs</code>): filtragem de diversidade de sub-rede limita -pares por sub-rede /24 IPv4 (ou prefixo /48 IPv6) para evitar falhas -correlacionadas. Se todos os seus fragmentos caírem no mesmo rack, uma única -queda de energia os elimina.</p> -</li> -<li> -<p><em>Serviço</em> (<code>service.rs</code>): <code>ReplicationService</code> é o orquestrador. -<code>replicate_tessera()</code> codifica os dados, encontra os pares mais próximos via -DHT, aplica diversidade de sub-rede e distribui fragmentos em round-robin. -<code>receive_fragment()</code> valida o checksum BLAKE3, verifica o saldo de -reciprocidade (rejeita se o déficit do remetente exceder o limite -configurado), armazena o fragmento e atualiza o livro-razão. -<code>handle_attestation_request()</code> lista os fragmentos locais e calcula seus -checksums como prova de posse.</p> -</li> -<li> -<p><em>Reparo</em> (<code>repair.rs</code>): <code>check_tessera_health()</code> solicita atestações dos -detentores conhecidos, recorre ao ping para nós não responsivos, verifica a -integridade local dos fragmentos e retorna uma de três ações: <code>Healthy</code>, -<code>NeedsReplication { deficit }</code> ou <code>CorruptLocal { fragment_index }</code>. O loop de -reparo roda a cada 24 horas (com 2 horas de jitter) via <code>tokio::select!</code> com -integração de desligamento.</p> -</li> -<li> -<p><em>Configuração</em> (<code>config.rs</code>): <code>ReplicationConfig</code> com padrões para intervalo -de reparo (24h), jitter (2h), transferências simultâneas (4), espaço livre -mínimo (1 GB), tolerância de déficit (256 MB) e limite de armazenamento por -par (1 GB).</p> -</li> -</ul> -<p><strong>tesd</strong> (atualizado) — O daemon agora abre um banco de dados SQLite -(<code>db/tesseras.db</code>), executa migrações, cria instâncias de <code>FsFragmentStore</code>, -<code>SqliteReciprocityLedger</code> e <code>FsBlobStore</code>, envolve o engine DHT em um -<code>DhtPortAdapter</code>, constrói um <code>ReplicationService</code> e lança o loop de reparo como -tarefa em segundo plano com desligamento gracioso.</p> -<p><strong>Testes</strong> — 193 testes em todo o workspace:</p> -<ul> -<li>15 testes unitários em tesseras-replication (camadas de codificação de -fragmentos, validação de checksum, diversidade de sub-rede, verificações de -saúde do reparo, fluxos de recebimento/replicação do serviço)</li> -<li>3 testes de integração com armazenamento real (ciclo completo -codificar→distribuir→receber para tessera média, replicação de arquivo inteiro -para tessera pequena, rejeição de fragmento adulterado)</li> -<li>Testes usam SQLite em memória + diretório temporário para fragmentos com mocks -mockall para DHT e BlobStore</li> -<li>Zero avisos do clippy, formatação limpa</li> -</ul> -<h2 id="decisoes-de-arquitetura">Decisões de arquitetura</h2> -<ul> -<li><strong>Fragmentação em três camadas</strong>: arquivos pequenos não precisam de -codificação de apagamento — o overhead não compensa. Arquivos médios e grandes -recebem progressivamente mais shards de paridade. Isso evita desperdiçar -armazenamento em tesseras pequenas enquanto oferece redundância forte para as -grandes.</li> -<li><strong>Distribuição por push do dono</strong>: o dono da tessera codifica os fragmentos e -os envia aos pares, em vez dos pares puxarem. Isso simplifica o protocolo (sem -fase de negociação) e garante que os fragmentos são distribuídos -imediatamente.</li> -<li><strong>Reciprocidade bilateral sem consenso</strong>: cada nó rastreia seu próprio saldo -com cada par localmente. Sem livro-razão global, sem token, sem blockchain. Se -o par A armazena 500 MB para o par B, o par B deveria armazenar -aproximadamente 500 MB para o par A. Free riders perdem redundância -gradualmente — seus fragmentos são despriorizados para reparo, mas nunca -deletados.</li> -<li><strong>Diversidade de sub-rede</strong>: os fragmentos são espalhados por diferentes -sub-redes para sobreviver a falhas correlacionadas. Uma queda de datacenter -não deveria eliminar todas as cópias de uma tessera.</li> -<li><strong>Verificações de saúde por atestação primeiro</strong>: o loop de reparo pede aos -detentores que provem posse (atestação com checksums) antes de declarar uma -tessera degradada. Apenas quando a atestação falha é que ele recorre a um -simples ping. Isso detecta corrupção silenciosa de dados, não apenas partida -de nós.</li> -</ul> -<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2> -<ul> -<li><strong>Fase 3: API e Apps</strong> — App Flutter mobile/desktop via flutter_rust_bridge, -API GraphQL (async-graphql), nó WASM no navegador</li> -<li><strong>Fase 4: Resiliência e Escala</strong> — Assinaturas pós-quânticas ML-DSA, travessia -avançada de NAT, Compartilhamento de Segredo de Shamir para herdeiros, -empacotamento para Alpine/Arch/Debian/FreeBSD/OpenBSD, CI no SourceHut</li> -<li><strong>Fase 5: Exploração e Cultura</strong> — navegador público de tesseras, curadoria -institucional, integração genealógica, exportação para mídia física</li> -</ul> -<p>Os nós conseguem se encontrar e manter vivas as memórias uns dos outros. Em -seguida, damos às pessoas uma forma de segurar suas memórias nas mãos.</p> - -</article> - - </main> - - <footer> - <p>© 2026 Tesseras Project. <a href="/atom.xml">News Feed</a> · <a href="https://git.sr.ht/~ijanc/tesseras">Source</a></p> - </footer> -</body> -</html> diff --git a/pt-br/news/phase2-replication/index.html.gz b/pt-br/news/phase2-replication/index.html.gz Binary files differdeleted file mode 100644 index 7658f2c..0000000 --- a/pt-br/news/phase2-replication/index.html.gz +++ /dev/null diff --git a/pt-br/news/phase3-api-and-apps/index.html b/pt-br/news/phase3-api-and-apps/index.html deleted file mode 100644 index 57ea05e..0000000 --- a/pt-br/news/phase3-api-and-apps/index.html +++ /dev/null @@ -1,167 +0,0 @@ -<!DOCTYPE html> -<html lang="pt-br"> -<head> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <title>Fase 3: Memórias nas Suas Mãos — Tesseras</title> - <meta name="description" content="Tesseras agora tem um app Flutter e um nó Rust embarcado — qualquer pessoa pode criar e preservar memórias pelo celular."> - <!-- Open Graph --> - <meta property="og:type" content="article"> - <meta property="og:title" content="Fase 3: Memórias nas Suas Mãos"> - <meta property="og:description" content="Tesseras agora tem um app Flutter e um nó Rust embarcado — qualquer pessoa pode criar e preservar memórias pelo celular."> - <meta property="og:image" content="https://tesseras.net/images/social.jpg"> - <meta property="og:image:width" content="1200"> - <meta property="og:image:height" content="630"> - <meta property="og:site_name" content="Tesseras"> - <!-- Twitter Card --> - <meta name="twitter:card" content="summary_large_image"> - <meta name="twitter:title" content="Fase 3: Memórias nas Suas Mãos"> - <meta name="twitter:description" content="Tesseras agora tem um app Flutter e um nó Rust embarcado — qualquer pessoa pode criar e preservar memórias pelo celular."> - <meta name="twitter:image" content="https://tesseras.net/images/social.jpg"> - <link rel="stylesheet" href="https://tesseras.net/style.css?h=21f0f32121928ee5c690"> - - - <link rel="alternate" type="application/atom+xml" title="Tesseras" href="https://tesseras.net/atom.xml"> - - - <link rel="icon" type="image/png" sizes="32x32" href="https://tesseras.net/images/favicon.png?h=be4e123a23393b1a027d"> - -</head> -<body> - <header> - <h1> - <a href="https://tesseras.net/pt-br/"> - <img src="https://tesseras.net/images/logo-64.png?h=c1b8d0c4c5f93b49d40b" alt="Tesseras" width="40" height="40" class="logo"> - Tesseras - </a> - </h1> - <nav> - - <a href="https://tesseras.net/pt-br/about/">Sobre</a> - <a href="https://tesseras.net/pt-br/news/">Notícias</a> - <a href="https://tesseras.net/pt-br/releases/">Lançamentos</a> - <a href="https://tesseras.net/pt-br/faq/">FAQ</a> - <a href="https://tesseras.net/pt-br/subscriptions/">Inscrições</a> - <a href="https://tesseras.net/pt-br/contact/">Contato</a> - - </nav> - <nav class="lang-switch"> - - <a href="https://tesseras.net/news/phase3-api-and-apps/">English</a> | <strong>Português</strong> - - </nav> - </header> - - <main> - -<article> - <h2>Fase 3: Memórias nas Suas Mãos</h2> - <p class="news-date">2026-02-14</p> - <p>As pessoas agora podem segurar suas memórias nas próprias mãos. A Fase 3 entrega -o que as fases anteriores construíram: um app mobile onde alguém baixa o -Tesseras, cria uma identidade, tira uma foto, e aquela memória entra na rede de -preservação. Sem contas na nuvem, sem assinaturas, sem nenhuma empresa entre -você e suas memórias.</p> -<h2 id="o-que-foi-construido">O que foi construído</h2> -<p><strong>tesseras-embedded</strong> — Um nó P2P completo que roda dentro de um app mobile. A -struct <code>EmbeddedNode</code> é dona de um runtime Tokio, banco SQLite, transporte QUIC, -engine Kademlia DHT, serviço de replicação e serviço de tessera — a mesma stack -do daemon desktop, compilada como biblioteca compartilhada. Um padrão singleton -global (<code>Mutex<Option<EmbeddedNode>></code>) garante um único nó por ciclo de vida do -app. Ao iniciar, ele abre o banco de dados, executa migrações, carrega ou gera -uma identidade Ed25519 com proof-of-work para o node ID, faz bind QUIC numa -porta efêmera, conecta DHT e replicação, e inicia o loop de reparo. Ao parar, -envia um sinal de shutdown e drena graciosamente.</p> -<p>Onze funções FFI são expostas para Dart via flutter_rust_bridge: ciclo de vida -(<code>node_start</code>, <code>node_stop</code>, <code>node_is_running</code>), identidade (<code>create_identity</code>, -<code>get_identity</code>), memórias (<code>create_memory</code>, <code>get_timeline</code>, <code>get_memory</code>) e -status da rede (<code>get_network_stats</code>, <code>get_replication_status</code>). Todos os tipos -que cruzam a fronteira FFI são structs planas com apenas <code>String</code>, -<code>Option<String></code>, <code>Vec<String></code> e primitivos — sem trait objects, sem generics, -sem lifetimes.</p> -<p>Quatro módulos adaptadores fazem a ponte entre as ports do core e as -implementações concretas: <code>Blake3HasherAdapter</code>, -<code>Ed25519SignerAdapter</code>/<code>Ed25519VerifierAdapter</code> para criptografia, -<code>DhtPortAdapter</code> para operações DHT, e <code>ReplicationHandlerAdapter</code> para RPCs de -fragmentos e atestação recebidos.</p> -<p>A feature flag <code>bundled-sqlite</code> compila o SQLite a partir do código-fonte, -necessário para Android e iOS onde a biblioteca do sistema pode não estar -disponível. A configuração do Cargokit passa essa flag automaticamente em builds -de debug e release.</p> -<p><strong>App Flutter</strong> — Uma aplicação Material Design 3 com gerenciamento de estado -Riverpod, direcionada para Android, iOS, Linux, macOS e Windows a partir de uma -única base de código.</p> -<p>O <em>fluxo de onboarding</em> são três telas: uma tela de boas-vindas explicando o -projeto em uma frase ("Preserve suas memórias através dos milênios. Sem nuvem. -Sem empresa."), uma tela de criação de identidade que dispara a geração do par -de chaves Ed25519 em Rust, e uma tela de confirmação mostrando o nome do usuário -e a identidade criptográfica.</p> -<p>A <em>tela de timeline</em> exibe memórias em ordem cronológica reversa com previews de -imagem, texto de contexto e chips para tipo de memória e visibilidade. -Pull-to-refresh recarrega a partir do nó Rust. Um floating action button abre a -<em>tela de criação de memória</em>, que suporta seleção de foto da galeria ou câmera -via <code>image_picker</code>, texto de contexto opcional, dropdowns de tipo de memória e -visibilidade, e tags separadas por vírgula. Criar uma memória chama o FFI Rust -sincronamente, depois retorna à timeline.</p> -<p>A <em>tela de rede</em> mostra dois cards: status do nó (contagem de peers, tamanho da -DHT, estado de bootstrap, uptime) e saúde da replicação (total de fragmentos, -fragmentos saudáveis, fragmentos em reparo, fator de replicação). A <em>tela de -configurações</em> exibe a identidade do usuário — nome, node ID truncado, chave -pública truncada e data de criação.</p> -<p>Três providers Riverpod gerenciam o estado: <code>nodeProvider</code> inicia o nó embarcado -ao abrir o app usando o diretório de documentos e para ao fazer dispose; -<code>identityProvider</code> carrega o perfil existente ou cria um novo; -<code>timelineProvider</code> busca a lista de memórias com paginação.</p> -<p><strong>Testes</strong> — 9 testes unitários Rust em tesseras-embedded cobrindo ciclo de vida -do nó (start/stop sem panic), persistência de identidade entre reinícios, ciclos -de reinício sem corrupção do SQLite, streaming de eventos de rede, recuperação -de estatísticas, criação de memória e recuperação da timeline, e busca de -memória individual por hash. 2 testes Flutter: um teste de integração -verificando inicialização do Rust e startup do app, e um smoke test de widget.</p> -<h2 id="decisoes-de-arquitetura">Decisões de arquitetura</h2> -<ul> -<li><strong>Nó embarcado, não cliente-servidor</strong>: o celular roda a stack P2P completa, -não um thin client conversando com um daemon remoto. Isso significa que -memórias são preservadas mesmo sem internet. Usuários com um Raspberry Pi ou -VPS podem opcionalmente conectar o app ao seu daemon via GraphQL para maior -disponibilidade, mas não é obrigatório.</li> -<li><strong>FFI síncrono</strong>: todas as funções flutter_rust_bridge são marcadas como -<code>#[frb(sync)]</code> e bloqueiam no runtime Tokio interno. Isso simplifica o lado -Dart (sem complexidade de bridge assíncrono) enquanto o lado Rust lida com -concorrência internamente. A UI thread do Flutter permanece responsiva porque -o Riverpod envolve as chamadas em providers assíncronos.</li> -<li><strong>Singleton global</strong>: um global <code>Mutex<Option<EmbeddedNode>></code> garante que o -ciclo de vida do nó seja previsível — um start, um stop, sem race conditions. -Plataformas mobile matam processos agressivamente, então simplicidade no -gerenciamento de ciclo de vida é uma feature.</li> -<li><strong>Tipos FFI planos</strong>: nenhuma abstração Rust vaza pela fronteira FFI. Todo -tipo é uma struct plana com strings e números. Isso torna os bindings Dart -auto-gerados confiáveis e fáceis de debugar.</li> -<li><strong>Onboarding de três telas</strong>: a criação de identidade é o único passo -obrigatório. Sem email, sem senha, sem registro em servidor. O app gera uma -identidade criptográfica localmente e está pronto para uso.</li> -</ul> -<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2> -<ul> -<li><strong>Fase 4: Resiliência e Escala</strong> — NAT traversal avançado (STUN/TURN), -Shamir's Secret Sharing para herdeiros, tesseras seladas com criptografia -temporal, ajuste de performance, auditorias de segurança, empacotamento para -Alpine/Arch/Debian/FreeBSD/OpenBSD</li> -<li><strong>Fase 5: Exploração e Cultura</strong> — Navegador público de tesseras por -era/localização/tema/idioma, curadoria institucional, integração com -genealogia, exportação para mídia física (M-DISC, microfilme, papel livre de -ácido com QR)</li> -</ul> -<p>A infraestrutura está completa. A rede existe, a replicação funciona, e agora -qualquer pessoa com um celular pode participar. O que resta é fortalecer o que -temos e abrir para o mundo.</p> - -</article> - - </main> - - <footer> - <p>© 2026 Tesseras Project. <a href="/atom.xml">News Feed</a> · <a href="https://git.sr.ht/~ijanc/tesseras">Source</a></p> - </footer> -</body> -</html> diff --git a/pt-br/news/phase3-api-and-apps/index.html.gz b/pt-br/news/phase3-api-and-apps/index.html.gz Binary files differdeleted file mode 100644 index d9c466e..0000000 --- a/pt-br/news/phase3-api-and-apps/index.html.gz +++ /dev/null diff --git a/pt-br/news/phase4-encryption-sealed/index.html b/pt-br/news/phase4-encryption-sealed/index.html deleted file mode 100644 index 3cbd9bf..0000000 --- a/pt-br/news/phase4-encryption-sealed/index.html +++ /dev/null @@ -1,187 +0,0 @@ -<!DOCTYPE html> -<html lang="pt-br"> -<head> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <title>Fase 4: Criptografia e Tesseras Seladas — Tesseras</title> - <meta name="description" content="Tesseras agora suporta memórias privadas e seladas com criptografia híbrida pós-quântica — AES-256-GCM, X25519 + ML-KEM-768 e publicação de chaves com bloqueio temporal."> - <!-- Open Graph --> - <meta property="og:type" content="article"> - <meta property="og:title" content="Fase 4: Criptografia e Tesseras Seladas"> - <meta property="og:description" content="Tesseras agora suporta memórias privadas e seladas com criptografia híbrida pós-quântica — AES-256-GCM, X25519 + ML-KEM-768 e publicação de chaves com bloqueio temporal."> - <meta property="og:image" content="https://tesseras.net/images/social.jpg"> - <meta property="og:image:width" content="1200"> - <meta property="og:image:height" content="630"> - <meta property="og:site_name" content="Tesseras"> - <!-- Twitter Card --> - <meta name="twitter:card" content="summary_large_image"> - <meta name="twitter:title" content="Fase 4: Criptografia e Tesseras Seladas"> - <meta name="twitter:description" content="Tesseras agora suporta memórias privadas e seladas com criptografia híbrida pós-quântica — AES-256-GCM, X25519 + ML-KEM-768 e publicação de chaves com bloqueio temporal."> - <meta name="twitter:image" content="https://tesseras.net/images/social.jpg"> - <link rel="stylesheet" href="https://tesseras.net/style.css?h=21f0f32121928ee5c690"> - - - <link rel="alternate" type="application/atom+xml" title="Tesseras" href="https://tesseras.net/atom.xml"> - - - <link rel="icon" type="image/png" sizes="32x32" href="https://tesseras.net/images/favicon.png?h=be4e123a23393b1a027d"> - -</head> -<body> - <header> - <h1> - <a href="https://tesseras.net/pt-br/"> - <img src="https://tesseras.net/images/logo-64.png?h=c1b8d0c4c5f93b49d40b" alt="Tesseras" width="40" height="40" class="logo"> - Tesseras - </a> - </h1> - <nav> - - <a href="https://tesseras.net/pt-br/about/">Sobre</a> - <a href="https://tesseras.net/pt-br/news/">Notícias</a> - <a href="https://tesseras.net/pt-br/releases/">Lançamentos</a> - <a href="https://tesseras.net/pt-br/faq/">FAQ</a> - <a href="https://tesseras.net/pt-br/subscriptions/">Inscrições</a> - <a href="https://tesseras.net/pt-br/contact/">Contato</a> - - </nav> - <nav class="lang-switch"> - - <a href="https://tesseras.net/news/phase4-encryption-sealed/">English</a> | <strong>Português</strong> - - </nav> - </header> - - <main> - -<article> - <h2>Fase 4: Criptografia e Tesseras Seladas</h2> - <p class="news-date">2026-02-14</p> - <p>Algumas memórias não são para todos. Um diário privado, uma carta para ser -aberta em 2050, um segredo de família selado até que os netos tenham idade -suficiente. Até agora, toda tessera na rede era aberta. A Fase 4 muda isso: -Tesseras agora criptografa conteúdo privado e selado com um esquema -criptográfico híbrido projetado para resistir tanto a ataques clássicos quanto -quânticos.</p> -<p>O princípio continua o mesmo — criptografar o mínimo possível. Memórias públicas -precisam de disponibilidade, não de sigilo. Mas quando alguém cria uma tessera -privada ou selada, o conteúdo agora é trancado por criptografia AES-256-GCM com -chaves protegidas por um mecanismo híbrido de encapsulamento de chaves -combinando X25519 e ML-KEM-768. Ambos os algoritmos precisam ser quebrados para -acessar o conteúdo.</p> -<h2 id="o-que-foi-construido">O que foi construído</h2> -<p><strong>Encriptador AES-256-GCM</strong> (<code>tesseras-crypto/src/encryption.rs</code>) — Criptografia -simétrica de conteúdo com nonces aleatórios de 12 bytes e dados autenticados -associados (AAD). O AAD vincula o texto cifrado ao seu contexto: para tesseras -privadas, o hash do conteúdo é incluído; para tesseras seladas, tanto o hash do -conteúdo quanto o timestamp <code>open_after</code> são vinculados no AAD. Isso significa -que mover texto cifrado entre tesseras com datas de abertura diferentes causa -falha na decriptação — você não consegue enganar o sistema para abrir uma -memória selada antecipadamente trocando o texto cifrado para uma tessera com uma -data de selo anterior.</p> -<p><strong>Mecanismo Híbrido de Encapsulamento de Chaves</strong> (<code>tesseras-crypto/src/kem.rs</code>) -— Troca de chaves usando X25519 (Diffie-Hellman clássico em curva elíptica) -combinado com ML-KEM-768 (o KEM pós-quântico baseado em reticulados padronizado -pelo NIST, anteriormente Kyber). Ambos os segredos compartilhados são combinados -via <code>blake3::derive_key</code> com uma string de contexto fixa ("tesseras hybrid kem -v1") para produzir uma única chave de criptografia de conteúdo de 256 bits. Isso -segue a mesma filosofia "dual desde o início" das assinaturas duplas do projeto -(Ed25519 + ML-DSA): se qualquer algoritmo for quebrado no futuro, o outro ainda -protege o conteúdo.</p> -<p><strong>Envelope de Chave Selada</strong> (<code>tesseras-crypto/src/sealed.rs</code>) — Encapsula uma -chave de criptografia de conteúdo usando o KEM híbrido, para que apenas o dono -da tessera possa recuperá-la. O KEM produz uma chave de transporte, que é XORed -com a chave de conteúdo para produzir uma chave encapsulada armazenada junto ao -texto cifrado do KEM. Ao desselar, o dono decapsula o texto cifrado do KEM para -recuperar a chave de transporte, depois faz XOR novamente para recuperar a chave -de conteúdo.</p> -<p><strong>Publicação de Chave</strong> (<code>tesseras-crypto/src/sealed.rs</code>) — Um artefato assinado -independente para publicar a chave de conteúdo de uma tessera selada após a data -<code>open_after</code> ter passado. O dono assina a chave de conteúdo, o hash da tessera e -o timestamp de publicação com suas chaves duais (Ed25519, com placeholder -ML-DSA). O manifesto permanece imutável — a publicação da chave é um documento -separado. Outros nós verificam a assinatura contra a chave pública do dono antes -de usar a chave publicada para decriptar o conteúdo.</p> -<p><strong>EncryptionContext</strong> (<code>tesseras-core/src/enums.rs</code>) — Um tipo de domínio que -representa o contexto AAD para criptografia. Ele vive em tesseras-core e não em -tesseras-crypto porque é um conceito de domínio (não um detalhe de implementação -criptográfica). O método <code>to_aad_bytes()</code> produz serialização determinística: um -byte de tag (0x00 para Private, 0x01 para Sealed), seguido do hash de conteúdo -e, para Sealed, o timestamp <code>open_after</code> como i64 little-endian.</p> -<p><strong>Validação de domínio</strong> (<code>tesseras-core/src/service.rs</code>) — -<code>TesseraService::create()</code> agora rejeita tesseras Sealed e Private que não -fornecem chaves de criptografia. Esta é uma validação no nível de domínio: a -camada de serviço garante que você não pode criar uma memória selada sem a -maquinaria criptográfica para protegê-la. A mensagem de erro é clara: "missing -encryption keys for visibility sealed until 2050-01-01."</p> -<p><strong>Atualizações de tipos do core</strong> — <code>TesseraIdentity</code> agora inclui um campo -opcional <code>encryption_public: Option<HybridEncryptionPublic></code> contendo tanto as -chaves públicas X25519 quanto ML-KEM-768. <code>KeyAlgorithm</code> ganhou as variantes -<code>X25519</code> e <code>MlKem768</code>. O layout do sistema de arquivos de identidade agora -suporta <code>node.x25519.key</code>/<code>.pub</code> e <code>node.mlkem768.key</code>/<code>.pub</code>.</p> -<p><strong>Testes</strong> — 8 testes unitários para AES-256-GCM (roundtrip, chave errada, texto -cifrado adulterado, AAD errado, falha de decriptação cross-context, nonces -únicos, mais 2 testes baseados em propriedades para payloads arbitrários e -unicidade de nonces). 5 testes unitários para HybridKem (roundtrip, par de -chaves errado, X25519 adulterado, determinismo do KDF, mais 1 teste baseado em -propriedades). 4 testes unitários para SealedKeyEnvelope e KeyPublication. 2 -testes de integração cobrindo o ciclo de vida completo de tesseras seladas e -privadas: gerar chaves, criar chave de conteúdo, criptografar, selar, desselar, -decriptar, publicar chave e verificar — o ciclo completo.</p> -<h2 id="decisoes-de-arquitetura">Decisões de arquitetura</h2> -<ul> -<li><strong>KEM híbrido desde o início</strong>: X25519 + ML-KEM-768 segue a mesma filosofia -das assinaturas duplas. Não sabemos quais suposições criptográficas se -manterão ao longo dos milênios, então combinamos algoritmos clássicos e -pós-quânticos. O custo é ~1,2 KB de material de chave adicional por identidade -— trivial comparado às fotos e vídeos em uma tessera.</li> -<li><strong>BLAKE3 para KDF</strong>: ao invés de adicionar <code>hkdf</code> + <code>sha2</code> como novas -dependências, usamos <code>blake3::derive_key</code> com uma string de contexto fixa. O -modo de derivação de chaves do BLAKE3 é especificamente projetado para este -caso de uso, e o projeto já depende do BLAKE3 para hashing de conteúdo.</li> -<li><strong>Manifestos imutáveis</strong>: quando a data <code>open_after</code> de uma tessera selada -passa, a chave de conteúdo é publicada como um artefato assinado separado -(<code>KeyPublication</code>), não modificando o manifesto. Isso preserva a natureza -append-only e endereçada por conteúdo das tesseras. O manifesto foi assinado -no momento da criação e nunca muda.</li> -<li><strong>Vinculação AAD previne troca de texto cifrado</strong>: o <code>EncryptionContext</code> -vincula tanto o hash de conteúdo quanto (para tesseras seladas) o timestamp -<code>open_after</code> nos dados autenticados do AES-GCM. Um atacante que copie conteúdo -criptografado de uma tessera "selada até 2050" para uma tessera "selada até -2025" vai descobrir que a decriptação falha — o AAD não corresponde mais.</li> -<li><strong>Encapsulamento de chave por XOR</strong>: o envelope de chave selada usa um XOR -simples da chave de conteúdo com a chave de transporte derivada do KEM, ao -invés de uma camada adicional de AES-GCM. Como a chave de transporte é um -valor aleatório fresco do KEM e é usada exatamente uma vez, o XOR é -informação-teoricamente seguro para este caso de uso específico e evita -complexidade desnecessária.</li> -<li><strong>Validação de domínio, não validação de storage</strong>: a verificação de "chaves -de criptografia ausentes" vive em <code>TesseraService::create()</code>, não na camada de -storage. Isso segue o padrão de arquitetura hexagonal: regras de domínio são -aplicadas na fronteira de serviço, não espalhadas pelos adaptadores.</li> -</ul> -<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2> -<ul> -<li><strong>Fase 4 continuada: Resiliência e Escala</strong> — Shamir's Secret Sharing para -distribuição de chaves de herdeiros, NAT traversal avançado (STUN/TURN), -ajuste de performance, auditorias de segurança, empacotamento para sistemas -operacionais</li> -<li><strong>Fase 5: Exploração e Cultura</strong> — Navegador público de tesseras por -era/localização/tema/idioma, curadoria institucional, integração com -genealogia, exportação para mídia física (M-DISC, microfilme, papel livre de -ácido com QR)</li> -</ul> -<p>Tesseras seladas fazem do Tesseras uma verdadeira cápsula do tempo. Um pai agora -pode gravar uma mensagem para o neto que ainda não nasceu, selá-la até 2060 e -saber que o envelope criptográfico vai resistir — mesmo que os computadores -quânticos do futuro tentem abri-lo antes da hora.</p> - -</article> - - </main> - - <footer> - <p>© 2026 Tesseras Project. <a href="/atom.xml">News Feed</a> · <a href="https://git.sr.ht/~ijanc/tesseras">Source</a></p> - </footer> -</body> -</html> diff --git a/pt-br/news/phase4-encryption-sealed/index.html.gz b/pt-br/news/phase4-encryption-sealed/index.html.gz Binary files differdeleted file mode 100644 index b039bac..0000000 --- a/pt-br/news/phase4-encryption-sealed/index.html.gz +++ /dev/null diff --git a/pt-br/news/phase4-institutional-onboarding/index.html b/pt-br/news/phase4-institutional-onboarding/index.html deleted file mode 100644 index 023892c..0000000 --- a/pt-br/news/phase4-institutional-onboarding/index.html +++ /dev/null @@ -1,252 +0,0 @@ -<!DOCTYPE html> -<html lang="pt-br"> -<head> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <title>Fase 4: Onboarding de Nos Institucionais — Tesseras</title> - <meta name="description" content="Bibliotecas, arquivos e museus agora podem ingressar na rede Tesseras como nos institucionais verificados com identidade baseada em DNS, indices de busca full-text e compromissos configuraveis de armazenamento."> - <!-- Open Graph --> - <meta property="og:type" content="article"> - <meta property="og:title" content="Fase 4: Onboarding de Nos Institucionais"> - <meta property="og:description" content="Bibliotecas, arquivos e museus agora podem ingressar na rede Tesseras como nos institucionais verificados com identidade baseada em DNS, indices de busca full-text e compromissos configuraveis de armazenamento."> - <meta property="og:image" content="https://tesseras.net/images/social.jpg"> - <meta property="og:image:width" content="1200"> - <meta property="og:image:height" content="630"> - <meta property="og:site_name" content="Tesseras"> - <!-- Twitter Card --> - <meta name="twitter:card" content="summary_large_image"> - <meta name="twitter:title" content="Fase 4: Onboarding de Nos Institucionais"> - <meta name="twitter:description" content="Bibliotecas, arquivos e museus agora podem ingressar na rede Tesseras como nos institucionais verificados com identidade baseada em DNS, indices de busca full-text e compromissos configuraveis de armazenamento."> - <meta name="twitter:image" content="https://tesseras.net/images/social.jpg"> - <link rel="stylesheet" href="https://tesseras.net/style.css?h=21f0f32121928ee5c690"> - - - <link rel="alternate" type="application/atom+xml" title="Tesseras" href="https://tesseras.net/atom.xml"> - - - <link rel="icon" type="image/png" sizes="32x32" href="https://tesseras.net/images/favicon.png?h=be4e123a23393b1a027d"> - -</head> -<body> - <header> - <h1> - <a href="https://tesseras.net/pt-br/"> - <img src="https://tesseras.net/images/logo-64.png?h=c1b8d0c4c5f93b49d40b" alt="Tesseras" width="40" height="40" class="logo"> - Tesseras - </a> - </h1> - <nav> - - <a href="https://tesseras.net/pt-br/about/">Sobre</a> - <a href="https://tesseras.net/pt-br/news/">Notícias</a> - <a href="https://tesseras.net/pt-br/releases/">Lançamentos</a> - <a href="https://tesseras.net/pt-br/faq/">FAQ</a> - <a href="https://tesseras.net/pt-br/subscriptions/">Inscrições</a> - <a href="https://tesseras.net/pt-br/contact/">Contato</a> - - </nav> - <nav class="lang-switch"> - - <a href="https://tesseras.net/news/phase4-institutional-onboarding/">English</a> | <strong>Português</strong> - - </nav> - </header> - - <main> - -<article> - <h2>Fase 4: Onboarding de Nos Institucionais</h2> - <p class="news-date">2026-02-15</p> - <p>Uma rede P2P composta apenas por individuos e fragil. Discos rigidos morrem, -celulares sao perdidos, pessoas perdem interesse. A sobrevivencia a longo prazo -das memorias da humanidade depende de instituicoes — bibliotecas, arquivos, -museus, universidades — que medem seus tempos de vida em seculos. A Fase 4 -continua com o onboarding de nos institucionais: organizacoes verificadas agora -podem prometer armazenamento, manter indices de busca e participar da rede com -uma identidade distinta.</p> -<p>O design segue um principio de confiar mas verificar: instituicoes se -identificam via registros DNS TXT (o mesmo mecanismo usado por SPF, DKIM e DMARC -para email), prometem um orcamento de armazenamento e recebem isencoes de -reciprocidade para que possam armazenar fragmentos para outros sem esperar nada -em troca. Em contrapartida, a rede trata seus fragmentos como replicas de maior -qualidade e limita a dependencia excessiva de qualquer instituicao individual -atraves de restricoes de diversidade.</p> -<h2 id="o-que-foi-construido">O que foi construido</h2> -<p><strong>Bits de capacidade</strong> (<code>tesseras-core/src/network.rs</code>) — Dois novos flags -adicionados ao bitfield <code>Capabilities</code>: <code>INSTITUTIONAL</code> (bit 7) e <code>SEARCH_INDEX</code> -(bit 8). Um novo construtor <code>institutional_default()</code> retorna o conjunto -completo de capacidades da Fase 2 mais esses dois bits e <code>RELAY</code>. Nos normais -anunciam <code>phase2_default()</code> que nao inclui flags institucionais. Testes de -roundtrip de serializacao verificam que os novos bits sobrevivem a codificacao -MessagePack.</p> -<p><strong>Tipos de busca</strong> (<code>tesseras-core/src/search.rs</code>) — Tres novos tipos de dominio -para o subsistema de busca:</p> -<ul> -<li><code>SearchFilters</code> — parametros de consulta: <code>memory_type</code>, <code>visibility</code>, -<code>language</code>, <code>date_range</code>, <code>geo</code> (bounding box), <code>page</code>, <code>page_size</code></li> -<li><code>SearchHit</code> — um resultado individual: hash do conteudo mais um -<code>MetadataExcerpt</code> (titulo, descricao, tipo de memoria, data de criacao, -visibilidade, idioma, tags)</li> -<li><code>GeoFilter</code> — bounding box com <code>min_lat</code>, <code>max_lat</code>, <code>min_lon</code>, <code>max_lon</code> para -consultas espaciais</li> -</ul> -<p>Todos os tipos derivam <code>Serialize</code>/<code>Deserialize</code> para transporte e -<code>Clone</code>/<code>Debug</code> para diagnostico.</p> -<p><strong>Configuracao institucional do daemon</strong> (<code>tesd/src/config.rs</code>) — Uma nova secao -<code>[institutional]</code> no TOML com <code>domain</code> (o dominio DNS a verificar), -<code>pledge_bytes</code> (compromisso de armazenamento em bytes) e <code>search_enabled</code> -(toggle para o indice FTS5). O metodo <code>to_dht_config()</code> agora define -<code>Capabilities::institutional_default()</code> quando a configuracao institucional esta -presente, para que nos institucionais anunciem os bits de capacidade corretos em -respostas Pong.</p> -<p><strong>Verificacao DNS TXT</strong> (<code>tesd/src/institutional.rs</code>) — Resolucao DNS assincrona -usando <code>hickory-resolver</code> para verificar identidade institucional. O daemon -consulta registros TXT em <code>_tesseras.<dominio></code> e analisa campos chave-valor: -<code>v</code> (versao), <code>node</code> (node ID em hexadecimal) e <code>pledge</code> (compromisso de -armazenamento em bytes). A verificacao checa:</p> -<ol> -<li>Um registro TXT existe em <code>_tesseras.<dominio></code></li> -<li>O campo <code>node</code> corresponde ao node ID do proprio daemon</li> -<li>O campo <code>pledge</code> esta presente e e valido</li> -</ol> -<p>Na inicializacao, o daemon tenta a verificacao DNS. Se bem-sucedida, o no roda -com capacidades institucionais. Se falhar, o no registra um aviso e faz -downgrade para um no completo normal — sem crash, sem intervencao manual.</p> -<p><strong>Comando CLI de setup</strong> (<code>tesseras-cli/src/institutional.rs</code>) — Um novo -subcomando <code>institutional setup</code> que guia operadores pelo onboarding:</p> -<ol> -<li>Le a identidade do no a partir do diretorio de dados</li> -<li>Solicita nome de dominio e tamanho do pledge</li> -<li>Gera o registro DNS TXT exato a adicionar: -<code>v=tesseras1 node=<hex> pledge=<bytes></code></li> -<li>Escreve a secao institucional no arquivo de configuracao do daemon</li> -<li>Imprime os proximos passos: adicionar o registro TXT, reiniciar o daemon</li> -</ol> -<p><strong>Indice de busca SQLite</strong> (<code>tesseras-storage</code>) — Uma migracao -(<code>003_institutional.sql</code>) que cria tres estruturas:</p> -<ul> -<li><code>search_content</code> — uma tabela virtual FTS5 para busca full-text sobre -metadados de tesseras (titulo, descricao, criador, tags, idioma)</li> -<li><code>geo_index</code> — uma tabela virtual R-tree para consultas espaciais de bounding -box sobre latitude/longitude</li> -<li><code>geo_map</code> — uma tabela de mapeamento ligando IDs de linhas do R-tree a hashes -de conteudo</li> -</ul> -<p>O adaptador <code>SqliteSearchIndex</code> implementa o port trait <code>SearchIndex</code> com -<code>index_tessera()</code> (inserir/atualizar) e <code>search()</code> (consultar com filtros). -Consultas FTS5 suportam busca em linguagem natural; consultas geo usam -<code>INTERSECT</code> do R-tree para lookups de bounding box. Resultados sao ranqueados -por score de relevancia do FTS5.</p> -<p>A migracao tambem adiciona uma coluna <code>is_institutional</code> a tabela <code>reciprocity</code>, -tratada de forma idempotente via checagens <code>pragma_table_info</code> (o -<code>ALTER TABLE ADD COLUMN</code> do SQLite nao tem <code>IF NOT EXISTS</code>).</p> -<p><strong>Bypass de reciprocidade</strong> (<code>tesseras-replication/src/service.rs</code>) — Nos -institucionais sao isentos de checagens de reciprocidade. Quando -<code>receive_fragment()</code> e chamado, se o node ID do remetente esta marcado como -institucional no ledger de reciprocidade, a checagem de saldo e ignorada -completamente. Isso significa que instituicoes podem armazenar fragmentos para -toda a rede sem precisar "ganhar" creditos primeiro — sua identidade verificada -por DNS e compromisso de armazenamento servem como credencial.</p> -<p><strong>Restricao de diversidade por tipo de no</strong> -(<code>tesseras-replication/src/distributor.rs</code>) — Uma nova funcao -<code>apply_institutional_diversity()</code> limita quantas replicas de uma unica tessera -podem ir para nos institucionais. O limite e <code>ceil(fator_replicacao / 3.5)</code> — -com o padrao <code>r=7</code>, no maximo 2 de 7 replicas vao para instituicoes. Isso impede -que a rede se torne dependente de um pequeno numero de grandes instituicoes: se -os servidores de uma universidade cairem, pelo menos 5 replicas permanecem em -nos independentes.</p> -<p><strong>Extensoes de mensagens DHT</strong> (<code>tesseras-dht/src/message.rs</code>) — Duas novas -variantes de mensagem:</p> -<table><thead><tr><th>Mensagem</th><th>Proposito</th></tr></thead><tbody> -<tr><td><code>Search</code></td><td>Cliente envia string de consulta, filtros e numero da pagina</td></tr> -<tr><td><code>SearchResult</code></td><td>No institucional responde com resultados e contagem total</td></tr> -</tbody></table> -<p>A funcao <code>encode()</code> foi trocada de serializacao MessagePack posicional para -nomeada (<code>rmp_serde::to_vec_named</code>) para lidar corretamente com campos opcionais -de <code>SearchFilters</code> — a codificacao posicional quebra quando -<code>skip_serializing_if</code> omite campos.</p> -<p><strong>Metricas Prometheus</strong> (<code>tesd/src/metrics.rs</code>) — Oito metricas especificas -institucionais:</p> -<ul> -<li><code>tesseras_institutional_pledge_bytes</code> — compromisso de armazenamento -configurado</li> -<li><code>tesseras_institutional_stored_bytes</code> — bytes realmente armazenados</li> -<li><code>tesseras_institutional_pledge_utilization_ratio</code> — razao armazenado/prometido</li> -<li><code>tesseras_institutional_peers_served</code> — peers unicos que receberam fragmentos</li> -<li><code>tesseras_institutional_search_index_total</code> — tesseras no indice de busca</li> -<li><code>tesseras_institutional_search_queries_total</code> — consultas de busca recebidas</li> -<li><code>tesseras_institutional_dns_verification_status</code> — 1 se verificado por DNS, 0 -caso contrario</li> -<li><code>tesseras_institutional_dns_verification_last</code> — timestamp Unix da ultima -verificacao</li> -</ul> -<p><strong>Testes de integracao</strong> — Dois testes em -<code>tesseras-replication/tests/integration.rs</code>:</p> -<ul> -<li><code>institutional_peer_bypasses_reciprocity</code> — verifica que um peer institucional -com deficit massivo (-999.999 de saldo) ainda pode armazenar fragmentos, -enquanto um peer nao institucional com o mesmo deficit e rejeitado</li> -<li><code>institutional_node_accepts_fragment_despite_deficit</code> — teste async completo -usando <code>ReplicationService</code> com DHT, fragment store, reciprocity ledger e blob -store mockados: envia um fragmento de um remetente institucional e verifica -que e aceito</li> -</ul> -<p>322 testes passam em todo o workspace. Clippy limpo com <code>-D warnings</code>.</p> -<h2 id="decisoes-de-arquitetura">Decisoes de arquitetura</h2> -<ul> -<li><strong>DNS TXT ao inves de PKI ou blockchain</strong>: DNS e universalmente implantado, -universalmente compreendido e ja usado para verificacao de dominio (SPF, DKIM, -Let's Encrypt). Instituicoes ja gerenciam DNS. Nenhuma autoridade -certificadora, nenhum token, nenhuma transacao on-chain — apenas um registro -TXT. Se uma instituicao perder controle de seu dominio, a verificacao -naturalmente falha na proxima checagem.</li> -<li><strong>Degradacao graciosa em falha DNS</strong>: se a verificacao DNS falha na -inicializacao, o daemon faz downgrade para um no completo normal ao inves de -recusar iniciar. Isso previne incidentes operacionais — uma misconfiguracao -DNS nao deveria tirar um no do ar.</li> -<li><strong>Limite de diversidade em <code>ceil(r / 3.5)</code></strong>: com <code>r=7</code>, no maximo 2 replicas -vao para instituicoes. Isso e conservador — garante que a rede nunca dependa -de instituicoes para quorum majoritario, enquanto ainda se beneficia de sua -capacidade de armazenamento e uptime.</li> -<li><strong>Codificacao MessagePack nomeada</strong>: trocar de codificacao posicional para -nomeada adiciona ~15% de overhead por mensagem mas elimina uma classe de bugs -de serializacao quando campos opcionais estao presentes. O DHT nao e limitado -por largura de banda no nivel de mensagem, entao o tradeoff vale a pena.</li> -<li><strong>Isencao de reciprocidade ao inves de concessao de creditos</strong>: ao inves de -dar as instituicoes um saldo inicial grande de creditos (que e arbitrario e -precisa de ajuste), isentamos completamente. Sua identidade verificada por DNS -e compromisso publico de armazenamento substituem o mecanismo de reciprocidade -bilateral.</li> -<li><strong>FTS5 + R-tree no SQLite</strong>: busca full-text e indexacao espacial sao -embutidas no SQLite como extensoes carregaveis. Nenhum motor de busca externo -(Elasticsearch, Meilisearch) necessario. Isso mantem o deploy como um unico -binario com um unico arquivo de banco de dados — critico para operadores -institucionais que podem nao ter uma equipe de DevOps.</li> -</ul> -<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2> -<ul> -<li><strong>Fase 4 continuacao</strong> — deduplicacao de armazenamento (armazenamento -enderecavel por conteudo com BLAKE3), auditorias de seguranca, empacotamento -para OS (Alpine, Arch, Debian, OpenBSD, FreeBSD)</li> -<li><strong>Fase 5: Exploracao e Cultura</strong> — navegador publico de tesseras por -era/localizacao/tema/idioma, curadoria institucional, integracao genealogica -(FamilySearch, Ancestry), exportacao para midia fisica (M-DISC, microfilme, -papel livre de acido com QR), contexto assistido por IA</li> -</ul> -<p>O onboarding institucional fecha uma lacuna critica no modelo de preservacao do -Tesseras. Nos individuais fornecem resiliencia de base — milhares de -dispositivos ao redor do globo, cada um armazenando alguns fragmentos. Nos -institucionais fornecem ancoragem — organizacoes com infraestrutura -profissional, armazenamento redundante e horizontes operacionais de multiplas -decadas. Juntos, formam uma rede onde memorias podem sobreviver tanto a -dispositivos individuais quanto a instituicoes individuais.</p> - -</article> - - </main> - - <footer> - <p>© 2026 Tesseras Project. <a href="/atom.xml">News Feed</a> · <a href="https://git.sr.ht/~ijanc/tesseras">Source</a></p> - </footer> -</body> -</html> diff --git a/pt-br/news/phase4-institutional-onboarding/index.html.gz b/pt-br/news/phase4-institutional-onboarding/index.html.gz Binary files differdeleted file mode 100644 index 8d67e91..0000000 --- a/pt-br/news/phase4-institutional-onboarding/index.html.gz +++ /dev/null diff --git a/pt-br/news/phase4-nat-traversal/index.html b/pt-br/news/phase4-nat-traversal/index.html deleted file mode 100644 index 6b43a65..0000000 --- a/pt-br/news/phase4-nat-traversal/index.html +++ /dev/null @@ -1,238 +0,0 @@ -<!DOCTYPE html> -<html lang="pt-br"> -<head> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <title>Fase 4: Furando NATs — Tesseras</title> - <meta name="description" content="Os nos Tesseras agora podem descobrir seu tipo de NAT via STUN, coordenar UDP hole punching atraves de introdutores e usar relay transparente quando a conectividade direta falha."> - <!-- Open Graph --> - <meta property="og:type" content="article"> - <meta property="og:title" content="Fase 4: Furando NATs"> - <meta property="og:description" content="Os nos Tesseras agora podem descobrir seu tipo de NAT via STUN, coordenar UDP hole punching atraves de introdutores e usar relay transparente quando a conectividade direta falha."> - <meta property="og:image" content="https://tesseras.net/images/social.jpg"> - <meta property="og:image:width" content="1200"> - <meta property="og:image:height" content="630"> - <meta property="og:site_name" content="Tesseras"> - <!-- Twitter Card --> - <meta name="twitter:card" content="summary_large_image"> - <meta name="twitter:title" content="Fase 4: Furando NATs"> - <meta name="twitter:description" content="Os nos Tesseras agora podem descobrir seu tipo de NAT via STUN, coordenar UDP hole punching atraves de introdutores e usar relay transparente quando a conectividade direta falha."> - <meta name="twitter:image" content="https://tesseras.net/images/social.jpg"> - <link rel="stylesheet" href="https://tesseras.net/style.css?h=21f0f32121928ee5c690"> - - - <link rel="alternate" type="application/atom+xml" title="Tesseras" href="https://tesseras.net/atom.xml"> - - - <link rel="icon" type="image/png" sizes="32x32" href="https://tesseras.net/images/favicon.png?h=be4e123a23393b1a027d"> - -</head> -<body> - <header> - <h1> - <a href="https://tesseras.net/pt-br/"> - <img src="https://tesseras.net/images/logo-64.png?h=c1b8d0c4c5f93b49d40b" alt="Tesseras" width="40" height="40" class="logo"> - Tesseras - </a> - </h1> - <nav> - - <a href="https://tesseras.net/pt-br/about/">Sobre</a> - <a href="https://tesseras.net/pt-br/news/">Notícias</a> - <a href="https://tesseras.net/pt-br/releases/">Lançamentos</a> - <a href="https://tesseras.net/pt-br/faq/">FAQ</a> - <a href="https://tesseras.net/pt-br/subscriptions/">Inscrições</a> - <a href="https://tesseras.net/pt-br/contact/">Contato</a> - - </nav> - <nav class="lang-switch"> - - <a href="https://tesseras.net/news/phase4-nat-traversal/">English</a> | <strong>Português</strong> - - </nav> - </header> - - <main> - -<article> - <h2>Fase 4: Furando NATs</h2> - <p class="news-date">2026-02-15</p> - <p>A maioria dos dispositivos das pessoas ficam atras de um NAT — um tradutor de -enderecos de rede que permite acessar a internet mas impede conexoes de entrada. -Para uma rede P2P, isso e um problema existencial: se dois nos atras de NATs nao -conseguem se comunicar, a rede se fragmenta. A Fase 4 continua com uma pilha -completa de travessia de NAT: descoberta via STUN, hole punching coordenado e -fallback por relay.</p> -<p>A abordagem segue o mesmo padrao da maioria dos sistemas P2P consolidados -(WebRTC, BitTorrent, IPFS): tente a opcao mais barata primeiro, escale apenas -quando necessario. Conectividade direta nao custa nada. Hole punching custa -alguns pacotes coordenados. Relay custa largura de banda sustentada de um -terceiro. Tesseras tenta nessa ordem.</p> -<h2 id="o-que-foi-construido">O que foi construido</h2> -<p><strong>Classificacao NatType</strong> (<code>tesseras-core/src/network.rs</code>) — Um novo enum -<code>NatType</code> (Public, Cone, Symmetric, Unknown) adicionado a camada de dominio -core. Esse tipo e compartilhado por toda a pilha: o cliente STUN o escreve, o -DHT o divulga em mensagens Pong, e o coordenador de punch o le para decidir se -hole punching vale a pena tentar (Cone-para-Cone funciona ~80% das vezes; -Symmetric-para-Symmetric quase nunca funciona).</p> -<p><strong>Cliente STUN</strong> (<code>tesseras-net/src/stun.rs</code>) — Uma implementacao STUN minima -(RFC 5389 Binding Request/Response) que descobre o endereco externo de um no. O -codec codifica requisicoes de 20 bytes com um ID de transacao aleatorio e -decodifica respostas XOR-MAPPED-ADDRESS. A funcao <code>discover_nat()</code> consulta -multiplos servidores STUN em paralelo (Google, Cloudflare por padrao), compara -os enderecos mapeados e classifica o tipo de NAT:</p> -<ul> -<li>Mesmo IP e porta de todos os servidores → <strong>Public</strong> (sem NAT)</li> -<li>Mesmo endereco mapeado de todos os servidores → <strong>Cone</strong> (hole punching -funciona)</li> -<li>Enderecos mapeados diferentes → <strong>Symmetric</strong> (hole punching nao confiavel)</li> -<li>Sem respostas → <strong>Unknown</strong></li> -</ul> -<p>Retentativas com backoff exponencial e timeouts configuraveis. 12 testes -cobrindo roundtrips de codec, todos os caminhos de classificacao e consultas -async em loopback.</p> -<p><strong>Coordenacao de punch assinada</strong> (<code>tesseras-net/src/punch.rs</code>) — Assinatura e -verificacao Ed25519 para mensagens <code>PunchIntro</code>, <code>RelayRequest</code> e -<code>RelayMigrate</code>. Cada introducao e assinada pelo iniciador com uma janela de -timestamp de 30 segundos, prevenindo ataques de reflexao (onde um atacante -reproduz uma introducao antiga para redirecionar trafego). O formato do payload -e <code>target || external_addr || timestamp</code> — alterar qualquer campo invalida a -assinatura. 6 testes unitarios mais 3 testes baseados em propriedades com -proptest (IDs de no, portas e tokens de sessao arbitrarios).</p> -<p><strong>Gerenciador de sessoes de relay</strong> (<code>tesseras-net/src/relay.rs</code>) — Gerencia -sessoes de relay UDP transparente entre nos com NAT. Cada sessao tem um token -aleatorio de 16 bytes; os nos prefixam seus pacotes com o token, o relay remove -e encaminha. Funcionalidades:</p> -<ul> -<li>Encaminhamento bidirecional (A→R→B e B→R→A)</li> -<li>Limite de taxa: 256 KB/s para nos reciprocos, 64 KB/s para nao reciprocos</li> -<li>Duracao maxima de 10 minutos para sessoes bootstrap (nao reciprocas)</li> -<li>Migracao de endereco: quando o IP de um no muda (Wi-Fi para celular), um -<code>RelayMigrate</code> assinado atualiza a sessao sem derruba-la</li> -<li>Limpeza por inatividade com timeout configuravel</li> -<li>8 testes unitarios mais 2 testes baseados em propriedades</li> -</ul> -<p><strong>Extensoes de mensagens DHT</strong> (<code>tesseras-dht/src/message.rs</code>) — Sete novas -variantes de mensagem adicionadas ao protocolo DHT:</p> -<table><thead><tr><th>Mensagem</th><th>Proposito</th></tr></thead><tbody> -<tr><td><code>PunchIntro</code></td><td>"Quero conectar ao no X, aqui esta meu endereco externo assinado"</td></tr> -<tr><td><code>PunchRequest</code></td><td>O introdutor encaminha a requisicao ao destino</td></tr> -<tr><td><code>PunchReady</code></td><td>O destino confirma prontidao, envia seu endereco externo</td></tr> -<tr><td><code>RelayRequest</code></td><td>"Crie uma sessao de relay para o no X"</td></tr> -<tr><td><code>RelayOffer</code></td><td>O relay responde com seu endereco e token de sessao</td></tr> -<tr><td><code>RelayClose</code></td><td>Encerrar uma sessao de relay</td></tr> -<tr><td><code>RelayMigrate</code></td><td>Atualizar sessao apos mudanca de rede</td></tr> -</tbody></table> -<p>A mensagem <code>Pong</code> foi estendida com metadados NAT: <code>nat_type</code>, -<code>relay_slots_available</code> e <code>relay_bandwidth_used_kbps</code>. Todos os novos campos -usam <code>#[serde(default)]</code> para compatibilidade retroativa — nos antigos ignoram o -que nao reconhecem, nos novos usam defaults. 9 novos testes de roundtrip de -serializacao.</p> -<p><strong>Trait NatHandler e dispatch</strong> (<code>tesseras-dht/src/engine.rs</code>) — Uma nova trait -async <code>NatHandler</code> (5 metodos) injetada no engine DHT, seguindo o mesmo padrao -de injecao de dependencia do <code>ReplicationHandler</code> existente. O loop de dispatch -de mensagens do engine agora roteia todas as mensagens punch/relay para o -handler. Isso mantem o engine DHT agnóstico ao protocolo enquanto permite que a -logica de travessia de NAT viva em <code>tesseras-net</code>.</p> -<p><strong>Tipos de reconexao mobile</strong> (<code>tesseras-embedded/src/reconnect.rs</code>) — Uma -maquina de estados de reconexao em tres fases para dispositivos moveis:</p> -<ol> -<li><strong>QuicMigration</strong> (0-2s) — tenta migracao de conexao QUIC para todos os peers -ativos</li> -<li><strong>ReStun</strong> (2-5s) — redescobre endereco externo via STUN</li> -<li><strong>ReEstablish</strong> (5-10s) — reconecta peers que a migracao nao conseguiu salvar</li> -</ol> -<p>Peers sao reconectados em ordem de prioridade: nos bootstrap primeiro, depois -nos que guardam nossos fragmentos, depois nos cujos fragmentos guardamos, depois -vizinhos DHT gerais. Uma nova variante de evento <code>NetworkChanged</code> foi adicionada -ao stream de eventos FFI para que o app Flutter possa mostrar progresso de -reconexao.</p> -<p><strong>Configuracao NAT do daemon</strong> (<code>tesd/src/config.rs</code>) — Uma nova secao <code>[nat]</code> -na configuracao TOML com lista de servidores STUN, toggle de relay, maximo de -sessoes relay, limites de largura de banda (reciproco vs bootstrap) e timeout de -inatividade. Todos os campos tem defaults sensiveis; relay e desabilitado por -padrao.</p> -<p><strong>Metricas Prometheus</strong> (<code>tesseras-net/src/metrics.rs</code>) — 16 metricas em quatro -subsistemas:</p> -<ul> -<li><strong>STUN</strong>: requisicoes, falhas, histograma de latencia</li> -<li><strong>Punch</strong>: tentativas/sucessos/falhas (por par de tipo NAT), histograma de -latencia</li> -<li><strong>Relay</strong>: sessoes ativas, sessoes totais, bytes encaminhados, timeouts por -inatividade, hits de rate limit</li> -<li><strong>Reconexao</strong>: mudancas de rede, tentativas/sucessos por fase, histograma de -duracao</li> -</ul> -<p>6 testes verificando registro, incremento, cardinalidade de labels e deteccao de -registro duplo.</p> -<p><strong>Testes de integracao</strong> — Dois testes end-to-end usando <code>MemTransport</code> (rede -simulada em memoria):</p> -<ul> -<li><code>punch_integration.rs</code> — Fluxo completo de hole-punch com 3 nos: A envia -<code>PunchIntro</code> assinado ao introdutor I, I verifica e encaminha <code>PunchRequest</code> a -B, B verifica a assinatura original e envia <code>PunchReady</code> de volta, A e B -trocam mensagens diretamente. Tambem testa que uma assinatura invalida e -corretamente rejeitada.</li> -<li><code>relay_integration.rs</code> — Fluxo completo de relay com 3 nos: A solicita relay -de R, R cria sessao e envia <code>RelayOffer</code> a ambos os peers, A e B trocam -pacotes prefixados com token atraves de R, A migra para um novo endereco no -meio da sessao, A fecha a sessao, e o teste verifica que a sessao e encerrada -e encaminhamento posterior falha.</li> -</ul> -<p><strong>Testes de propriedade</strong> — 7 testes baseados em proptest cobrindo: roundtrips -de assinatura para todos os tres tipos de mensagem assinada (IDs de no, portas e -tokens arbitrarios), determinismo de classificacao NAT (mesmas entradas sempre -produzem mesma saida), validade de binding request STUN, unicidade de tokens de -sessao, e rejeicao de pacotes curtos pelo relay.</p> -<p><strong>Alvos Justfile</strong> — <code>just test-nat</code> executa todos os testes de travessia NAT em -<code>tesseras-net</code> e <code>tesseras-dht</code>. <code>just test-chaos</code> e um placeholder para futuros -testes de caos com Docker Compose e <code>tc netem</code>.</p> -<h2 id="decisoes-de-arquitetura">Decisoes de arquitetura</h2> -<ul> -<li><strong>STUN ao inves de TURN</strong>: implementamos STUN (descoberta) e relay customizado -ao inves de TURN completo. TURN requer alocacao autenticada e foi projetado -para relay de midia; nosso relay e mais simples — encaminhamento UDP com -prefixo de token e limites de taxa. Isso mantem o protocolo minimo e evita -depender de servidores TURN externos.</li> -<li><strong>Assinaturas em introducoes</strong>: cada <code>PunchIntro</code> e assinado pelo iniciador. -Sem isso, um atacante poderia enviar introducoes forjadas para redirecionar as -tentativas de hole-punch de um no para um endereco controlado pelo atacante -(ataque de reflexao). A janela de timestamp de 30 segundos limita replay.</li> -<li><strong>Tiers reciprocos de largura de banda</strong>: nos relay dao 4x mais largura de -banda (256 vs 64 KB/s) para peers com boas pontuacoes de reciprocidade. Isso -incentiva nos a armazenar fragmentos para outros — se voce contribui, recebe -melhor servico de relay quando precisa.</li> -<li><strong>Extensao Pong retrocompativel</strong>: novos campos NAT em <code>Pong</code> usam -<code>#[serde(default)]</code> e <code>Option<T></code>. Nos antigos que nao entendem esses campos -simplesmente os pulam durante deserializacao. Nenhum bump de versao de -protocolo necessario.</li> -<li><strong>NatHandler como trait async</strong>: a logica de travessia NAT e injetada no -engine DHT via trait, assim como <code>ReplicationHandler</code>. Isso mantem o engine -DHT focado em roteamento e gerenciamento de peers, e permite que a -implementacao NAT seja trocada ou desabilitada sem tocar no codigo core do -DHT.</li> -</ul> -<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2> -<ul> -<li><strong>Fase 4 continuacao</strong> — tuning de performance (pooling de conexoes, cache de -fragmentos, SQLite WAL), auditorias de seguranca, onboarding de nos -institucionais, empacotamento para OS</li> -<li><strong>Fase 5: Exploracao e Cultura</strong> — navegador publico de tesseras por -era/localizacao/tema/idioma, curadoria institucional, integracao genealogica, -exportacao para midia fisica (M-DISC, microfilme, papel livre de acido com QR)</li> -</ul> -<p>Com travessia de NAT, Tesseras pode conectar nos independentemente de sua -topologia de rede. Nos publicos conversam diretamente. Nos com NAT Cone furam -com ajuda de um introdutor. Nos com NAT Symmetric ou firewalled usam relay -atraves de peers voluntarios. A rede se adapta ao mundo real, onde a maioria dos -dispositivos esta atras de um NAT e as condicoes de rede mudam constantemente.</p> - -</article> - - </main> - - <footer> - <p>© 2026 Tesseras Project. <a href="/atom.xml">News Feed</a> · <a href="https://git.sr.ht/~ijanc/tesseras">Source</a></p> - </footer> -</body> -</html> diff --git a/pt-br/news/phase4-nat-traversal/index.html.gz b/pt-br/news/phase4-nat-traversal/index.html.gz Binary files differdeleted file mode 100644 index 6aa4bc7..0000000 --- a/pt-br/news/phase4-nat-traversal/index.html.gz +++ /dev/null diff --git a/pt-br/news/phase4-performance-tuning/index.html b/pt-br/news/phase4-performance-tuning/index.html deleted file mode 100644 index 528224d..0000000 --- a/pt-br/news/phase4-performance-tuning/index.html +++ /dev/null @@ -1,169 +0,0 @@ -<!DOCTYPE html> -<html lang="pt-br"> -<head> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <title>Fase 4: Tuning de Performance — Tesseras</title> - <meta name="description" content="SQLite em modo WAL com configuracao centralizada de pragmas, cache LRU de fragmentos, gerenciamento de ciclo de vida do pool de conexoes QUIC e otimizacao do hot path de atestacao."> - <!-- Open Graph --> - <meta property="og:type" content="article"> - <meta property="og:title" content="Fase 4: Tuning de Performance"> - <meta property="og:description" content="SQLite em modo WAL com configuracao centralizada de pragmas, cache LRU de fragmentos, gerenciamento de ciclo de vida do pool de conexoes QUIC e otimizacao do hot path de atestacao."> - <meta property="og:image" content="https://tesseras.net/images/social.jpg"> - <meta property="og:image:width" content="1200"> - <meta property="og:image:height" content="630"> - <meta property="og:site_name" content="Tesseras"> - <!-- Twitter Card --> - <meta name="twitter:card" content="summary_large_image"> - <meta name="twitter:title" content="Fase 4: Tuning de Performance"> - <meta name="twitter:description" content="SQLite em modo WAL com configuracao centralizada de pragmas, cache LRU de fragmentos, gerenciamento de ciclo de vida do pool de conexoes QUIC e otimizacao do hot path de atestacao."> - <meta name="twitter:image" content="https://tesseras.net/images/social.jpg"> - <link rel="stylesheet" href="https://tesseras.net/style.css?h=21f0f32121928ee5c690"> - - - <link rel="alternate" type="application/atom+xml" title="Tesseras" href="https://tesseras.net/atom.xml"> - - - <link rel="icon" type="image/png" sizes="32x32" href="https://tesseras.net/images/favicon.png?h=be4e123a23393b1a027d"> - -</head> -<body> - <header> - <h1> - <a href="https://tesseras.net/pt-br/"> - <img src="https://tesseras.net/images/logo-64.png?h=c1b8d0c4c5f93b49d40b" alt="Tesseras" width="40" height="40" class="logo"> - Tesseras - </a> - </h1> - <nav> - - <a href="https://tesseras.net/pt-br/about/">Sobre</a> - <a href="https://tesseras.net/pt-br/news/">Notícias</a> - <a href="https://tesseras.net/pt-br/releases/">Lançamentos</a> - <a href="https://tesseras.net/pt-br/faq/">FAQ</a> - <a href="https://tesseras.net/pt-br/subscriptions/">Inscrições</a> - <a href="https://tesseras.net/pt-br/contact/">Contato</a> - - </nav> - <nav class="lang-switch"> - - <a href="https://tesseras.net/news/phase4-performance-tuning/">English</a> | <strong>Português</strong> - - </nav> - </header> - - <main> - -<article> - <h2>Fase 4: Tuning de Performance</h2> - <p class="news-date">2026-02-15</p> - <p>Uma rede P2P que atravessa NATs mas engasga com seu proprio I/O nao serve de -muito. A Fase 4 continua com tuning de performance: centralizacao da -configuracao do banco de dados, cache de blobs de fragmentos em memoria, -gerenciamento de ciclo de vida de conexoes QUIC e eliminacao de leituras -desnecessarias de disco no hot path de atestacao.</p> -<p>O principio orientador foi o mesmo do resto do Tesseras: fazer a coisa mais -simples que realmente funciona. Sem alocadores customizados, sem estruturas de -dados lock-free, sem complexidade prematura. Um <code>StorageConfig</code> centralizado, um -cache LRU, um reaper de conexoes e uma correcao pontual para evitar reler blobs -que ja tinham checksum calculado.</p> -<h2 id="o-que-foi-construido">O que foi construido</h2> -<p><strong>Configuracao SQLite centralizada</strong> (<code>tesseras-storage/src/database.rs</code>) — Um -novo struct <code>StorageConfig</code> e funcoes <code>open_database()</code> / <code>open_in_memory()</code> que -aplicam todos os pragmas SQLite em um unico lugar: journal mode WAL, foreign -keys, modo synchronous (NORMAL por padrao, FULL para hardware instavel como -RPi + cartao SD), busy timeout, tamanho do cache de paginas e intervalo de -autocheckpoint WAL. Anteriormente, cada ponto de chamada abria uma conexao e -aplicava pragmas ad hoc. Agora o daemon, CLI e testes passam todos pelo mesmo -caminho. 7 testes cobrindo foreign keys, busy timeout, journal mode, migracoes, -modos synchronous e criacao de arquivos WAL em disco.</p> -<p><strong>Cache LRU de fragmentos</strong> (<code>tesseras-storage/src/cache.rs</code>) — Um -<code>CachedFragmentStore</code> que envolve qualquer <code>FragmentStore</code> com um cache LRU -ciente de bytes. Blobs de fragmentos sao cacheados na leitura e invalidados na -escrita ou exclusao. Quando o cache excede seu limite de bytes configurado, as -entradas menos recentemente usadas sao removidas. O cache e transparente: ele -proprio implementa <code>FragmentStore</code>, entao o resto da pilha nao sabe que esta la. -Metricas Prometheus opcionais rastreiam hits, misses e uso atual de bytes. 3 -testes: hit no cache evita leitura interna, store invalida cache, remocao quando -excede bytes maximos.</p> -<p><strong>Metricas Prometheus de storage</strong> (<code>tesseras-storage/src/metrics.rs</code>) — Um -struct <code>StorageMetrics</code> com tres contadores/gauges: <code>fragment_cache_hits</code>, -<code>fragment_cache_misses</code> e <code>fragment_cache_bytes</code>. Registrado no registry -Prometheus e conectado ao cache de fragmentos via <code>with_metrics()</code>.</p> -<p><strong>Correcao do hot path de atestacao</strong> (<code>tesseras-replication/src/service.rs</code>) — -O fluxo de atestacao anteriormente lia cada blob de fragmento do disco e -recalculava seu checksum BLAKE3. Como <code>list_fragments()</code> ja retorna <code>FragmentId</code> -com um checksum armazenado, a correcao e trivial: usar <code>frag.checksum</code> ao inves -de <code>blake3::hash(&data)</code>. Isso elimina uma leitura de disco por fragmento -durante atestacao — para uma tessera com 100 fragmentos, sao 100 leituras a -menos. Um teste com <code>expect_read_fragment().never()</code> verifica que nenhuma -leitura de blob acontece durante atestacao.</p> -<p><strong>Ciclo de vida do pool de conexoes QUIC</strong> -(<code>tesseras-net/src/quinn_transport.rs</code>) — Um struct <code>PoolConfig</code> controlando -maximo de conexoes, timeout de inatividade e intervalo do reaper. -<code>PooledConnection</code> envolve cada <code>quinn::Connection</code> com um timestamp -<code>last_used</code>. Quando o pool atinge capacidade maxima, a conexao inativa mais -antiga e removida antes de abrir uma nova. Uma tarefa reaper em background -(Tokio spawn) periodicamente fecha conexoes que ficaram inativas alem do -timeout. 4 novas metricas de pool: <code>tesseras_conn_pool_size</code>, <code>pool_hits_total</code>, -<code>pool_misses_total</code>, <code>pool_evictions_total</code>.</p> -<p><strong>Integracao no daemon</strong> (<code>tesd/src/config.rs</code>, <code>main.rs</code>) — Uma nova secao -<code>[performance]</code> na configuracao TOML com campos para tamanho de cache SQLite, -modo synchronous, busy timeout, tamanho de cache de fragmentos, maximo de -conexoes, timeout de inatividade e intervalo do reaper. O <code>main()</code> do daemon -agora chama <code>open_database()</code> com o <code>StorageConfig</code> configurado, envolve -<code>FsFragmentStore</code> com <code>CachedFragmentStore</code> e vincula QUIC com o <code>PoolConfig</code> -configurado. A dependencia direta de <code>rusqlite</code> foi removida do crate do daemon.</p> -<p><strong>Migracao do CLI</strong> (<code>tesseras-cli/src/commands/init.rs</code>, <code>create.rs</code>) — Ambos -os comandos <code>init</code> e <code>create</code> agora usam <code>tesseras_storage::open_database()</code> com -o <code>StorageConfig</code> padrao ao inves de abrir conexoes <code>rusqlite</code> diretamente. A -dependencia de <code>rusqlite</code> foi removida do crate do CLI.</p> -<h2 id="decisoes-de-arquitetura">Decisoes de arquitetura</h2> -<ul> -<li><strong>Padrao decorator para cache</strong>: <code>CachedFragmentStore</code> envolve -<code>Box<dyn FragmentStore></code> e implementa <code>FragmentStore</code> ele proprio. Isso -significa que cache e opt-in, composavel e invisivel para consumidores. O -daemon habilita; testes podem pular.</li> -<li><strong>Remocao ciente de bytes</strong>: o cache LRU rastreia bytes totais, nao contagem -de entradas. Blobs de fragmentos variam muito em tamanho (um fragmento de -texto de 4KB vs um shard de foto de 2MB), entao contar entradas daria uma -visao enganosa do uso de memoria.</li> -<li><strong>Sem crate de pool de conexoes</strong>: ao inves de trazer uma biblioteca generica -de pool, o pool de conexoes e um wrapper fino sobre -<code>DashMap<SocketAddr, PooledConnection></code> com um reaper Tokio. Conexoes QUIC sao -multiplexadas, entao o "pool" e realmente sobre gerenciamento de ciclo de vida -(limpeza de inativos, maximo de conexoes) e nao sobre emprestar/devolver.</li> -<li><strong>Checksums armazenados ao inves de releituras</strong>: a correcao de atestacao e -intencionalmente minima — uma linha alterada, uma leitura de disco removida -por fragmento. Os checksums ja estavam armazenados no SQLite por -<code>store_fragment()</code>, apenas nao estavam sendo usados.</li> -<li><strong>Configuracao centralizada de pragmas</strong>: um unico struct <code>StorageConfig</code> -substitui chamadas <code>PRAGMA</code> espalhadas. O flag <code>sqlite_synchronous_full</code> -existe especificamente para implantacoes em Raspberry Pi onde o kernel pode -crashar e perder transacoes WAL nao checkpointadas.</li> -</ul> -<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2> -<ul> -<li><strong>Fase 4 continuacao</strong> — Shamir's Secret Sharing para herdeiros, tesseras -seladas (criptografia time-lock), auditorias de seguranca, onboarding de nos -institucionais, deduplicacao de storage, empacotamento para OS</li> -<li><strong>Fase 5: Exploracao e Cultura</strong> — navegador publico de tesseras por -era/localizacao/tema/idioma, curadoria institucional, integracao genealogica, -exportacao para midia fisica (M-DISC, microfilme, papel livre de acido com QR)</li> -</ul> -<p>Com tuning de performance implementado, Tesseras lida com o caso comum de forma -eficiente: leituras de fragmentos acertam o cache LRU, atestacao pula I/O de -disco, conexoes QUIC inativas sao removidas automaticamente e o SQLite e -configurado consistentemente em toda a pilha. Os proximos passos focam em -funcionalidades criptograficas (Shamir, time-lock) e hardening para implantacao -em producao.</p> - -</article> - - </main> - - <footer> - <p>© 2026 Tesseras Project. <a href="/atom.xml">News Feed</a> · <a href="https://git.sr.ht/~ijanc/tesseras">Source</a></p> - </footer> -</body> -</html> diff --git a/pt-br/news/phase4-performance-tuning/index.html.gz b/pt-br/news/phase4-performance-tuning/index.html.gz Binary files differdeleted file mode 100644 index a0428ab..0000000 --- a/pt-br/news/phase4-performance-tuning/index.html.gz +++ /dev/null diff --git a/pt-br/news/phase4-shamir-heir-recovery/index.html b/pt-br/news/phase4-shamir-heir-recovery/index.html deleted file mode 100644 index d2df99f..0000000 --- a/pt-br/news/phase4-shamir-heir-recovery/index.html +++ /dev/null @@ -1,209 +0,0 @@ -<!DOCTYPE html> -<html lang="pt-br"> -<head> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <title>Fase 4: Recuperação de Chaves por Herdeiros com Shamir's Secret Sharing — Tesseras</title> - <meta name="description" content="Tesseras agora permite dividir sua identidade criptográfica em fragmentos distribuídos a herdeiros de confiança — qualquer limiar deles pode reconstruir suas chaves, mas menos que isso não revela nada."> - <!-- Open Graph --> - <meta property="og:type" content="article"> - <meta property="og:title" content="Fase 4: Recuperação de Chaves por Herdeiros com Shamir's Secret Sharing"> - <meta property="og:description" content="Tesseras agora permite dividir sua identidade criptográfica em fragmentos distribuídos a herdeiros de confiança — qualquer limiar deles pode reconstruir suas chaves, mas menos que isso não revela nada."> - <meta property="og:image" content="https://tesseras.net/images/social.jpg"> - <meta property="og:image:width" content="1200"> - <meta property="og:image:height" content="630"> - <meta property="og:site_name" content="Tesseras"> - <!-- Twitter Card --> - <meta name="twitter:card" content="summary_large_image"> - <meta name="twitter:title" content="Fase 4: Recuperação de Chaves por Herdeiros com Shamir's Secret Sharing"> - <meta name="twitter:description" content="Tesseras agora permite dividir sua identidade criptográfica em fragmentos distribuídos a herdeiros de confiança — qualquer limiar deles pode reconstruir suas chaves, mas menos que isso não revela nada."> - <meta name="twitter:image" content="https://tesseras.net/images/social.jpg"> - <link rel="stylesheet" href="https://tesseras.net/style.css?h=21f0f32121928ee5c690"> - - - <link rel="alternate" type="application/atom+xml" title="Tesseras" href="https://tesseras.net/atom.xml"> - - - <link rel="icon" type="image/png" sizes="32x32" href="https://tesseras.net/images/favicon.png?h=be4e123a23393b1a027d"> - -</head> -<body> - <header> - <h1> - <a href="https://tesseras.net/pt-br/"> - <img src="https://tesseras.net/images/logo-64.png?h=c1b8d0c4c5f93b49d40b" alt="Tesseras" width="40" height="40" class="logo"> - Tesseras - </a> - </h1> - <nav> - - <a href="https://tesseras.net/pt-br/about/">Sobre</a> - <a href="https://tesseras.net/pt-br/news/">Notícias</a> - <a href="https://tesseras.net/pt-br/releases/">Lançamentos</a> - <a href="https://tesseras.net/pt-br/faq/">FAQ</a> - <a href="https://tesseras.net/pt-br/subscriptions/">Inscrições</a> - <a href="https://tesseras.net/pt-br/contact/">Contato</a> - - </nav> - <nav class="lang-switch"> - - <a href="https://tesseras.net/news/phase4-shamir-heir-recovery/">English</a> | <strong>Português</strong> - - </nav> - </header> - - <main> - -<article> - <h2>Fase 4: Recuperação de Chaves por Herdeiros com Shamir's Secret Sharing</h2> - <p class="news-date">2026-02-15</p> - <p>O que acontece com suas memórias quando você morre? Até agora, Tesseras -conseguia preservar conteúdo ao longo de milênios — mas as chaves privadas e -seladas morriam com o dono. A Fase 4 continua com uma solução: Shamir's Secret -Sharing, um esquema criptográfico que permite dividir sua identidade em -fragmentos e distribuí-los para as pessoas em quem você mais confia.</p> -<p>A matemática é elegante: você escolhe um limiar T e um total N. Qualquer T -fragmentos reconstroem o segredo completo; T-1 fragmentos não revelam -absolutamente nada. Isso não é "quase nada" — é informação-teoricamente seguro. -Um atacante com um fragmento a menos que o limiar tem exatamente zero bits de -informação sobre o segredo, independentemente do poder computacional que tenha.</p> -<h2 id="o-que-foi-construido">O que foi construído</h2> -<p><strong>Aritmética de corpo finito GF(256)</strong> (<code>tesseras-crypto/src/shamir/gf256.rs</code>) — -Shamir's Secret Sharing requer aritmética em um corpo finito. Implementamos -GF(256) usando o mesmo polinômio irredutível do AES (x^8 + x^4 + x^3 + x + 1), -com tabelas de lookup para logaritmo e exponenciação computadas em tempo de -compilação. Todas as operações são em tempo constante via consulta a tabelas — -sem ramificações baseadas em dados secretos. O módulo inclui o método de Horner -para avaliação de polinômios e interpolação de Lagrange em x=0 para recuperação -do segredo. 233 linhas, exaustivamente testado: todos os 256 elementos para -propriedades de identidade/inverso, comutatividade e associatividade.</p> -<p><strong>ShamirSplitter</strong> (<code>tesseras-crypto/src/shamir/mod.rs</code>) — A API principal de -split/reconstruct. <code>split()</code> recebe uma fatia de bytes do segredo, uma -configuração (limiar T, total N) e a chave pública Ed25519 do dono. Para cada -byte do segredo, constrói um polinômio aleatório de grau T-1 sobre GF(256) com o -byte do segredo como termo constante, e então o avalia em N pontos distintos. -<code>reconstruct()</code> recebe T ou mais fragmentos e recupera o segredo via -interpolação de Lagrange. Ambas as operações incluem validação extensiva: -limites do limiar, consistência de sessão, correspondência de impressão digital -do dono e verificação de checksum BLAKE3.</p> -<p><strong>Formato HeirShare</strong> — Cada fragmento é um artefato autocontido e serializável -com:</p> -<ul> -<li>Versão do formato (v1) para compatibilidade futura</li> -<li>Índice do fragmento (1..N) e metadados de limiar/total</li> -<li>ID de sessão (8 bytes aleatórios) — impede mistura de fragmentos de sessões -diferentes</li> -<li>Impressão digital do dono (primeiros 8 bytes do hash BLAKE3 da chave pública -Ed25519)</li> -<li>Dados do fragmento (os y-values de Shamir, mesmo comprimento do segredo)</li> -<li>Checksum BLAKE3 sobre todos os campos anteriores</li> -</ul> -<p>Os fragmentos são serializados em dois formatos: <strong>MessagePack</strong> (binário -compacto, para uso programático) e <strong>texto base64</strong> (legível por humanos, para -impressão e armazenamento físico). O formato texto inclui um cabeçalho com -metadados e delimitadores:</p> -<pre><code>--- TESSERAS HEIR SHARE --- -Format: v1 -Owner: a1b2c3d4e5f6a7b8 (fingerprint) -Share: 1 of 3 (threshold: 2) -Session: 9f8e7d6c5b4a3210 -Created: 2026-02-15 - -<dados MessagePack codificados em base64> ---- END HEIR SHARE --- -</code></pre> -<p>Este formato é projetado para ser impresso em papel, armazenado em um cofre -bancário ou gravado em metal. O cabeçalho é informacional — apenas o payload -base64 é analisado durante a reconstrução.</p> -<p><strong>Integração com CLI</strong> (<code>tesseras-cli/src/commands/heir.rs</code>) — Três novos -subcomandos:</p> -<ul> -<li><code>tes heir create</code> — divide sua identidade Ed25519 em fragmentos de herdeiros. -Solicita confirmação (sua identidade completa está em jogo), gera arquivos -<code>.bin</code> e <code>.txt</code> para cada fragmento e escreve <code>heir_meta.json</code> no diretório de -identidade.</li> -<li><code>tes heir reconstruct</code> — carrega arquivos de fragmentos (detecta -automaticamente formato binário vs texto), valida consistência, reconstrói o -segredo, deriva o par de chaves Ed25519 e opcionalmente o instala em -<code>~/.tesseras/identity/</code> (com backup automático da identidade existente).</li> -<li><code>tes heir info</code> — exibe metadados do fragmento e verifica o checksum sem expor -nenhum material secreto.</li> -</ul> -<p><strong>Formato do blob secreto</strong> — As chaves de identidade são serializadas em um -blob versionado antes da divisão: um byte de versão (0x01), um byte de flags -(0x00 para somente Ed25519), seguido da chave secreta Ed25519 de 32 bytes. Isso -deixa espaço para expansão futura quando as chaves privadas X25519 e ML-KEM-768 -forem integradas ao sistema de fragmentos de herdeiros.</p> -<p><strong>Testes</strong> — 20 testes unitários para ShamirSplitter (roundtrip, todas as -combinações de fragmentos, fragmentos insuficientes, dono errado, sessão errada, -limite threshold-1, segredos grandes até o tamanho de chave ML-KEM-768). 7 -testes unitários para aritmética GF(256) (propriedades de campo exaustivas). 3 -testes baseados em propriedades com proptest (segredos arbitrários até 5000 -bytes, configurações T-de-N arbitrárias, verificação de segurança -informação-teórica). Testes de roundtrip de serialização para ambos os formatos -MessagePack e texto base64. 2 testes de integração cobrindo o ciclo de vida -completo de herdeiros: gerar identidade, dividir em fragmentos, serializar, -desserializar, reconstruir, verificar par de chaves e assinar/verificar com -chaves reconstruídas.</p> -<h2 id="decisoes-de-arquitetura">Decisões de arquitetura</h2> -<ul> -<li><strong>GF(256) ao invés de GF(primo)</strong>: usamos GF(256) ao invés de um corpo primo -porque ele mapeia naturalmente para bytes — cada elemento é um único byte, -cada fragmento tem o mesmo comprimento do segredo. Sem aritmética de inteiros -grandes, sem redução modular, sem padding. Esta é a mesma abordagem usada pela -maioria das implementações reais de Shamir, incluindo SSSS e Hashicorp Vault.</li> -<li><strong>Tabelas de lookup em tempo de compilação</strong>: as tabelas LOG e EXP para -GF(256) são computadas em tempo de compilação usando <code>const fn</code>. Isso -significa zero custo de inicialização em tempo de execução e operações em -tempo constante via consulta a tabelas ao invés de loops.</li> -<li><strong>ID de sessão previne mistura entre sessões</strong>: cada chamada a <code>split()</code> gera -um novo ID de sessão aleatório. Se um herdeiro acidentalmente usar fragmentos -de duas sessões diferentes de divisão (por exemplo, antes e depois de uma -rotação de chaves), a reconstrução falha de forma limpa com um erro de -validação ao invés de produzir dados corrompidos.</li> -<li><strong>Checksums BLAKE3 detectam corrupção</strong>: cada fragmento inclui um checksum -BLAKE3 sobre seu conteúdo. Isso captura degradação de bits, erros de -transmissão e truncamento acidental antes de qualquer tentativa de -reconstrução. Um fragmento impresso em papel e escaneado via OCR vai falhar no -checksum se um único caractere estiver errado.</li> -<li><strong>Impressão digital do dono para identificação</strong>: os fragmentos incluem os -primeiros 8 bytes de BLAKE3(chave pública Ed25519) como impressão digital. -Isso permite aos herdeiros verificar a qual identidade um fragmento pertence -sem revelar a chave pública completa. Durante a reconstrução, a impressão -digital é verificada contra a chave recuperada.</li> -<li><strong>Formato duplo para resiliência</strong>: ambos os formatos binário (MessagePack) e -texto (base64) são gerados porque mídias físicas têm modos de falha diferentes -de armazenamento digital. Um pendrive pode falhar; papel sobrevive. Um QR code -pode ficar ilegível; texto base64 pode ser digitado manualmente.</li> -<li><strong>Versionamento do blob</strong>: o segredo é envolvido em um blob versionado -(versão + flags + material de chave) para que versões futuras possam incluir -chaves adicionais (X25519, ML-KEM-768) sem quebrar compatibilidade com -fragmentos existentes.</li> -</ul> -<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2> -<ul> -<li><strong>Fase 4 continuada: Resiliência e Escala</strong> — NAT traversal avançado -(STUN/TURN), ajuste de performance (pool de conexões, cache de fragmentos, -SQLite WAL), auditorias de segurança, integração de nós institucionais, -empacotamento para sistemas operacionais</li> -<li><strong>Fase 5: Exploração e Cultura</strong> — navegador público de tesseras por -era/localização/tema/idioma, curadoria institucional, integração com -genealogia, exportação para mídia física (M-DISC, microfilme, papel livre de -ácido com QR)</li> -</ul> -<p>Com Shamir's Secret Sharing, Tesseras fecha a última lacuna crítica na -preservação a longo prazo. Suas memórias sobrevivem a falhas de infraestrutura -através de erasure coding. Sua privacidade sobrevive a computadores quânticos -através de criptografia híbrida. E agora, sua identidade sobrevive a você — -passada adiante para as pessoas que você escolheu, exigindo a cooperação delas -para desbloquear o que você deixou para trás.</p> - -</article> - - </main> - - <footer> - <p>© 2026 Tesseras Project. <a href="/atom.xml">News Feed</a> · <a href="https://git.sr.ht/~ijanc/tesseras">Source</a></p> - </footer> -</body> -</html> diff --git a/pt-br/news/phase4-shamir-heir-recovery/index.html.gz b/pt-br/news/phase4-shamir-heir-recovery/index.html.gz Binary files differdeleted file mode 100644 index cebcabc..0000000 --- a/pt-br/news/phase4-shamir-heir-recovery/index.html.gz +++ /dev/null diff --git a/pt-br/news/phase4-storage-deduplication/index.html b/pt-br/news/phase4-storage-deduplication/index.html deleted file mode 100644 index e927cfb..0000000 --- a/pt-br/news/phase4-storage-deduplication/index.html +++ /dev/null @@ -1,229 +0,0 @@ -<!DOCTYPE html> -<html lang="pt-br"> -<head> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <title>Fase 4: Deduplicacao de Armazenamento — Tesseras</title> - <meta name="description" content="Uma nova camada de armazenamento enderecavel por conteudo elimina dados duplicados entre tesseras, reduzindo uso de disco e habilitando coleta de lixo automatica."> - <!-- Open Graph --> - <meta property="og:type" content="article"> - <meta property="og:title" content="Fase 4: Deduplicacao de Armazenamento"> - <meta property="og:description" content="Uma nova camada de armazenamento enderecavel por conteudo elimina dados duplicados entre tesseras, reduzindo uso de disco e habilitando coleta de lixo automatica."> - <meta property="og:image" content="https://tesseras.net/images/social.jpg"> - <meta property="og:image:width" content="1200"> - <meta property="og:image:height" content="630"> - <meta property="og:site_name" content="Tesseras"> - <!-- Twitter Card --> - <meta name="twitter:card" content="summary_large_image"> - <meta name="twitter:title" content="Fase 4: Deduplicacao de Armazenamento"> - <meta name="twitter:description" content="Uma nova camada de armazenamento enderecavel por conteudo elimina dados duplicados entre tesseras, reduzindo uso de disco e habilitando coleta de lixo automatica."> - <meta name="twitter:image" content="https://tesseras.net/images/social.jpg"> - <link rel="stylesheet" href="https://tesseras.net/style.css?h=21f0f32121928ee5c690"> - - - <link rel="alternate" type="application/atom+xml" title="Tesseras" href="https://tesseras.net/atom.xml"> - - - <link rel="icon" type="image/png" sizes="32x32" href="https://tesseras.net/images/favicon.png?h=be4e123a23393b1a027d"> - -</head> -<body> - <header> - <h1> - <a href="https://tesseras.net/pt-br/"> - <img src="https://tesseras.net/images/logo-64.png?h=c1b8d0c4c5f93b49d40b" alt="Tesseras" width="40" height="40" class="logo"> - Tesseras - </a> - </h1> - <nav> - - <a href="https://tesseras.net/pt-br/about/">Sobre</a> - <a href="https://tesseras.net/pt-br/news/">Notícias</a> - <a href="https://tesseras.net/pt-br/releases/">Lançamentos</a> - <a href="https://tesseras.net/pt-br/faq/">FAQ</a> - <a href="https://tesseras.net/pt-br/subscriptions/">Inscrições</a> - <a href="https://tesseras.net/pt-br/contact/">Contato</a> - - </nav> - <nav class="lang-switch"> - - <a href="https://tesseras.net/news/phase4-storage-deduplication/">English</a> | <strong>Português</strong> - - </nav> - </header> - - <main> - -<article> - <h2>Fase 4: Deduplicacao de Armazenamento</h2> - <p class="news-date">2026-02-15</p> - <p>Quando multiplas tesseras compartilham a mesma foto, o mesmo clipe de audio ou -os mesmos dados de fragmento, a camada de armazenamento antiga mantinha copias -separadas de cada. Em um no armazenando milhares de tesseras para a rede, essa -duplicacao se acumula rapidamente. A Fase 4 continua com deduplicacao de -armazenamento: um armazenamento enderecavel por conteudo (CAS) que garante que -cada dado unico seja armazenado exatamente uma vez em disco, independentemente -de quantas tesseras o referenciam.</p> -<p>O design e simples e comprovado: hash do conteudo com BLAKE3, usar o hash como -nome do arquivo e manter uma contagem de referencias no SQLite. Quando duas -tesseras incluem a mesma foto de 5 MB, um arquivo existe em disco com -refcount 2. Quando uma tessera e deletada, o refcount cai para 1 e o arquivo -permanece. Quando a ultima referencia e liberada, uma varredura periodica limpa -o orfao.</p> -<h2 id="o-que-foi-construido">O que foi construido</h2> -<p><strong>Migracao do esquema CAS</strong> (<code>tesseras-storage/migrations/004_dedup.sql</code>) — Tres -novas tabelas:</p> -<ul> -<li><code>cas_objects</code> — rastreia cada objeto no armazenamento: hash BLAKE3 (chave -primaria), tamanho em bytes, contagem de referencias e timestamp de criacao</li> -<li><code>blob_refs</code> — mapeia identificadores logicos de blobs (hash da tessera + hash -da memoria + nome do arquivo) para hashes CAS, substituindo a convencao antiga -de caminhos no sistema de arquivos</li> -<li><code>fragment_refs</code> — mapeia identificadores logicos de fragmentos (hash da -tessera + indice do fragmento) para hashes CAS, substituindo o antigo layout -do diretorio <code>fragments/</code></li> -</ul> -<p>Indices nas colunas de hash garantem lookups O(1) durante leituras e contagem de -referencias.</p> -<p><strong>CasStore</strong> (<code>tesseras-storage/src/cas.rs</code>) — O motor central de armazenamento -enderecavel por conteudo. Arquivos sao armazenados sob um diretorio de prefixo -de dois niveis: <code><raiz>/<prefixo-hex-2-chars>/<hash-completo>.blob</code>. O -armazenamento fornece cinco operacoes:</p> -<ul> -<li><code>put(hash, data)</code> — escreve dados em disco se ainda nao presente, incrementa o -refcount. Retorna se ocorreu um hit de deduplicacao.</li> -<li><code>get(hash)</code> — le dados do disco pelo hash</li> -<li><code>release(hash)</code> — decrementa o refcount. Se chegar a zero, o arquivo em disco -e deletado imediatamente.</li> -<li><code>contains(hash)</code> — verifica existencia sem ler</li> -<li><code>ref_count(hash)</code> — retorna a contagem de referencias atual</li> -</ul> -<p>Todas as operacoes sao atomicas dentro de uma unica transacao SQLite. O refcount -e a fonte de verdade — se o refcount diz que o objeto existe, o arquivo deve -estar em disco.</p> -<p><strong>FsBlobStore com CAS</strong> (<code>tesseras-storage/src/blob.rs</code>) — Reescrito para -delegar todo armazenamento ao CAS. Quando um blob e escrito, seu hash BLAKE3 e -computado e passado para <code>cas.put()</code>. Uma linha em <code>blob_refs</code> mapeia o caminho -logico (tessera + memoria + arquivo) para o hash CAS. Leituras buscam o hash CAS -via <code>blob_refs</code> e leem de <code>cas.get()</code>. Deletar uma tessera libera todas as suas -referencias de blob em uma unica transacao.</p> -<p><strong>FsFragmentStore com CAS</strong> (<code>tesseras-storage/src/fragment.rs</code>) — Mesmo padrao -para fragmentos codificados com erasure coding. O checksum BLAKE3 de cada -fragmento ja e computado durante a codificacao Reed-Solomon, entao e usado -diretamente como chave CAS. A verificacao de fragmentos agora checa o hash CAS -ao inves de recomputar do zero — se o CAS diz que os dados estao intactos, -estao.</p> -<p><strong>Coletor de lixo sweep</strong> (<code>cas.rs:sweep()</code>) — Uma passagem periodica de GC que -trata tres casos limite que o caminho normal de refcount nao consegue:</p> -<ol> -<li><strong>Arquivos orfaos</strong> — arquivos em disco sem linha correspondente em -<code>cas_objects</code>. Pode acontecer apos um crash durante escrita. Arquivos com -menos de 1 hora sao pulados (periodo de graca para escritas em andamento); -orfaos mais antigos sao deletados.</li> -<li><strong>Refcounts vazados</strong> — linhas em <code>cas_objects</code> com refcount zero que nao -foram limpas (ex: se o processo morreu entre decrementar e deletar). Essas -linhas sao removidas.</li> -<li><strong>Idempotente</strong> — executar sweep duas vezes produz o mesmo resultado.</li> -</ol> -<p>O sweep e conectado ao loop de reparo existente em <code>tesseras-replication</code>, entao -roda automaticamente a cada 24 horas junto com as verificacoes de saude dos -fragmentos.</p> -<p><strong>Migracao do layout antigo</strong> (<code>tesseras-storage/src/migration.rs</code>) — Uma -estrategia de migracao copy-first que move dados do layout antigo baseado em -diretorios (<code>blobs/<tessera>/<memoria>/<arquivo></code> e -<code>fragments/<tessera>/<indice>.shard</code>) para o CAS. A migracao:</p> -<ol> -<li>Verifica a versao de armazenamento em <code>storage_meta</code> (versao 1 = layout -antigo, versao 2 = CAS)</li> -<li>Percorre os diretorios antigos <code>blobs/</code> e <code>fragments/</code></li> -<li>Computa hashes BLAKE3 e insere no CAS via <code>put()</code> — duplicatas sao -automaticamente deduplicadas</li> -<li>Cria entradas correspondentes em <code>blob_refs</code> / <code>fragment_refs</code></li> -<li>Remove diretorios antigos somente apos todos os dados estarem seguros no CAS</li> -<li>Atualiza a versao de armazenamento para 2</li> -</ol> -<p>A migracao roda na inicializacao do daemon, e idempotente (segura para -re-executar) e reporta estatisticas: arquivos migrados, duplicatas encontradas, -bytes economizados.</p> -<p><strong>Metricas Prometheus</strong> (<code>tesseras-storage/src/metrics.rs</code>) — Dez novas metricas -para observabilidade:</p> -<table><thead><tr><th>Metrica</th><th>Descricao</th></tr></thead><tbody> -<tr><td><code>cas_objects_total</code></td><td>Total de objetos unicos no CAS</td></tr> -<tr><td><code>cas_bytes_total</code></td><td>Total de bytes armazenados</td></tr> -<tr><td><code>cas_dedup_hits_total</code></td><td>Numero de escritas que encontraram um objeto existente</td></tr> -<tr><td><code>cas_bytes_saved_total</code></td><td>Bytes economizados por deduplicacao</td></tr> -<tr><td><code>cas_gc_refcount_deletions_total</code></td><td>Objetos deletados quando refcount chegou a zero</td></tr> -<tr><td><code>cas_gc_sweep_orphans_cleaned_total</code></td><td>Arquivos orfaos removidos pelo sweep</td></tr> -<tr><td><code>cas_gc_sweep_leaked_refs_cleaned_total</code></td><td>Linhas de refcount vazadas limpas</td></tr> -<tr><td><code>cas_gc_sweep_skipped_young_total</code></td><td>Orfaos jovens pulados (periodo de graca)</td></tr> -<tr><td><code>cas_gc_sweep_duration_seconds</code></td><td>Tempo gasto no sweep GC</td></tr> -</tbody></table> -<p><strong>Testes baseados em propriedades</strong> — Dois testes proptest verificam invariantes -do CAS sob entradas aleatorias:</p> -<ul> -<li><code>refcount_matches_actual_refs</code> — apos N operacoes aleatorias de put/release, o -refcount sempre corresponde ao numero real de referencias pendentes</li> -<li><code>cas_path_is_deterministic</code> — o mesmo hash sempre produz o mesmo caminho no -sistema de arquivos</li> -</ul> -<p><strong>Atualizacao de testes de integracao</strong> — Todos os testes de integracao em -<code>tesseras-core</code>, <code>tesseras-replication</code>, <code>tesseras-embedded</code> e <code>tesseras-cli</code> -atualizados para os novos construtores com CAS. Testes de deteccao de -adulteracao atualizados para funcionar com o layout de diretorio CAS.</p> -<p>347 testes passam em todo o workspace. Clippy limpo com <code>-D warnings</code>.</p> -<h2 id="decisoes-de-arquitetura">Decisoes de arquitetura</h2> -<ul> -<li><strong>BLAKE3 como chave CAS</strong>: o hash de conteudo que ja computamos para -verificacao de integridade serve tambem como chave de deduplicacao. Nenhuma -etapa adicional de hashing — o hash computado durante <code>create</code> ou <code>replicate</code> -e reutilizado como endereco CAS.</li> -<li><strong>Refcount SQLite ao inves de reflinks do sistema de arquivos</strong>: consideramos -usar copy-on-write no nivel do sistema de arquivos (reflinks em btrfs/XFS), -mas isso amarraria o Tesseras a sistemas de arquivos especificos. Refcounting -em SQLite funciona em qualquer sistema de arquivos, incluindo FAT32 em -pendrives baratos e ext4 em Raspberry Pis.</li> -<li><strong>Diretorios de prefixo hexadecimal de dois niveis</strong>: armazenar todos os -objetos CAS em um diretorio plano desaceleraria sistemas de arquivos com -milhoes de entradas. A divisao <code><prefixo 2 chars>/</code> limita qualquer diretorio -individual a ~65k entradas antes de um segundo nivel ser necessario. Isso -segue a abordagem usada pelo object store do Git.</li> -<li><strong>Periodo de graca para arquivos orfaos</strong>: o sweep GC pula arquivos com menos -de 1 hora para evitar deletar objetos sendo escritos por uma operacao -concorrente. Esta e uma escolha pragmatica — troca uma pequena janela de -potenciais orfaos por seguranca contra crashes sem exigir fsync ou commit de -duas fases.</li> -<li><strong>Migracao copy-first</strong>: a migracao copia dados para o CAS antes de remover -diretorios antigos. Se o processo for interrompido, os dados antigos -permanecem intactos e a migracao pode ser re-executada. Isso e mais lento que -mover arquivos mas garante zero perda de dados.</li> -<li><strong>Sweep no loop de reparo</strong>: ao inves de adicionar um timer separado de GC, o -sweep CAS aproveita o loop de reparo existente de 24 horas. Isso mantem o -daemon simples — um unico ciclo de manutencao em segundo plano cuida tanto da -saude dos fragmentos quanto da limpeza de armazenamento.</li> -</ul> -<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2> -<ul> -<li><strong>Fase 4 continuacao</strong> — auditorias de seguranca, empacotamento para OS -(Alpine, Arch, Debian, OpenBSD, FreeBSD)</li> -<li><strong>Fase 5: Exploracao e Cultura</strong> — navegador publico de tesseras por -era/localizacao/tema/idioma, curadoria institucional, integracao genealogica -(FamilySearch, Ancestry), exportacao para midia fisica (M-DISC, microfilme, -papel livre de acido com QR), contexto assistido por IA</li> -</ul> -<p>A deduplicacao de armazenamento completa a historia de eficiencia de -armazenamento do Tesseras. Um no que armazena fragmentos para milhares de -usuarios — comum para nos institucionais e nos completos sempre ligados — agora -paga o custo de disco apenas por dados unicos. Combinado com codificacao de -apagamento Reed-Solomon (que ja minimiza redundancia no nivel da rede), o -sistema alcanca armazenamento eficiente tanto nas camadas local quanto -distribuida.</p> - -</article> - - </main> - - <footer> - <p>© 2026 Tesseras Project. <a href="/atom.xml">News Feed</a> · <a href="https://git.sr.ht/~ijanc/tesseras">Source</a></p> - </footer> -</body> -</html> diff --git a/pt-br/news/phase4-storage-deduplication/index.html.gz b/pt-br/news/phase4-storage-deduplication/index.html.gz Binary files differdeleted file mode 100644 index 5e8ad15..0000000 --- a/pt-br/news/phase4-storage-deduplication/index.html.gz +++ /dev/null diff --git a/pt-br/news/phase4-wasm-browser-verification/index.html b/pt-br/news/phase4-wasm-browser-verification/index.html deleted file mode 100644 index da4605b..0000000 --- a/pt-br/news/phase4-wasm-browser-verification/index.html +++ /dev/null @@ -1,199 +0,0 @@ -<!DOCTYPE html> -<html lang="pt-br"> -<head> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <title>Fase 4: Verificar Sem Instalar Nada — Tesseras</title> - <meta name="description" content="Tesseras agora compila para WebAssembly — qualquer pessoa pode verificar integridade e autenticidade de uma tessera diretamente no navegador, sem instalar nenhum software."> - <!-- Open Graph --> - <meta property="og:type" content="article"> - <meta property="og:title" content="Fase 4: Verificar Sem Instalar Nada"> - <meta property="og:description" content="Tesseras agora compila para WebAssembly — qualquer pessoa pode verificar integridade e autenticidade de uma tessera diretamente no navegador, sem instalar nenhum software."> - <meta property="og:image" content="https://tesseras.net/images/social.jpg"> - <meta property="og:image:width" content="1200"> - <meta property="og:image:height" content="630"> - <meta property="og:site_name" content="Tesseras"> - <!-- Twitter Card --> - <meta name="twitter:card" content="summary_large_image"> - <meta name="twitter:title" content="Fase 4: Verificar Sem Instalar Nada"> - <meta name="twitter:description" content="Tesseras agora compila para WebAssembly — qualquer pessoa pode verificar integridade e autenticidade de uma tessera diretamente no navegador, sem instalar nenhum software."> - <meta name="twitter:image" content="https://tesseras.net/images/social.jpg"> - <link rel="stylesheet" href="https://tesseras.net/style.css?h=21f0f32121928ee5c690"> - - - <link rel="alternate" type="application/atom+xml" title="Tesseras" href="https://tesseras.net/atom.xml"> - - - <link rel="icon" type="image/png" sizes="32x32" href="https://tesseras.net/images/favicon.png?h=be4e123a23393b1a027d"> - -</head> -<body> - <header> - <h1> - <a href="https://tesseras.net/pt-br/"> - <img src="https://tesseras.net/images/logo-64.png?h=c1b8d0c4c5f93b49d40b" alt="Tesseras" width="40" height="40" class="logo"> - Tesseras - </a> - </h1> - <nav> - - <a href="https://tesseras.net/pt-br/about/">Sobre</a> - <a href="https://tesseras.net/pt-br/news/">Notícias</a> - <a href="https://tesseras.net/pt-br/releases/">Lançamentos</a> - <a href="https://tesseras.net/pt-br/faq/">FAQ</a> - <a href="https://tesseras.net/pt-br/subscriptions/">Inscrições</a> - <a href="https://tesseras.net/pt-br/contact/">Contato</a> - - </nav> - <nav class="lang-switch"> - - <a href="https://tesseras.net/news/phase4-wasm-browser-verification/">English</a> | <strong>Português</strong> - - </nav> - </header> - - <main> - -<article> - <h2>Fase 4: Verificar Sem Instalar Nada</h2> - <p class="news-date">2026-02-15</p> - <p>Confiança não deveria exigir instalação de software. Se alguém te envia uma -tessera — um pacote de memórias preservadas — você deveria poder verificar que é -genuína e não foi modificada sem baixar um app, criar uma conta, ou confiar em -um servidor. É isso que o <code>tesseras-wasm</code> entrega: arraste um arquivo tessera -para uma página web, e a verificação criptográfica acontece inteiramente no seu -navegador.</p> -<h2 id="o-que-foi-construido">O que foi construído</h2> -<p><strong>tesseras-wasm</strong> — Um crate Rust que compila para WebAssembly via wasm-pack, -expondo quatro funções stateless para JavaScript. O crate depende do -<code>tesseras-core</code> para parsing do manifesto e chama primitivas criptográficas -diretamente (blake3, ed25519-dalek) ao invés de depender do <code>tesseras-crypto</code>, -que puxa bibliotecas pós-quânticas baseadas em C que não compilam para -<code>wasm32-unknown-unknown</code>.</p> -<p><code>parse_manifest</code> recebe os bytes brutos do MANIFEST (texto UTF-8 plano, não -MessagePack), delega para <code>tesseras_core::manifest::Manifest::parse()</code>, e -retorna uma string JSON com a chave pública Ed25519 do criador, caminhos dos -arquivos de assinatura, e uma lista de arquivos com seus hashes BLAKE3 -esperados, tamanhos e tipos MIME. Structs internas (<code>ManifestJson</code>, -<code>CreatorPubkey</code>, <code>SignatureFiles</code>, <code>FileEntry</code>) são serializadas com serde_json. -Os campos de chave pública ML-DSA e arquivo de assinatura estão presentes no -contrato JSON mas definidos como <code>null</code> — prontos para quando a assinatura -pós-quântica for implementada no lado nativo.</p> -<p><code>hash_blake3</code> computa um hash BLAKE3 de bytes arbitrários e retorna uma string -hexadecimal de 64 caracteres. É chamada uma vez por arquivo na tessera para -verificar integridade contra o MANIFEST.</p> -<p><code>verify_ed25519</code> recebe uma mensagem, uma assinatura de 64 bytes e uma chave -pública de 32 bytes, constrói uma <code>ed25519_dalek::VerifyingKey</code>, e retorna se a -assinatura é válida. A validação de comprimento retorna erros descritivos -("Ed25519 public key must be 32 bytes") ao invés de causar panic.</p> -<p><code>verify_ml_dsa</code> é um stub que retorna um erro explicando que verificação ML-DSA -ainda não está disponível. Isso é deliberado: o crate <code>ml-dsa</code> no crates.io está -na v0.1.0-rc.7 (pré-release), e o <code>tesseras-crypto</code> usa <code>pqcrypto-dilithium</code> -(CRYSTALS-Dilithium baseado em C) que é incompatível em nível de bytes com FIPS -204 ML-DSA. Ambos os lados precisam usar a mesma implementação em Rust puro -antes que a verificação cruzada funcione. Verificação Ed25519 é suficiente — -toda tessera é assinada com Ed25519.</p> -<p>Todas as quatro funções usam um padrão de duas camadas para testabilidade: -funções internas retornam <code>Result<T, String></code> e são testadas nativamente, -enquanto wrappers finos <code>#[wasm_bindgen]</code> convertem erros para <code>JsError</code>. Isso -evita que <code>JsError::new()</code> cause panic em targets não-WASM durante os testes.</p> -<p>O binário WASM compilado tem 109 KB bruto e 44 KB com gzip — bem abaixo do -orçamento de 200 KB. O wasm-opt aplica otimização <code>-Oz</code> após o wasm-pack -compilar com <code>opt-level = "z"</code>, LTO e uma única unidade de codegen.</p> -<p><strong>@tesseras/verify</strong> — Um pacote npm TypeScript (<code>crates/tesseras-wasm/js/</code>) que -orquestra a verificação no lado do navegador. A API pública é uma única função:</p> -<pre><code data-lang="typescript">async function verifyTessera( - archive: Uint8Array, - onProgress?: (current: number, total: number, file: string) => void -): Promise<VerificationResult> -</code></pre> -<p>O tipo <code>VerificationResult</code> fornece tudo que uma UI precisa: validade geral, -hash da tessera, chaves públicas do criador, status das assinaturas -(valid/invalid/missing para Ed25519 e ML-DSA), resultados de integridade por -arquivo com hashes esperados e reais, uma lista de arquivos inesperados não -presentes no MANIFEST, e um array de erros.</p> -<p>A descompactação de arquivos (<code>unpack.ts</code>) lida com três formatos: tar -comprimido com gzip (detectado pelos magic bytes <code>\x1f\x8b</code>, descomprimido com -fflate e depois parseado como tar), ZIP (magic <code>PK\x03\x04</code>, descompactado com -<code>unzipSync</code> do fflate), e tar bruto (<code>ustar</code> no offset 257). Uma função -<code>normalizePath</code> remove o prefixo <code>tessera-<hash>/</code> para que os caminhos internos -correspondam às entradas do MANIFEST.</p> -<p>A verificação roda em um Web Worker (<code>worker.ts</code>) para manter a thread da UI -responsiva. O worker inicializa o módulo WASM, descompacta o arquivo, parseia o -MANIFEST, verifica a assinatura Ed25519 contra a chave pública do criador, -depois faz hash de cada arquivo com BLAKE3 e compara com os valores esperados. -Mensagens de progresso são transmitidas de volta para a thread principal após -cada arquivo. Se qualquer assinatura é inválida, a verificação para -imediatamente sem fazer hash dos arquivos — falhando rápido na verificação mais -crítica.</p> -<p>O arquivo é transferido para o worker com zero-copy -(<code>worker.postMessage({ type: "verify", archive }, [archive.buffer])</code>) para -evitar duplicar arquivos de tessera potencialmente grandes na memória.</p> -<p><strong>Pipeline de build</strong> — Três novos targets no justfile: <code>wasm-build</code> executa -wasm-pack com <code>--target web --release</code> e otimiza com wasm-opt; <code>wasm-size</code> -reporta o tamanho do binário bruto e com gzip; <code>test-wasm</code> executa a suíte de -testes nativos.</p> -<p><strong>Testes</strong> — 9 testes unitários nativos cobrem hashing BLAKE3 (entrada vazia, -valor conhecido), verificação Ed25519 (assinatura válida, assinatura inválida, -chave errada, comprimento de chave inválido), e parsing do MANIFEST (manifesto -válido, UTF-8 inválido, lixo). 3 testes de integração WASM rodam em Chrome -headless via <code>wasm-pack test --headless --chrome</code>, verificando que -<code>hash_blake3</code>, <code>verify_ed25519</code> e <code>parse_manifest</code> funcionam corretamente quando -compilados para <code>wasm32-unknown-unknown</code>.</p> -<h2 id="decisoes-de-arquitetura">Decisões de arquitetura</h2> -<ul> -<li><strong>Sem dependência do tesseras-crypto</strong>: o crate WASM chama blake3 e -ed25519-dalek diretamente. O <code>tesseras-crypto</code> depende do <code>pqcrypto-kyber</code> -(ML-KEM baseado em C via pqcrypto-traits) que requer um toolchain de -compilador C e não tem target wasm32. Dependendo apenas de crates Rust puros, -o build WASM tem zero dependências C e compila sem problemas para WebAssembly.</li> -<li><strong>ML-DSA adiado, não fingido</strong>: ao invés de silenciosamente pular a -verificação pós-quântica, o stub retorna um erro explícito. Isso garante que -se uma tessera contiver uma assinatura ML-DSA, o resultado da verificação -reportará <code>ml_dsa: "missing"</code> ao invés de fingir que foi verificada. O -orquestrador JS lida com isso graciosamente — uma tessera é válida se Ed25519 -passar e ML-DSA estiver ausente (ainda não implementado em nenhum dos lados).</li> -<li><strong>Padrão de função interna</strong>: <code>JsError</code> não pode ser construído em targets -não-WASM (causa panic). Dividir cada função em -<code>foo_inner() -> Result<T, String></code> e <code>foo() -> Result<T, JsError></code> permite que -a suíte de testes nativa exercite toda a lógica sem tocar em tipos JavaScript. -Os testes de integração WASM em Chrome headless testam a superfície completa -do <code>#[wasm_bindgen]</code>.</li> -<li><strong>Isolamento em Web Worker</strong>: operações criptográficas (especialmente BLAKE3 -sobre arquivos de mídia grandes) podem levar centenas de milissegundos. Rodar -em um Worker previne travamentos na UI. O protocolo de progresso com streaming -(<code>{ type: "progress", current, total, file }</code>) permite que a UI mostre uma -barra de progresso durante a verificação de tesseras com muitos arquivos.</li> -<li><strong>Transferência zero-copy</strong>: <code>archive.buffer</code> é transferido para o Worker, não -copiado. Para um arquivo tessera de 50 MB, isso evita dobrar o uso de memória -durante a verificação.</li> -<li><strong>MANIFEST em texto plano, não MessagePack</strong>: o crate WASM parseia o mesmo -formato de MANIFEST em texto plano que o CLI. Isso é por design — o MANIFEST é -a Pedra de Rosetta da tessera, legível por qualquer pessoa com um editor de -texto. A dependência <code>rmp-serde</code> no Cargo.toml não é usada e será removida.</li> -</ul> -<h2 id="o-que-vem-a-seguir">O que vem a seguir</h2> -<ul> -<li><strong>Fase 4: Resiliência e Escala</strong> — Empacotamento para sistemas operacionais -(Alpine, Arch, Debian, FreeBSD, OpenBSD), CI no SourceHut e GitHub Actions, -auditorias de segurança, explorador de tesseras no navegador em tesseras.net -usando @tesseras/verify</li> -<li><strong>Fase 5: Exploração e Cultura</strong> — Navegador público de tesseras por -era/localização/tema/idioma, curadoria institucional, integração com -genealogia, exportação para mídia física (M-DISC, microfilme, papel livre de -ácido com QR)</li> -</ul> -<p>A verificação não exige mais confiança em software. Um arquivo tessera arrastado -para um navegador é verificado com o mesmo rigor criptográfico do CLI — mesmos -hashes BLAKE3, mesmas assinaturas Ed25519, mesmo parser de MANIFEST. A diferença -é que agora qualquer pessoa pode fazer isso.</p> - -</article> - - </main> - - <footer> - <p>© 2026 Tesseras Project. <a href="/atom.xml">News Feed</a> · <a href="https://git.sr.ht/~ijanc/tesseras">Source</a></p> - </footer> -</body> -</html> diff --git a/pt-br/news/phase4-wasm-browser-verification/index.html.gz b/pt-br/news/phase4-wasm-browser-verification/index.html.gz Binary files differdeleted file mode 100644 index 9b90534..0000000 --- a/pt-br/news/phase4-wasm-browser-verification/index.html.gz +++ /dev/null diff --git a/pt-br/news/reed-solomon/index.html b/pt-br/news/reed-solomon/index.html deleted file mode 100644 index 8947909..0000000 --- a/pt-br/news/reed-solomon/index.html +++ /dev/null @@ -1,210 +0,0 @@ -<!DOCTYPE html> -<html lang="pt-br"> -<head> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <title>Reed-Solomon: Como o Tesseras Sobrevive à Perda de Dados — Tesseras</title> - <meta name="description" content="Um mergulho profundo na codificação de apagamento Reed-Solomon — o que é, por que o Tesseras a utiliza e os desafios de manter memórias vivas ao longo dos séculos."> - <!-- Open Graph --> - <meta property="og:type" content="article"> - <meta property="og:title" content="Reed-Solomon: Como o Tesseras Sobrevive à Perda de Dados"> - <meta property="og:description" content="Um mergulho profundo na codificação de apagamento Reed-Solomon — o que é, por que o Tesseras a utiliza e os desafios de manter memórias vivas ao longo dos séculos."> - <meta property="og:image" content="https://tesseras.net/images/social.jpg"> - <meta property="og:image:width" content="1200"> - <meta property="og:image:height" content="630"> - <meta property="og:site_name" content="Tesseras"> - <!-- Twitter Card --> - <meta name="twitter:card" content="summary_large_image"> - <meta name="twitter:title" content="Reed-Solomon: Como o Tesseras Sobrevive à Perda de Dados"> - <meta name="twitter:description" content="Um mergulho profundo na codificação de apagamento Reed-Solomon — o que é, por que o Tesseras a utiliza e os desafios de manter memórias vivas ao longo dos séculos."> - <meta name="twitter:image" content="https://tesseras.net/images/social.jpg"> - <link rel="stylesheet" href="https://tesseras.net/style.css?h=21f0f32121928ee5c690"> - - - <link rel="alternate" type="application/atom+xml" title="Tesseras" href="https://tesseras.net/atom.xml"> - - - <link rel="icon" type="image/png" sizes="32x32" href="https://tesseras.net/images/favicon.png?h=be4e123a23393b1a027d"> - -</head> -<body> - <header> - <h1> - <a href="https://tesseras.net/pt-br/"> - <img src="https://tesseras.net/images/logo-64.png?h=c1b8d0c4c5f93b49d40b" alt="Tesseras" width="40" height="40" class="logo"> - Tesseras - </a> - </h1> - <nav> - - <a href="https://tesseras.net/pt-br/about/">Sobre</a> - <a href="https://tesseras.net/pt-br/news/">Notícias</a> - <a href="https://tesseras.net/pt-br/releases/">Lançamentos</a> - <a href="https://tesseras.net/pt-br/faq/">FAQ</a> - <a href="https://tesseras.net/pt-br/subscriptions/">Inscrições</a> - <a href="https://tesseras.net/pt-br/contact/">Contato</a> - - </nav> - <nav class="lang-switch"> - - <a href="https://tesseras.net/news/reed-solomon/">English</a> | <strong>Português</strong> - - </nav> - </header> - - <main> - -<article> - <h2>Reed-Solomon: Como o Tesseras Sobrevive à Perda de Dados</h2> - <p class="news-date">2026-02-14</p> - <p>Seu disco rígido vai morrer. Seu provedor de nuvem vai pivotar. O array RAID no -seu armário vai sobreviver ao controlador, mas não ao dono. Se uma memória está -armazenada em exatamente um lugar, ela tem exatamente uma forma de se perder -para sempre.</p> -<p>Tesseras é uma rede que mantém memórias humanas vivas através de ajuda mútua. O -mecanismo central de sobrevivência é a <strong>codificação de apagamento -Reed-Solomon</strong> — uma técnica emprestada da comunicação espacial profunda que nos -permite reconstruir dados mesmo quando pedaços desaparecem.</p> -<h2 id="o-que-e-reed-solomon">O que é Reed-Solomon?</h2> -<p>Reed-Solomon é uma família de códigos corretores de erros inventada por Irving -Reed e Gustave Solomon em 1960. O caso de uso original era corrigir erros em -dados transmitidos por canais ruidosos — pense na Voyager enviando fotos de -Júpiter, ou num CD tocando apesar de arranhões.</p> -<p>A ideia-chave: se você adicionar redundância cuidadosamente calculada aos seus -dados <em>antes</em> que algo dê errado, você pode recuperar o original mesmo depois de -perder alguns pedaços.</p> -<p>Eis a intuição. Suponha que você tenha um polinômio de grau 2 — uma parábola. -Você precisa de 3 pontos para defini-lo de forma única. Mas se você avaliá-lo em -5 pontos, pode perder quaisquer 2 desses 5 e ainda reconstruir o polinômio a -partir dos 3 restantes. Reed-Solomon generaliza essa ideia para trabalhar sobre -corpos finitos (corpos de Galois), onde o "polinômio" são seus dados e os -"pontos de avaliação" são seus fragmentos.</p> -<p>Em termos concretos:</p> -<ol> -<li><strong>Divida</strong> seus dados em <em>k</em> shards de dados</li> -<li><strong>Calcule</strong> <em>m</em> shards de paridade a partir dos shards de dados</li> -<li><strong>Distribua</strong> todos os <em>k + m</em> shards em diferentes locais</li> -<li><strong>Reconstrua</strong> os dados originais a partir de quaisquer <em>k</em> dos <em>k + m</em> -shards</li> -</ol> -<p>Você pode perder até <em>m</em> shards — quaisquer <em>m</em>, de dados ou paridade, em -qualquer combinação — e ainda recuperar tudo.</p> -<h2 id="por-que-nao-simplesmente-fazer-copias">Por que não simplesmente fazer cópias?</h2> -<p>A abordagem ingênua para redundância é a replicação: faça 3 cópias, armazene-as -em 3 lugares. Isso dá tolerância a 2 falhas ao custo de 3x o seu armazenamento.</p> -<p>Reed-Solomon é dramaticamente mais eficiente:</p> -<table><thead><tr><th>Estratégia</th><th style="text-align: right">Overhead de armazenamento</th><th style="text-align: right">Falhas toleradas</th></tr></thead><tbody> -<tr><td>Replicação 3x</td><td style="text-align: right">200%</td><td style="text-align: right">2 de 3</td></tr> -<tr><td>Reed-Solomon (16,8)</td><td style="text-align: right">50%</td><td style="text-align: right">8 de 24</td></tr> -<tr><td>Reed-Solomon (48,24)</td><td style="text-align: right">50%</td><td style="text-align: right">24 de 72</td></tr> -</tbody></table> -<p>Com 16 shards de dados e 8 de paridade, você usa 50% de armazenamento extra mas -pode sobreviver à perda de um terço de todos os fragmentos. Para alcançar a -mesma tolerância a falhas só com replicação, você precisaria de 3x o -armazenamento.</p> -<p>Para uma rede que visa preservar memórias ao longo de décadas e séculos, essa -eficiência não é um luxo — é a diferença entre um sistema viável e um que se -afoga no próprio overhead.</p> -<h2 id="como-o-tesseras-usa-reed-solomon">Como o Tesseras usa Reed-Solomon</h2> -<p>Nem todos os dados merecem o mesmo tratamento. Uma memória de texto de 500 bytes -e um vídeo de 100 MB têm necessidades de redundância muito diferentes. O -Tesseras usa uma estratégia de fragmentação em três camadas:</p> -<p><strong>Small (< 4 MB)</strong> — Replicação do arquivo inteiro para 7 pares. Para tesseras -pequenas, o overhead da codificação de apagamento (tempo de codificação, -gerenciamento de fragmentos, lógica de reconstrução) supera seus benefícios. -Cópias simples são mais rápidas e mais simples.</p> -<p><strong>Medium (4–256 MB)</strong> — 16 shards de dados + 8 de paridade = 24 fragmentos no -total. Cada fragmento tem aproximadamente 1/16 do tamanho original. Quaisquer 16 -dos 24 fragmentos reconstroem o original. Distribuídos entre 7 pares.</p> -<p><strong>Large (≥ 256 MB)</strong> — 48 shards de dados + 24 de paridade = 72 fragmentos no -total. Maior contagem de shards significa fragmentos individuais menores (mais -fáceis de transferir e armazenar) e maior tolerância absoluta a falhas. Também -distribuídos entre 7 pares.</p> -<p>A implementação usa o crate <code>reed-solomon-erasure</code> operando sobre GF(2⁸) — o -mesmo corpo de Galois usado em códigos QR e CDs. Cada fragmento carrega um -checksum BLAKE3 para que a corrupção seja detectada imediatamente, não propagada -silenciosamente.</p> -<pre><code>Tessera (álbum de fotos de 120 MB) - ↓ codificar -16 shards de dados (7,5 MB cada) + 8 shards de paridade (7,5 MB cada) - ↓ distribuir -24 fragmentos entre 7 pares (diversidade de sub-rede) - ↓ quaisquer 16 fragmentos -Tessera original recuperada -</code></pre> -<h2 id="os-desafios">Os desafios</h2> -<p>Reed-Solomon resolve o problema matemático da redundância. Os desafios de -engenharia estão em tudo ao redor.</p> -<h3 id="rastreamento-de-fragmentos">Rastreamento de fragmentos</h3> -<p>Cada fragmento precisa ser localizável. O Tesseras usa uma DHT Kademlia para -descoberta de pares e mapeamento de fragmentos para pares. Quando um nó fica -offline, seus fragmentos precisam ser recriados e distribuídos para novos pares. -Isso significa rastrear quais fragmentos existem, onde estão e se ainda estão -intactos — numa rede sem autoridade central.</p> -<h3 id="corrupcao-silenciosa">Corrupção silenciosa</h3> -<p>Um fragmento que retorna dados errados é pior que um ausente — pelo menos um -fragmento ausente é honestamente ausente. O Tesseras aborda isso com -verificações de saúde baseadas em atestação: o loop de reparo periodicamente -pede aos detentores de fragmentos que provem posse retornando checksums BLAKE3. -Se um checksum não bater, o fragmento é tratado como perdido.</p> -<h3 id="falhas-correlacionadas">Falhas correlacionadas</h3> -<p>Se todos os 24 fragmentos de uma tessera caírem em máquinas no mesmo datacenter, -uma única queda de energia os elimina todos. A matemática do Reed-Solomon assume -falhas independentes. O Tesseras impõe <strong>diversidade de sub-rede</strong> durante a -distribuição: no máximo 2 fragmentos por sub-rede /24 IPv4 (ou prefixo /48 -IPv6). Isso espalha fragmentos por diferentes infraestruturas físicas.</p> -<h3 id="velocidade-de-reparo-vs-carga-na-rede">Velocidade de reparo vs. carga na rede</h3> -<p>Quando um par fica offline, o relógio começa a contar. Fragmentos perdidos -precisam ser recriados antes que mais falhas se acumulem. Mas reparo agressivo -inunda a rede. O Tesseras equilibra isso com um loop de reparo configurável -(padrão: a cada 24 horas com 2 horas de jitter) e limites de transferências -simultâneas (padrão: 4 transferências simultâneas). O jitter previne tempestades -de reparo onde cada nó verifica seus fragmentos no mesmo momento.</p> -<h3 id="gerenciamento-de-chaves-a-longo-prazo">Gerenciamento de chaves a longo prazo</h3> -<p>Reed-Solomon protege contra perda de dados, não contra perda de acesso. Se uma -tessera é criptografada (visibilidade privada ou selada), você precisa da chave -de descriptografia para tornar os dados recuperados úteis. O Tesseras separa -essas preocupações: codificação de apagamento cuida da disponibilidade, enquanto -o Compartilhamento de Segredo de Shamir (uma fase futura) cuidará da -distribuição de chaves entre herdeiros. A filosofia de design do projeto — -criptografar o mínimo possível — mantém o problema de gerenciamento de chaves -pequeno.</p> -<h3 id="limitacoes-do-corpo-de-galois">Limitações do corpo de Galois</h3> -<p>O corpo GF(2⁸) limita o número total de shards a 255 (dados + paridade -combinados). Para o Tesseras, isso não é uma restrição prática — mesmo a camada -Large usa apenas 72 shards. Mas significa que arquivos extremamente grandes com -milhares de fragmentos exigiriam um corpo diferente ou um esquema de codificação -em camadas.</p> -<h3 id="compatibilidade-evolutiva-do-codec">Compatibilidade evolutiva do codec</h3> -<p>Uma tessera codificada hoje precisa ser decodificável em 50 anos. Reed-Solomon -sobre GF(2⁸) é um dos algoritmos mais amplamente implementados na computação — -está em todo leitor de CD, em todo scanner de código QR, em toda sonda espacial. -Essa ubiquidade é em si uma estratégia de sobrevivência. O algoritmo não será -esquecido porque metade da infraestrutura do mundo depende dele.</p> -<h2 id="o-quadro-geral">O quadro geral</h2> -<p>Reed-Solomon é uma peça de um quebra-cabeça maior. Ele trabalha em conjunto com:</p> -<ul> -<li><strong>DHT Kademlia</strong> para encontrar pares e rotear fragmentos</li> -<li><strong>Checksums BLAKE3</strong> para verificação de integridade</li> -<li><strong>Reciprocidade bilateral</strong> para troca justa de armazenamento (sem blockchain)</li> -<li><strong>Diversidade de sub-rede</strong> para independência de falhas</li> -<li><strong>Reparo automático</strong> para manter a redundância ao longo do tempo</li> -</ul> -<p>Nenhuma técnica isolada faz memórias sobreviverem. Reed-Solomon garante que -dados <em>podem</em> ser recuperados. A DHT garante que fragmentos <em>podem ser -encontrados</em>. A reciprocidade garante que pares <em>querem ajudar</em>. O reparo -garante que nada disso se degrade com o tempo.</p> -<p>Uma tessera é uma aposta de que a soma desses mecanismos, rodando em muitas -máquinas independentes operadas por muitas pessoas independentes, é mais durável -que qualquer instituição isolada. Reed-Solomon é a fundação matemática dessa -aposta.</p> - -</article> - - </main> - - <footer> - <p>© 2026 Tesseras Project. <a href="/atom.xml">News Feed</a> · <a href="https://git.sr.ht/~ijanc/tesseras">Source</a></p> - </footer> -</body> -</html> diff --git a/pt-br/news/reed-solomon/index.html.gz b/pt-br/news/reed-solomon/index.html.gz Binary files differdeleted file mode 100644 index d7674cf..0000000 --- a/pt-br/news/reed-solomon/index.html.gz +++ /dev/null diff --git a/pt-br/releases/index.html b/pt-br/releases/index.html deleted file mode 100644 index 72c9145..0000000 --- a/pt-br/releases/index.html +++ /dev/null @@ -1,83 +0,0 @@ -<!DOCTYPE html> -<html lang="pt-br"> -<head> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <title>Lançamentos — Tesseras</title> - <meta name="description" content="Lançamentos e downloads do software Tesseras"> - <!-- Open Graph --> - <meta property="og:type" content="website"> - <meta property="og:title" content="Lançamentos"> - <meta property="og:description" content="Lançamentos e downloads do software Tesseras"> - <meta property="og:image" content="https://tesseras.net/images/social.jpg"> - <meta property="og:image:width" content="1200"> - <meta property="og:image:height" content="630"> - <meta property="og:site_name" content="Tesseras"> - <!-- Twitter Card --> - <meta name="twitter:card" content="summary_large_image"> - <meta name="twitter:title" content="Lançamentos"> - <meta name="twitter:description" content="Lançamentos e downloads do software Tesseras"> - <meta name="twitter:image" content="https://tesseras.net/images/social.jpg"> - <link rel="stylesheet" href="https://tesseras.net/style.css?h=21f0f32121928ee5c690"> - - - <link rel="alternate" type="application/atom+xml" title="Tesseras" href="https://tesseras.net/atom.xml"> - - - <link rel="icon" type="image/png" sizes="32x32" href="https://tesseras.net/images/favicon.png?h=be4e123a23393b1a027d"> - -</head> -<body> - <header> - <h1> - <a href="https://tesseras.net/pt-br/"> - <img src="https://tesseras.net/images/logo-64.png?h=c1b8d0c4c5f93b49d40b" alt="Tesseras" width="40" height="40" class="logo"> - Tesseras - </a> - </h1> - <nav> - - <a href="https://tesseras.net/pt-br/about/">Sobre</a> - <a href="https://tesseras.net/pt-br/news/">Notícias</a> - <a href="https://tesseras.net/pt-br/releases/">Lançamentos</a> - <a href="https://tesseras.net/pt-br/faq/">FAQ</a> - <a href="https://tesseras.net/pt-br/subscriptions/">Inscrições</a> - <a href="https://tesseras.net/pt-br/contact/">Contato</a> - - </nav> - <nav class="lang-switch"> - - <a href="https://tesseras.net/releases/">English</a> | <strong>Português</strong> - - </nav> - </header> - - <main> - -<article> - <h2>Lançamentos</h2> - <p>Nenhum lançamento ainda. Tesseras está em desenvolvimento inicial (Fase 0).</p> -<h3 id="formato-de-lancamento">Formato de Lançamento</h3> -<p>Quando disponíveis, os lançamentos incluirão:</p> -<table><thead><tr><th>Arquivo</th><th>Descrição</th></tr></thead><tbody> -<tr><td><code>tesseras-X.Y.Z.tar.gz</code></td><td>Tarball com código-fonte</td></tr> -<tr><td><code>tesseras-X.Y.Z.tar.gz.sig</code></td><td>Assinatura signify</td></tr> -<tr><td><code>SHA256</code></td><td>Checksums BLAKE3</td></tr> -<tr><td><code>CHANGELOG.md</code></td><td>O que mudou</td></tr> -</tbody></table> -<p>Os lançamentos seguem <a rel="external" href="https://semver.org/">Versionamento Semântico</a>. Tarballs -são assinados com <a rel="external" href="https://man.openbsd.org/signify">signify</a>.</p> -<h3 id="verificando-um-lancamento">Verificando um Lançamento</h3> -<pre><code>signify -Vep tesseras.pub -m tesseras-X.Y.Z.tar.gz -x tesseras-X.Y.Z.tar.gz.sig -b3sum -c SHA256 -</code></pre> - -</article> - - </main> - - <footer> - <p>© 2026 Tesseras Project. <a href="/atom.xml">News Feed</a> · <a href="https://git.sr.ht/~ijanc/tesseras">Source</a></p> - </footer> -</body> -</html> diff --git a/pt-br/releases/index.html.gz b/pt-br/releases/index.html.gz Binary files differdeleted file mode 100644 index 0ee936f..0000000 --- a/pt-br/releases/index.html.gz +++ /dev/null diff --git a/pt-br/subscriptions/index.html b/pt-br/subscriptions/index.html deleted file mode 100644 index cae6bf7..0000000 --- a/pt-br/subscriptions/index.html +++ /dev/null @@ -1,112 +0,0 @@ -<!DOCTYPE html> -<html lang="pt-br"> -<head> - <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <title>Inscrições — Tesseras</title> - <meta name="description" content="Inscreva-se nas listas de discussão do Tesseras"> - <!-- Open Graph --> - <meta property="og:type" content="website"> - <meta property="og:title" content="Inscrições"> - <meta property="og:description" content="Inscreva-se nas listas de discussão do Tesseras"> - <meta property="og:image" content="https://tesseras.net/images/social.jpg"> - <meta property="og:image:width" content="1200"> - <meta property="og:image:height" content="630"> - <meta property="og:site_name" content="Tesseras"> - <!-- Twitter Card --> - <meta name="twitter:card" content="summary_large_image"> - <meta name="twitter:title" content="Inscrições"> - <meta name="twitter:description" content="Inscreva-se nas listas de discussão do Tesseras"> - <meta name="twitter:image" content="https://tesseras.net/images/social.jpg"> - <link rel="stylesheet" href="https://tesseras.net/style.css?h=21f0f32121928ee5c690"> - - - <link rel="alternate" type="application/atom+xml" title="Tesseras" href="https://tesseras.net/atom.xml"> - - - <link rel="icon" type="image/png" sizes="32x32" href="https://tesseras.net/images/favicon.png?h=be4e123a23393b1a027d"> - -</head> -<body> - <header> - <h1> - <a href="https://tesseras.net/pt-br/"> - <img src="https://tesseras.net/images/logo-64.png?h=c1b8d0c4c5f93b49d40b" alt="Tesseras" width="40" height="40" class="logo"> - Tesseras - </a> - </h1> - <nav> - - <a href="https://tesseras.net/pt-br/about/">Sobre</a> - <a href="https://tesseras.net/pt-br/news/">Notícias</a> - <a href="https://tesseras.net/pt-br/releases/">Lançamentos</a> - <a href="https://tesseras.net/pt-br/faq/">FAQ</a> - <a href="https://tesseras.net/pt-br/subscriptions/">Inscrições</a> - <a href="https://tesseras.net/pt-br/contact/">Contato</a> - - </nav> - <nav class="lang-switch"> - - <a href="https://tesseras.net/subscriptions/">English</a> | <strong>Português</strong> - - </nav> - </header> - - <main> - -<article> - <h2>Inscrições</h2> - <h3 id="listas-de-discussao">Listas de Discussão</h3> -<p>Tesseras usa quatro listas de discussão hospedadas no SourceHut, cada uma com um -propósito diferente.</p> -<h4 id="tesseras-announce">tesseras-announce</h4> -<p>Anúncios de lançamento, marcos e notícias importantes do projeto. Baixo tráfego, -somente leitura.</p> -<ul> -<li>Inscrever-se: -<a href="mailto:~ijanc/tesseras-announce+subscribe@lists.sr.ht">~ijanc/tesseras-announce@lists.sr.ht</a></li> -<li><a rel="external" href="https://lists.sr.ht/~ijanc/tesseras-announce">Navegar nos arquivos</a></li> -</ul> -<h4 id="tesseras-devel">tesseras-devel</h4> -<p>Patches, revisão de código, discussão de arquitetura e coordenação de -desenvolvimento.</p> -<ul> -<li>Inscrever-se: -<a href="mailto:~ijanc/tesseras-devel+subscribe@lists.sr.ht">~ijanc/tesseras-devel@lists.sr.ht</a></li> -<li><a rel="external" href="https://lists.sr.ht/~ijanc/tesseras-devel">Navegar nos arquivos</a></li> -</ul> -<h4 id="tesseras-discuss">tesseras-discuss</h4> -<p>Suporte a usuários, discussão geral, perguntas e conversa da comunidade.</p> -<ul> -<li>Inscrever-se: -<a href="mailto:~ijanc/tesseras-discuss+subscribe@lists.sr.ht">~ijanc/tesseras-discuss@lists.sr.ht</a></li> -<li><a rel="external" href="https://lists.sr.ht/~ijanc/tesseras-discuss">Navegar nos arquivos</a></li> -</ul> -<h4 id="tesseras-security">tesseras-security</h4> -<p>Divulgação responsável de vulnerabilidades de segurança. Restrita a -mantenedores; relatos são bem-vindos de qualquer pessoa.</p> -<ul> -<li>Relatar: -<a href="mailto:~ijanc/tesseras-security@lists.sr.ht">~ijanc/tesseras-security@lists.sr.ht</a></li> -<li><a rel="external" href="https://lists.sr.ht/~ijanc/tesseras-security">Navegar nos arquivos</a></li> -</ul> -<h3 id="bug-tracker">Bug Tracker</h3> -<p>Registre bugs e pedidos de funcionalidades no -<a rel="external" href="https://todo.sr.ht/~ijanc/tesseras">ticket tracker</a>.</p> -<h3 id="feeds">Feeds</h3> -<p>Você também pode acompanhar o projeto via feeds no seu leitor de feeds:</p> -<ul> -<li><a href="/pt-br/atom.xml">Feed de notícias</a> — anúncios e atualizações do projeto</li> -<li><a rel="external" href="https://sr.ht/~ijanc/tesseras/feed.rss">Feed SourceHut</a> — commits, tickets e -atividade das listas</li> -</ul> - -</article> - - </main> - - <footer> - <p>© 2026 Tesseras Project. <a href="/atom.xml">News Feed</a> · <a href="https://git.sr.ht/~ijanc/tesseras">Source</a></p> - </footer> -</body> -</html> diff --git a/pt-br/subscriptions/index.html.gz b/pt-br/subscriptions/index.html.gz Binary files differdeleted file mode 100644 index bbb0e55..0000000 --- a/pt-br/subscriptions/index.html.gz +++ /dev/null |