@aegis-fluxion/core 0.5.0 → 0.7.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.
package/README.md CHANGED
@@ -4,7 +4,7 @@ Low-level E2E-encrypted WebSocket primitives for the `aegis-fluxion` ecosystem.
4
4
 
5
5
  If you prefer a single user-facing package, use [`aegis-fluxion`](../aegis-fluxion/README.md).
6
6
 
7
- Version: **0.5.0**
7
+ Version: **0.7.1**
8
8
 
9
9
  ---
10
10
 
@@ -17,6 +17,11 @@ Version: **0.5.0**
17
17
  - Heartbeat and zombie socket cleanup
18
18
  - Auto-reconnect with fresh re-handshake
19
19
  - **Binary payload support**: `Buffer`, `Uint8Array`, `Blob`
20
+ - **Server middleware pipeline** via `SecureServer.use(...)`
21
+ - Middleware phases: `connection`, `incoming`, `outgoing`
22
+ - Per-socket middleware metadata available as `SecureServerClient.metadata`
23
+ - **Rate limiting & DDoS shield** with per-connection/per-IP controls
24
+ - Optional MCP bridge package: `@aegis-fluxion/mcp-adapter`
20
25
 
21
26
  ---
22
27
 
@@ -28,6 +33,160 @@ npm install @aegis-fluxion/core ws
28
33
 
29
34
  ---
30
35
 
36
+ ## Middleware in 0.6.0+
37
+
38
+ `SecureServer` now supports phase-based middleware for auth, policy enforcement, and payload
39
+ normalization.
40
+
41
+ ```ts
42
+ import { SecureClient, SecureServer } from "@aegis-fluxion/core";
43
+
44
+ const server = new SecureServer({ host: "127.0.0.1", port: 8080 });
45
+
46
+ server.use(async (context, next) => {
47
+ if (context.phase === "connection") {
48
+ const rawApiKey = context.request.headers["x-api-key"];
49
+ const apiKey = Array.isArray(rawApiKey) ? rawApiKey[0] : rawApiKey;
50
+
51
+ if (apiKey !== "dev-secret") {
52
+ throw new Error("Unauthorized");
53
+ }
54
+
55
+ context.metadata.set("role", "editor");
56
+ }
57
+
58
+ await next();
59
+ });
60
+
61
+ server.use(async (context, next) => {
62
+ if (
63
+ context.phase === "incoming" &&
64
+ context.event === "post:create" &&
65
+ typeof context.data === "object" &&
66
+ context.data !== null
67
+ ) {
68
+ const payload = context.data as { title?: string };
69
+ context.data = { title: String(payload.title ?? "").trim() };
70
+ }
71
+
72
+ await next();
73
+
74
+ if (context.phase === "outgoing" && context.event === "post:create") {
75
+ context.data = {
76
+ ...(context.data as Record<string, unknown>),
77
+ middleware: true
78
+ };
79
+ }
80
+ });
81
+
82
+ server.on("post:create", async (payload, client) => {
83
+ return {
84
+ ok: true,
85
+ role: client.metadata.get("role"),
86
+ payload
87
+ };
88
+ });
89
+
90
+ const client = new SecureClient("ws://127.0.0.1:8080", {
91
+ wsOptions: {
92
+ headers: {
93
+ "x-api-key": "dev-secret"
94
+ }
95
+ }
96
+ });
97
+
98
+ client.on("ready", async () => {
99
+ const response = await client.emit("post:create", { title: " Hello " }, { timeoutMs: 1500 });
100
+ console.log(response);
101
+ });
102
+ ```
103
+
104
+ Notes:
105
+
106
+ - Throwing in `connection` middleware rejects the socket and closes with code `1008`.
107
+ - `metadata` is mutable in middleware (`Map`) and exposed read-only on `SecureServerClient`.
108
+
109
+ ---
110
+
111
+ ## Rate Limiting & DDoS Protection (0.7.1)
112
+
113
+ `SecureServer` can enforce burst limits per connection and per source IP before event handlers run.
114
+
115
+ ```ts
116
+ import { SecureServer } from "@aegis-fluxion/core";
117
+
118
+ const server = new SecureServer({
119
+ host: "127.0.0.1",
120
+ port: 8080,
121
+ rateLimit: {
122
+ enabled: true,
123
+ windowMs: 1_000,
124
+ maxEventsPerConnection: 120,
125
+ maxEventsPerIp: 300,
126
+ action: "throttle",
127
+ throttleMs: 150,
128
+ maxThrottleMs: 2_000,
129
+ disconnectAfterViolations: 4,
130
+ disconnectCode: 1013,
131
+ disconnectReason: "Rate limit exceeded. Please retry later."
132
+ }
133
+ });
134
+ ```
135
+
136
+ Behavior summary:
137
+
138
+ - When limits are exceeded, the server can **throttle** or **disconnect** the peer.
139
+ - Throttle mode delays the first over-limit message and drops subsequent flood packets during the throttle window.
140
+ - Disconnect mode closes abusive sockets with your configured close code/reason.
141
+ - Source IP is resolved from `x-forwarded-for` (first hop) or socket remote address.
142
+
143
+ ---
144
+
145
+ ## MCP Adapter Integration (0.7.0)
146
+
147
+ Use `@aegis-fluxion/mcp-adapter` to carry MCP JSON-RPC messages through your encrypted core
148
+ transport.
149
+
150
+ ```ts
151
+ import { SecureClient, SecureServer } from "@aegis-fluxion/core";
152
+ import { SecureMCPTransport } from "@aegis-fluxion/mcp-adapter";
153
+
154
+ const secureServer = new SecureServer({ host: "127.0.0.1", port: 9091 });
155
+
156
+ secureServer.on("connection", async (client) => {
157
+ const mcpServerTransport = new SecureMCPTransport({
158
+ mode: "server",
159
+ server: secureServer,
160
+ clientId: client.id
161
+ });
162
+
163
+ mcpServerTransport.onmessage = async (message) => {
164
+ // Forward into your MCP server runtime.
165
+ console.log("MCP request on server tunnel", message);
166
+ };
167
+
168
+ await mcpServerTransport.start();
169
+ });
170
+
171
+ const secureClient = new SecureClient("ws://127.0.0.1:9091");
172
+
173
+ const mcpClientTransport = new SecureMCPTransport({
174
+ mode: "client",
175
+ client: secureClient
176
+ });
177
+
178
+ await mcpClientTransport.start();
179
+
180
+ await mcpClientTransport.send({
181
+ jsonrpc: "2.0",
182
+ id: 100,
183
+ method: "tools/list",
184
+ params: {}
185
+ });
186
+ ```
187
+
188
+ ---
189
+
31
190
  ## Binary Data Support
