# Message Identity Specifications (Draft v1)
## NOTE: superceded by [**Draft v2**](https://notes.status.im/oUChlPB3Q2aUPLYBSjq6MQ?both)
The following specification detaisl the methods and processes by which to handle user defined identity data, including:
- ENS name data
- Display name data
- Profile image data
## Table of contents
[toc]
## Protobuf structure
```protobuf
// ProfileImage represents data associated with a user's profile image
message ProfileImage {
// source_type allows the application to use a range of image sources
SourceType source_type = 1;
// source is a context based source for the profile image data,
// context is determined by the `source_type`
string source = 2;
// SourceType are the predefined types of image source allowed
enum SourceType {
UNKNOWN_SOURCE_TYPE = 0;
// ENS_AVATAR uses the ENS record's resolver get-text-data.avatar data
// if `source` is empty inspect record
// if `source` is set use source URL
// The parent `ChatMessageIdentity` must have a valid `ens_name` set
ENS_AVATAR = 1;
// IPFS_ADDRESS uses IPFS to get the image data
// 'source' must be set
// `source` is an IPFS address
IPFS_ADDRESS = 2;
// URL_ADDRESS uses a standard internet URL to the image data
// `source` must be set
// `source` is a URL
URL_ADDRESS = 3;
// RAW_PAYLOAD uses base64 encoded image data
// `source` must be set
// `source` is base64 encoded image data
RAW_PAYLOAD = 4;
}
}
// ChatMessageIdentity represents the user defined identity associated with their messages
message ChatMessageIdentity {
// ens_name is the valid ENS name associated with the chat key
string ens_name = 1;
// display_name is the user's chosen display name
string display_name = 2;
// profile_image is the data associated with the user's profile image
ProfileImage profile_image = 3;
}
message ChatMessage {
//...
// Self defined identity data of sender
ChatMessageIdentity identity = 5;
//...
}
```
## JSON Examples
**Display name with IPFS profile image**
```json
{
"ChatMessage": {
"text": "Hey there!",
"identity": {
"display_name": "lilblockchainz",
"profile_image": {
"source": "QmR7GSQM93Cx5eAg6a6yRzNde1FQv7uL6X1o4k7zrJa3LX",
"source_type": 2
}
}
}
}
```
**ENS name with ENS avatar profile image**
```json
{
"ChatMessage": {
"text": "Hey there!",
"identity": {
"ens_name": "lilblockchainz.eth",
"profile_image": {
"source_type": 1
}
}
}
}
```
**No display name (defaults to random 3 word) URL profile image**
```json
{
"ChatMessage": {
"text": "Hey there!",
"identity": {
"profile_image": {
"source": "https://example.com/images/profile.png",
"source_type": 3
}
}
}
}
```
**No message identity (defaults to random 3 word)**
```json
{
"ChatMessage": {
"text": "Hey there!"
}
}
```
**Empty template**
```json
{
"ChatMessage": {
"text": "",
"identity": {
"ens_name": "",
"display_name": "",
"profile_image": {
"source": "",
"source_type": 0
}
}
}
}
```
## Persistence
### User's identity data
// TODO
### Other user's (correspondants) identity data
To efficiently handle identity data of messages from other identities the device should implement persistence.
**Note:**
Update the existing `contacts` table to handle persistence
```sql
CREATE TABLE IF NOT EXISTS message_identities (
/* chat_key the message author's public chat key, used as the index*/
chat_key VARCHAR PRIMARY KEY ON CONFLICT REPLACE,
/* identity_hash the sha256 hash of the parsed ChatMessageIdentity */
identity_hash VARCHAR NOT NULL,
/* last_clock is the clock value of the message that contained the last */
/* unique ChatMessageIdentity hash, used to determine which identity */
/* data should be given priority if the message sender changes their */
/* data multiple times since the last message pull */
last_clock
/* ens_name a valid ENS name associated with the user's chat key */
ens_name VARCHAR,
/* display_name the given display name */
display_name VARCHAR,
/* profile_image_dst the local path to the profile image cached on the user's device */
profile_image_dst VARCHAR
/* profile_image_source_type is an enum representing the source type of the profile image */
profile_image_source_type int
/* profile_image_last_updated is the last date that the profile image cache was updated */
profile_image_last_updated TIME
);
```
#### `identity_hash`
The `identity_hash` is a sha256 hash of the parsed ChatMessageIdentity protobuf, used to make checking for identity changes simple.
#### `profile_image_dst`
The `profile_image_dst` is the file path of the locally stored image file of a message identity profile image. The file represents a sanitised cache of the image file to be renewed every 7 days or when an image update is received from a new message or a manual image update request is given.
## Security precautions
Sanitise and cache all images to be displayed by the device.
## Process flows
### Setting Identity process flow
```mermaid
graph LR
%% Intities
user((User))
subgraph status [Status App]
subgraph status-react
UI{UI}
end
subgraph status-go
db[(db - chat_identity)]
int[Account management service]
API[Account management API Endpoint]
end
end
%% Connections
user --> UI
UI --> API
API --> int
int --> db
```
### Sending message process flow
```mermaid
graph LR
%% Intities
user((User))
subgraph status [Status App]
subgraph status-react
UI{UI}
end
subgraph status-go
db[(db - chat_identity)]
int[Send message service]
API[Send Message API Endpoint]
end
end
network{{Waku Network}}
%% Connections
user --> UI
UI --> API
API -->|Step 1| int
int -->|Step 2| db
db -->|Step 3| int
int -->|Step 4| network
```
Step 1 - Standard unchanged send message API call
Step 2 - query db for user identity data from `chat_identity` table, or memory store
Step 3 - attach identity data to waku message
Step 4 - Standard unchanged broadcast to waku network
### Receiving message process flow
```mermaid
graph BT
%% Intities
user((User))
subgraph status [Status App]
subgraph status-react
UI{UI}
end
subgraph status-go
db[(db - message_identities)]
ser[Get Messages service]
API[Get Messages API Endpoint]
dir[Image Cache]
end
end
network{{Waku Network}}
%% Connections
user --> UI -->|Step 11| user
UI --> API -->|Step 10| UI
API -->|Step 1| ser -->|Step 9| API
ser -->|Step 2| network -->|Step 3 & 4| ser
ser -->|Step 5| db -->|Step 6| ser
ser -->|Step 7| dir
ser -->|Step 8| db
```
1. Standard unchanged get message API call
2. Standard call to Waku network / mailserver for new messages
3. Standard messages return
4. Parse messages
- Extract any `ChatMessageIdentity` data from chat message payloads
- Calculate hashes for all unique `ChatMessageIdentity`
- Assign `ChatMessageIdentity` to memory mapping (`map[chat_key]ChatMessageIdentity`)
- ignore any duplicates or any `ChatMessageIdentity` from a message with a lower clock than in the mapping
5. Get `identity_hash`, `last_clock` and `profile_image_last_updated` stored in `message_identities` where the chat keys match the map indexes
6. Compare `identity_hash` and `last_clock` against each chat key
- If the new message clock is higher and the hash does not match proceed to step 7
- If no record was found for the chat key proceed to step 7
7. Check image is new or that cache age is too old
- Resolve parsed protobuf `ProfileImage` (because there are many potential sources for an image this would be a large part of the work)
- Get raw image data from ENS, IPFS, payload, URL etc
- Parse and sanitise the image data
- Store image on local device disk
8. Update or create record in the database
9. Append to the `MessengerResponse.Contact` struct return data to API endpoint
10. Standard message response return
11. `status-react` populates new messages in the chat view with contact data
- Setting the user display names, profile photos, etc
### Image cache update process flow
In theory this would only affect images with a source type of `ENS_AVATAR` or `URL_ADDRESS`, as these two are the only sources that have the potential to change without the altering the `ChatMessageIdentity` hash.
This process would be triggered by an API call and/or as part of the [Receiving message process flow](#Receiving-message-process-flow)
```mermaid
graph LR
%% Intities
subgraph status-go
db[(db - message_identities)]
ser[Update Profile Image Cache service]
dir[Image Cache]
end
%% Connections
Signal -->|Step 1| ser
db -->|Step 2| ser -->|Step 3| db
ser -->|Step 4| dir
ser -->|Step 5| db
```
// TODO detail the steps