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
// Messages are stored in a DHTLog
// DHT Schema: SMPL(0,1,[identityPublicKey])
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;
}

// A record of a 1-1 chat that is synchronized between
// two users. Visible and encrypted for the other party
//
// 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 converation or a group chat (eventually)
message Chat {
    // What kind of chat is this
    ChatType type = 1;
    // 1-1 Chat key
    veilid.TypedKey remote_conversation_key = 2;
}

// 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;
}