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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
//! RFC 8620 §5.5 generic filter types for JMAP `/query` methods.
//!
//! Provides [`Filter`], [`FilterOperator`], and [`Operator`].
//! Object-specific filter conditions (e.g. `EmailFilterCondition`) are
//! defined in their respective type crates.
//!
//! # Filter algebra is excluded from extras preservation
//!
//! The filter algebra defined in this module is **intentionally not extensible**
//! via the workspace "extras preservation" policy. See [`Filter`],
//! [`FilterOperator`], and [`Operator`] for details. The same exclusion applies
//! to every per-object `FilterCondition` / `Comparator` / `ComparatorProperty`
//! type in the downstream `jmap-*-types` crates (see workspace `AGENTS.md`,
//! bd JMAP-lbdy "Decision: filter algebra excluded").
use ;
/// Logical operator for combining filter conditions (RFC 8620 §5.5).
///
/// # Excluded from extras preservation
///
/// This enum is **out of scope** for the workspace extras-preservation policy:
/// it carries no `Unknown(String)` catch-all variant, and backends must
/// dispatch on its known variants (`AND`, `OR`, `NOT`) to evaluate a filter
/// tree. An `Unknown` operator would be meaningless — a server that cannot
/// interpret the operator cannot evaluate the filter, and silently round-
/// tripping it back to the client would yield wrong query results.
///
/// More broadly, filter algebra (this enum and the per-object
/// `FilterCondition` / `Comparator` types) is excluded because unrecognised
/// filter clauses are a query-correctness hazard: silently dropping or
/// round-tripping a clause the server does not understand can return the
/// wrong set of records to the client without any error signal.
///
/// ## What to do instead
///
/// **IETF-track path.** Vendors who need both capability-level declaration
/// and filterability for custom fields should use
/// `draft-ietf-jmap-metadata` (capability URI
/// `urn:ietf:params:jmap:metadata`), which defines a `Metadata` / `Annotation`
/// companion object keyed by `(relatedType, relatedId)` with schema discovery
/// via the capability's `metadataTypes` / `maxDepth` properties and a
/// `Metadata/query` filter. Implemented in `jmap-metadata-types`,
/// `jmap-metadata-server`, and `jmap-metadata-client` (bd JMAP-06zp).
///
/// **Pre-IETF escape.** Vendors who cannot wait for the metadata draft can
/// either escape the filter tree to `serde_json::Value` or fork the
/// per-crate `FilterCondition` type. See
/// `crate-jmap-calendars-types/PLAN.md` for the hybrid sloppy-value
/// pattern.
///
/// Cross-reference: bd JMAP-lbdy "Decision: filter algebra excluded".
/// A filter node: either a logical operator combining sub-filters, or a
/// type-specific condition object (RFC 8620 §5.5).
///
/// Serializes as an untagged union. The presence of the `"operator"` key
/// distinguishes `Filter::Operator` from `Filter::Condition`.
///
/// **Variant ordering is critical**: `Operator` is listed before `Condition`
/// because serde untagged tries variants in declaration order.
/// `FilterOperator<T>` requires an `"operator"` field and fails fast without
/// it, allowing the deserializer to fall through to `Condition(T)`.
///
/// # Excluded from extras preservation
///
/// This type is **out of scope** for the workspace extras-preservation
/// policy: it carries no flatten-extras `extra` field, and the per-object
/// condition type `T` is also expected to be non-extensible. Filter clauses
/// the server does not understand are a query-correctness hazard — silently
/// preserving an unrecognised clause and round-tripping it back to the
/// client can return the wrong set of records with no error signal.
///
/// ## What to do instead
///
/// **IETF-track path.** Vendors who need both capability-level declaration
/// and filterability for custom fields should use
/// `draft-ietf-jmap-metadata` (capability URI
/// `urn:ietf:params:jmap:metadata`), which defines a filterable
/// `Metadata` / `Annotation` companion object. Implemented in `jmap-metadata-types`,
/// `jmap-metadata-server`, and `jmap-metadata-client` (bd JMAP-06zp).
///
/// **Pre-IETF escape.** Vendors who cannot wait for the metadata draft can
/// either escape the filter tree to `serde_json::Value` or fork the
/// per-crate `FilterCondition` type. See
/// `crate-jmap-calendars-types/PLAN.md` for the hybrid sloppy-value
/// pattern.
///
/// Cross-reference: bd JMAP-lbdy "Decision: filter algebra excluded".
/// Logical combination of filters (RFC 8620 §5.5).
///
/// # Excluded from extras preservation
///
/// This type is **out of scope** for the workspace extras-preservation
/// policy: it carries no flatten-extras `extra` field, and its
/// [`Operator`] field is a closed control enum that backends must dispatch
/// on. See [`Operator`] and [`Filter`] for the rationale and for the two
/// recommended paths (`draft-ietf-jmap-metadata`, bd JMAP-06zp; or the
/// pre-IETF sloppy-value escape).
///
/// Cross-reference: bd JMAP-lbdy "Decision: filter algebra excluded".