32
191
 
33
192
  `@aegis-fluxion/core` supports encrypted binary payload transfer while preserving type fidelity.
@@ -115,6 +274,7 @@ client.on("ready", async () => {
115
274
 
116
275
  - `on("connection" | "ready" | "disconnect" | "error", handler)`
117
276
  - `on("custom:event", (data, client) => unknown | Promise<unknown>)`
277
+ - `use((context, next) => void | Promise<void>)`
118
278
  - `emit(event, data): SecureServer`
119
279
  - `emitTo(clientId, event, data): boolean`
120
280
  - `emitTo(clientId, event, data, callback): boolean`
@@ -127,11 +287,22 @@ client.on("ready", async () => {
127
287
 
128
288
  - `id: string`
129
289
  - `socket: WebSocket`
290
+ - `metadata: ReadonlyMap<string, unknown>`
130
291
  - `emit(event, data, ...ackArgs): boolean | Promise<unknown>`
131
292
  - `join(room): boolean`
132
293
  - `leave(room): boolean`
133
294
  - `leaveAll(): number`
134
295
 
296
+ ### Middleware Types
297
+
298
+ - `SecureServerMiddleware`
299
+ - `SecureServerMiddlewareContext`
300
+ - `SecureServerConnectionMiddlewareContext`
301
+ - `SecureServerMessageMiddlewareContext`
302
+ - `SecureServerMiddlewareNext`
303
+ - `SecureServerRateLimitOptions`
304
+ - `SecureServerRateLimitAction`
305
+
135
306
  ### `SecureClient`
136
307
 
137
308
  - `connect(): void`
@@ -153,6 +324,8 @@ client.on("ready", async () => {
153
324
  - Authentication tags are verified on every packet (tampered packets are dropped).
154
325
  - Internal transport events are reserved (`__handshake`, `__rpc:req`, `__rpc:res`).
155
326
  - Pending ACK requests are rejected on timeout/disconnect.
327
+ - Overload traffic can be throttled or disconnected before custom handlers are invoked.
328
+ - Middleware-level policy rejection uses WebSocket close code `1008`.
156
329
 
157
330
  ---
158
331