Bem-vindo de volta ao Nostr Compass, seu guia semanal do Nostr.

Nesta semana: a especificação Marmot é marcada como adotada em 42 arquivos, enquanto o MDK lança da v0.9.0 à v0.9.3 com avatares de grupo criptografados, suporte a signers externos e bindings do MarmotKit para iOS e Android. O Mostro lança o Transport v2 em mensagens diretas NIP-44, com barreiras antispam e uma janela de coexistência tanto no mostrod v0.18.0 quanto no Mobile v1.3.0. O Bitchat 1.6.0 adiciona prova de trabalho NIP-13 às mensagens de canais de geohash, um gateway opcional da malha para o Nostr que permite a um único telefone conectado dar acesso a uma multidão inteira, pacotes de prekeys, verificação transitiva e grupos privados criptografados administrados pelo criador. O Amber delimita assinaturas de perfil por conta, busca listas de relays NIP-65 antes dos metadados de perfil e adiciona uma notificação ao vivo do status do Tor com ação de reinicialização. O rust-nostr adiciona expiração NIP-40 aos builders de gift wrap e DM NIP-17, ancorada ao timestamp aleatório do wrap. O Amethyst incorpora 43 PRs de reforço da sincronização negentropy, infraestrutura de busca de texto completo NIP-50 e kinds de eventos para nichos. O Nostrord lança v2.0.0 e v2.1.0, com pool de relays unificado, detecção de WebSockets zumbis e uma camada completa de cache disk-first.

Também foram lançados Ngit v2.6.2, Jumble v26.7.1, Applesauce signers 6.2.2, Bray v1.33.0, Deepmarks 1.0.0, Bitcredit Core v0.5.13, Coop Mobile v0.2.4, Granary v11.0, Nostr-relay v0.0.244, Manent v1.4.0, Routstrd v0.3.7, Nymchat 1.0.1 e 21Meetup 1.1.0.

O repositório de NIPs incorpora um alinhamento de nomes entre NIP-51 e NIP-37 e abre cinco propostas: Endereços Web Nostr NIP-AD, gestão de claims de códigos de convite NIP-86, um formato HSL para cores de papéis, proveniência de mídia atestada por hardware NIP-80 e uma correção de paginação na NIP-01. As análises aprofundadas cobrem NIP-13 (prova de trabalho) e NIP-40 (timestamp de expiração).


Principais notícias

Marmot marca a especificação como adotada e o MDK lança a série v0.9.x

O repositório do protocolo Marmot incorporou a PR #170 em 3 de julho, alterando 42 arquivos de Status: draft for internal review (e experimental draft) para Status: adopted. O título do README deixou de apresentar o repositório como trabalho em andamento e passou a ser “Marmot Protocol”, como texto adotado; os documentos da era MIP foram reenquadrados como a versão obsoleta do protocolo; e a seção “Review Status” (“This is not adopted spec text yet”) virou “Review Guidance”, para a edição da especificação atual. O rótulo v2 desaparece por toda parte: formulações de contraste com MIP (“new in v2”, “the v2 spec keeps”) são substituídas por “this spec” e “under this spec”. Dois documentos permanecem como rascunho intencionalmente: implementation-model.md continua não normativo, e o documento do recurso multidispositivo segue como rascunho.

O mesmo repositório incorporou a PR #171, alinhando invariantes de política de administradores, membros e mudanças de papéis. A verificação entre componentes de que um Remove não pode deixar o grupo sem administrador agora é declarada como propriedade de toda epoch resultante, avaliada em relação ao conjunto de administradores da epoch anterior quando um commit não contém atualização da política de administradores. A regra de branch candidata da convergência foi reforçada: “validates” agora significa a validade integral do commit, incluindo as verificações entre componentes da epoch resultante, impedindo que um commit que viole invariantes crie uma aresta candidata em qualquer branch. Notificações de estado derivadas de um commit substituído DEVEM ser retiradas quando a seleção de branch o troca, fechando no nível da especificação o bug em que “uma renomeação perdedora aparece como mensagem de sistema bem-sucedida”. Uma nova seção “Realizing removal” em member-departure.md define a entrada primária de efetivação (o commit canônico aceito que remove sua última leaf) e o fallback para clientes que nunca aplicaram o commit de remoção: evidência autenticada pós-expulsão agora produz um resultado SelfEvicted, com semântica de reter como inativa a cópia removida do grupo. A PR #236 reforçou depois a validação na fronteira do wire, fixando a aceitação da validade de KeyPackages em 84 dias mais uma margem de uma hora para desvio de relógio, adicionando uma tabela de cardinalidade de tags Nostr para h de grupo, p de gift wrap, e e relays de welcome e tags de KeyPackage, e declarando que ids e metadados de eventos Nostr não verificados não são evidências confiáveis de roteamento, replay ou telemetria.

Mais abaixo na cadeia, o workspace do MDK lançou a v0.9.0 em 6 de julho com atualização de versão de todo o workspace, seguida por v0.9.1, v0.9.2 e v0.9.3 nos dois dias seguintes. A v0.9.0 rotaciona entradas antigas do keyring quando um novo banco SQLite é criado e aplica a disciplina de validar antes de alterar em toda a camada de armazenamento. A v0.9.1 direciona toda conexão de saída por um único ponto de passagem de dial seguro do host, pela PR #732, fechando a classe de bugs em que diferentes pontos de chamada chegavam à rede com validações diferentes. A v0.9.3 expõe avatares de grupo criptografados aos bindings uniffi por download_group_image e image_hash_hex, na PR #771, adiciona suporte a signers externos e marca wn-opencode como pronto para produção pela PR #781. Junto aos lançamentos do MDK, o MarmotKit disponibiliza bindings de iOS e Android em cada versão (um MarmotKit.xcframework mais bindings Swift para iOS e bindings Kotlin mais bibliotecas JNI para Android, ambos gerados de um hash imutável de commit do MDK), e um novo canal de releases do wn-agent fornece instaladores shell que fixam a versão do WN Agent em uma tag imutável, para que aplicativos dependentes obtenham o agente atual com um único comando curl.

Mostro v0.18.0 e Mobile v1.3.0 lançam o Transport v2 sobre NIP-44

Mostro é o protocolo de negociação peer-to-peer de Bitcoin que executa livros de ofertas, escrow e resolução de disputas sobre eventos Nostr, coordenado por um daemon (mostrod) com o qual os clientes se comunicam por DMs criptografadas. Até esta semana, o protocolo no wire entre clientes e mostrod era o Transport v1. O Mostro v0.18.0 traz o Transport v2, colocando o protocolo sobre mensagens diretas NIP-44, com barreiras antispam e recepção dupla no servidor. A PR #776 é a alteração de wire da Fase 1, a PR #780 adiciona as barreiras antispam da Fase 2 para o protocolo v2, e a PR #785 faz a versão interna do protocolo seguir o transporte ativo, para que um cliente v2 e outro v1 coexistam durante a migração. A PR #782 relacionada corrige uma tag de informações NIP-33 ao renomear protocol_versions para o singular protocol_version. Além do trabalho de transporte, o release traz um caminho unificado de cotações ao vivo da Fase 4, com cache e fiscalização de dados obsoletos (PR #783), e um provedor de câmbio fiat El Toque para os pares cubanos CUP e MLC (PR #778). A PR #779 adiciona uma notificação à parte penalizada quando há slash em uma disputa, para que o usuário que perdeu seu bond seja informado diretamente pelo daemon; antes, isso aparecia apenas como um saldo ausente na carteira.

