Matrix protocol in OCaml, Eio specialised
at main 420 lines 19 kB view raw view rendered
1# ocaml-matrix 2 3**Status: SUBSTANTIALLY COMPLETE** 4 5OCaml Matrix SDK providing protocol types and a full HTTP client for the Matrix chat protocol (spec v1.17). Uses `requests` for HTTP and `jsont` for JSON encoding/decoding. Provides an Eio-idiomatic wrapper for structured concurrency. 6 7## Specification 8 9The Matrix spec is vendored at `spec/matrix-spec` as a git submodule (currently tracking v1.17). 10 11See: https://github.com/matrix-org/matrix-spec 12 13## Client-Server API Feature Coverage 14 15The Matrix spec defines 41 feature modules for clients. Here is the implementation status for each: 16 17### Authentication & Session Management 18 19| Feature | Status | Module | Notes | 20|---------|--------|--------|-------| 21| Login (password) | ✅ Complete | `Auth` | Username/password with device settings | 22| Login (token/SSO) | ✅ Complete | `Auth` | Token-based login for SSO flows | 23| Token refresh | ✅ Complete | `Auth` | Refresh expired access tokens | 24| Logout | ✅ Complete | `Auth` | Single session or all sessions | 25| Registration | ✅ Complete | `Auth` | Guest or user account creation | 26| Whoami | ✅ Complete | `Auth` | Query current user/device | 27| UIAA | ✅ Complete | `Uiaa` | Password, recaptcha, email, dummy flows | 28| Soft logout | ⚠️ Partial | `Auth` | Token expiry detected, re-auth supported | 29| Account locking | ❌ Not implemented | - | Server-side feature | 30| OAuth 2.0 | ❌ Not implemented | - | Industry-standard auth (new in spec) | 31 32### Synchronization 33 34| Feature | Status | Module | Notes | 35|---------|--------|--------|-------| 36| `/sync` endpoint | ✅ Complete | `Sync` | Full parameter support | 37| Long-polling | ✅ Complete | `Sync` | Configurable timeout | 38| Incremental sync | ✅ Complete | `Sync` | next_batch token tracking | 39| Sync filters | ✅ Complete | `Sync` | Create, retrieve, apply filters | 40| Event filters | ✅ Complete | `Sync` | Type/sender filtering with limits | 41| Room event filters | ✅ Complete | `Sync` | Lazy load members, contains_url | 42| Sync loop | ✅ Complete | `Sync` | Callback-based continuous polling | 43| Sliding sync (MSC3575) | ⚠️ Stub | `Sliding_sync` | Data structures only | 44 45### Rooms & Membership 46 47| Feature | Status | Module | Notes | 48|---------|--------|--------|-------| 49| Room creation | ✅ Complete | `Rooms` | Name, topic, visibility, preset, type | 50| Join room (by ID) | ✅ Complete | `Rooms` | With server routing | 51| Join room (by alias) | ✅ Complete | `Rooms` | Alias resolution included | 52| Leave room | ✅ Complete | `Rooms` | Standard leave | 53| Forget room | ✅ Complete | `Rooms` | Remove from history | 54| Invite user | ✅ Complete | `Rooms` | By user ID | 55| Kick user | ✅ Complete | `Rooms` | With optional reason | 56| Ban/unban user | ✅ Complete | `Rooms` | With optional reason | 57| Get joined rooms | ✅ Complete | `Rooms` | List all joined rooms | 58| Get room members | ✅ Complete | `Rooms` | With membership state filtering | 59| Public room list | ✅ Complete | `Rooms` | Browse with pagination | 60| Power levels | ✅ Complete | `Rooms` | Get/set room and user permissions | 61| Knocking | ✅ Complete | `Event` | Join rule and membership type defined | 62| Restricted join rules | ✅ Complete | `Event` | Room-based access control | 63| Room upgrades | ⚠️ Partial | `Event` | Tombstone event type, no upgrade API | 64 65### Messaging 66 67| Feature | Status | Module | Notes | 68|---------|--------|--------|-------| 69| Text messages | ✅ Complete | `Messages` | Plain text with msgtype | 70| Emotes | ✅ Complete | `Messages` | m.emote support | 71| Notices | ✅ Complete | `Messages` | m.notice support | 72| HTML formatting | ✅ Complete | `Messages`, `Event` | format + formatted_body | 73| Image messages | ✅ Complete | `Messages`, `Event` | With media info | 74| File messages | ✅ Complete | `Messages`, `Event` | With media info | 75| Audio messages | ✅ Complete | `Messages`, `Event` | With media info | 76| Video messages | ✅ Complete | `Messages`, `Event` | With media info | 77| Location messages | ✅ Complete | `Event` | geo_uri with location info | 78| Stickers | ✅ Complete | `Event` | Sticker content type | 79| Redaction | ✅ Complete | `Messages` | With optional reason | 80| Get messages | ✅ Complete | `Messages` | Pagination forward/backward | 81| Get event context | ✅ Complete | `Messages` | Events before/after | 82| Rich replies | ✅ Complete | `Relations` | m.in_reply_to structure | 83| Threads | ✅ Complete | `Relations` | m.thread relation type | 84| Reactions | ✅ Complete | `Relations` | m.annotation with emoji key | 85| Edits | ✅ Complete | `Relations` | m.replace relation type | 86| Polls | ✅ Complete | `Event` | Start, response, end content types | 87 88### Room State 89 90| Feature | Status | Module | Notes | 91|---------|--------|--------|-------| 92| Get state events | ✅ Complete | `State` | By type and state key | 93| Set state events | ✅ Complete | `State` | Returns event ID | 94| Room name | ✅ Complete | `State`, `Event` | Get/set with content type | 95| Room topic | ✅ Complete | `State`, `Event` | Get/set with content type | 96| Room avatar | ✅ Complete | `State`, `Event` | Get/set with image info | 97| Room canonical alias | ✅ Complete | `Event` | Primary alias with alternates | 98| Join rules | ✅ Complete | `Event` | Public/invite/knock/restricted/private | 99| History visibility | ✅ Complete | `Event` | Invited/joined/shared/world_readable | 100| Guest access | ✅ Complete | `Event` | Can_join/forbidden | 101| Room encryption | ✅ Complete | `Event` | Algorithm and rotation settings | 102| Pinned events | ✅ Complete | `Event` | List of pinned event IDs | 103| Server ACLs | ✅ Complete | `Event` | Allow/deny rules | 104| Room creation event | ✅ Complete | `Event` | Creator, version, predecessor | 105 106### User Profile & Presence 107 108| Feature | Status | Module | Notes | 109|---------|--------|--------|-------| 110| Get profile | ✅ Complete | `Profile` | Display name and avatar | 111| Set display name | ✅ Complete | `Profile` | Update own name | 112| Set avatar | ✅ Complete | `Profile` | Update own avatar URL | 113| Get presence | ✅ Complete | `Presence` | Online/offline/unavailable | 114| Set presence | ✅ Complete | `Presence` | With status message | 115| Last active time | ✅ Complete | `Presence` | Activity timestamp | 116 117### Ephemeral Events 118 119| Feature | Status | Module | Notes | 120|---------|--------|--------|-------| 121| Typing notifications | ✅ Complete | `Typing` | Set typing state with timeout | 122| Read receipts | ✅ Complete | `Receipts` | Send with receipt type | 123| Read markers | ✅ Complete | `Receipts` | Set fully_read position | 124 125### End-to-End Encryption 126 127| Feature | Status | Module | Notes | 128|---------|--------|--------|-------| 129| Ed25519 key generation | ✅ Complete | `Keys` | Signing keys | 130| Curve25519 key generation | ✅ Complete | `Keys` | Key exchange | 131| One-time key generation | ✅ Complete | `Keys` | Batch generation with signing | 132| Fallback keys | ⚠️ Partial | `Keys` | Structure defined, upload untested | 133| Device key upload | ✅ Complete | `Keys` | With signatures | 134| Device key query | ✅ Complete | `Keys` | Fetch keys for users | 135| One-time key claim | ✅ Complete | `Keys` | Obtain keys for Olm setup | 136| Key change tracking | ✅ Complete | `Keys` | Between syncs | 137| Olm sessions | ✅ Complete | `Olm` | Create, store, retrieve | 138| X3DH key exchange | ✅ Complete | `Olm` | Triple Diffie-Hellman | 139| Double Ratchet | ✅ Complete | `Olm` | Per-session encryption | 140| Megolm sessions | ✅ Complete | `Olm` | Outbound/inbound group keys | 141| Message encryption | ✅ Complete | `Olm` | With authentication | 142| Message decryption | ✅ Complete | `Olm` | With verification | 143| Session pickling | ⚠️ Partial | `Olm` | Simplified JSON format | 144| Encrypted event type | ✅ Complete | `Event` | Olm and Megolm algorithms | 145 146### Device & Key Verification 147 148| Feature | Status | Module | Notes | 149|---------|--------|--------|-------| 150| List devices | ✅ Complete | `Devices` | All devices for user | 151| Get device info | ✅ Complete | `Devices` | IP and timestamp | 152| Update device | ✅ Complete | `Devices` | Display name | 153| Delete device | ✅ Complete | `Devices` | Single or batch | 154| Cross-signing keys | ✅ Complete | `Verification` | Master, self, user signing | 155| SAS verification | ⚠️ Partial | `Verification` | 20/64 emoji, no to-device | 156| QR verification | ⚠️ Partial | `Verification` | Structures only, no encode/decode | 157| Device trust | ✅ Complete | `Verification` | Trust state tracking | 158| Signature verification | ⚠️ Partial | `Verification` | Existence check only | 159| Verification events | ✅ Complete | `Event` | Ready, start, accept, key, mac, cancel, done | 160 161### Key Backup 162 163| Feature | Status | Module | Notes | 164|---------|--------|--------|-------| 165| Backup encryption | ✅ Complete | `Backup` | m.megolm_backup.v1.curve25519-aes-sha2 | 166| Backup decryption | ✅ Complete | `Backup` | AES-CTR with HKDF | 167| Recovery key generation | ⚠️ Partial | `Backup` | Uses base64, not base58 | 168| Recovery key parsing | ❌ Stub | `Backup` | Needs implementation | 169| Backup upload | ❌ Not implemented | - | No server API integration | 170| Backup download | ❌ Not implemented | - | No server API integration | 171| Backup version management | ❌ Not implemented | - | No server API integration | 172 173### Media 174 175| Feature | Status | Module | Notes | 176|---------|--------|--------|-------| 177| Upload media | ✅ Complete | `Media` | Binary with content type | 178| Download media | ✅ Complete | `Media` | By server/media ID | 179| Thumbnails | ✅ Complete | `Media` | Scaled/cropped versions | 180| MXC URI parsing | ✅ Complete | `Media` | Parse mxc:// URIs | 181| MXC to HTTP URL | ✅ Complete | `Media` | With thumbnail options | 182| Upload size limit | ✅ Complete | `Media` | Query configuration | 183| Encrypted media | ✅ Complete | `Event` | Encrypted file structure | 184 185### Account Management 186 187| Feature | Status | Module | Notes | 188|---------|--------|--------|-------| 189| Global account data | ✅ Complete | `Account` | Get/set arbitrary data | 190| Room account data | ✅ Complete | `Account` | Per-room data | 191| Third-party IDs | ✅ Complete | `Account` | Query, add, delete 3PIDs | 192| Email verification | ✅ Complete | `Account` | Request tokens | 193| Phone verification | ✅ Complete | `Account` | Request tokens | 194| Password change | ✅ Complete | `Account` | With device logout option | 195| Account deactivation | ✅ Complete | `Account` | Irreversible with erasure | 196| Ignored users | ✅ Complete | `Account` | Maintain ignore list | 197 198### Room Directory 199 200| Feature | Status | Module | Notes | 201|---------|--------|--------|-------| 202| Alias resolution | ✅ Complete | `Directory` | Alias to room ID | 203| Create alias | ✅ Complete | `Directory` | New room alias | 204| Delete alias | ✅ Complete | `Directory` | Remove alias | 205| Room visibility | ✅ Complete | `Directory` | Get/set directory visibility | 206| Public room search | ✅ Complete | `Directory` | With term and type filtering | 207 208### Spaces 209 210| Feature | Status | Module | Notes | 211|---------|--------|--------|-------| 212| Space child events | ✅ Complete | `Event` | Via servers, order, suggested | 213| Space parent events | ✅ Complete | `Event` | Via servers, canonical | 214| Space hierarchy | ✅ Complete | `Spaces` | Navigate structure | 215| Space management | ✅ Complete | `Spaces` | Parent/child relationships | 216 217### Voice/Video Calling 218 219| Feature | Status | Module | Notes | 220|---------|--------|--------|-------| 221| Call invite | ✅ Complete | `Event`, `Calls` | SDP offer, lifetime | 222| Call answer | ✅ Complete | `Event`, `Calls` | SDP answer | 223| Call hangup | ✅ Complete | `Event`, `Calls` | With reason codes | 224| ICE candidates | ✅ Complete | `Event`, `Calls` | Candidate exchange | 225| Call member | ✅ Complete | `Event` | LiveKit support, foci_active | 226 227### Push Notifications 228 229| Feature | Status | Module | Notes | 230|---------|--------|--------|-------| 231| Get push rules | ✅ Complete | `Push` | User notification rules | 232| Set push rules | ✅ Complete | `Push` | Update rules | 233| Enable/disable rules | ✅ Complete | `Push` | Toggle specific rules | 234| Delete rules | ✅ Complete | `Push` | Remove rules | 235| Push gateway | ❌ Not implemented | - | Separate API | 236 237### Additional Features 238 239| Feature | Status | Module | Notes | 240|---------|--------|--------|-------| 241| Room preview | ✅ Complete | `Room_preview` | Info before joining | 242| Room tagging | ⚠️ Partial | `Account` | Via account data | 243| Server notices | ❌ Not implemented | - | Server-side feature | 244| OpenID | ❌ Not implemented | - | Token provisioning | 245| Third-party invites | ❌ Not implemented | - | Email/phone invites | 246| Third-party networks | ❌ Not implemented | - | Bridge support | 247| Server-side search | ❌ Not implemented | - | Full-text search | 248| Reporting content | ❌ Not implemented | - | Event flagging | 249| Moderation policy lists | ✅ Complete | `Event` | Policy rule content type | 250| Server ACLs | ✅ Complete | `Event` | Allow/deny in state | 251| Secret storage | ❌ Not implemented | - | m.secret_storage.v1 | 252| Recently used emoji | ❌ Not implemented | - | Client-side typically | 253 254## Protocol Types Coverage 255 256### Identifiers (Matrix_id) 257 258| Type | Status | Notes | 259|------|--------|-------| 260| Server_name | ✅ Complete | Hostname validation | 261| User_id | ✅ Complete | @localpart:server format | 262| Room_id | ✅ Complete | !opaque_id:server format | 263| Event_id | ✅ Complete | v1-3 and v4 formats | 264| Room_alias | ✅ Complete | #alias:server format | 265| Device_id | ✅ Complete | Opaque string | 266| Session_id | ✅ Complete | Megolm session IDs | 267| Transaction_id | ✅ Complete | With generate() | 268 269### Event Content Types (Matrix_event) 270 271| Category | Types | Status | 272|----------|-------|--------| 273| Room state | 16 types | ✅ Complete | 274| Space events | 2 types | ✅ Complete | 275| Call events | 5 types | ✅ Complete | 276| Verification events | 7 types | ✅ Complete | 277| Message events | 8 types | ✅ Complete | 278| Encrypted content | 1 type | ✅ Complete | 279| Relations | 3 types | ✅ Complete | 280| Location/Beacons | 2 types | ✅ Complete | 281| Policy rules | 1 type | ✅ Complete | 282 283### Sync Response (Matrix_sync) 284 285| Component | Status | Notes | 286|-----------|--------|-------| 287| Timeline | ✅ Complete | Events, limited, pagination | 288| Ephemeral | ✅ Complete | Typing, receipts | 289| Account data | ✅ Complete | Per-room and global | 290| Room state | ✅ Complete | State events | 291| Joined rooms | ✅ Complete | Full room state | 292| Invited rooms | ✅ Complete | Invite state | 293| Left rooms | ✅ Complete | Leave state | 294| Knocked rooms | ✅ Complete | Knock state | 295| Device lists | ✅ Complete | Changed/left tracking | 296| To-device | ✅ Complete | Direct messages | 297| Presence | ✅ Complete | User presence | 298 299## Client Architecture 300 301### Libraries 302 303| Library | Purpose | Status | 304|---------|---------|--------| 305| `matrix_proto` | Protocol types with jsont codecs | ✅ Complete | 306| `matrix_client` | HTTP client (Result-based) | ✅ Complete | 307| `matrix_eio` | Eio wrapper (exception-based) | ✅ Complete | 308 309### Client Modules 310 311All 23 modules have Eio wrappers: 312 313| Module | Lines | Status | Notes | 314|--------|-------|--------|-------| 315| Auth | 304 | ✅ Complete | All login flows | 316| Sync | 246 | ✅ Complete | Sync loop with callbacks | 317| Rooms | 461 | ✅ Complete | Full room management | 318| Messages | 232 | ✅ Complete | All message types | 319| State | 139 | ✅ Complete | State get/set | 320| Keys | 447 | ✅ Complete | E2EE key management | 321| Olm | 895 | ✅ Complete | Session management | 322| Verification | 535 | ⚠️ Partial | SAS incomplete | 323| Backup | 466 | ⚠️ Partial | No server API | 324| Media | 118 | ✅ Complete | Upload/download | 325| Profile | 108 | ✅ Complete | Name/avatar | 326| Presence | 72 | ✅ Complete | Status management | 327| Typing | 31 | ✅ Complete | Typing indicators | 328| Receipts | 39 | ✅ Complete | Read receipts | 329| Devices | 89 | ✅ Complete | Device management | 330| Account | 329 | ✅ Complete | Account data, 3PIDs | 331| Directory | 182 | ✅ Complete | Aliases, search | 332| Relations | 330 | ✅ Complete | Reactions, edits, threads | 333| Uiaa | 435 | ✅ Complete | Multi-stage auth | 334| Timeline | 423 | ⚠️ Partial | TODO: trimming | 335| Store | 1001 | ⚠️ Partial | In-memory only | 336| Send_queue | 466 | ⚠️ Partial | No HTTP integration | 337| Push | 368 | ✅ Complete | Push rules | 338| Spaces | 212 | ✅ Complete | Hierarchy | 339| Calls | 193 | ✅ Complete | VoIP events | 340| Room_preview | 257 | ✅ Complete | Preview info | 341| Sliding_sync | 500 | ❌ Stub | MSC3575 structures only | 342 343## Known Limitations 344 345### Verification Module 346- SAS emoji table has 20 entries (spec requires 64) 347- `verify_cross_signing_signature` checks existence, not cryptographic validity 348- QR code verification has structures but no encoding/decoding 349- No to-device message sending for verification flow 350 351### Backup Module 352- Recovery key uses base64 encoding instead of base58 353- `parse_recovered_key` is a stub 354- No server API calls for backup upload/download/version management 355 356### Send_queue Module 357- Provides queue management but no HTTP integration 358- Caller must implement `send_fn` for actual sending 359- No automatic persistence 360 361### Store Module 362- All stores (STATE_STORE, CRYPTO_STORE, EVENT_CACHE_STORE) are in-memory only 363- Pluggable architecture defined but only memory backends exist 364- No SQLite or file-based implementations 365 366### Timeline Module 367- LinkedChunk `push_back` has TODO for trimming when over `max_events` 368- LRU eviction removes oldest room without access-time preservation 369 370### Olm Module 371- Session pickle/unpickle uses simplified JSON format 372- Needs real-world validation 373- No session recovery from corrupted state 374 375## Test Coverage 376 377| Area | Tests | Status | 378|------|-------|--------| 379| Protocol types | 39 roundtrip tests | ✅ Complete | 380| Sync response | Fixture-based | ✅ Complete | 381| Integration tests | None | ❌ Needed | 382 383## Dependencies 384 385- `jsont` / `jsont.bytesrw` - JSON encoding/decoding 386- `requests` - HTTP client 387- `eio` - Async I/O with structured concurrency 388- `uri` - URI handling 389- `ptime` - Timestamps 390- `base64` - Base64 encoding 391- `mirage-crypto` - AES-CBC encryption 392- `mirage-crypto-ec` - Ed25519/X25519 cryptography 393- `mirage-crypto-rng` - Secure random number generation 394- `digestif` - SHA-256 hashing 395- `kdf.hkdf` - HKDF key derivation 396 397## Room Versions 398 399The implementation supports room version events but does not enforce version-specific behavior: 400 401| Version | Key Feature | Event Support | 402|---------|-------------|---------------| 403| v1-v6 | Core messaging | ✅ | 404| v7 | Knocking | ✅ | 405| v8 | Restricted joins | ✅ | 406| v9 | Redaction fixes | ✅ | 407| v10 | Integer power levels | ✅ | 408| v11 | Redaction clarification | ✅ | 409| v12 | Creator infinite power | ✅ | 410 411## Summary 412 413**Overall completion: ~85%** 414 415- **Core features**: 95% complete (auth, sync, rooms, messages, state, presence) 416- **E2EE primitives**: 90% complete (keys, Olm, Megolm - verification partial) 417- **Advanced features**: 70% complete (backup, sliding sync, secret storage incomplete) 418- **Infrastructure**: 80% complete (storage in-memory only, no integration tests) 419 420The SDK is suitable for building Matrix clients with basic E2EE support. Full production use requires completing verification flows, backup server integration, and persistent storage backends.