Change:
NAME and I have completed interop testing that covers all of the functionality in the spec. We found a couple of places where there were ambiguities in the spec that led to different implementation decisions, and in the process of resolving those, found a couple of errors / omissions in drarft-19. The current PSK proposal validation forbids with other than . The branch and reinit sections call for the creation of PSK proposals with types and . Given the text in the PSK section, these proposals would be invalid. This PR explicitly allows and in the specific context of those operations. (This is a little pro-forma, since the PSK proposals are only seen by the committer. But it seems good to allow the committer to have consistent PSK proposal validation logic.) The text says that Add, Remove, and ReInit proposals can be sent by external senders, but is silent about other proposal types. This PR explicitly indicates which proposal types may be originated by external senders, and adds an IANA registry column to track. GREASE values for proposal types, credential types, and extension types are defined for use in Capabilities, but nothing currently forbids their use elsewhere. This PR forbids their use in actual Proposal or Credential objects, and in GroupContext extensions. The field of the Proposal object was inconsistently referred to as both and . This PR changes it to be everywhere.
Merge when ready.

Discussion:
"external": The signature key at the index indicated by "sender_index" in the "external_senders" group context extension (see external-senders-extension).  The "content_type" of the <del> message MUST be "proposal". </del> <ins> message MUST be "proposal" and the "proposal_type" MUST be a value that is allowed for external senders. </ins> "new_member_commit": The signature key in the LeafNode in the Commit's path (see joining-via-external-commits).  The

A PreSharedKey proposal is invalid if any of the following is true: <del> The "psktype" in the PreSharedKeyID struct is set to "resumption" and the "usage" is "reinit" or "branch". </del> <ins> The PreSharedKey proposal is not being processed as part of a reinitialization of the group (see reinitialization), and the PreSharedKeyID has "psktype" set to "resumption" and "usage" set to "reinit". The PreSharedKey proposal is not being processed as part of a subgroup branching operation (see subgroup-branching), and the PreSharedKeyID has "psktype" set to "resumption" and "usage" set to "branch". </ins> The "psk_nonce" is not of length "KDF.Nh".

includes it in the new list.) Note that once the GroupContext is updated, its inclusion in the <del> confirmation_tag by way of the key schedule will confirm that all </del> <ins> "confirmation_tag" by way of the key schedule will confirm that all </ins> members of the group agree on the extensions in use. 12.1.8. <del> Add and Remove proposals can be constructed and sent to the group by a party that is outside the group in two cases.  One case, indicated by an "external" SenderType is useful in cases where, for example, an automated service might propose to remove a member of a group who has been inactive for a long time, or propose adding a newly-hired staff member to a group representing a real-world team. ReInit proposals can also be sent to the group by an "external" sender, for example to enforce a changed policy regarding MLS version or ciphersuite. </del> <ins> Proposals can be constructed and sent to the group by a party that is outside the group in two cases.  One case, indicated by an "external" SenderType is useful in cases where, for example, an automated service might propose to remove a member of a group who has been inactive for a long time, or propose adding a newly-hired staff member to a group representing a real-world team.  An "external" sender might send a ReInit proposal, to enforce a changed policy regarding MLS version or ciphersuite. </ins> The "external" SenderType requires that signers are pre-provisioned to the clients within a group and can only be used if the

the sender will not have the keys necessary to construct a PrivateMessage object. <ins> Some types of proposal cannot be sent by an "external" sender.  Among the proposal types defined in this document, only the following types may be sent by an "external" sender: "add" "remove" "psk" "reinit" "group_context_extensions" Messages from "external" senders containing proposal types other than the above MUST be rejected as malformed.  New proposal types defined in the future MUST define whether they may be sent by "external" senders.  A column is defined in the relevant IANA registry (mls- proposal-types) to reflect this property. </ins> 12.1.8.1. The "external_senders" extension is a group context extension that

example, a sender might populate these extensions with a randomly- sized amount of random data. <ins> GREASE values MUST NOT be sent in the following fields, because an unsupported value in one these fields (including a GREASE value), will cause the enclosing message to be rejected: "Proposal.proposal_type" "Credential.credential_type" "GroupContext.extensions" "GroupContextExtensions.extensions" </ins> A set of values reserved for GREASE have been registered in the various registries in iana-considerations.  This prevents conflict between GREASE and real future values.  The following values are

"proposal_type" field of a Proposal.  Clients MUST NOT implement any special processing rules for how to handle these values when receiving them, since this negates their utility for detecting <del> extensibility failures.  GREASE values MUST be handled using normal logic for processing unsupported values.  When comparing lists of capabilities to identify mutually-supported capabilities, clients MUST represent their own capabilities with a list containing only the capabilities actually supported, without any GREASE values.  In other words, lists including GREASE values are only sent to other clients; </del> <ins> extensibility failures. GREASE values MUST be handled using normal logic for processing unsupported values.  When comparing lists of capabilities to identify mutually-supported capabilities, clients MUST represent their own capabilities with a list containing only the capabilities actually supported, without any GREASE values.  In other words, lists including GREASE values are only sent to other clients; </ins> representations of a client's own capabilities MUST NOT contain GREASE values.

Recommended: Same as in <ins> External: Whether a proposal of this type may be sent by an "external" sender (see external-proposals). </ins> Path Required: Whether a Commit covering a proposal of this type is required to have its "path" field populated (see commit).