Bon retour sur Nostr Compass, votre guide hebdomadaire de Nostr.

Cette semaine : Amber renforce l’authentification relais et chiffre les secrets stockés, Cambium signe pour des sites web sous charge d’auth relais, Citrine héberge des groupes et des sites statiques sur un relais téléphone, Vector met en file la modération sous le spam et synchronise les mutes entre appareils, Sonar ajoute des réponses en fil sur le mesh, Nostria publie des podcasts, et Nail fait le pont entre l’e-mail et Nostr via des gift wraps. Les versions couvrent l’état de groupe MDK, la frappe de badges, l’appairage signataire par QR, la signature navigateur sur Android et une bibliothèque wallet-connect partagée. Le travail protocolaire touche les patches de commentaires, les métadonnées de fichiers chiffrés, le formatage de fils, les garanties de redémarrage Marmot et les listes d’appartenance Concord. Analyses approfondies : badges et commentaires.

À la une

Amber 6.5.0 ferme un confused deputy d’auth relais et chiffre les secrets stockés

Amber est un signataire Android NIP-55 et NIP-46. La version 6.5.0 ferme quatre failles divulguées : un confused deputy dans l’authentification relais qui permettait à tout appelant d’obtenir un événement kind 22242 NIP-42 pour des relais que l’utilisateur n’avait jamais approuvés ; un écart de rejeu NIP-46 ; des secrets de connexion et clés locales en clair désormais chiffrés au repos par enveloppe ; et un lot de durcissement en huit points couvrant l’autorisation de l’appelant avant déchiffrement, un parsing des permissions fail-closed, des avertissements pour le ws:// nu, des écrans QR sécurisés, la rédaction des journaux, l’effacement paresseux des clés à la déconnexion et l’utilisation optionnelle du Keystore sur appareil déverrouillé.

La version 6.5.1 rechiffre les secrets NIP-46 stockés lorsque la clé Keystore tourne après bascule de l’exigence d’appareil déverrouillé et corrige un plantage de l’éditeur de permissions. La version 6.5.2 cesse de déchiffrer des colonnes que la liste d’applications ne rend jamais, met en cache le handle Keystore, préchauffe le cache de compte au démarrage et debounce les notifications d’état relais.

La 6.4.0 de la semaine dernière rendait explicites les décisions de signature groupées ; la 6.5.x change ce qu’Amber autorisera désormais.

Cambium 0.4.0 signe pour des sites web et absorbe les rafales d’auth relais

Cambium est un proxy Android NIP-55 vers un signataire matériel Heartwood via NIP-46. Six versions sont sorties en deux jours.

La version 0.4.0 étend la signature aux sites web. Une page peut demander une signature via un callback nostrsigner: validé sans hériter des permissions accordées aux applications natives, ce qui empêche un onglet navigateur d’emprunter l’approbation d’une autre app. La même version corrige la forme minimale d’événement de la spécification : un événement ne portant que kind et content se signe désormais correctement, Cambium fournissant l’identité NIP-46 associée, l’horodatage courant et un tableau de tags vide avant de remettre l’événement à rust-nostr. L’instrumentation native rust-nostr est devenue une porte CI obligatoire dans le même changement.

La version 0.3.6 répare l’appairage avec des signataires conformes à la spec. L’ancienne build rust-nostr de Cambium n’acceptait que la chaîne littérale ack comme résultat d’un appel NIP-46 connect, si bien qu’un signataire répondant en renvoyant le secret de l’URI bunker — ce que la spec actuelle demande et ce que fait le firmware Heartwood — échouait avec une erreur de réponse inattendue. Le passage de rust-nostr 0.44.2 à 0.44.8 accepte les deux formes, vérifié contre du matériel live et contre nak bunker, qui répond toujours ack.

Les versions 0.4.1 à 0.4.3 concernent le contrôle d’admission sous charge. La version 0.4.1 réserve aux réactions, publications, suppressions et chiffrement un créneau de file d’attente avant l’authentification relais et le déchiffrement en arrière-plan, borne les appels en attente, les jette une fois l’appelant expiré et renvoie un résultat terminal unavailable en surcharge au lieu d’ouvrir un écran de signature au premier plan. La version 0.4.2 jette les sessions NIP-46 expirées ou longtemps inactives avant la requête suivante et laisse des copies concurrentes du même événement d’authentification kind 22242 partager une signature matérielle. La version 0.4.3 n’admet qu’un défi d’authentification distinct par identité dans le worker matériel, ne réessaie jamais l’authentification en interne et ouvre un cooldown de soixante secondes par identité après timeout tout en répondant encore aux doublons exacts en cache. Les mesures des notes de version viennent d’un téléphone GrapheneOS pilotant Amethyst : une rafale au cold start a produit trente-trois réponses overload immédiates et treize requêtes achevées sans timeout signataire, et une connexion fraîche pendant une rafale d’auth est revenue 1,254 seconde après approbation.

Citrine 3.1.0 transforme un relais téléphone en hôte de groupes et de sites

Citrine est un relais Android sur l’appareil. La version 3.1.0 ajoute trois capacités qui changent ce que le relais peut héberger.

