docs(sdk): add comprehensive SDK documentation and wire format reference
Covers all official SDKs (Rust, Go, Python, TypeScript, C FFI), the v2 wire format with method ID tables, authentication flow, and a build-your-own-SDK guide with implementation checklist.
This commit is contained in:
208
docs/sdk/wire-format.md
Normal file
208
docs/sdk/wire-format.md
Normal file
@@ -0,0 +1,208 @@
|
||||
# v2 Wire Format
|
||||
|
||||
The quicproquo v2 protocol uses QUIC (RFC 9000) with TLS 1.3 as the transport layer and Protocol Buffers for message serialization.
|
||||
|
||||
## Connection
|
||||
|
||||
- **Protocol**: QUIC with TLS 1.3
|
||||
- **ALPN**: `qpq`
|
||||
- **Port**: 5001 (default)
|
||||
- **Certificate**: Server presents a TLS certificate; clients verify against a CA cert
|
||||
|
||||
## Frame Format
|
||||
|
||||
Every RPC request and response is wrapped in a 10-byte binary header:
|
||||
|
||||
```
|
||||
0 1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| method_id (u16) | req_id (u32) |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| req_id (cont.) | payload_len (u32) |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| payload_len (cont.) | protobuf payload ... |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
```
|
||||
|
||||
| Field | Type | Bytes | Description |
|
||||
|---|---|---|---|
|
||||
| `method_id` | `u16` | 0-1 | RPC method identifier (network byte order) |
|
||||
| `req_id` | `u32` | 2-5 | Client-generated request correlation ID (network byte order) |
|
||||
| `payload_len` | `u32` | 6-9 | Length of the protobuf payload (network byte order) |
|
||||
| payload | bytes | 10+ | Protobuf-encoded request or response message |
|
||||
|
||||
All multi-byte integers are **big-endian** (network byte order).
|
||||
|
||||
## Stream Model
|
||||
|
||||
Each RPC call uses a **dedicated QUIC bidirectional stream**:
|
||||
|
||||
1. Client opens a new stream
|
||||
2. Client sends the request frame and marks end-of-stream
|
||||
3. Server reads the request, processes it, and sends the response frame
|
||||
4. Server marks end-of-stream
|
||||
|
||||
This allows concurrent RPCs without head-of-line blocking.
|
||||
|
||||
## Method IDs
|
||||
|
||||
### Auth (100-103)
|
||||
|
||||
| ID | Method | Request | Response |
|
||||
|---|---|---|---|
|
||||
| 100 | `OpaqueRegisterStart` | `OpaqueRegisterStartRequest` | `OpaqueRegisterStartResponse` |
|
||||
| 101 | `OpaqueRegisterFinish` | `OpaqueRegisterFinishRequest` | `OpaqueRegisterFinishResponse` |
|
||||
| 102 | `OpaqueLoginStart` | `OpaqueLoginStartRequest` | `OpaqueLoginStartResponse` |
|
||||
| 103 | `OpaqueLoginFinish` | `OpaqueLoginFinishRequest` | `OpaqueLoginFinishResponse` |
|
||||
|
||||
### Delivery (200-205)
|
||||
|
||||
| ID | Method | Request | Response |
|
||||
|---|---|---|---|
|
||||
| 200 | `Enqueue` | `EnqueueRequest` | `EnqueueResponse` |
|
||||
| 201 | `Fetch` | `FetchRequest` | `FetchResponse` |
|
||||
| 202 | `FetchWait` | `FetchWaitRequest` | `FetchWaitResponse` |
|
||||
| 203 | `Peek` | `PeekRequest` | `PeekResponse` |
|
||||
| 204 | `Ack` | `AckRequest` | `AckResponse` |
|
||||
| 205 | `BatchEnqueue` | `BatchEnqueueRequest` | `BatchEnqueueResponse` |
|
||||
|
||||
### Keys (300-304)
|
||||
|
||||
| ID | Method | Request | Response |
|
||||
|---|---|---|---|
|
||||
| 300 | `UploadKeyPackage` | `UploadKeyPackageRequest` | `UploadKeyPackageResponse` |
|
||||
| 301 | `FetchKeyPackage` | `FetchKeyPackageRequest` | `FetchKeyPackageResponse` |
|
||||
| 302 | `UploadHybridKey` | `UploadHybridKeyRequest` | `UploadHybridKeyResponse` |
|
||||
| 303 | `FetchHybridKey` | `FetchHybridKeyRequest` | `FetchHybridKeyResponse` |
|
||||
| 304 | `FetchHybridKeys` | `FetchHybridKeysRequest` | `FetchHybridKeysResponse` |
|
||||
|
||||
### Channel (400)
|
||||
|
||||
| ID | Method | Request | Response |
|
||||
|---|---|---|---|
|
||||
| 400 | `CreateChannel` | `CreateChannelRequest` | `CreateChannelResponse` |
|
||||
|
||||
### Group Management (410-413)
|
||||
|
||||
| ID | Method | Request | Response |
|
||||
|---|---|---|---|
|
||||
| 410 | `RemoveMember` | `RemoveMemberRequest` | `RemoveMemberResponse` |
|
||||
| 411 | `UpdateGroupMetadata` | `UpdateGroupMetadataRequest` | `UpdateGroupMetadataResponse` |
|
||||
| 412 | `ListGroupMembers` | `ListGroupMembersRequest` | `ListGroupMembersResponse` |
|
||||
| 413 | `RotateKeys` | `RotateKeysRequest` | `RotateKeysResponse` |
|
||||
|
||||
### User (500-501)
|
||||
|
||||
| ID | Method | Request | Response |
|
||||
|---|---|---|---|
|
||||
| 500 | `ResolveUser` | `ResolveUserRequest` | `ResolveUserResponse` |
|
||||
| 501 | `ResolveIdentity` | `ResolveIdentityRequest` | `ResolveIdentityResponse` |
|
||||
|
||||
### Blob (600-601)
|
||||
|
||||
| ID | Method | Request | Response |
|
||||
|---|---|---|---|
|
||||
| 600 | `UploadBlob` | `UploadBlobRequest` | `UploadBlobResponse` |
|
||||
| 601 | `DownloadBlob` | `DownloadBlobRequest` | `DownloadBlobResponse` |
|
||||
|
||||
### Device (700-702)
|
||||
|
||||
| ID | Method | Request | Response |
|
||||
|---|---|---|---|
|
||||
| 700 | `RegisterDevice` | `RegisterDeviceRequest` | `RegisterDeviceResponse` |
|
||||
| 701 | `ListDevices` | `ListDevicesRequest` | `ListDevicesResponse` |
|
||||
| 702 | `RevokeDevice` | `RevokeDeviceRequest` | `RevokeDeviceResponse` |
|
||||
|
||||
### P2P / Health (800-802)
|
||||
|
||||
| ID | Method | Request | Response |
|
||||
|---|---|---|---|
|
||||
| 800 | `PublishEndpoint` | `PublishEndpointRequest` | `PublishEndpointResponse` |
|
||||
| 801 | `ResolveEndpoint` | `ResolveEndpointRequest` | `ResolveEndpointResponse` |
|
||||
| 802 | `Health` | `HealthRequest` | `HealthResponse` |
|
||||
|
||||
### Federation (900-905)
|
||||
|
||||
| ID | Method | Request | Response |
|
||||
|---|---|---|---|
|
||||
| 900 | `RelayEnqueue` | `RelayEnqueueRequest` | `RelayEnqueueResponse` |
|
||||
| 901-905 | Reserved | -- | -- |
|
||||
|
||||
### Account (950)
|
||||
|
||||
| ID | Method | Request | Response |
|
||||
|---|---|---|---|
|
||||
| 950 | `DeleteAccount` | `DeleteAccountRequest` | `DeleteAccountResponse` |
|
||||
|
||||
## Protobuf Definitions
|
||||
|
||||
All message types are defined in `proto/qpq/v1/*.proto`:
|
||||
|
||||
| File | Services |
|
||||
|---|---|
|
||||
| `auth.proto` | OPAQUE registration and login |
|
||||
| `common.proto` | Auth context, account deletion |
|
||||
| `delivery.proto` | Message enqueue, fetch, peek, ack |
|
||||
| `keys.proto` | MLS key packages, hybrid keys |
|
||||
| `channel.proto` | Channel creation |
|
||||
| `user.proto` | User/identity resolution |
|
||||
| `group.proto` | Group management |
|
||||
| `blob.proto` | Binary object storage |
|
||||
| `device.proto` | Multi-device management |
|
||||
| `p2p.proto` | P2P endpoints, health |
|
||||
| `federation.proto` | Cross-server relay |
|
||||
| `push.proto` | Push notifications |
|
||||
| `recovery.proto` | Account recovery |
|
||||
| `moderation.proto` | Content moderation |
|
||||
|
||||
## Authentication Flow
|
||||
|
||||
Authentication uses the OPAQUE protocol (asymmetric PAKE):
|
||||
|
||||
```
|
||||
Client Server
|
||||
│ │
|
||||
│ OpaqueRegisterStart(username, │
|
||||
│ registration_request) │
|
||||
│ ──────────────────────────────────►│
|
||||
│ │
|
||||
│ OpaqueRegisterStartResponse( │
|
||||
│ registration_response) │
|
||||
│ ◄──────────────────────────────────│
|
||||
│ │
|
||||
│ OpaqueRegisterFinish(username, │
|
||||
│ upload, identity_key) │
|
||||
│ ──────────────────────────────────►│
|
||||
│ │
|
||||
│ OpaqueRegisterFinishResponse( │
|
||||
│ success) │
|
||||
│ ◄──────────────────────────────────│
|
||||
│ │
|
||||
│ OpaqueLoginStart(username, │
|
||||
│ login_request) │
|
||||
│ ──────────────────────────────────►│
|
||||
│ │
|
||||
│ OpaqueLoginStartResponse( │
|
||||
│ login_response) │
|
||||
│ ◄──────────────────────────────────│
|
||||
│ │
|
||||
│ OpaqueLoginFinish(username, │
|
||||
│ finalization, identity_key) │
|
||||
│ ──────────────────────────────────►│
|
||||
│ │
|
||||
│ OpaqueLoginFinishResponse( │
|
||||
│ session_token) │
|
||||
│ ◄──────────────────────────────────│
|
||||
```
|
||||
|
||||
The `session_token` is used for subsequent authenticated RPCs.
|
||||
|
||||
## Error Handling
|
||||
|
||||
The server returns protobuf-encoded error responses on the same stream. Error conditions include:
|
||||
|
||||
- Invalid method ID: stream reset
|
||||
- Authentication failure: error response with details
|
||||
- Rate limiting: error response with retry-after hint
|
||||
- Internal errors: generic error response
|
||||
Reference in New Issue
Block a user