Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Threema/threema-protocols/src/   (Social Medium ©)  Datei vom 26.9.2026 mit Größe 30 kB image not shown  

Quelle  csp-e2e.proto   Sprache: Unknown

 

Spracherkennung für: .proto vermutete Sprache: C {C[69] Corba[69] CS[69]} [Methode: maximale Elemente, drei Dimensionen]

// ## End-to-End Encrypted Messages (Supplementary)
//
// This is a supplementary section to the corresponding structbuf section
// with newer messages that use protobuf instead of structbuf. All defined
// messages here follow the same logic.

syntax = "proto3";

package csp_e2e;

option java_package = "ch.threema.protobuf.csp.e2e";
option java_multiple_files = true;
option php_namespace = "Threema\\Protocols\\Csp\\E2e";

import "common.proto";
import "md-d2d-sync.proto";

// Metadata sent within a CSP payload `message-with-metadata-box` struct.
message MessageMetadata {
  // Padding that is ignored by the receiver.
  // Recommended to be chosen such that the total length of padding + nickname
  // is at least 16 bytes. May be empty if the nickname is long enough.
  bytes padding = 1;

  // Unique message ID. Must match the message ID of the outer struct
  // (i.e. `message-with-metadata-box.message-id`).
  fixed64 message_id = 3;

  // Unix-ish timestamp in milliseconds for when the message has been created.
  //
  // Messages sent in a group must have the same timestamp for each group
  // member.
  uint64 created_at = 4;

  // Nickname
  //
  // Should be sent when the associate message requires _user profile
  // distribution_.
  //
  // When the user cleared its nickname, send an empty string. Do not send the
  // user's Threema ID (i.e. process data).
  //
  // Recommended to not exceed 32 grapheme clusters. Should not contain
  // whitespace characters at the beginning or the end of string.
  optional string nickname = 2;
}