O Mostro Mobile v1.3.0 é a metade cliente da migração. A PR #613 migra o app para Riverpod 3.x; a Fase A (PR #620) adiciona recepção dupla de mensagens diretas NIP-44 tanto no isolate principal quanto no isolate em segundo plano, para que um mostrod v2 e um cliente v1 conversem durante a migração; a Fase B, na PR #624, adiciona envio duplo; a PR #632 reaplica o envio duplo após a mudança para Riverpod 3.x; e a Fase C, na PR #637, conclui a migração. O release também amplia a cobertura de métodos de pagamento africanos: a PR #625 adiciona métodos em kwacha do Malawi, e a PR #627 adiciona KES (xelim queniano), MZN (metical moçambicano), TZS (xelim tanzaniano), UGX (xelim ugandense), ZAR (rand sul-africano) e ZMW (kwacha zambiano), além de ampliar NGN (naira nigeriana). Um fluxo de restauração agora aguarda a conectividade do node antes de emitir pedidos de restauração, e o tratamento consciente da causa distingue o slash do bond provocado por disputa daquele provocado por timeout.

Bitchat 1.6.0 adiciona prova de trabalho NIP-13 e um gateway opcional da malha para o Nostr

O Bitchat 1.6.0 é o aplicativo de chat em malha Bluetooth que usa Nostr para seus canais de geohash e para a transferência de DMs. O release faz duas coisas com forte relação com o Nostr. A PR #1382 adiciona NIP-13 (prova de trabalho) às mensagens de saída dos canais de geohash (eventos efêmeros kind 20000): cada envio minera uma tag ["nonce", "<value>", "<target>"] antes de publicar, mirando 8 bits zero iniciais, o que exige em média 256 tentativas de hash e termina em menos de um milissegundo em um Mac da série M. Eventos recebidos com PoW validada relaxam o limite da taxa de entrada por remetente: um spammer paga computação por mensagem, enquanto um remetente comum não percebe o custo. O escopo é deliberadamente estreito: somente mensagens de canal kind 20000 mineram PoW; heartbeats de presença (kind 20001), notas de localização kind 1 e DMs não mudam.

A PR #1384 adiciona o modo gateway, um uplink opcional da malha para o Nostr em canais de geohash. Quando um usuário restrito à malha (sem internet nem relay acessível) envia algo em um canal de geohash e outro peer da malha anuncia a capacidade .gateway, o evento kind 20000 assinado é envolvido em um novo envelope TLV MessageType.nostrCarrier = 0x28 e enviado diretamente a um gateway. O peer gateway publica o evento no Nostr em nome do remetente e retransmite o tráfego recebido do canal de volta à malha, com TTL padrão. Depósitos no uplink percorrem o caminho de envelope courier (direcionado, retransmitido em múltiplos saltos); o downlink usa broadcast. A assinatura acontece antes que o evento saia do remetente, então o gateway pode decidir se publica, mas não pode falsificar a autoria. A motivação declarada são cenários de desastre e protestos, nos quais um único telefone conectado na multidão basta para dar a todo o canal de geohash um uplink Nostr funcional.

O mesmo release traz um segundo lote de trabalho próximo ao Nostr. A PR #1381 adiciona pacotes de prekeys para um primeiro contato assíncrono com forward secrecy no caminho de correio courier, permitindo ao remetente escrever para um peer offline e entregar a mensagem à malha sem antes fazer um handshake Noise ao vivo. A PR #1380 adiciona verificação transitiva: um peer que concluiu o handshake Noise com alguém já verificado por você passa a ser abonado pela sessão Noise, fazendo o grafo de confiança avançar um salto por vez, em vez de exigir nova verificação presencial para cada contato. A PR #1383 adiciona grupos privados criptografados administrados pelo criador sobre a malha; a PR #1376 detecta, renderiza e resgata tokens de ecash Cashu com um comando /pay; e a PR #1379 adiciona um mural persistente e assinado por geohash, sobre a sincronização da malha. A PR #1372 amplia o store-and-forward com couriers abertos, roteamento spray-and-wait, outbox persistente e uma janela de seis horas de histórico público. O Bitchat 1.5.4 foi lançado no início da semana com a correção ponta a ponta dos favoritos na PR #1367, que resolve duplicatas na lista de peers, sincronização Nostr e corrupção de chaves por /fav.


Releases com tags

Amber v6.2.3 delimita assinaturas de perfil e adiciona uma notificação de status do Tor

