BuzzioDocs

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.

Sealed delivery path

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

  1. Wake via FCM (no sender id)
  2. Read pending sealed node
  3. Open envelope with identity private key
  4. Validate certificate fields as required by client policy
  5. Feed inner ciphertext into Double Ratchet
  6. Persist plaintext locally (SQLCipher)
  7. 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.