Files
quicproquo/docs/sdk/wire-format.md
Christian Nennemann 2e081ead8e chore: rename quicproquo → quicprochat in docs, Docker, CI, and packaging
Rename all project references from quicproquo/qpq to quicprochat/qpc
across documentation, Docker configuration, CI workflows, packaging
scripts, operational configs, and build tooling.

- Docker: crate paths, binary names, user/group, data dirs, env vars
- CI: workflow crate references, binary names, artifact names
- Docs: all markdown files under docs/, SDK READMEs, book.toml
- Packaging: OpenWrt Makefile, init script, UCI config (file renames)
- Scripts: justfile, dev-shell, screenshot, cross-compile, ai_team
- Operations: Prometheus config, alert rules, Grafana dashboard
- Config: .env.example (QPQ_* → QPC_*), CODEOWNERS paths
- Top-level: README, CONTRIBUTING, ROADMAP, CLAUDE.md
2026-03-21 19:14:06 +01:00

209 lines
8.2 KiB
Markdown

# v2 Wire Format
The quicprochat 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**: `qpc`
- **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/qpc/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