// Copyright 2020 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only package signalservice; option java_package = "org.whispersystems.signalservice.internal.storage"; option java_outer_classname = "SignalStorageProtos"; enum OptionalBool { UNSET = 0; ENABLED = 1; DISABLED = 2; } message StorageManifest { optional uint64 version = 1; optional bytes value = 2; } message StorageItem { optional bytes key = 1; optional bytes value = 2; } message StorageItems { repeated StorageItem items = 1; } message ReadOperation { repeated bytes readKey = 1; } message WriteOperation { optional StorageManifest manifest = 1; repeated StorageItem insertItem = 2; repeated bytes deleteKey = 3; optional bool clearAll = 4; } message ManifestRecord { message Identifier { enum Type { UNKNOWN = 0; CONTACT = 1; GROUPV1 = 2; GROUPV2 = 3; ACCOUNT = 4; STORY_DISTRIBUTION_LIST = 5; STICKER_PACK = 6; CALL_LINK = 7; } optional bytes raw = 1; optional Type type = 2; } optional uint64 version = 1; optional uint32 sourceDevice = 3; repeated Identifier keys = 2; optional bytes recordIkm = 4; // Next ID: 5 } message StorageRecord { oneof record { ContactRecord contact = 1; GroupV1Record groupV1 = 2; GroupV2Record groupV2 = 3; AccountRecord account = 4; StoryDistributionListRecord storyDistributionList = 5; StickerPackRecord stickerPack = 6; CallLinkRecord callLink = 7; } } message ContactRecord { enum IdentityState { DEFAULT = 0; VERIFIED = 1; UNVERIFIED = 2; } message Name { optional string given = 1; optional string family = 2; } optional string aci = 1; optional string serviceE164 = 2; optional string pni = 15; optional bytes profileKey = 3; optional bytes identityKey = 4; optional IdentityState identityState = 5; optional string givenName = 6; optional string familyName = 7; optional string username = 8; optional bool blocked = 9; optional bool whitelisted = 10; optional bool archived = 11; optional bool markedUnread = 12; optional uint64 mutedUntilTimestamp = 13; optional bool hideStory = 14; optional uint64 unregisteredAtTimestamp = 16; optional string systemGivenName = 17; optional string systemFamilyName = 18; optional string systemNickname = 19; optional bool hidden = 20; optional bool pniSignatureVerified = 21; optional Name nickname = 22; optional string note = 23; } message GroupV1Record { optional bytes id = 1; optional bool blocked = 2; optional bool whitelisted = 3; optional bool archived = 4; optional bool markedUnread = 5; optional uint64 mutedUntilTimestamp = 6; } message GroupV2Record { enum StorySendMode { DEFAULT = 0; DISABLED = 1; ENABLED = 2; } optional bytes masterKey = 1; optional bool blocked = 2; optional bool whitelisted = 3; optional bool archived = 4; optional bool markedUnread = 5; optional uint64 mutedUntilTimestamp = 6; optional bool dontNotifyForMentionsIfMuted = 7; optional bool hideStory = 8; reserved /* storySendEnabled */ 9; // removed optional StorySendMode storySendMode = 10; } message AccountRecord { enum PhoneNumberSharingMode { UNKNOWN = 0; EVERYBODY = 1; NOBODY = 2; } message PinnedConversation { message Contact { optional string serviceId = 1; optional string e164 = 2; } oneof identifier { Contact contact = 1; bytes legacyGroupId = 3; bytes groupMasterKey = 4; } } message UsernameLink { enum Color { UNKNOWN = 0; BLUE = 1; WHITE = 2; GREY = 3; OLIVE = 4; GREEN = 5; ORANGE = 6; PINK = 7; PURPLE = 8; } optional bytes entropy = 1; // 32 bytes of entropy used for encryption optional bytes serverId = 2; // 16 bytes of encoded UUID provided by the server optional Color color = 3; // color of the QR code itself } optional bytes profileKey = 1; optional string givenName = 2; optional string familyName = 3; optional string avatarUrl = 4; optional bool noteToSelfArchived = 5; optional bool readReceipts = 6; optional bool sealedSenderIndicators = 7; optional bool typingIndicators = 8; reserved 9; // proxiedLinkPreviews optional bool noteToSelfMarkedUnread = 10; optional bool linkPreviews = 11; optional PhoneNumberSharingMode phoneNumberSharingMode = 12; optional bool notDiscoverableByPhoneNumber = 13; repeated PinnedConversation pinnedConversations = 14; optional bool preferContactAvatars = 15; optional uint32 universalExpireTimer = 17; optional bool primarySendsSms = 18; reserved 19; // deprecatedE164 repeated string preferredReactionEmoji = 20; optional bytes subscriberId = 21; optional string subscriberCurrencyCode = 22; optional bool displayBadgesOnProfile = 23; optional bool donorSubscriptionManuallyCancelled = 24; optional bool keepMutedChatsArchived = 25; optional bool hasSetMyStoriesPrivacy = 26; optional bool hasViewedOnboardingStory = 27; reserved 28; // deprecatedStoriesDisabled optional bool storiesDisabled = 29; optional OptionalBool storyViewReceiptsEnabled = 30; reserved 31; // hasReadOnboardingStory optional bool hasSeenGroupStoryEducationSheet = 32; optional string username = 33; optional bool hasCompletedUsernameOnboarding = 34; optional UsernameLink usernameLink = 35; optional bytes backupsSubscriberId = 36; optional string backupsSubscriberCurrencyCode = 37; optional bool backupsSubscriptionManuallyCancelled = 38; } message StoryDistributionListRecord { optional bytes identifier = 1; optional string name = 2; repeated string recipientServiceIds = 3; optional uint64 deletedAtTimestamp = 4; optional bool allowsReplies = 5; optional bool isBlockList = 6; } message StickerPackRecord { optional bytes packId = 1; // 16 bytes optional bytes packKey = 2; // 32 bytes, used to derive the AES-256 key // aesKey = HKDF( // input = packKey, // salt = 32 zero bytes, // info = "Sticker Pack" // ) optional uint32 position = 3; // When displayed sticker packs should be first sorted // in descending order by zero-based `position` and // then by ascending `packId` (lexicographically, // packId can be treated as a hex string). // When installing a sticker pack the client should find // the maximum `position` among currently known stickers // and use `max_position + 1` as the value for the new // `position`. optional uint64 deletedAtTimestamp = 4; // Timestamp in milliseconds. When present and // non-zero - `packKey` and `position` should // be unset } message CallLinkRecord { optional bytes rootKey = 1; // 16 bytes optional bytes adminPasskey = 2; // Non-empty when the current user is an admin optional uint64 deletedAtTimestampMs = 3; // When present and non-zero, `adminPasskey` // should be cleared }