Le support de NIP-29, la spécification de groupes basée sur relais où le relais lui-même détient l’appartenance et l’état de modération, signifie qu’un téléphone peut héberger un groupe au lieu d’en rejoindre un. Le support de NIP-86, l’API de gestion de relais qui expose des actions administratives via JSON-RPC authentifié, arrive avec un écran de réglages, de sorte que listes blanches et bannissements peuvent être pilotés depuis l’API comme depuis l’app. Le support des sites statiques NIP-5A laisse le relais servir des nsites aux clients web, avec une liste de navigation modernisée portant icônes, recherche, tri par dernière mise à jour, progression d’installation, descriptions et un ensemble configurable de relais pour les récupérer, par défaut nsite.run, nos.lol et nostr.land.

La surface de modération a grandi en parallèle dans la même version. Bannir une clé publique localement propose désormais de purger les événements stockés de cet auteur, une liste configurable REJECTED_KINDS bloque les kinds que l’opérateur ne veut pas stocker, et le contrôle d’accès peut importer depuis des listes existantes. Un outil de rebroadcast repousse les événements stockés vers des relais sélectionnés, ce qui donne à une archive tenue sur téléphone un moyen de réensemencer le réseau. La version retire aussi l’extension WebSocket permessage-deflate, resserre le hot path des requêtes, corrige Tor qui ne démarrait ou ne s’arrêtait pas quand le réglage d’exposition via Tor changeait, et déplace les journaux dans une base locale avec logcat limité aux builds debug.

Vector 0.4.2 fait survivre la modération communautaire à une vague de spam

Vector est une messagerie Concord pour bureau et Android. La version 0.4.2 se concentre sur la modération sous charge.

Les bannissements rapides s’écrasaient auparavant mutuellement. Ils sont désormais mis en file, empilés et réglés en une seule opération, de sorte qu’une vague de comptes coûte une rotation de clé au lieu d’une par compte. Accepter une invitation dans une communauté depuis dissoute explique maintenant pourquoi et retire l’invitation de chaque appareil de l’utilisateur, et dissoudre une communauté possédée la retire de la liste communautaire partout — correctif arrivé en version 0.4.3. Les messages communautaires arrivant pendant un rattrapage en arrière-plan ne déclenchent plus de notifications comme s’ils venaient d’être envoyés, et l’indicateur de frappe expire à partir du moment de l’envoi pour qu’un signal retardé ne traîne pas dans un canal.

La liste communautaire shardée définie par Concord a passé une revue inter-clients avec Armada, l’autre client Concord. Les renommages ne gonflent plus la liste, les égalités se résolvent identiquement sur les deux clients, et les données inchangées ne sont plus republiées vers les relais. Le mute a aussi quitté le chemin DM : un utilisateur peut désormais muter quelqu’un directement depuis une communauté sans historique de messages préalable, et le mute s’applique aux notifications et badges sur les canaux et DM tout en laissant les messages visibles. Les messages épinglés sont devenus une surface de canal partagée avec liens cliquables, et les modifications d’un épinglé le suivent partout où il apparaît. Listes de blocage, mutes et surnoms se synchronisent entre les appareils d’un utilisateur, de même que les chats épinglés. La version 0.4.3 cesse aussi d’annoncer que l’utilisateur tape quand un autre client Nostr est connecté sous la même identité, et débloque le bootstrap Tor sous Windows, qui restait figé à quinze pour cent sur x64 et ARM64.

Sonar apporte des réponses en fil à une messagerie mesh avec NIP-C7

Sonar est une messagerie mesh Bluetooth et Nostr. La version 0.1-alpha.13.1 ajoute des réponses de type Signal dans le chat kind 9 NIP-C7, plus mentions, réassemblage Bluetooth borné, plafonds de sauvegarde, vérification de signature de chemin mesh et repli push FCM. Les versions 0.1-alpha.13.2 et 0.1-alpha.13.3 corrigent les plantages à l’ouverture du chat sur Android et le chevauchement clavier iOS.

Nostria commence à publier des podcasts et demande aux relais de compter

Nostria est un client web. Les versions 4.1.70 et 4.1.71 ajoutent la publication de podcasts pour abonnés premium, avec épisodes comme événements Nostr signés. La version 4.1.69 utilise NIP-45 COUNT pour les totaux de réactions, réponses et zaps dans les fils et achève la localisation. La 4.1.67 de la semaine dernière a étendu l’administration communautaire chiffrée.

Versions

MDK 0.9.14 : historique de groupe fail-closed via une création de groupe plus rapide

