# 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<RefCell<>>`
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
