@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 +174 -1
- package/dist/index.cjs +399 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +52 -1
- package/dist/index.d.ts +52 -1
- package/dist/index.js +399 -14
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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.
|
|
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
|
|