@floegence/flowersec-core 2.4.2 → 2.5.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
@@ -65,6 +65,20 @@ const session = await controller.waitForSession();
65
65
  The immutable callback definition applies to every generation, while each
66
66
  Session gets a fresh router. Terminated Session work is never replayed.
67
67
 
68
+ ### Application streams on any Session
69
+
70
+ ```ts
71
+ import { StreamHandlers } from "@floegence/flowersec-core";
72
+
73
+ const streamHandlers = new StreamHandlers({ maxConcurrentStreams: 32 });
74
+ streamHandlers.handleStream("files/read", async (incoming) => serveFile(incoming));
75
+ await streamHandlers.serve(session);
76
+ ```
77
+
78
+ The portable root, browser, and Node entrypoints share this dispatcher. The
79
+ sealed registrar used by Node `ProxyServer.register(...)` is exported only from
80
+ the Node entrypoint.
81
+
68
82
  For the complete durable `ArtifactLease` spend workflow, see the
69
83
  [TypeScript cookbook](../examples/ts/README.md). Node raw-QUIC-only artifacts
70
84
  may omit `origin`; providing an absolute HTTP(S) origin enables WebSocket
@@ -98,7 +112,7 @@ The Browser and Node `connect(...)` operations are one-shot and never reconnect.
98
112
 
99
113
  The controller has one scheduler and one in-flight attempt. Its states are `idle`, `connecting`, `connected`, `waiting`, `failed`, and `closed`; immutable snapshots expose `ConnectionSnapshot.retryDisposition` while the corresponding retry decision applies and clear it before a new attempt, after connection, and on close. Call `start()` once, observe snapshots with `subscribe(...)`, await an established session with `waitForSession(...)`, and use `retryNow()` only to wake a `waiting` controller. `close()` cancels acquisition, connection, and waiting before closing the current session.
100
114
 
101
- Node `SessionHandlers` accept application stream kinds whose UTF-8 encoding is 1 through 255 bytes and reserve `flowersec.rpc.v2` for Flowersec RPC. `AcceptedSession.serve(...)` half-closes successfully handled streams. A rejected handler Promise resets only that stream; the accept loop and unrelated streams continue.
115
+ `StreamHandlers` and Node `SessionHandlers` accept application stream kinds containing 1 through 128 canonical UTF-8 bytes, reject leading or trailing Unicode whitespace, controls, and unassigned scalars, and reserve `flowersec.rpc.v2` for Flowersec RPC. Successful handlers half-close their stream. A rejected handler Promise resets only that stream; the accept loop and unrelated streams continue.
102
116
 
103
117
  Reliable streams apply bounded per-stream receive backpressure instead of buffering application data without limit. A slow consumer pauses carrier progress until reads release capacity; records retain carrier order, so a rekey behind backpressured DATA completes after the consumer resumes. `closeWrite()` sends the graceful FIN and keeps reads available. `reset()` and `close()` abort both directions. If a write is canceled or fails after its wire commit may have started, only that stream becomes terminal and cannot be reused.
104
118
 
