From 03b8610e04bbe95bace53cc1f43421eb550ec6b7 Mon Sep 17 00:00:00 2001 From: Alex Emmet <111742636+Alex-Emmet@users.noreply.github.com> Date: Fri, 28 Aug 2026 13:50:15 +0200 Subject: [PATCH] [Updt] Docs --- src/content/docs/components/iota/endpoints.md | 252 ++++++++++---- .../docs/components/omega/endpoints.md | 118 ++++--- src/content/docs/components/omega/https.md | 132 ++++++- .../docs/components/omikron/endpoints.md | 323 ++++++------------ 4 files changed, 474 insertions(+), 351 deletions(-) diff --git a/src/content/docs/components/iota/endpoints.md b/src/content/docs/components/iota/endpoints.md index 1c73a53..fa52166 100644 --- a/src/content/docs/components/iota/endpoints.md +++ b/src/content/docs/components/iota/endpoints.md @@ -2,33 +2,117 @@ title: Endpoints --- -All messages to the `Iota` are either from the `Omikron` directly, from a `Client` or another `Iota` trying to message a `User` on the `Iota`. -All messages will be marked with a `sender_id` this will be added on the `Omikron`. -It is important to note that the `Iota ID` is not shared with others as it is what verifies the `Iota` users to Tensamin. -In the response the `sender_id` & `receiver_id` must be swapped as sender. -When a message comes from an iota without a `sender-id` that the iota has access to or is designated for the client (`33333333-3333-3333-3333-333333333333`) the message will not be send. +All application messages arrive at the `Iota` through an authenticated MTP +connection. A sealed application operation uses the reserved `Relay` +communication type. Its outer sender is absent, and its outer receiver is +only the next-hop Iota or local client ID. + +The Iota opens and verifies Relay metadata and content. It resolves the +claimed signer ID through trusted user key history; it never treats a public +key carried by the message as authoritative. The `sender_id` fields in the +examples below describe authenticated application data inside the protected +Relay, not an outer MTP sender added by Omikron. + +The Iota ID is used by the MTP routing layer and is not an application signer +identity. Omikron does not rewrite a Relay's sender, emit `MessageOtherIota`, +or inspect the protected operation to choose a route. + +## MTP Relay API + +The Relay API uses the MTP `0.3.0` implementation and protocol version `3.0`. +MTP sends the frame as binary data; the shapes below describe its logical +fields for application integration. + +### `Relay` frame + +```text +CommunicationValue { + id: optional u32, + type: Relay, + sender: absent, + receiver: next-hop u64, + payload: encrypted relay metadata, +} +``` + +The clear `receiver` is the only routing identity. The payload is sealed from +Omikron and Omega. The `id` is an MTP correlation value and is not the +authenticated application message identity. + +After the metadata recipient opens the payload, the authenticated metadata +contains: + +```text +RelayVersion: unsigned integer +MessageId: string +FinalRecipientId: unsigned integer +CreatedAt: Unix epoch milliseconds +Content: encrypted signed application content +Metadata: optional application metadata +``` + +The signed content contains `MessageType` and the application `Content` value. +The content recipient set is separate from the metadata recipient set. Include +the destination Iota in the content recipient set when that Iota must apply +the operation; metadata-only participants forward the sealed content. + +### Relay verification + +The receiving Iota performs these checks before dispatching application data: + +1. The outer receiver is the local Iota ID. +2. The outer sender is absent. +3. The claimed signer ID is read from decrypted metadata but remains untrusted. +4. Trusted signing-key history is resolved from local user state or the + authenticated Omega control plane. +5. The metadata signature and final recipient are verified with those keys. +6. `(signer_id, MessageId)` is inserted into durable replay storage before an + application side effect. +7. The content signature is checked against the same trusted signer keys. + +An application `SenderId` field is checked against the authenticated signer; +it is not a substitute for Relay signature verification. `CreatedAt` can be +used for retention, but it is not part of the replay identity. + +### Relay routing + +The outer receiver changes when the Relay crosses a routing boundary. The +sealed payload and absent outer sender remain unchanged. + +| Stage | Outer receiver | Operation | +| --- | --- | --- | +| Client to origin Iota | Origin Iota ID | Verify the local user's Relay and resolve the final recipient's hosting Iota. | +| Origin Iota to remote Iota | Destination Iota ID | Call `forward_relay_frame()` and send the unchanged sealed Relay through Omikron. | +| Destination Iota to client | Final user ID | Verify and apply content, then forward the original Relay to the local client. | + +The Iota never creates `MessageOtherIota`, reconstructs `SetChatSecret`, or +adds the authenticated signer as an outer MTP sender. Failed delivery stores +the encoded sealed Relay for retry. ## Messages ### Messaging Lifecycle -The messaging system follows a strict derivation loop to ensure delivery and correct state synchronization: +The messaging system persists and verifies each protected operation before it +is delivered or forwarded: -1. The client sends a `message_send` to its Iota. -2. The Iota sends a response `message_send` as confirmation back to the client. -3. The Iota sends a `message_other_iota` to the chat partner's Iota. - - **If it times out:** - - The initial Iota sends a `message_state` to the client with the state `"sending"`. - - **If successful:** - - The other Iota receives the `message_other_iota` and handles it. - - The other Iota informs its client with a `message_live`. - - **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. +1. The client sends a sealed `Relay` containing the application operation to + its associated Iota. +2. The Iota verifies the protected signer, final recipient, message ID, and + application content before applying the operation. +3. When another Iota must receive the operation, the Iota persists any + required delivery state and forwards the same sealed `Relay` through + Omikron. The outer receiver changes only when the next hop changes. +4. The recipient Iota verifies the Relay again, stores the operation, and + sends the resulting application update to its local 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. +`Iota` stores each mutation on the sender and recipient replicas. `Content` +remains encrypted chat content. The sender is the authenticated signer from +the protected Relay and must own the original message for edits and deletion. +The request and update examples in this section show protected application +content, not the outer MTP `CommunicationValue`. #### `MessageEdit` @@ -75,6 +159,10 @@ Changes an existing message. `ChatPartnerId` and `SendTime` identify the message Adds one reaction for the authenticated user. Repeating the same request does not create a duplicate row. +Iota stores at most ten distinct reaction strings per message. A user may use +an existing reaction string after the limit is reached. A new string at the +limit returns `ErrorInvalidData` and produces no live update. + ##### `REQ (C2S):` ```json @@ -142,6 +230,27 @@ Removes the authenticated user's matching reaction. `Accepted` is `true` for an add and `false` for a removal. +#### `MessageGet` + +Fetches one visible message by `SendTime`. Include `ChatPartnerId` when the +request is a reply lookup. The successful response then includes `Offset`, +the message's absolute position in the same descending history order used by +`MessagesGet`. + +```json +{ + "type": "MessageGet", + "data": { + "ChatPartnerId": "", + "SendTime": "" + } +} +``` + +Use the returned `Offset` as the starting position for a page that contains +the target. Requests without `ChatPartnerId` remain accepted for compatibility +but do not include an offset. + #### `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. @@ -185,8 +294,10 @@ Deletes a message from both replicas. The existing `MessageDeleteLive` MTP type 2. The initial Iota will store the state and forward the `message_state` to its client. ### Client adds someone to their contacts -When adding via name, the omikron will intercept and fill the chat_partner_id. -The iota will never read, or handle the chat_partner_name. + +Resolve a contact name through the control plane before creating the protected +`AddConversation` operation. Omikron does not inspect or mutate this +operation. The JSON below represents the protected application content. ##### `REQ:` @@ -197,7 +308,7 @@ The iota will never read, or handle the chat_partner_name. "type": "add_conversation", "id": "", - + "data": { "chat_partner_id": id, "chat_partner_name": "name" @@ -220,41 +331,33 @@ The iota will never read, or handle the chat_partner_name. ### Client messages someone -##### `REQ:` +The following object is the protected application content passed to the MTP +Relay builder. It is not the outer frame and its `SenderId`, when present, is +checked against the authenticated Relay signer. + +##### `CONTENT:` ```json { - "sender_id": "", - "receiver_id": "", - - "type": "message_send", - "id": "", - "data": { - "receiver_id": "", - "content": "", - "files": [ + "MessageType": "MessageSend", + "Content": { + "ReceiverId": "", + "Content": "", + "Files": [ { - "name": "", - "id": "", - "type": "[ image | image_top_right | file ]" + "Name": "", + "Id": "", + "Type": "[ image | image_top_right | file ]" } ] } } ``` -##### `RES:` - -```json -{ - "sender_id": "", - "receiver_id": "", - - "type": "message_send", - "id": "", - "data": {} -} -``` +The Relay metadata carries the authenticated `MessageId` and +`FinalRecipientId`. It also carries `CreatedAt` as Unix epoch milliseconds. +The application does not put the signer identity in the outer MTP sender +field. ### Client loads messages @@ -313,49 +416,50 @@ 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 +### Route a message to another Iota -##### `REQ:` +The client sends the same `Relay` frame to its origin Iota regardless of the +final recipient's hosting Iota. -```json -{ - "type": "message_send", - "id": "", - "data": { - "receiver_id": "99999999-8888-7777-6666-555555555555", - "content": "Hello, how are you?" - } +```text +Relay { + id: , + sender: absent, + receiver: , + payload: , } ``` -##### `RES:` +The origin Iota resolves the final recipient through the authenticated control +plane and forwards the original sealed frame with `receiver` set to the +destination Iota. It does not create a second application message. -```json -{ - "type": "message", - "id": "", - "receiver": "" +```text +Relay { + id: , + sender: absent, + receiver: , + payload: , } ``` -### Receive live message (`message_other_iota`) +### Receive a live message from a sealed Relay ##### `UPDATE:` -```json -{ - "type": "message_live", - "id": "", - "receiver": "", - - "data": { - "send_time": unixstamp, - "message": "", - "sender_id": "99999999-8888-7777-6666-555555555555" - } +```text +Relay { + id: , + sender: absent, + receiver: , + payload: , } ``` +The destination Iota applies the authenticated operation before forwarding +the frame to the local client. The client receives the application update +through its authenticated MTP connection. + ## Communities ### Client storing a community on their Iota diff --git a/src/content/docs/components/omega/endpoints.md b/src/content/docs/components/omega/endpoints.md index b138897..19a6bf3 100644 --- a/src/content/docs/components/omega/endpoints.md +++ b/src/content/docs/components/omega/endpoints.md @@ -1,73 +1,93 @@ --- -title: WSS Endpoints +title: MTP Endpoints +lastUpdated: 2026-08-14 --- -The `Omega` can be reached by HTTPS request from `Client` and `Iota`. -`Omikron` servers establish a Secure Websocket when booting. +`Omega` serves HTTPS API routes and authenticated MTP WebTransport sessions. +`Omikron` connects through the MTP WebTransport endpoint. The Omega service +uses MTP protocol version `0.3.0` and requires transport authentication before +dispatching application frames. -This documentation is split into `Omikron` (WSS) and `HTTPS`. +This document covers the MTP connection between `Omikron` and `Omega` and the +control messages handled after authentication. HTTP routes are documented in +[`https.md`](./https.md). -## Omikron +## MTP Omikron Connection -### Identification +### Authentication -Any message to the `Omega` will be ignored until Identification. +The MTP opening exchange negotiates protocol version `3.0` and completes the +configured cryptographic login or registration flow. Omega uses +`ForceAuthentication`, so an unauthenticated WebTransport session does not +reach the application dispatcher. The authenticated MTP client ID identifies +the `Omikron` connection. -##### `REQ:` +The MTP `Identification`, `Register`, challenge, and signed proof frames are +transport messages. They are not application-level JSON endpoints. After the +handshake, Omega validates the authenticated `Omikron` capability description +before accepting control messages or Relay frames. + +### Relay Routing + +`Relay` is the reserved MTP communication type for opaque routing between +`Omikron` instances. The logical shape below describes the MTP frame; MTP sends +the frame as binary data, not as JSON. + +#### `Relay` + +The outer `receiver` is the destination `Iota` next hop. The outer `sender` +field must be absent. The payload contains the sealed Relay metadata and +content and is not opened by Omega. + +##### `REQ (Omikron → Omega):` ```json { - "type": "identification", - "data": { - "omikron": "", - } + "type": "Relay", + "id": "", + "receiver": "", + "payload": "" } ``` -##### `REQ & RES:` +##### `FORWARD:` + +Omega resolves the destination `Iota` through its primary `Omikron` route and +sends the Relay to that one authenticated connection. The outer receiver and +sealed payload remain unchanged. Omega does not decrypt Relay metadata or +content, resolve the original signer, rewrite the sender, or interpret the +inner application type. + +Relay route failures are infrastructure failures. Omega rejects a frame with +an outer sender, a missing destination `Iota`, an unavailable primary route, +an unavailable target connection, or a route that points back to the source +`Omikron`. Omega does not turn these failures into user-authored Relay content. + +### Control Messages + +Control messages use the negotiated MTP type map after the authenticated +connection is established. + +#### `PushNotification` + +Sends a notification to a user. The receiver ID can be specified in the MTP +frame's `receiver` field or in the data payload. + +##### `REQ (Omikron → Omega):` ```json { - "type": "challenge", - "data": { - "public_key": "", - "challenge": "" - } + "type": "PushNotification", + "receiver_id": "?", + "sender_id": "" } ``` -##### `REQ & RES:` + +##### `RES (Omega → Omikron):` ```json { - "type": "challenge_response", - "data": { - "challenge": "", - } -} -``` -##### `RES:` - -```json -{ - "type": "identification_response", - "data": { - "accepted": boolean, - } -} -``` - -### Push Notification - -Sends a push notification to a user. The receiver ID can be specified either in the `receiver` field of the message or in the data payload. - -##### `REQ:` - -```json -{ - "type": "push_notification", - "data": { - "receiver_id": "", // Optional, if not in receiver field - "sender_id": "" - } + "type": "PushNotification", + "id": "" } ``` diff --git a/src/content/docs/components/omega/https.md b/src/content/docs/components/omega/https.md index e3020eb..3590a22 100644 --- a/src/content/docs/components/omega/https.md +++ b/src/content/docs/components/omega/https.md @@ -1,22 +1,126 @@ --- title: HTTPS Endpoints +lastUpdated: 2026-08-14 --- -#### GET `/api/get/omikron/` -Get an Omikron to connect to. -#### GET `/api/get/omikron/` -Get an Omikron to connect to, when needing a certain omikron. -#### GET `/api/get/omikron/` -Get an Omikron to connect to, when needing the Omikron a certain User / a certains user's Iota is connected to. -#### GET `/api/get/omikron/` -Get an Omikron to connect to, when needing the Omikron a certain Iota is connected to. +`Omega` exposes discovery and profile data over HTTPS. All identifiers in the +routes below are positive decimal integers. + +#### GET `/api/get/omikron` + +Returns a randomly selected connected `Omikron`. + +##### `RES:` ```json { - "type": "omikron", - "data": { - "omikron_id": id, - "domain": "omikron.tensamin.net" - } + "status": "success", + "id": "", + "public_key": "", + "ip_address": "", + "port": "" } -``` \ No newline at end of file +``` + +#### GET `/api/get/omikron/` + +Returns a connected `Omikron` by ID. If `` identifies a connected `Iota` +or a user with an assigned `Iota`, the response identifies that account's +primary connected `Omikron`. + +##### `RES:` + +```json +{ + "status": "success", + "id": "", + "public_key": "", + "ip_address": "", + "port": "" +} +``` + +#### GET `/api/get/connections` + +Returns the live in-memory map of `Omikron` IDs to their connected `Iota` IDs +and hosted user IDs. The map is empty after an Omega restart until connected +`Omikron` instances publish their state. + +##### `RES:` + +```json +{ + "status": "success", + "": { + "": ["", "..."] + } +} +``` + +#### GET `/api/get/iota/` + +Returns the public identity data for an `Iota`. + +##### `RES:` + +```json +{ + "status": "success", + "iota_id": "", + "public_key": "" +} +``` + +#### GET `/api/get/user/` + +Returns a user's profile and assigned `Iota` ID. + +##### `RES:` + +```json +{ + "status": "success", + "username": "", + "public_key": "", + "user_id": "", + "iota_id": "?", + "sub_level": "", + "sub_end": "", + "display": "?", + "status_message": "?", + "about": "?", + "avatar": "?" +} +``` + +#### GET `/api/get/id/` + +Resolves a username to its public profile and identity IDs. The username is +limited to 15 characters after URL decoding. + +##### `RES:` + +```json +{ + "status": "success", + "username": "", + "public_key": "", + "user_id": "", + "iota_id": "?", + "sub_level": "", + "sub_end": "" +} +``` + +#### GET `/api/get/public_key` + +Returns Omega's public MTP key bundle in base64 form. + +##### `RES:` + +```json +{ + "status": "success", + "public_key": "" +} +``` diff --git a/src/content/docs/components/omikron/endpoints.md b/src/content/docs/components/omikron/endpoints.md index 1334526..761b5cf 100644 --- a/src/content/docs/components/omikron/endpoints.md +++ b/src/content/docs/components/omikron/endpoints.md @@ -1,252 +1,147 @@ --- title: Endpoints +lastUpdated: 2026-08-14 --- -To use the `Omikrons` functions a Secure Websocket connection must be established. -Where to connect is provided by the `Omega` Server. -All entries are split into `Iota` & `Client`. -As the `Omikron` connects the `Iota` and `Client` by passing messages from one to the other all Communication from `Iota` to `Client` has to contain a `receiver_id` -The `Omikron` will add a `sender_id` to Messages from `Client` to the `Iota`. +Omikron exposes an MTP WebTransport endpoint through its HTTPS listener. It +does not expose the previous JSON-over-WebSocket challenge protocol. Native +and browser clients use the MTP client APIs described in the repository's +`mtp-docs` guides. -The `receiver_id` and `sender_id` of the `Omikron` server are `22222222-2222-2222-2222-222222222222`. +Omikron and its peers use the MTP `0.3.0` implementation and the wire protocol +version `3.0`. The MTP opening exchange negotiates the version and completes +transport authentication before Omikron dispatches application frames. -## Messages +## Connection identities -### Message mutation forwarding +The MTP connection description selects the Omikron connection class: -`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. +| Description | Authentication | Connection | Relay access | +| --- | --- | --- | --- | +| `client` | Registered MTP authentication | User client | Yes | +| `iota` | Registered MTP authentication | Iota node | Yes | +| `anonymous` | Unauthenticated | Temporary anonymous client | No | -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. +The `client` ID is the authenticated user ID. The `iota` ID is the +authenticated Iota ID. A connection with an unknown description is rejected by +the application dispatcher. MTP challenge and proof frames are transport +messages, not application endpoints. -> See also: `components/iota/endpoints.md` for message mutation payloads. +## MTP frame shape -## Identification +MTP sends binary `CommunicationValue` frames. The following is a logical shape +for documentation; it is not a JSON wire format. -Any message to the `Omikron` will be ignored until Identification. - -### Iota - -##### `REQ:` - -```json -{ - "type": "identification", - "data": { - "iota_id": "", - } +```text +CommunicationValue { + id: optional u32, + type: CommunicationType, + sender: optional u64, + receiver: optional u64, + payload: DataValue, } ``` -##### `REQ & RES:` +`Relay` is the reserved opaque communication type. A Relay has no outer +`sender`, its outer `receiver` is the next-hop ID, and its payload contains +protected relay metadata and content. Omikron reads only the clear routing +fields. It never opens relay metadata or content, resolves the original +signer, or changes the sealed payload. -```json -{ - "type": "challenge", - "data": { - "public_key": "", - "challenge": "" - } -} -``` -##### `REQ & RES:` +Tensamin user IDs and Iota IDs currently share the same numeric range. An +Iota-origin Relay whose receiver matches both a local Client identity and a +local Iota identity is rejected as ambiguous; Omikron never chooses a route +from a colliding numeric ID. -```json -{ - "type": "challenge_response", - "data": { - "challenge": "", - } -} -``` -##### `RES:` +## Relay -```json -{ - "type": "identification_response", - "data": { - "accepted": boolean, - } +### Client to Iota + +A registered Client may send a Relay only to the Iota currently associated +with that Client. + +```text +Relay { + id: request or correlation ID, + sender: absent, + receiver: associated Iota ID, + payload: opaque sealed relay, } ``` ---- +Omikron validates the Relay layout with MTP's `forward_relay_frame` and sends +the unchanged frame to the local Iota connection. A Client cannot address an +arbitrary Iota or Omikron through this path. -### Client +### Iota routing -This is a two step process. +An Iota may send a Relay to a locally connected Client, another locally +connected Iota, or Omega. Omikron chooses the destination from the clear outer +receiver and the authenticated connection that supplied the frame. -Get a challenge: +| Source connection | Destination | Omikron action | +| --- | --- | --- | +| Client | Its associated Iota | Send to that local Iota | +| Iota | Local Client | Send to matching client sessions | +| Iota | Local Iota | Send to that Iota | +| Iota | Remote Iota | Send to Omega | +| Omega | Local Iota | Send to that Iota | +| Anonymous client | Any destination | Reject | -#### `REQ:` +Omega sends a Relay to one destination Omikron. Omikron accepts it only when +the destination Iota is connected locally. It never sends an unavailable +Omega Relay back to Omega or broadcasts it to other Omikrons. -```json -{ - "id": "", - "type": "identification", - "data": { - "user_id": "" - } -} -``` +### Validation and errors -#### `RES:` +Omikron rejects a Relay when: -```json -{ - "id": "", - "type": "challenge", - "data": { - "challenge": "", - "public_key": "" - } -} -``` +- the communication type is not the reserved `Relay` type; +- an outer sender is present; +- the next-hop receiver is missing; +- a Client addresses an Iota other than its associated Iota; +- an Iota routes to itself; +- the destination Iota or Client is unavailable; or +- the frame cannot be sent on the selected connection. -Send back the solved challenge: +Routing failures are ordinary service error frames sent to the authenticated +source connection. The failure frame is not a Relay and does not claim to be +from the original user. Unknown non-Relay application messages are rejected; +Omikron does not use generic fallthrough forwarding. -#### `REQ:` +## Application messages -```json -{ - "id": "", - "type": "challenge_response", - "data": { - "challenge": "" - } -} -``` +Direct control messages remain available after MTP authentication. Examples +include `GetUserData`, `GetIotaData`, `ChangeUserData`, `ClientChanged`, and +registration control messages. These messages use the negotiated MTP type map +and may use the existing control-plane sender semantics. -#### `RES:` +`MessageGet`, `MessagesGet`, and `GetChatSecret` are authenticated peer-control +messages. A Client sends them to its associated Iota through Omikron. Omikron +adds the authenticated client ID as the outer sender for the Iota request, +waits for the correlated response, and returns that response to the Client. +It does not read or store message contents. -```json -{ - "id": "", - "type": "identification_response", - "data": {} -} -``` +Those semantics do not apply to `Relay`. Omikron never adds a user or Iota ID +to a Relay and never uses the outer sender as the original message identity. -## Ping & Pong +Message delivery, edits, reactions, deletion, chat secrets, and other +application operations travel inside the sealed Relay. The recipient Iota +opens and verifies the Relay, checks the original signer against its trusted +public-key history, applies the operation, and persists or forwards the sealed +Relay when required. -A ping request comes from the Client or Iota and the Omikron returns a pong answer. -The ping request should contain the last Client or Iota ping and the pong answer will contain the last ping of the Omikron.**** +## Keepalive -### Iota +MTP handles protocol Ping and Pong frames through the connection dispatcher. +Application handlers must not treat keepalive frames as Relay traffic. See the +repository's `mtp-docs/CONNECTIONS.md` and `mtp-docs/PROTOCOL-REFERENCE.md` +files. -#### REQ: +## Related API documentation -```json -{ - "id": "", - "type": "ping", - "data": { - "last_ping": long - } -} -``` - -#### RES: - -```json -{ - "id": "", - "type": "pong", - "data": { - "user_ping": { - "": long, - "": long - } - } -} -``` - -### Client - -#### `REQ:` - -```json -{ - "id": "", - "type": "ping", - "data": { - "last_ping": long - } -} -``` - -#### `RES:` - -```json -{ - "id": "", - "type": "pong", - "data": { - "last_ping": long - } -} -``` - -## User Online Status - -### Set Client Status - -The client can change their online status by sending a `client_changed` message. -Supported status values: `user_online`, `user_offline`, `user_dnd`, `user_idle`, `user_wc`, `user_invisible`. - -When `user_invisible` is set, the user remains connected and can send/receive messages, but appears as `user_offline` to all other users. - -#### `REQ` (Client → Omikron): - -```json -{ - "id": "", - "type": "client_changed", - "data": { - "user_state": "" - } -} -``` - -### Online Status Notifications - -When a connected user changes their status, interested clients receive a notification: - -#### `EVENT` (Omikron → Client): - -```json -{ - "type": "client_changed", - "data": { - "user_id": "", - "user_state": "" - } -} -``` - -### Online Status in User Data - -When fetching another user's profile via `get_user_data`, their online status is included in the response. Invisible users are reported as `user_offline`. - -#### `RES` (Omikron → Client, field in `get_user_data`): - -```json -{ - "id": "", - "type": "get_user_data", - "data": { - "user_id": long, - "username": "", - "display": "", - "public_key": "", - "iota_id": long, - "online_status": "", - "omikron_id": long, - "omikron_connections": [long, ...], - "sub_level": long, - "sub_end": long, - "about": "?", - "avatar": "?", - "status": "?" - } -} -``` +- [Calling](./calling) +- [User management](./user-management) +- `mtp-docs/CONNECTOR.md` +- `mtp-docs/NATIVE-CLIENT.md` +- `mtp-docs/NATIVE-HOST-WEB-SERVER.md`