// Edit an existing message (e.g. a text message or a media message caption).
//
// **Properties (1:1)**:
// - Kind: 1:1
// - Flags:
//   - `0x01`: Send push notification.
// - User profile distribution: No
// - Exempt from blocking: No
// - Implicit _direct_ contact creation: No
// - Protect against replay: Yes
// - Unarchive: No
// - Bump _last update_: No
// - Reflect:
//   - Incoming: Yes
//   - Outgoing: Yes
//   - _Sent_ update: No
// - Delivery receipts: No
// - Reactions: No
// - Edit applies to: N/A (obviously)
// - Deletable by: N/A
// - When rejected: N/A (ignored)
// - Send to Threema Gateway ID group creator: N/A
//
// **Properties (Group)**:
// - Kind: Group
// - Flags:
//   - `0x01`: Send push notification.
// - User profile distribution: No
// - Exempt from blocking: No
// - Implicit _direct_ contact creation: No
// - Protect against replay: Yes
// - Unarchive: No
// - Bump _last update_: No
// - Reflect:
//   - Incoming: Yes
//   - Outgoing: Yes
//   - _Sent_ update: No
// - Delivery receipts: N/A
// - Reactions: No
// - Edit applies to: N/A (obviously)
// - Deletable by: N/A
// - When rejected: N/A (ignored)
// - Send to Threema Gateway ID group creator: If capture is enabled
//
// The following steps must be invoked when the user wants to edit a 1:1
// message:
//
// 1. If the sender or the receiver do not have `EDIT_MESSAGE_SUPPORT`, disallow
//    editing and abort these steps.
// 2. Let `message` be the referred message.
// 3. If the user is not the original sender of `message`, disallow editing and
//    abort these steps.
// 4. If `message` has been sent (`sent-at`) more than 6 hours ago, disallow
//    editing and abort these steps.¹
// 5. Allow the user to edit the referred message.
//
// The following steps must be invoked when the user wants to edit a group
// message:
//
// 1. If the group is marked as _left_, disallow editing and abort these steps.
// 2. If the sender or all of the group members do not have
//    `EDIT_MESSAGE_SUPPORT`, disallow editing and abort these steps.
// 3. Let `message` be the referred message.
// 4. If the user is not the original sender of `message`, disallow editing and
//    abort these steps.
// 5. If the group is not a _notes_ group:
//    1. If `message` has been sent (`sent-at`) more than 6 hours ago, disallow
//       editing and abort these steps.¹
// 6. If any of the group members do not have `EDIT_MESSAGE_SUPPORT`, notify the
//    user that the affected contacts will not receive the edited content.
// 7. Allow the user to edit the referred message.
//
// The following steps must be invoked when the user wants to submit an edited
// 1:1 message.
//
// 1. If the sender or the receiver do not have `EDIT_MESSAGE_SUPPORT`, discard
//    the edited message and abort these steps.
// 2. Run the _Common Edit Message Submit Preflight Steps_.
// 3. Let `edited-at` be the current timestamp.
// 4. Run the _1:1 Messages Submit Steps_ with `messages` set from the following
//    properties:
//    - `created-at` set to `edited-at`,
//    - to construct an `EditMessage` message.
// 5. Edit the referred message as defined by the associated _Edit applies to_
//    property and add an indicator to the referred message, informing the user
//    that the referred message has been edited by the user at `edited-at`.
//
// The following steps must be invoked when the user wants to submit an edited
// group message.
//
// 1. If the group is marked as _left_, discard the edited message and abort
//    these steps.
// 2. If the sender or all of the group members do not have
//    `EDIT_MESSAGE_SUPPORT`, discard the edited message and abort these steps.
// 3. Run the _Common Edit Message Submit Preflight Steps_.
// 4. Let `edited-at` be the current timestamp.
// 5. Run the _Group Messages Submit Steps_ with `messages` set from the
//    following properties:
//    - `created-at` set to `edited-at`,
//    - to construct an `EditMessage` message (wrapped by
//      [`group-member-container`](ref:e2e.group-member-container)).
// 6. Edit the referred message as defined by the associated _Edit applies to_
//    property and add an indicator to the referred message, informing the user
//    that the referred message has been edited by the user at `edited-at`.
//
// The following steps are defined as the _Common Edit Message Submit Preflight
// Steps_:
//
// 1. Lookup the message with `message_id` originally sent by the sender within
//    the associated conversation and let `message` be the result.
// 2. If `message` is no longer defined, discard the edited message and abort
//    these steps.
// 3. If the content of `message` is identical to the edited message, discard
//    the edited message and abort these steps.
//
// When reflected from another device as an incoming or outgoing 1:1 message:
//
// 1. Run the _Common Edit Message Receive Steps_.
//
// When receiving this message as a 1:1 message:
//
// 1. Run the _Common Edit Message Receive Steps_.
//
// When reflected from another device as an incoming or outgoing group message:
//
// 1. Run the _Common Edit Message Receive Steps_.
//
// When receiving this message as a group message (wrapped by
// [`group-member-container`](ref:e2e.group-member-container)):
//
// 1. Run the [_Common Group Receive Steps_](ref:e2e#receiving). If the message
//    has been discarded, abort these steps.
// 2. Run the _Common Edit Message Receive Steps_.
//
// The following steps are defined as the _Common Edit Message Receive Steps_:
//
// 1. Lookup the message with `message_id` originally sent by the sender within
//    the associated conversation and let `referred-message` be the result.
// 2. If `referred-message` is not defined or the sender is not the original
//    sender of `referred-message`, discard the message and abort these steps.²
// 3. If `referred-message` is not editable (see the associated _Edit applies
//    to_ property), discard the message and abort these steps.
// 4. Edit `referred-message` as defined by the associated _Edit applies to_
//    property and add an indicator to `referred-message`, informing the user
//    that the message has been edited by the sender at the message's (the
//    `EditMessage`'s) `created-at`.
//
// ¹: For simplicity, the time constraint is applied on the sender side only.
// The receiver will always accept a request to edit a message. This is deemed
// acceptable considering this is not a security feature.
//
// ²: Implementations do not track the group member setup at the time a message
// was received. Therefore, an edited message is always sent to the **current**
// group member setup, including any group members that weren't part of the
// group when the message was sent. However, any ordinary client will discard
// `EditMessage` for unknown messages. This leak is not great but considered
// acceptable for now.
message EditMessage {
  // Unique ID of the referred message to be edited.
  fixed64 message_id = 1;

  // Text (or caption) to update the referred message with. Should be ≤ 6000
  // bytes.
  string text = 2;
}

