Original text:
represents a transcript over the whole history of MLSPlaintext Commit messages, up to the confirmation tag field in the current MLSPlaintext message.  The confirmation tag is then included in the <del> transcript for the next epoch.  The interim transcript hash is passed to new members in the GroupInfo struct, and enables existing members to incorporate a Commit message into the transcript without having to store the whole MLSPlaintextCommitAuthData structure. </del>  As shown above, when a new group is created, the "interim_transcript_hash" field is set to the zero-length octet 11.1.8.  Add and Remove proposals can be constructed and sent to the group by a party that is outside the group.  For example, a Delivery Service might propose to remove a member of a group who has been inactive for Construct a GroupInfo reflecting the new state: <del> Group ID, epoch, tree, confirmed transcript hash, and interim transcript hash from the new state </del>  The confirmation_tag from the MLSPlaintext object  Sign the GroupInfo using the member's private signing key Encrypt the GroupInfo using the key and nonce derived from the node in the "tree" array divided by two. Construct a new group state using the information in the GroupInfo <del> object.  The new member's position in the tree is "index", as defined above.  In particular, the confirmed transcript hash for the new state is the "prior_confirmed_transcript_hash" in the GroupInfo object. </del>  Update the leaf at index "index" with the private key corresponding to the public key in the node. their participation in the group (once in the ratchet tree) In the Welcome message, to tell new members of a group what <del> parameters are being used by the group </del>  In the GroupContext object, to ensure that all members of the group have the same view of the parameters in use <del> In other words, clients advertise their capabilities in KeyPackage extensions, the creator of the group expresses its choices for the group in Welcome extensions, and the GroupContext confirms that all members of the group have the same view of the group's extensions. </del>  This extension mechanism is designed to allow for secure and forward- compatible negotiation of extensions.  For this to work, KP: KeyPackage messages <del> GI: GroupInfo objects </del>  Recommended: Whether support for this extension is recommended by the IETF MLS WG.  Valid values are "Y" and "N".  The "Recommended"

Reviewer comments:
NAME r?
Discussed at 20211004 interim, ready to merge after adding some additional detail about when to use one or the other.
After a thorough review of the current MLS extension system, there are a few questions and we also have a few suggestions for changes. The total set of extensions is fixed and cannot be changed during the lifetime of a group. The set of extensions that is associated with a group is decided by the group creator. All extension types from the set have to be supported by all clients and must therefore be advertised in their capabilities extension. The implementation needs to validate the support in 4 instances: When creating a new group, when joining a group, when creating an add proposal, when parsing someone else's add proposal as part of a Commit. Key package extensions are simple and well-understood, in that they never leave the KeyPackage and there is group consensus through the tree hash. The other kind of extension seems to be called a Group Info Extension (GIE). GIEs can come in two flavours: a) they must be included in the group context, b) they must not be included in the group context. The ratchet tree extensions is an example of type b). GIEs of type a) are essentially just passed from the Adder to the New Joiner, using Welcome messages as an E2EE pipe.The spec does not explicitly introduce the notion of a GIE, it is only mentioned in 16.2. Should the spec be more explicit here? Should the flavour of a GIE (as described above) be reflected in the struct in the spec? E.g. a message type that indicates whether a GIE should be included in the GroupContext (see proposal below). Can the content of a GIE be dynamic (i.e. it can change during the lifetime of a group)? The ratchet tree extension seems to validate that assumption, it is a bit unclear if this is true for all kinds of GIE. We should be more explicit in the spec. If the content of GIEs is indeed dynamic, should those GIEs always be excluded from the GroupContext? Or optionally? If they are to be included in the GroupContext, how do clients agree on the changes? (See proposal below) We need more guidance regarding extensions in order to keep implementations aligned and capable of interop. A first suggestion would be to allow for the creation of extensions that have dynamic content. This would allow them to use MLS to agree on arbitrary data. The requirement would be to make GIEs with dynamic content more robust by introducing a new proposal type to update the content of extensions: Another improvement to the current extension system would be to be more clear about the kinds of extensions by introducing a dedicated field for every extension: This would allow generic extensions, which in turn allow committers of Add proposals to communicate arbitrary data to new group members in a robust fashion.
Thanks for the analysis here. To your point about “dynamic GIEs” — My initial concept here was that the GIEs included in the GroupContext would be fixed for all time. The ratchet tree extension would not be included in the GroupContext; as you say, it just uses the Welcome for E2E tunneling. Boiling this down a bit, it seems like there are a few problems to solve here: Clarifying which extensions in the GroupInfo go into the GroupContext and which are just used for tunneling E2E Allowing for updates to the group’s extensions For the former, there's a pretty simple solution available: Just have separate fields in the GroupContext for permanent and ephemeral extensions. The joiner processing would then place the into the MLS state / GroupContext, and use/discard the . We could also then update the IANA considerations to reflect these additional categories for where an extension can appear. For the latter problem, I think your ExtensionUpdate is about the right approach. It might be simpler just to have the update proposal provide wholesale replacement to the extensions, so that we don't have to design a merge algorithm. I'm not totally sure this is worth doing right now, since it seems easy to do as an extension. But especially if we keep it simple, I'm not strongly opposed.
NAME NAME and I discussed real-time, propose to do the following: Split out the GroupContext extensions as above Define a new proposal type to update the group's extensions:

