P8. Limits, errors, and edge cases
Normative protocol documentation for the current implementation. Not independently audited.
P8.1 Size limits
| Limit | Value | Applies to |
|---|---|---|
| Max JSON PDU (data channel) | 16 MiB | Any single JSON object; MUST reject larger |
| Cascade chunk size | 8192 bytes | finalCiphertext over data channel |
| Fast transfer chunk (initial) | 8 MiB | Fast file path |
| Fast transfer chunk range | 1 MiB – 16 MiB | Adaptive |
| Fast per-message metadata cap | 256 KiB | Some fast paths |
| WebRTC buffer threshold | 8 MiB | bufferedAmount backpressure |
Oversized cascade payloads MUST use chunking (P5); senders MUST NOT truncate without chunking.
P8.2 Error handling — Profile-v0 (current)
| Condition | Receiver behavior |
|---|---|
| JSON parse error | MUST drop PDU |
| PDU size > 16 MiB | MUST drop before full parse if possible |
Unknown type | MUST drop; MAY log at debug only |
| Decrypt/auth failure | MUST NOT deliver plaintext |
| Missing chunk | MUST wait or timeout; MUST NOT decrypt partial |
| Handshake PDU after fatal error | SHOULD ignore |
| Encrypt failure | MAY fallback MLS-only; SHOULD log |
Profile-v0 has no application-level error codes on the wire.
P8.3 Recommended timeouts
Implementations MAY use other values until Profile-v1. Recommended SHOULD values:
| Timer | Recommended | Applies to |
|---|---|---|
| Chunk reassembly | 120 s | Per messageId |
| Handshake stall | 300 s | From data channel open to encryptionReady |
P8.4 Denial of service
Receivers SHOULD cap:
- 4096 chunks per
messageId - 64 concurrent
messageIdreassemblies per remote peer
Additional mitigations:
- Reject excessive JSON array lengths before allocation.
- Signaling rate limits: broker policy (out of band).
P8.5 Security considerations
This profile addresses mitigations for:
- Chunk flooding / reassembly DoS (P8.4 caps).
- Oversize JSON / memory exhaustion (16 MiB cap).
- Signaling MITM via broker compromise (P2.8).
- Malicious peer (invalid PDUs, spam) — drop on failure.
- Application-layer replay — dedup by
messageId(product layer). - Supply-chain / subverted JS — see ch. 8.
P8.6 Edge cases
| Case | Rule |
|---|---|
| Cascade disabled mid-session | MUST re-handshake or send cleartext only if encryption off |
| Peer ID change | MUST full handshake |
| MLS fallback after cascade fail | encryptedMessage uses envelope not cascadedPayload |
| Empty plaintext | Allowed; still encrypted |
Duplicate messageId | Application-layer dedup; not protocol-forbidden |
P8.7 Versioning (v0)
Until EnkryptedChat-Profile-v1 is published, implementations MAY add JSON fields without breaking single-codebase deployments. Third parties MUST NOT assume stability.
Profile-v0 implements protocol-error PDUs in p2p (MLSProvider, PeerProvider). Receivers MUST still drop failing PDUs if no error PDU is received.
P8.8 protocol-error PDU (implemented)
| Field | Type | Required | Description |
|---|---|---|---|
type | string | MUST | "protocol-error" |
code | number | MUST | See table below |
messageId | string | MAY | Related message |
detail | string | MAY | Debug text; MUST NOT contain secrets |
| Code | Name | When |
|---|---|---|
| 1 | DECRYPT_FAILED | AEAD/auth failure |
| 2 | UNKNOWN_PDU | Unknown type |
| 3 | CHUNK_TIMEOUT | Reassembly timeout |
| 4 | OVERSIZE | PDU over limit |
| 5 | HANDSHAKE_REQUIRED | E2EE before encryptionReady |
Senders SHOULD emit protocol-error on the paths implemented in Profile-v0 (MLSProvider, PeerProvider); receivers MUST still drop failing PDUs if no error PDU is received.