From f254ac3534a190762ec583d282284c881383e6f0 Mon Sep 17 00:00:00 2001 From: Alex Emmet <111742636+Alex-Emmet@users.noreply.github.com> Date: Mon, 13 Jul 2026 14:07:56 +0200 Subject: [PATCH] edits --- src/content/docs/components/iota/endpoints.md | 164 ++++++++++++++++++ .../docs/components/omikron/endpoints.md | 10 ++ 2 files changed, 174 insertions(+) diff --git a/src/content/docs/components/iota/endpoints.md b/src/content/docs/components/iota/endpoints.md index 47d4133..1c73a53 100644 --- a/src/content/docs/components/iota/endpoints.md +++ b/src/content/docs/components/iota/endpoints.md @@ -25,6 +25,161 @@ The messaging system follows a strict derivation loop to ensure delivery and cor - **If the client doesn't answer:** 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. + +### 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": "", + "data": { + "ChatPartnerId": "", + "SendTime": "", + "Content": "" + } +} +``` + +##### `RES (S2C):` + +```json +{ + "type": "Success" +} +``` + +##### `UPDATE:` + +```json +{ + "type": "MessageEditLive", + "sender_id": "", + "receiver_id": "", + "data": { + "ChatPartnerId": "", + "SendTime": "", + "Content": "" + } +} +``` + +#### `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": "", + "data": { + "ChatPartnerId": "", + "SendTime": "", + "Reaction": "" + } +} +``` + +##### `RES (S2C):` + +```json +{ + "type": "Success" +} +``` + +#### `MessageReactionRemove` + +Removes the authenticated user's matching reaction. + +##### `REQ (C2S):` + +```json +{ + "type": "MessageReactionRemove", + "sender_id": "", + "data": { + "ChatPartnerId": "", + "SendTime": "", + "Reaction": "" + } +} +``` + +##### `RES (S2C):` + +```json +{ + "type": "Success" +} +``` + +##### `UPDATE:` + +```json +{ + "type": "MessageReactionLive", + "sender_id": "", + "receiver_id": "", + "data": { + "ChatPartnerId": "", + "SendTime": "", + "Reaction": "", + "SenderId": "", + "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": "", + "data": { + "ChatPartnerId": "", + "SendTime": "" + } +} +``` + +##### `RES (S2C):` + +```json +{ + "type": "Success" +} +``` + +##### `UPDATE:` + +```json +{ + "type": "MessageDeleteLive", + "sender_id": "", + "receiver_id": "", + "data": { + "ChatPartnerId": "", + "SendTime": "" + } +} +``` - **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. 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, "timestamp": 0, // UNIX Timestamp for time sent "content": "", + "Edited": true, + "Reactions": [ + { + "Reaction": "", + "SenderId": "" + } + ], "files": [ { "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 ##### `REQ:` diff --git a/src/content/docs/components/omikron/endpoints.md b/src/content/docs/components/omikron/endpoints.md index 30bc9b2..1334526 100644 --- a/src/content/docs/components/omikron/endpoints.md +++ b/src/content/docs/components/omikron/endpoints.md @@ -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`. +## 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 Any message to the `Omikron` will be ignored until Identification.