From d68c6a2fe70bc376b004c8432c04f5de8c451895 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 22 Apr 2026 08:09:31 +0000 Subject: [PATCH] fix(marmot): SelfRemove uses IANA proposal type 0x000A (not 0xF001) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SelfRemove is standardized in draft-ietf-mls-extensions with IANA-registered proposal type 0x000A. openmls and mdk encode it that way on the wire. Quartz was writing 0xF001 (Marmot private-use range), so mdk's strict tls_codec read 0x000A for a known proposal type it didn't recognize and the decoder drifted past the variant body, surfacing later as Tls(DecodingError("Trying to decode Option with 64 for option...")) when it reached `Commit.path` with misaligned bytes. Fixes test 11 (amy leave → B still sees A as member). https://claude.ai/code/session_1469d7f4-bb66-4ffa-a44d-1dfa4b526484 --- .../vitorpamplona/quartz/marmot/mls/messages/Proposal.kt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/marmot/mls/messages/Proposal.kt b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/marmot/mls/messages/Proposal.kt index 8e25297ac..67ab80be9 100644 --- a/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/marmot/mls/messages/Proposal.kt +++ b/quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/marmot/mls/messages/Proposal.kt @@ -45,8 +45,11 @@ enum class ProposalType( EXTERNAL_INIT(6), GROUP_CONTEXT_EXTENSIONS(7), - // Marmot custom proposal types (private-use range 0xF000-0xFFFF) - SELF_REMOVE(0xF001), + // SelfRemove is standardized in MLS Extensions draft-ietf-mls-extensions + // as IANA proposal type 0x000A, NOT a Marmot private-use value. + // openmls / mdk encode it as 0x000A on the wire; quartz was writing + // 0xF001, which strict receivers reject as "Unknown ProposalType". + SELF_REMOVE(0x000A), ; companion object {