# envelope.capnp — top-level wire message for all noiseml traffic. # # Every frame exchanged over the Noise channel is serialised as an Envelope. # The Delivery Service routes by (groupId, msgType) without inspecting payload. # # Field sizing rationale: # groupId / senderId : 32 bytes — SHA-256 digest # payload : opaque — MLS blob or control data; size bounded by # the Noise transport max message size (65535 B) # timestampMs : UInt64 — unix epoch milliseconds; sufficient until year 292M # # ID generated with: capnp id @0xe4a7f2c8b1d63509; struct Envelope { # Message type discriminant — determines how payload is interpreted. msgType @0 :MsgType; # 32-byte SHA-256 digest of the group name. # The Delivery Service uses this as its routing key. # Zero-filled for point-to-point control messages (ping, keyPackageUpload, etc.). groupId @1 :Data; # 32-byte SHA-256 digest of the sender's Ed25519 identity public key. senderId @2 :Data; # Opaque payload. Interpretation is determined by msgType: # ping / pong — empty # keyPackageUpload — openmls-serialised KeyPackage blob # keyPackageFetch — target identity key (32 bytes) # keyPackageResponse — openmls-serialised KeyPackage blob (or empty if none) # mlsWelcome — MLSMessage blob (Welcome variant) # mlsCommit — MLSMessage blob (PublicMessage / Commit variant) # mlsApplication — MLSMessage blob (PrivateMessage / Application variant) # error — UTF-8 error description payload @3 :Data; # Unix timestamp in milliseconds at the time of send. timestampMs @4 :UInt64; enum MsgType { ping @0; pong @1; keyPackageUpload @2; keyPackageFetch @3; keyPackageResponse @4; mlsWelcome @5; mlsCommit @6; mlsApplication @7; error @8; } }