wse-client 2.1.1 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +17 -6
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -14,7 +14,7 @@ High-performance WebSocket server built in Rust with native clustering, E2E encr
14
14
  | Feature | Details |
15
15
  |---------|---------|
16
16
  | **Rust core** | tokio async runtime, tungstenite WebSocket transport, dedicated thread pool, zero GIL on the data path |
17
- | **JWT authentication** | Rust-native HS256 validation during handshake (0.01ms), cookie + Authorization header extraction |
17
+ | **JWT authentication** | HS256, RS256, ES256 algorithms via jsonwebtoken crate. Validated during handshake (0.01ms), cookie + Authorization header extraction, key rotation, kid validation |
18
18
  | **Protocol negotiation** | `client_hello`/`server_hello` handshake with feature discovery, capability advertisement, version agreement |
19
19
  | **Topic subscriptions** | Per-connection topic subscriptions with automatic cleanup on disconnect |
20
20
  | **Pre-framed broadcast** | WebSocket frame built once, shared via Arc across all connections, single allocation per broadcast |
@@ -99,7 +99,7 @@ High-performance WebSocket server built in Rust with native clustering, E2E encr
99
99
 
100
100
  | Feature | Details |
101
101
  |---------|---------|
102
- | **Origin validation** | `ALLOWED_ORIGINS` env var, rejects unlisted origins with close code 4403 |
102
+ | **Origin validation** | Configure in reverse proxy (nginx/Caddy) to prevent CSWSH |
103
103
  | **Cookie auth** | `access_token` HTTP-only cookie with `Secure + SameSite=Lax` (OWASP recommended for browsers) |
104
104
  | **Frame protection** | 1 MB max frame size, serde_json parsing (no eval), escaped user IDs in server_ready |
105
105
  | **Cluster frame protection** | zstd decompression output capped at 1 MB (MAX_FRAME_SIZE), protocol version validation |
@@ -163,9 +163,14 @@ token = rust_jwt_encode(
163
163
  | `host` | required | Bind address |
164
164
  | `port` | required | Bind port |
165
165
  | `max_connections` | 1000 | Maximum concurrent WebSocket connections |
166
- | `jwt_secret` | None | HS256 secret for JWT validation (bytes, min 32 bytes). `None` disables authentication |
166
+ | `jwt_secret` | None | JWT key for validation. HS256: shared secret (bytes, min 32). RS256/ES256: PEM public key. `None` disables auth |
167
167
  | `jwt_issuer` | None | Expected `iss` claim. Skipped if `None` |
168
168
  | `jwt_audience` | None | Expected `aud` claim. Skipped if `None` |
169
+ | `jwt_cookie_name` | "access_token" | Cookie name for JWT token extraction |
170
+ | `jwt_previous_secret` | None | Previous key for zero-downtime rotation. HS256: previous secret. RS256/ES256: previous public key PEM |
171
+ | `jwt_key_id` | None | Expected `kid` header claim. Rejects tokens with mismatched key ID |
172
+ | `jwt_algorithm` | None | JWT algorithm: `"HS256"` (default), `"RS256"`, or `"ES256"` |
173
+ | `jwt_private_key` | None | PEM private key for RS256/ES256 token encoding. Not needed for HS256 |
169
174
  | `max_inbound_queue_size` | 131072 | Drain mode bounded queue capacity |
170
175
  | `recovery_enabled` | False | Enable per-topic message recovery buffers |
171
176
  | `recovery_buffer_size` | 128 | Ring buffer slots per topic (rounded to power-of-2) |
@@ -175,6 +180,12 @@ token = rust_jwt_encode(
175
180
  | `presence_enabled` | False | Enable per-topic presence tracking |
176
181
  | `presence_max_data_size` | 4096 | Max bytes for a user's presence metadata |
177
182
  | `presence_max_members` | 0 | Max tracked members per topic (0 = unlimited) |
183
+ | `max_outbound_queue_bytes` | 16777216 | Per-connection outbound buffer limit (bytes, default 16 MB). Messages dropped when exceeded |
184
+ | `rate_limit_capacity` | 100000.0 | Token bucket capacity per connection |
185
+ | `rate_limit_refill` | 10000.0 | Token bucket refill rate per second |
186
+ | `max_message_size` | 1048576 | Maximum WebSocket frame size in bytes (default 1 MB) |
187
+ | `ping_interval` | 25 | Server-initiated ping interval in seconds |
188
+ | `idle_timeout` | 60 | Force-close connections idle for this many seconds |
178
189
 
179
190
  ---
180
191
 
@@ -375,7 +386,7 @@ Token delivery:
375
386
  - **Backend clients**: `Authorization: Bearer <token>` header and/or `access_token` cookie
376
387
  - **API clients**: `Authorization: Bearer <token>` header
377
388
 
378
- Required claims: `sub` (user ID), `exp` (expiration), `iat` (issued at). Optional: `iss`, `aud` (validated if configured).
389
+ Required claims: `sub` (user ID), `exp` (expiration). Recommended: `iat` (issued at). Optional: `iss`, `aud` (validated if configured).
379
390
 
380
391
  ### End-to-End Encryption
381
392
 
@@ -499,10 +510,10 @@ Benchmarked on AMD EPYC 7502P (32 cores / 64 threads, 128 GB RAM), Ubuntu 24.04.
499
510
 
500
511
  | Mode | Peak Throughput | Connections | Message Loss |
501
512
  |------|----------------|-------------|--------------|
502
- | Standalone (fan-out) | 5.0M deliveries/s | 500K | 0% |
513
+ | Standalone (fan-out) | 4.7M deliveries/s | 100K | 0% |
503
514
  | Standalone (inbound JSON) | 14.7M msg/s | 500K | 0% |
504
515
  | Standalone (inbound msgpack) | 30M msg/s | 500K | 0% |
505
- | Cluster (2 nodes) | 9.5M deliveries/s | 20K per node | 0% |
516
+ | Cluster (2 nodes, 50/50) | 6.6M deliveries/s | 500 per node | 0% |
506
517
 
507
518
  Sub-millisecond latency. Median 0.38ms with JWT authentication. Connection handshake: 0.53ms median (Rust JWT path).
508
519
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wse-client",
3
- "version": "2.1.1",
3
+ "version": "2.2.1",
4
4
  "description": "WSE (WebSocket Engine) React client. Type-safe hooks, auto-reconnect, offline queue, E2E encryption.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",