MDK est le kit de développement Rust pour Marmot, un protocole de messagerie de groupe chiffrée transporté sur Nostr. La version 0.9.12 rend plusieurs chemins d’état de groupe fail-closed au lieu de deviner. Une ancre de fork manquante est désormais une erreur dure (PR #1329), une proposition de départ est persistée atomiquement pour qu’un crash ne laisse pas un départ à moitié appliqué (PR #1360), et le replay d’incident refuse de deviner un format sur des flux JSON délimités par newline sans manifeste (PR #1140). Les tests de convergence se sont élargis en parallèle, avec récupération cross-route à historique retenu (PR #1350), assurance de convergence cross-adaptateur (PR #1372) et campagnes de convergence isolée généralisées (PR #1357). Le diagnostic de rejet relais est conservé au lieu d’être réduit à un échec générique (PR #1361).

La version 0.9.13 est arrivée le 18 août avec le format de stockage v2 (PR #1421), rails de migration et écritures delta remplaçant les snapshots de compte live (PR #1435), plus un rattrapage d’invitation plus rapide (PR #1444) et des bindings macOS (PR #1402). La version 0.9.14 a suivi le 19 août avec du polish de création de groupe : images fondatrices pré-téléversées (PR #1498), batching KeyPackage (PR #1494), rétention atomique du message initial (PR #1497) et publication de profil avec relais détenus par le compte (PR #1495). MarmotKit 0.9.14 et wn-agent 0.9.14 sortent avec la crate centrale.

Divine Mobile 1.0.20 : frapper un badge sans quitter l’app

Divine Mobile est un client de vidéos courtes qui publie et récupère de la vidéo via Nostr. La version 1.0.20 permet à un utilisateur de frapper un badge NIP-58, les événements de récompense signés décrits dans la première analyse approfondie de ce numéro, et de le remettre à quelqu’un sans quitter l’app. Toucher un badge sur un profil explique ce qu’il fallait pour le gagner — la partie de la spec souvent non implémentée parce que l’événement de définition et l’événement d’attribution sont stockés séparément.

Le reste de la version est du travail client : thème clair, recadrage, rotation et retournement dans l’éditeur stop-motion, brouillons à un tap du recorder, timing de légende sur la vidéo, un fil qui dépriorise le déjà vu, support lecteur d’écran dans l’éditeur, le recorder et les onglets profil, gestion du mouvement réduit, et réglages de compte pour e-mail et mot de passe Divine et liaison ou déliaison de comptes. Les vidéos supprimées quittent désormais l’état local, et les signets persistent. La 1.0.19 de la semaine dernière a durci l’isolation de compte et la validation des messages privés ; l’émission de badges est une nouvelle surface de publication par-dessus.

ClipRelay 0.2.0 : appairer un signataire avec une caméra

ClipRelay synchronise un presse-papiers entre appareils via Nostr. La version Android 0.2.0 ajoute la connexion QR nostrconnect://, pour se connecter avec une app signataire sur un autre téléphone, et le scan caméra d’URLs bunker, ce qui supprime l’habitude de coller une chaîne porteuse de secret via une messagerie. La connexion bunker expire désormais après soixante secondes au lieu de rester pendue, et le bouton de nouvelle tentative après un échec de connexion Amber fonctionne. La version bureau 0.2.0 reprend le timeout et les correctifs d’onglet de connexion.

La version 0.1.4 avait ajouté la sync de presse-papiers sensible avec courte expiration relais, relais de session signataire épinglés et une sonde de vivacité exigeant un aller-retour réel au lieu d’un EOSE synthétisé localement. La 0.1.3 de la semaine dernière a rétabli les connexions après période d’inactivité.

Bark 1.3.9 : un signataire navigateur qui tourne sur Android

Bark est une extension navigateur qui fournit l’interface window.nostr NIP-07, l’objet qu’une page web appelle pour demander une signature ou une opération de chiffrement. La version 1.3.9 déclare le support Android pour la build Firefox, de sorte que la liste des modules s’installe sur un téléphone. Firefox sur Android n’implémente pas l’API windows, donc toute approbation ouvrant une fenêtre popup aurait été refusée purement et simplement ; la surface d’approbation retombe désormais sur un onglet au premier plan où fermer refuse, une action de revue le met au premier plan, et l’arrière-plan se ferme une fois la requête réglée. Les notes de version enregistrent une vérification sur un Pixel 10 Pro XL sous GrapheneOS avec Firefox 153.0.4, et indiquent clairement que Chromium sur Android compile hors le sous-système d’extensions, donc aucun navigateur Android dérivé de Chromium ne peut exécuter Bark.

La version 1.3.8 corrige un défaut d’interop NIP-46 dans l’autre sens. Bark sonde un dialecte de signature Heartwood compact en envoyant l’événement comme objet JSON, que des signataires strictement typés incluant nak et des bunkers construits sur rust-nostr ne peuvent pas parser et jettent silencieusement, si bien que la signature restait pendue. La sonde n’est envoyée qu’aux signataires s’étant identifiés comme Heartwood, et tout autre signataire reçoit un appel sign_event standard dès la première signature.

Bray 3.0.0 et Toll Booth 6.0.0 passent à une bibliothèque wallet-connect partagée

Bray et Toll Booth paient tous deux via Nostr Wallet Connect NIP-47, la spec qui laisse une application demander des paiements à un portefeuille via des événements Nostr chiffrés. Bray 3.0.0 et Toll Booth 6.0.0 déclarent chacun un breaking change adoptant nwc-kit pour les paiements portefeuille, et Toll Booth retire son flux d’identifiants payeur dans le même changement. Les deux publient des builds reproductibles dont la sortie était byte-identique sur deux runners indépendants, avec le hash tarball imprimé dans les notes de version pour qu’un lecteur puisse vérifier l’artefact registry.

Trois patches Toll Booth ont suivi : 6.0.1 épingle la clé hôte de déploiement négociée, 6.1.1 épingle cashu-ts à la version visée par son patch, et 6.1.2 rétablit une build d’image.

NoorNote 1.3.4 : rejoindre des communautés chiffrées depuis un lien d’invitation

NoorNote est un client Nostr pour bureau, web et Android. La version 1.3.4 ajoute les communautés Armada et Concord chiffrées comme addon : un utilisateur rejoint via un lien d’invitation, voit les communautés rejointes listées dans les réglages et reçoit des notifications d’activité. La même version ajoute un contrôle pour masquer les quote-posts externes, les notes surlignées citant un paragraphe d’article web, globalement ou par auteur, avec les reposts d’entre eux masqués aussi et les propres surlignés de l’utilisateur laissés visibles. La résolution de profil a aussi été réparée, de sorte que les profils ne s’affichent plus comme une clé publique tronquée ou un placeholder anonyme.

La version 1.3.5 ajoute un expander pour les longues notes et corrige la disposition du champ de saisie du lien d’invitation Armada. La 1.3.2 de la semaine dernière a déplacé la découverte d’articles dans le graphe social ; l’appartenance communautaire est une surface distincte.

Mostro déplace le chat de litige hors du gift wrap

Mostro est un daemon d’échange pair à pair dont ordres et messages circulent comme événements Nostr, avec mostro-core comme bibliothèque partagée et Mostro Mobile comme client. Mobile 1.3.2 migre le chat de litige du gift wrap NIP-59 vers une enveloppe de chat kind 14 et sécurise le backlog avec des curseurs durables par conversation. mostro-core 0.14.5 sérialise l’identifiant rumor dans le gift wrap (PR #164), 0.14.4 corrige un bug de moyenne de notes (PR #163), et Mobile 1.3.1 passe à des serveurs Blossom conservant les pièces jointes de chat chiffrées. Utiliser le daemon 0.18.2 ou 0.18.4.

NYM 3.73.522 : chats de groupe chiffrés et stockage local chiffré

NYM est un client Nostr avec sa propre intégration d’assistant. La version 3.73.522 chiffre le stockage SQLite local après que 3.73.521 a affiné le chat de groupe chiffré, et 3.73.520 corrige une rupture de content-security-policy et une double présentation de nouveau message.

Morganite 0.0.4 : vérifier un blob avant de le mettre en cache

Morganite est un serveur Android Blossom, le protocole média où un fichier est adressé par le hash SHA-256 de son contenu et servi depuis tout hôte qui le détient. La version 0.0.4 vérifie le hash d’un blob pendant le téléchargement en un seul passage avant de le mettre en cache — le contrôle qui rend l’adressage de contenu significatif côté réception. La version suit aussi la taille de cache de façon incrémentale au lieu de rescanner le répertoire à chaque sauvegarde, déplace les appels réseau bloquants sur des threads d’entrée-sortie, réutilise des instances Tika pour la détection MIME et persiste les journaux dans une base locale.

Nouveautés découvertes

Nail amène l’e-mail sur Nostr comme événements gift-wrapped

Nail est un pont mail et client web sous licence MIT de l’équipe Formstr, le groupe derrière Formstr et nostr-calendar. Lancement le 18 août avec PR #7, un changement de 22 fichiers ajoutant des tags k aux événements mail, récupération de clé dans les réglages et un message de bienvenue. Son déploiement tourne sur mailstr.app, qui sert l’enregistrement _smtp NIP-05 propre au pont, le schéma DNS qui mappe un nom de domaine à une clé publique Nostr.

Le mail lui-même est un événement Nostr. Les constantes du client définissent un rumor mail kind 1301 porté dans un gift wrap kind 1059 NIP-59, de sorte qu’un message atteint son destinataire via la même enveloppe masquant les métadonnées que les DM privés. Les relais de livraison viennent d’une liste de boîte de réception kind 10050 NIP-17 avec une liste de relais kind 10002 NIP-65 derrière, les dossiers sont des labels kind 1985 NIP-32 sous un espace de noms mail, et les réglages client vivent dans un événement de données d’application kind 30078 NIP-78. Les pièces jointes au-delà de 60 000 octets vont sur Blossom au lieu de l’événement, parce que NIP-44 plafonne le texte clair chiffré à 65 535 octets. Une adresse est un npub sur un domaine, et un domaine local sans enregistrement NIP-05 est traité comme une boîte inexistante.

La moitié pont est un serveur Node LMTP tournant à côté d’un déploiement mailcow sans le patcher : Postfix route les domaines correspondants vers le pont, et le pont injecte les réponses via SMTP. Ce design force une réponse honnête à la question la plus dure d’un pont e-mail : que prouve un en-tête From ? Le chemin de réception de Nail classe chaque message dans l’un de quatre états de provenance : le pont configuré l’a scellé et refuse de relayer un expéditeur qu’il n’a pas vérifié en amont, l’utilisateur l’a scellé lui-même, l’enregistrement NIP-05 de l’adresse se résout sur la clé de scellement, ou rien ne corrobore l’en-tête. Dans ce dernier cas l’interface retombe sur la clé publique de scellement, la seule identité que l’événement peut réellement prouver. Les appels API pont s’authentifient avec des événements HTTP signés NIP-98.

Glow stocke des labels de portefeuille sur les relais sous une identité dérivée de passkey

Glow est un portefeuille Lightning auto-dépositaire de Breez. La connexion passkey dérive une identité Nostr, et les labels de portefeuille se listent depuis et s’enregistrent vers les relais sous cette identité, avec des doublons byte-identiques réduits sur une couverture relais partielle.

En développement

Amethyst reconstruit le flux de décision d’authentification relais

Amethyst est un client Nostr Android. Un bloc de travail fusionné remodele la gestion de l’authentification client-relais NIP-42. L’interface de permissions et le flux de décision ont été repensés (PR #3899), l’authentification attend désormais la résolution d’un défi au lieu d’expirer (PR #3905), les nouveaux comptes s’authentifient par défaut toujours avec les relais (PR #3931), et un choix « toujours se connecter » est honoré pour les relais que le compte n’utilise pas lui-même (PR #3937). L’authentification reconnaît aussi les groupes NIP-29 et les communautés Concord comme lieux rejoints (PR #3906), ce qui empêche un groupe hébergé sur relais de ressembler à un relais inconnu à chaque ouverture.

Deux autres changements touchent des surfaces protocolaires. Le minage proof-of-work sous NIP-13 rafraîchit created_at pendant le minage et gagne une analyse de chemin GPU (PR #3911), et les hôtes napplet plein écran gèrent les insets de méthode de saisie (PR #3932). Une sauvegarde de clé guidée au premier lancement avec point d’entrée dans les réglages a aussi fusionné (PR #3909), aux côtés de la possibilité de muter des chats publics (PR #3939).

nostrord implémente une proposition de clé de chiffrement non fusionnée

nostrord est un client de chat Nostr organisé autour de groupes scoped relais. Il a fusionné une implémentation de NIP-4e, une proposition non fusionnée pour découpler le chiffrement de message de la clé d’identité que Compass a décrite pour la dernière fois dans le numéro du 15 juillet. Le compte annonce sa propre clé de chiffrement kind 10044, détient la moitié privée localement et déchiffre les DM entrants in-process, ce qui sort un bunker ou une extension navigateur du chemin de lecture (PR #261). L’appairage d’appareils via kinds 4454 et 4455 déplace cette clé vers un second appareil, et une auto-archive republie l’historique adressé à la nouvelle clé. L’envoi visait d’abord la clé annoncée (PR #247), et un suivi corrige l’appairage qui négociait avec succès sans remettre la clé (PR #271). La pull request indique que le format wire suit l’implémentation Jumble déployée là où elle diverge de la proposition ouverte, ce qui place la définition de travail de cette spec dans du code livré plutôt que dans le document.

L’identité de groupe a été resserrée dans le même lot. Un identifiant de groupe n’est unique que dans son relais (PR #269), donc le même identifiant sur deux relais est traité comme deux groupes (PR #272), et les posts de fil s’affichent comme posts de forum (PR #274). Le churn de connexion produisant des invites de signature kind 22242 répétées a aussi été stoppé (PR #268), la même classe de pression signataire sur laquelle Cambium a passé trois versions cette semaine.

nostream ajoute un moniteur de relais et frappe des codes d’invitation

nostream est une implémentation de relais TypeScript. Il a fusionné un worker cluster et un planificateur de sondes publiant des événements de monitoring relais NIP-66, la spec de découverte qui laisse un moniteur annoncer vivacité et données de capacité sur d’autres relais (PR #724), avec schéma de réglages et valeurs par défaut (PR #689) et tests d’intégration (PR #733). Un outil CLI frappe désormais des codes d’invitation NIP-43, le schéma de métadonnées d’accès relais qui conditionne l’admission (PR #732), et le relais annonce enfin la preuve de travail NIP-13 dans sa liste supportée (PR #680), qu’il avait implémentée sans l’annoncer. Les jobs data vending machine ont aussi gagné une migration de persistance et un dépôt (PR #727), et le relais intercepte NIP-90 (requêtes de jobs data-vending-machine) et les enregistre via le dépôt de jobs (PR #729).

rust-nostr corrige un identifiant gift wrap et rejette les reposts protégés

rust-nostr est la bibliothèque Rust et le kit de développement derrière une large part du travail client Rust et mobile de ce numéro. Il garantit désormais que l’identifiant rumor est calculé avant que le scellement gift wrap ne soit chiffré (PR #1444), la même classe de défaut que Mostro a corrigée dans sa propre bibliothèque cette semaine. Son relais local rejette un repost d’un événement protégé NIP-70 (PR #1445), la protection pour laquelle cette spec existe, et le parsing de réponse NIP-47 tolère montants manquants et null (PR #1450) au lieu d’échouer sur un portefeuille qui les omet. Le parsing d’URL relais a été durci (PR #1451).

NDK ajoute des DM post-quantiques et supprime une dépendance GPL

NDK est un kit de développement Dart pour Nostr. Il a fusionné un chiffrement post-quantique hybride pour les DM utilisant ML-KEM-1024, le mécanisme d’encapsulation de clé sur réseau standardisé FIPS 203 (PR #713), à côté de l’accord de clé classique au lieu de le remplacer. Un changement séparé a remplacé une implémentation Dilithium GPL-3.0-only par fips204, le standard de signature ML-DSA (PR #712), ce qui supprime une contrainte de licence pour les applications embarquant le kit. Les connexions sont aussi passées à une identité chacune (PR #710).

Nostter ajoute listes de signets, badges de profil et téléversements Blossom

Nostter est un client web. Il a fusionné le support des formes standard et legacy des listes de signets NIP-51 (PR #2311), mis à jour sa gestion des badges de profil NIP-58 (PR #2281), ajouté un uploader média Blossom (PR #2298), et affiche désormais un identifiant NIP-05, le nom de vérification DNS, dans l’autocomplétion de mentions (PR #2303).

Zap Cooking lie les routes admin à des requêtes signées et chiffre les connexions portefeuille stockées

Zap Cooking est un site de recettes construit sur des événements Nostr long-form. Un lot sécurité chiffre au repos les chaînes de connexion Nostr Wallet Connect dans une enveloppe NIP-44 (PR #622), remplace une comparaison de clé publique spoofable sur les routes admin par l’authentification HTTP NIP-98, le schéma qui signe un événement pour autoriser une requête HTTP (PR #626), et efface les données de compte à la déconnexion tout en bornant les enregistrements NIP-46 en attente (PR #627).

Mises à jour des NIP et travail de spécification du protocole

NIPs

Aucune pull request n’a fusionné dans nostr-protocol/nips pendant cette fenêtre. Six propositions ont été ouvertes après la clôture du numéro précédent, trois d’entre elles le 18 août après la première circulation du brouillon.

NIPs PR #2438 propose NIP-9A, le patch par commentaires. Un patch est un commentaire kind 1111 référençant l’événement patché comme parent dont le content commence par le label littéral PATCH, suivi de lignes de patch. Une ligne commençant par un chiffre édite le content de la cible sous la forme <index> -<deleted> +<inserted> <caractères insérés>, comptés en caractères Unicode au lieu d’octets, et une ligne commençant par t remplace un tag lisible comme title, description, subject ou picture. Le design est délibérément rétrocompatible : un client qui ne comprend pas le format affiche le patch comme un commentaire étiqueté ordinaire, et un client qui le comprend applique le patch et masque le commentaire. La proposition nomme kinds 1, 11, 1111, 24 et 1621 comme patchables et demande aux auteurs et lecteurs de refuser des patches trop grands, trop nombreux ou publiés longtemps après l’événement original — tentative explicite d’empêcher la fonctionnalité de devenir un canal d’édition général pour des événements immuables.

NIPs PR #2437 propose le chiffrement de fichiers pour NIP-94, la spec de métadonnées de fichier décrivant un fichier téléversé dans un événement kind 1063. Elle ajoute trois tags optionnels : encryption-algorithm, avec aes-gcm comme seule valeur listée, plus decryption-key et decryption-nonce encodés en hex. La sémantique des tags se déplace en conséquence, avec m décrivant le type MIME avant chiffrement, x tenant le hash du fichier chiffré, et ox le hash de l’original, et toute source thumb, image et fallback chiffrée sous la même clé et le même nonce. L’objectif déclaré est qu’un opérateur Blossom public hébergeant les octets ne puisse pas dire ce qu’ils sont, et l’auteur cadre le changement comme copier les propriétés de chiffrement de message privé NIP-17 dans les métadonnées de fichier pour que le même traitement fonctionne dans un tag imeta.

NIPs PR #2436 amende NIP-7D, la spec de fil de forum construite sur des événements de fil kind 11 avec commentaires kind 1111 NIP-22 comme réponses. Elle ajoute une section de formatage indiquant qu’un post de fil peut être formaté comme une note kind 1, avec images inline, liens et références NIP-27, et pourrait aussi supporter Djot, un langage de balisage léger à grammaire non ambiguë. L’argument de l’auteur est que laisser le formatage non spécifié invite à une implémentation Markdown par défaut plus tard, et la pull request pointe vers squalk comme implémentation Djot existante.

NIPs PR #2439 ajoute les méthodes assign et unassign à NIP-86 (commandes de gestion de relais), pour qu’un administrateur de relais accorde des permissions admin à une autre pubkey sans partager la clé maîtresse.

NIPs PR #2442 succède à la proposition de piste audio que Compass a couverte en janvier pendant que ce brouillon restait ouvert ; la pull request antérieure s’est depuis fermée et celle-ci shippe en production sur lightning.fm comme événements de piste kind 31337, avec objets release kind 31339, profils de groupe, contributeurs par piste et splits zap NIP-57 optionnels tout en gardant les ventes sous NIP-99. Le contrat d’interop est publié sur lightning.fm/interop, et l’éditeur bureau et le daemon vendeur auto-hébergé sont open source.

Marmot

Marmot PR #416 a fusionné le 13 août et ajoute un contrat de durabilité et de redémarrage au cœur protocolaire. Les documents adoptés définissaient déjà convergence déterministe, matériel candidate-parent retenu, ordre publish-before-apply et comportement fail-closed sur historique manquant, sans règle sans ambiguïté pour une interruption de processus aux coutures entre eux. Le changement définit faits logiques recoverables, équivalence de redémarrage, frontières d’interruption de publication et de convergence, transitions observer-atomiques, gestion de matériel manquant ou corrompu et récupération d’effet d’application, puis ajoute des scénarios de conformité crash et redémarrage pour chacun. Il laisse transactions, journaux, snapshots, stratégie de replay, planificateurs et formats de stockage définis par implémentation, et indique qu’aucun changement d’encodage wire n’est requis. L’échec spécifique qu’il exclut est une publication acceptée en externe mais non confirmée localement, ou une branche sélectionnée partiellement appliquée, produisant des résultats protocolaires dépendants de l’implémentation après redémarrage.

Concord et CORDs

Concord PR #18, couvert précédemment dans le numéro de la semaine dernière comme proposition ouverte, a fusionné le 15 août. Il shard la liste communautaire chiffrée à travers des événements kind 33302, supprime la limite de cinquante appartenances et élague les entrées retirées pour que la liste reste dans les limites de taille relais. Les notes de version de Vector cette semaine enregistrent la moitié client de ce changement, incluant résolution d’égalité et la décision de ne plus republier des données inchangées.

Concord PR #22 propose des brokers audio et vidéo détenus par la communauté. L’entité métadonnées CORD-02 porterait une liste optionnelle av_brokers à côté de ses relais, évoluant par édition comme le reste de cette entité, et le rendez-vous CORD-07 puiserait dans cette liste, ou depuis le broker propre au membre quand la communauté n’en publie aucun, ordonné par le tie-break room-keyed existant. Le tag broker sur la présence reste lisible et utile pour signaler une scission résiduelle, et l’argument de la proposition pour le rétrograder du routage est direct : router dessus laisse une entrée non fiable d’un autre membre l’emporter sur l’instruction propre à la communauté.

Concord PR #23 rend normatif dans CORD-05 un comportement d’implémentation existant. Avant de persister une adhésion, l’édition métadonnées genesis du propriétaire doit s’ouvrir sous les clés livrées, avec plans pivotés ancrés sur la paire de compaction. La pull request indique d’emblée que ce n’a jamais été une vulnérabilité live : l’acceptation de bundle de Vector refuse déjà un bundle dont la racine livrée ne peut pas ouvrir la genesis du propriétaire et ne garde jamais une invitation pour une communauté déjà détenue, et Armada jette déjà tout bundle qui déplacerait la base d’une communauté détenue. L’écart était l’absence d’exigence dans la spec, donc un client fidèle à la spec aurait pu livrer la version vulnérable.

Les documents de mise à niveau Blossom, les propositions d’application Napplet et la spécification Gamma Markets n’ont enregistré aucun changement dans cette fenêtre.

Analyse approfondie de NIP

Badges (NIP-58)

NIP-58, défini par sa spécification primaire, donne à une identité Nostr un moyen d’accorder un jeton nommé à une autre, et au destinataire le contrôle de savoir s’il apparaît sur son profil. Le problème qu’il adresse est qu’une déclaration sur une personne sur Nostr n’est autrement qu’une note : il n’y a pas de structure disant qui a émis une affirmation, comment elle s’appelle, à quoi elle ressemble, ou si le sujet l’a acceptée. Les badges donnent à cette affirmation trois événements signés distincts avec trois intentions d’auteurs distinctes encodées.

La mécanique repose sur une définition adressable, une attribution et une liste d’affichage. Une définition de badge est un événement kind 30009 publié par l’émetteur, adressable via son tag d, de sorte que l’émetteur peut réviser plus tard les tags name, description, image et thumb du badge sans changer l’identifiant vers lequel autre chose pointe. L’attribution est un événement kind 8 publié par le même émetteur, portant un tag a tenant la coordonnée 30009:<issuer-pubkey>:<d-identifier> de la définition et un ou plusieurs tags p nommant des destinataires. La liste d’affichage est un événement kind 30008 publié par le destinataire avec la valeur d fixe profile_badges, listant des paires de tags a et e où le tag a est la coordonnée de définition et le tag e l’événement d’attribution spécifique. Ces paires sont ordonnées et lues comme paires : un tag a sans attribution correspondante, ou un tag e sans définition correspondante, est ignoré, donc un badge à demi référencé ne s’affiche silencieusement pas.

Les compromis de design sont visibles dans ce que la spécification refuse de faire. Il n’y a pas de mécanisme de révocation ni d’expiration, donc une attribution est une déclaration permanente de l’émetteur sur un moment dans le temps, et un émetteur qui change d’avis ne peut que changer la définition vers laquelle l’attribution pointe. Il n’y a pas de transfert, donc un badge ne circule pas comme jeton. Il n’y a pas de registre d’émetteurs de confiance, ce qui reporte toute la question de confiance sur le client et le lecteur : un badge vaut exactement ce que vaut la clé publique de son émetteur pour la personne qui le regarde. La spec accorde aussi aux clients la latitude d’afficher moins de badges que le destinataire en a listé et de choisir quelle taille d’image rendre, ce qui empêche un profil de devenir un mur de graphiques choisis entièrement par des tiers.

La spec adjacente la plus proche est NIP-51, la spec de listes, et comparer les deux montre pourquoi les badges ont besoin de trois événements au lieu d’un. Une liste est un auteur qui sélectionne des références ; l’auteur de la liste est l’auteur de l’affirmation. Un badge partage l’autorité en deux : l’émetteur signe que l’attribution a eu lieu et le destinataire signe qu’il accepte son affichage. Aucune des deux parties ne peut produire seule le résultat visible, ce qui sépare un badge d’une étiquette auto-appliquée.

Un événement kind 8 d’attribution live récupéré depuis nos.lol et relay.primal.net cette semaine :

{
  "id": "08504dec368939bd63849a349cab83dea0ac199a852129dbf68cf35fe5c64e96",
  "pubkey": "bef514bd58c8ceea4beb9e6b84a8d983935f7be26f49e14df68098f1ba64156e",
  "created_at": 1787051248,
  "kind": 8,
  "tags": [
    ["a", "30009:bef514bd58c8ceea4beb9e6b84a8d983935f7be26f49e14df68098f1ba64156e:blocks_orange_league"],
    ["p", "92dfa05d915196a7a09152fa3f57871debfd422e1d278ac5af266a70c3350b1f", "wss://relay.damus.io"]
  ],
  "content": "Badge awarded!",
  "sig": "5bf0218dfec5e56b47339b0b4b992cceedd2e18798fb3d47cafea51850c00827f66251e4a3e08190370e04a5e1d4d092eeb441141b7219acdd18b80290a022f8"
}

Les implémentations actuelles couvrent émission, affichage et lecture. Divine Mobile 1.0.20 frappe et accorde un badge dans l’app et explique un badge gagné quand un lecteur le touche, Nostter PR #2281 met à jour la gestion des badges de profil dans un client web, et Amethyst publie des événements d’attribution portant son propre tag client, l’un d’eux apparaissant dans les données relais aux côtés de l’exemple ci-dessus.

Commentaires (NIP-22)

NIP-22, défini par sa spécification primaire, fournit un événement de commentaire général pour répondre à des choses qui ne sont pas des notes texte court. Le fil de notes courtes avait déjà NIP-10, dont les conventions de tags ont grandi autour du kind 1 et de ses chaînes de réponses. NIP-22 existe parce qu’une vidéo, un article, un événement calendrier, une page wiki ou une URL a besoin d’une structure de réponse identifiant quel type de chose est visé, et que cela fonctionne quand la cible est adressable, ou est une ressource externe sans événement Nostr du tout.

La mécanique repose sur une distinction de casse. Un commentaire est un événement kind 1111 portant deux jeux de tags : tags majuscules décrivant la racine de la discussion et tags minuscules décrivant le parent immédiat. E, A et I nomment un événement racine, une coordonnée adressable racine ou un identifiant externe racine, K nomme le kind de la racine, et P nomme l’auteur racine. Les minuscules e, a, i, k et p nomment les mêmes faits sur le parent, qui est la racine elle-même pour un commentaire de premier niveau et un autre commentaire kind 1111 pour une réponse imbriquée. Les séparer permet à un client de récupérer toute une discussion avec un filtre sur les tags racine majuscules, sans parcourir la chaîne de réponses, tout en rendant correctement l’imbrication depuis les tags parent minuscules. Les variantes I et i portent des identifiants externes au format NIP-73, ce qui permet à un fil de commentaires de s’attacher à une page web, un épisode de podcast ou un livre.

Les compromis concernent surtout ce que NIP-22 décline d’absorber. La spécification indique que les commentaires ne doivent pas servir à répondre à des notes kind 1, ce qui empêche deux modèles de fil de concurrencer sur les mêmes objets et laisse NIP-10 en place là où il fonctionne déjà. L’imbrication est permise mais la racine reste fixe, donc un fil profond ne perd jamais son ancre même quand des événements intermédiaires sont indisponibles. Les tags kind portent la charge : un client qui récupère un commentaire sans sa cible peut encore dire à quoi il a affaire depuis K et k, et décider s’il peut rendre ce kind. Ce que la spec ne fournit pas est un modèle d’ordonnancement ou de modération, donc ordre d’affichage, repli et masquage relèvent entièrement de la politique client.

Comparé à NIP-10, la différence est dans le typage. NIP-10 suppose que la cible est une note et encode la position dans un fil ; NIP-22 encode explicitement l’identité et le kind de la cible et ne suppose rien d’autre à son sujet. Ce typage explicite est pourquoi les propositions plus récentes de ce numéro visent le kind 1111 : un commentaire porte déjà une déclaration machine-lisible de ce à quoi il est attaché.

Un commentaire kind 1111 live récupéré depuis nos.lol et relay.primal.net cette semaine, répondant à un autre commentaire sous une vidéo :

{
  "id": "c8d335f8bfea58ecd1a943d6000fb2045f4bddf4a36c67df53eb661671f7ab45",
  "pubkey": "3e911baba55ae247339cf805dd6ff49ad2cd6bee84ac44e088ce66450c49104f",
  "created_at": 1787062681,
  "kind": 1111,
  "tags": [
    ["E", "1c492f2bac17b79d66934a340fa43d8d30d0aea4c9fa329346c05573ef912d70", "", "482d024b8acfde50e7429e5ac561d764f3a53a8b4fb0b6975369d9f0926ef839"],
    ["A", "34236:482d024b8acfde50e7429e5ac561d764f3a53a8b4fb0b6975369d9f0926ef839:e64ba9ea157b1a315caff51dbca656ed73ce817d4494e3966adf24055a86f5c5", ""],
    ["K", "34236"],
    ["P", "482d024b8acfde50e7429e5ac561d764f3a53a8b4fb0b6975369d9f0926ef839"],
    ["e", "7a14723b9ef999e74b1757a0fb74942cb6c121138d4ddafe096a57a67ed0a442", "", "8b69e548402afa997343d73e8088224a440f256350f6257b61acc4bb1fa4af4f"],
    ["k", "1111"],
    ["p", "8b69e548402afa997343d73e8088224a440f256350f6257b61acc4bb1fa4af4f"],
    ["client", "Divine", "31990:d95aa8fc0eff8e488952495b8064991d27fb96ed8652f12cdedc5a4e8b5ae540:divine-mobile", "wss://relay.divine.video"]
  ],
  "content": "niiice",
  "sig": "a5517fdea07647efa7ab1730fbea8df882690bba667e93ea5aeba4a73be6a49af1ee17c045535483650caf41dbbcb0897d5803fa39b59f395fd6f9bb193bb789"
}

Les tags majuscules tiennent la vidéo et son auteur tandis que les minuscules e et k pointent vers le commentaire parent — la forme que décrit la spec. Les implémentations lisant et écrivant kind 1111 incluent Divine Mobile, dont le tag client apparaît dans l’événement ci-dessus, Amethyst, dont les commentaires apparaissent dans les mêmes résultats relais, et nostrord, qui rend les posts de fil comme posts de forum cette semaine. Le format de patch proposé dans NIPs PR #2438 s’appuie sur le même kind.


Envoyez un DM NIP-17 pour partager un projet ou une actualité via le projet Nostr Compass.