Skip to main content

aven_protocol/wire/
tail.rs

1//! Ordinary encrypted tail messages. Context authentication is backend-owned.
2use serde::{Deserialize, Serialize};
3pub mod batch;
4pub const RECORD_LIMIT: usize = 135640;
5/// Bodies without a record; also the framing allowance around records.
6pub const CONTROL_LIMIT: usize = 16384;
7/// One record: an append request or a lookup response.
8pub const APPEND_LIMIT: usize = crate::base64_bytes::encoded_len(RECORD_LIMIT) + CONTROL_LIMIT;
9/// Serialized size of the records in one pull page.
10pub const PAGE_BYTES: usize = 2 * 1048576;
11pub const PAGE_COUNT: usize = 256;
12pub const RESPONSE_LIMIT: usize = PAGE_BYTES + CONTROL_LIMIT;
13pub const BATCH_COUNT: usize = 128;
14pub const BATCH_BYTES: usize = 1048576;
15pub const BATCH_APPEND_LIMIT: usize = crate::base64_bytes::encoded_len(BATCH_BYTES) + CONTROL_LIMIT;
16pub const BATCH_CONTROL_LIMIT: usize = 256 * 1024;
17
18#[derive(Clone, Serialize, Deserialize, PartialEq, Eq)]
19#[serde(deny_unknown_fields)]
20pub struct Mapping {
21    pub operation_id: String,
22    pub sequence: i64,
23    pub commitment: [u8; 32],
24}
25#[derive(Clone, Serialize, Deserialize)]
26#[serde(deny_unknown_fields)]
27pub struct Accepted {
28    pub mapping: Mapping,
29    #[serde(with = "crate::base64_bytes")]
30    pub record: Vec<u8>,
31}
32#[derive(Clone, Serialize, Deserialize)]
33#[serde(deny_unknown_fields)]
34pub struct BatchFeatures {
35    pub count: usize,
36    pub bytes: usize,
37}
38
39#[derive(Clone, Serialize, Deserialize)]
40#[serde(deny_unknown_fields)]
41pub enum Operation {
42    Features,
43    Append {
44        ticket: Option<super::images::Ticket>,
45        #[serde(with = "crate::base64_bytes")]
46        record: Vec<u8>,
47    },
48    Lookup {
49        operation_id: String,
50        expected: Option<Mapping>,
51    },
52    Pull {
53        after: i64,
54        limit: usize,
55        watermark: Option<i64>,
56    },
57}
58#[derive(Clone, Serialize, Deserialize)]
59#[serde(deny_unknown_fields)]
60pub struct Page {
61    pub after: i64,
62    pub watermark: i64,
63    pub cursor: i64,
64    pub has_more: bool,
65    pub records: Vec<Accepted>,
66}
67#[derive(Clone, Serialize, Deserialize)]
68#[serde(transparent)]
69pub struct BatchRecord(
70    #[serde(
71        serialize_with = "crate::base64_bytes::serialize",
72        deserialize_with = "crate::base64_bytes::bounded::<_, RECORD_LIMIT>"
73    )]
74    pub Vec<u8>,
75);
76
77#[derive(Clone, Serialize, Deserialize)]
78#[serde(deny_unknown_fields)]
79pub enum BatchOperation {
80    Append {
81        #[serde(deserialize_with = "batch::bounded_items")]
82        records: Vec<BatchRecord>,
83    },
84    Resolve {
85        #[serde(deserialize_with = "batch::bounded_items")]
86        operation_ids: Vec<String>,
87    },
88}
89
90#[derive(Clone, Serialize, Deserialize)]
91#[serde(deny_unknown_fields)]
92pub enum Resolution {
93    Found(batch::CompactMapping),
94    Absent { operation_id: String },
95    Bootstrap { operation_id: String },
96}
97
98#[derive(Clone, Serialize, Deserialize)]
99#[serde(deny_unknown_fields)]
100pub enum BatchReply {
101    Appended(#[serde(deserialize_with = "batch::bounded_items")] Vec<batch::CompactMapping>),
102    Resolved(#[serde(deserialize_with = "batch::bounded_items")] Vec<Resolution>),
103}
104
105#[derive(Clone, Serialize, Deserialize)]
106#[serde(deny_unknown_fields)]
107pub enum Reply {
108    Features(BatchFeatures),
109    Appended(Mapping),
110    Found(Accepted),
111    Absent,
112    Bootstrap,
113    Page(Page),
114}
115
116pub const PATH: &str = "/e2ee/tail/v1";
117pub const BATCH_PATH: &str = "/e2ee/tail/batch/v1";
118#[derive(Serialize, Deserialize)]
119#[serde(deny_unknown_fields)]
120pub struct Envelope<T> {
121    pub context: Context,
122    pub correlation: [u8; 32],
123    pub operation: T,
124}
125
126#[derive(Clone, Serialize, Deserialize, PartialEq, Eq)]
127#[serde(deny_unknown_fields)]
128pub struct Context {
129    pub vault: [u8; 32],
130    pub genesis: [u8; 32],
131    pub device: [u8; 32],
132    pub head: [u8; 32],
133    pub stream: [u8; 32],
134    pub descriptor: [u8; 32],
135}
136
137impl Context {
138    pub fn authentication<'a>(
139        &self,
140        bearer: &'a crate::claim::Secret,
141    ) -> super::enrollment::Authentication<'a> {
142        super::enrollment::Authentication {
143            vault: self.vault,
144            genesis: self.genesis,
145            device: self.device,
146            head: self.head,
147            bearer,
148        }
149    }
150}