173 lines
4.6 KiB
Markdown
173 lines
4.6 KiB
Markdown
# Reliquary Architecture & Protocol Reference
|
|
|
|
## 1. Project Overview
|
|
**Reliquary** is a self-hosted, high-performance chat platform operating on the **Reliquary Protocol**.
|
|
* **Philosophy:** Desktop-first, native performance, decentralized identity.
|
|
* **Routing:** No server-to-server federation. The Client handles all routing.
|
|
* **Identity:** Cryptographic keypairs (secp256k1). User ID: `user@home.server`.
|
|
* **Push Notifications:** Explicitly out of scope for MVP. Desktop relies on background WebSockets; Android relies on Foreground Services.
|
|
|
|
---
|
|
|
|
## 2. Current System State
|
|
*The following features are implemented or have a fixed specification.*
|
|
|
|
### ✅ Core Features
|
|
* **Auth:** JWT-based. Register/Login returns encrypted keypair.
|
|
* **Join Flow:** Cryptographic signature verification.
|
|
* **REST API:** Basic CRUD for Channels and Text-only Messages.
|
|
* **Gateway:** WebSocket server for event fanout (Specification defined in Section 4).
|
|
|
|
### 💾 Database Models (ObjectBox)
|
|
* **User:** `userId`, `publicKey`, `passwordHash` (home only).
|
|
* **Channel:** `id`, `name`, `createdAt`.
|
|
* **Message:** `id`, `channelId`, `authorUserId`, `content`, `createdAt`.
|
|
|
|
---
|
|
|
|
## 3. Active Implementation Target: Component & File System
|
|
*⚠️ THIS SECTION DESCRIBES NEW FEATURES TO BE CODED ⚠️*
|
|
|
|
We are migrating from plain text to **Reliquary Components**. This allows rich media, embeds, and collapsible UIs.
|
|
|
|
### 3.1 UX Flow: Staged Uploads (Discord-Style)
|
|
To ensure instant UI feedback and save server bandwidth:
|
|
1. **Stage (Client):** User picks files. Client shows local previews. User reorders/adds spoilers. *No network request yet.*
|
|
2. **Commit (Client):** User hits "Send". Client adds a "Dummy Message" to the UI with a progress bar.
|
|
3. **Upload (Network):** Client POSTs files to `/api/uploads`.
|
|
4. **Publish (Network):** Client gets `FileId`s, builds the `componentsJson`, and POSTs to `/api/messages`.
|
|
5. **Resolve (Network):** Server broadcasts the new message via Gateway. Client swaps "Dummy" for "Real".
|
|
|
|
### 3.2 New/Modified Database Models
|
|
```dart
|
|
@Entity()
|
|
class Message {
|
|
// ... existing fields ...
|
|
|
|
// Search Index (Server concatenates text from all components)
|
|
String content;
|
|
|
|
// Source of Truth (JSON List<Component>)
|
|
String componentsJson;
|
|
}
|
|
|
|
@Entity()
|
|
class File {
|
|
int id;
|
|
int uploaderId;
|
|
String path; // /uploads/uuid.jpg
|
|
String mimeType;
|
|
int width; // CRITICAL for layout
|
|
int height;
|
|
int sizeBytes;
|
|
|
|
bool isAttached; // False until linked to a Message
|
|
DateTime createdAt;
|
|
}
|
|
```
|
|
|
|
### 3.3 Component JSON Schema
|
|
All items in `componentsJson` must follow this structure.
|
|
|
|
**Base Wrapper:**
|
|
```json
|
|
{
|
|
"type": "text | gallery | collapsible | embed",
|
|
"modifiers":, // "spoiler" applies blur
|
|
"fallback": "String for push notifs",
|
|
"data": { ... }
|
|
}
|
|
```
|
|
|
|
**Gallery Component (Images/Video):**
|
|
```json
|
|
{
|
|
"type": "gallery",
|
|
"modifiers": [],
|
|
"fallback": "Image",
|
|
"data": {
|
|
"items":
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 4. Gateway Protocol Specification (WebSockets)
|
|
*The server implements a WebSocket Gateway at `/gateway`.*
|
|
|
|
### Connection & Auth
|
|
* **URL:** `ws://host:port/gateway`
|
|
* **Auth:** `?token=<jwt>` (Query param) or `Authorization: Bearer <jwt>` (Header).
|
|
* **OpCode: Ready** (Server -> Client on connect):
|
|
```json
|
|
{ "op": "ready", "connectionId": "gw_1", "userId": "alice@home" }
|
|
```
|
|
|
|
### Client -> Server Ops
|
|
**Subscribe:**
|
|
```json
|
|
{ "op": "subscribe", "channelIds": [12, 13] }
|
|
```
|
|
**Unsubscribe:**
|
|
```json
|
|
{ "op": "unsubscribe", "channelIds": [12] }
|
|
```
|
|
**Heartbeat:**
|
|
```json
|
|
{ "op": "ping" }
|
|
```
|
|
|
|
### Server -> Client Ops (Events)
|
|
**Message Created:**
|
|
```json
|
|
{
|
|
"op": "event",
|
|
"event": "message.created",
|
|
"channelId": 12,
|
|
"message": {
|
|
"id": 101,
|
|
"content": "Legacy text or fallback",
|
|
"componentsJson": "[...]",
|
|
"authorId": "alice@home",
|
|
"createdAt": "..."
|
|
}
|
|
}
|
|
```
|
|
*(Also supports `message.updated` and `message.deleted`)*
|
|
|
|
---
|
|
|
|
## 5. API Reference: Pagination & Uploads
|
|
|
|
### GET /api/messages
|
|
Used for initial load and history backfilling.
|
|
* **Params:**
|
|
* `channelId` (required)
|
|
* `limit` (default 50)
|
|
* `before` (Message ID) -> Load older messages.
|
|
* `after` (Message ID) -> Load newer messages (catch-up).
|
|
|
|
* **Response:**
|
|
```json
|
|
{
|
|
"messages": [],
|
|
"hasMore": true,
|
|
"nextBefore": 51, // Cursor for older
|
|
"nextAfter": 100 // Cursor for newer
|
|
}
|
|
```
|
|
|
|
### POST /api/uploads (New)
|
|
* **Format:** `multipart/form-data`
|
|
* **Response:**
|
|
```json
|
|
{
|
|
"id": 505,
|
|
"url": "/uploads/505.png",
|
|
"width": 1920,
|
|
"height": 1080,
|
|
"mimeType": "image/png"
|
|
}
|
|
```
|