syntax = "proto3"; package veilidchat; import "veilid.proto"; import "dht.proto"; // AttachmentKind // Enumeration of well-known attachment types enum AttachmentKind { ATTACHMENT_KIND_UNSPECIFIED = 0; ATTACHMENT_KIND_FILE = 1; ATTACHMENT_KIND_IMAGE = 2; } // A single attachment message Attachment { // Type of the data AttachmentKind kind = 1; // MIME type of the data string mime = 2; // Title or filename string name = 3; // Pointer to the data content dht.DataReference content = 4; // Author signature over all attachment fields and content fields and bytes veilid.Signature signature = 5; } // A single message as part of a series of messages message Message { // Author of the message veilid.TypedKey author = 1; // Time the message was sent (us since epoch) uint64 timestamp = 2; // Text of the message string text = 3; // Author signature over all of the fields and attachment signatures veilid.Signature signature = 4; // Attachments on the message repeated Attachment attachments = 5; } // 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 // // 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; // Identity master (JSON) to publish to friend string identity_master_json = 2; // Messages DHTLog (xxx for now DHTShortArray) veilid.TypedKey messages = 3; } // 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 profile as locally edited Profile edited_profile = 1; // Copy of friend's profile from remote conversation Profile remote_profile = 2; // Copy of friend's IdentityMaster in JSON from remote conversation string identity_master_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 bool show_availability = 7; } // Contact availability enum Availability { AVAILABILITY_UNSPECIFIED = 0; AVAILABILITY_OFFLINE = 1; AVAILABILITY_FREE = 2; AVAILABILITY_BUSY = 3; AVAILABILITY_AWAY = 4; } // 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 string name = 1; // Pronouns of user string pronouns = 2; // Status/away message string status = 3; // Availability Availability availability = 4; // Avatar DHTData optional veilid.TypedKey avatar = 5; } enum ChatType { CHAT_TYPE_UNSPECIFIED = 0; SINGLE_CONTACT = 1; GROUP = 2; } // Either a 1-1 conversation or a group chat (eventually) // Privately encrypted, this is the local user's copy of the chat message Chat { // What kind of chat is this ChatType type = 1; // Conversation key for the other party veilid.TypedKey remote_conversation_record_key = 2; // Reconciled chat record DHTLog (xxx for now DHTShortArray) dht.OwnedDHTRecordPointer reconciled_chat_record = 3; } // 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 uint32 auto_away_timeout_sec = 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; } // EncryptionKeyType // Encryption of secret enum EncryptionKeyType { ENCRYPTION_KEY_TYPE_UNSPECIFIED = 0; ENCRYPTION_KEY_TYPE_NONE = 1; ENCRYPTION_KEY_TYPE_PIN = 2; ENCRYPTION_KEY_TYPE_PASSWORD = 3; } // 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; // Identity master DHT record key veilid.TypedKey identity_master_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 identity master DHT record key veilid.TypedKey identity_master_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; }