Message delivery path (sealed 1-to-1)
This page explains the preferred sealed 1-to-1 delivery path end-to-end.
Status: Sealed path preferred and write-cutover complete (allowLegacyFallback = false). Inbox parse is sealed-only (non-sealed junk deleted). Legacy receipt_batches creates denied by rules.
Reviewer PDF: Protocol one-pager · Download
Sequence
Sender Cloud Function Recipient
| | |
|-- obtain SenderCertificate | |
|-- Double Ratchet encrypt body | |
|-- seal outer AEAD(cert || msg)-->| deliverSealedMessage |
| |-- rate limit / blocks / limits |
| |-- write pending_chats from:sealed|
| |-- FCM: {message_id, sealed:1} -->|
| | |-- open sealed envelope
| | |-- learn sender from inner
| | |-- Double Ratchet decrypt
| | |-- delete relay copy
| | |-- store in SQLCipher
Step detail
1. Session establishment (first message / new device)
- Recipient publishes identity key and prekeys.
- Sender runs X3DH (4-DH style) to derive an initial shared secret.
- Both sides initialize the Double Ratchet (Alice/Bob ratchet init variants as implemented in
CryptoEngine).
2. Inner message encryption
- Payload (text/media metadata references, reply ids, client flags) is encrypted under the current ratchet message key (AES-GCM family).
- Inner structure still names the real sender — but that structure is inside the sealed outer envelope on the preferred path.
3. Outer sealed envelope
- Ephemeral keypair ECDH to recipient identity public key
- HKDF info:
buzzio_sealed_sender_v1 - AES-GCM wraps JSON
{ v, cert, msg } - Wire form:
ephemeralPub (uncompressed secp256k1) || ciphertext
4. Privileged write
- Only Cloud Functions / Admin SDK write
from: "sealed"nodes. - Clients cannot forge sealed delivery through RTDB rules alone.
5. Recipient processing
- Wake via FCM (no sender id)
- Read pending sealed node
- Open envelope with identity private key
- Validate certificate fields as required by client policy
- Feed inner ciphertext into Double Ratchet
- Persist plaintext locally (SQLCipher)
- Acknowledge / delete relay copy (delete-on-delivery)
6. Undelivered retention
If the recipient never comes online, sealed undelivered envelopes are purged on a short schedule (~3 days) so the relay does not become a long-lived archive.
Control plane (receipts, Secure View, disappear, once-view)
Sensitive control signals use sealed controls (sealed_controls/{recipient}/{id} + deliverSealedControl):
| Kind (examples) | Purpose |
|---|---|
| receipt | Delivery / read acknowledgements |
| secure_mode (wire) | Secure View request/agree/reject (public name) |
| disappearing | Chat-level disappear timers |
| once_view | Once-view mode signals |
| kept | Keep/exempt from disappear |
Controls follow the same privacy goal as messages: recipient learns the peer; durable plaintext A↔B trees are avoided on the preferred path.
Legacy cutover (complete)
Cut over (2026-08-05): sealed-only writes and sealed-only inbox parse. Legacy receipt listeners gated off. Client creates denied on pending_chats, sealed_controls, and receipt_batches. See Sealed sender.