@aegis-fluxion/core 0.8.0 → 0.10.0
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 +195 -2
- package/dist/index.cjs +867 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +80 -1
- package/dist/index.d.ts +80 -1
- package/dist/index.js +867 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Low-level encrypted WebSocket primitives for the `aegis-fluxion` ecosystem.
|
|
4
4
|
|
|
5
|
-
Version: **0.
|
|
5
|
+
Version: **0.10.0**
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -10,7 +10,9 @@ Version: **0.8.0**
|
|
|
10
10
|
|
|
11
11
|
- Ephemeral ECDH handshake (`prime256v1`)
|
|
12
12
|
- AES-256-GCM encrypted envelopes
|
|
13
|
+
- Built-in telemetry via `getMetrics()` and `getMetricsPrometheus()`
|
|
13
14
|
- ACK request/response (Promise + callback styles)
|
|
15
|
+
- Encrypted chunked streaming for large `Buffer`/`Readable` payloads
|
|
14
16
|
- Secure room routing (`join`, `leave`, `leaveAll`, `to(room).emit(...)`)
|
|
15
17
|
- Middleware phases: `connection`, `incoming`, `outgoing`
|
|
16
18
|
- Rate limiting and DDoS controls per connection and IP
|
|
@@ -27,9 +29,200 @@ npm install @aegis-fluxion/core ws
|
|
|
27
29
|
|
|
28
30
|
---
|
|
29
31
|
|
|
32
|
+
## Observability & telemetry (new in 0.10.0)
|
|
33
|
+
|
|
34
|
+
`SecureServer` exposes real-time metrics for operational visibility:
|
|
35
|
+
|
|
36
|
+
- active secure connections
|
|
37
|
+
- successful/failed handshakes (including resume attempts)
|
|
38
|
+
- encrypted message and byte throughput (ingress/egress)
|
|
39
|
+
- DDoS/rate-limit counters (blocked, throttled, disconnected)
|
|
40
|
+
|
|
41
|
+
### JSON metrics snapshot
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import { SecureServer } from "@aegis-fluxion/core";
|
|
45
|
+
|
|
46
|
+
const server = new SecureServer({ host: "127.0.0.1", port: 8080 });
|
|
47
|
+
|
|
48
|
+
const snapshot = server.getMetrics();
|
|
49
|
+
console.log(snapshot.activeConnections);
|
|
50
|
+
console.log(snapshot.encryptedMessagesReceivedTotal);
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Prometheus endpoint integration
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
import { createServer } from "node:http";
|
|
57
|
+
import { SecureServer } from "@aegis-fluxion/core";
|
|
58
|
+
|
|
59
|
+
const secureServer = new SecureServer({ host: "127.0.0.1", port: 8080 });
|
|
60
|
+
|
|
61
|
+
createServer((request, response) => {
|
|
62
|
+
if (request.url === "/metrics") {
|
|
63
|
+
response.setHeader("Content-Type", "text/plain; version=0.0.4; charset=utf-8");
|
|
64
|
+
response.end(secureServer.getMetricsPrometheus());
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
response.statusCode = 404;
|
|
69
|
+
response.end("Not Found");
|
|
70
|
+
}).listen(9100, "127.0.0.1");
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Frontend integration (React)
|
|
76
|
+
|
|
77
|
+
`@aegis-fluxion/core` is server/runtime focused. For browser clients, pair it with
|
|
78
|
+
`@aegis-fluxion/browser-client`.
|
|
79
|
+
|
|
80
|
+
### Node backend (`SecureServer`)
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
import { SecureServer } from "@aegis-fluxion/core";
|
|
84
|
+
|
|
85
|
+
const server = new SecureServer({ host: "127.0.0.1", port: 8080 });
|
|
86
|
+
|
|
87
|
+
server.on("feed:publish", async (payload) => {
|
|
88
|
+
server.emit("feed:message", payload);
|
|
89
|
+
return { ok: true };
|
|
90
|
+
});
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### React frontend (`BrowserSecureClient`)
|
|
94
|
+
|
|
95
|
+
```tsx
|
|
96
|
+
import { useEffect, useMemo, useState } from "react";
|
|
97
|
+
import { BrowserSecureClient } from "@aegis-fluxion/browser-client";
|
|
98
|
+
|
|
99
|
+
export function SecureFeedPanel() {
|
|
100
|
+
const [status, setStatus] = useState("connecting");
|
|
101
|
+
const [messages, setMessages] = useState<string[]>([]);
|
|
102
|
+
|
|
103
|
+
const client = useMemo(() => {
|
|
104
|
+
return new BrowserSecureClient("ws://127.0.0.1:8080", {
|
|
105
|
+
autoConnect: false,
|
|
106
|
+
reconnect: true
|
|
107
|
+
});
|
|
108
|
+
}, []);
|
|
109
|
+
|
|
110
|
+
useEffect(() => {
|
|
111
|
+
const onReady = () => setStatus("ready");
|
|
112
|
+
const onDisconnect = () => setStatus("disconnected");
|
|
113
|
+
const onFeedMessage = (payload: unknown) => {
|
|
114
|
+
const data = payload as { text?: string };
|
|
115
|
+
if (typeof data.text === "string") {
|
|
116
|
+
setMessages((prev) => [data.text, ...prev]);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
client.on("ready", onReady);
|
|
121
|
+
client.on("disconnect", onDisconnect);
|
|
122
|
+
client.on("feed:message", onFeedMessage);
|
|
123
|
+
client.connect();
|
|
124
|
+
|
|
125
|
+
return () => {
|
|
126
|
+
client.off("ready", onReady);
|
|
127
|
+
client.off("disconnect", onDisconnect);
|
|
128
|
+
client.off("feed:message", onFeedMessage);
|
|
129
|
+
client.disconnect();
|
|
130
|
+
};
|
|
131
|
+
}, [client]);
|
|
132
|
+
|
|
133
|
+
return (
|
|
134
|
+
<section>
|
|
135
|
+
<p>Status: {status}</p>
|
|
136
|
+
<ul>
|
|
137
|
+
{messages.map((message) => (
|
|
138
|
+
<li key={message}>{message}</li>
|
|
139
|
+
))}
|
|
140
|
+
</ul>
|
|
141
|
+
</section>
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
## Chunked streaming (new in 0.9.0)
|
|
149
|
+
|
|
150
|
+
`@aegis-fluxion/core@0.9.0` adds secure chunked stream transport for large payloads.
|
|
151
|
+
|
|
152
|
+
### Supported stream sources
|
|
153
|
+
|
|
154
|
+
- `Buffer`
|
|
155
|
+
- `Uint8Array`
|
|
156
|
+
- `Readable`
|
|
157
|
+
- `AsyncIterable<Buffer | Uint8Array | ArrayBuffer>`
|
|
158
|
+
|
|
159
|
+
### Stream APIs
|
|
160
|
+
|
|
161
|
+
- Client outbound: `client.emitStream(event, source, options?)`
|
|
162
|
+
- Client inbound: `client.onStream(event, handler)`
|
|
163
|
+
- Server outbound: `server.emitStreamTo(clientId, event, source, options?)`
|
|
164
|
+
- Server inbound: `server.onStream(event, handler)`
|
|
165
|
+
- Per-client server outbound helper: `serverClient.emitStream(event, source, options?)`
|
|
166
|
+
|
|
167
|
+
### Options
|
|
168
|
+
|
|
169
|
+
- `chunkSizeBytes` (default `64 * 1024`, max `1024 * 1024`)
|
|
170
|
+
- `metadata` (optional object attached to the stream start frame)
|
|
171
|
+
- `totalBytes` (optional size hint; required when source size is unknown and you want announced size)
|
|
172
|
+
- `signal` (`AbortSignal` to cancel transfer)
|
|
173
|
+
|
|
174
|
+
### Example
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
import { Readable } from "node:stream";
|
|
178
|
+
import { SecureClient, SecureServer } from "@aegis-fluxion/core";
|
|
179
|
+
|
|
180
|
+
const server = new SecureServer({ host: "127.0.0.1", port: 8080 });
|
|
181
|
+
const client = new SecureClient("ws://127.0.0.1:8080");
|
|
182
|
+
|
|
183
|
+
server.onStream("media:upload", async (stream, info, peer) => {
|
|
184
|
+
const chunks: Buffer[] = [];
|
|
185
|
+
|
|
186
|
+
for await (const chunk of stream) {
|
|
187
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const uploaded = Buffer.concat(chunks);
|
|
191
|
+
|
|
192
|
+
await peer.emitStream("media:download", Readable.from(uploaded), {
|
|
193
|
+
chunkSizeBytes: 64 * 1024,
|
|
194
|
+
totalBytes: uploaded.length,
|
|
195
|
+
metadata: { direction: "server-to-client" }
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
console.log("Server received stream", {
|
|
199
|
+
streamId: info.streamId,
|
|
200
|
+
announcedTotalBytes: info.totalBytes,
|
|
201
|
+
receivedBytes: uploaded.length
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
client.on("ready", async () => {
|
|
206
|
+
const payload = Buffer.from("chunked secure payload");
|
|
207
|
+
|
|
208
|
+
const result = await client.emitStream("media:upload", payload, {
|
|
209
|
+
chunkSizeBytes: 64 * 1024,
|
|
210
|
+
totalBytes: payload.length,
|
|
211
|
+
metadata: { direction: "client-to-server" }
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
console.log(result); // { streamId, chunkCount, totalBytes }
|
|
215
|
+
});
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Each chunk is delivered inside reserved internal `start/chunk/end/abort` frames and encrypted
|
|
219
|
+
through the same AES-256-GCM channel used by standard events.
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
30
223
|
## Session resumption (TLS 1.3-style)
|
|
31
224
|
|
|
32
|
-
`@aegis-fluxion/core@0.8.0`
|
|
225
|
+
`@aegis-fluxion/core@0.8.0` introduced secure resume-first reconnect behavior:
|
|
33
226
|
|
|
34
227
|
- Full handshake path uses ephemeral ECDH (`hello` frame).
|
|
35
228
|
- Resume path uses ticket-bound proofs (`resume` / `resume-ack` frames).
|