chore: rename project quicnprotochat -> quicproquo (binaries: qpq)
Rename the entire workspace:
- Crate packages: quicnprotochat-{core,proto,server,client,gui,p2p,mobile} -> quicproquo-*
- Binary names: quicnprotochat -> qpq, quicnprotochat-server -> qpq-server,
quicnprotochat-gui -> qpq-gui
- Default files: *-state.bin -> qpq-state.bin, *-server.toml -> qpq-server.toml,
*.db -> qpq.db
- Environment variable prefix: QUICNPROTOCHAT_* -> QPQ_*
- App identifier: chat.quicnproto.gui -> chat.quicproquo.gui
- Proto package: quicnprotochat.bench -> quicproquo.bench
- All documentation, Docker, CI, and script references updated
HKDF domain-separation strings and P2P ALPN remain unchanged for
backward compatibility with existing encrypted state and wire protocol.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -16,10 +16,10 @@ This compiles all four crates:
|
||||
|
||||
| Crate | Type | Purpose |
|
||||
|---|---|---|
|
||||
| `quicnprotochat-core` | library | Crypto primitives, MLS `GroupMember` state machine, hybrid KEM |
|
||||
| `quicnprotochat-proto` | library | Cap'n Proto schemas, generated types, envelope serialisation helpers |
|
||||
| `quicnprotochat-server` | binary | Unified Authentication + Delivery Service (`NodeService`) |
|
||||
| `quicnprotochat-client` | binary | CLI client with subcommands (`ping`, `register`, `send`, `recv`, etc.) |
|
||||
| `quicproquo-core` | library | Crypto primitives, MLS `GroupMember` state machine, hybrid KEM |
|
||||
| `quicproquo-proto` | library | Cap'n Proto schemas, generated types, envelope serialisation helpers |
|
||||
| `quicproquo-server` | binary | Unified Authentication + Delivery Service (`NodeService`) |
|
||||
| `quicproquo-client` | binary | CLI client with subcommands (`ping`, `register`, `send`, `recv`, etc.) |
|
||||
|
||||
For a release build with LTO, symbol stripping, and single codegen unit:
|
||||
|
||||
@@ -47,25 +47,25 @@ cargo test --workspace
|
||||
|
||||
The test suite includes:
|
||||
|
||||
- **`quicnprotochat-proto`**: Round-trip serialisation tests for Cap'n Proto `Envelope` messages (Ping, Pong, corrupted-input error handling).
|
||||
- **`quicnprotochat-core`**: Two-party MLS round-trip (`create_group` / `add_member` / `send_message` / `receive_message`), group ID lifecycle assertions.
|
||||
- **`quicnprotochat-client`**: Integration tests for MLS group operations and auth service interactions (require a running server or use in-process mocks).
|
||||
- **`quicproquo-proto`**: Round-trip serialisation tests for Cap'n Proto `Envelope` messages (Ping, Pong, corrupted-input error handling).
|
||||
- **`quicproquo-core`**: Two-party MLS round-trip (`create_group` / `add_member` / `send_message` / `receive_message`), group ID lifecycle assertions.
|
||||
- **`quicproquo-client`**: Integration tests for MLS group operations and auth service interactions (require a running server or use in-process mocks).
|
||||
|
||||
To run tests for a single crate:
|
||||
|
||||
```bash
|
||||
cargo test -p quicnprotochat-core
|
||||
cargo test -p quicproquo-core
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Cap'n Proto code generation
|
||||
|
||||
The `quicnprotochat-proto` crate does not contain hand-written Rust types for wire messages. Instead, its `build.rs` script invokes the `capnp` compiler at build time to generate Rust source from the `.capnp` schema files.
|
||||
The `quicproquo-proto` crate does not contain hand-written Rust types for wire messages. Instead, its `build.rs` script invokes the `capnp` compiler at build time to generate Rust source from the `.capnp` schema files.
|
||||
|
||||
### How it works
|
||||
|
||||
1. `build.rs` locates the workspace-root `schemas/` directory (two levels above `crates/quicnprotochat-proto/`).
|
||||
1. `build.rs` locates the workspace-root `schemas/` directory (two levels above `crates/quicproquo-proto/`).
|
||||
2. It invokes `capnpc::CompilerCommand` on all four schema files:
|
||||
- `schemas/envelope.capnp` -- top-level wire envelope with `MsgType` discriminant
|
||||
- `schemas/auth.capnp` -- `AuthenticationService` RPC interface
|
||||
@@ -82,7 +82,7 @@ The `build.rs` script emits `cargo:rerun-if-changed` directives for each schema
|
||||
|
||||
The `src_prefix` is set to the `schemas/` directory so that inter-schema imports (e.g., `using Auth = import "auth.capnp".Auth;` inside `node.capnp`) resolve correctly.
|
||||
|
||||
### Design constraints of quicnprotochat-proto
|
||||
### Design constraints of quicproquo-proto
|
||||
|
||||
The proto crate is intentionally restricted:
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Certificate lifecycle and CA-signed TLS
|
||||
|
||||
This page describes how to use CA-issued certificates with quicnprotochat and how to think about certificate pinning, rotation, and lifecycle.
|
||||
This page describes how to use CA-issued certificates with quicproquo and how to think about certificate pinning, rotation, and lifecycle.
|
||||
|
||||
For basic server TLS setup (self-signed certs, generation), see [Running the Server](running-the-server.md#tls-certificate-handling).
|
||||
|
||||
@@ -8,8 +8,8 @@ For basic server TLS setup (self-signed certs, generation), see [Running the Ser
|
||||
|
||||
## Current behaviour
|
||||
|
||||
- **Server:** Uses a single TLS certificate and private key (DER format). If the files are missing and the server is not in production mode, it generates a self-signed certificate. Production mode (`QUICNPROTOCHAT_PRODUCTION=1`) requires existing cert and key files.
|
||||
- **Client:** Trusts exactly the roots in the file given by `--ca-cert` (or `QUICNPROTOCHAT_CA_CERT`). Typically this is the server's own certificate (pinning) or a CA that signed the server cert.
|
||||
- **Server:** Uses a single TLS certificate and private key (DER format). If the files are missing and the server is not in production mode, it generates a self-signed certificate. Production mode (`QPQ_PRODUCTION=1`) requires existing cert and key files.
|
||||
- **Client:** Trusts exactly the roots in the file given by `--ca-cert` (or `QPQ_CA_CERT`). Typically this is the server's own certificate (pinning) or a CA that signed the server cert.
|
||||
|
||||
---
|
||||
|
||||
@@ -20,7 +20,7 @@ To pin the server so the client only connects to that server:
|
||||
1. Copy the server's certificate file (e.g. `data/server-cert.der`) from the server (or your deployment).
|
||||
2. Use that file as the client's CA cert:
|
||||
```bash
|
||||
quicnprotochat --ca-cert /path/to/server-cert.der ...
|
||||
qpq --ca-cert /path/to/server-cert.der ...
|
||||
```
|
||||
3. The client will only accept a connection if the server presents that exact certificate (or a chain ending in it). No separate CA bundle is required.
|
||||
|
||||
@@ -43,12 +43,12 @@ To use a certificate issued by a public CA (e.g. Let's Encrypt):
|
||||
```
|
||||
2. **Configure the server** to use those paths:
|
||||
```bash
|
||||
export QUICNPROTOCHAT_TLS_CERT=/etc/quicnprotochat/server-cert.der
|
||||
export QUICNPROTOCHAT_TLS_KEY=/etc/quicnprotochat/server-key.der
|
||||
export QPQ_TLS_CERT=/etc/quicproquo/server-cert.der
|
||||
export QPQ_TLS_KEY=/etc/quicproquo/server-key.der
|
||||
```
|
||||
3. **Configure the client** to trust the CA that signed the server cert. Use the CA’s certificate (or the CA bundle) as `--ca-cert`:
|
||||
```bash
|
||||
quicnprotochat --ca-cert /etc/ssl/certs/your-ca.der --server-name your.server.example ...
|
||||
qpq --ca-cert /etc/ssl/certs/your-ca.der --server-name your.server.example ...
|
||||
```
|
||||
The `--server-name` must match the certificate’s SAN (e.g. DNS name).
|
||||
|
||||
@@ -60,7 +60,7 @@ To use a certificate issued by a public CA (e.g. Let's Encrypt):
|
||||
|
||||
- **Manual rotation:** Replace `server-cert.der` and `server-key.der` on disk, then restart the server. Clients that pin the new cert must be updated with the new cert file.
|
||||
- **Let’s Encrypt renewal:** After renewing (e.g. via certbot), convert the new cert and key to DER, replace the files, and restart the server. If clients use the CA cert (e.g. ISRG Root X1) as `--ca-cert`, they do not need updates when the server cert is renewed.
|
||||
- **OCSP / CRL:** The quicnprotochat server does not currently perform OCSP stapling or CRL checks. Revocation is handled by the client or by operational procedures (e.g. short-lived certs, rotation on compromise).
|
||||
- **OCSP / CRL:** The quicproquo server does not currently perform OCSP stapling or CRL checks. Revocation is handled by the client or by operational procedures (e.g. short-lived certs, rotation on compromise).
|
||||
|
||||
---
|
||||
|
||||
@@ -70,6 +70,6 @@ To use a certificate issued by a public CA (e.g. Let's Encrypt):
|
||||
|------------------|-------------|--------------------|
|
||||
| Pinned (single server) | Self-signed or any | Server’s cert file |
|
||||
| CA-issued | Let’s Encrypt (or other CA) | CA cert (or bundle) |
|
||||
| Production | Always use existing cert/key; set `QUICNPROTOCHAT_PRODUCTION=1` | CA or pinned server cert |
|
||||
| Production | Always use existing cert/key; set `QPQ_PRODUCTION=1` | CA or pinned server cert |
|
||||
|
||||
For production, prefer either (a) certificate pinning with the server’s cert or (b) a CA-issued server cert with clients trusting the CA, and plan for rotation and restart (or future reload support).
|
||||
|
||||
@@ -75,13 +75,13 @@ You will need **three terminal windows**: one for the server, one for Alice, and
|
||||
In **Terminal 1** (Server):
|
||||
|
||||
```bash
|
||||
cargo run -p quicnprotochat-server
|
||||
cargo run -p quicproquo-server
|
||||
```
|
||||
|
||||
Wait for the log line confirming it is accepting connections:
|
||||
|
||||
```
|
||||
INFO quicnprotochat_server: accepting QUIC connections addr="0.0.0.0:7000"
|
||||
INFO quicproquo_server: accepting QUIC connections addr="0.0.0.0:7000"
|
||||
```
|
||||
|
||||
If this is the first run, you will also see a log line about generating the self-signed TLS certificate. The certificate is written to `data/server-cert.der`, which the client will use for TLS verification.
|
||||
@@ -91,7 +91,7 @@ If this is the first run, you will also see a log line about generating the self
|
||||
In **Terminal 2** (Alice):
|
||||
|
||||
```bash
|
||||
cargo run -p quicnprotochat-client -- register-state \
|
||||
cargo run -p quicproquo-client -- register-state \
|
||||
--state alice.bin \
|
||||
--server 127.0.0.1:7000
|
||||
```
|
||||
@@ -116,7 +116,7 @@ KeyPackage uploaded successfully.
|
||||
In **Terminal 3** (Bob):
|
||||
|
||||
```bash
|
||||
cargo run -p quicnprotochat-client -- register-state \
|
||||
cargo run -p quicproquo-client -- register-state \
|
||||
--state bob.bin \
|
||||
--server 127.0.0.1:7000
|
||||
```
|
||||
@@ -137,7 +137,7 @@ In **Terminal 2** (Alice):
|
||||
First, create the group:
|
||||
|
||||
```bash
|
||||
cargo run -p quicnprotochat-client -- create-group \
|
||||
cargo run -p quicproquo-client -- create-group \
|
||||
--state alice.bin \
|
||||
--group-id "demo-chat"
|
||||
```
|
||||
@@ -151,7 +151,7 @@ Alice is now the sole member of the group at epoch 0.
|
||||
Next, invite Bob using his identity key from Step 3:
|
||||
|
||||
```bash
|
||||
cargo run -p quicnprotochat-client -- invite \
|
||||
cargo run -p quicproquo-client -- invite \
|
||||
--state alice.bin \
|
||||
--peer-key <BOB_KEY> \
|
||||
--server 127.0.0.1:7000
|
||||
@@ -173,7 +173,7 @@ Alice's group state has now advanced to epoch 1.
|
||||
In **Terminal 3** (Bob):
|
||||
|
||||
```bash
|
||||
cargo run -p quicnprotochat-client -- join \
|
||||
cargo run -p quicproquo-client -- join \
|
||||
--state bob.bin \
|
||||
--server 127.0.0.1:7000
|
||||
```
|
||||
@@ -195,7 +195,7 @@ Bob is now a member of the group at epoch 1, sharing the same group secret as Al
|
||||
In **Terminal 2** (Alice):
|
||||
|
||||
```bash
|
||||
cargo run -p quicnprotochat-client -- send \
|
||||
cargo run -p quicproquo-client -- send \
|
||||
--state alice.bin \
|
||||
--peer-key <BOB_KEY> \
|
||||
--msg "Hello Bob, this is encrypted with MLS!" \
|
||||
@@ -215,7 +215,7 @@ message sent
|
||||
In **Terminal 3** (Bob):
|
||||
|
||||
```bash
|
||||
cargo run -p quicnprotochat-client -- recv \
|
||||
cargo run -p quicproquo-client -- recv \
|
||||
--state bob.bin \
|
||||
--server 127.0.0.1:7000
|
||||
```
|
||||
@@ -233,7 +233,7 @@ This command:
|
||||
In **Terminal 3** (Bob):
|
||||
|
||||
```bash
|
||||
cargo run -p quicnprotochat-client -- send \
|
||||
cargo run -p quicproquo-client -- send \
|
||||
--state bob.bin \
|
||||
--peer-key <ALICE_KEY> \
|
||||
--msg "Hi Alice, received loud and clear!" \
|
||||
@@ -249,7 +249,7 @@ message sent
|
||||
In **Terminal 2** (Alice):
|
||||
|
||||
```bash
|
||||
cargo run -p quicnprotochat-client -- recv \
|
||||
cargo run -p quicproquo-client -- recv \
|
||||
--state alice.bin \
|
||||
--server 127.0.0.1:7000
|
||||
```
|
||||
@@ -266,7 +266,7 @@ If you want to see the entire flow in a single command without managing three te
|
||||
|
||||
```bash
|
||||
# Ensure the server is running, then:
|
||||
cargo run -p quicnprotochat-client -- demo-group --server 127.0.0.1:7000
|
||||
cargo run -p quicproquo-client -- demo-group --server 127.0.0.1:7000
|
||||
```
|
||||
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Docker Deployment
|
||||
|
||||
quicnprotochat includes a multi-stage Dockerfile and a Docker Compose configuration for building and running the server in containers.
|
||||
quicproquo includes a multi-stage Dockerfile and a Docker Compose configuration for building and running the server in containers.
|
||||
|
||||
---
|
||||
|
||||
@@ -40,7 +40,7 @@ services:
|
||||
- "7000:7000"
|
||||
environment:
|
||||
RUST_LOG: "info"
|
||||
QUICNPROTOCHAT_LISTEN: "0.0.0.0:7000"
|
||||
QPQ_LISTEN: "0.0.0.0:7000"
|
||||
healthcheck:
|
||||
test: ["CMD", "bash", "-c", "echo '' > /dev/tcp/localhost/7000"]
|
||||
interval: 5s
|
||||
@@ -81,9 +81,9 @@ RUN apt-get update \
|
||||
Key steps:
|
||||
|
||||
1. **Base image**: `rust:bookworm` (Debian Bookworm with the Rust toolchain pre-installed).
|
||||
2. **Install `capnproto`**: Required by `quicnprotochat-proto/build.rs` to compile `.capnp` schemas at build time.
|
||||
2. **Install `capnproto`**: Required by `quicproquo-proto/build.rs` to compile `.capnp` schemas at build time.
|
||||
3. **Copy manifests first**: `Cargo.toml` and `Cargo.lock` are copied before source code. Dummy `main.rs` / `lib.rs` stubs are created so that `cargo build` can resolve and cache the dependency graph. This ensures that dependency compilation is cached in a separate Docker layer -- subsequent builds that only change source code skip the dependency compilation step entirely.
|
||||
4. **Copy schemas**: The `schemas/` directory is copied before the dependency build because `quicnprotochat-proto/build.rs` requires the `.capnp` files during compilation.
|
||||
4. **Copy schemas**: The `schemas/` directory is copied before the dependency build because `quicproquo-proto/build.rs` requires the `.capnp` files during compilation.
|
||||
5. **Copy real source and build**: After the dependency cache layer, real source files are copied in and `cargo build --release` is run.
|
||||
|
||||
### Stage 2: Runtime (`debian:bookworm-slim`)
|
||||
@@ -95,16 +95,16 @@ RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends ca-certificates \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY --from=builder /build/target/release/quicnprotochat-server /usr/local/bin/quicnprotochat-server
|
||||
COPY --from=builder /build/target/release/qpq-server /usr/local/bin/qpq-server
|
||||
|
||||
EXPOSE 7000
|
||||
|
||||
ENV RUST_LOG=info \
|
||||
QUICNPROTOCHAT_LISTEN=0.0.0.0:7000
|
||||
QPQ_LISTEN=0.0.0.0:7000
|
||||
|
||||
USER nobody
|
||||
|
||||
CMD ["quicnprotochat-server"]
|
||||
CMD ["qpq-server"]
|
||||
```
|
||||
|
||||
Key characteristics:
|
||||
@@ -112,9 +112,9 @@ Key characteristics:
|
||||
- **Minimal image**: No Rust toolchain, no `capnp` compiler, no build artifacts.
|
||||
- **`ca-certificates`**: Included for future HTTPS calls (e.g., ACME certificate provisioning or key sync endpoints).
|
||||
- **Non-root execution**: The container runs as `nobody` for defense in depth.
|
||||
- **Default port**: The Dockerfile defaults to port `7000` via `QUICNPROTOCHAT_LISTEN`, but the `docker-compose.yml` overrides this to `7000` for consistency with the development workflow.
|
||||
- **Default port**: The Dockerfile defaults to port `7000` via `QPQ_LISTEN`, but the `docker-compose.yml` overrides this to `7000` for consistency with the development workflow.
|
||||
|
||||
> **Note**: The `EXPOSE 7000` directive in the Dockerfile and the `QUICNPROTOCHAT_LISTEN=0.0.0.0:7000` override in `docker-compose.yml` mean the effective listen port is `7000` when using Compose. If you run the Docker image directly without Compose, the server will listen on `7000` by default.
|
||||
> **Note**: The `EXPOSE 7000` directive in the Dockerfile and the `QPQ_LISTEN=0.0.0.0:7000` override in `docker-compose.yml` mean the effective listen port is `7000` when using Compose. If you run the Docker image directly without Compose, the server will listen on `7000` by default.
|
||||
|
||||
---
|
||||
|
||||
@@ -129,7 +129,7 @@ services:
|
||||
volumes:
|
||||
- server-data:/data
|
||||
environment:
|
||||
QUICNPROTOCHAT_DATA_DIR: "/data"
|
||||
QPQ_DATA_DIR: "/data"
|
||||
|
||||
volumes:
|
||||
server-data:
|
||||
@@ -140,7 +140,7 @@ Or use a bind mount for easier inspection:
|
||||
```bash
|
||||
docker compose run \
|
||||
-v $(pwd)/server-data:/data \
|
||||
-e QUICNPROTOCHAT_DATA_DIR=/data \
|
||||
-e QPQ_DATA_DIR=/data \
|
||||
server
|
||||
```
|
||||
|
||||
@@ -153,18 +153,18 @@ Without a volume, all server state (including TLS certificates and message queue
|
||||
To build the Docker image without starting a container:
|
||||
|
||||
```bash
|
||||
docker build -t quicnprotochat-server -f docker/Dockerfile .
|
||||
docker build -t qpq-server -f docker/Dockerfile .
|
||||
```
|
||||
|
||||
To run it manually:
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
--name quicnprotochat \
|
||||
--name quicproquo \
|
||||
-p 7000:7000/udp \
|
||||
-e QUICNPROTOCHAT_LISTEN=0.0.0.0:7000 \
|
||||
-e QPQ_LISTEN=0.0.0.0:7000 \
|
||||
-e RUST_LOG=info \
|
||||
quicnprotochat-server
|
||||
qpq-server
|
||||
```
|
||||
|
||||
Note the `/udp` suffix on the port mapping -- QUIC runs over UDP.
|
||||
@@ -180,7 +180,7 @@ When the server runs in Docker with `docker compose up`, the client can connect
|
||||
docker compose cp server:/data/server-cert.der ./data/server-cert.der
|
||||
|
||||
# Connect
|
||||
cargo run -p quicnprotochat-client -- ping \
|
||||
cargo run -p quicproquo-client -- ping \
|
||||
--ca-cert ./data/server-cert.der \
|
||||
--server-name localhost
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Prerequisites
|
||||
|
||||
Before building quicnprotochat you need a Rust toolchain and the Cap'n Proto schema compiler. Docker is optional but useful for reproducible builds and deployment.
|
||||
Before building quicproquo you need a Rust toolchain and the Cap'n Proto schema compiler. Docker is optional but useful for reproducible builds and deployment.
|
||||
|
||||
---
|
||||
|
||||
@@ -8,7 +8,7 @@ Before building quicnprotochat you need a Rust toolchain and the Cap'n Proto sch
|
||||
|
||||
**Minimum supported Rust version: 1.77+ (stable)**
|
||||
|
||||
quicnprotochat uses the 2021 edition and workspace resolver v2. Any stable Rust release from 1.77 onward should work. Install or update via [rustup](https://rustup.rs/):
|
||||
quicproquo uses the 2021 edition and workspace resolver v2. Any stable Rust release from 1.77 onward should work. Install or update via [rustup](https://rustup.rs/):
|
||||
|
||||
```bash
|
||||
# Install rustup (if not already present)
|
||||
@@ -29,7 +29,7 @@ The workspace depends on several crates that use procedural macros (`serde_deriv
|
||||
|
||||
## Cap'n Proto compiler (`capnp`)
|
||||
|
||||
The `quicnprotochat-proto` crate runs a `build.rs` script that invokes the `capnp` binary at compile time to generate Rust types from the `.capnp` schema files in `schemas/`. The `capnp` binary must be on your `PATH`.
|
||||
The `quicproquo-proto` crate runs a `build.rs` script that invokes the `capnp` binary at compile time to generate Rust types from the `.capnp` schema files in `schemas/`. The `capnp` binary must be on your `PATH`.
|
||||
|
||||
### Debian / Ubuntu
|
||||
|
||||
@@ -74,7 +74,7 @@ See [Building from Source -- Troubleshooting](building.md#troubleshooting) for m
|
||||
|
||||
## Optional: Docker and Docker Compose
|
||||
|
||||
If you prefer to build and run quicnprotochat in containers, you will need:
|
||||
If you prefer to build and run quicproquo in containers, you will need:
|
||||
|
||||
- **Docker Engine** 20.10+ (or Docker Desktop)
|
||||
- **Docker Compose** v2+ (the `docker compose` plugin, not the legacy `docker-compose` binary)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Running the Client
|
||||
|
||||
The quicnprotochat CLI client provides subcommands for connectivity testing, identity registration, KeyPackage exchange, and persistent group messaging. All commands connect to the server over QUIC + TLS 1.3 and issue Cap'n Proto RPC calls against the `NodeService` endpoint.
|
||||
The quicproquo CLI client provides subcommands for connectivity testing, identity registration, KeyPackage exchange, and persistent group messaging. All commands connect to the server over QUIC + TLS 1.3 and issue Cap'n Proto RPC calls against the `NodeService` endpoint.
|
||||
|
||||
---
|
||||
|
||||
@@ -10,8 +10,8 @@ These flags apply to every subcommand:
|
||||
|
||||
| Flag | Env var | Default | Purpose |
|
||||
|---|---|---|---|
|
||||
| `--ca-cert` | `QUICNPROTOCHAT_CA_CERT` | `data/server-cert.der` | Path to the server's TLS certificate (DER format). The client uses this to verify the server's identity during the TLS handshake. |
|
||||
| `--server-name` | `QUICNPROTOCHAT_SERVER_NAME` | `localhost` | Expected TLS server name. Must match a SAN in the server's certificate. |
|
||||
| `--ca-cert` | `QPQ_CA_CERT` | `data/server-cert.der` | Path to the server's TLS certificate (DER format). The client uses this to verify the server's identity during the TLS handshake. |
|
||||
| `--server-name` | `QPQ_SERVER_NAME` | `localhost` | Expected TLS server name. Must match a SAN in the server's certificate. |
|
||||
|
||||
Most subcommands also accept `--server` (default `127.0.0.1:7000`) to specify the server address.
|
||||
|
||||
@@ -24,11 +24,11 @@ Most subcommands also accept `--server` (default `127.0.0.1:7000`) to specify th
|
||||
Send a health probe to the server and print the round-trip time.
|
||||
|
||||
```bash
|
||||
cargo run -p quicnprotochat-client -- ping
|
||||
cargo run -p quicproquo-client -- ping
|
||||
```
|
||||
|
||||
```bash
|
||||
cargo run -p quicnprotochat-client -- ping --server 192.168.1.10:7000
|
||||
cargo run -p quicproquo-client -- ping --server 192.168.1.10:7000
|
||||
```
|
||||
|
||||
**Output:**
|
||||
@@ -49,7 +49,7 @@ These commands generate a fresh identity keypair in memory each time they run. T
|
||||
Generate a fresh Ed25519 identity, create an MLS KeyPackage, and upload it to the Authentication Service.
|
||||
|
||||
```bash
|
||||
cargo run -p quicnprotochat-client -- register
|
||||
cargo run -p quicproquo-client -- register
|
||||
```
|
||||
|
||||
**Output:**
|
||||
@@ -66,7 +66,7 @@ Share the `identity_key` value with peers who want to add you to a group. They w
|
||||
Fetch a peer's KeyPackage from the Authentication Service by their Ed25519 public key.
|
||||
|
||||
```bash
|
||||
cargo run -p quicnprotochat-client -- fetch-key a1b2c3d4e5f6...
|
||||
cargo run -p quicproquo-client -- fetch-key a1b2c3d4e5f6...
|
||||
```
|
||||
|
||||
The `identity_key` argument must be exactly 64 lowercase hex characters (32 bytes).
|
||||
@@ -90,7 +90,7 @@ KeyPackages are single-use: fetching a KeyPackage atomically removes it from the
|
||||
Run a complete Alice-and-Bob MLS round-trip against a live server. Both identities are created in-process; both communicate through the server's AS and DS.
|
||||
|
||||
```bash
|
||||
cargo run -p quicnprotochat-client -- demo-group --server 127.0.0.1:7000
|
||||
cargo run -p quicproquo-client -- demo-group --server 127.0.0.1:7000
|
||||
```
|
||||
|
||||
**Output:**
|
||||
@@ -106,21 +106,21 @@ This is the fastest way to verify that the entire stack (QUIC + TLS + Cap'n Prot
|
||||
|
||||
## Persistent group commands
|
||||
|
||||
These commands use a state file (`--state`, default `quicnprotochat-state.bin`) to persist the Ed25519 identity seed and MLS group state between invocations. A companion key store file (same path with `.ks` extension) holds HPKE init private keys.
|
||||
These commands use a state file (`--state`, default `qpq-state.bin`) to persist the Ed25519 identity seed and MLS group state between invocations. A companion key store file (same path with `.ks` extension) holds HPKE init private keys.
|
||||
|
||||
All persistent commands share the `--state` flag:
|
||||
|
||||
| Flag | Env var | Default |
|
||||
|---|---|---|
|
||||
| `--state` | `QUICNPROTOCHAT_STATE` | `quicnprotochat-state.bin` |
|
||||
| `--server` | `QUICNPROTOCHAT_SERVER` | `127.0.0.1:7000` |
|
||||
| `--state` | `QPQ_STATE` | `qpq-state.bin` |
|
||||
| `--server` | `QPQ_SERVER` | `127.0.0.1:7000` |
|
||||
|
||||
### `register-state`
|
||||
|
||||
Create or load a persistent identity, generate a KeyPackage, and upload it to the AS.
|
||||
|
||||
```bash
|
||||
cargo run -p quicnprotochat-client -- register-state \
|
||||
cargo run -p quicproquo-client -- register-state \
|
||||
--state alice.bin \
|
||||
--server 127.0.0.1:7000
|
||||
```
|
||||
@@ -141,10 +141,10 @@ Refresh the KeyPackage on the server using your **existing** state file. Does no
|
||||
- Your KeyPackage has expired (server TTL, e.g. 24h).
|
||||
- Your KeyPackage was consumed (someone invited you) and you want to be invitable again.
|
||||
|
||||
Run with the same `--access-token` (or `QUICNPROTOCHAT_ACCESS_TOKEN`) as for other commands.
|
||||
Run with the same `--access-token` (or `QPQ_ACCESS_TOKEN`) as for other commands.
|
||||
|
||||
```bash
|
||||
cargo run -p quicnprotochat-client -- refresh-keypackage \
|
||||
cargo run -p quicproquo-client -- refresh-keypackage \
|
||||
--state alice.bin \
|
||||
--server 127.0.0.1:7000
|
||||
```
|
||||
@@ -163,7 +163,7 @@ If you are told "no key" when someone tries to invite you, have them wait and ru
|
||||
Create a new MLS group. The caller becomes the sole member at epoch 0.
|
||||
|
||||
```bash
|
||||
cargo run -p quicnprotochat-client -- create-group \
|
||||
cargo run -p quicproquo-client -- create-group \
|
||||
--state alice.bin \
|
||||
--group-id "project-chat"
|
||||
```
|
||||
@@ -180,7 +180,7 @@ The group state is saved to the state file. You can now invite peers with `invit
|
||||
Fetch a peer's KeyPackage from the AS, add them to the group, and deliver the Welcome message via the DS.
|
||||
|
||||
```bash
|
||||
cargo run -p quicnprotochat-client -- invite \
|
||||
cargo run -p quicproquo-client -- invite \
|
||||
--state alice.bin \
|
||||
--peer-key b9a8c7d6e5f4... \
|
||||
--server 127.0.0.1:7000
|
||||
@@ -202,7 +202,7 @@ invited peer (welcome queued)
|
||||
Join a group by consuming a Welcome message from the DS.
|
||||
|
||||
```bash
|
||||
cargo run -p quicnprotochat-client -- join \
|
||||
cargo run -p quicproquo-client -- join \
|
||||
--state bob.bin \
|
||||
--server 127.0.0.1:7000
|
||||
```
|
||||
@@ -219,7 +219,7 @@ joined group successfully
|
||||
Encrypt and send an application message to a peer via the DS.
|
||||
|
||||
```bash
|
||||
cargo run -p quicnprotochat-client -- send \
|
||||
cargo run -p quicproquo-client -- send \
|
||||
--state alice.bin \
|
||||
--peer-key b9a8c7d6e5f4... \
|
||||
--msg "hello from alice" \
|
||||
@@ -238,7 +238,7 @@ message sent
|
||||
Receive and decrypt all pending messages from the DS.
|
||||
|
||||
```bash
|
||||
cargo run -p quicnprotochat-client -- recv \
|
||||
cargo run -p quicproquo-client -- recv \
|
||||
--state bob.bin \
|
||||
--server 127.0.0.1:7000
|
||||
```
|
||||
@@ -257,12 +257,12 @@ Additional flags:
|
||||
|
||||
```bash
|
||||
# Wait up to 5 seconds for messages
|
||||
cargo run -p quicnprotochat-client -- recv \
|
||||
cargo run -p quicproquo-client -- recv \
|
||||
--state bob.bin \
|
||||
--wait-ms 5000
|
||||
|
||||
# Stream messages continuously
|
||||
cargo run -p quicnprotochat-client -- recv \
|
||||
cargo run -p quicproquo-client -- recv \
|
||||
--state bob.bin \
|
||||
--stream --wait-ms 10000
|
||||
```
|
||||
@@ -271,7 +271,7 @@ cargo run -p quicnprotochat-client -- recv \
|
||||
|
||||
## HPKE init key lifecycle warning
|
||||
|
||||
The MLS protocol requires that the HPKE init private key generated during KeyPackage creation is available when processing the corresponding Welcome message. In quicnprotochat, this private key is stored in the key store file (`.ks` extension alongside the state file).
|
||||
The MLS protocol requires that the HPKE init private key generated during KeyPackage creation is available when processing the corresponding Welcome message. In quicproquo, this private key is stored in the key store file (`.ks` extension alongside the state file).
|
||||
|
||||
**The same state file and key store must be used for both `register-state` and `join`.** If you:
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# Running the Server
|
||||
|
||||
The quicnprotochat server is a single binary (`quicnprotochat-server`) that exposes a unified **NodeService** endpoint combining Authentication Service (KeyPackage management) and Delivery Service (message relay) operations over a single QUIC + TLS 1.3 connection.
|
||||
The quicproquo server is a single binary (`qpq-server`) that exposes a unified **NodeService** endpoint combining Authentication Service (KeyPackage management) and Delivery Service (message relay) operations over a single QUIC + TLS 1.3 connection.
|
||||
|
||||
---
|
||||
|
||||
## Quick start
|
||||
|
||||
```bash
|
||||
cargo run -p quicnprotochat-server
|
||||
cargo run -p quicproquo-server
|
||||
```
|
||||
|
||||
On first launch the server will:
|
||||
@@ -20,8 +20,8 @@ On first launch the server will:
|
||||
You should see output similar to:
|
||||
|
||||
```
|
||||
2025-01-01T00:00:00.000000Z INFO quicnprotochat_server: generated self-signed TLS certificate cert="data/server-cert.der" key="data/server-key.der"
|
||||
2025-01-01T00:00:00.000000Z INFO quicnprotochat_server: accepting QUIC connections addr="0.0.0.0:7000"
|
||||
2025-01-01T00:00:00.000000Z INFO quicproquo_server: generated self-signed TLS certificate cert="data/server-cert.der" key="data/server-key.der"
|
||||
2025-01-01T00:00:00.000000Z INFO quicproquo_server: accepting QUIC connections addr="0.0.0.0:7000"
|
||||
```
|
||||
|
||||
---
|
||||
@@ -32,36 +32,36 @@ All configuration is available via CLI flags and environment variables. Environm
|
||||
|
||||
| Purpose | CLI flag | Env var | Default |
|
||||
|---|---|---|---|
|
||||
| QUIC listen address | `--listen` | `QUICNPROTOCHAT_LISTEN` | `0.0.0.0:7000` |
|
||||
| TLS certificate (DER) | `--tls-cert` | `QUICNPROTOCHAT_TLS_CERT` | `data/server-cert.der` |
|
||||
| TLS private key (DER) | `--tls-key` | `QUICNPROTOCHAT_TLS_KEY` | `data/server-key.der` |
|
||||
| Data directory | `--data-dir` | `QUICNPROTOCHAT_DATA_DIR` | `data` |
|
||||
| QUIC listen address | `--listen` | `QPQ_LISTEN` | `0.0.0.0:7000` |
|
||||
| TLS certificate (DER) | `--tls-cert` | `QPQ_TLS_CERT` | `data/server-cert.der` |
|
||||
| TLS private key (DER) | `--tls-key` | `QPQ_TLS_KEY` | `data/server-key.der` |
|
||||
| Data directory | `--data-dir` | `QPQ_DATA_DIR` | `data` |
|
||||
| Log level | -- | `RUST_LOG` | `info` |
|
||||
|
||||
### Examples
|
||||
|
||||
```bash
|
||||
# Listen on a custom port
|
||||
cargo run -p quicnprotochat-server -- --listen 0.0.0.0:9000
|
||||
cargo run -p quicproquo-server -- --listen 0.0.0.0:9000
|
||||
|
||||
# Use pre-existing TLS credentials
|
||||
cargo run -p quicnprotochat-server -- \
|
||||
--tls-cert /etc/quicnprotochat/cert.der \
|
||||
--tls-key /etc/quicnprotochat/key.der
|
||||
cargo run -p quicproquo-server -- \
|
||||
--tls-cert /etc/quicproquo/cert.der \
|
||||
--tls-key /etc/quicproquo/key.der
|
||||
|
||||
# Via environment variables
|
||||
QUICNPROTOCHAT_LISTEN=0.0.0.0:9000 \
|
||||
QPQ_LISTEN=0.0.0.0:9000 \
|
||||
RUST_LOG=debug \
|
||||
cargo run -p quicnprotochat-server
|
||||
cargo run -p quicproquo-server
|
||||
```
|
||||
|
||||
### Production deployment
|
||||
|
||||
Set `QUICNPROTOCHAT_PRODUCTION=1` (or `true` / `yes`) so the server enforces production checks:
|
||||
Set `QPQ_PRODUCTION=1` (or `true` / `yes`) so the server enforces production checks:
|
||||
|
||||
- **Auth:** A non-empty `QUICNPROTOCHAT_AUTH_TOKEN` is required; the value `devtoken` is rejected.
|
||||
- **Auth:** A non-empty `QPQ_AUTH_TOKEN` is required; the value `devtoken` is rejected.
|
||||
- **TLS:** Existing cert and key files are required (auto-generation is disabled).
|
||||
- **SQL store:** When `--store-backend=sql`, a non-empty `QUICNPROTOCHAT_DB_KEY` is required. An empty key leaves the database unencrypted on disk and is not acceptable for production.
|
||||
- **SQL store:** When `--store-backend=sql`, a non-empty `QPQ_DB_KEY` is required. An empty key leaves the database unencrypted on disk and is not acceptable for production.
|
||||
|
||||
---
|
||||
|
||||
@@ -88,7 +88,7 @@ To use a certificate issued by a CA or a custom self-signed certificate:
|
||||
```
|
||||
2. Point the server at them:
|
||||
```bash
|
||||
cargo run -p quicnprotochat-server -- \
|
||||
cargo run -p quicproquo-server -- \
|
||||
--tls-cert cert.der \
|
||||
--tls-key key.der
|
||||
```
|
||||
@@ -128,7 +128,7 @@ The server persists its state to the data directory (`--data-dir`, default `data
|
||||
| `data/deliveries.bin` | `bincode`-serialised map of `(channelId, recipientKey)` to message queues |
|
||||
| `data/hybridkeys.bin` | `bincode`-serialised map of identity keys to hybrid (X25519 + ML-KEM-768) public keys |
|
||||
|
||||
Storage is implemented by the `FileBackedStore` in `crates/quicnprotochat-server/src/storage.rs`. Every mutation (upload, enqueue, fetch) flushes the entire map to disk synchronously. This is suitable for proof-of-concept workloads but not production traffic. See [Storage Backend](../internals/storage-backend.md) for details.
|
||||
Storage is implemented by the `FileBackedStore` in `crates/quicproquo-server/src/storage.rs`. Every mutation (upload, enqueue, fetch) flushes the entire map to disk synchronously. This is suitable for proof-of-concept workloads but not production traffic. See [Storage Backend](../internals/storage-backend.md) for details.
|
||||
|
||||
---
|
||||
|
||||
@@ -153,16 +153,16 @@ The server uses `tracing` with `tracing-subscriber` and respects the `RUST_LOG`
|
||||
|
||||
```bash
|
||||
# Default: info level
|
||||
RUST_LOG=info cargo run -p quicnprotochat-server
|
||||
RUST_LOG=info cargo run -p quicproquo-server
|
||||
|
||||
# Debug level for detailed RPC tracing
|
||||
RUST_LOG=debug cargo run -p quicnprotochat-server
|
||||
RUST_LOG=debug cargo run -p quicproquo-server
|
||||
|
||||
# Trace level for maximum verbosity
|
||||
RUST_LOG=trace cargo run -p quicnprotochat-server
|
||||
RUST_LOG=trace cargo run -p quicproquo-server
|
||||
|
||||
# Filter to specific crates
|
||||
RUST_LOG=quicnprotochat_server=debug,quinn=warn cargo run -p quicnprotochat-server
|
||||
RUST_LOG=quicproquo_server=debug,quinn=warn cargo run -p quicproquo-server
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user