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:
| 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:
- Client opens a new stream
- Client sends the request frame and marks end-of-stream
- Server reads the request, processes it, and sends the response frame
- 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):
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