1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// Copyright (c) 2024-2026 Tristan Stoltz / Luminous Dynamics
// SPDX-License-Identifier: Apache-2.0 OR MIT
//! # xenia-wire
//!
//! AEAD-sealed binary wire protocol for remote-control streams.
//!
//! **Pre-alpha.** The wire format is not yet frozen and breaking changes
//! will land between `0.1.x` releases. Do not deploy in production.
//!
//! ## What this crate provides
//!
//! - **[`Session`]** — minimal AEAD session state: a current key, an
//! optional previous key with grace period for rekey, per-session
//! random `source_id` + `epoch`, monotonic nonce counter, and a
//! 64-slot sliding replay window.
//! - **[`ReplayWindow`]** — sliding-window replay protection keyed by
//! `(source_id, payload_type)`. IPsec/DTLS semantics.
//! - **[`Sealable`]** — generic bincode-based serialization contract.
//! Bring your own payload type.
//! - **[`seal`] / [`open`]** — generic functions for any `Sealable` payload.
//! - **[`seal_frame`] / [`open_frame`] / [`seal_input`] / [`open_input`]** —
//! convenience wrappers for the reference [`Frame`] + [`Input`] types.
//! Available under the default `reference-frame` feature.
//! - **[`seal_frame_lz4`] / [`open_frame_lz4`]** — LZ4-before-AEAD
//! compression variants. Available under the `lz4` feature.
//!
//! ## What this crate deliberately does NOT do
//!
//! - **No transport.** Sealed bytes are returned to the caller; the
//! caller ships them over TCP / WebSocket / QUIC / whatever.
//! - **No handshake.** Session keys arrive from somewhere else
//! (ML-KEM-768 in real deployments). Call [`Session::install_key`]
//! directly in tests or early prototypes.
//! - **No state machine.** `Session` has no lifecycle — no connecting,
//! authenticating, closing. Those are application concerns.
//! - **No domain semantics.** The reference [`Frame`] / [`Input`] types
//! carry opaque byte payloads. Implement [`Sealable`] on your own
//! types for anything real.
//!
//! ## Quick start
//!
//! ```
//! use xenia_wire::{Session, seal_frame, open_frame, Frame};
//!
//! let key = [0xAB; 32];
//! let mut sender = Session::new();
//! let mut receiver = Session::new();
//! sender.install_key(key);
//! receiver.install_key(key);
//!
//! let frame = Frame {
//! frame_id: 1,
//! timestamp_ms: 1_700_000_000_000,
//! payload: b"hello, xenia".to_vec(),
//! };
//! let sealed = seal_frame(&frame, &mut sender).unwrap();
//! let opened = open_frame(&sealed, &mut receiver).unwrap();
//! assert_eq!(opened.payload, b"hello, xenia");
//!
//! // Replaying the same bytes fails — the sliding window catches it.
//! assert!(open_frame(&sealed, &mut receiver).is_err());
//! ```
//!
//! ## Wire format
//!
//! ```text
//! envelope = nonce || ciphertext || tag
//! nonce : 12 bytes — source_id[0..6] || payload_type || epoch || seq[0..4]
//! ciphertext : len(plaintext) bytes — ChaCha20-Poly1305 encrypt(plaintext)
//! tag : 16 bytes — Poly1305 authentication tag
//! ```
//!
//! The plaintext is typically `bincode::serialize(payload)`. Under the
//! `lz4` feature the plaintext is `lz4_flex::compress_prepend_size(bincode_bytes)`.
//!
//! ## Feature flags
//!
//! | Feature | Default | Description |
//! |-------------------|---------|------------------------------------------------------|
//! | `reference-frame` | yes | Ships [`Frame`] + [`Input`] reference types. |
//! | `lz4` | no | Adds LZ4-before-AEAD variants for frame sealing. |
//!
//! ## License
//!
//! Dual-licensed under Apache-2.0 OR MIT.
pub use WireError;
pub use ;
pub use ;
pub use ;
pub use Sealable;
pub use ;
pub use ;
pub use ;
pub use ;
pub use ;