// Copyright 2020 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only syntax = "proto3"; package signalservice; option java_package = "org.signal.storageservice.storage.protos.groups"; option java_outer_classname = "GroupProtos"; option java_multiple_files = true; message AvatarUploadAttributes { string key = 1; string credential = 2; string acl = 3; string algorithm = 4; string date = 5; string policy = 6; string signature = 7; } // Stored data message Member { enum Role { UNKNOWN = 0; DEFAULT = 1; ADMINISTRATOR = 2; } bytes user_id = 1; Role role = 2; bytes profileKey = 3; bytes presentation = 4; uint32 joinedAtVersion = 5; // These two fields each decrypt to a UTF8 string bytes label_emoji = 6; bytes label_string = 7; } message MemberPendingProfileKey { Member member = 1; bytes addedByUserId = 2; uint64 timestamp = 3; // ms since epoch } message MemberPendingAdminApproval { bytes user_id = 1; bytes profileKey = 2; bytes presentation = 3; uint64 timestamp = 4; // ms since epoch } message MemberBanned { bytes user_id = 1; uint64 timestamp = 2; // ms since epoch } message AccessControl { enum AccessRequired { UNKNOWN = 0; ANY = 1; MEMBER = 2; ADMINISTRATOR = 3; UNSATISFIABLE = 4; } AccessRequired attributes = 1; AccessRequired members = 2; AccessRequired addFromInviteLink = 3; } message Group { bytes publicKey = 1; bytes title = 2; bytes description = 11; // The URL for this group's avatar. The content at this URL can be // decrypted/deserialized into a `GroupAttributeBlob`. string avatarUrl = 3; bytes disappearingMessagesTimer = 4; AccessControl accessControl = 5; uint32 version = 6; repeated Member members = 7; repeated MemberPendingProfileKey membersPendingProfileKey = 8; repeated MemberPendingAdminApproval membersPendingAdminApproval = 9; bytes inviteLinkPassword = 10; bool announcements_only = 12; repeated MemberBanned members_banned = 13; // next: 14 } message GroupAttributeBlob { oneof content { string title = 1; bytes avatar = 2; uint32 disappearingMessagesDuration = 3; string descriptionText = 4; } } message GroupInviteLink { message GroupInviteLinkContentsV1 { bytes groupMasterKey = 1; bytes inviteLinkPassword = 2; } oneof contents { GroupInviteLinkContentsV1 contentsV1 = 1; } } message GroupJoinInfo { bytes publicKey = 1; bytes title = 2; bytes description = 8; string avatar = 3; uint32 memberCount = 4; AccessControl.AccessRequired addFromInviteLink = 5; uint32 version = 6; bool pendingAdminApproval = 7; bool pendingAdminApprovalFull = 9; // next: 10 } // Deltas message GroupChange { message Actions { message AddMemberAction { Member added = 1; bool joinFromInviteLink = 2; } message DeleteMemberAction { bytes deletedUserId = 1; } message ModifyMemberRoleAction { bytes user_id = 1; Member.Role role = 2; } message ModifyMemberLabelAction { bytes user_id = 1; // These two fields each decrypt to a UTF8 string bytes label_emoji = 2; bytes label_string = 3; } message ModifyMemberProfileKeyAction { bytes presentation = 1; bytes user_id = 2; bytes profile_key = 3; } message AddMemberPendingProfileKeyAction { MemberPendingProfileKey added = 1; } message DeleteMemberPendingProfileKeyAction { bytes deletedUserId = 1; } message PromoteMemberPendingProfileKeyAction { bytes presentation = 1; bytes user_id = 2; bytes profile_key = 3; } message PromoteMemberPendingPniAciProfileKeyAction { bytes presentation = 1; bytes user_id = 2; bytes pni = 3; bytes profile_key = 4; } message AddMemberPendingAdminApprovalAction { MemberPendingAdminApproval added = 1; } message DeleteMemberPendingAdminApprovalAction { bytes deletedUserId = 1; } message PromoteMemberPendingAdminApprovalAction { bytes user_id = 1; Member.Role role = 2; } message AddMemberBannedAction { MemberBanned added = 1; } message DeleteMemberBannedAction { bytes deletedUserId = 1; } message ModifyTitleAction { bytes title = 1; } message ModifyDescriptionAction { bytes description = 1; } message ModifyAvatarAction { string avatar = 1; } message ModifyDisappearingMessageTimerAction { bytes timer = 1; } message ModifyAttributesAccessControlAction { AccessControl.AccessRequired attributesAccess = 1; } message ModifyMembersAccessControlAction { AccessControl.AccessRequired membersAccess = 1; } message ModifyAddFromInviteLinkAccessControlAction { AccessControl.AccessRequired addFromInviteLinkAccess = 1; } message ModifyInviteLinkPasswordAction { bytes inviteLinkPassword = 1; } message ModifyAnnouncementsOnlyAction { bool announcements_only = 1; } bytes sourceUserId = 1; // clients should not provide this value; the server will provide it in the response buffer to ensure the signature is binding to a particular group // if clients set it during a request the server will respond with 400. bytes group_id = 25; uint32 version = 2; repeated AddMemberAction addMembers = 3; repeated DeleteMemberAction deleteMembers = 4; repeated ModifyMemberRoleAction modifyMemberRoles = 5; repeated ModifyMemberLabelAction modifyMemberLabels = 26; // change epoch = 6; repeated ModifyMemberProfileKeyAction modifyMemberProfileKeys = 6; repeated AddMemberPendingProfileKeyAction addMembersPendingProfileKey = 7; repeated DeleteMemberPendingProfileKeyAction deleteMembersPendingProfileKey = 8; repeated PromoteMemberPendingProfileKeyAction promoteMembersPendingProfileKey = 9; ModifyTitleAction modifyTitle = 10; ModifyAvatarAction modifyAvatar = 11; ModifyDisappearingMessageTimerAction modifyDisappearingMessageTimer = 12; ModifyAttributesAccessControlAction modifyAttributesAccess = 13; ModifyMembersAccessControlAction modifyMemberAccess = 14; ModifyAddFromInviteLinkAccessControlAction modifyAddFromInviteLinkAccess = 15; // change epoch = 1 repeated AddMemberPendingAdminApprovalAction addMembersPendingAdminApproval = 16; // change epoch = 1 repeated DeleteMemberPendingAdminApprovalAction deleteMembersPendingAdminApproval = 17; // change epoch = 1 repeated PromoteMemberPendingAdminApprovalAction promoteMembersPendingAdminApproval = 18; // change epoch = 1 ModifyInviteLinkPasswordAction modifyInviteLinkPassword = 19; // change epoch = 1 ModifyDescriptionAction modifyDescription = 20; // change epoch = 2 ModifyAnnouncementsOnlyAction modify_announcements_only = 21; // change epoch = 3 repeated AddMemberBannedAction add_members_banned = 22; // change epoch = 4 repeated DeleteMemberBannedAction delete_members_banned = 23; // change epoch = 4 repeated PromoteMemberPendingPniAciProfileKeyAction promote_members_pending_pni_aci_profile_key = 24; // change epoch = 5 // next: 27 } bytes actions = 1; bytes serverSignature = 2; uint32 changeEpoch = 3; } // External credentials message ExternalGroupCredential { string token = 1; } // API responses message GroupResponse { Group group = 1; bytes group_send_endorsements_response = 2; } message GroupChanges { message GroupChangeState { GroupChange groupChange = 1; Group groupState = 2; } repeated GroupChangeState groupChanges = 1; bytes group_send_endorsements_response = 2; } message GroupChangeResponse { GroupChange group_change = 1; bytes group_send_endorsements_response = 2; }