edits
All checks were successful
/ deploy (push) Successful in 51s

This commit is contained in:
Alex Emmet 2026-07-13 14:07:56 +02:00
commit f254ac3534
2 changed files with 174 additions and 0 deletions

View file

@ -25,6 +25,161 @@ The messaging system follows a strict derivation loop to ensure delivery and cor
- **If the client doesn't answer:** - **If the client doesn't answer:**
1. The other Iota will send a `message_state` to the initial Iota with the state `"sent"`. 1. The other Iota will send a `message_state` to the initial Iota with the state `"sent"`.
2. The initial Iota will store the state and forward the `message_state` to its client. 2. The initial Iota will store the state and forward the `message_state` to its client.
### Message mutations
`Iota` stores each mutation on the sender and recipient replicas. `Content` remains encrypted chat content. The sender is taken from the authenticated MTP connection and must own the original message for edits and deletion.
#### `MessageEdit`
Changes an existing message. `ChatPartnerId` and `SendTime` identify the message.
##### `REQ (C2S):`
```json
{
"type": "MessageEdit",
"sender_id": "<authenticated-user-id>",
"data": {
"ChatPartnerId": "<chat-partner-id>",
"SendTime": "<message-unix-milliseconds>",
"Content": "<encrypted-base64>"
}
}
```
##### `RES (S2C):`
```json
{
"type": "Success"
}
```
##### `UPDATE:`
```json
{
"type": "MessageEditLive",
"sender_id": "<editing-user-id>",
"receiver_id": "<chat-partner-id>",
"data": {
"ChatPartnerId": "<editing-user-id>",
"SendTime": "<message-unix-milliseconds>",
"Content": "<encrypted-base64>"
}
}
```
#### `MessageReactionAdd`
Adds one reaction for the authenticated user. Repeating the same request does not create a duplicate row.
##### `REQ (C2S):`
```json
{
"type": "MessageReactionAdd",
"sender_id": "<authenticated-user-id>",
"data": {
"ChatPartnerId": "<chat-partner-id>",
"SendTime": "<message-unix-milliseconds>",
"Reaction": "<emoji-or-reaction-text>"
}
}
```
##### `RES (S2C):`
```json
{
"type": "Success"
}
```
#### `MessageReactionRemove`
Removes the authenticated user's matching reaction.
##### `REQ (C2S):`
```json
{
"type": "MessageReactionRemove",
"sender_id": "<authenticated-user-id>",
"data": {
"ChatPartnerId": "<chat-partner-id>",
"SendTime": "<message-unix-milliseconds>",
"Reaction": "<emoji-or-reaction-text>"
}
}
```
##### `RES (S2C):`
```json
{
"type": "Success"
}
```
##### `UPDATE:`
```json
{
"type": "MessageReactionLive",
"sender_id": "<reacting-user-id>",
"receiver_id": "<chat-partner-id>",
"data": {
"ChatPartnerId": "<reacting-user-id>",
"SendTime": "<message-unix-milliseconds>",
"Reaction": "<emoji-or-reaction-text>",
"SenderId": "<reacting-user-id>",
"Accepted": true
}
}
```
`Accepted` is `true` for an add and `false` for a removal.
#### `MessageDeleteLive`
Deletes a message from both replicas. The existing `MessageDeleteLive` MTP type is used for both the authenticated delete request and the recipient update because no separate delete request type exists in the client type map.
##### `REQ (C2S):`
```json
{
"type": "MessageDeleteLive",
"sender_id": "<authenticated-user-id>",
"data": {
"ChatPartnerId": "<chat-partner-id>",
"SendTime": "<message-unix-milliseconds>"
}
}
```
##### `RES (S2C):`
```json
{
"type": "Success"
}
```
##### `UPDATE:`
```json
{
"type": "MessageDeleteLive",
"sender_id": "<deleting-user-id>",
"receiver_id": "<chat-partner-id>",
"data": {
"ChatPartnerId": "<deleting-user-id>",
"SendTime": "<message-unix-milliseconds>"
}
}
```
- **If the client answers with `message_state`:** - **If the client answers with `message_state`:**
1. The other Iota will store the state (either `"received"` or `"read"`) and forward the `message_state` to the initial Iota. 1. The other Iota will store the state (either `"received"` or `"read"`) and forward the `message_state` to the initial Iota.
2. The initial Iota will store the state and forward the `message_state` to its client. 2. The initial Iota will store the state and forward the `message_state` to its client.
@ -133,6 +288,13 @@ The iota will never read, or handle the chat_partner_name.
"sent_by_self": true, "sent_by_self": true,
"timestamp": 0, // UNIX Timestamp for time sent "timestamp": 0, // UNIX Timestamp for time sent
"content": "<markdown (encrypted)>", "content": "<markdown (encrypted)>",
"Edited": true,
"Reactions": [
{
"Reaction": "<emoji-or-reaction-text>",
"SenderId": "<user-id>"
}
],
"files": [ "files": [
{ {
"name": "<cool name>", "name": "<cool name>",
@ -149,6 +311,8 @@ The iota will never read, or handle the chat_partner_name.
} }
``` ```
`ClientConnected` and `MessagesGet` include `Edited: true` for messages with at least one edit and a `Reactions` array. Each reaction contains `Reaction` and `SenderId` fields. Clients that do not consume these fields continue to receive the existing message fields.
### Send a message to other Iota ### Send a message to other Iota
##### `REQ:` ##### `REQ:`

View file

@ -10,6 +10,16 @@ The `Omikron` will add a `sender_id` to Messages from `Client` to the `Iota`.
The `receiver_id` and `sender_id` of the `Omikron` server are `22222222-2222-2222-2222-222222222222`. The `receiver_id` and `sender_id` of the `Omikron` server are `22222222-2222-2222-2222-222222222222`.
## Messages
### Message mutation forwarding
`Omikron` forwards `MessageEditLive`, `MessageReactionLive`, and `MessageDeleteLive` by their MTP receiver. The sender Iota persists the authenticated request before forwarding it. The recipient Iota persists the live update before Omikron sends it to the recipient client.
The request types `MessageEdit`, `MessageReactionAdd`, and `MessageReactionRemove` stay on the sender Iota. `MessageDeleteLive` is both the delete request and the live update; the authenticated connection direction distinguishes the request from a forwarded update.
> See also: `components/iota/endpoints.md` for message mutation payloads.
## Identification ## Identification
Any message to the `Omikron` will be ignored until Identification. Any message to the `Omikron` will be ignored until Identification.