package/dist/facade.d.ts CHANGED
@@ -2,6 +2,8 @@ export type { ByteStream, IncomingStream, JsonObject, JsonPrimitive, JsonValue,
2
2
  export { SessionError, UnreliableMessageError } from "./public/contract.js";
3
3
  export { createStreamMetadata, StreamMetadataError } from "./public/streamMetadata.js";
4
4
  export type { StreamMetadata } from "./public/streamMetadata.js";
5
+ export { HandlerRegistrationError, StreamHandlers, } from "./public/streamHandlers.js";
6
+ export type { StreamHandler, StreamHandlerOptions, } from "./public/streamHandlers.js";
5
7
  export { ArtifactLeaseError, createArtifactLease, } from "./public/artifactLease.js";
6
8
  export type { ArtifactLease } from "./public/artifactLease.js";
7
9
  export { Artifact, ArtifactError, parseArtifact } from "./public/artifact.js";
package/dist/facade.js CHANGED
@@ -1,5 +1,6 @@
1
1
  export { SessionError, UnreliableMessageError } from "./public/contract.js";
2
2
  export { createStreamMetadata, StreamMetadataError } from "./public/streamMetadata.js";
3
+ export { HandlerRegistrationError, StreamHandlers, } from "./public/streamHandlers.js";
3
4
  export { ArtifactLeaseError, createArtifactLease, } from "./public/artifactLease.js";
4
5
  export { Artifact, ArtifactError, parseArtifact } from "./public/artifact.js";
5
6
  export { ConnectError } from "./public/connectError.js";
@@ -1,6 +1,9 @@
1
- import { type IncomingStream, type JsonValue, type OperationOptions, type Session } from "../public/contract.js";
1
+ import { type JsonValue, type OperationOptions, type Session } from "../public/contract.js";
2
2
  import { type DirectAuthorizationDecision, type RuntimeAuthorizationRequest } from "./controlplane.js";
3
+ import { type StreamHandler, type StreamHandlerOptions } from "../public/streamHandlers.js";
3
4
  export type { RuntimeAuthorizationRequest } from "./controlplane.js";
5
+ export { HandlerRegistrationError } from "../public/streamHandlers.js";
6
+ export type { StreamHandler } from "../public/streamHandlers.js";
4
7
  export type AuthorizationDecision = DirectAuthorizationDecision;
5
8
  export type RPCHandlerResult = Readonly<{
6
9
  payload: JsonValue;
@@ -16,20 +19,14 @@ export type RPCHandler = (payload: JsonValue, request: Readonly<{
16
19
  export type NotificationHandler = (payload: JsonValue, request: Readonly<{
17
20
  typeId: number;
18
21
  }>) => Promise<void> | void;
19
- export type StreamHandler = (incoming: IncomingStream, options: OperationOptions) => Promise<void>;
20
- export type SessionHandlerOptions = Readonly<{
21
- maxConcurrentStreams?: number;
22
- }>;
23
- export declare class HandlerRegistrationError extends Error {
24
- readonly code: "invalid_handler" | "already_registered" | "frozen";
25
- constructor(code: "invalid_handler" | "already_registered" | "frozen");
26
- }
22
+ export type SessionHandlerOptions = StreamHandlerOptions;
27
23
  export declare class RPCHandlers {
28
24
  constructor();
29
25
  handleRPC(typeId: number, handler: RPCHandler): void;
30
26
  handleNotification(typeId: number, handler: NotificationHandler): void;
31
27
  }
32
28
  export declare class SessionHandlers {
29
+ private readonly streamHandlerRegistrarBrand;
33
30
  constructor(options?: SessionHandlerOptions);
34
31
  handleRPC(typeId: number, handler: RPCHandler): void;
35
32
  handleNotification(typeId: number, handler: NotificationHandler): void;
@@ -9,18 +9,9 @@ import { unwrapArtifact } from "../public/artifact.js";
9
9
  import { SessionError, } from "../public/contract.js";
10
10
  import { projectSessionV2 } from "../v2/publicSession.js";
11
11
  import { runtimeAuthorizationRequestFromDecoded, } from "./controlplane.js";
12
- const DEFAULT_MAX_CONCURRENT_STREAMS = 64;
13
- const MAX_CONCURRENT_STREAMS = 128;
12
+ import { HandlerRegistrationError, StreamHandlers, freezeStreamHandlers, registerStreamHandlersAtomically, serveFrozenStreamHandlers, } from "../public/streamHandlers.js";
13
+ export { HandlerRegistrationError } from "../public/streamHandlers.js";
14
14
  const DEFAULT_CLEANUP_TIMEOUT_MS = 2_000;
15
- const encoder = new TextEncoder();
16
- export class HandlerRegistrationError extends Error {
17
- code;
18
- constructor(code) {
19
- super(`Flowersec handler registration failed (code=${code})`);
20
- this.code = code;
21
- this.name = "HandlerRegistrationError";
22
- }
23
- }
24
15
  export class RPCHandlers {
25
16
  constructor() {
26
17
  rpcHandlerStates.set(this, createRPCHandlerState());
@@ -34,16 +25,9 @@ export class RPCHandlers {
34
25
  }
35
26
  export class SessionHandlers {
36
27
  constructor(options = {}) {
37
- const maximum = options.maxConcurrentStreams ?? DEFAULT_MAX_CONCURRENT_STREAMS;
38
- if (!Number.isSafeInteger(maximum) ||
39
- maximum < 1 ||
40
- maximum > MAX_CONCURRENT_STREAMS) {
41
- throw new HandlerRegistrationError("invalid_handler");
42
- }
43
28
  sessionHandlerStates.set(this, {
44
- maxConcurrentStreams: maximum,
45
29
  rpc: createRPCHandlerState(),
46
- streams: new Map(),
30
+ streams: new StreamHandlers(options),
47
31
  frozen: false,
48
32
  });
49
33
  }
@@ -57,15 +41,7 @@ export class SessionHandlers {
57
41
  }
58
42
  handleStream(kind, handler) {
59
43
  const state = mutableSessionHandlerState(this);
60
- if (kind.length < 1 ||
61
- encoder.encode(kind).length > 255 ||
62
- kind === "flowersec.rpc.v2" ||
63
- typeof handler !== "function") {
64
- throw new HandlerRegistrationError("invalid_handler");
65
- }
66
- if (state.streams.has(kind))
67
- throw new HandlerRegistrationError("already_registered");
68
- state.streams.set(kind, handler);
44
+ state.streams.handleStream(kind, handler);
69
45
  }
70
46
  }
71
47
  const rpcHandlerStates = new WeakMap();
@@ -89,6 +65,11 @@ function mutableSessionHandlerState(handlers) {
89
65
  throw new HandlerRegistrationError("frozen");
90
66
  return state;
91
67
  }
68
+ /** @internal */
69
+ export function registerSessionStreamHandlersAtomically(handlers, entries) {
70
+ const state = mutableSessionHandlerState(handlers);
71
+ registerStreamHandlersAtomically(state.streams, entries);
72
+ }
92
73
  function registerRPC(state, typeId, handler) {
93
74
  validateRPCRegistration(typeId, handler);
94
75
  if (state.requests.has(typeId) || state.notifications.has(typeId)) {
@@ -162,63 +143,18 @@ function freezeSessionHandlers(handlers) {
162
143
  state.frozen = true;
163
144
  state.snapshot = Object.freeze({
164
145
  rpc: freezeRPCHandlerState(state.rpc),
165
- maxConcurrentStreams: state.maxConcurrentStreams,
166
- streams: new Map(state.streams),
146
+ streams: freezeStreamHandlers(state.streams),
167
147
  });
168
148
  return state.snapshot;
169
149
  }
170
- /** @internal */
171
- export function registerSessionStreamsAtomically(handlers, entries) {
172
- const state = mutableSessionHandlerState(handlers);
173
- const pending = new Set();
174
- for (const [kind, handler] of entries) {
175
- if (kind.length < 1 ||
176
- encoder.encode(kind).length > 255 ||
177
- kind === "flowersec.rpc.v2" ||
178
- typeof handler !== "function")
179
- throw new HandlerRegistrationError("invalid_handler");
180
- if (state.streams.has(kind) || pending.has(kind))
181
- throw new HandlerRegistrationError("already_registered");
182
- pending.add(kind);
183
- }
184
- for (const [kind, handler] of entries)
185
- state.streams.set(kind, handler);
186
- }
187
150
  export class AcceptedSession {
188
151
  constructor() { }
189
152
  get session() {
190
153
  return acceptedSessionState(this).session;
191
154
  }
192
155
  async serve(options = {}) {
193
- const active = new Set();
194
156
  const state = acceptedSessionState(this);
195
- try {
196
- while (true) {
197
- if (options.signal?.aborted)
198
- throw new SessionError("canceled");
199
- const incoming = await this.session.acceptStream(options);
200
- const handler = state.handlers.streams.get(incoming.kind);
201
- if (handler === undefined ||
202
- active.size >= state.handlers.maxConcurrentStreams) {
203
- await incoming.stream.reset();
204
- continue;
205
- }
206
- const task = (async () => {
207
- try {
208
- await handler(incoming, options);
209
- await incoming.stream.closeWrite();
210
- }
211
- catch {
212
- await incoming.stream.reset().catch(() => undefined);
213
- }
214
- })().finally(() => active.delete(task));
215
- active.add(task);
216
- }
217
- }
218
- finally {
219
- await this.close().catch(() => undefined);
220
- await Promise.allSettled(active);
221
- }
157
+ await serveFrozenStreamHandlers(state.handlers.streams, this.session, options, async () => await this.close());
222
158
  }
223
159
  async close() {
224
160
  const state = acceptedSessionState(this);
@@ -1,11 +1,11 @@
1
1
  export { connect, createConnectionController } from "./connectSession.js";
2
2
  export { AcceptedSession, Acceptor, HandlerRegistrationError, RPCHandlers, SessionHandlers, createAcceptor, } from "./acceptor.js";
3
- export type { AcceptorListener, AcceptorOptions, AuthorizationDecision, RPCHandler, RPCHandlerResult, NotificationHandler, SessionHandlerOptions, StreamHandler, } from "./acceptor.js";
3
+ export type { AcceptorListener, AcceptorOptions, AuthorizationDecision, RPCHandler, RPCHandlerResult, NotificationHandler, SessionHandlerOptions, } from "./acceptor.js";
4
4
  export { TunnelRuntime, createTunnelRuntime } from "./tunnelRuntime.js";
5
5
  export type { TunnelAuthorizationDecision, TunnelRuntimeListener, TunnelRuntimeOptions, } from "./tunnelRuntime.js";
6
6
  export type { ConnectionControllerOptions, SessionOptions, SessionTLSOptions, } from "./connectSession.js";
7
7
  export { AuthorizationRecord, AuthorizationResponse, TunnelAuthorizationResponse, ControlPlaneError, EndpointSet, IssuedArtifact, Issuer, RuntimeAuthorizationRequest, authorizeRuntime, authorizeTunnelRuntime, createEndpointSet, parseAuthorizationRecord, parseRuntimeAuthorizationRequest, rejectRuntime, rejectTunnelRuntime, } from "./controlplane.js";
8
8
  export type { ArtifactMetadata, ControlPlaneErrorCode, DirectIssueOptions, IssuedTunnelPair, Scope, SessionOptions as ControlPlaneSessionOptions, TunnelIssueOptions, } from "./controlplane.js";
9
9
  export { ProxyServer, ProxyServerError } from "./proxyServer.js";
10
- export type { ProxyServerOptions } from "./proxyServer.js";
10
+ export type { ProxyServerOptions, StreamHandlerRegistrar } from "./proxyServer.js";
11
11
  export * from "../facade.js";
@@ -1,4 +1,6 @@
1
+ import { StreamHandlers } from "../public/streamHandlers.js";
1
2
  import { SessionHandlers } from "./acceptor.js";
3
+ export type StreamHandlerRegistrar = StreamHandlers | SessionHandlers;
2
4
  export type ProxyServerOptions = Readonly<{
3
5
  upstream: string;
4
6
  upstreamOrigin: string;
@@ -26,6 +28,6 @@ export declare class ProxyServerError extends Error {
26
28
  export declare class ProxyServer {
27
29
  #private;
28
30
  constructor(options: ProxyServerOptions);
29
- register(handlers: SessionHandlers): void;
31
+ register(handlers: StreamHandlerRegistrar): void;
30
32
  close(): Promise<void>;
31
33
  }
@@ -2,7 +2,8 @@ import { createRequire } from "node:module";
2
2
  import { SessionError } from "../public/contract.js";
3
3
  import { writeJsonFrame } from "../framing/jsonframe.js";
4
4
  import { ProxyByteReader, writeAll } from "../proxy/stream.js";
5
- import { registerSessionStreamsAtomically, SessionHandlers, } from "./acceptor.js";
5
+ import { StreamHandlers, registerStreamHandlersAtomically, } from "../public/streamHandlers.js";
6
+ import { SessionHandlers, registerSessionStreamHandlersAtomically, } from "./acceptor.js";
6
7
  const HTTP_KIND = "flowersec-proxy/http1";
7
8
  const WS_KIND = "flowersec-proxy/ws";
8
9
  const WIRE_VERSION = 1;
@@ -38,13 +39,20 @@ export class ProxyServer {
38
39
  register(handlers) {
39
40
  if (this.#closed)
40
41
  throw new ProxyServerError("closed");
41
- if (!(handlers instanceof SessionHandlers))
42
- throw new ProxyServerError("handler_registration");
43
42
  try {
44
- registerSessionStreamsAtomically(handlers, [
43
+ const registrations = [
45
44
  [HTTP_KIND, this.#httpHandler()],
46
45
  [WS_KIND, this.#webSocketHandler()],
47
- ]);
46
+ ];
47
+ if (handlers instanceof StreamHandlers) {
48
+ registerStreamHandlersAtomically(handlers, registrations);
49
+ }
50
+ else if (handlers instanceof SessionHandlers) {
51
+ registerSessionStreamHandlersAtomically(handlers, registrations);
52
+ }
53
+ else {
54
+ throw new TypeError("invalid Flowersec stream handler registrar");
55
+ }
48
56
  }
49
57
  catch (error) {
50
58
  this.#report(error);
@@ -0,0 +1,20 @@
1
+ import { type IncomingStream, type OperationOptions, type Session } from "./contract.js";
2
+ export type StreamHandler = (incoming: IncomingStream, options: OperationOptions) => Promise<void>;
3
+ export type StreamHandlerOptions = Readonly<{
4
+ maxConcurrentStreams?: number;
5
+ }>;
6
+ export declare class HandlerRegistrationError extends Error {
7
+ readonly code: "invalid_handler" | "already_registered" | "frozen";
8
+ constructor(code: "invalid_handler" | "already_registered" | "frozen");
9
+ }
10
+ export type FrozenStreamHandlers = Readonly<{
11
+ maxConcurrentStreams: number;
12
+ streams: ReadonlyMap<string, StreamHandler>;
13
+ }>;
14
+ /** Carrier-neutral application-stream handlers for any established Session. */
15
+ export declare class StreamHandlers {
16
+ private readonly streamHandlerRegistrarBrand;
17
+ constructor(options?: StreamHandlerOptions);
18
+ handleStream(kind: string, handler: StreamHandler): void;
19
+ serve(session: Session, options?: OperationOptions): Promise<void>;
20
+ }
@@ -0,0 +1,124 @@
1
+ import { SessionError, } from "./contract.js";
2
+ import { validApplicationStreamKind } from "../v2/protocol.js";
3
+ const DEFAULT_MAX_CONCURRENT_STREAMS = 64;
4
+ const MAX_CONCURRENT_STREAMS = 128;
5
+ export class HandlerRegistrationError extends Error {
6
+ code;
7
+ constructor(code) {
8
+ super(`Flowersec handler registration failed (code=${code})`);
9
+ this.code = code;
10
+ this.name = "HandlerRegistrationError";
11
+ }
12
+ }
13
+ const streamHandlerStates = new WeakMap();
14
+ /** Carrier-neutral application-stream handlers for any established Session. */
15
+ export class StreamHandlers {
16
+ constructor(options = {}) {
17
+ const maximum = options.maxConcurrentStreams ?? DEFAULT_MAX_CONCURRENT_STREAMS;
18
+ if (!Number.isSafeInteger(maximum) ||
19
+ maximum < 1 ||
20
+ maximum > MAX_CONCURRENT_STREAMS) {
21
+ throw new HandlerRegistrationError("invalid_handler");
22
+ }
23
+ streamHandlerStates.set(this, {
24
+ maxConcurrentStreams: maximum,
25
+ streams: new Map(),
26
+ frozen: false,
27
+ });
28
+ }
29
+ handleStream(kind, handler) {
30
+ registerStreamHandlersAtomically(this, [[kind, handler]]);
31
+ }
32
+ async serve(session, options = {}) {
33
+ if (session === null || typeof session !== "object") {
34
+ throw new HandlerRegistrationError("invalid_handler");
35
+ }
36
+ await serveFrozenStreamHandlers(freezeStreamHandlers(this), session, options, async () => await session.close());
37
+ }
38
+ }
39
+ function mutableStreamHandlerState(handlers) {
40
+ const state = streamHandlerStates.get(handlers);
41
+ if (state === undefined)
42
+ throw new HandlerRegistrationError("invalid_handler");
43
+ if (state.frozen)
44
+ throw new HandlerRegistrationError("frozen");
45
+ return state;
46
+ }
47
+ function registerIntoState(state, entries) {
48
+ if (entries.length === 0)
49
+ throw new HandlerRegistrationError("invalid_handler");
50
+ const pending = new Set();
51
+ for (const [kind, handler] of entries) {
52
+ if (!validApplicationStreamKind(kind) ||
53
+ kind === "flowersec.rpc.v2" ||
54
+ typeof handler !== "function") {
55
+ throw new HandlerRegistrationError("invalid_handler");
56
+ }
57
+ if (state.streams.has(kind) || pending.has(kind)) {
58
+ throw new HandlerRegistrationError("already_registered");
59
+ }
60
+ pending.add(kind);
61
+ }
62
+ for (const [kind, handler] of entries)
63
+ state.streams.set(kind, handler);
64
+ }
65
+ /** @internal */
66
+ export function registerStreamHandlersAtomically(handlers, entries) {
67
+ registerIntoState(mutableStreamHandlerState(handlers), entries);
68
+ }
69
+ /** @internal */
70
+ export function freezeStreamHandlers(handlers) {
71
+ const state = streamHandlerStates.get(handlers);
72
+ if (state === undefined)
73
+ throw new HandlerRegistrationError("invalid_handler");
74
+ if (state.snapshot !== undefined)
75
+ return state.snapshot;
76
+ state.frozen = true;
77
+ state.snapshot = Object.freeze({
78
+ maxConcurrentStreams: state.maxConcurrentStreams,
79
+ streams: new Map(state.streams),
80
+ });
81
+ return state.snapshot;
82
+ }
83
+ /** @internal */
84
+ export async function serveFrozenStreamHandlers(snapshot, session, options, close) {
85
+ const active = new Set();
86
+ const controller = new AbortController();
87
+ const abortFromCaller = () => controller.abort(options.signal?.reason);
88
+ if (options.signal?.aborted === true)
89
+ abortFromCaller();
90
+ else
91
+ options.signal?.addEventListener("abort", abortFromCaller, { once: true });
92
+ const handlerOptions = Object.freeze({
93
+ signal: controller.signal,
94
+ });
95
+ try {
96
+ while (true) {
97
+ if (controller.signal.aborted)
98
+ throw new SessionError("canceled");
99
+ const incoming = await session.acceptStream(handlerOptions);
100
+ const handler = snapshot.streams.get(incoming.kind);
101
+ if (handler === undefined ||
102
+ active.size >= snapshot.maxConcurrentStreams) {
103
+ await incoming.stream.reset();
104
+ continue;
105
+ }
106
+ const task = (async () => {
107
+ try {
108
+ await handler(incoming, handlerOptions);
109
+ await incoming.stream.closeWrite();
110
+ }
111
+ catch {
112
+ await incoming.stream.reset().catch(() => undefined);
113
+ }
114
+ })().finally(() => active.delete(task));
115
+ active.add(task);
116
+ }
117
+ }
118
+ finally {
119
+ options.signal?.removeEventListener("abort", abortFromCaller);
120
+ controller.abort(new SessionError("closed"));
121
+ await close().catch(() => undefined);
122
+ await Promise.allSettled(active);
123
+ }
124
+ }
@@ -567,16 +567,21 @@ function bytesEqual(left, right) {
567
567
  }
568
568
  function validateOpenKind(value) {
569
569
  const encoded = encoder.encode(value);
570
- if (!validOpenUnicodeString(value, MAX_OPEN_KIND_BYTES, false)) {
570
+ if (!validApplicationStreamKind(value)) {
571
571
  throw new ProtocolV2Error("invalid OPEN kind");
572
572
  }
573
- const scalars = Array.from(value);
574
- if (isUnicodeWhitespace(scalars[0].codePointAt(0)) ||
575
- isUnicodeWhitespace(scalars.at(-1).codePointAt(0))) {
576
- throw new ProtocolV2Error("OPEN kind has leading or trailing Unicode whitespace");
577
- }
578
573
  return encoded;
579
574
  }
575
+ /** @internal */
576
+ export function validApplicationStreamKind(value) {
577
+ if (typeof value !== "string" ||
578
+ !validOpenUnicodeString(value, MAX_OPEN_KIND_BYTES, false)) {
579
+ return false;
580
+ }
581
+ const scalars = Array.from(value);
582
+ return !(isUnicodeWhitespace(scalars[0].codePointAt(0)) ||
583
+ isUnicodeWhitespace(scalars.at(-1).codePointAt(0)));
584
+ }
580
585
  function canonicalMetadata(raw, allowEmpty) {
581
586
  if (raw.length === 0 && allowEmpty)
582
587
  return encoder.encode("{}");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@floegence/flowersec-core",
3
- "version": "2.4.2",
3
+ "version": "2.5.1",
4
4
  "description": "Flowersec core TypeScript library for carrier-neutral encrypted sessions and multiplexed streams.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -77,7 +77,7 @@
77
77
  "ws": "^8.21.2"
78
78
  },
79
79
  "optionalDependencies": {
80
- "@floegence/flowersec-node-native": "2.4.2"
80
+ "@floegence/flowersec-node-native": "2.5.1"
81
81
  },
82
82
  "devDependencies": {
83
83
  "@playwright/test": "1.62.1",
@@ -95,5 +95,5 @@
95
95
  "vite": "^8.2.1",
96
96
  "vitest": "4.1.10"
97
97
  },
98
- "flowersecSourceCommit": "1393acdb891a6c935a435bee9068f65b68268795"
98
+ "flowersecSourceCommit": "8debd2888634e8e7c88fd848ff5b08d22aa6d1f2"
99
99
  }
@@ -1,20 +1,20 @@
1
1
  {
2
2
  "bomFormat": "CycloneDX",
3
3
  "specVersion": "1.5",
4
- "serialNumber": "urn:uuid:a7cb7385-1123-5452-8424-bbcb7904bbbb",
4
+ "serialNumber": "urn:uuid:7870295b-822d-59a5-8999-b6c86bdedcd2",
5
5
  "version": 1,
6
6
  "metadata": {
7
7
  "component": {
8
8
  "type": "library",
9
9
  "name": "@floegence/flowersec-core",
10
- "version": "2.4.2",
11
- "purl": "pkg:npm/%40floegence/flowersec-core@2.4.2",
12
- "bom-ref": "pkg:npm/%40floegence/flowersec-core@2.4.2"
10
+ "version": "2.5.1",
11
+ "purl": "pkg:npm/%40floegence/flowersec-core@2.5.1",
12
+ "bom-ref": "pkg:npm/%40floegence/flowersec-core@2.5.1"
13
13
  },
14
14
  "properties": [
15
15
  {
16
16
  "name": "flowersec:source-inventory-sha256",
17
- "value": "59d233df0e12f2c371ab542c83edf97a2968a75c7d17c057e453b97f530a90e4"
17
+ "value": "aba1d1c470bb7af7da0d63211ac38f323b17e6e6f91337c0951508521d23b2b0"
18
18
  }
19
19
  ]
20
20
  },
@@ -190,7 +190,7 @@
190
190
  ],
191
191
  "dependencies": [
192
192
  {
193
- "ref": "pkg:npm/%40floegence/flowersec-core@2.4.2",
193
+ "ref": "pkg:npm/%40floegence/flowersec-core@2.5.1",
194
194
  "dependsOn": [
195
195
  "pkg:npm/%40noble/ciphers@2.3.0",
196
196
  "pkg:npm/%40noble/curves@2.3.0",
package/sbom/spdx.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "dataLicense": "CC0-1.0",
4
4
  "SPDXID": "SPDXRef-DOCUMENT",
5
5
  "name": "flowersec-ts",
6
- "documentNamespace": "https://github.com/floegence/flowersec/sbom/flowersec-ts/59d233df0e12f2c371ab542c83edf97a2968a75c7d17c057e453b97f530a90e4",
6
+ "documentNamespace": "https://github.com/floegence/flowersec/sbom/flowersec-ts/aba1d1c470bb7af7da0d63211ac38f323b17e6e6f91337c0951508521d23b2b0",
7
7
  "creationInfo": {
8
8
  "created": "1970-01-01T00:00:00Z",
9
9
  "creators": [
@@ -13,19 +13,19 @@
13
13
  "packages": [
14
14
  {
15
15
  "name": "@floegence/flowersec-core",
16
- "SPDXID": "SPDXRef-Package-9eec732cc29715c69e1e",
17
- "versionInfo": "2.4.2",
16
+ "SPDXID": "SPDXRef-Package-8e2bb9ca6799b3b43dc6",
17
+ "versionInfo": "2.5.1",
18
18
  "downloadLocation": "NOASSERTION",
19
19
  "filesAnalyzed": false,
20
20
  "licenseConcluded": "NOASSERTION",
21
21
  "licenseDeclared": "NOASSERTION",
22
22
  "copyrightText": "NOASSERTION",
23
- "comment": "Flowersec source inventory SHA-256: 59d233df0e12f2c371ab542c83edf97a2968a75c7d17c057e453b97f530a90e4",
23
+ "comment": "Flowersec source inventory SHA-256: aba1d1c470bb7af7da0d63211ac38f323b17e6e6f91337c0951508521d23b2b0",
24
24
  "externalRefs": [
25
25
  {
26
26
  "referenceCategory": "PACKAGE-MANAGER",
27
27
  "referenceType": "purl",
28
- "referenceLocator": "pkg:npm/%40floegence/flowersec-core@2.4.2"
28
+ "referenceLocator": "pkg:npm/%40floegence/flowersec-core@2.5.1"
29
29
  }
30
30
  ]
31
31
  },
@@ -136,30 +136,30 @@
136
136
  {
137
137
  "spdxElementId": "SPDXRef-DOCUMENT",
138
138
  "relationshipType": "DESCRIBES",
139
- "relatedSpdxElement": "SPDXRef-Package-9eec732cc29715c69e1e"
139
+ "relatedSpdxElement": "SPDXRef-Package-8e2bb9ca6799b3b43dc6"
140
140
  },
141
141
  {
142
- "spdxElementId": "SPDXRef-Package-9eec732cc29715c69e1e",
142
+ "spdxElementId": "SPDXRef-Package-8e2bb9ca6799b3b43dc6",
143
143
  "relationshipType": "DEPENDS_ON",
144
144
  "relatedSpdxElement": "SPDXRef-Package-5ce913a03239b02770fb"
145
145
  },
146
146
  {
147
- "spdxElementId": "SPDXRef-Package-9eec732cc29715c69e1e",
147
+ "spdxElementId": "SPDXRef-Package-8e2bb9ca6799b3b43dc6",
148
148
  "relationshipType": "DEPENDS_ON",
149
149
  "relatedSpdxElement": "SPDXRef-Package-01009adf60db02c13634"
150
150
  },
151
151
  {
152
- "spdxElementId": "SPDXRef-Package-9eec732cc29715c69e1e",
152
+ "spdxElementId": "SPDXRef-Package-8e2bb9ca6799b3b43dc6",
153
153
  "relationshipType": "DEPENDS_ON",
154
154
  "relatedSpdxElement": "SPDXRef-Package-8815b117c8a1d5f7eeb0"
155
155
  },
156
156
  {
157
- "spdxElementId": "SPDXRef-Package-9eec732cc29715c69e1e",
157
+ "spdxElementId": "SPDXRef-Package-8e2bb9ca6799b3b43dc6",
158
158
  "relationshipType": "DEPENDS_ON",
159
159
  "relatedSpdxElement": "SPDXRef-Package-f8b45a289df643042b94"
160
160
  },
161
161
  {
162
- "spdxElementId": "SPDXRef-Package-9eec732cc29715c69e1e",
162
+ "spdxElementId": "SPDXRef-Package-8e2bb9ca6799b3b43dc6",
163
163
  "relationshipType": "DEPENDS_ON",
164
164
  "relatedSpdxElement": "SPDXRef-Package-b779412f685822663496"
165
165
  },