@floegence/flowersec-core 3.0.4 → 3.1.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.
@@ -57,6 +57,14 @@ export type ConnectionControllerSnapshotV3<Session extends ManagedSessionV3 = Ma
57
57
  failure?: ConnectionControllerFailureV3;
58
58
  retryDisposition?: RetryDispositionV3;
59
59
  }>;
60
+ export type ConnectionDiagnosticV3 = Readonly<{
61
+ state: ConnectionControllerStateV3;
62
+ attempt: number;
63
+ failure?: ConnectionControllerFailureV3;
64
+ retryDisposition?: RetryDispositionV3;
65
+ }>;
66
+ /** Produces a stable diagnostic value without retaining a Session or transport detail. */
67
+ export declare function connectionDiagnosticV3(snapshot: ConnectionControllerSnapshotV3): ConnectionDiagnosticV3;
60
68
  export type ConnectionControllerOptionsV3 = Readonly<{
61
69
  maximumAttempts?: number;
62
70
  clock?: ControllerClockV3;
@@ -68,7 +76,8 @@ export declare class ConnectionControllerV3Error extends Error {
68
76
  readonly code: "failed" | "closed" | "canceled";
69
77
  readonly failure?: ConnectionControllerFailureV3 | undefined;
70
78
  readonly retryDisposition?: RetryDispositionV3 | undefined;
71
- constructor(code: "failed" | "closed" | "canceled", failure?: ConnectionControllerFailureV3 | undefined, retryDisposition?: RetryDispositionV3 | undefined);
79
+ readonly diagnostic: ConnectionDiagnosticV3;
80
+ constructor(code: "failed" | "closed" | "canceled", failure?: ConnectionControllerFailureV3 | undefined, retryDisposition?: RetryDispositionV3 | undefined, diagnostic?: ConnectionDiagnosticV3);
72
81
  }
73
82
  export declare class ConnectionControllerV3<Session extends ManagedSessionV3 = ManagedSessionV3> {
74
83
  #private;
@@ -8,16 +8,40 @@ const ARTIFACT_SOURCE_FAILURE_CODES_V3 = new Set([
8
8
  "connection_failed",
9
9
  "expired_artifact",
10
10
  ]);
11
+ /** Produces a stable diagnostic value without retaining a Session or transport detail. */
12
+ export function connectionDiagnosticV3(snapshot) {
13
+ const failure = snapshot.failure === undefined
14
+ ? undefined
15
+ : Object.freeze({ phase: snapshot.failure.phase, code: snapshot.failure.code });
16
+ const retryDisposition = snapshot.retryDisposition === undefined
17
+ ? undefined
18
+ : validateRetryDispositionV3(snapshot.retryDisposition);
19
+ return Object.freeze({
20
+ state: snapshot.state,
21
+ attempt: snapshot.attempt,
22
+ ...(failure === undefined ? {} : { failure }),
23
+ ...(retryDisposition === undefined ? {} : { retryDisposition }),
24
+ });
25
+ }
11
26
  export class ConnectionControllerV3Error extends Error {
12
27
  code;
13
28
  failure;
14
29
  retryDisposition;
15
- constructor(code, failure, retryDisposition) {
16
- super(`Flowersec v3 connection controller stopped (code=${code})`);
30
+ diagnostic;
31
+ constructor(code, failure, retryDisposition, diagnostic) {
32
+ super(`Flowersec connection controller stopped (code=${code})`);
17
33
  this.code = code;
18
34
  this.failure = failure;
19
35
  this.retryDisposition = retryDisposition;
20
36
  this.name = "ConnectionControllerError";
37
+ this.diagnostic = diagnostic ?? Object.freeze({
38
+ state: code === "failed" ? "failed" : code === "closed" ? "closed" : "idle",
39
+ attempt: 0,
40
+ ...(failure === undefined ? {} : { failure }),
41
+ ...(retryDisposition === undefined ? {} : {
42
+ retryDisposition: validateRetryDispositionV3(retryDisposition),
43
+ }),
44
+ });
21
45
  }
22
46
  }
23
47
  export class ConnectionControllerV3 {
@@ -95,15 +119,22 @@ export class ConnectionControllerV3 {
95
119
  if (this.currentSession !== undefined)
96
120
  return this.currentSession;
97
121
  if (this.#state === "failed") {
98
- throw new ConnectionControllerV3Error("failed", this.#failure, this.#disposition);
122
+ const snapshot = this.#snapshot();
123
+ throw new ConnectionControllerV3Error("failed", this.#failure, this.#disposition, connectionDiagnosticV3(snapshot));
99
124
  }
100
125
  if (this.#state === "closed") {
101
- throw new ConnectionControllerV3Error("closed", this.#failure, this.#disposition);
126
+ const snapshot = this.#snapshot();
127
+ throw new ConnectionControllerV3Error("closed", this.#failure, this.#disposition, connectionDiagnosticV3(snapshot));
128
+ }
129
+ if (options.signal?.aborted === true) {
130
+ throw new ConnectionControllerV3Error("canceled", undefined, undefined, connectionDiagnosticV3(this.#snapshot()));
102
131
  }
103
- if (options.signal?.aborted === true)
104
- throw new ConnectionControllerV3Error("canceled");
105
132
  return await new Promise((resolve, reject) => {
133
+ let settled = false;
106
134
  const finish = (session, error) => {
135
+ if (settled)
136
+ return;
137
+ settled = true;
107
138
  this.#listeners.delete(listener);
108
139
  options.signal?.removeEventListener("abort", canceled);
109
140
  session === undefined ? reject(error) : resolve(session);
@@ -113,15 +144,22 @@ export class ConnectionControllerV3 {
113
144
  finish(snapshot.currentSession);
114
145
  }
115
146
  else if (snapshot.state === "failed") {
116
- finish(undefined, new ConnectionControllerV3Error("failed", snapshot.failure, snapshot.retryDisposition));
147
+ finish(undefined, new ConnectionControllerV3Error("failed", snapshot.failure, snapshot.retryDisposition, connectionDiagnosticV3(snapshot)));
117
148
  }
118
149
  else if (snapshot.state === "closed") {
119
- finish(undefined, new ConnectionControllerV3Error("closed", snapshot.failure, snapshot.retryDisposition));
150
+ finish(undefined, new ConnectionControllerV3Error("closed", snapshot.failure, snapshot.retryDisposition, connectionDiagnosticV3(snapshot)));
120
151
  }
121
152
  };
122
- const canceled = () => finish(undefined, new ConnectionControllerV3Error("canceled"));
153
+ const canceled = () => {
154
+ const snapshot = this.#snapshot();
155
+ finish(undefined, new ConnectionControllerV3Error("canceled", undefined, undefined, connectionDiagnosticV3(snapshot)));
156
+ };
123
157
  this.#listeners.add(listener);
124
158
  options.signal?.addEventListener("abort", canceled, { once: true });
159
+ if (options.signal?.aborted === true)
160
+ canceled();
161
+ else
162
+ listener(this.#snapshot());
125
163
  });
126
164
  }
127
165
  close() {
@@ -190,10 +228,10 @@ export class ConnectionControllerV3 {
190
228
  if (acquisition.kind === "failure") {
191
229
  const error = sourceFailure(acquisition);
192
230
  const ordinal = this.#cycle.recordFailedAcquisitionOrLease();
193
- this.#recordFailure("artifact", error.code, error.disposition);
194
- if (error.disposition.kind === "terminal" || this.#attemptBudgetExhausted())
231
+ this.#recordFailure("artifact", error.code, error.retryDisposition);
232
+ if (error.retryDisposition.kind === "terminal" || this.#attemptBudgetExhausted())
195
233
  return;
196
- pendingDisposition = error.disposition;
234
+ pendingDisposition = error.retryDisposition;
197
235
  void ordinal;
198
236
  continue;
199
237
  }
@@ -222,7 +260,7 @@ export class ConnectionControllerV3 {
222
260
  await retireArtifactLeaseV3(claim);
223
261
  this.#cycle.recordFailedAcquisitionOrLease();
224
262
  const error = new ConnectErrorV3("artifact_invalid", { kind: "terminal" });
225
- this.#recordFailure("connect", error.code, error.disposition);
263
+ this.#recordFailure("connect", error.code, error.retryDisposition);
226
264
  return;
227
265
  }
228
266
  try {
@@ -232,12 +270,12 @@ export class ConnectionControllerV3 {
232
270
  await retireArtifactLeaseV3(claim);
233
271
  this.#cycle.recordFailedAcquisitionOrLease();
234
272
  const error = new ConnectErrorV3("expired_artifact", { kind: "retryable" });
235
- this.#recordFailure("connect", error.code, error.disposition);
273
+ this.#recordFailure("connect", error.code, error.retryDisposition);
236
274
  if (this.#attemptBudgetExhausted())
237
275
  return;
238
276
  next = "primary";
239
277
  replacementContext = undefined;
240
- pendingDisposition = error.disposition;
278
+ pendingDisposition = error.retryDisposition;
241
279
  continue;
242
280
  }
243
281
  const candidates = next === "replacement"
@@ -249,7 +287,7 @@ export class ConnectionControllerV3 {
249
287
  const error = next === "replacement"
250
288
  ? replacementTerminal(replacementContext)
251
289
  : this.#cycle.blockedPolicyTerminal();
252
- this.#recordFailure("connect", error.code, error.disposition);
290
+ this.#recordFailure("connect", error.code, error.retryDisposition);
253
291
  return;
254
292
  }
255
293
  let rawResult;
@@ -319,12 +357,12 @@ export class ConnectionControllerV3 {
319
357
  let sessionFailure;
320
358
  try {
321
359
  sessionFailure = this.#projectSessionFailure(termination.error);
322
- validateRetryDispositionV3(sessionFailure.disposition);
360
+ validateRetryDispositionV3(sessionFailure.retryDisposition);
323
361
  }
324
362
  catch {
325
363
  sessionFailure = new ConnectErrorV3("connection_failed", { kind: "terminal" });
326
364
  }
327
- const disposition = sessionFailure.disposition;
365
+ const disposition = sessionFailure.retryDisposition;
328
366
  this.#cycle.recordFailedAcquisitionOrLease();
329
367
  this.#recordFailure("session", sessionFailure.code, disposition);
330
368
  if (disposition.kind === "terminal")
@@ -345,13 +383,13 @@ export class ConnectionControllerV3 {
345
383
  const error = next === "replacement" && result.error.code !== "expired_artifact"
346
384
  ? replacementTerminal(replacementContext)
347
385
  : result.error;
348
- const disposition = error.disposition;
386
+ const disposition = error.retryDisposition;
349
387
  this.#recordFailure("connect", error.code, disposition);
350
388
  if (disposition.kind === "terminal" || this.#attemptBudgetExhausted())
351
389
  return;
352
390
  next = "primary";
353
391
  replacementContext = undefined;
354
- pendingDisposition = result.error.disposition;
392
+ pendingDisposition = result.error.retryDisposition;
355
393
  continue;
356
394
  }
357
395
  if (result.kind === "post_spend_failure") {
@@ -365,12 +403,12 @@ export class ConnectionControllerV3 {
365
403
  };
366
404
  }
367
405
  this.#cycle.recordFailedAcquisitionOrLease();
368
- this.#recordFailure("connect", postSpendResult.error.code, postSpendResult.error.disposition);
369
- if (postSpendResult.error.disposition.kind === "terminal" || this.#attemptBudgetExhausted())
406
+ this.#recordFailure("connect", postSpendResult.error.code, postSpendResult.error.retryDisposition);
407
+ if (postSpendResult.error.retryDisposition.kind === "terminal" || this.#attemptBudgetExhausted())
370
408
  return;
371
409
  next = "primary";
372
410
  replacementContext = undefined;
373
- pendingDisposition = postSpendResult.error.disposition;
411
+ pendingDisposition = postSpendResult.error.retryDisposition;
374
412
  continue;
375
413
  }
376
414
  if (artifactLeaseStateV3(claim) !== "claimed") {
@@ -382,17 +420,17 @@ export class ConnectionControllerV3 {
382
420
  this.#cycle.recordFailedAcquisitionOrLease();
383
421
  if (isExpired(artifact, this.#nowUnixSeconds)) {
384
422
  const error = new ConnectErrorV3("expired_artifact", { kind: "retryable" });
385
- this.#recordFailure("connect", error.code, error.disposition);
423
+ this.#recordFailure("connect", error.code, error.retryDisposition);
386
424
  if (this.#attemptBudgetExhausted())
387
425
  return;
388
426
  next = "primary";
389
427
  replacementContext = undefined;
390
- pendingDisposition = error.disposition;
428
+ pendingDisposition = error.retryDisposition;
391
429
  continue;
392
430
  }
393
431
  if (next === "replacement") {
394
432
  const error = replacementTerminal(replacementContext);
395
- this.#recordFailure("connect", error.code, error.disposition);
433
+ this.#recordFailure("connect", error.code, error.retryDisposition);
396
434
  return;
397
435
  }
398
436
  const triggerKeys = blockPolicyRefreshTriggersV3(artifact.path.kind, result.failures, this.#cycle);
@@ -406,14 +444,14 @@ export class ConnectionControllerV3 {
406
444
  }
407
445
  if (triggerKeys.size > 0 && refresh.code === "connection_failed") {
408
446
  const terminal = this.#cycle.blockedPolicyTerminal();
409
- this.#recordFailure("connect", terminal.code, terminal.disposition);
447
+ this.#recordFailure("connect", terminal.code, terminal.retryDisposition);
410
448
  return;
411
449
  }
412
- this.#recordFailure("connect", refresh.code, refresh.disposition);
413
- if (refresh.disposition.kind === "terminal" || this.#attemptBudgetExhausted())
450
+ this.#recordFailure("connect", refresh.code, refresh.retryDisposition);
451
+ if (refresh.retryDisposition.kind === "terminal" || this.#attemptBudgetExhausted())
414
452
  return;
415
453
  next = "primary";
416
- pendingDisposition = refresh.disposition;
454
+ pendingDisposition = refresh.retryDisposition;
417
455
  }
418
456
  }
419
457
  async #acquire() {
@@ -467,7 +505,7 @@ export class ConnectionControllerV3 {
467
505
  return {
468
506
  kind: "failure",
469
507
  code: error.code,
470
- disposition: validateRetryDispositionV3(error.disposition),
508
+ disposition: validateRetryDispositionV3(error.retryDisposition),
471
509
  };
472
510
  }
473
511
  catch {
@@ -696,7 +734,7 @@ function normalizeLeaseAttemptResultV3(value, candidates, capability) {
696
734
  const error = Reflect.get(value, "error");
697
735
  if (!(error instanceof ConnectErrorV3) || !CONNECT_ERROR_CODES_V3.has(error.code))
698
736
  return undefined;
699
- const normalizedError = new ConnectErrorV3(error.code, validateRetryDispositionV3(error.disposition));
737
+ const normalizedError = new ConnectErrorV3(error.code, validateRetryDispositionV3(error.retryDisposition));
700
738
  return Object.freeze({ kind, error: normalizedError });
701
739
  }
702
740
  catch {
@@ -206,7 +206,7 @@ export class ControllerRetryWaitV3 {
206
206
  this.#waiting = true;
207
207
  this.#manual = false;
208
208
  this.#absoluteDeadline = validated.kind === "retry_after"
209
- ? validated.absoluteUnixMilliseconds
209
+ ? validated.notBeforeUnixMilliseconds
210
210
  : undefined;
211
211
  try {
212
212
  while (!signal.aborted) {
@@ -264,11 +264,21 @@ function saturatingDifferenceMilliseconds(deadline, now) {
264
264
  function validateControllerWaitDisposition(value) {
265
265
  if (value.kind === "terminal" || value.kind === "retryable")
266
266
  return value;
267
- if (value.kind !== "retry_after" || !Number.isSafeInteger(value.absoluteUnixMilliseconds) ||
268
- value.absoluteUnixMilliseconds < 0 || value.absoluteUnixMilliseconds > 253_402_300_799_999) {
267
+ if (value.kind !== "retry_after") {
269
268
  throw new ConnectErrorV3("artifact_invalid", { kind: "terminal" });
270
269
  }
271
- return value;
270
+ const deadline = value.notBeforeUnixMilliseconds ?? value.absoluteUnixMilliseconds;
271
+ if (deadline === undefined || !Number.isSafeInteger(deadline) || deadline < 0 ||
272
+ deadline > 253_402_300_799_999 || value.notBeforeUnixMilliseconds !== undefined &&
273
+ value.absoluteUnixMilliseconds !== undefined &&
274
+ value.notBeforeUnixMilliseconds !== value.absoluteUnixMilliseconds) {
275
+ throw new ConnectErrorV3("artifact_invalid", { kind: "terminal" });
276
+ }
277
+ return Object.freeze({
278
+ kind: "retry_after",
279
+ notBeforeUnixMilliseconds: deadline,
280
+ absoluteUnixMilliseconds: deadline,
281
+ });
272
282
  }
273
283
  function controllerBackoffForWait(consecutiveFailure) {
274
284
  if (!Number.isSafeInteger(consecutiveFailure) || consecutiveFailure < 1) {
@@ -13,12 +13,22 @@ export type RetryDispositionV3 = Readonly<{
13
13
  kind: "retryable";
14
14
  }> | Readonly<{
15
15
  kind: "retry_after";
16
+ notBeforeUnixMilliseconds: number;
17
+ /** @deprecated Use notBeforeUnixMilliseconds. */
18
+ absoluteUnixMilliseconds?: number;
19
+ }>;
20
+ type RetryDispositionInputV3 = RetryDispositionV3 | Readonly<{
21
+ kind: "retry_after";
22
+ /** @deprecated Use notBeforeUnixMilliseconds. */
16
23
  absoluteUnixMilliseconds: number;
24
+ notBeforeUnixMilliseconds?: number;
17
25
  }>;
18
26
  export declare class ConnectErrorV3 extends Error {
19
27
  readonly code: PublicConnectErrorCodeV3;
20
- readonly disposition: RetryDispositionV3;
21
- constructor(code: PublicConnectErrorCodeV3, disposition: RetryDispositionV3);
28
+ readonly retryDisposition: RetryDispositionV3;
29
+ constructor(code: PublicConnectErrorCodeV3, disposition: RetryDispositionInputV3);
30
+ /** @deprecated Use retryDisposition. */
31
+ get disposition(): RetryDispositionV3;
22
32
  }
23
33
  export type TransportSecuritySnapshotV3 = Readonly<{
24
34
  mode: "ca";
@@ -29,6 +39,7 @@ export type TransportSecuritySnapshotV3 = Readonly<{
29
39
  }>;
30
40
  export declare function snapshotTransportSecurityPolicyV3(policy: TransportSecurityPolicyV3, attemptNowUnixSeconds: number, supportedModes: readonly ("ca" | "pin")[]): TransportSecuritySnapshotV3;
31
41
  export declare function projectTransportFailureV3(failure: TransportFailureV3, _policyMode: "ca" | "pin"): ConnectErrorV3;
32
- export declare function validateRetryDispositionV3(value: RetryDispositionV3): RetryDispositionV3;
33
- export declare function aggregateRetryDispositionsV3(values: readonly RetryDispositionV3[]): RetryDispositionV3;
42
+ export declare function validateRetryDispositionV3(value: RetryDispositionInputV3): RetryDispositionV3;
43
+ export declare function aggregateRetryDispositionsV3(values: readonly RetryDispositionInputV3[]): RetryDispositionV3;
34
44
  export declare function controllerBackoffMillisecondsV3(consecutiveFailure: number): number;
45
+ export {};
@@ -11,13 +11,15 @@ export class TransportFailureV3 extends Error {
11
11
  }
12
12
  export class ConnectErrorV3 extends Error {
13
13
  code;
14
- disposition;
14
+ retryDisposition;
15
15
  constructor(code, disposition) {
16
16
  super(`Flowersec connection failed (code=${code})`);
17
17
  this.code = code;
18
- this.disposition = disposition;
19
18
  this.name = "ConnectError";
19
+ this.retryDisposition = validateRetryDispositionValueV3(disposition);
20
20
  }
21
+ /** @deprecated Use retryDisposition. */
22
+ get disposition() { return this.retryDisposition; }
21
23
  }
22
24
  export function snapshotTransportSecurityPolicyV3(policy, attemptNowUnixSeconds, supportedModes) {
23
25
  if (!Number.isSafeInteger(attemptNowUnixSeconds) || attemptNowUnixSeconds < 0) {
@@ -64,28 +66,26 @@ export function projectTransportFailureV3(failure, _policyMode) {
64
66
  }
65
67
  }
66
68
  export function validateRetryDispositionV3(value) {
67
- if (value.kind === "terminal")
68
- return terminal();
69
- if (value.kind === "retryable")
70
- return retryable();
71
- if (value.kind !== "retry_after" || !Number.isSafeInteger(value.absoluteUnixMilliseconds) ||
72
- value.absoluteUnixMilliseconds < 0 || value.absoluteUnixMilliseconds > 253_402_300_799_999) {
69
+ try {
70
+ return validateRetryDispositionValueV3(value);
71
+ }
72
+ catch {
73
73
  throw new ConnectErrorV3("artifact_invalid", terminal());
74
74
  }
75
- return Object.freeze({ kind: "retry_after", absoluteUnixMilliseconds: value.absoluteUnixMilliseconds });
76
75
  }
77
76
  export function aggregateRetryDispositionsV3(values) {
78
77
  let latest;
79
78
  let canRetry = false;
80
79
  for (const input of values) {
81
80
  const value = validateRetryDispositionV3(input);
82
- if (value.kind === "retry_after")
83
- latest = Math.max(latest ?? 0, value.absoluteUnixMilliseconds);
81
+ if (value.kind === "retry_after") {
82
+ latest = Math.max(latest ?? 0, value.notBeforeUnixMilliseconds);
83
+ }
84
84
  else if (value.kind === "retryable")
85
85
  canRetry = true;
86
86
  }
87
87
  if (latest !== undefined)
88
- return Object.freeze({ kind: "retry_after", absoluteUnixMilliseconds: latest });
88
+ return retryAfter(latest);
89
89
  return canRetry ? retryable() : terminal();
90
90
  }
91
91
  export function controllerBackoffMillisecondsV3(consecutiveFailure) {
@@ -98,3 +98,23 @@ export function controllerBackoffMillisecondsV3(consecutiveFailure) {
98
98
  }
99
99
  const terminal = () => Object.freeze({ kind: "terminal" });
100
100
  const retryable = () => Object.freeze({ kind: "retryable" });
101
+ const retryAfter = (notBeforeUnixMilliseconds) => Object.freeze({
102
+ kind: "retry_after",
103
+ notBeforeUnixMilliseconds,
104
+ absoluteUnixMilliseconds: notBeforeUnixMilliseconds,
105
+ });
106
+ function validateRetryDispositionValueV3(value) {
107
+ if (value.kind === "terminal")
108
+ return terminal();
109
+ if (value.kind === "retryable")
110
+ return retryable();
111
+ const legacy = value.absoluteUnixMilliseconds;
112
+ const canonical = value.notBeforeUnixMilliseconds;
113
+ const deadline = canonical ?? legacy;
114
+ if (deadline === undefined ||
115
+ canonical !== undefined && legacy !== undefined && canonical !== legacy ||
116
+ !Number.isSafeInteger(deadline) || deadline < 0 || deadline > 253_402_300_799_999) {
117
+ throw new TypeError("invalid Flowersec retry-after deadline");
118
+ }
119
+ return retryAfter(deadline);
120
+ }
@@ -38,10 +38,12 @@ class InternalUnreliableMessageChannelV3 {
38
38
  }
39
39
  async send(message, options) {
40
40
  throwIfAborted(options.signal);
41
- if (!(message instanceof Uint8Array) || message.byteLength < 1 ||
42
- message.byteLength > UNRELIABLE_MESSAGE_MAX_PLAINTEXT_BYTES_V3) {
41
+ if (!(message instanceof Uint8Array) || message.byteLength < 1) {
43
42
  throw new UnreliableMessageError("invalid_message");
44
43
  }
44
+ if (message.byteLength > UNRELIABLE_MESSAGE_MAX_PLAINTEXT_BYTES_V3) {
45
+ throw new UnreliableMessageError("too_large");
46
+ }
45
47
  const payload = message.slice();
46
48
  const expiresAt = requireFutureExpiry(options.expiresAtUnixMs, this.now());
47
49
  if (expiresAt === undefined)
@@ -74,8 +76,8 @@ class InternalUnreliableMessageChannelV3 {
74
76
  });
75
77
  }
76
78
  catch (error) {
77
- if (error instanceof DOMException && error.name === "AbortError")
78
- throw error;
79
+ if (isAbortError(error))
80
+ throw new UnreliableMessageError("canceled");
79
81
  throw new UnreliableMessageError("operation_failed");
80
82
  }
81
83
  finally {
@@ -91,7 +93,7 @@ class InternalUnreliableMessageChannelV3 {
91
93
  }
92
94
  catch (error) {
93
95
  if (isAbortError(error))
94
- throw error;
96
+ throw new UnreliableMessageError("canceled");
95
97
  throw new UnreliableMessageError("closed");
96
98
  }
97
99
  if (isPreviousVersionDatagram(wire)) {
@@ -241,7 +243,7 @@ function requireFutureExpiry(value, now) {
241
243
  }
242
244
  function throwIfAborted(signal) {
243
245
  if (signal?.aborted === true)
244
- throw new DOMException("operation aborted", "AbortError");
246
+ throw new UnreliableMessageError("canceled");
245
247
  }
246
248
  function isAbortError(error) {
247
249
  return error instanceof DOMException && error.name === "AbortError" ||
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@floegence/flowersec-core",
3
- "version": "3.0.4",
3
+ "version": "3.1.1",
4
4
  "description": "Flowersec core TypeScript library for carrier-neutral encrypted sessions and multiplexed streams.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -93,7 +93,7 @@
93
93
  "vitest": "4.1.10"
94
94
  },
95
95
  "optionalDependencies": {
96
- "@floegence/flowersec-node-native": "3.0.4"
96
+ "@floegence/flowersec-node-native": "3.1.1"
97
97
  },
98
- "flowersecSourceCommit": "35dbe22a6aa1b10d53587e19a18232e2dfb2bbf4"
98
+ "flowersecSourceCommit": "ef37df09147b1b08f2a5aaaf3cd0760806afd312"
99
99
  }
@@ -1,20 +1,20 @@
1
1
  {
2
2
  "bomFormat": "CycloneDX",
3
3
  "specVersion": "1.5",
4
- "serialNumber": "urn:uuid:cff299ba-9035-5c07-8271-4cad66e78e07",
4
+ "serialNumber": "urn:uuid:77052be3-258a-5fb4-894e-2b8f821f3bdf",
5
5
  "version": 1,
6
6
  "metadata": {
7
7
  "component": {
8
8
  "type": "library",
9
9
  "name": "@floegence/flowersec-core",
10
- "version": "3.0.4",
11
- "purl": "pkg:npm/%40floegence/flowersec-core@3.0.4",
12
- "bom-ref": "pkg:npm/%40floegence/flowersec-core@3.0.4"
10
+ "version": "3.1.1",
11
+ "purl": "pkg:npm/%40floegence/flowersec-core@3.1.1",
12
+ "bom-ref": "pkg:npm/%40floegence/flowersec-core@3.1.1"
13
13
  },
14
14
  "properties": [
15
15
  {
16
16
  "name": "flowersec:source-inventory-sha256",
17
- "value": "af5a7b36732531ffcf37270c1412322cd50ddf095686ccd1bf28d2d95703edca"
17
+ "value": "af1844fd4e36b6f817976846fd645bffb060c3d9dfa1f94f579d043b7a13f735"
18
18
  }
19
19
  ]
20
20
  },
@@ -22,9 +22,9 @@
22
22
  {
23
23
  "type": "library",
24
24
  "name": "@floegence/flowersec-node-native",
25
- "version": "3.0.4",
26
- "purl": "pkg:npm/%40floegence/flowersec-node-native@3.0.4",
27
- "bom-ref": "pkg:npm/%40floegence/flowersec-node-native@3.0.4",
25
+ "version": "3.1.1",
26
+ "purl": "pkg:npm/%40floegence/flowersec-node-native@3.1.1",
27
+ "bom-ref": "pkg:npm/%40floegence/flowersec-node-native@3.1.1",
28
28
  "licenses": [
29
29
  {
30
30
  "expression": "MIT"
@@ -50,9 +50,9 @@
50
50
  {
51
51
  "type": "library",
52
52
  "name": "@floegence/flowersec-node-native-darwin-arm64",
53
- "version": "3.0.4",
54
- "purl": "pkg:npm/%40floegence/flowersec-node-native-darwin-arm64@3.0.4",
55
- "bom-ref": "pkg:npm/%40floegence/flowersec-node-native-darwin-arm64@3.0.4",
53
+ "version": "3.1.1",
54
+ "purl": "pkg:npm/%40floegence/flowersec-node-native-darwin-arm64@3.1.1",
55
+ "bom-ref": "pkg:npm/%40floegence/flowersec-node-native-darwin-arm64@3.1.1",
56
56
  "licenses": [
57
57
  {
58
58
  "expression": "MIT"
@@ -78,9 +78,9 @@
78
78
  {
79
79
  "type": "library",
80
80
  "name": "@floegence/flowersec-node-native-darwin-x64",
81
- "version": "3.0.4",
82
- "purl": "pkg:npm/%40floegence/flowersec-node-native-darwin-x64@3.0.4",
83
- "bom-ref": "pkg:npm/%40floegence/flowersec-node-native-darwin-x64@3.0.4",
81
+ "version": "3.1.1",
82
+ "purl": "pkg:npm/%40floegence/flowersec-node-native-darwin-x64@3.1.1",
83
+ "bom-ref": "pkg:npm/%40floegence/flowersec-node-native-darwin-x64@3.1.1",
84
84
  "licenses": [
85
85
  {
86
86
  "expression": "MIT"
@@ -106,9 +106,9 @@
106
106
  {
107
107
  "type": "library",
108
108
  "name": "@floegence/flowersec-node-native-linux-arm64-gnu",
109
- "version": "3.0.4",
110
- "purl": "pkg:npm/%40floegence/flowersec-node-native-linux-arm64-gnu@3.0.4",
111
- "bom-ref": "pkg:npm/%40floegence/flowersec-node-native-linux-arm64-gnu@3.0.4",
109
+ "version": "3.1.1",
110
+ "purl": "pkg:npm/%40floegence/flowersec-node-native-linux-arm64-gnu@3.1.1",
111
+ "bom-ref": "pkg:npm/%40floegence/flowersec-node-native-linux-arm64-gnu@3.1.1",
112
112
  "licenses": [
113
113
  {
114
114
  "expression": "MIT"
@@ -134,9 +134,9 @@
134
134
  {
135
135
  "type": "library",
136
136
  "name": "@floegence/flowersec-node-native-linux-x64-gnu",
137
- "version": "3.0.4",
138
- "purl": "pkg:npm/%40floegence/flowersec-node-native-linux-x64-gnu@3.0.4",
139
- "bom-ref": "pkg:npm/%40floegence/flowersec-node-native-linux-x64-gnu@3.0.4",
137
+ "version": "3.1.1",
138
+ "purl": "pkg:npm/%40floegence/flowersec-node-native-linux-x64-gnu@3.1.1",
139
+ "bom-ref": "pkg:npm/%40floegence/flowersec-node-native-linux-x64-gnu@3.1.1",
140
140
  "licenses": [
141
141
  {
142
142
  "expression": "MIT"
@@ -330,9 +330,9 @@
330
330
  ],
331
331
  "dependencies": [
332
332
  {
333
- "ref": "pkg:npm/%40floegence/flowersec-core@3.0.4",
333
+ "ref": "pkg:npm/%40floegence/flowersec-core@3.1.1",
334
334
  "dependsOn": [
335
- "pkg:npm/%40floegence/flowersec-node-native@3.0.4",
335
+ "pkg:npm/%40floegence/flowersec-node-native@3.1.1",
336
336
  "pkg:npm/%40noble/ciphers@2.3.0",
337
337
  "pkg:npm/%40noble/curves@2.3.0",
338
338
  "pkg:npm/%40noble/hashes@2.3.0",
@@ -341,28 +341,28 @@
341
341
  ]
342
342
  },
343
343
  {
344
- "ref": "pkg:npm/%40floegence/flowersec-node-native@3.0.4",
344
+ "ref": "pkg:npm/%40floegence/flowersec-node-native@3.1.1",
345
345
  "dependsOn": [
346
- "pkg:npm/%40floegence/flowersec-node-native-darwin-arm64@3.0.4",
347
- "pkg:npm/%40floegence/flowersec-node-native-darwin-x64@3.0.4",
348
- "pkg:npm/%40floegence/flowersec-node-native-linux-arm64-gnu@3.0.4",
349
- "pkg:npm/%40floegence/flowersec-node-native-linux-x64-gnu@3.0.4"
346
+ "pkg:npm/%40floegence/flowersec-node-native-darwin-arm64@3.1.1",
347
+ "pkg:npm/%40floegence/flowersec-node-native-darwin-x64@3.1.1",
348
+ "pkg:npm/%40floegence/flowersec-node-native-linux-arm64-gnu@3.1.1",
349
+ "pkg:npm/%40floegence/flowersec-node-native-linux-x64-gnu@3.1.1"
350
350
  ]
351
351
  },
352
352
  {
353
- "ref": "pkg:npm/%40floegence/flowersec-node-native-darwin-arm64@3.0.4",
353
+ "ref": "pkg:npm/%40floegence/flowersec-node-native-darwin-arm64@3.1.1",
354
354
  "dependsOn": []
355
355
  },
356
356
  {
357
- "ref": "pkg:npm/%40floegence/flowersec-node-native-darwin-x64@3.0.4",
357
+ "ref": "pkg:npm/%40floegence/flowersec-node-native-darwin-x64@3.1.1",
358
358
  "dependsOn": []
359
359
  },
360
360
  {
361
- "ref": "pkg:npm/%40floegence/flowersec-node-native-linux-arm64-gnu@3.0.4",
361
+ "ref": "pkg:npm/%40floegence/flowersec-node-native-linux-arm64-gnu@3.1.1",
362
362
  "dependsOn": []
363
363
  },
364
364
  {
365
- "ref": "pkg:npm/%40floegence/flowersec-node-native-linux-x64-gnu@3.0.4",
365
+ "ref": "pkg:npm/%40floegence/flowersec-node-native-linux-x64-gnu@3.1.1",
366
366
  "dependsOn": []
367
367
  },
368
368
  {