feat: add delivery sequence numbers + major server/client refactor
Delivery sequence numbers (MLS epoch ordering fix):
- schemas/node.capnp: add Envelope{seq,data} struct; enqueue returns seq:UInt64;
fetch/fetchWait return List(Envelope) instead of List(Data)
- storage.rs: Store trait enqueue returns u64; fetch/fetch_limited return
Vec<(u64, Vec<u8>)>; FileBackedStore gains QueueMapV3 with per-inbox seq
counters and V2→V3 on-disk migration
- migrations/002_add_seq.sql: seq column, delivery_seq_counters table, index
- sql_store.rs: atomic UPSERT counter via RETURNING, ORDER BY seq, SCHEMA_VERSION→3
- node_service/delivery.rs: builds Envelope list; returns seq from enqueue
- client/rpc.rs: enqueue→u64, fetch_all/fetch_wait→Vec<(u64,Vec<u8>)>
- client/commands.rs: sort-by-seq before MLS processing; retry loop in cmd_recv
and receive_pending_plaintexts for correct epoch ordering
Server refactor:
- Split monolithic main.rs into node_service/{mod,delivery,auth_ops,key_ops,p2p_ops}
- Add auth.rs (token validation, rate limiting), config.rs, metrics.rs, tls.rs
- Add SQL migrations runner (001_initial.sql, 002_add_seq.sql)
- OPAQUE PAKE login/registration, sealed-sender mode, queue depth limit (1000)
Client refactor:
- Split lib.rs into client/{commands,rpc,state,retry,hex,mod}
- Add cmd_whoami, cmd_health, cmd_check_key, cmd_ping subcommands
- Add cmd_register_user, cmd_login (OPAQUE), cmd_refresh_keypackage
- Hybrid PQ envelope (X25519 + ML-KEM-768) on all send/recv paths
- E2E test suite expanded
Other:
- quicnprotochat-gui: Tauri 2 desktop GUI skeleton (backend + HTML UI)
- quicnprotochat-p2p: iroh-based P2P transport stub
- quicnprotochat-core: app_message, hybrid_crypto modules; GroupMember API updates
- .github/workflows/size-lint.yml: binary size regression check
- docs: protocol comparison, roadmap updates, fully-operational checklist
This commit is contained in:
@@ -83,7 +83,7 @@ KeyPackage fetched successfully.
|
||||
No KeyPackage available for this identity.
|
||||
```
|
||||
|
||||
KeyPackages are single-use: fetching a KeyPackage atomically removes it from the server. If the peer needs to be added to another group, they must upload a new KeyPackage.
|
||||
KeyPackages are single-use: fetching a KeyPackage atomically removes it from the server. The server may also enforce a TTL (e.g. 24 hours) on stored KeyPackages. If the peer needs to be added to another group, or their KeyPackage expired, they must upload a new one (see `refresh-keypackage` below).
|
||||
|
||||
### `demo-group`
|
||||
|
||||
@@ -125,7 +125,7 @@ cargo run -p quicnprotochat-client -- register-state \
|
||||
--server 127.0.0.1:7000
|
||||
```
|
||||
|
||||
If `alice.bin` does not exist, a new identity is generated and saved. If it already exists, the existing identity is loaded and a new KeyPackage is generated from it.
|
||||
If `alice.bin` does not exist, a new identity is generated and saved. If it already exists, the existing identity is loaded and a new KeyPackage is generated from it. You can run `register-state` again at any time to upload a fresh KeyPackage (e.g. after the previous one was consumed or expired). For refresh-only (no new identity), use `refresh-keypackage` instead.
|
||||
|
||||
**Output:**
|
||||
```
|
||||
@@ -134,6 +134,30 @@ fingerprint : 9f8e7d6c5b4a...
|
||||
KeyPackage uploaded successfully.
|
||||
```
|
||||
|
||||
### `refresh-keypackage`
|
||||
|
||||
Refresh the KeyPackage on the server using your **existing** state file. Does not create a new identity. Use this when:
|
||||
|
||||
- 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.
|
||||
|
||||
```bash
|
||||
cargo run -p quicnprotochat-client -- refresh-keypackage \
|
||||
--state alice.bin \
|
||||
--server 127.0.0.1:7000
|
||||
```
|
||||
|
||||
**Output:**
|
||||
```
|
||||
identity_key : a1b2c3d4e5f6...
|
||||
fingerprint : 9f8e7d6c5b4a...
|
||||
KeyPackage uploaded successfully.
|
||||
```
|
||||
|
||||
If you are told "no key" when someone tries to invite you, have them wait and run `refresh-keypackage`, then try the invite again.
|
||||
|
||||
### `create-group`
|
||||
|
||||
Create a new MLS group. The caller becomes the sole member at epoch 0.
|
||||
@@ -269,7 +293,8 @@ In ephemeral mode (`register` and `demo-group`), the key is held in process memo
|
||||
| `register` | No | Generate ephemeral identity + KeyPackage, upload to AS |
|
||||
| `fetch-key <hex>` | No | Fetch a peer's KeyPackage from AS |
|
||||
| `demo-group` | No | Automated Alice-and-Bob round-trip |
|
||||
| `register-state` | Yes | Upload KeyPackage for persistent identity |
|
||||
| `register-state` | Yes | Upload KeyPackage for persistent identity (creates identity if needed) |
|
||||
| `refresh-keypackage` | Yes | Upload a fresh KeyPackage from existing state (no new identity) |
|
||||
| `create-group` | Yes | Create MLS group (sole member, epoch 0) |
|
||||
| `invite` | Yes | Add peer to group, deliver Welcome via DS |
|
||||
| `join` | Yes | Consume Welcome from DS, join group |
|
||||
|
||||
Reference in New Issue
Block a user