// Remove an existing message.
//
// Note: This is a soft-security feature at best and it applies a best effort
// approach, meaning that it relies on some level of good will on the receiving
// end. A malicious receiver can easily persist a message prior to removal by
// e.g. making a screenshot, forwarding it, changing the date, explicitly saving
// it (if it contains media), etc.
//
// **Properties (1:1)**:
// - Kind: 1:1
// - Flags:
//   - `0x01`: Send push notification.
// - User profile distribution: No
// - Exempt from blocking: No
// - Implicit _direct_ contact creation: No
// - Protect against replay: Yes
// - Unarchive: No
// - Bump _last update_: No
// - Reflect:
//   - Incoming: Yes
//   - Outgoing: Yes
//   - _Sent_ update: No
// - Delivery receipts: No
// - Reactions: No
// - Edit applies to: N/A
// - Deletable by: N/A (obviously)
// - When rejected: N/A (ignored)
// - Send to Threema Gateway ID group creator: N/A
//
// **Properties (Group)**:
// - Kind: Group
// - Flags:
//   - `0x01`: Send push notification.
// - User profile distribution: No
// - Exempt from blocking: No
// - Implicit _direct_ contact creation: No
// - Protect against replay: Yes
// - Unarchive: No
// - Bump _last update_: No
// - Reflect:
//   - Incoming: Yes
//   - Outgoing: Yes
//   - _Sent_ update: No
// - Delivery receipts: N/A
// - Reactions: No
// - Edit applies to: N/A
// - Deletable by: N/A (obviously)
// - When rejected: N/A (ignored)
// - Send to Threema Gateway ID group creator: If capture is enabled
//
// The following steps must be invoked when the user wants to delete a 1:1
// message:
//
// 1. If the sender or the receiver do not have `DELETE_MESSAGE_SUPPORT`,
//    disallow removal and abort these steps.
// 2. Let `message` be the referred message.
// 3. If the user is not the original sender of `message`, disallow removal and
//    abort these steps.
// 4. If `message` has been sent (`sent-at`) more than 6 hours ago, disallow
//    removal and abort these steps.¹
// 5. Let `deleted-at` be the current timestamp.
// 6. Run the _1:1 Messages Submit Steps_ with `messages` set from the following
//    properties:
//    - `created-at` set to `deleted-at`,
//    - to construct a `DeleteMessage` message.
// 7. Replace the referred message with a message informing the user that the
//    referred message of the user has been removed at `deleted-at`.²
//
// The following steps must be invoked when the user wants to delete a group
// message.
//
// 1. If the group is marked as _left_, disallow removal and abort these steps.
// 2. If the sender or all of the group members do not have
//    `DELETE_MESSAGE_SUPPORT`, disallow removal and abort these steps.
// 3. Let `message` be the referred message.
// 4. If the user is not the original sender of `message`, disallow removal and
//    abort these steps.
// 5. If the group is not a _notes_ group:
//    1. If `message` has been sent (`sent-at`) more than 6 hours ago, disallow
//       removal and abort these steps.¹
// 6. Let `deleted-at` be the current timestamp.
// 7. If any of the group members do not have `DELETE_MESSAGE_SUPPORT`, notify
//    the user that the affected contacts will continue to see the message.
// 8. Run the _Group Messages Submit Steps_ with `messages` set from the
//    following properties:
//    - `created-at` set to `deleted-at`,
//    - to construct a `DeleteMessage` message (wrapped by
//      [`group-member-container`](ref:e2e.group-member-container)).
// 9. Replace the referred message with a message informing the user that the
//    referred message of the user has been removed at `deleted-at`.²
//
// When reflected from another device as an incoming or outgoing 1:1 message:
//
// 1. Run the _Common Delete Message Receive Steps_.
//
// When receiving this message as a 1:1 message:
//
// 1. Run the _Common Delete Message Receive Steps_.
//
// When reflected from another device as an incoming or outgoing group message:
//
// 1. Run the _Common Delete Message Receive Steps_.
//
// When receiving this message as a group message (wrapped by
// [`group-member-container`](ref:e2e.group-member-container)):
//
// 1. Run the [_Common Group Receive Steps_](ref:e2e#receiving). If the message
//    has been discarded, abort these steps.
// 2. Run the _Common Delete Message Receive Steps_.
//
// The following steps are defined as the _Common Delete Message Receive Steps_:
//
// 1. Lookup the message with `message_id` originally sent by the sender within
//    the associated conversation and let `referred-message` be the result.
// 2. If `referred-message` is not defined or the sender is not the original
//    sender of `referred-message`, discard the message and abort these steps.
// 3. If `referred-message` is not deletable (see the associated _Deletable by_
//    property), discard the message and abort these steps.
// 4. Replace `referred-message` with a message informing the user that the
//    message of the sender has been removed at the message's (the
//    `DeleteMessage`'s) `created-at`.²
//
// ¹: For simplicity, the time constraint is applied on the sender side only.
// The receiver will always accept a request to delete a message. This is deemed
// acceptable considering this is just barely a soft-security feature.
//
// ²: All references to a removed message (e.g. quotes) must be updated as well,
// so that the message content is no longer visible. An implementation should
// also try to withdraw or update any notification created for a removed
// message.
message DeleteMessage {
  // Unique ID of the referred message to be removed.
  fixed64 message_id = 1;
}

