You’re right, the interoperability means you can communicate in the same group between Whitenoise and 0xChat, but the MLS state on different devices and clients is stored locally and can’t sync.

However, maybe in the future, we could enable transferring that state to other clients or devices in a secure way, such as encrypting it and transferring it via Bluetooth or local network.

Reply to this note

Please Login to reply.

Discussion

Got it. That's still really far along, congrats to all.

:110percent: need that state sharing yes.

If you have your own relay that you Auth on, it can be relatively straightforward.

Or if the group has their own relay, cool stuff can be done too.

I like the incentives there.

Want great UX, frictionless state sharing, extra privacy guarantees, ... 👉 Get a relay.

MLS stores key packages on the local device, so for state sharing, we need to migrate this part. The remaining events can be synced via relays. I also agree with you — having a private relay is a better choice, especially one relay per group. This is also a key design focus for me in 0xchat lite.

I went from thinking multiple redundant relays were Nostr's superpower to thinking Nostr is best without that—it's other things that are the real superpower. At least for use cases that can scale.

This 💯

still compiling*/*ya t *Y*

Great to hear!

We're working on an all-in-one solution for Communitues and Private groups.

Both relay and blossom (and maybe even mint at some point).

That sounds really interesting! It seems like it has some similarities to 0xchat lite I'm currently working on.

Anything we can read?

not yet, just code atm 😆

I wonder if AndOtherStuff is intended as a fund for community projects in general, or if it's to be a fund only disbursed to the specific community initiatives listed there already?

Very unclear for now.

I doubt they'll be into #communikeys anytime soon tho. So not counting on anything from that side for Zapchat yet.

Even if we do MLS etc...

Yeah, didn't see any announcement or call for proposals. Wait and see i guess.

#Vibe doesn't seem to incentivize much transparency so far lol 😜

We went from "build in public" to "build in vibe and release vague stuff".

https://treasures.to/ To be fair it's pretty nuts you can just prompt something like this into life.

With Zaplab we'll have a #stack that can vibe apps like this that tap straight into your Communities etc...

One content type apps like this are perfect for vibing.

- work outs

- treasures

- quizzes

- slide decks

- ....

In MLS, multi-device sync is achieved by multiple device IDs (leaf nodes) sharing a single user identity. Each device has its own leaf but proves it belongs to the same user via the same identity credential.

Each device joins the same MLS group as a separate leaf node, but all represent the same user.

Will Keychat, 0xchat and White Noise all be able to interoperate? I can't quite picture how the UX would work if I create a group in Keychat and then somehow who uses 0xchat or White Noise wants to join.

Interoperability between the three clients in an MLS group isn’t hard, since they’re all built on OpenMLS and use shared relays.

The main difference is that Keychat uses a different “envelope” format for MLS messages compared to the other two clients. We need to write a note explaining the design rationale behind this “envelope” format, and we truly hope to have 0xChat’s understanding and support.

Is there any specification available regarding this envelope format?

We've been using the metaphor of a letter: the envelope is where the sending and receiving addresses are written. To protect metadata privacy, both the sending and receiving addresses need to be updated frequently.

NIP-EE group events

{

"id": ,

"kind": 445,

"created_at": ,

"pubkey": ,

"content": ,

"tags": [

["h", ]

],

"sig":

}

In the NIP-EE group event, the content field is first encrypted using MLS, and then encrypted again using NIP-44. The NIP-44 encryption is done using a Nostr keypair generated from the MLS exporter_secret to calculate the conversation key value. Keychat follows the same approach. The public key—used as the sender address—is randomly generated, and Keychat does this as well.

The difference lies in the receiving address. In NIP-EE, the receiving address is set using:

"tags": [ ["h", ] ]

The h tag represents the Nostr group ID (from the Nostr Group Data Extension). Updating the group ID requires a member to send a commit message.

Keychat, on the other hand, uses:

"tags": [ ["p", ] ]

This receiverPublicKey is derived from the MLS exporter_secret, so it updates automatically without the need for a separate commit message.

Keychat uses kind: 1059, as it satisfies the constraints of kind 1059, enabling the integration of both MLS messages and NIP-17 DMs in a unified format.

Thanks for the information! From what I understand, the Nostr group ID probably doesn't need to change—but please correct me if I'm wrong. That said, I do think using a pubkey derived from the exporter_secret as the receiver is a good idea.

Using different kind values for MLS messages might be better than sharing kind 1059, since they serve different purposes—especially when it comes to filtering MLS messages specifically.

If there are differing opinions, perhaps it would be a good idea to propose a new NIP or extend NIP-EE. That way, different clients can work together to choose a solution that fits best for everyone.

Really glad you like the idea of deriving the receiving address from the exporter_secret.

If the Nostr group ID doesn't change, external observers can see how frequently and at what times the group communicates, even though the ID itself is anonymous. If I remember correctly, NIP-EE just hasn't specified how to update this ID yet, but it plans to in the future.

A gift wrap event is a kind:1059 event that wraps any other event. It's a general-purpose gift wrap — the inner event can be of any kind. Think about NIP-17 DMs: external observers can only see that it's a kind:1059 event.

And how about the keypackages?

Keychat's current MLS KeyPackage event is a replaceable event, which makes it easier to update and manage the KeyPackage. Events are replaceable, which means that for each combination of pubkey and kind, only the latest event must be stored by relays, and older versions may be discarded.

In addition, after a new member joins a group, an update commit is performed immediately.

Keychat can also publish the KeyPackage using NIP-EE’s kind: 443.

What do you think about using replaceable events to update and manage KeyPackages?

Yes, I agree that using replaceable events helps reduce the need for manual deletion and management—I’ve considered this before as well.

And I think we could even use addressable events, with the d tag to indicate different clients and devices, so that each device or client can maintain its own KeyPackage.

This is cool!

Thanks for explaining 🙏. Great thread here.

Yeah, this UX would definitely be a challenge.

Keychat probably doesn't follow the NIP-EE, but I think it's something worth considering. nostr:npub1h0uj825jgcr9lzxyp37ehasuenq070707pj63je07n8mkcsg3u0qnsrwx8

At first glance it looks to me like you follow NIP-EE in order to interop then you have to follow that NIP super carefully. So many checklist items in there that you cannot not tick.

When creating a brand-new application-layer spec, is it better for one team to define the spec first and have others build apps around it? Or should multiple teams start by building apps independently and then work together to converge on the best possible spec?

We strongly recommend reading the MLS specification directly, rather than relying solely on NIP-EE.

I read this MIMI doc, traumatic flashbacks to Feynman diagrams in old textbooks.

https://www.ietf.org/archive/id/draft-ietf-mimi-protocol-01.html

I don't quite get your point. NIP-EE also follows the MLS specification, it just standardizes the use of Nostr events to send mls messages.

Yeeeessss