@xtr-dev/rondevu-server 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ADVANCED.md +502 -0
- package/README.md +136 -282
- package/dist/index.js +692 -731
- package/dist/index.js.map +4 -4
- package/migrations/0006_service_offer_refactor.sql +40 -0
- package/migrations/0007_simplify_schema.sql +54 -0
- package/migrations/0008_peer_id_to_username.sql +67 -0
- package/migrations/fresh_schema.sql +81 -0
- package/package.json +2 -1
- package/src/app.ts +38 -591
- package/src/config.ts +0 -13
- package/src/crypto.ts +98 -133
- package/src/rpc.ts +725 -0
- package/src/storage/d1.ts +169 -182
- package/src/storage/sqlite.ts +142 -168
- package/src/storage/types.ts +51 -95
- package/src/worker.ts +0 -6
- package/wrangler.toml +3 -3
- package/src/middleware/auth.ts +0 -51
package/README.md
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/@xtr-dev/rondevu-server)
|
|
4
4
|
|
|
5
|
-
🌐 **
|
|
5
|
+
🌐 **Simple WebRTC signaling with RPC interface**
|
|
6
6
|
|
|
7
|
-
Scalable WebRTC signaling server with cryptographic username claiming, service publishing, and
|
|
7
|
+
Scalable WebRTC signaling server with cryptographic username claiming, service publishing with semantic versioning, and efficient offer/answer exchange via JSON-RPC interface.
|
|
8
8
|
|
|
9
9
|
**Related repositories:**
|
|
10
10
|
- [@xtr-dev/rondevu-client](https://github.com/xtr-dev/rondevu-client) - TypeScript client library ([npm](https://www.npmjs.com/package/@xtr-dev/rondevu-client))
|
|
@@ -15,12 +15,14 @@ Scalable WebRTC signaling server with cryptographic username claiming, service p
|
|
|
15
15
|
|
|
16
16
|
## Features
|
|
17
17
|
|
|
18
|
+
- **RPC Interface**: Single endpoint for all operations with batching support
|
|
18
19
|
- **Username Claiming**: Cryptographic username ownership with Ed25519 signatures (365-day validity, auto-renewed on use)
|
|
19
|
-
- **Service Publishing**:
|
|
20
|
-
- **
|
|
21
|
-
- **
|
|
22
|
-
- **
|
|
20
|
+
- **Service Publishing**: Service:version@username naming (e.g., `chat:1.0.0@alice`)
|
|
21
|
+
- **Service Discovery**: Random and paginated discovery for finding services without knowing usernames
|
|
22
|
+
- **Semantic Versioning**: Compatible version matching (chat:1.0.0 matches any 1.x.x)
|
|
23
|
+
- **Signature-Based Authentication**: All authenticated requests use Ed25519 signatures
|
|
23
24
|
- **Complete WebRTC Signaling**: Offer/answer exchange and ICE candidate relay
|
|
25
|
+
- **Batch Operations**: Execute multiple operations in a single HTTP request
|
|
24
26
|
- **Dual Storage**: SQLite (Node.js/Docker) and Cloudflare D1 (Workers) backends
|
|
25
27
|
|
|
26
28
|
## Architecture
|
|
@@ -30,11 +32,13 @@ Username Claiming → Service Publishing → Service Discovery → WebRTC Connec
|
|
|
30
32
|
|
|
31
33
|
alice claims "alice" with Ed25519 signature
|
|
32
34
|
↓
|
|
33
|
-
alice publishes
|
|
35
|
+
alice publishes chat:1.0.0@alice with offers
|
|
34
36
|
↓
|
|
35
|
-
bob
|
|
37
|
+
bob queries chat:1.0.0@alice (direct) or chat:1.0.0 (discovery) → gets offer SDP
|
|
36
38
|
↓
|
|
37
|
-
WebRTC connection established
|
|
39
|
+
bob posts answer SDP → WebRTC connection established
|
|
40
|
+
↓
|
|
41
|
+
ICE candidates exchanged via server relay
|
|
38
42
|
```
|
|
39
43
|
|
|
40
44
|
## Quick Start
|
|
@@ -46,7 +50,7 @@ npm install && npm start
|
|
|
46
50
|
|
|
47
51
|
**Docker:**
|
|
48
52
|
```bash
|
|
49
|
-
docker build -t rondevu . && docker run -p 3000:3000 -e STORAGE_PATH=:memory:
|
|
53
|
+
docker build -t rondevu . && docker run -p 3000:3000 -e STORAGE_PATH=:memory: rondevu
|
|
50
54
|
```
|
|
51
55
|
|
|
52
56
|
**Cloudflare Workers:**
|
|
@@ -54,351 +58,201 @@ docker build -t rondevu . && docker run -p 3000:3000 -e STORAGE_PATH=:memory: -e
|
|
|
54
58
|
npx wrangler deploy
|
|
55
59
|
```
|
|
56
60
|
|
|
57
|
-
##
|
|
58
|
-
|
|
59
|
-
### Public Endpoints
|
|
60
|
-
|
|
61
|
-
#### `GET /`
|
|
62
|
-
Returns server version and info
|
|
63
|
-
|
|
64
|
-
#### `GET /health`
|
|
65
|
-
Health check endpoint with version
|
|
61
|
+
## RPC Interface
|
|
66
62
|
|
|
67
|
-
|
|
68
|
-
Register a new peer and receive credentials (peerId + secret)
|
|
63
|
+
All API calls are made to `POST /rpc` with JSON-RPC format.
|
|
69
64
|
|
|
70
|
-
|
|
65
|
+
### Request Format
|
|
71
66
|
|
|
72
|
-
**
|
|
67
|
+
**Single method call:**
|
|
73
68
|
```json
|
|
74
69
|
{
|
|
75
|
-
"
|
|
76
|
-
"
|
|
70
|
+
"method": "getUser",
|
|
71
|
+
"message": "getUser:alice:1733404800000",
|
|
72
|
+
"signature": "base64-encoded-signature",
|
|
73
|
+
"params": {
|
|
74
|
+
"username": "alice"
|
|
75
|
+
}
|
|
77
76
|
}
|
|
78
77
|
```
|
|
79
78
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
#### `GET /users/:username`
|
|
83
|
-
Check username availability and claim status
|
|
84
|
-
|
|
85
|
-
**Response:**
|
|
79
|
+
**Batch calls:**
|
|
86
80
|
```json
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
81
|
+
[
|
|
82
|
+
{
|
|
83
|
+
"method": "getUser",
|
|
84
|
+
"message": "getUser:alice:1733404800000",
|
|
85
|
+
"signature": "base64-encoded-signature",
|
|
86
|
+
"params": { "username": "alice" }
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"method": "claimUsername",
|
|
90
|
+
"message": "claim:bob:1733404800000",
|
|
91
|
+
"signature": "base64-encoded-signature",
|
|
92
|
+
"params": {
|
|
93
|
+
"username": "bob",
|
|
94
|
+
"publicKey": "base64-encoded-public-key"
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
]
|
|
94
98
|
```
|
|
95
99
|
|
|
96
|
-
|
|
97
|
-
Claim a username with cryptographic proof
|
|
98
|
-
|
|
99
|
-
**Request:**
|
|
100
|
-
```json
|
|
101
|
-
{
|
|
102
|
-
"publicKey": "base64-encoded-ed25519-public-key",
|
|
103
|
-
"signature": "base64-encoded-signature",
|
|
104
|
-
"message": "claim:alice:1733404800000"
|
|
105
|
-
}
|
|
106
|
-
```
|
|
100
|
+
### Response Format
|
|
107
101
|
|
|
108
|
-
**
|
|
102
|
+
**Single response:**
|
|
109
103
|
```json
|
|
110
104
|
{
|
|
111
|
-
"
|
|
112
|
-
"
|
|
113
|
-
"expiresAt": 1765027200000
|
|
105
|
+
"success": true,
|
|
106
|
+
"result": { /* method-specific data */ }
|
|
114
107
|
}
|
|
115
108
|
```
|
|
116
109
|
|
|
117
|
-
**
|
|
118
|
-
- Username format: `^[a-z0-9][a-z0-9-]*[a-z0-9]$` (3-32 characters)
|
|
119
|
-
- Signature must be valid Ed25519 signature
|
|
120
|
-
- Timestamp must be within 5 minutes (replay protection)
|
|
121
|
-
- Expires after 365 days, auto-renewed on use
|
|
122
|
-
|
|
123
|
-
#### `GET /users/:username/services/:fqn`
|
|
124
|
-
Get service by username and FQN with semver-compatible matching
|
|
125
|
-
|
|
126
|
-
**Semver Matching:**
|
|
127
|
-
- Requesting `chat@1.0.0` matches any `1.x.x` version
|
|
128
|
-
- Major version must match exactly (`chat@1.0.0` will NOT match `chat@2.0.0`)
|
|
129
|
-
- For major version 0, minor must also match (`0.1.0` will NOT match `0.2.0`)
|
|
130
|
-
- Returns the most recently published compatible version
|
|
131
|
-
|
|
132
|
-
**Response:**
|
|
110
|
+
**Error response:**
|
|
133
111
|
```json
|
|
134
112
|
{
|
|
135
|
-
"
|
|
136
|
-
"
|
|
137
|
-
"username": "alice",
|
|
138
|
-
"serviceFqn": "chat.app@1.0.0",
|
|
139
|
-
"offerId": "offer-hash",
|
|
140
|
-
"sdp": "v=0...",
|
|
141
|
-
"isPublic": true,
|
|
142
|
-
"metadata": {},
|
|
143
|
-
"createdAt": 1733404800000,
|
|
144
|
-
"expiresAt": 1733405100000
|
|
113
|
+
"success": false,
|
|
114
|
+
"error": "Error message"
|
|
145
115
|
}
|
|
146
116
|
```
|
|
147
117
|
|
|
148
|
-
**
|
|
118
|
+
**Batch responses:** Array of responses matching request array order.
|
|
149
119
|
|
|
150
|
-
|
|
120
|
+
## Core Methods
|
|
151
121
|
|
|
152
|
-
|
|
153
|
-
Publish a service with multiple offers (requires authentication and username signature)
|
|
122
|
+
### Username Management
|
|
154
123
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
**Request:**
|
|
159
|
-
```json
|
|
124
|
+
```typescript
|
|
125
|
+
// Check username availability
|
|
126
|
+
POST /rpc
|
|
160
127
|
{
|
|
161
|
-
"
|
|
162
|
-
"
|
|
163
|
-
{ "sdp": "v=0..." },
|
|
164
|
-
{ "sdp": "v=0..." }
|
|
165
|
-
],
|
|
166
|
-
"ttl": 300000,
|
|
167
|
-
"isPublic": false,
|
|
168
|
-
"metadata": { "description": "Chat service" },
|
|
169
|
-
"signature": "base64-encoded-signature",
|
|
170
|
-
"message": "publish:alice:com.example.chat@1.0.0:1733404800000"
|
|
128
|
+
"method": "getUser",
|
|
129
|
+
"params": { "username": "alice" }
|
|
171
130
|
}
|
|
172
|
-
```
|
|
173
131
|
|
|
174
|
-
|
|
175
|
-
|
|
132
|
+
// Claim username (requires signature)
|
|
133
|
+
POST /rpc
|
|
176
134
|
{
|
|
177
|
-
"
|
|
178
|
-
"
|
|
179
|
-
"
|
|
180
|
-
"
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
"sdp": "v=0...",
|
|
185
|
-
"createdAt": 1733404800000,
|
|
186
|
-
"expiresAt": 1733405100000
|
|
187
|
-
},
|
|
188
|
-
{
|
|
189
|
-
"offerId": "offer-hash-2",
|
|
190
|
-
"sdp": "v=0...",
|
|
191
|
-
"createdAt": 1733404800000,
|
|
192
|
-
"expiresAt": 1733405100000
|
|
193
|
-
}
|
|
194
|
-
],
|
|
195
|
-
"isPublic": false,
|
|
196
|
-
"metadata": { "description": "Chat service" },
|
|
197
|
-
"createdAt": 1733404800000,
|
|
198
|
-
"expiresAt": 1733405100000
|
|
135
|
+
"method": "claimUsername",
|
|
136
|
+
"message": "claim:alice:1733404800000",
|
|
137
|
+
"signature": "base64-signature",
|
|
138
|
+
"params": {
|
|
139
|
+
"username": "alice",
|
|
140
|
+
"publicKey": "base64-public-key"
|
|
141
|
+
}
|
|
199
142
|
}
|
|
200
143
|
```
|
|
201
144
|
|
|
202
|
-
|
|
203
|
-
- Service name: Reverse domain notation (e.g., `com.example.chat`)
|
|
204
|
-
- Version: Semantic versioning (e.g., `1.0.0`, `2.1.3-beta`)
|
|
205
|
-
- Complete FQN: `service-name@version` (e.g., `com.example.chat@1.0.0`)
|
|
206
|
-
|
|
207
|
-
**Validation:**
|
|
208
|
-
- Service name pattern: `^[a-z0-9]([a-z0-9-]*[a-z0-9])?(\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)+$`
|
|
209
|
-
- Length: 3-128 characters
|
|
210
|
-
- Version pattern: `^[0-9]+\.[0-9]+\.[0-9]+(-[a-z0-9.-]+)?$`
|
|
211
|
-
|
|
212
|
-
#### `GET /services/:uuid`
|
|
213
|
-
Get service details by UUID
|
|
214
|
-
|
|
215
|
-
**Response:**
|
|
216
|
-
```json
|
|
217
|
-
{
|
|
218
|
-
"serviceId": "...",
|
|
219
|
-
"username": "alice",
|
|
220
|
-
"serviceFqn": "com.example.chat@1.0.0",
|
|
221
|
-
"offerId": "...",
|
|
222
|
-
"sdp": "v=0...",
|
|
223
|
-
"isPublic": false,
|
|
224
|
-
"metadata": { ... },
|
|
225
|
-
"createdAt": 1733404800000,
|
|
226
|
-
"expiresAt": 1733405100000
|
|
227
|
-
}
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
#### `DELETE /users/:username/services/:fqn`
|
|
231
|
-
Unpublish a service (requires authentication and ownership)
|
|
232
|
-
|
|
233
|
-
**Headers:**
|
|
234
|
-
- `Authorization: Bearer {peerId}:{secret}`
|
|
145
|
+
### Service Publishing
|
|
235
146
|
|
|
236
|
-
|
|
237
|
-
|
|
147
|
+
```typescript
|
|
148
|
+
// Publish service (requires signature)
|
|
149
|
+
POST /rpc
|
|
238
150
|
{
|
|
239
|
-
"
|
|
151
|
+
"method": "publishService",
|
|
152
|
+
"message": "publishService:alice:chat:1.0.0@alice:1733404800000",
|
|
153
|
+
"signature": "base64-signature",
|
|
154
|
+
"params": {
|
|
155
|
+
"serviceFqn": "chat:1.0.0@alice",
|
|
156
|
+
"offers": [{ "sdp": "webrtc-offer-sdp" }],
|
|
157
|
+
"ttl": 300000
|
|
158
|
+
}
|
|
240
159
|
}
|
|
241
160
|
```
|
|
242
161
|
|
|
243
|
-
###
|
|
244
|
-
|
|
245
|
-
#### `POST /services/:uuid/answer`
|
|
246
|
-
Answer a service offer (requires authentication)
|
|
162
|
+
### Service Discovery
|
|
247
163
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
**Request:**
|
|
252
|
-
```json
|
|
164
|
+
```typescript
|
|
165
|
+
// Get specific service
|
|
166
|
+
POST /rpc
|
|
253
167
|
{
|
|
254
|
-
"
|
|
168
|
+
"method": "getService",
|
|
169
|
+
"params": { "serviceFqn": "chat:1.0.0@alice" }
|
|
255
170
|
}
|
|
256
|
-
```
|
|
257
171
|
|
|
258
|
-
|
|
259
|
-
|
|
172
|
+
// Random discovery
|
|
173
|
+
POST /rpc
|
|
260
174
|
{
|
|
261
|
-
"
|
|
262
|
-
"
|
|
175
|
+
"method": "getService",
|
|
176
|
+
"params": { "serviceFqn": "chat:1.0.0" }
|
|
263
177
|
}
|
|
264
|
-
```
|
|
265
178
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
**Headers:**
|
|
270
|
-
- `Authorization: Bearer {peerId}:{secret}`
|
|
271
|
-
|
|
272
|
-
**Response:**
|
|
273
|
-
```json
|
|
179
|
+
// Paginated discovery
|
|
180
|
+
POST /rpc
|
|
274
181
|
{
|
|
275
|
-
"
|
|
276
|
-
"
|
|
277
|
-
|
|
278
|
-
|
|
182
|
+
"method": "getService",
|
|
183
|
+
"params": {
|
|
184
|
+
"serviceFqn": "chat:1.0.0",
|
|
185
|
+
"limit": 10,
|
|
186
|
+
"offset": 0
|
|
187
|
+
}
|
|
279
188
|
}
|
|
280
189
|
```
|
|
281
190
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
#### `POST /services/:uuid/ice-candidates`
|
|
285
|
-
Post ICE candidates for a service (requires authentication)
|
|
191
|
+
### WebRTC Signaling
|
|
286
192
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
**Request:**
|
|
291
|
-
```json
|
|
193
|
+
```typescript
|
|
194
|
+
// Answer offer (requires signature)
|
|
195
|
+
POST /rpc
|
|
292
196
|
{
|
|
293
|
-
"
|
|
294
|
-
"
|
|
197
|
+
"method": "answerOffer",
|
|
198
|
+
"message": "answer:bob:offer-id:1733404800000",
|
|
199
|
+
"signature": "base64-signature",
|
|
200
|
+
"params": {
|
|
201
|
+
"serviceFqn": "chat:1.0.0@alice",
|
|
202
|
+
"offerId": "offer-id",
|
|
203
|
+
"sdp": "webrtc-answer-sdp"
|
|
204
|
+
}
|
|
295
205
|
}
|
|
296
|
-
```
|
|
297
206
|
|
|
298
|
-
|
|
299
|
-
|
|
207
|
+
// Add ICE candidates (requires signature)
|
|
208
|
+
POST /rpc
|
|
300
209
|
{
|
|
301
|
-
"
|
|
302
|
-
"
|
|
210
|
+
"method": "addIceCandidates",
|
|
211
|
+
"params": {
|
|
212
|
+
"serviceFqn": "chat:1.0.0@alice",
|
|
213
|
+
"offerId": "offer-id",
|
|
214
|
+
"candidates": [{ /* RTCIceCandidateInit */ }]
|
|
215
|
+
}
|
|
303
216
|
}
|
|
304
|
-
```
|
|
305
|
-
|
|
306
|
-
**Note:** If `offerId` is omitted, the server will auto-detect the peer's offer
|
|
307
|
-
|
|
308
|
-
#### `GET /services/:uuid/ice-candidates?since=1234567890&offerId=optional-offer-id`
|
|
309
|
-
Get ICE candidates from the other peer (requires authentication)
|
|
310
|
-
|
|
311
|
-
**Headers:**
|
|
312
|
-
- `Authorization: Bearer {peerId}:{secret}`
|
|
313
217
|
|
|
314
|
-
|
|
315
|
-
|
|
218
|
+
// Poll for answers and ICE candidates (requires signature)
|
|
219
|
+
POST /rpc
|
|
316
220
|
{
|
|
317
|
-
"
|
|
318
|
-
|
|
319
|
-
"candidate": "candidate:1 1 UDP...",
|
|
320
|
-
"createdAt": 1733404800000
|
|
321
|
-
}
|
|
322
|
-
],
|
|
323
|
-
"offerId": "offer-hash"
|
|
221
|
+
"method": "poll",
|
|
222
|
+
"params": { "since": 1733404800000 }
|
|
324
223
|
}
|
|
325
224
|
```
|
|
326
225
|
|
|
327
|
-
**Note:** Returns candidates from the opposite role (offerer gets answerer candidates and vice versa)
|
|
328
|
-
|
|
329
226
|
## Configuration
|
|
330
227
|
|
|
331
|
-
|
|
228
|
+
Quick reference for common environment variables:
|
|
332
229
|
|
|
333
230
|
| Variable | Default | Description |
|
|
334
231
|
|----------|---------|-------------|
|
|
335
232
|
| `PORT` | `3000` | Server port (Node.js/Docker) |
|
|
336
233
|
| `CORS_ORIGINS` | `*` | Comma-separated allowed origins |
|
|
337
234
|
| `STORAGE_PATH` | `./rondevu.db` | SQLite database path (use `:memory:` for in-memory) |
|
|
338
|
-
| `VERSION` | `2.0.0` | Server version (semver) |
|
|
339
|
-
| `AUTH_SECRET` | Random 32-byte hex | Secret key for credential encryption (required for production) |
|
|
340
|
-
| `OFFER_DEFAULT_TTL` | `300000` | Default offer TTL in ms (5 minutes) |
|
|
341
|
-
| `OFFER_MIN_TTL` | `60000` | Minimum offer TTL in ms (1 minute) |
|
|
342
|
-
| `OFFER_MAX_TTL` | `3600000` | Maximum offer TTL in ms (1 hour) |
|
|
343
|
-
| `MAX_OFFERS_PER_REQUEST` | `10` | Maximum offers per create request |
|
|
344
|
-
|
|
345
|
-
## Database Schema
|
|
346
|
-
|
|
347
|
-
### usernames
|
|
348
|
-
- `username` (PK): Claimed username
|
|
349
|
-
- `public_key`: Ed25519 public key (base64)
|
|
350
|
-
- `claimed_at`: Claim timestamp
|
|
351
|
-
- `expires_at`: Expiry timestamp (365 days)
|
|
352
|
-
- `last_used`: Last activity timestamp
|
|
353
|
-
- `metadata`: Optional JSON metadata
|
|
354
|
-
|
|
355
|
-
### services
|
|
356
|
-
- `id` (PK): Service ID (UUID)
|
|
357
|
-
- `username` (FK): Owner username
|
|
358
|
-
- `service_fqn`: Fully qualified name (com.example.chat@1.0.0)
|
|
359
|
-
- `is_public`: Public/private flag
|
|
360
|
-
- `metadata`: JSON metadata
|
|
361
|
-
- `created_at`, `expires_at`: Timestamps
|
|
362
|
-
|
|
363
|
-
### offers
|
|
364
|
-
- `id` (PK): Offer ID (hash of SDP)
|
|
365
|
-
- `peer_id` (FK): Owner peer ID
|
|
366
|
-
- `service_id` (FK): Optional link to service (null for standalone offers)
|
|
367
|
-
- `sdp`: WebRTC offer SDP
|
|
368
|
-
- `answerer_peer_id`: Peer ID of answerer (null until answered)
|
|
369
|
-
- `answer_sdp`: WebRTC answer SDP (null until answered)
|
|
370
|
-
- `created_at`, `expires_at`, `last_seen`: Timestamps
|
|
371
|
-
|
|
372
|
-
### service_index (privacy layer)
|
|
373
|
-
- `uuid` (PK): Random UUID for discovery
|
|
374
|
-
- `service_id` (FK): Links to service
|
|
375
|
-
- `username`, `service_fqn`: Denormalized for performance
|
|
376
235
|
|
|
377
|
-
|
|
236
|
+
📚 See [ADVANCED.md](./ADVANCED.md#configuration) for complete configuration reference.
|
|
378
237
|
|
|
379
|
-
|
|
380
|
-
- **Algorithm**: Ed25519 signatures
|
|
381
|
-
- **Message Format**: `claim:{username}:{timestamp}`
|
|
382
|
-
- **Replay Protection**: Timestamp must be within 5 minutes
|
|
383
|
-
- **Key Management**: Private keys never leave the client
|
|
238
|
+
## Documentation
|
|
384
239
|
|
|
385
|
-
|
|
386
|
-
-
|
|
387
|
-
-
|
|
388
|
-
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
- **Private Services**: Only UUID exposed, FQN hidden
|
|
392
|
-
- **Public Services**: FQN and metadata visible
|
|
393
|
-
- **No Enumeration**: Cannot list all services without knowing FQN
|
|
240
|
+
📚 **[ADVANCED.md](./ADVANCED.md)** - Comprehensive guide including:
|
|
241
|
+
- Complete RPC method reference with examples
|
|
242
|
+
- Full configuration options
|
|
243
|
+
- Database schema documentation
|
|
244
|
+
- Security implementation details
|
|
245
|
+
- Migration guides
|
|
394
246
|
|
|
395
|
-
##
|
|
247
|
+
## Security
|
|
396
248
|
|
|
397
|
-
|
|
249
|
+
All authenticated operations require Ed25519 signatures:
|
|
250
|
+
- **Message Format**: `{method}:{username}:{context}:{timestamp}`
|
|
251
|
+
- **Signature**: Base64-encoded Ed25519 signature of the message
|
|
252
|
+
- **Replay Protection**: Timestamps must be within 5 minutes
|
|
253
|
+
- **Username Ownership**: Verified via public key signature
|
|
398
254
|
|
|
399
|
-
|
|
400
|
-
- ❌ Removed: Topic-based discovery, bloom filters, public peer listings
|
|
401
|
-
- ✅ Added: Username claiming, service publishing, UUID-based privacy
|
|
255
|
+
See [ADVANCED.md](./ADVANCED.md#security) for detailed security documentation.
|
|
402
256
|
|
|
403
257
|
## License
|
|
404
258
|
|