// Announces and immediately starts a group call.
//
// **Properties**:
// - Kind: Group
// - Flags:
//   - `0x01`: Send push notification.
// - User profile distribution: Yes
// - Exempt from blocking: Yes
// - Implicit _direct_ contact creation: No
// - Protect against replay: Yes
// - Unarchive: TODO(SE-508)
// - Bump _last update_: TODO(SE-508)
// - Reflect:
//   - Incoming: Yes
//   - Outgoing: Yes
//   - _Sent_ update: No
// - Delivery receipts: N/A
// - Reactions: No
// - When rejected: N/A¹
// - Edit applies to: N/A
// - Deletable by: N/A
// - Send to Threema Gateway ID group creator: If capture is enabled
//
// ¹: For the group creator it will be handled as if `group-sync-request` was
// received, re-sending a `GroupCallStart` if still ongoing, implicitly
// triggered by FS `Reject` receive steps.
//
// When the user wants to create a new group call or join an existing group
// call, run the steps outlined in the _Create or Join_ section of the Group
// Call Protocol.
//
// When reflected from another device as an incoming or outgoing message:
//
// 1. Run the _Common Group Call Start Receive Steps_.
//
// When receiving this message:
//
// 1. Run the [_Common Group Receive Steps_](ref:e2e#receiving). If the message
//    has been discarded, abort these steps.
// 2. Run the _Common Group Call Start Receive Steps_.
//
// The following steps are defined as the _Common Group Call Start Receive
// Steps_:
//
// 1. If the hostname of `sfu_base_url` does not use the scheme `https` or does
//    not end with one of the set of [_Allowed SFU Hostname
//    Suffixes_](ref:group-calls#obtain-sfu-information), log a warning, discard
//    the message and abort these steps.
// 2. Let `running` be the list of group calls that are currently considered
//    running within the group.
// 3. If another call with the same GCK exists in `running`, log a warning,
//    discard the message and abort these steps.
// 4. Add the received call to the list of group calls that are currently
//    considered running (even if `protocol_version` is unsupported¹).
// 5. Start a task to run the _Group Call Refresh Steps_.²
//
// ¹: Adding unsupported `protocol_version`s allows the user to join an ongoing
//  call after an app update where support for `protocol_version` has been
//  added.
//
// ²: This ensures that the user automatically switches to the chosen call if it
// is currently participating in a group call of this group.
message GroupCallStart {
  // Protocol version used for group calls of this group. The current version
  // number is `1`.
  //
  // Note: This is a _major_ version and may only be increased in case of
  // breaking changes due to the significant UX impact this has when running the
  // _Group Call Refresh Steps_ (i.e. only calls with supported protocol
  // versions can be _chosen_).
  uint32 protocol_version = 1;

  // The secret Group Call Key (`GCK`) used for this call.
  bytes gck = 2;

  // The base URL of the SFU, used to join or peek the call.
  string sfu_base_url = 3;
}