O Amber v6.2.3 é uma rodada de desempenho e correção no signer Android NIP-46, e as PRs incorporadas na semana ao redor dele apontam para um tema coerente. O release adiciona uma configuração ajustável do intervalo de busca de perfil, com opções nunca e sempre (PR #492); exibe a foto do perfil no bottom sheet de troca de conta; e delimita as assinaturas de perfil pela conta atual, para que um signer com várias contas pare de espalhar assinaturas das contas com as quais o usuário não está assinando no momento. A análise de permissões do bunker ganha tratamento explícito para erros de parsing. Várias violações do StrictMode são corrigidas: uma DiskReadViolation do log onSuccess do Coil, uma violação de keystore ao carregar a conta na thread principal, leituras na thread principal do nome e da foto no seletor de conta e a construção antecipada de KeyPair() nas telas de login e cadastro, agora movida para fora da thread principal. Nos dias seguintes ao lançamento da v6.2.3, a PR #493 reordenou o boot para buscar a lista de relays NIP-65 do usuário antes dos metadados de perfil (assim a consulta usa os relays nos quais ele publica), e a PR #494 transformou a notificação integrada do Tor em um indicador de status ao vivo com ação de reinicialização, de modo que o usuário cujo daemon Tor morra durante uma sessão de assinatura veja a falha e possa reiniciá-lo sem sair do signer. A PR #495 ativou o Android Lint em modo estrito, tratando warnings como erros em toda a base.

Jumble v26.7.1 torna o Blossom o serviço padrão de upload em uma versão focada em DMs

O Jumble v26.7.1 é uma versão do cliente web Nostr focada em mensagens diretas e mídia. O release reformula as configurações de upload e torna o Blossom o serviço padrão, substituindo o NIP-96 anterior. O tratamento de DMs ganha menu de mensagens no celular, ações melhores no desktop, botão “rolar até a mais recente”, reações com toque longo em mídia de DM e opção de repetir o envio de DMs que falharam a partir da lista. A edição de emojis personalizados ganha uma tela de detalhes; o tamanho de balões melhora para invoices e conteúdo incorporado; vários problemas de rolagem e ordenação são corrigidos; e problemas do editor envolvendo inserção de emoji, cópia de texto e arrastar arquivos são resolvidos. A orientação das imagens é corrigida quando metadados são removidos no upload, e downloads Linux ARM64 entram na matriz de releases.

Applesauce signers 6.2.2 remove uma dependência do nbunksec

O applesauce-signers@6.2.2 remove a dependência @sandwichfarm/encoded-entities do subpacote em favor de um helper integrado de nbunksec, pelo commit d654349. A codificação de sessão bunker NIP-46 do Applesauce, adicionada na semana passada, não exige mais a biblioteca externa, reduzindo uma superfície da cadeia de suprimentos para clientes dependentes do pacote signers.

Ngit v2.6.2 impede eventos duplicados de status de PR em pushes para o branch padrão

O Ngit v2.6.2 é um release de correção do CLI git-over-Nostr. git push para o branch padrão deixa de publicar eventos duplicados de status merged/applied para PRs já marcadas como applied, porque a detecção de merge agora lê o estado pré-push do repositório Nostr (a fonte da verdade para saber se uma PR já foi resolvida no lado NIP-34 do fluxo); a heurística anterior dependia de detalhes internos do git e duplicava o evento. Repositórios ativos que usam ngit para pushes git-over-Nostr param de emitir eventos de status kind 1621 duplicados para sua audiência.

CLI Bray v1.33.0 ganha perfil de bunker, persona e saída via Tor

O Bray v1.33.0 é um release de SDK Nostr mais CLI. bunker --profile <name> ganha uma chave de conexão autoestável e fallback de relay, para que um perfil salvo sobreviva à indisponibilidade de um relay; bunker --persona <name> assina como uma identidade derivada de nsec-tree, permitindo a um signer atuar como várias pubkeys de uma só árvore; e todas as requisições HTTP podem passar por um proxy SOCKS Tor quando configurado. O release adiciona subcomandos de carteira para NWC NIP-47, operações de escrita administrativas de grupos NIP-29 (create, update, add-user, remove-user, set-roles), verbos administrativos NIP-86 e helpers de outbox NIP-65. Verbos de publicação ganham flags --jsonl, --csv e --tsv, um verbo req para consultas genéricas com filtros NIP-01, um verbo event para construir eventos arbitrários, um comando publish-raw que assina e transmite eventos pré-construídos, um comando avulso bunker sign para assinatura NIP-46 e uma flag --relay por comando em todos os comandos de publicação. O trabalho de segurança cobre três lotes de pendências da auditoria: disciplina de zeragem de segredos, reforço de bearer auth e rate limiting no transporte HTTP e validação SSRF de URLs de relays. O tarball npm tem 533.844 bytes, com build reproduzível byte a byte verificado em dois runners de CI independentes.

Deepmarks 1.0.0 reforça a superfície de favoritos do Nostr

O Deepmarks 1.0.0 é um marco 1.0 de reforço de segurança para um serviço público de favoritos Nostr. Cada favorito continua sendo um evento Nostr assinado que qualquer cliente pode ler. A API e o worker de arquivo ocupam uma posição privilegiada na rede (podem alcançar Redis interno, o caminho de relay do bunker e metadados da nuvem), então a proteção SSRF é essencial; o release corrige um bypass crítico com literais IPv6 em isPrivateIp: literais entre colchetes eram classificados como públicos, permitindo que [::1], [fd00::1] e [::ffff:10.0.0.4], mapeado de IPv4, alcançassem alvos internos em conexões dual-stack. A proteção agora remove colchetes e reduz IPv6 compatível ou mapeado de IPv4 ao v4 embutido antes da verificação de faixa privada em ambos os serviços. Perfis kind:0 recebidos de relays externos agora têm assinatura verificada no destino, impedindo um relay hostil de falsificar nip05 ou lud16 para uma pubkey vítima arbitrária; e URLs de favoritos têm o esquema verificado em cada ponto de renderização, impedindo que um favorito kind:39701 publicado diretamente no relay com uma d-tag javascript: ou data: chegue a um <a href>. Recibos de zap agora sobrevivem a uma falha transitória do bunker: o handler de liquidação reivindica atomicamente o zap pendente, só finaliza após assinatura bem-sucedida e libera a reivindicação em caso de falha, para que um invoice_updated reenviado possa tentar novamente. A drenagem do fan-out de /publish usa BLMOVE para uma lista de processamento por worker com recuperação condicionada a heartbeat, preservando em caso de crash um evento assinado para o qual o cliente já recebeu 202.

Bitcredit Core v0.5.13 descriptografa metadados de blocos no transporte Nostr

O Bitcredit Core v0.5.13 remove uma camada de criptografia dos eventos públicos Nostr usados pelo protocolo de títulos de crédito. Os metadados dos blocos (id, hash e assinatura) agora trafegam sem criptografia no Nostr; apenas os dados do bloco permanecem criptografados com a chave do título correspondente. Aplicativos novos processam cadeias antigas; aplicativos antigos não processam cadeias novas. O release também adiciona uma função do serviço de títulos para buscar a cadeia e muda a publicação para um modelo otimista por limiar: assim que um número configurado de relays (um, por padrão) aceita a publicação, os demais recebem o evento de forma assíncrona, e a publicação deixa de ser bloqueada pelo relay mais lento.

Coop Mobile v0.2.3 e v0.2.4

O Coop Mobile lançou a v0.2.3 em 4 de julho e a v0.2.4 em 7 de julho, mantendo a cadência constante do cliente Android de mensagens diretas NIP-17. A v0.2.3 adiciona renderização inline de imagens e links em mensagens, anexos de imagem, entrada por reconhecimento de voz e confirmação para remover contatos. A v0.2.4 corrige um indicador que ficava preso para sempre, melhora o handshake Nostr Connect e adiciona importação de ncryptsec1 (o formato de chave privada criptografada NIP-49), junto a uma tela reformulada de importação de identidade.

Granary v11.0 adiciona suporte a eventos de vídeo NIP-71

O Granary v11.0 é a biblioteca de conversão multiprotocolo que sustenta as pontes entre redes do Bridgy Fed. O módulo Nostr ganha três mudanças visíveis. Eventos de vídeo NIP-71 (kinds 21, 22, 34235 e 34236) agora são convertidos em notas ActivityStreams 1 com anexos de vídeo; o conversor extrai a imagem imeta (thumbnail), a duração, a tag de nível superior published_at e a tag alt como displayName fallback do primeiro anexo de vídeo ou áudio. Na API, sign foi renomeado para hash_and_sign e verify agora lança ValueError em caso de falha; o construtor Nostr lança ValueError para URL de relay inválida, e Nostr.query ignora de forma segura o desafio AUTH NIP-42 quando o chamador não definiu privkey. Uma correção posterior impede crashes quando um objeto Nostr article chega sem id. Pontes e leitores que consomem eventos de vídeo NIP-71 pelo Granary agora podem apresentá-los no formato esperado pelo destino.

Nostr-relay v0.0.244 adiciona um backend Firestore

O mattn/nostr-relay v0.0.244 adiciona um backend Firestore pela PR #12, ampliando a camada de armazenamento do relay em Go com a opção Google Cloud Firestore, além dos backends existentes. É uma mudança pequena, mas abre o Firestore como banco serverless gerenciado para operadores de relay.

Manent v1.4.0 corrige AUTH NIP-42 e adiciona fluxos de mídia pela área de transferência

O Manent v1.4.0 é o aplicativo de notas criptografadas e armazenamento de arquivos criado sobre Nostr, com criptografia NIP-44, suporte a signers NIP-46 e NIP-55, roteamento de outbox NIP-65 e armazenamento Blossom. O release corrige a autenticação de relay NIP-42 (antes quebrada), corrige uploads Blossom para hosts http:// (antes tratados de forma errada) e reescreve o fluxo de compactação. Na mídia, agora é possível copiar ou colar uma imagem pela área de transferência, arrastar e soltar arquivos, recortar e girar imagens, reproduzir vídeos e GIFs e gravar vídeo com um toque longo no ícone da câmera. No Linux, a área de transferência primária pode ser acessada com o botão do meio do mouse. O carregamento e a rolagem de notas recebem várias otimizações.

Routstrd v0.3.7 torna o armazenamento de eventos Nostr a fonte da verdade persistente

O Routstrd v0.3.7 é o daemon local da rede descentralizada de inferência de IA Routstr, que direciona requisições de LLM pela descoberta de provedores em eventos Nostr kind 38421 e reviews LGTM kind 38425. O release adiciona o subcomando routstrd update, que baixa novos binários de routstrd e cocod e reinicia daemons em execução de forma controlada; o daemon agora chama refreshNostrEvents() na inicialização e a cada 21 minutos, mantendo descoberta e reviews atualizados sem intervenção. O @routstr/sdk incluído passa de 0.3.12 para 0.3.15, remove a camada ProviderRegistry em favor do uso direto de DiscoveryAdapter, limpa modelos de provedores Nostr desaparecidos para que não vazem para rankings e trata o armazenamento de eventos Nostr como fonte da verdade persistente (o TTL incorreto de 210 minutos dos eventos em cache foi removido). O tratamento de reembolsos Xcashu é reforçado: tokens de reembolso são tentados antes dos originais no caminho de erro, respostas 404 são tentadas 3× com intervalos de dois minutos, e 425 Too Early é tratado sem lançar exceção.

Nymchat 1.0.1 estreia como Progressive Web App sobre NIP-17

O Nymchat 1.0.1 (também chamado NYM, Nostr Ynstant Messenger) é um Progressive Web App e mensageiro nativo iOS/Android para chat efêmero sobre Nostr, integrado ao Bitchat. Canais usam eventos efêmeros kind 20000 para geohashes e kind 23333 para canais nomeados; mensagens privadas e grupos trafegam em eventos gift-wrapped NIP-17 (kind 1059), com chaves efêmeras rotativas por destinatário e recuperação automática pós-comprometimento. O usuário pode gerar um par de chaves efêmero por sessão sem cadastro ou entrar com uma identidade persistente via extensões de navegador NIP-07, signer remoto NIP-46 ou nsec. A criptografia local opcional da identidade usa senha, PIN, passkey ou desbloqueio biométrico por WebAuthn PRF (passkey e biometria) ou PBKDF2 (senha e PIN), sem gravar a chave em texto simples no disco enquanto a criptografia está ativa. Chamadas de voz e vídeo usam gift wraps NIP-17 para sinalização e WebRTC para a mídia. Reações usam NIP-25, emojis personalizados usam NIP-30, e o web app é servido como arquivos estáticos mais Cloudflare Pages Functions que atuam como proxy de privacidade para relays e mídia.

21Meetup 1.1.0 lança distintivos de presença assinados no Nostr

O 21Meetup 1.1.0 é um aplicativo Flutter da comunidade alemã de Bitcoin Einundzwanzig que registra presença em encontros por tags NFC e códigos QR rotativos. Cada distintivo de presença é um evento Nostr (kind 21000) assinado pelo organizador com Schnorr BIP-340, de modo que o participante acumula eventos assinados que atestam encontros e alturas de bloco específicos. O QR gira a cada 10 segundos, impedindo a emissão remota do distintivo, e a tag NFC só é legível em proximidade física. Uma pontuação de confiança é calculada localmente com os distintivos coletados e pode ser apresentada como QR para verificação em negociações peer-to-peer. O aplicativo mira reputação na comunidade Bitcoin, não uma rede social Nostr genérica, mas os eventos de distintivo são eventos Nostr comuns que qualquer leitor pode verificar.

Nostrord v2.0.0 e v2.1.0 unificam o pool de relays e recuperam WebSockets zumbis

O Nostrord v2.0.0 é um grande lançamento do cliente Nostr KMP/WASM compatível com NIP-29, NIP-42, NIP-44, NIP-46, NIP-57, NIP-65 e NIP-98. A v2.0.1 chegou um dia depois pela PR #166, com uma correção bloqueadora no desktop: o pacote 2.0.0 (deb, rpm, msi, dmg) quebrava na inicialização com NoClassDefFoundError: java/sql/DriverManager, pois a imagem jlink do jpackage não incluía o módulo java.sql, exigido pelo driver sqlite SQLDelight. A correção adiciona java.sql à imagem de runtime; a mesma PR direciona o envio otimista pela camada de rede para que a mensagem chegue ao relay (antes, o caminho apenas guardava silenciosamente em cache e nunca entregava), além de corrigir teclado e rolagem na web móvel.

A v2.1.0 veio em 7 de julho com a “unificação do pool de relays” (PR #176), que incorpora ao pool compartilhado o socket de relay antes separado e focado em NIP-29. Um único agendador de reconexão cobre todos os relays; a assinatura AUTH NIP-42 é limitada e repetida; publicações falham de forma fechada e tentam novamente quando autenticação é exigida; condições de corrida por tempestade de requisições em requestPrivateGroupData e fetchGroupPreviews são fechadas; buscas da lista de grupos do usuário kind 10009 são agrupadas por relay; e a assinatura ao vivo mux_chat passa a cobrir todos os grupos em que o usuário entrou, não apenas o aberto, recuperando-se sozinha quando um relay a descarta silenciosamente. Mudanças de UI substituem a linha “Sending…” que deslocava o layout por um ícone inline de relógio e depois check e transformam o recuo de rolagem travado em uma linha Retry explícita. A PR #179 entrou no mesmo dia para detectar WebSockets zumbis no Android: redes móveis e modo Doze encerram o TCP sem frame de fechamento, então escritas ficam no buffer local do socket morto sem lançar erro, e isConnected() permanece true mesmo sem nunca mais receber nada. NostrGroupClient agora registra lastInboundAtMs em cada frame, ganha markDead() (que cancela o loop de frames para disparar o fluxo normal de reconexão e nova assinatura) e probeLiveness() (uma REQ que qualquer relay precisa responder em cinco segundos), acionado quando há timeout de OK sem frames recebidos ou quando o mux está obsoleto e o socket não recebe frames. Uma segunda correção na mesma PR impede a gravação de mensagens otimistas no cache persistente no momento da inserção; elas só são gravadas após confirmação da entrega. A v2.1.1 chegou um dia depois pela PR #178, adicionando implementações de plataforma iOS, suporte a testes nativos e ícones, junto ao trabalho com WebSockets zumbis da v2.1.0.


Alterações ainda não lançadas

rust-nostr adiciona expiração NIP-40 aos builders de gift wrap e DM privada

O rust-nostr incorporou a PR #1384, adicionando uma opção expiration a GiftWrapBuilder e PrivateDirectMessageBuilder. A biblioteca recebe uma Duration do chamador: a tag de expiração NIP-40 é ancorada ao created_at aleatório do gift wrap (created_at + duration), desacoplando-a da hora real do envio. Permitir ao chamador passar um timestamp absoluto revelaria a hora do envio a um observador do relay (bastaria subtrair a duração para recuperar a hora original), por isso a biblioteca constrói a tag internamente a partir do timestamp aleatório do wrap. A tag de expiração fica no evento gift wrap, não no seal kind 13 (que a NIP-59 exige que tenha tags vazias). A NIP-17 repassa o mesmo valor de PrivateDirectMessageBuilder ao builder do gift wrap. A mudança fecha a issue #1381 e usa o mesmo padrão de builder adotado pelo rust-nostr para extra_tags. O rust-nostr também incorporou a PR #1387, consolidando nostr-relay-builder em nostr-sdk e achatando o workspace.

Amethyst passa a semana reforçando a sincronização negentropy e adicionando busca NIP-50

O branch principal do Amethyst incorporou 43 PRs em três temas coerentes. O maior é a sincronização negentropy na fronteira geode–strfry: um modo de falha por janela recusada, que antes lançava o cliente em um loop de divisão de janelas, agora recua corretamente (PR #3480); a dependência negentropyKmp passa à v1.1.1 (PR #3475); chega um benchmark geode–strfry de um milhão de eventos com espelho de paridade strfry (PR #3478); e benchmarks de produção entram na matriz de CI, junto a otimizações mais amplas de sincronização (PR #3458, PR #3466). Coleções concorrentes lock-free substituem o padrão anterior de um mutex por relay, acompanhadas de uma correção de threading no socket UDP (PR #3459).

O segundo tema é a infraestrutura de busca de texto completo NIP-50. Uma interface SearchableEvent permite que eventos carreguem diretamente metadados de índice (PR #3452), e extensões de busca NIP-50 agora são removidas antes da consulta ao FTS do SQLite, para o mecanismo local não engasgar com a sintaxe de extensões do servidor (PR #3464). Os relays de busca padrão são centralizados (PR #3446).

O terceiro tema são integrações de protocolo para nichos. O suporte aos eventos de detecção de aves Birdstar (kind 2473) chega ao cliente Android (PR #3473), e estados salvos de cartões de memória do PS1 podem ser publicados como eventos assinados kind 38192 (PR #3482). Fechando a semana: uma configuração de assinatura de composição acrescenta texto personalizado automaticamente às publicações (PR #3450); a tela de notificações do desktop é redesenhada com toasts nativos do sistema e filtro compartilhado (PR #3457); a coluna Messages ganha um bloqueio de privacidade (PR #3432); NostrServer.ingest adiciona um caminho de escrita local com opção de pular a verificação por envio (PR #3469); e os contratos de equals/hashCode são corrigidos no caminho de verificação OpenTimestamps (PR #3477).

Buzz continua reforçando o relay e define o kind 44200 para métricas de turnos de agentes

O Buzz, projeto antes chamado Sprout, incorporou 123 PRs entre 1º e 7 de julho. Dois temas concentram a maior parte do trabalho. O primeiro é um novo kind para telemetria de agentes: a PR #1441 define métricas duráveis e criptografadas de turnos de agentes NIP-AM como kind 44200, registrando a telemetria em um evento assinado que o relay do próprio usuário arquiva e mantendo as métricas em infraestrutura controlada por ele. Depois vêm um arquivo local do kind (PR #1555), atomicidade no caminho de remoção do kind (PR #1562) e a inclusão do nome do modelo no caminho de emissão, para leitores distinguirem qual modelo produziu cada turno (PR #1564).

O segundo tema é desempenho do relay. O despacho pós-commit é adiado e uma clonagem de verificação é evitada (PR #1453); viagens ao banco para ingestão e fan-out são agrupadas, com quedas medidas de 7% a 16% na latência p99 do ack e de 29% a 53% na cauda p999 em relação ao commit anterior (PR #1454); consultas multifiltro rodam com concorrência limitada (PR #1457); e frames de dados WebSocket de saída são agrupados no envio (PR #1464). Junto ao desempenho, um conjunto de ícones de workspace por comunidade, configurado por administradores e servido pelo relay via NIP-11, amplia o documento de informações NIP-11 com uma superfície de personalização por comunidade (PR #1463); proprietários de agentes podem apagar mensagens de seus agentes por eventos kind 5 do relay, com UX correspondente no desktop e no celular (PR #1519); tracing OpenTelemetry se junta às métricas Prometheus no relay (PR #1398); e o registro de nomes de repositórios git migra para Postgres (PR #1432).

Divine Video conecta verificação de assinaturas do relay e extrai o NostrConnect

O aplicativo móvel do Divine Video incorporou 97 PRs no período, e o tema voltado ao Nostr é o reforço da fronteira de confiança e a limpeza da autenticação. A PR #5774 verifica assinaturas de eventos recebidos de relays, fechando uma classe de bugs de confiança indevida no relay; a PR #5828 criptografa o token push FCM no evento de cancelamento de registro kind 3080, para que o token do dispositivo deixe de aparecer em texto simples no relay quando o usuário cancela a assinatura; e a PR #5831 divide a REQ de exclusões kind 5 em partes, evitando que usuários com grande histórico de exclusões excedam o frame do relay. Na autenticação, a PR #5826 extrai um NostrConnectCoordinator para o fluxo nostrconnect://, limpando o caminho de bunker iniciado pelo cliente NIP-46 antes da refatoração mais ampla acompanhada na issue #4741. A PR #5709 mapeia reposts kind 16 quando notification_type não existe, para que a notificação seja renderizada corretamente mesmo quando o cliente remetente omite a dica.

Zap Cooking corrige login bunker NIP-46 e adiciona busca de receitas NIP-50

O frontend do Zap Cooking incorporou 18 PRs com um tema: fazer as superfícies de autenticação Nostr se recuperarem de falhas. A PR #503 corrige o login bunker com handshake explícito de conexão, tratamento de authUrl e apresentação de erros, de modo que quem conecta um signer externo veja uma mensagem real quando há falha, em vez de a tela de login ficar travada. A PR #495 adiciona autenticação NIP-98 aos caminhos de upload de imagem e texto do endpoint de extração de receitas, atribuindo uploads à pubkey. Outro tema traz busca de texto completo de receitas NIP-50 pelo backend do relay de busca nostrarchives (PR #483), permitindo consultar receitas no corpus dos relays sem índice local. Também há polimento da renderização: conteúdo e mídia de notas citadas aparecem diretamente na nota principal, substituindo o fallback de link escondido (PR #491); chegam previews de links e dimensionamento de hashtags (PR #492); consultas com várias palavras funcionam (PR #482); e cards sociais de preview são gerados no servidor para links de notas, reads e perfis (PR #494).

swift-nostr-client v0.6.0 avança rumo ao primeiro lançamento estável

O yysskk/swift-nostr-client lançou a v0.6.0 junto a 30 PRs incorporadas. A biblioteca Nostr em Swift se aproxima de uma primeira API estável para clientes Swift que evitam vincular as toolchains MDK ou MarmotKit.

Nostr Applet Protocol (NAPS) reforça o roteamento e o fan-out de NAP-OUTBOX

O NAPS teve uma semana significativa de limpeza, sobretudo em NAP-OUTBOX. O destaque são fronteiras mais rígidas: menos roteamento controlado pelo chamador, menos detalhes de relays vazados e um formato compartilhado de resultado de eventos, capaz de transportar hints de relay e sidecars de recursos, integrado ao NAP-RESOURCE. A publicação também fica mais clara, com regras explícitas de fan-out para outbox, inbox e relays. Efeito líquido: menos ambiguidade e melhor interoperabilidade.

Toolchain Napplet reforça o alinhamento do protocolo e lança seu CLI

Nesta semana, os pacotes do Napplet passaram de “SDK útil” para uma toolchain de protocolo mais coesa. O grande tema é o alinhamento às especificações NAP ativas: suporte a consultas NAP-COUNT, o ciclo de vida de OUTBOX controlado pelo runtime e sidecars de RelayEventResult foram incorporados, tornando leituras e assinaturas mediadas pelo shell mais precisas. Vários domínios também foram refinados: suporte a registro CVM, envelopes de erro de DM, contexto de sessão MEDIA, campos de contagem LISTS, resultados de perfil COMMON e o esquema htree: RESOURCE. No ferramental, o novo @napplet/cli é um marco importante, adicionando descoberta de configuração, planejamento de deploy, assinatura, uploads Blossom e geração de manifestos. Por fim, o prelúdio de shim injetável pelo host e o trabalho de preparação para JSR facilitaram a injeção, publicação e verificação da stack.

primal-android amplia a superfície de signer remoto

O Primal Android incorporou 18 PRs no período. No lado Nostr, a PR #1075 implementa os métodos switch_relays e logout no papel de signer remoto do app, ampliando a superfície NIP-46 do Primal. A PR #1083 adiciona um framework de migração local do app condicionado à splash screen, e a PR #1080 implementa prefetching do feed de notas no view-model da splash. O restante é polimento de UI nas barras superior e inferior da Home, nas dicas de Explore e na tela de perfil.

Wisp adiciona seletor de várias contas e testes do parser Blossom

O Wisp incorporou nove PRs. A PR #604 adiciona um seletor de várias contas com caminho explícito de cancelamento no fluxo de adicionar conta. A PR #613 adiciona testes unitários de Blossom.parseServerList, reforçando o parser da lista de servidores Blossom. A PR #574 reescreve a tela de zap para o layout iOS com configurações de zap instantâneo; a PR #605 transforma o histórico de transações em bottom sheet aberto com gesto para cima; a PR #611 interpreta hashtags com letras Unicode não ASCII; a PR #609 mantém a paginação do feed de notas do perfil e renderiza mídia de galeria inline; e a PR #603 preserva linhas em branco antes de segmentos inline de perfis e hashtags.

TAO e Wired elevam o sinal de PoW a 21 bits e exibem raízes com PoW recente

smolgrrr/TAO e smolgrrr/Wired, com o mesmo conjunto de commits nos dois repositórios, incorporaram 13 PRs. A PR #84 eleva o alvo padrão de prova de trabalho do sinal de publicação a 21 bits zero iniciais, e a PR #80 exibe raízes do feed com atividade PoW recente, permitindo ordenar a timeline pelo trabalho NIP-13 recente; antes, a ordem usava apenas a idade do evento. A PR #75 restaura um seletor de emojis personalizados, e a PR #65 adiciona previews do primeiro frame de vídeos. É o segundo cliente Nostr da semana a usar NIP-13 como filtro de primeira classe para conteúdo gerado por usuários, complementando a PoW do Bitchat restrita aos canais.

keep-android aprimora a UX NIP-46 e traz uma correção de TOCTOU

O privkeyio/keep-android lançou a v1.1.5 junto a 13 PRs, e depois a v1.1.6 em 8 de julho, fixando o keep core subjacente na v0.5.0. Keep é um cofre móvel de identidade (coberto na Edição #29 como CustID). A v1.1.5 aprimorou a UX do fluxo de desafio NIP-46. A v1.1.6 fecha uma condição de corrida check-then-set (TOCTOU) em set_active_share, vinda do crate keep-mobile; mostra a URL e o método autorizados no prompt de aprovação de autenticação HTTP NIP-98, para o usuário ver o que assina; e faz a verificação de saúde do RNG falhar de forma fechada (retornando erro) em vez de causar panic. Um teste instrumentado cobre o kill switch do fluxo de aprovação NIP-55. Os recursos CLI da v0.5.0 subjacente (desbloqueio threshold-OPRF, DKG por software e carteiras HD FROST) ainda não aparecem no app Android; a v1.1.6 entrega somente as correções de segurança.

Heartwood lança a ponte de assinatura relay–serial

O forgesworn/heartwood v0.7.0 entrega a ponte de assinatura relay–serial que estava em andamento na semana passada, conectando o plano de dados em modo HSM ao caminho de signer serial do Bray. A PR #11 é a própria ponte; a PR #13 adiciona cobertura de frames seriais e corrige o offset do payload em read_frame no dispositivo; e a PR #14 extrai o codec de frames seriais para um crate compartilhado heartwood-frame.

SafeBox publica relatório de progresso da Fase 3 e runbook de jail no FreeBSD

O SafeBox é um cofre privado e portátil de dados no Nostr que reúne NIP-47 Nostr Wallet Connect, nAuth, nembed e transferência de registros mediada por relays via QR e NFC em um serviço implantável por operadores. Um relatório de progresso de julho de 2026, publicado em 6 de julho, marca a Fase 3 como substancialmente concluída: 49 commits foram feitos desde o relatório de abril, levando o repositório a 1.136 commits, e os quatro compromissos de engenharia da fase — reforçar os experimentos da Fase 2, suportar instâncias interoperáveis, preparar para escala e adicionar disciplina de produto comercial — estão em grande parte entregues. O relatório apresenta como próximo passo um piloto limitado e revela que uma operadora de telecomunicações sob NDA estuda um piloto de registros de saúde no SafeBox.

O trabalho concreto voltado ao Nostr foi feito antes na Fase 3 e é resumido no relatório: ações NWC mutáveis agora entram em fila para evitar corridas de proofs; melts Lightning que falham protegem proofs antes de retornar; listeners NWC de longa duração se atualizam proativamente, mantendo a sessão além do limiar de inatividade — antes ela travava silenciosamente —; e callbacks LNURL usam origens canônicas, com respostas JSON e CORS explícitas. A troca de registros por QR e NFC ganhou uma especificação unificada de fluxo, cobrindo modos apresentados pelo destinatário, pelo remetente e entre dispositivos, com tratamento mais claro de KEM (Key Encapsulation Mechanism) e proteção contra replay pela biblioteca Open Quantum Safe. O commit do período é 6866dae, que adiciona um runbook de deploy em jail do FreeBSD e build do liboqs, junto a uma especificação do appliance FreeBSD, documentando snapshots ZFS, isolamento por jail, gestão do serviço por rc.d, configuração de proxy reverso no host e rollback para deploy do SafeBox em hardware FreeBSD/ARM.

O relatório também anuncia o OpenETR como spin-off independente que aplica a arquitetura de controle criptográfico e registros portáteis do SafeBox a registros eletrônicos transferíveis: conhecimentos de embarque, recibos de armazém, notas promissórias e certificados. O repositório OpenETR recebeu sete commits em 7 de julho, incluindo ea612a9, que separa atestação do registro principal; ca153a3, sobre o tratamento de mandato versus efeito; e ba84b61, que compara formatos de credenciais verificáveis.


Trabalho de protocolo e atualizações de NIPs

Incorporado: NIP-51 e NIP-37 alinham o nome do kind 10013

A PR #2404 é uma correção de consistência apenas no texto. Na NIP-37, o kind 10013 é chamado Relay List for Private Content; na NIP-51, sob Draft relays, o mesmo kind era descrito com termos diferentes. A NIP-51 agora usa o nome da NIP-37. Não há alteração no wire nem nova semântica de tags; o valor está no fato de a NIP-51 ser a especificação guarda-chuva para eventos em forma de lista e a NIP-37 ser o complemento sobre conteúdo privado, e nomes desalinhados tornam fácil não perceber que ambas descrevem o mesmo kind.

Aberto: Endereços Web Nostr NIP-AD por consulta a .well-known

A PR #2406 abre como sucessora da PR #2393, já fechada, com um rascunho completo em AD.md. A NIP-AD define URLs web que carregam uma contraparte Nostr opcional. Um cliente que encontra uma URL como https://golf.com/players solicita https://golf.com/.well-known/nostr.json?ad=/players, que retorna um objeto JSON mapeando caminhos a pares {filter, relays}. O filtro é um filtro NIP-01 padrão (kinds, authors, #d, limit etc.), e o array relays indica quais relays consultar. Com "limit": 1, a URL resolve para um único evento; sem ele, para uma lista. Em um navegador comum, a URL renderiza HTML como qualquer outra, permitindo ao mesmo domínio atender usuários web e clientes Nostr por um caminho canônico. Os casos de uso declarados incluem nomes de grupos NIP-29 resolvidos para eventos kind 39000 em um relay específico (eliminando a necessidade de cultivar ids de grupo), consultas nsite NIP-5A, feeds hospedados que publicam um filtro {"ids": [...]}, renderização nativa de URLs coladas njump.me/nevent1... e URLs específicas de clientes, e blogs alimentados pelo Nostr que existem tanto de forma nativa na rede quanto para visitantes externos. A reutilização de .well-known/nostr.json e o layout com o caminho como chave do objeto permitem que o resolver seja um arquivo estático.

Aberto: gestão de claims de códigos de convite na NIP-86

A PR #2408 propõe três métodos para a NIP-86: listclaims (params [], retorna um array de códigos de convite NIP-43), createclaim (params [claim], retorna true) e deleteclaim (params [claim], retorna true). Hoje, a NIP-86 permite ao administrador de relay gerenciar usuários e atribuições de papéis, mas não oferece uma interface para códigos de convite. O caso de uso do autor é o onboarding em relays de comunidades: o administrador cria um código associado a um papel, recebe o pagamento antes de a identidade do usuário existir, entrega o código, e um bot observa o evento de claim kind 28935 no relay e atribui automaticamente o papel. Os três métodos permitem executar todo esse fluxo pela RPC de gestão do relay.

Aberto: cor de papel como tupla (h, s, l)

A PR #2402 altera o formato de cor de papéis na NIP-43 de um único hue (0 a 360) para uma tupla de hue (0 a 360), saturation (0 a 1) e lightness (0 a 1). Strings vazias são permitidas em qualquer componente para que clientes apliquem seus próprios padrões e mantenham uma paleta coerente, e o texto recomenda fornecer apenas hue, salvo quando se deseja uma cor específica como prata. A mudança atravessa a NIP-86 na mesma PR: createrole e editrole passam a receber [id, label, description, [h, s, l], order]; a assinatura anterior tinha um parâmetro único de cor nessa posição. A motivação é que apenas o hue obriga clientes a escolher saturation e lightness pelo operador, levando clientes diferentes a renderizar o mesmo papel com intensidades visivelmente distintas.

Aberto: proveniência de mídia atestada por hardware NIP-80

A PR #2409 abre a NIP-80, um formato de evento para proveniência de mídia ancorada no hardware de captura. Uma câmera assina cada foto no momento da captura e publica a prova em relays, indexada pelo próprio conteúdo, para que a verificação sobreviva à remoção de metadados, re-hospedagem e retirada por plataformas. A proposta define seis novos kinds: 1080 para atestações de captura; 1081 para atestações de derivação que cobrem redimensionar, recortar, recomprimir ou ocultar, com modo de revelação ou opção de conhecimento zero; 1082 para revogações (eventos regulares, permanentes, limitados ao autor e monotônicos); 11080 para anúncios de dispositivos; 31080 para endossos de dispositivos; e 31081 para um conjunto de dispositivos destinado a atestações anônimas (marcado como experimental e talvez separado em uma NIP complementar). Primitivos reutilizados incluem a semântica da x-tag NIP-94, imeta da NIP-92, NIP-65 para descobrir revogações, Blossom para armazenar mídia e ancoragem opcional de timestamp NIP-03.

O modelo de assinatura combina uma chave de dispositivo BIP-340 com uma chave ECDSA de hardware, porque os secure elements mais comuns ainda não produzem assinaturas BIP-340 (Microchip ATECC608 suporta P-256; NXP SE050 suporta secp256k1, mas apenas ECDSA; módulos TPM 2.0 e Infineon OPTIGA Trust M cobrem P-256/RSA; Apple Secure Enclave e Android StrongBox usam P-256). O escopo declarado não tenta provar que a cena é real: uma atestação prova que esta imagem exata veio deste dispositivo aproximadamente neste horário e só foi alterada das formas declaradas e comprováveis; a especificação proíbe clientes de reduzir os resultados a um simples selo “autêntico”. Um protótipo funcional, OpenVeilCam, runtime de câmera em Rust para Raspberry Pi com secure element ATECC608, está sendo atualizado para publicar os kinds propostos junto a um verificador independente.

Aberto: reforço da paginação na NIP-01

A PR #2407 adiciona à NIP-01 uma subseção “Pagination & limits”. As regras concretas: um relay que impõe um limit máximo DEVE configurá-lo acima do maior número de eventos que compartilham um único created_at em seu banco, para que um segundo não preencha sozinho uma página e trave a paginação. Clientes que paginam para trás DEVEM repetir requisições com until = oldest (inclusivo) e DEVEM remover duplicatas por id, pois o segundo mais antigo é buscado novamente em cada rodada; a paginação termina quando uma rodada não produz eventos novos após a deduplicação. Se uma página cheia tiver os eventos mais antigo e mais novo com o mesmo created_at, o cliente DEVE tentar esse segundo com um limit maior; se o relay limitar o valor e ainda retornar uma página restrita a um segundo, o cliente DEVE avançar com until = oldest - 1 (tratando eventos não recuperados como perdidos) ou abortar. A paginação normal NÃO DEVE definir limit; o máximo do relay é a autoridade, e um valor menor reintroduz o travamento. A exceção é aumentar limit para esvaziar um segundo travado. Isso importa porque um cursor ingênuo de since/until perde eventos com timestamps duplicados ou os reprocessa, e o texto atual da NIP-01 não explica a nenhum dos lados como escapar dessa armadilha.


Análise aprofundada da NIP: NIP-13 (Prova de trabalho)

A NIP-13 define um mecanismo de prova de trabalho para eventos Nostr. Ela existe porque spam semelhante ao de e-mail é trivial em uma rede pública de relays: qualquer pessoa gera um par de chaves e inunda um assunto, sem custo econômico por evento. A NIP-13 permite ao autor impor um custo computacional por evento que um spammer pagaria em conjunto, mas um remetente comum paga apenas uma vez por mensagem. Relays e clientes podem exigir ou preferir eventos que cumpram um limiar de dificuldade.

O mecanismo

O autor escolhe um alvo de dificuldade em bits e minera o id do evento — o hash sha256 do evento serializado — até que tenha ao menos esse número de bits zero iniciais. Como o id inclui o timestamp created_at, as tags e o conteúdo, a mineração precisa alterar algo no corpo para explorar o espaço de hashes. A NIP-13 define a tag nonce exatamente para isso:

["nonce", "<nonce_value>", "<target_bits>"]

nonce_value é qualquer string escolhida pelo minerador; target_bits é a dificuldade com que ele se comprometeu. O verificador conta os bits zero iniciais do id e compara com target_bits. O valor na tag é uma alegação, e o verificador mede a contagem real no id para confirmá-la.

A quantidade de bits zero iniciais em uma saída sha256 aleatória segue uma distribuição geométrica: cada bit adicional dobra o trabalho esperado. Oito bits exigem em média 256 tentativas de hash; 20 bits, cerca de um milhão; e 28 bits, aproximadamente 268 milhões. O alvo de 8 bits do Bitchat para canais de geohash custa menos de um milissegundo de CPU em hardware moderno e termina sem latência perceptível. O padrão de 21 bits do TAO e Wired exige cerca de dois milhões de tentativas por publicação, rápido em um laptop, mas caro em escala para uma fazenda de bots. A NIP-13 não impõe dificuldade; cada relay e cliente escolhe a sua.

Exemplo de evento

Uma nota kind 1 mínima, minerada com NIP-13, é assim:

{
  "id": "000000000e9d97a1ab09fc381030b346cdd7a1a8a6f27c9c88f68c8b9d0f6c8a",
  "pubkey": "82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2",
  "created_at": 1720368000,
  "kind": 1,
  "tags": [
    ["nonce", "72847", "28"]
  ],
  "content": "hello, this cost me 28 bits of PoW",
  "sig": "b1a5c9c74cff59f8a48e5c3b3d8e1c8e7e2c1d4a8e2b9f7d1c3e8b4f6a2c8d1e9f4b3c7a1d8e5b2f9c6a3d7e1b8f4c9a2d6e3b7f1c8a4d9e2b5f8c1a7d4e6b9f3c2"
}

O id começa com sete zeros hexadecimais (28 bits zero iniciais, igual ao target_bits da tag nonce). O minerador variou nonce_value 72847 até o id atingir o alvo. Um verificador calcula o hash do evento serializado e confirma que o id tem ao menos 28 bits zero iniciais, depois verifica a assinatura. A NIP-13 não adiciona campos; adiciona a tag nonce e restringe a contagem de bits zero do id.

Onde é usada

O release 1.5.4 do Bitchat usa PoW de 8 bits em mensagens kind 20000 de canais de geohash: os envios mineram a tag antes da publicação, e eventos recebidos com PoW validada relaxam o limite de entrada por remetente. TAO e Wired usam PoW de 21 bits como limiar padrão de sinal de publicação e exibem raízes do feed com atividade PoW recente, tratando-a como sinal de ordenação da timeline. O cagliostr exige NIP-13 no relay, rejeitando eventos abaixo de um limiar. NoStrudel oferece uma configuração de mineração no cliente para autores que desejam sinalizar a clientes de filtragem. Damus e Amethyst calculam bits zero iniciais ao exibir eventos, permitindo ao usuário ver o compromisso PoW das notas. Coracle oferece PoW tanto para mineração quanto para filtragem. NDK e nostr-tools oferecem helpers de mineração a usuários das bibliotecas.

A propriedade que molda a implantação da NIP-13 é que a PoW não pode ser falsificada: uma alegação de target_bits só conta como evidência quando o id tem aquela quantidade de zeros, e uma falsificação exige refazer o trabalho. Isso permite ao Bitchat usar a PoW recebida para relaxar rate limits mesmo quando um spammer alega alta dificuldade; a verificação é uma contagem de hash, não uma decisão de confiança. A propriedade complementar é que a PoW não vincula o minerador a uma pubkey ou conteúdo específico; um spammer ainda pode minerar a 8 bits e gastar computação, mas esse gasto é real. A NIP-13 transforma o problema do spam de “impossível” em “quantificável” e permite aos clientes definir seu próprio preço.


Análise aprofundada da NIP: NIP-40 (Timestamp de expiração)

A NIP-40 define uma tag expiration que instrui relay e cliente a considerar um evento expirado após determinado timestamp Unix. Ela existe porque eventos Nostr seriam permanentes: depois que um evento assinado chega a um relay, a única forma de removê-lo é um evento de exclusão NIP-09, e mesmo assim o relay pode guardar o original. A NIP-40 permite ao autor declarar na publicação que o evento é temporário e pede aos relays que parem de servi-lo e aos clientes que parem de exibi-lo depois do horário.

O mecanismo

O autor adiciona uma tag expiration ao evento:

["expiration", "<unix_timestamp>"]

O timestamp está em segundos Unix. Um relay PODE rejeitar na entrada eventos cuja expiração já passou, PODE deixar de servir eventos expirados e DEVERIA respeitar a expiração declarada pelo autor. Um cliente DEVERIA ocultar eventos expirados. A NIP-40 não exige que o relay apague o evento nem sobrepõe a semântica de eventos protegidos da NIP-70; ela é uma dica somada a um contrato flexível.

A tag fica no próprio evento ou, em mensagens envolvidas, no wrap externo. A NIP-40 não define semântica de exclusão; o evento continua assinado e qualquer pessoa que o possua ainda pode lê-lo. Ela cria uma expectativa coordenada de que relay e cliente deixem de apresentá-lo após o prazo. Isso torna a NIP-40 útil para posts efêmeros, anúncios temporários, notas de eventos ao vivo que não devem ser servidas depois do fim e mensagens diretas NIP-17 que não devem persistir além de um horizonte declarado.

Interação com gift wrap

A PR do rust-nostr incorporada nesta semana (PR #1384) mostra como a NIP-40 interage com gift wrap da NIP-59. A NIP-59 define um envelope em duas camadas: um evento “seal” kind 13 assinado pela chave real do remetente e um evento “gift wrap” kind 1059 assinado por uma chave efêmera. As duas camadas têm valores created_at aleatórios, até 48 horas antes do envio real, impedindo o observador do relay de descobrir o timestamp verdadeiro. A NIP-59 exige que o seal tenha tags vazias.

Essa exigência faz a tag de expiração ficar no gift wrap, não no seal, e também explica por que ancorá-la à hora real derrotaria a privacidade temporal: se o chamador passasse um timestamp absoluto de expiração, o observador subtrairia o TTL pretendido e recuperaria a hora real. A decisão do rust-nostr é expor a API como uma Duration fornecida pelo chamador e calcular expiration = wrap.created_at + duration dentro da biblioteca. O created_at do wrap já é aleatório, então o timestamp de expiração herda essa aleatoriedade e não revela o envio real.

Exemplo de evento

Um exemplo mínimo de NIP-40 em uma nota kind 1:

{
  "id": "1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b",
  "pubkey": "82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2",
  "created_at": 1720368000,
  "kind": 1,
  "tags": [
    ["expiration", "1720454400"]
  ],
  "content": "this note expires in 24 hours",
  "sig": "d2e5b8a1c4f7b0d3e6a9c2f5b8d1e4a7c0f3b6d9e2a5c8f1b4d7e0a3c6f9b2d5e8a1c4f7b0d3e6a9c2f5b8d1e4a7c0f3b6d9e2a5c8f1b4d7e0a3c6f9b2d5e8a1"
}

created_at é o timestamp Unix da publicação; a tag diz que o evento deve deixar de ser servido 86.400 segundos (24 horas) depois. Um relay compatível para de retorná-lo em REQs após 1720454400, e um cliente compatível o oculta depois desse horário.

Onde é usada

Os builders do rust-nostr (GiftWrapBuilder, PrivateDirectMessageBuilder) agora expõem expiração como parâmetro Duration de primeira classe. NDK oferece um helper de expiração para builders de kind 1 e DM. nostr-tools tem o par getExpiration e isExpired para ler e aplicar a tag. strfry, nostr-rs-relay, khatru e outras implementações respeitam a NIP-40 no tratamento de REQs, rejeitando ou omitindo eventos expirados conforme a política do operador. Damus, Amethyst, noStrudel, Coracle e Primal filtram eventos expirados nas timelines. Clientes de atividade ao vivo como zap.stream usam NIP-40 nos eventos de chat kind 1311 associados, para que o chat não persista após o fim da transmissão.

A propriedade que permite à NIP-40 chegar de forma limpa à maioria das implementações é ser opt-in por evento e não exigir implantação coordenada. Um autor pode adicionar a tag hoje; um relay que a respeita mantém um conjunto de trabalho mais limpo; um relay que a ignora não fica pior do que antes; e um cliente que oculta eventos expirados entrega o que o autor pediu. A mudança desta semana no rust-nostr reforça que a posição da tag importa tanto quanto sua presença: em um envelope que preserva privacidade, como o gift wrap NIP-59, ela fica na camada cujo timestamp já é aleatório, e a API impede que o chamador vaze sem querer um timestamp real de volta para o wrap.


Por esta semana é só. Está construindo algo ou tem notícias para compartilhar? Entre em contato por DM NIP-17 ou nos encontre no Nostr.