Revised text:
represents a transcript over the whole history of MLSPlaintext Commit messages, up to the confirmation tag field in the current MLSPlaintext message.  The confirmation tag is then included in the  <ins> transcript for the next epoch.  The interim transcript hash is computed by new members using the confirmation tag in the GroupInfo struct, and enables existing members to incorporate a Commit message into the transcript without having to store the whole MLSPlaintextCommitAuthData structure. </ins> As shown above, when a new group is created, the "interim_transcript_hash" field is set to the zero-length octet 11.1.8. <ins> A GroupContextExtensions proposal is used to update the list of extensions in the GroupContext for the group. "struct { Extension extensions<0..2^32-1>; } GroupContextExtensions; " A member of the group applies a GroupContextExtensions proposal by removing all of the existing extensions from the GroupContext object for the group and replacing them with the list of extensions in the proposal.  (This is a wholesale replacement, not a merge.  An extension is only carried over if the sender of the proposal includes it in the new list.)  Note that once the GroupContext is updated, its inclusion in the confirmation_tag by way of the key schedule will confirm that all members of the group agree on the extensions in use. 11.1.9. </ins> Add and Remove proposals can be constructed and sent to the group by a party that is outside the group.  For example, a Delivery Service might propose to remove a member of a group who has been inactive for Construct a GroupInfo reflecting the new state:  <ins> Group ID, epoch, tree, confirmed transcript hash, interim transcript hash, and group context extensions from the new state </ins> The confirmation_tag from the MLSPlaintext object <ins> Other extensions as defined by the application </ins> Sign the GroupInfo using the member's private signing key Encrypt the GroupInfo using the key and nonce derived from the node in the "tree" array divided by two. Construct a new group state using the information in the GroupInfo  <ins> object. The GroupContext contains the "group_id", "epoch", "tree_hash", "confirmed_transcript_hash", and "group_context_extensions" fields from the GroupInfo object. The new member's position in the tree is "index", as defined above. </ins> Update the leaf at index "index" with the private key corresponding to the public key in the node. their participation in the group (once in the ratchet tree) In the Welcome message, to tell new members of a group what  <ins> parameters are being used by the group, and to provide any additional details required to join the group </ins> In the GroupContext object, to ensure that all members of the group have the same view of the parameters in use  <ins> In other words, an application can use GroupContext extensions to ensure that all members of the group agree on a set of parameters. Clients indicate their support for parameters in KeyPackage extensions.  New members of a group are informed of the group's GroupContext extensions via the "group_context_extensions" field in the GroupInfo or PublicGroupState object.  The "other_extensions" field in a GroupInfo object can be used to provide additional parameters to new joiners that are used to join the group. </ins> This extension mechanism is designed to allow for secure and forward- compatible negotiation of extensions.  For this to work, KP: KeyPackage messages  <ins> GC: GroupContext objects (and the "group_context_extensions" field of GroupInfo objects) GI: The "other_extensions" field of GroupInfo objects </ins> Recommended: Whether support for this extension is recommended by the IETF MLS WG.  Valid values are "Y" and "N".  The "Recommended"