// React to a message.
//
// **Properties (1:1)**:
// - Kind: 1:1
// - Flags:
//   - `0x01`: Send push notification.
// - User profile distribution: Yes
// - Exempt from blocking: No
// - Implicit _direct_ contact creation: No
// - Protect against replay: Yes
// - Reflect:
//   - Incoming: Yes
//   - Outgoing: Yes
//   - _Sent_ update: No
// - Delivery receipts: No
// - Reactions: No, that would be silly!
// - When rejected: N/A (ignored)
// - Edit applies to: N/A (can withdraw and apply with another `Reaction`)
// - Deletable by: N/A (can withdraw with another `Reaction`)
// - Send to Threema Gateway ID group creator: N/A
//
// **Properties (Group)**:
// - Kind: 1:1
// - Flags:
//   - `0x01`: Send push notification.
// - User profile distribution: Yes
// - Exempt from blocking: No
// - Implicit _direct_ contact creation: No
// - Protect against replay: Yes
// - Reflect:
//   - Incoming: Yes
//   - Outgoing: Yes
//   - _Sent_ update: No
// - Delivery receipts: N/A
// - Reactions: No, that would be silly!
// - When rejected: N/A (ignored)
// - Edit applies to: N/A (can withdraw and apply with another `Reaction`)
// - Deletable by: N/A (can withdraw with another `Reaction`)
// - Send to Threema Gateway ID group creator: If capture is enabled
//
// When the user submits a reaction in a 1:1 conversation:
//
// 1. Let `reaction` be the reaction to be applied to or withdrawn from a
//    referred message which must contain a single fully-qualified [emoji
//    codepoint sequence that is part of the currently supported Unicode
//    standard][emoji-test.txt].
// 2. Run the _Legacy Reaction Mapping Steps_ with `reaction` and let
//    `legacy-reaction` be the result.
// 3. If `legacy-reaction` is not defined and the sender or the receiver does
//    not have `REACTION_SUPPORT`, log a warning and abort these steps.¹
// 4. Let `reacted-at` be the current timestamp.
// 5. If both sender and receiver have `REACTION_SUPPORT`, run the _1:1 Messages
//    Submit Steps_ with `messages` set from the following properties:
//    - `created-at` set to `reacted-at`,
//    - to construct a `Reaction` message from `reaction`.
// 6. If the sender or the receiver does not have `REACTION_SUPPORT`, run the
//    _1:1 Messages Submit Steps_ with `messages` set from the following
//    properties:
//    - `created-at` set to `reacted-at`,
//    - to construct the `legacy-reaction`.
// 7. Apply `reaction` (i.e. apply or withdraw) to the referred message with the
//    `reacted-at` timestamp.
//
// When the user submits a reaction in a group conversation:
//
// 1. Let `reaction` be the reaction to be applied to or withdrawn from a
//    referred message which must contain a single fully-qualified [emoji
//    codepoint sequence that is part of the currently supported Unicode
//    standard][emoji-test.txt].
// 2. Run the _Legacy Reaction Mapping Steps_ with `reaction` and let
//    `legacy-reaction` be the result.
// 3. If `legacy-reaction` is not defined:
//    1. If the sender does not have `REACTION_SUPPORT`, log a warning and abort
//       these steps.²
//    2. If all of the group members do not have `REACTION_SUPPORT`, log a
//       warning and and abort these steps.²
//    3. If any of the group members do not have `REACTION_SUPPORT`, notify the
//       user that the affected contacts will not receive the reaction.
// 4. Let `reacted-at` be the current timestamp.
// 5. Run the _Group Messages Submit Steps_ with `messages` set from the
//    following properties:
//    - `created-at` set to `reacted-at`,
//    - to construct a _canonical_ `Reaction` message from `reaction`,
//    - to construct a _specific_ message in the following way:
//      1. Let `receiver` be the specific receiver.
//      2. If the `receiver` does not have `REACTION_SUPPORT` and
//         `legacy-reaction` is defined, return the `legacy-reaction` (wrapped
//         by [`group-member-container`](ref:e2e.group-member-container)).
//      3. Construct and return the _canonical_ `Reaction` message from
//         `reaction` (wrapped by
//         [`group-member-container`](ref:e2e.group-member-container)).³
// 6. Apply `reaction` (i.e. apply or withdraw) to the referred message with the
//    `reacted-at` timestamp.
//
// The following steps are defined as the _Legacy Reaction Mapping Steps_:
//
// 1. If `action` is of variant `apply`:
//    1. If `action.apply` equals one of the following codepoint sequences,
//       return a `e2e.delivery-receipt` of type _acknowledge_ (0x03):
//       - `1F44D` (��)
//       - `1F44D 1F3FB` (����)
//       - `1F44D 1F3FC` (����)
//       - `1F44D 1F3FD` (����)
//       - `1F44D 1F3FE` (����)
//       - `1F44D 1F3FF` (����)
//    2. If `action.apply` equals one of the following codepoint sequences,
//       return a `e2e.delivery-receipt` of type _decline_ (0x04):
//       - `1F44E` (��)
//       - `1F44E 1F3FB` (����)
//       - `1F44E 1F3FC` (����)
//       - `1F44E 1F3FD` (����)
//       - `1F44E 1F3FE` (����)
//       - `1F44E 1F3FF` (����)
// 2. Return no message.
//
// When reflected from another device as an incoming or outgoing 1:1 message:
//
// 1. Run the _Common Reaction Receive Steps_.
//
// When receiving this message:
//
// 1. Run the _Common Reaction Receive Steps_.
//
// When receiving this message (wrapped by
// [`group-member-container`](ref:e2e.group-member-container)):
//
// 1. Run the [_Common Group Receive Steps_](ref:e2e#receiving). If the reaction
//    message has been discarded, abort these steps.
// 1. Run the _Common Reaction Receive Steps_.
//
// The following steps are defined as the _Common Reaction Receive Steps_:
//
// 1. Lookup the referred message with `message_id` within the associated
//    conversation and let `referred-message` be the result.
// 2. If `referred-message` is not defined, discard the message and abort these
//    steps.
// 3. If `referred-message` is not reactable (see the associated _Reactions_
//    property), discard the message and abort these steps.
// 4. If `action` is of variant `apply`:
//    1. If `apply` contains more than 64 bytes, discard the message and abort
//       these steps.
//    2. Decode `apply` to a UTF-8 string. If the string is empty, discard the
//       message and abort these steps.
//    3. Apply (or re-apply) the resulting emoji from the sender to
//       `referred-message` with the message's (the `Reaction`'s) `created-at`
//       timestamp used for the time of reaction.⁴⁵
// 5. If `action` is of variant `withdraw`:
//    1. If `withdraw` contains more than 64 bytes, discard the message and
//       abort these steps.
//    2. Decode `withdraw` to a UTF-8 string. If the string is empty, discard
//       the message and abort these steps.
//    3. Remove the resulting emoji reaction from the sender for `message`.⁴⁵
//
// ¹: The UI should not allow to create non-legacy reactions in 1:1
// conversations with a sender or receiver that does not have
// `REACTION_SUPPORT`.
//
// ²: The UI should not allow to create non-legacy reactions in group
// conversations with a sender that does not have `REACTION_SUPPORT` or when all
// other group members don't have `REACTION_SUPPORT`.
//
// ³: In case the reaction could not be mapped to a legacy reaction, this
// results in a `Reaction` message being sent to group members that currently do
// not support reactions. This is intentional.
//
// ⁴: Note that the _apply_ mechanism is additive, meaning multiple reactions
// from the same sender are allowed on a single message. This is why the
// _withdraw_ mechanism is needed which removes a specific reaction. On the
// other hand, a deprecated `e2e.delivery-receipt` will replace all existing
// reactions of the sender at once (including these new-style reactions).
//
// ⁵: The UI should display a placeholder (�) for unknown emojis, meaining those
// which are not a single fully-qualified [emoji codepoint sequence that is part
// of the currently supported Unicode standard][emoji-test.txt]. But the
// individual code sequences still have individual display buckets.
//
// [emoji-test.txt]: https://www.unicode.org/Public/emoji/latest/emoji-test.txt
message Reaction {
  // Unique ID of the referred message.
  fixed64 message_id = 1;

  // A single emoji reaction to be applied or withdrawn.
  oneof action {
    // Apply a new emoji reaction.
    bytes apply = 2;

    // Withdraw a specific emoji reaction.
    bytes withdraw = 3;
  }
}

