77c3634745
Follow-up to the earlier MIP-spec alignment commit, addressing the remaining audit items: - MIP-00 (KeyPackageUtils.isValid): now performs every strict tag-level check that MDK does — d tag is exactly 64 hex chars, mls_protocol_version is exactly "1.0", mls_ciphersuite is exactly "0x0001", mls_extensions contains both 0xf2ee + 0x000a, mls_proposals contains 0x000a, encoding is "base64", content non-empty, i tag present. Adds `isCryptographicallyValid` for deep checks: i tag matches the computed KeyPackageRef (RFC 9420 §5.2), Basic credential identity equals the event's pubkey, KeyPackage signature verifies. - MIP-01 (MarmotGroupData): encoder now omits the v3-only `disappearing_message_secs` field when version < 3, so v2 output matches MDK's `tls_codec` 0.4 byte-for-byte. Adds byte-level fixture tests pinned to the Rust reference (encode + decode in both directions). - MIP-02 (WelcomeGiftWrap): replaces the redundant sign-then-rumorize step with `RumorAssembler.assembleRumor`, producing a true unsigned rumor as NIP-59 requires (no wasted secp256k1 signature). - MIP-05 kind 449 (TokenRemovalEvent.build): no longer accepts a tag initializer. Per the MIP-05 spec the token-removal event MUST have empty tags; allowing arbitrary caller-supplied tags risks metadata leakage and rejection by strict validators (e.g. the MDK reference). - RFC 9420 §6 PublicMessage framing: encoder/decoder now branch on `contentType`. Application messages keep the `opaque<V>` length prefix; Proposal/Commit bodies are emitted/parsed as their typed structs (no outer length prefix), per the MLS RFC. Previously encoder used `putBytes` raw and decoder used `readOpaqueVarInt`, so neither could roundtrip and Proposal/Commit PublicMessages from other MLS clients would mis-parse. - KeyPackageUtilsTest fixtures: switch tiny "0"/"1"/"lr" slot ids to realistic 64-char hex slot ids, since `isValid` now enforces the MIP-00 d-tag format.