# Service Architecture The quicprochat server exposes 44 RPC methods through a single QUIC + TLS 1.3 endpoint on **port 5001**. Methods are dispatched by numeric method ID using the v2 Protobuf framing protocol. This page documents the method reference, connection lifecycle, storage model, and authentication flow. --- ## RPC Endpoint A single QUIC + TLS 1.3 listener on **port 5001** serves all operations. The ALPN identifier is `qpc`. Each RPC call uses a dedicated QUIC bidirectional stream; calls are concurrent and do not block each other. ```text quicprochat-server (port 5001, ALPN: "qpc") | +-- Auth (100-103) | +-- 100: OpaqueRegisterStart | +-- 101: OpaqueRegisterFinish | +-- 102: OpaqueLoginStart | +-- 103: OpaqueLoginFinish | +-- Delivery (200-205) | +-- 200: Enqueue | +-- 201: Fetch | +-- 202: FetchWait | +-- 203: Peek | +-- 204: Ack | +-- 205: BatchEnqueue | +-- Keys (300-304) | +-- 300: UploadKeyPackage | +-- 301: FetchKeyPackage | +-- 302: UploadHybridKey | +-- 303: FetchHybridKey | +-- 304: FetchHybridKeys | +-- Channel (400) | +-- 400: CreateChannel | +-- Group Management (410-413) | +-- 410: RemoveMember | +-- 411: UpdateGroupMetadata | +-- 412: ListGroupMembers | +-- 413: RotateKeys | +-- Moderation (420-424) | +-- 420: ReportMessage | +-- 421: BanUser | +-- 422: UnbanUser | +-- 423: ListReports | +-- 424: ListBanned | +-- User (500-501) | +-- 500: ResolveUser | +-- 501: ResolveIdentity | +-- Key Transparency (510-520) | +-- 510: RevokeKey | +-- 511: CheckRevocation | +-- 520: AuditKeyTransparency | +-- Blob (600-601) | +-- 600: UploadBlob | +-- 601: DownloadBlob | +-- Device (700-710) | +-- 700: RegisterDevice | +-- 701: ListDevices | +-- 702: RevokeDevice | +-- 710: RegisterPushToken | +-- Recovery (750-752) | +-- 750: StoreRecoveryBundle | +-- 751: FetchRecoveryBundle | +-- 752: DeleteRecoveryBundle | +-- P2P (800-802) | +-- 800: PublishEndpoint | +-- 801: ResolveEndpoint | +-- 802: Health | +-- Federation (900-905) | +-- 900: RelayEnqueue | +-- 901: RelayBatchEnqueue | +-- 902: ProxyFetchKeyPackage | +-- 903: ProxyFetchHybridKey | +-- 904: ProxyResolveUser | +-- 905: FederationHealth | +-- Account (950) +-- 950: DeleteAccount Push event types (server -> client, uni-stream): 1000: PushNewMessage 1001: PushTyping 1002: PushPresence 1003: PushMembership ``` --- ## RPC Method Reference ### Auth (100-103) OPAQUE password authentication (asymmetric PAKE). The password is never sent to the server. Method IDs 100-103 implement the 4-step OPAQUE handshake. | ID | Method | Description | |-----|-------------------------|-------------| | 100 | `OpaqueRegisterStart` | Client initiates registration with `username` and OPAQUE `registration_request` blob. Server returns `registration_response`. | | 101 | `OpaqueRegisterFinish` | Client completes registration with `username`, OPAQUE `upload` blob, and Ed25519 `identity_key`. Server stores the OPAQUE record. | | 102 | `OpaqueLoginStart` | Client initiates login with `username` and OPAQUE `login_request` blob. Server returns `login_response`. | | 103 | `OpaqueLoginFinish` | Client completes login with `username`, OPAQUE `finalization` blob, and `identity_key`. Server returns a `session_token`. | The `session_token` is an opaque bearer token used for subsequent authenticated RPCs. It is passed in the Protobuf request body (not as a frame-level header). ### Delivery (200-205) Store-and-forward relay. The server never inspects MLS ciphertext -- it routes opaque byte blobs by recipient key. | ID | Method | Description | |-----|----------------|-------------| | 200 | `Enqueue` | Append an opaque payload to the recipient's FIFO queue. Wakes `FetchWait` waiters. | | 201 | `Fetch` | Drain and return all queued payloads in FIFO order. | | 202 | `FetchWait` | Same as `Fetch`, but long-polls if the queue is empty (up to `timeout_ms`). | | 203 | `Peek` | Return queued payloads without removing them. | | 204 | `Ack` | Acknowledge and remove specific payloads by sequence number. | | 205 | `BatchEnqueue` | Enqueue multiple payloads in a single RPC call. | ### Keys (300-304) MLS KeyPackage distribution and hybrid PQ public key management. | ID | Method | Description | |-----|--------------------|-------------| | 300 | `UploadKeyPackage` | Append a TLS-encoded MLS KeyPackage to the identity's queue. Single-use: each fetch atomically removes one. | | 301 | `FetchKeyPackage` | Atomically pop and return the oldest KeyPackage for an identity. Returns empty if none. | | 302 | `UploadHybridKey` | Store (or replace) the X25519+ML-KEM-768 hybrid public key for an identity. | | 303 | `FetchHybridKey` | Return the stored hybrid public key for a single identity. | | 304 | `FetchHybridKeys` | Return hybrid public keys for multiple identities in one call. | ### Group Management (400, 410-413) | ID | Method | Description | |-----|-----------------------|-------------| | 400 | `CreateChannel` | Register a new channel (group) on the server. | | 410 | `RemoveMember` | Remove a member from a group (server-side record). | | 411 | `UpdateGroupMetadata` | Update group name, description, or settings. | | 412 | `ListGroupMembers` | List all members of a group. | | 413 | `RotateKeys` | Trigger a server-assisted key rotation event. | ### User / Identity (500-501) | ID | Method | Description | |-----|-------------------|-------------| | 500 | `ResolveUser` | Resolve a username to an Ed25519 public key. | | 501 | `ResolveIdentity` | Resolve an identity key to user profile information. | ### Key Transparency (510-520) | ID | Method | Description | |-----|--------------------------|-------------| | 510 | `RevokeKey` | Append a key revocation record to the transparency log. | | 511 | `CheckRevocation` | Check whether a given key has been revoked. | | 520 | `AuditKeyTransparency` | Fetch a transparency log audit proof for a key. | ### Blob Storage (600-601) | ID | Method | Description | |-----|----------------|-------------| | 600 | `UploadBlob` | Store a binary blob (file attachment, avatar, etc.). Returns a content-addressed blob ID. | | 601 | `DownloadBlob` | Retrieve a blob by ID. | ### Device Management (700-710) | ID | Method | Description | |-----|-----------------------|-------------| | 700 | `RegisterDevice` | Register a new device for a user account. | | 701 | `ListDevices` | List all registered devices for the authenticated user. | | 702 | `RevokeDevice` | Revoke a device, invalidating its session. | | 710 | `RegisterPushToken` | Register a push notification token (APNs / FCM) for a device. | ### Recovery (750-752) | ID | Method | Description | |-----|-------------------------|-------------| | 750 | `StoreRecoveryBundle` | Encrypt and store an account recovery bundle server-side. | | 751 | `FetchRecoveryBundle` | Retrieve the recovery bundle (requires OPAQUE re-authentication). | | 752 | `DeleteRecoveryBundle` | Delete the stored recovery bundle. | ### P2P and Health (800-802) | ID | Method | Description | |-----|--------------------|-------------| | 800 | `PublishEndpoint` | Publish a direct P2P endpoint (iroh node address). | | 801 | `ResolveEndpoint` | Resolve a peer's P2P endpoint by identity key. | | 802 | `Health` | Liveness/readiness probe. Returns server uptime and status. | ### Federation (900-905) | ID | Method | Description | |-----|-------------------------|-------------| | 900 | `RelayEnqueue` | Relay a single message to a user on another server. | | 901 | `RelayBatchEnqueue` | Relay multiple messages in one request. | | 902 | `ProxyFetchKeyPackage` | Fetch a KeyPackage from a remote server on behalf of a local client. | | 903 | `ProxyFetchHybridKey` | Fetch a hybrid public key from a remote server. | | 904 | `ProxyResolveUser` | Resolve a username on a remote server. | | 905 | `FederationHealth` | Check health of the federation link to another server. | ### Moderation (420-424) | ID | Method | Description | |-----|----------------|-------------| | 420 | `ReportMessage` | Submit a content moderation report. | | 421 | `BanUser` | Ban a user from a channel or server-wide. | | 422 | `UnbanUser` | Lift a ban. | | 423 | `ListReports` | List pending moderation reports (admin only). | | 424 | `ListBanned` | List banned users (admin only). | ### Account (950) | ID | Method | Description | |-----|-----------------|-------------| | 950 | `DeleteAccount` | Permanently delete the authenticated account and all associated data. | --- ## Per-Connection Lifecycle Each incoming QUIC connection follows this sequence: ```text Client Server ------ ------ 1. UDP QUIC INITIAL -> 2. <- QUIC HANDSHAKE TLS 1.3 ServerHello + Certificate (self-signed) ALPN: "qpc" 3. Client verifies server cert against pinned CA cert (--ca-cert flag) 4. QUIC connection established 5. Per RPC call: Client opens bidirectional stream Client writes RequestFrame: [method_id: u16][req_id: u32][len: u32][protobuf] Client marks end-of-write 6. Server reads RequestFrame Server dispatches to handler by method_id Handler processes, writes ResponseFrame: [status: u8][req_id: u32][len: u32][protobuf] 7. For push events (server -> client): Server opens uni-stream Server writes PushFrame: [event_type: u16][len: u32][protobuf] 8. Multiple RPCs run concurrently (each on its own stream) ``` ### Concurrency model Unlike the v1 Cap'n Proto RPC (which was `!Send` due to `Rc>` internals and required `LocalSet`), the v2 RPC framework uses `Arc`-based shared state and spawns each handler with `tokio::spawn`. The server can handle many concurrent requests per connection without a `LocalSet`. --- ## Status Codes Response frames carry a `status: u8` field: | Value | Status | Meaning | |-------|------------------|---------| | 0 | `Ok` | Success | | 1 | `BadRequest` | Malformed request or missing required field | | 2 | `Unauthorized` | Missing or invalid session token | | 3 | `Forbidden` | Valid token but insufficient permissions | | 4 | `NotFound` | Requested resource does not exist | | 5 | `RateLimited` | Request rate limit exceeded; retry after backoff | | 8 | `DeadlineExceeded` | Request timed out on the server | | 9 | `Unavailable` | Server temporarily unable to serve the request | | 10 | `Internal` | Unexpected server error | | 11 | `UnknownMethod` | The requested method_id is not registered | --- ## Authentication Flow OPAQUE (RFC-compliant asymmetric PAKE) prevents the password from reaching the server in any form: ```text Client Server | | | OpaqueRegisterStart(100): | | username, registration_request | | --------------------------------->| | | | registration_response | | <---------------------------------| | | | OpaqueRegisterFinish(101): | | username, upload, identity_key | | --------------------------------->| | | | success | | <---------------------------------| | | | OpaqueLoginStart(102): | | username, login_request | | --------------------------------->| | | | login_response | | <---------------------------------| | | | OpaqueLoginFinish(103): | | username, finalization, | | identity_key | | --------------------------------->| | | | session_token | | <---------------------------------| ``` The `session_token` is then passed in subsequent Protobuf requests. The server validates it on every authenticated method call. --- ## Configuration | Flag | Env var | Default | Description | |----------------|----------------------------|------------------------|-------------| | `--listen` | `QPC_LISTEN` | `0.0.0.0:5001` | QUIC listen address (host:port). | | `--data-dir` | `QPC_DATA_DIR` | `data` | Directory for persisted state. | | `--tls-cert` | `QPC_TLS_CERT` | `data/server-cert.der` | Path to TLS certificate (DER). Auto-generated if missing. | | `--tls-key` | `QPC_TLS_KEY` | `data/server-key.der` | Path to TLS private key (DER). Auto-generated if missing. | Logging level is controlled by the `RUST_LOG` environment variable (default: `info`). --- ## Further Reading - [Architecture Overview](overview.md) -- two-service model and system diagram - [End-to-End Data Flow](data-flow.md) -- sequence diagrams for registration, group creation, and messaging - [Protobuf Framing](../protocol-layers/capn-proto.md) -- frame format details and method ID constants - [Wire Format Reference](../wire-format/overview.md) -- full Protobuf schema documentation