[Updt] Docs
This commit is contained in:
parent
f254ac3534
commit
03b8610e04
4 changed files with 487 additions and 364 deletions
|
|
@ -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": "<chat-partner-id>",
|
||||
"SendTime": "<message-unix-milliseconds>"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
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": "<uuid>",
|
||||
|
||||
|
||||
"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": "<user-id>",
|
||||
"receiver_id": "<user-id>",
|
||||
|
||||
"type": "message_send",
|
||||
"id": "<uuid>",
|
||||
"data": {
|
||||
"receiver_id": "<uuid>",
|
||||
"content": "<markdown (encrypted)>",
|
||||
"files": [
|
||||
"MessageType": "MessageSend",
|
||||
"Content": {
|
||||
"ReceiverId": "<user-id>",
|
||||
"Content": "<markdown (encrypted)>",
|
||||
"Files": [
|
||||
{
|
||||
"name": "<cool name>",
|
||||
"id": "<uuid>",
|
||||
"type": "[ image | image_top_right | file ]"
|
||||
"Name": "<file-name>",
|
||||
"Id": "<uuid>",
|
||||
"Type": "[ image | image_top_right | file ]"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
##### `RES:`
|
||||
|
||||
```json
|
||||
{
|
||||
"sender_id": "<user-id>",
|
||||
"receiver_id": "<user-id>",
|
||||
|
||||
"type": "message_send",
|
||||
"id": "<uuid>",
|
||||
"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": "<message_id>",
|
||||
"data": {
|
||||
"receiver_id": "99999999-8888-7777-6666-555555555555",
|
||||
"content": "Hello, how are you?"
|
||||
}
|
||||
```text
|
||||
Relay {
|
||||
id: <optional-mtp-frame-id>,
|
||||
sender: absent,
|
||||
receiver: <origin-iota-id>,
|
||||
payload: <sealed MessageSend operation>,
|
||||
}
|
||||
```
|
||||
|
||||
##### `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": "<message_id>",
|
||||
"receiver": "<user_id>"
|
||||
```text
|
||||
Relay {
|
||||
id: <same-mtp-frame-id>,
|
||||
sender: absent,
|
||||
receiver: <destination-iota-id>,
|
||||
payload: <same sealed MessageSend operation>,
|
||||
}
|
||||
```
|
||||
|
||||
### Receive live message (`message_other_iota`)
|
||||
### Receive a live message from a sealed Relay
|
||||
|
||||
##### `UPDATE:`
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "message_live",
|
||||
"id": "<message_id>",
|
||||
"receiver": "<user_id>",
|
||||
|
||||
"data": {
|
||||
"send_time": unixstamp,
|
||||
"message": "<content>",
|
||||
"sender_id": "99999999-8888-7777-6666-555555555555"
|
||||
}
|
||||
```text
|
||||
Relay {
|
||||
id: <same-mtp-frame-id>,
|
||||
sender: absent,
|
||||
receiver: <final-user-id>,
|
||||
payload: <same sealed MessageSend operation>,
|
||||
}
|
||||
```
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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": "<omikron-id>",
|
||||
}
|
||||
"type": "Relay",
|
||||
"id": "<frame-id>",
|
||||
"receiver": "<iota-id>",
|
||||
"payload": "<opaque sealed relay 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": "<omegas public key>",
|
||||
"challenge": "<random encrypted b64 string>"
|
||||
}
|
||||
"type": "PushNotification",
|
||||
"receiver_id": "<user-id>?",
|
||||
"sender_id": "<user-id>"
|
||||
}
|
||||
```
|
||||
##### `REQ & RES:`
|
||||
|
||||
##### `RES (Omega → Omikron):`
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "challenge_response",
|
||||
"data": {
|
||||
"challenge": "<decrypted b64 string>",
|
||||
}
|
||||
}
|
||||
```
|
||||
##### `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": "<user-id>", // Optional, if not in receiver field
|
||||
"sender_id": "<user-id>"
|
||||
}
|
||||
"type": "PushNotification",
|
||||
"id": "<frame-id>"
|
||||
}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -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/<omikron-id>`
|
||||
Get an Omikron to connect to, when needing a certain omikron.
|
||||
|
||||
#### GET `/api/get/omikron/<user-id>`
|
||||
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/<iota-id>`
|
||||
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": "<omikron-id>",
|
||||
"public_key": "<base64>",
|
||||
"ip_address": "<ip-address>",
|
||||
"port": "<port>"
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
#### GET `/api/get/omikron/<id>`
|
||||
|
||||
Returns a connected `Omikron` by ID. If `<id>` 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": "<omikron-id>",
|
||||
"public_key": "<base64>",
|
||||
"ip_address": "<ip-address>",
|
||||
"port": "<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",
|
||||
"<omikron-id>": {
|
||||
"<iota-id>": ["<user-id>", "..."]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### GET `/api/get/iota/<id>`
|
||||
|
||||
Returns the public identity data for an `Iota`.
|
||||
|
||||
##### `RES:`
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"iota_id": "<iota-id>",
|
||||
"public_key": "<base64>"
|
||||
}
|
||||
```
|
||||
|
||||
#### GET `/api/get/user/<id>`
|
||||
|
||||
Returns a user's profile and assigned `Iota` ID.
|
||||
|
||||
##### `RES:`
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"username": "<username>",
|
||||
"public_key": "<base64>",
|
||||
"user_id": "<user-id>",
|
||||
"iota_id": "<iota-id>?",
|
||||
"sub_level": "<integer>",
|
||||
"sub_end": "<unix-milliseconds>",
|
||||
"display": "<string>?",
|
||||
"status_message": "<string>?",
|
||||
"about": "<string>?",
|
||||
"avatar": "<base64>?"
|
||||
}
|
||||
```
|
||||
|
||||
#### GET `/api/get/id/<username>`
|
||||
|
||||
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": "<username>",
|
||||
"public_key": "<base64>",
|
||||
"user_id": "<user-id>",
|
||||
"iota_id": "<iota-id>?",
|
||||
"sub_level": "<integer>",
|
||||
"sub_end": "<unix-milliseconds>"
|
||||
}
|
||||
```
|
||||
|
||||
#### GET `/api/get/public_key`
|
||||
|
||||
Returns Omega's public MTP key bundle in base64 form.
|
||||
|
||||
##### `RES:`
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"public_key": "<base64>"
|
||||
}
|
||||
```
|
||||
|
|
|
|||
|
|
@ -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": "<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": "<omikrons public key>",
|
||||
"challenge": "<random encrypted b64 string>"
|
||||
}
|
||||
}
|
||||
```
|
||||
##### `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": "<decrypted b64 string>",
|
||||
}
|
||||
}
|
||||
```
|
||||
##### `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": "<uuid>",
|
||||
"type": "identification",
|
||||
"data": {
|
||||
"user_id": "<user-id>"
|
||||
}
|
||||
}
|
||||
```
|
||||
### Validation and errors
|
||||
|
||||
#### `RES:`
|
||||
Omikron rejects a Relay when:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "<uuid>",
|
||||
"type": "challenge",
|
||||
"data": {
|
||||
"challenge": "<base64 string>",
|
||||
"public_key": "<base64 string>"
|
||||
}
|
||||
}
|
||||
```
|
||||
- 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": "<uuid>",
|
||||
"type": "challenge_response",
|
||||
"data": {
|
||||
"challenge": "<decrypted 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": "<uuid>",
|
||||
"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": "<uuid>",
|
||||
"type": "ping",
|
||||
"data": {
|
||||
"last_ping": long
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### RES:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "<uuid>",
|
||||
"type": "pong",
|
||||
"data": {
|
||||
"user_ping": {
|
||||
"<user-id>": long,
|
||||
"<user-id>": long
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Client
|
||||
|
||||
#### `REQ:`
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "<uuid>",
|
||||
"type": "ping",
|
||||
"data": {
|
||||
"last_ping": long
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### `RES:`
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "<uuid>",
|
||||
"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": "<uuid>",
|
||||
"type": "client_changed",
|
||||
"data": {
|
||||
"user_state": "<status>"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 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-id>",
|
||||
"user_state": "<status>"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 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": "<uuid>",
|
||||
"type": "get_user_data",
|
||||
"data": {
|
||||
"user_id": long,
|
||||
"username": "<string>",
|
||||
"display": "<string>",
|
||||
"public_key": "<base64>",
|
||||
"iota_id": long,
|
||||
"online_status": "<status>",
|
||||
"omikron_id": long,
|
||||
"omikron_connections": [long, ...],
|
||||
"sub_level": long,
|
||||
"sub_end": long,
|
||||
"about": "<string>?",
|
||||
"avatar": "<base64>?",
|
||||
"status": "<string>?"
|
||||
}
|
||||
}
|
||||
```
|
||||
- [Calling](./calling)
|
||||
- [User management](./user-management)
|
||||
- `mtp-docs/CONNECTOR.md`
|
||||
- `mtp-docs/NATIVE-CLIENT.md`
|
||||
- `mtp-docs/NATIVE-HOST-WEB-SERVER.md`
|
||||
|
|
|
|||
Loading…
Reference in a new issue