mirror of
https://gitlab.com/veilid/veilidchat.git
synced 2024-10-01 06:55:46 -04:00
481 lines
16 KiB
Protocol Buffer
481 lines
16 KiB
Protocol Buffer
////////////////////////////////////////////////////////////////////////////////////
|
|
// VeilidChat Protocol Buffer Definitions
|
|
//
|
|
// * Timestamps are in microseconds (us) since epoch
|
|
// * Durations are in microseconds (us)
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
syntax = "proto3";
|
|
package veilidchat;
|
|
|
|
import "veilid.proto";
|
|
import "dht.proto";
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// Enumerations
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Contact availability
|
|
enum Availability {
|
|
AVAILABILITY_UNSPECIFIED = 0;
|
|
AVAILABILITY_OFFLINE = 1;
|
|
AVAILABILITY_FREE = 2;
|
|
AVAILABILITY_BUSY = 3;
|
|
AVAILABILITY_AWAY = 4;
|
|
}
|
|
|
|
// Encryption used on secret keys
|
|
enum EncryptionKeyType {
|
|
ENCRYPTION_KEY_TYPE_UNSPECIFIED = 0;
|
|
ENCRYPTION_KEY_TYPE_NONE = 1;
|
|
ENCRYPTION_KEY_TYPE_PIN = 2;
|
|
ENCRYPTION_KEY_TYPE_PASSWORD = 3;
|
|
}
|
|
|
|
// Scope of a chat
|
|
enum Scope {
|
|
// Can read chats but not send messages
|
|
WATCHERS = 0;
|
|
// Can send messages subject to moderation
|
|
// If moderation is disabled, this is equivalent to WATCHERS
|
|
MODERATED = 1;
|
|
// Can send messages without moderation
|
|
TALKERS = 2;
|
|
// Can moderate messages sent my members if moderation is enabled
|
|
MODERATORS = 3;
|
|
// Can perform all actions
|
|
ADMINS = 4;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// Data
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Reference to data on the DHT
|
|
message DHTDataReference {
|
|
veilid.TypedKey dht_data = 1;
|
|
veilid.TypedKey hash = 2;
|
|
}
|
|
|
|
// Reference to data on the BlockStore
|
|
message BlockStoreDataReference {
|
|
veilid.TypedKey block = 1;
|
|
}
|
|
|
|
// DataReference
|
|
// Pointer to data somewhere in Veilid
|
|
// Abstraction over DHTData and BlockStore
|
|
message DataReference {
|
|
oneof kind {
|
|
DHTDataReference dht_data = 1;
|
|
BlockStoreDataReference block_store_data = 2;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// Attachments
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// A single attachment
|
|
message Attachment {
|
|
oneof kind {
|
|
AttachmentMedia media = 1;
|
|
}
|
|
// Author signature over all attachment fields and content fields and bytes
|
|
veilid.Signature signature = 2;
|
|
}
|
|
|
|
// A file, audio, image, or video attachment
|
|
message AttachmentMedia {
|
|
// MIME type of the data
|
|
string mime = 1;
|
|
// Title or filename
|
|
string name = 2;
|
|
// Pointer to the data content
|
|
DataReference content = 3;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// Chat room controls
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Permissions of a chat
|
|
message Permissions {
|
|
// Parties in this scope or higher can add members to their own group or lower
|
|
Scope can_add_members = 1;
|
|
// Parties in this scope or higher can change the 'info' of a group
|
|
Scope can_edit_info = 2;
|
|
// If moderation is enabled or not.
|
|
bool moderated = 3;
|
|
}
|
|
|
|
// The membership of a chat
|
|
message Membership {
|
|
// Conversation keys for parties in the 'watchers' group
|
|
repeated veilid.TypedKey watchers = 1;
|
|
// Conversation keys for parties in the 'moderated' group
|
|
repeated veilid.TypedKey moderated = 2;
|
|
// Conversation keys for parties in the 'talkers' group
|
|
repeated veilid.TypedKey talkers = 3;
|
|
// Conversation keys for parties in the 'moderators' group
|
|
repeated veilid.TypedKey moderators = 4;
|
|
// Conversation keys for parties in the 'admins' group
|
|
repeated veilid.TypedKey admins = 5;
|
|
}
|
|
|
|
// The chat settings
|
|
message ChatSettings {
|
|
// Title for the chat
|
|
string title = 1;
|
|
// Description for the chat
|
|
string description = 2;
|
|
// Icon for the chat
|
|
optional DataReference icon = 3;
|
|
// Default message expiration duration (in us)
|
|
uint64 default_expiration = 4;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// Messages
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// A single message as part of a series of messages
|
|
message Message {
|
|
|
|
// A text message
|
|
message Text {
|
|
// Text of the message
|
|
string text = 1;
|
|
// Topic of the message / Content warning
|
|
optional string topic = 2;
|
|
// Message id replied to (author id + message id)
|
|
optional bytes reply_id = 3;
|
|
// Message expiration timestamp
|
|
uint64 expiration = 4;
|
|
// Message view limit before deletion
|
|
uint32 view_limit = 5;
|
|
// Attachments on the message
|
|
repeated Attachment attachments = 6;
|
|
}
|
|
|
|
// A secret message
|
|
message Secret {
|
|
// Text message protobuf encrypted by a key
|
|
bytes ciphertext = 1;
|
|
// Secret expiration timestamp
|
|
// This is the time after which an un-revealed secret will get deleted
|
|
uint64 expiration = 2;
|
|
}
|
|
|
|
// A 'delete' control message
|
|
// Deletes a set of messages by their ids
|
|
message ControlDelete {
|
|
repeated bytes ids = 1;
|
|
}
|
|
// An 'erase' control message
|
|
// Deletes a set of messages from before some timestamp
|
|
message ControlErase {
|
|
// The latest timestamp to delete messages before
|
|
// If this is zero then all messages are cleared
|
|
uint64 timestamp = 1;
|
|
}
|
|
// A 'change settings' control message
|
|
message ControlSettings {
|
|
ChatSettings settings = 1;
|
|
}
|
|
|
|
// A 'change permissions' control message
|
|
// Changes the permissions of a chat
|
|
message ControlPermissions {
|
|
Permissions permissions = 1;
|
|
}
|
|
|
|
// A 'change membership' control message
|
|
// Changes the
|
|
message ControlMembership {
|
|
Membership membership = 1;
|
|
}
|
|
|
|
// A 'moderation' control message
|
|
// Accepts or rejects a set of messages
|
|
message ControlModeration {
|
|
repeated bytes accepted_ids = 1;
|
|
repeated bytes rejected_ids = 2;
|
|
}
|
|
|
|
// A 'read receipt' control message
|
|
message ControlReadReceipt {
|
|
repeated bytes read_ids = 1;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// Unique id for this author stream
|
|
// Calculated from the hash of the previous message from this author
|
|
bytes id = 1;
|
|
// Author of the message (identity public key)
|
|
veilid.TypedKey author = 2;
|
|
// Time the message was sent according to sender
|
|
uint64 timestamp = 3;
|
|
|
|
// Message kind
|
|
oneof kind {
|
|
Text text = 4;
|
|
Secret secret = 5;
|
|
ControlDelete delete = 6;
|
|
ControlErase erase = 7;
|
|
ControlSettings settings = 8;
|
|
ControlPermissions permissions = 9;
|
|
ControlMembership membership = 10;
|
|
ControlModeration moderation = 11;
|
|
}
|
|
|
|
// Author signature over all of the fields and attachment signatures
|
|
veilid.Signature signature = 12;
|
|
}
|
|
|
|
// Locally stored messages for chats
|
|
message ReconciledMessage {
|
|
// The message as sent
|
|
Message content = 1;
|
|
// The timestamp the message was reconciled
|
|
uint64 reconciled_time = 2;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// Chats
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// The means of direct communications that is synchronized between
|
|
// two users. Visible and encrypted for the other party.
|
|
// Includes communications for:
|
|
// * Profile changes
|
|
// * Identity changes
|
|
// * 1-1 chat messages
|
|
// * Group chat messages
|
|
//
|
|
// DHT Schema: SMPL(0,1,[identityPublicKey])
|
|
// DHT Key (UnicastOutbox): localConversation
|
|
// DHT Secret: None
|
|
// Encryption: DH(IdentityA, IdentityB)
|
|
message Conversation {
|
|
// Profile to publish to friend
|
|
Profile profile = 1;
|
|
// SuperIdentity (JSON) to publish to friend or chat room
|
|
string super_identity_json = 2;
|
|
// Messages DHTLog
|
|
veilid.TypedKey messages = 3;
|
|
}
|
|
|
|
// A member of chat which may or may not be associated with a contact
|
|
message ChatMember {
|
|
// The identity public key most recently associated with the chat member
|
|
veilid.TypedKey remote_identity_public_key = 1;
|
|
// Conversation key for the other party
|
|
veilid.TypedKey remote_conversation_record_key = 2;
|
|
}
|
|
|
|
// A 1-1 chat
|
|
// Privately encrypted, this is the local user's copy of the chat
|
|
message DirectChat {
|
|
// Settings
|
|
ChatSettings settings = 1;
|
|
// Conversation key for this user
|
|
veilid.TypedKey local_conversation_record_key = 2;
|
|
// Conversation key for the other party
|
|
ChatMember remote_member = 3;
|
|
}
|
|
|
|
// A group chat
|
|
// Privately encrypted, this is the local user's copy of the chat
|
|
message GroupChat {
|
|
// Settings
|
|
ChatSettings settings = 1;
|
|
// Membership
|
|
Membership membership = 2;
|
|
// Permissions
|
|
Permissions permissions = 3;
|
|
// Conversation key for this user
|
|
veilid.TypedKey local_conversation_record_key = 4;
|
|
// Conversation keys for the other parties
|
|
repeated ChatMember remote_members = 5;
|
|
}
|
|
|
|
// Some kind of chat
|
|
message Chat {
|
|
oneof kind {
|
|
DirectChat direct = 1;
|
|
GroupChat group = 2;
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// Accounts
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Publicly shared profile information for both contacts and accounts
|
|
// Contains:
|
|
// Name - Friendly name
|
|
// Pronouns - Pronouns of user
|
|
// Icon - Little picture to represent user in contact list
|
|
message Profile {
|
|
// Friendy name (max length 64)
|
|
string name = 1;
|
|
// Pronouns of user (max length 64)
|
|
string pronouns = 2;
|
|
// Description of the user (max length 1024)
|
|
string about = 3;
|
|
// Status/away message (max length 128)
|
|
string status = 4;
|
|
// Availability
|
|
Availability availability = 5;
|
|
// Avatar
|
|
optional DataReference avatar = 6;
|
|
// Timestamp of last change
|
|
uint64 timestamp = 7;
|
|
}
|
|
|
|
// A record of an individual account
|
|
// Pointed to by the identity account map in the identity key
|
|
//
|
|
// DHT Schema: DFLT(1)
|
|
// DHT Private: accountSecretKey
|
|
message Account {
|
|
// The user's profile that gets shared with contacts
|
|
Profile profile = 1;
|
|
// Invisibility makes you always look 'Offline'
|
|
bool invisible = 2;
|
|
// Auto-away sets 'away' mode after an inactivity time (only if autodetect_away is set)
|
|
uint32 auto_away_timeout_min = 3;
|
|
// The contacts DHTList for this account
|
|
// DHT Private
|
|
dht.OwnedDHTRecordPointer contact_list = 4;
|
|
// The ContactInvitationRecord DHTShortArray for this account
|
|
// DHT Private
|
|
dht.OwnedDHTRecordPointer contact_invitation_records = 5;
|
|
// The Chats DHTList for this account
|
|
// DHT Private
|
|
dht.OwnedDHTRecordPointer chat_list = 6;
|
|
// The GroupChats DHTList for this account
|
|
// DHT Private
|
|
dht.OwnedDHTRecordPointer group_chat_list = 7;
|
|
// Free message (max length 128)
|
|
string free_message = 8;
|
|
// Busy message (max length 128)
|
|
string busy_message = 9;
|
|
// Away message (max length 128)
|
|
string away_message = 10;
|
|
// Auto-detect away
|
|
bool autodetect_away = 11;
|
|
|
|
}
|
|
|
|
// A record of a contact that has accepted a contact invitation
|
|
// Contains a copy of the most recent remote profile as well as
|
|
// a locally edited profile.
|
|
// Contains a copy of the most recent identity from the contact's
|
|
// Master identity dht key
|
|
//
|
|
// Stored in ContactList DHTList
|
|
message Contact {
|
|
// Friend's nickname
|
|
string nickname = 1;
|
|
// Copy of friend's profile from remote conversation
|
|
Profile profile = 2;
|
|
// Copy of friend's SuperIdentity in JSON from remote conversation
|
|
string super_identity_json = 3;
|
|
// Copy of friend's most recent identity public key from their identityMaster
|
|
veilid.TypedKey identity_public_key = 4;
|
|
// Remote conversation key to sync from friend
|
|
veilid.TypedKey remote_conversation_record_key = 5;
|
|
// Our conversation key for friend to sync
|
|
veilid.TypedKey local_conversation_record_key = 6;
|
|
// Show availability to this contact
|
|
bool show_availability = 7;
|
|
// Notes about this friend
|
|
string notes = 8;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
// Invitations
|
|
////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Invitation that is shared for VeilidChat contact connections
|
|
// serialized to QR code or data blob, not send over DHT, out of band.
|
|
// Writer secret is unique to this invitation. Writer public key is in the ContactRequestPrivate
|
|
// in the ContactRequestInbox subkey 0 DHT key
|
|
message ContactInvitation {
|
|
// Contact request DHT record key
|
|
veilid.TypedKey contact_request_inbox_key = 1;
|
|
// Writer secret key bytes possibly encrypted with nonce appended
|
|
bytes writer_secret = 2;
|
|
}
|
|
|
|
// Signature of invitation with identity
|
|
message SignedContactInvitation {
|
|
// The serialized bytes for the contact invitation
|
|
bytes contact_invitation = 1;
|
|
// The signature of the contact_invitation bytes with the identity
|
|
veilid.Signature identity_signature = 2;
|
|
}
|
|
|
|
// Contact request unicastinbox on the DHT
|
|
// DHTSchema: SMPL 1 owner key, 1 writer key symmetrically encrypted with writer secret
|
|
message ContactRequest {
|
|
// The kind of encryption used on the unicastinbox writer key
|
|
EncryptionKeyType encryption_key_type = 1;
|
|
// The private part encoded and symmetrically encrypted with the unicastinbox writer secret
|
|
bytes private = 2;
|
|
}
|
|
|
|
// The private part of a possibly encrypted contact request
|
|
// Symmetrically encrypted with writer secret
|
|
message ContactRequestPrivate {
|
|
// Writer public key for signing writes to contact request unicastinbox
|
|
veilid.CryptoKey writer_key = 1;
|
|
// Snapshot of profile
|
|
Profile profile = 2;
|
|
// SuperIdentity DHT record key
|
|
veilid.TypedKey super_identity_record_key = 3;
|
|
// Local chat DHT record key
|
|
veilid.TypedKey chat_record_key = 4;
|
|
// Expiration timestamp
|
|
uint64 expiration = 5;
|
|
}
|
|
|
|
// To accept or reject a contact request, fill this out and send to the ContactRequest unicastinbox
|
|
message ContactResponse {
|
|
// Accept or reject
|
|
bool accept = 1;
|
|
// Remote SuperIdentity DHT record key
|
|
veilid.TypedKey super_identity_record_key = 2;
|
|
// Remote chat DHT record key if accepted
|
|
veilid.TypedKey remote_conversation_record_key = 3;
|
|
}
|
|
|
|
// Signature of response with identity
|
|
// Symmetrically encrypted with writer secret
|
|
message SignedContactResponse {
|
|
// Serialized bytes for ContactResponse
|
|
bytes contact_response = 1;
|
|
// Signature of the contact_accept bytes with the identity
|
|
veilid.Signature identity_signature = 2;
|
|
}
|
|
|
|
// Contact request record kept in Account DHTList to keep track of extant contact invitations
|
|
message ContactInvitationRecord {
|
|
// Contact request unicastinbox DHT record key (parent is accountkey)
|
|
dht.OwnedDHTRecordPointer contact_request_inbox = 1;
|
|
// Writer key sent to contact for the contact_request_inbox smpl inbox subkey
|
|
veilid.CryptoKey writer_key = 2;
|
|
// Writer secret sent encrypted in the invitation
|
|
veilid.CryptoKey writer_secret = 3;
|
|
// Local chat DHT record key (parent is accountkey, will be moved to Contact if accepted)
|
|
veilid.TypedKey local_conversation_record_key = 4;
|
|
// Expiration timestamp
|
|
uint64 expiration = 5;
|
|
// A copy of the raw SignedContactInvitation invitation bytes post-encryption and signing
|
|
bytes invitation = 6;
|
|
// The message sent along with the invitation
|
|
string message = 7;
|
|
} |