Skip to main content

wire/privacy/
operation.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//! What `Command::PrivacyOperation` asks for, and the result the host
7//! keeps for it under its `idem` (`crates/wire/spec/Privacy.lean` ยง8-89).
8
9use kernel::{AxError, IdemKey};
10use serde::{Deserialize, Serialize};
11
12use super::answer::PrivacyValue;
13use super::{PrivacyControl, PrivacyFaultCode, PrivacySettlement};
14
15/// Change one host privacy control, or check the operation that has no
16/// conclusion: the payload of `Command::PrivacyOperation`. The city's
17/// listener carries it out on the host, and its result is read back from
18/// [`crate::PrivacyAnswer::outcomes`] under `idem`.
19#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
20#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
21pub struct PrivacyRequest {
22    pub action: PrivacyAction,
23    pub idem: IdemKey,
24}
25
26/// One change the person confirmed on the page. `expected` is the value
27/// the page showed when the person confirmed; the host writes nothing when
28/// its fresh read differs (`crates/sprawling/spec/Privacy/Confirmation.lean`
29/// D58).
30#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
31#[serde(rename_all = "snake_case")]
32#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
33pub enum PrivacyAction {
34    /// Write the control's value over `expected`.
35    Apply {
36        control: PrivacyControl,
37        expected: PrivacyValue,
38    },
39    /// Put back the value this app's latest change of the control found.
40    Restore {
41        control: PrivacyControl,
42        expected: PrivacyValue,
43    },
44    /// The person's check of the operation that has no conclusion:
45    /// `expected` is the value the page showed for its control. Writes
46    /// nothing.
47    Reconcile { expected: PrivacyValue },
48}
49
50/// The result kept for one operation a page sent.
51#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
52#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
53pub struct PrivacyOutcome {
54    pub idem: IdemKey,
55    pub action: PrivacyAction,
56    pub result: PrivacyResult,
57}
58
59/// Where one operation stands.
60#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
61#[serde(rename_all = "snake_case")]
62#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
63pub enum PrivacyResult {
64    /// Accepted and not finished: it waits for an earlier operation, for
65    /// administrator approval, or for its readback.
66    Running,
67    /// `operation` is the history's number for it, never zero.
68    Applied {
69        operation: u64,
70    },
71    Restored {
72        operation: u64,
73    },
74    /// The target already held the control's value; nothing was written
75    /// or recorded.
76    AlreadyWritten,
77    Reconciled {
78        operation: u64,
79        settlement: PrivacySettlement,
80    },
81    /// The change asked for did not happen, or its result is unconfirmed;
82    /// `error` says which and what to do.
83    Refused {
84        code: PrivacyFaultCode,
85        error: AxError,
86    },
87}