// A control message from the Threema Work Directory, providing a set of Work
// Sync Deltas for immediate visibility (or requesting a full Work Sync).
//
// **Properties (1:1)**:
// - Kind: 1:1
// - Flags: None
// - User profile distribution: N/A (not sent by apps)
// - Exempt from blocking: Yes
// - Implicit _direct_ contact creation: N/A (blocking is circumvented)
// - Protect against replay: Yes
// - Unarchive: No
// - Bump _last update_: No
// - Reflect:
//   - Incoming: No
//   - Outgoing: No
//   - _Sent_ update: No
// - Delivery receipts: N/A
// - Reactions: N/A
// - When rejected: N/A (not sent by clients)
// - Edit applies to: N/A
// - Deletable by: N/A
// - Send to Threema Gateway ID group creator: N/A
//
// When receiving this message:
//
// 1. If the application is not built for the _Work_, _Blue_ or _OnPrem_
//    flavour, log a warning, discard the message and abort these steps.
// 2. If the sender is not `*3MAW0RK`, discard the message and abort these
//    steps.
// 3. If `action` is of variant `require_work_sync`, schedule a persistent task
//    to make a full Work Sync.
// 4. If `action` is of variant `apply`:
//    1. Run the _Work Sync Delta Change Determination Steps_ with
//       `apply.deltas` and let `changes` be the result.
//    2. If `changes` is a marker that a _full Work Sync is required_, schedule
//       a persistent task to make a full Work Sync and abort these steps.
//    3. If `changes` is empty, discard the message and abort these steps.
//    4. (MD) Run the following sub-steps:
//       1. Begin a transaction with scope `WORK_SYNC_DELTA` and no
//          precondition.
//       2. Run the _Work Sync Delta Change Determination Steps_ another time
//          and update `changes` with the result.¹
//       3. If `changes` is a marker that a _full Work Sync is required_,
//          schedule a persistent task to make a full Work Sync. Otherwise,
//          reflect all `changes`.
//       4. Commit the transaction and await acknowledgement.
//    5. Apply all `changes` persistently.
// 5. If `action` is an unknown variant, log a warning that an unknown Work Sync
//    variant has been encountered.
//
// ¹: The two-tiered approach is necessary since we want to prevent unnecessary
// transactions from Work Sync Deltas that don't affect any contact in the
// user's contact list. But since changes may affect information that has been
// altered since the transaction was started, it needs to be run twice when
// multi-device is enabled.
//
// The following steps are defined as the _Work Sync Delta Change Determination
// Steps_:
//
// 1. Let `deltas` be a list of `WorkSyncDelta.Delta`.
// 2. Let `changes` be an empty list of _change instructions_ that would be
//    required to apply all `deltas`.
// 3. For each `delta` of `deltas`:
//    1. If `delta.action` is of variant `contact_sync`:
//       1. If `contact_sync.action` is of variant `update`:
//           1. Lookup the contact associated to `update.identity` and let
//              `contact` be the result.
//           2. If `contact` is not defined, discard `update` and continue with
//              the next delta.¹
//           3. If `contact` is not currently considered a work contact, return
//              that a _full Work Sync is required_.
//           4. If `contact`'s last full Work Sync timestamp is defined and ≥
//              `delta.applied_at`, discard `update` and continue with the next
//              delta.
//           5. If `update` does not diverge from the properties of `contact`,
//              discard `update` and continue with the next delta.
//           6. Add a change to `changes` for the necessary changes defined by
//              `update` to update the `contact` in form of a
//              `d2d_sync.Contact`.
//       2. If `contact_sync.action` is an unknown variant, log a warning that
//          an unknown Work Sync Delta contact action has been encountered.
//    2. If `delta.action` is an unknown variant, log a warning that an unknown
//       Work Sync Delta action has been encountered.
// 4. Return `changes`.
//
// ¹: We intentionally do not filter contacts marked as _invalid_ since it may
// be a relevant use case to revoke a contact and then updating other properties
// afterwards, e.g. removing its availability status, etc.
//
// Note: The _Work Sync Delta Change Determination Steps_ may result in
// inconsistencies until the next full Work Sync in some rare edge cases. For
// example, if a change to a contact is currently in progress by another
// device's transaction while this device determines that no change is required.
// This is considered acceptable.
message WorkSyncDelta {
  // Work contact synchronisation message.
  message ContactSync {
    // Update a Work contact.
    message Update {
      // Threema ID of the contact.
      //
      // Always required.
      string identity = 1;

      // Availability status of the contact.
      //
      // Always optional.
      d2d_sync.WorkAvailabilityStatus availability_status = 2;
    }

    // Synchronisation type.
    oneof action {
      // Update a Work contact.
      Update update = 1;
    }
  }

  message Delta {
    // Unix-ish timestamp in milliseconds for when the delta has been applied on
    // the server side (i.e. since when the change is in effect and would be
    // picked up by querying the _Work Sync_, a _Work Contacts_, or the _Work
    // Directory_ endpoint).
    uint64 applied_at = 1;

    oneof action {
      ContactSync contact_sync = 2;
    }
  }

  message Apply {
    repeated Delta deltas = 1;
  }

  oneof action {
    common.Unit require_work_sync = 1;
    Apply apply = 2;
  }
}

¤ Dauer der Verarbeitung: 0.4 Sekunden  (vorverarbeitet am  2026-11-04) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.