Skip to main content

wire/
privacy.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4// Copyright (c) 2026 2youg1 and the sprawling contributors
5
6//! The privacy page's vocabulary (`crates/wire/spec/Privacy.lean`): the
7//! closed sets every control is described by (§8-87), the answer to
8//! `Query::Privacy` (§8-88) and the operation `Command::PrivacyOperation`
9//! carries (§8-89).
10//!
11//! **The host's table is the one authority.** A control's target path, the
12//! value it writes and its edition lists are defined once, in the binary's
13//! `privacy::controls`, and reach the page only inside the answer; the
14//! words the page shows are defined once, in the client's `lang.json`,
15//! keyed by the spellings of these sets. Each set therefore has exactly
16//! one list of members, and every reader takes it from here.
17
18mod answer;
19mod operation;
20
21pub use answer::{PrivacyAnswer, PrivacyControlEntry, PrivacyCurrent, PrivacyEditions};
22pub use answer::{PrivacyHistory, PrivacyHost, PrivacyIntent, PrivacyNotWrittenEntry};
23pub use answer::{PrivacyOriginalLine, PrivacyTarget, PrivacyValue, PrivacyWindows};
24pub use operation::{PrivacyAction, PrivacyOutcome, PrivacyRequest, PrivacyResult};
25
26use serde::{Deserialize, Serialize};
27
28/// Declares a closed set together with `ALL`, its members in declaration
29/// order. The array is the variant list itself, so a member cannot be
30/// added to the enum and left out of the order the page draws in.
31macro_rules! listed {
32    (
33        $(#[$attr:meta])*
34        pub enum $name:ident { $($(#[$member:meta])* $variant:ident),* $(,)? }
35    ) => {
36        $(#[$attr])*
37        #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
38        #[serde(rename_all = "snake_case")]
39        #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
40        pub enum $name { $($(#[$member])* $variant),* }
41
42        impl $name {
43            /// Every member, in the order the privacy page shows them.
44            pub const ALL: [Self; [$(stringify!($variant)),*].len()] = [$(Self::$variant),*];
45        }
46    };
47}
48
49listed! {
50    /// One host setting this binary may change for the person on request
51    /// (a privacy control). Declared in page order: by
52    /// [`PrivacyCategory`], and within a category in the order of the
53    /// controls table.
54    pub enum PrivacyControl {
55        // Diagnostics and telemetry.
56        PowershellTelemetryOptout,
57        CeipConsolidatorTask,
58        CeipUsbTask,
59        WindowsCeip,
60        DiagnosticData,
61        FeedbackNotifications,
62        StepsRecorder,
63        ErrorReporting,
64        ErrorReportingAdditionalData,
65        DiagnosticLogCollection,
66        DumpCollection,
67        ApplicationTelemetry,
68        DeviceCensusTask,
69        DeviceCensusUserTask,
70        DotnetCliTelemetryOptout,
71        // Speech, typing and inking.
72        VoiceActivation,
73        VoiceActivationAboveLock,
74        OnlineSpeechRecognition,
75        ImplicitTextCollection,
76        ImplicitInkCollection,
77        HandwritingErrorReports,
78        InputPersonalization,
79        LinguisticDataCollection,
80        HandwritingDataSharing,
81        // Location and sensors.
82        LocationProvider,
83        LocationFeature,
84        Sensors,
85        // Search.
86        SearchWeb,
87        SearchWebResults,
88        CloudSearch,
89        Cortana,
90        CortanaAboveLock,
91        SearchLocation,
92        SearchHighlights,
93        // Suggestions, advertising and cloud content.
94        TailoredExperiences,
95        Spotlight,
96        ConsumerFeatures,
97        CloudOptimizedContent,
98        WindowsTips,
99        ConsumerAccountStateContent,
100        ThirdPartySuggestions,
101        SettingsOnlineTips,
102        Widgets,
103        AdvertisingId,
104        LanguageListWebsites,
105        // Activity history and cross-device.
106        StartLaunchTracking,
107        ActivityFeed,
108        ActivityPublish,
109        ActivityUpload,
110        ClipboardHistory,
111        CloudClipboard,
112        ContinueExperiences,
113        PhonePcLinking,
114        MessageSync,
115        // Cloud services and network connections.
116        OnesettingsDownloads,
117        FindMyDevice,
118        DeliveryOptimization,
119        OnedriveFileStorage,
120        OnedrivePreSigninTraffic,
121        PushNotificationsNetwork,
122        // App permissions.
123        AppLocation,
124        AppAccountInfo,
125        AppMotion,
126        AppPhoneCalls,
127        AppTrustedDevices,
128        AppUnpairedDevices,
129        AppDiagnosticInfo,
130        AppContacts,
131        AppCalendar,
132        AppCallHistory,
133        AppEmail,
134        AppTasks,
135        AppMessaging,
136        AppRadios,
137        AppCamera,
138        AppMicrophone,
139        AppNotifications,
140        AppBackground,
141        AppScreenCaptureProgrammatic,
142        AppScreenCaptureBorderless,
143        AppGazeInput,
144        AppHumanPresence,
145        AppForegroundText,
146        CameraDevice,
147        // Windows AI.
148        AppSystemAiModels,
149        RecallSnapshots,
150        RecallComponent,
151        ClickToDo,
152    }
153}
154
155listed! {
156    /// One line of the privacy request list as the person wrote it (an
157    /// original item), numbered as the list numbers it.
158    pub enum PrivacyOriginal {
159        K01,
160        K02,
161        K03,
162        K04,
163        K05,
164        K06,
165        K07,
166        K08,
167        K09,
168        K10,
169        K11,
170        K12,
171        K13,
172        K14,
173        K15,
174        K16,
175        K17,
176        K18,
177        K19,
178        K20,
179        K21,
180        K22,
181        K23,
182        K24,
183        K25,
184        K26,
185        K27,
186        K28,
187        K29,
188        K30,
189        K31,
190        K32,
191        K33,
192        K34,
193        K35,
194        K36,
195        K37,
196        K38,
197        K39,
198        K40,
199        K41,
200        K42,
201        K43,
202        K44,
203        K45,
204        K46,
205        K47,
206        K48,
207        K49,
208        K50,
209        K51,
210        K52,
211    }
212}
213
214listed! {
215    /// Why an original item is not written. The research decided each
216    /// one; nothing here is a judgement the host makes at run time.
217    pub enum PrivacyNotWritten {
218        /// No current policy template or policy CSP has the target.
219        Absent,
220        /// The target exists and Microsoft has retired what it governs.
221        Obsolete,
222        /// The sources do not settle the target's type or written value.
223        Undeterminable,
224        /// Writing it needs an operation kind this version does not have.
225        NeedsOperationKind,
226    }
227}
228
229listed! {
230    /// The sections of the privacy page, in page order.
231    pub enum PrivacyCategory {
232        Diagnostics,
233        SpeechInput,
234        LocationSensors,
235        Search,
236        Content,
237        ActivitySync,
238        CloudServices,
239        AppPermissions,
240        WindowsAi,
241    }
242}
243
244listed! {
245    /// The Windows editions Microsoft's documentation names when it says
246    /// where a policy is honoured or ignored.
247    pub enum PrivacyEdition {
248        Home,
249        Pro,
250        Enterprise,
251        Education,
252        IotEnterprise,
253        Server,
254    }
255}
256
257listed! {
258    /// What the sources say about whether writing a control changes
259    /// anything on current Windows builds.
260    pub enum PrivacyBuildEffect {
261        /// The effect is documented for current builds.
262        Documented,
263        /// The setting exists, and the sources leave open whether current
264        /// builds still act on it.
265        Uncertain,
266        /// The service or feature it governs has ended; writing it changes
267        /// nothing today.
268        NoCurrentEffect,
269    }
270}
271
272listed! {
273    /// How a control's edition lists read for the edition of this host.
274    pub enum PrivacyEditionFit {
275        /// The host's edition is in the control's honoured list.
276        Honoured,
277        /// The host's edition is in the control's ignored list.
278        Ignored,
279        /// Neither list names the host's edition, or the host's edition is
280        /// not one of [`PrivacyEdition`].
281        NotStated,
282    }
283}
284
285listed! {
286    /// Whose settings a control changes. A machine-scope write goes
287    /// through administrator approval.
288    pub enum PrivacyScope {
289        User,
290        Machine,
291    }
292}
293
294listed! {
295    /// The person's check of an operation that has no conclusion. It
296    /// writes nothing; it records what the target held.
297    pub enum PrivacySettlement {
298        /// The target held the operation's modified value: an apply now
299        /// owns its change.
300        Applied,
301        /// The target held the operation's original value.
302        NotApplied,
303        /// The target held a restore's modified value: the change it
304        /// undid is no longer owned.
305        Restored,
306        /// The target held neither value; nothing is owned and nothing is
307        /// put back.
308        Abandoned,
309    }
310}
311
312listed! {
313    /// Why a privacy operation ended without the change asked for, or
314    /// with a result nobody could confirm: the closed set of stable codes
315    /// (`crates/sprawling/spec/Privacy.lean` §12).
316    pub enum PrivacyFaultCode {
317        Identity,
318        Clock,
319        History,
320        Unreadable,
321        Unresolved,
322        Changed,
323        TargetAbsent,
324        NothingOwned,
325        Conflict,
326        NothingUnresolved,
327        HistoryFull,
328        Expired,
329        AccessDenied,
330        ElevationDeclined,
331        NotApplied,
332        ReadbackMismatch,
333        Unknown,
334        ReceiptLost,
335    }
336}
337
338impl PrivacyFaultCode {
339    /// The code as it travels, which every privacy error's subject also
340    /// opens with.
341    pub const fn as_str(self) -> &'static str {
342        match self {
343            Self::Identity => "identity",
344            Self::Clock => "clock",
345            Self::History => "history",
346            Self::Unreadable => "unreadable",
347            Self::Unresolved => "unresolved",
348            Self::Changed => "changed",
349            Self::TargetAbsent => "target_absent",
350            Self::NothingOwned => "nothing_owned",
351            Self::Conflict => "conflict",
352            Self::NothingUnresolved => "nothing_unresolved",
353            Self::HistoryFull => "history_full",
354            Self::Expired => "expired",
355            Self::AccessDenied => "access_denied",
356            Self::ElevationDeclined => "elevation_declined",
357            Self::NotApplied => "not_applied",
358            Self::ReadbackMismatch => "readback_mismatch",
359            Self::Unknown => "unknown",
360            Self::ReceiptLost => "receipt_lost",
361        }
362    }
363}
364
365#[cfg(test)]
366#[allow(clippy::unwrap_used, reason = "test code")]
367mod tests {
368    use super::PrivacyFaultCode;
369
370    /// The subject prefix and the wire spelling are one spelling.
371    #[test]
372    fn a_fault_code_reads_as_it_travels() {
373        for code in PrivacyFaultCode::ALL {
374            assert_eq!(
375                serde_json::to_value(code).unwrap(),
376                serde_json::Value::from(code.as_str())
377            );
378        }
379    }
380}