From 0d698629a75f21046d6e544b34c42e0b2803b5a9 Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Fri, 2 Oct 2026 21:13:27 -0700 Subject: White Noise (Marmot) chats: MLS group messaging in native JS The Chat tab now speaks the protocol the White Noise app speaks, beside Concord communities and NIP-17 DMs, without anyone having to pick one: - A two-person group with no name is a direct message. It lands in the same thread as that person's NIP-17 messages, and a reply goes back the way their last message came. A first message goes by White Noise only to someone whose KeyPackage another app published (a coinos wallet reads NIP-17 on all its devices; an MLS group reaches one). - Groups get rows of their own in the Messages list, a New group button, an invitation card, members, add/remove/rename for admins, leave. - Every wallet publishes a KeyPackage (kind 30443), so it can be invited. src/mls.js is RFC 9420 for ciphersuite 0x0001 on the noble libs (no WebAssembly), with the extensions-draft pieces Marmot needs (app_data_dictionary, app_data_update, app_ephemeral, self_remove). src/marmot.js is the Marmot layer: components, the account identity proof, the 30443/444/445 event shapes and the group engine (publish-before-apply, retained epochs, same-epoch tie-break). State is per device, in IndexedDB (src/marmot-store.js). The whole stack is one lazy chunk (72 KB). Tested against the RFC 9420 vectors (tools/mls-vectors-test.js) and against the Rust reference, MDK's wn CLI, at the protocol level (tools/marmot-interop-test.js) and through the real UI (tools/marmot-chat-test.js). Not yet: attachments in these chats, push for group messages, the app-message witness boost in fork selection. Co-Authored-By: Claude Fable 5.1 --- src/i18n.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'src/i18n.js') diff --git a/src/i18n.js b/src/i18n.js index 3ced02a..db3f7cf 100644 --- a/src/i18n.js +++ b/src/i18n.js @@ -460,6 +460,34 @@ const STR = { msgNoDmsYet: 'No messages yet. Say hi!', msgDmPlaceholder: 'Message', msgDmEncrypted: 'Private message · end-to-end encrypted', + msgNewGroup: 'New group', + msgGroupName: 'Group name', + msgGroupPeople: 'Add people by name or npub…', + msgGroupCreate: 'Create group', + msgGroupNeedPeople: 'Add at least one person', + msgGroupChecking: 'checking…', + msgGroupCantJoin: "can't join group chats yet", + msgGroupSomeCant: "{names} can't join group chats yet", + msgGroupInvite: '{name} invited you to {group}', + msgGroupUnnamed: 'Group chat', + msgGroupDecline: 'Decline', + msgGroupInfo: 'Private group · end-to-end encrypted', + msgGroupLeave: 'Leave group', + msgGroupRemove: 'Remove', + msgGroupRename: 'Rename', + msgGroupGone: 'You are no longer in this group', + msgGroupNoFiles: "Attachments aren't available in this chat yet", + msgGroupAttachment: 'Attachment', + msgGroupFailed: "Couldn't update the group. Try again", + msgGroupSetup: 'Your signer is needed once to set up group chats', + msgSysAdded: '{a} added {b}', + msgSysJoined: '{b} joined', + msgSysRemoved: '{a} removed {b}', + msgSysLeft: '{b} left', + msgSysAdminAdded: '{b} is now an admin', + msgSysAdminRemoved: '{b} is no longer an admin', + msgSysRenamed: '{a} named the group {name}', + msgSysDisbanded: '{a} ended the group', msgYouPrefix: 'You:', msgOpen: 'Open', msgNpubPlaceholder: 'npub…', -- cgit v1.2.3