@bcts/gstp 1.0.0-alpha.14

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/dist/index.cjs ADDED
@@ -0,0 +1,1308 @@
1
+ //#region rolldown:runtime
2
+ var __defProp = Object.defineProperty;
3
+ var __exportAll = (all, symbols) => {
4
+ let target = {};
5
+ for (var name in all) {
6
+ __defProp(target, name, {
7
+ get: all[name],
8
+ enumerable: true
9
+ });
10
+ }
11
+ if (symbols) {
12
+ __defProp(target, Symbol.toStringTag, { value: "Module" });
13
+ }
14
+ return target;
15
+ };
16
+
17
+ //#endregion
18
+ let _bcts_components = require("@bcts/components");
19
+ let _bcts_envelope = require("@bcts/envelope");
20
+ let _bcts_known_values = require("@bcts/known-values");
21
+ let _bcts_xid = require("@bcts/xid");
22
+
23
+ //#region src/error.ts
24
+ /**
25
+ * GSTP Error Types
26
+ *
27
+ * Error types returned when operating on GSTP messages.
28
+ * Ported from gstp-rust/src/error.rs
29
+ */
30
+ /**
31
+ * Error codes for GSTP operations.
32
+ */
33
+ let GstpErrorCode = /* @__PURE__ */ function(GstpErrorCode$1) {
34
+ /** Sender must have an encryption key. */
35
+ GstpErrorCode$1["SENDER_MISSING_ENCRYPTION_KEY"] = "SENDER_MISSING_ENCRYPTION_KEY";
36
+ /** Recipient must have an encryption key. */
37
+ GstpErrorCode$1["RECIPIENT_MISSING_ENCRYPTION_KEY"] = "RECIPIENT_MISSING_ENCRYPTION_KEY";
38
+ /** Sender must have a verification key. */
39
+ GstpErrorCode$1["SENDER_MISSING_VERIFICATION_KEY"] = "SENDER_MISSING_VERIFICATION_KEY";
40
+ /** Continuation has expired. */
41
+ GstpErrorCode$1["CONTINUATION_EXPIRED"] = "CONTINUATION_EXPIRED";
42
+ /** Continuation ID is invalid. */
43
+ GstpErrorCode$1["CONTINUATION_ID_INVALID"] = "CONTINUATION_ID_INVALID";
44
+ /** Peer continuation must be encrypted. */
45
+ GstpErrorCode$1["PEER_CONTINUATION_NOT_ENCRYPTED"] = "PEER_CONTINUATION_NOT_ENCRYPTED";
46
+ /** Requests must contain a peer continuation. */
47
+ GstpErrorCode$1["MISSING_PEER_CONTINUATION"] = "MISSING_PEER_CONTINUATION";
48
+ /** Error from envelope operations. */
49
+ GstpErrorCode$1["ENVELOPE"] = "ENVELOPE";
50
+ /** Error from XID operations. */
51
+ GstpErrorCode$1["XID"] = "XID";
52
+ return GstpErrorCode$1;
53
+ }({});
54
+ /**
55
+ * Error class for GSTP operations.
56
+ *
57
+ * Provides specific error types that can occur during GSTP message
58
+ * creation, sealing, and parsing operations.
59
+ */
60
+ var GstpError = class GstpError extends Error {
61
+ code;
62
+ constructor(code, message, cause) {
63
+ super(message);
64
+ this.name = "GstpError";
65
+ this.code = code;
66
+ if (cause !== void 0) this.cause = cause;
67
+ if ("captureStackTrace" in Error) Error.captureStackTrace(this, GstpError);
68
+ }
69
+ /**
70
+ * Returned when the sender is missing an encryption key.
71
+ */
72
+ static senderMissingEncryptionKey() {
73
+ return new GstpError(GstpErrorCode.SENDER_MISSING_ENCRYPTION_KEY, "sender must have an encryption key");
74
+ }
75
+ /**
76
+ * Returned when the recipient is missing an encryption key.
77
+ */
78
+ static recipientMissingEncryptionKey() {
79
+ return new GstpError(GstpErrorCode.RECIPIENT_MISSING_ENCRYPTION_KEY, "recipient must have an encryption key");
80
+ }
81
+ /**
82
+ * Returned when the sender is missing a verification key.
83
+ */
84
+ static senderMissingVerificationKey() {
85
+ return new GstpError(GstpErrorCode.SENDER_MISSING_VERIFICATION_KEY, "sender must have a verification key");
86
+ }
87
+ /**
88
+ * Returned when the continuation has expired.
89
+ */
90
+ static continuationExpired() {
91
+ return new GstpError(GstpErrorCode.CONTINUATION_EXPIRED, "continuation expired");
92
+ }
93
+ /**
94
+ * Returned when the continuation ID is invalid.
95
+ */
96
+ static continuationIdInvalid() {
97
+ return new GstpError(GstpErrorCode.CONTINUATION_ID_INVALID, "continuation ID invalid");
98
+ }
99
+ /**
100
+ * Returned when the peer continuation is not encrypted.
101
+ */
102
+ static peerContinuationNotEncrypted() {
103
+ return new GstpError(GstpErrorCode.PEER_CONTINUATION_NOT_ENCRYPTED, "peer continuation must be encrypted");
104
+ }
105
+ /**
106
+ * Returned when a request is missing the peer continuation.
107
+ */
108
+ static missingPeerContinuation() {
109
+ return new GstpError(GstpErrorCode.MISSING_PEER_CONTINUATION, "requests must contain a peer continuation");
110
+ }
111
+ /**
112
+ * Envelope error wrapper.
113
+ */
114
+ static envelope(cause) {
115
+ return new GstpError(GstpErrorCode.ENVELOPE, "envelope error", cause);
116
+ }
117
+ /**
118
+ * XID error wrapper.
119
+ */
120
+ static xid(cause) {
121
+ return new GstpError(GstpErrorCode.XID, "XID error", cause);
122
+ }
123
+ };
124
+
125
+ //#endregion
126
+ //#region src/continuation.ts
127
+ /**
128
+ * Continuation - Encrypted State Continuations (ESC)
129
+ *
130
+ * Continuations embed encrypted state data directly into messages,
131
+ * eliminating the need for local state storage and enhancing security
132
+ * for devices with limited storage or requiring distributed state management.
133
+ *
134
+ * Ported from gstp-rust/src/continuation.rs
135
+ */
136
+ /**
137
+ * Represents an encrypted state continuation.
138
+ *
139
+ * Continuations provide a way to maintain state across message exchanges
140
+ * without requiring local storage. The state is encrypted and embedded
141
+ * directly in the message envelope.
142
+ *
143
+ * @example
144
+ * ```typescript
145
+ * import { Continuation } from '@bcts/gstp';
146
+ *
147
+ * // Create a continuation with state
148
+ * const continuation = new Continuation("session state data")
149
+ * .withValidId(requestId)
150
+ * .withValidUntil(new Date(Date.now() + 60000)); // Valid for 60 seconds
151
+ *
152
+ * // Convert to envelope (optionally encrypted)
153
+ * const envelope = continuation.toEnvelope(recipientPublicKey);
154
+ * ```
155
+ */
156
+ var Continuation = class Continuation {
157
+ _state;
158
+ _validId;
159
+ _validUntil;
160
+ /**
161
+ * Creates a new Continuation with the given state.
162
+ *
163
+ * The state can be any value that implements EnvelopeEncodable.
164
+ *
165
+ * @param state - The state to embed in the continuation
166
+ * @param validId - Optional ID for validation
167
+ * @param validUntil - Optional expiration date
168
+ */
169
+ constructor(state, validId, validUntil) {
170
+ this._state = _bcts_envelope.Envelope.new(state);
171
+ this._validId = validId;
172
+ this._validUntil = validUntil;
173
+ }
174
+ /**
175
+ * Creates a new continuation with a specific valid ID.
176
+ *
177
+ * @param validId - The ID to use for validation
178
+ * @returns A new Continuation instance with the valid ID set
179
+ */
180
+ withValidId(validId) {
181
+ return new Continuation(this._state, validId, this._validUntil);
182
+ }
183
+ /**
184
+ * Creates a new continuation with an optional valid ID.
185
+ *
186
+ * @param validId - The ID to use for validation, or undefined
187
+ * @returns A new Continuation instance with the valid ID set
188
+ */
189
+ withOptionalValidId(validId) {
190
+ return new Continuation(this._state, validId, this._validUntil);
191
+ }
192
+ /**
193
+ * Creates a new continuation with a specific valid until date.
194
+ *
195
+ * @param validUntil - The date until which the continuation is valid
196
+ * @returns A new Continuation instance with the valid until date set
197
+ */
198
+ withValidUntil(validUntil) {
199
+ return new Continuation(this._state, this._validId, validUntil);
200
+ }
201
+ /**
202
+ * Creates a new continuation with an optional valid until date.
203
+ *
204
+ * @param validUntil - The date until which the continuation is valid, or undefined
205
+ * @returns A new Continuation instance with the valid until date set
206
+ */
207
+ withOptionalValidUntil(validUntil) {
208
+ return new Continuation(this._state, this._validId, validUntil);
209
+ }
210
+ /**
211
+ * Creates a new continuation with a validity duration from now.
212
+ *
213
+ * @param durationMs - The duration in milliseconds for which the continuation is valid
214
+ * @returns A new Continuation instance with the valid until date set
215
+ */
216
+ withValidDuration(durationMs) {
217
+ const validUntil = new Date(Date.now() + durationMs);
218
+ return new Continuation(this._state, this._validId, validUntil);
219
+ }
220
+ /**
221
+ * Returns the state envelope of the continuation.
222
+ */
223
+ state() {
224
+ return this._state;
225
+ }
226
+ /**
227
+ * Returns the valid ID of the continuation, if set.
228
+ */
229
+ id() {
230
+ return this._validId;
231
+ }
232
+ /**
233
+ * Returns the valid until date of the continuation, if set.
234
+ */
235
+ validUntil() {
236
+ return this._validUntil;
237
+ }
238
+ /**
239
+ * Checks if the continuation is valid at the given time.
240
+ *
241
+ * If no valid_until is set, always returns true.
242
+ * If no time is provided, always returns true.
243
+ *
244
+ * @param now - The time to check against, or undefined to skip time validation
245
+ * @returns true if the continuation is valid at the given time
246
+ */
247
+ isValidDate(now) {
248
+ if (this._validUntil === void 0) return true;
249
+ if (now === void 0) return true;
250
+ return now.getTime() <= this._validUntil.getTime();
251
+ }
252
+ /**
253
+ * Checks if the continuation has the expected ID.
254
+ *
255
+ * If no valid_id is set, always returns true.
256
+ * If no ID is provided for checking, always returns true.
257
+ *
258
+ * @param id - The ID to check against, or undefined to skip ID validation
259
+ * @returns true if the continuation has the expected ID
260
+ */
261
+ isValidId(id) {
262
+ if (this._validId === void 0) return true;
263
+ if (id === void 0) return true;
264
+ return this._validId.equals(id);
265
+ }
266
+ /**
267
+ * Checks if the continuation is valid (both date and ID).
268
+ *
269
+ * @param now - The time to check against, or undefined to skip time validation
270
+ * @param id - The ID to check against, or undefined to skip ID validation
271
+ * @returns true if the continuation is valid
272
+ */
273
+ isValid(now, id) {
274
+ return this.isValidDate(now) && this.isValidId(id);
275
+ }
276
+ /**
277
+ * Converts the continuation to an envelope.
278
+ *
279
+ * If a recipient is provided, the envelope is encrypted to that recipient.
280
+ *
281
+ * @param recipient - Optional recipient to encrypt the envelope to
282
+ * @returns The continuation as an envelope
283
+ */
284
+ toEnvelope(recipient) {
285
+ let envelope = this._state;
286
+ if (this._validId !== void 0) envelope = envelope.addAssertion(_bcts_known_values.ID, this._validId);
287
+ if (this._validUntil !== void 0) envelope = envelope.addAssertion(_bcts_known_values.VALID_UNTIL, this._validUntil.toISOString());
288
+ if (recipient !== void 0) envelope = envelope.encryptToRecipients([recipient]);
289
+ return envelope;
290
+ }
291
+ /**
292
+ * Parses a continuation from an envelope.
293
+ *
294
+ * @param encryptedEnvelope - The envelope to parse
295
+ * @param expectedId - Optional ID to validate against
296
+ * @param now - Optional time to validate against
297
+ * @param recipient - Optional private keys to decrypt with
298
+ * @returns The parsed continuation
299
+ * @throws GstpError if validation fails or parsing fails
300
+ */
301
+ static tryFromEnvelope(encryptedEnvelope, expectedId, now, recipient) {
302
+ let envelope = encryptedEnvelope;
303
+ if (recipient !== void 0) try {
304
+ envelope = encryptedEnvelope.decryptToRecipient(recipient);
305
+ } catch (e) {
306
+ throw GstpError.envelope(e instanceof Error ? e : new Error(String(e)));
307
+ }
308
+ const state = envelope.subject();
309
+ let validId;
310
+ try {
311
+ const idObj = envelope.objectForPredicate(_bcts_known_values.ID);
312
+ if (idObj !== void 0) {
313
+ const leafCbor = idObj.asLeaf();
314
+ if (leafCbor !== void 0) validId = _bcts_components.ARID.fromTaggedCborData(leafCbor.toData());
315
+ }
316
+ } catch {}
317
+ let validUntil;
318
+ try {
319
+ const validUntilObj = envelope.objectForPredicate(_bcts_known_values.VALID_UNTIL);
320
+ if (validUntilObj !== void 0) {
321
+ const dateStr = validUntilObj.asText();
322
+ if (dateStr !== void 0) validUntil = new Date(dateStr);
323
+ }
324
+ } catch {}
325
+ const continuation = new Continuation(state, validId, validUntil);
326
+ if (!continuation.isValidDate(now)) throw GstpError.continuationExpired();
327
+ if (!continuation.isValidId(expectedId)) throw GstpError.continuationIdInvalid();
328
+ return continuation;
329
+ }
330
+ /**
331
+ * Checks equality with another continuation.
332
+ *
333
+ * Two continuations are equal if they have the same state, ID, and valid_until.
334
+ *
335
+ * @param other - The continuation to compare with
336
+ * @returns true if the continuations are equal
337
+ */
338
+ equals(other) {
339
+ if (!this._state.digest().equals(other._state.digest())) return false;
340
+ if (this._validId === void 0 && other._validId === void 0) {} else if (this._validId !== void 0 && other._validId !== void 0) {
341
+ if (!this._validId.equals(other._validId)) return false;
342
+ } else return false;
343
+ if (this._validUntil === void 0 && other._validUntil === void 0) {} else if (this._validUntil !== void 0 && other._validUntil !== void 0) {
344
+ if (this._validUntil.getTime() !== other._validUntil.getTime()) return false;
345
+ } else return false;
346
+ return true;
347
+ }
348
+ /**
349
+ * Returns a string representation of the continuation.
350
+ */
351
+ toString() {
352
+ const parts = [`Continuation(state: ${this._state.formatFlat()}`];
353
+ if (this._validId !== void 0) parts.push(`id: ${this._validId.shortDescription()}`);
354
+ if (this._validUntil !== void 0) parts.push(`validUntil: ${this._validUntil.toISOString()}`);
355
+ return `${parts.join(", ")})`;
356
+ }
357
+ };
358
+
359
+ //#endregion
360
+ //#region src/sealed-request.ts
361
+ /**
362
+ * A sealed request that combines a Request with sender information and
363
+ * state continuations for secure communication.
364
+ *
365
+ * @example
366
+ * ```typescript
367
+ * import { SealedRequest, ARID } from '@bcts/gstp';
368
+ * import { XIDDocument } from '@bcts/xid';
369
+ *
370
+ * // Create sender XID document
371
+ * const sender = XIDDocument.new();
372
+ * const requestId = ARID.new();
373
+ *
374
+ * // Create a sealed request
375
+ * const request = SealedRequest.new("getBalance", requestId, sender)
376
+ * .withParameter("account", "alice")
377
+ * .withState("session-state-data")
378
+ * .withNote("Balance check");
379
+ *
380
+ * // Convert to sealed envelope
381
+ * const envelope = request.toEnvelope(
382
+ * new Date(Date.now() + 60000), // Valid for 60 seconds
383
+ * senderPrivateKey,
384
+ * recipientXIDDocument
385
+ * );
386
+ * ```
387
+ */
388
+ var SealedRequest = class SealedRequest {
389
+ _request;
390
+ _sender;
391
+ _state;
392
+ _peerContinuation;
393
+ constructor(request, sender, state, peerContinuation) {
394
+ this._request = request;
395
+ this._sender = sender;
396
+ this._state = state;
397
+ this._peerContinuation = peerContinuation;
398
+ }
399
+ /**
400
+ * Creates a new sealed request with the given function, ID, and sender.
401
+ *
402
+ * @param func - The function to call (string name or Function object)
403
+ * @param id - The request ID
404
+ * @param sender - The sender's XID document
405
+ */
406
+ static new(func, id, sender) {
407
+ return new SealedRequest(_bcts_envelope.Request.new(func, id), sender);
408
+ }
409
+ /**
410
+ * Creates a new sealed request with an expression body.
411
+ *
412
+ * @param body - The expression body
413
+ * @param id - The request ID
414
+ * @param sender - The sender's XID document
415
+ */
416
+ static newWithBody(body, id, sender) {
417
+ return new SealedRequest(_bcts_envelope.Request.newWithBody(body, id), sender);
418
+ }
419
+ /**
420
+ * Adds a parameter to the request.
421
+ */
422
+ withParameter(parameter, value) {
423
+ this._request = this._request.withParameter(parameter, value);
424
+ return this;
425
+ }
426
+ /**
427
+ * Adds an optional parameter to the request.
428
+ */
429
+ withOptionalParameter(parameter, value) {
430
+ if (value !== void 0) this._request = this._request.withParameter(parameter, value);
431
+ return this;
432
+ }
433
+ /**
434
+ * Returns the function of the request.
435
+ */
436
+ function() {
437
+ return this._request.function();
438
+ }
439
+ /**
440
+ * Returns the expression envelope of the request.
441
+ */
442
+ expressionEnvelope() {
443
+ return this._request.expressionEnvelope();
444
+ }
445
+ /**
446
+ * Returns the object for a parameter.
447
+ */
448
+ objectForParameter(param) {
449
+ return this._request.body().getParameter(param);
450
+ }
451
+ /**
452
+ * Returns all objects for a parameter.
453
+ */
454
+ objectsForParameter(param) {
455
+ const obj = this._request.body().getParameter(param);
456
+ return obj !== void 0 ? [obj] : [];
457
+ }
458
+ /**
459
+ * Extracts an object for a parameter as a specific type.
460
+ */
461
+ extractObjectForParameter(param) {
462
+ const envelope = this.objectForParameter(param);
463
+ if (envelope === void 0) throw GstpError.envelope(/* @__PURE__ */ new Error(`Parameter not found: ${param}`));
464
+ return envelope.extractSubject((cbor) => {
465
+ if (cbor.isInteger()) return cbor.toInteger();
466
+ if (cbor.isText()) return cbor.toText();
467
+ if (cbor.isBool()) return cbor.toBool();
468
+ if (cbor.isNumber()) return cbor.toNumber();
469
+ if (cbor.isByteString()) return cbor.toByteString();
470
+ return cbor;
471
+ });
472
+ }
473
+ /**
474
+ * Extracts an optional object for a parameter.
475
+ */
476
+ extractOptionalObjectForParameter(param) {
477
+ const envelope = this.objectForParameter(param);
478
+ if (envelope === void 0) return;
479
+ return envelope.extractSubject((cbor) => {
480
+ if (cbor.isInteger()) return cbor.toInteger();
481
+ if (cbor.isText()) return cbor.toText();
482
+ if (cbor.isBool()) return cbor.toBool();
483
+ if (cbor.isNumber()) return cbor.toNumber();
484
+ if (cbor.isByteString()) return cbor.toByteString();
485
+ return cbor;
486
+ });
487
+ }
488
+ /**
489
+ * Extracts all objects for a parameter as a specific type.
490
+ */
491
+ extractObjectsForParameter(param) {
492
+ return this.objectsForParameter(param).map((env) => env.extractSubject((cbor) => cbor));
493
+ }
494
+ /**
495
+ * Adds a note to the request.
496
+ */
497
+ withNote(note) {
498
+ this._request = this._request.withNote(note);
499
+ return this;
500
+ }
501
+ /**
502
+ * Adds a date to the request.
503
+ */
504
+ withDate(date) {
505
+ this._request = this._request.withDate(date);
506
+ return this;
507
+ }
508
+ /**
509
+ * Returns the body of the request.
510
+ */
511
+ body() {
512
+ return this._request.body();
513
+ }
514
+ /**
515
+ * Returns the ID of the request.
516
+ */
517
+ id() {
518
+ return this._request.id();
519
+ }
520
+ /**
521
+ * Returns the note of the request.
522
+ */
523
+ note() {
524
+ return this._request.note();
525
+ }
526
+ /**
527
+ * Returns the date of the request.
528
+ */
529
+ date() {
530
+ return this._request.date();
531
+ }
532
+ /**
533
+ * Adds state to the request that the receiver must return in the response.
534
+ */
535
+ withState(state) {
536
+ this._state = _bcts_envelope.Envelope.new(state);
537
+ return this;
538
+ }
539
+ /**
540
+ * Adds optional state to the request.
541
+ */
542
+ withOptionalState(state) {
543
+ this._state = state !== void 0 ? _bcts_envelope.Envelope.new(state) : void 0;
544
+ return this;
545
+ }
546
+ /**
547
+ * Adds a continuation previously received from the recipient.
548
+ */
549
+ withPeerContinuation(peerContinuation) {
550
+ this._peerContinuation = peerContinuation;
551
+ return this;
552
+ }
553
+ /**
554
+ * Adds an optional continuation previously received from the recipient.
555
+ */
556
+ withOptionalPeerContinuation(peerContinuation) {
557
+ this._peerContinuation = peerContinuation;
558
+ return this;
559
+ }
560
+ /**
561
+ * Returns the underlying request.
562
+ */
563
+ request() {
564
+ return this._request;
565
+ }
566
+ /**
567
+ * Returns the sender of the request.
568
+ */
569
+ sender() {
570
+ return this._sender;
571
+ }
572
+ /**
573
+ * Returns the state to be sent to the recipient.
574
+ */
575
+ state() {
576
+ return this._state;
577
+ }
578
+ /**
579
+ * Returns the continuation received from the recipient.
580
+ */
581
+ peerContinuation() {
582
+ return this._peerContinuation;
583
+ }
584
+ /**
585
+ * Converts the sealed request to a Request.
586
+ */
587
+ toRequest() {
588
+ return this._request;
589
+ }
590
+ /**
591
+ * Converts the sealed request to an Expression.
592
+ */
593
+ toExpression() {
594
+ return this._request.body();
595
+ }
596
+ /**
597
+ * Creates an envelope that can be decrypted by zero or one recipient.
598
+ *
599
+ * @param validUntil - Optional expiration date for the continuation
600
+ * @param signer - Optional signer for the envelope
601
+ * @param recipient - Optional recipient XID document for encryption
602
+ * @returns The sealed request as an envelope
603
+ */
604
+ toEnvelope(validUntil, signer, recipient) {
605
+ const recipients = recipient !== void 0 ? [recipient] : [];
606
+ return this.toEnvelopeForRecipients(validUntil, signer, recipients);
607
+ }
608
+ /**
609
+ * Creates an envelope that can be decrypted by zero or more recipients.
610
+ *
611
+ * @param validUntil - Optional expiration date for the continuation
612
+ * @param signer - Optional signer for the envelope
613
+ * @param recipients - Array of recipient XID documents for encryption
614
+ * @returns The sealed request as an envelope
615
+ */
616
+ toEnvelopeForRecipients(validUntil, signer, recipients) {
617
+ const continuation = new Continuation(this._state ?? _bcts_envelope.Envelope.new(null), this.id(), validUntil);
618
+ const senderEncryptionKey = this._sender.inceptionKey()?.publicKeys()?.encapsulationPublicKey();
619
+ if (senderEncryptionKey === void 0) throw GstpError.senderMissingEncryptionKey();
620
+ const senderContinuation = continuation.toEnvelope(senderEncryptionKey);
621
+ let result = this._request.toEnvelope();
622
+ result = result.addAssertion(_bcts_known_values.SENDER, this._sender.toEnvelope());
623
+ result = result.addAssertion(_bcts_known_values.SENDER_CONTINUATION, senderContinuation);
624
+ if (this._peerContinuation !== void 0) result = result.addAssertion(_bcts_known_values.RECIPIENT_CONTINUATION, this._peerContinuation);
625
+ if (signer !== void 0) result = result.sign(signer);
626
+ if (recipients !== void 0 && recipients.length > 0) {
627
+ const recipientKeys = recipients.map((recipient) => {
628
+ const key = recipient.encryptionKey();
629
+ if (key === void 0) throw GstpError.recipientMissingEncryptionKey();
630
+ return key;
631
+ });
632
+ result = result.wrap().encryptSubjectToRecipients(recipientKeys);
633
+ }
634
+ return result;
635
+ }
636
+ /**
637
+ * Parses a sealed request from an encrypted envelope.
638
+ *
639
+ * @param encryptedEnvelope - The encrypted envelope to parse
640
+ * @param expectedId - Optional expected request ID for validation
641
+ * @param now - Optional current time for continuation validation
642
+ * @param recipient - The recipient's private keys for decryption
643
+ * @returns The parsed sealed request
644
+ */
645
+ static tryFromEnvelope(encryptedEnvelope, expectedId, now, recipient) {
646
+ let signedEnvelope;
647
+ try {
648
+ signedEnvelope = encryptedEnvelope.decryptToRecipient(recipient);
649
+ } catch (e) {
650
+ throw GstpError.envelope(e instanceof Error ? e : new Error(String(e)));
651
+ }
652
+ let sender;
653
+ try {
654
+ const senderEnvelope = signedEnvelope.tryUnwrap().objectForPredicate(_bcts_known_values.SENDER);
655
+ if (senderEnvelope === void 0) throw new Error("Missing sender");
656
+ sender = _bcts_xid.XIDDocument.fromEnvelope(senderEnvelope);
657
+ } catch (e) {
658
+ throw GstpError.xid(e instanceof Error ? e : new Error(String(e)));
659
+ }
660
+ const senderVerificationKey = sender.inceptionKey()?.publicKeys()?.signingPublicKey();
661
+ if (senderVerificationKey === void 0) throw GstpError.senderMissingVerificationKey();
662
+ let requestEnvelope;
663
+ try {
664
+ requestEnvelope = signedEnvelope.verify(senderVerificationKey);
665
+ } catch (e) {
666
+ throw GstpError.envelope(e instanceof Error ? e : new Error(String(e)));
667
+ }
668
+ const peerContinuation = requestEnvelope.optionalObjectForPredicate(_bcts_known_values.SENDER_CONTINUATION);
669
+ if (peerContinuation !== void 0) {
670
+ if (!peerContinuation.subject().isEncrypted()) throw GstpError.peerContinuationNotEncrypted();
671
+ } else throw GstpError.missingPeerContinuation();
672
+ const encryptedContinuation = requestEnvelope.optionalObjectForPredicate(_bcts_known_values.RECIPIENT_CONTINUATION);
673
+ let state;
674
+ if (encryptedContinuation !== void 0) state = Continuation.tryFromEnvelope(encryptedContinuation, expectedId, now, recipient).state();
675
+ let request;
676
+ try {
677
+ request = _bcts_envelope.Request.fromEnvelope(requestEnvelope);
678
+ } catch (e) {
679
+ throw GstpError.envelope(e instanceof Error ? e : new Error(String(e)));
680
+ }
681
+ return new SealedRequest(request, sender, state, peerContinuation);
682
+ }
683
+ /**
684
+ * Returns a string representation of the sealed request.
685
+ */
686
+ toString() {
687
+ const stateStr = this._state !== void 0 ? this._state.formatFlat() : "None";
688
+ const peerStr = this._peerContinuation !== void 0 ? "Some" : "None";
689
+ return `SealedRequest(${this._request.summary()}, state: ${stateStr}, peer_continuation: ${peerStr})`;
690
+ }
691
+ /**
692
+ * Checks equality with another sealed request.
693
+ */
694
+ equals(other) {
695
+ if (!this._request.equals(other._request)) return false;
696
+ if (!this._sender.xid().equals(other._sender.xid())) return false;
697
+ if (this._state === void 0 && other._state === void 0) {} else if (this._state !== void 0 && other._state !== void 0) {
698
+ if (!this._state.digest().equals(other._state.digest())) return false;
699
+ } else return false;
700
+ if (this._peerContinuation === void 0 && other._peerContinuation === void 0) {} else if (this._peerContinuation !== void 0 && other._peerContinuation !== void 0) {
701
+ if (!this._peerContinuation.digest().equals(other._peerContinuation.digest())) return false;
702
+ } else return false;
703
+ return true;
704
+ }
705
+ };
706
+
707
+ //#endregion
708
+ //#region src/sealed-response.ts
709
+ /**
710
+ * A sealed response that combines a Response with sender information and
711
+ * state continuations for secure communication.
712
+ *
713
+ * @example
714
+ * ```typescript
715
+ * import { SealedResponse, ARID } from '@bcts/gstp';
716
+ * import { XIDDocument } from '@bcts/xid';
717
+ *
718
+ * // Create sender XID document
719
+ * const sender = XIDDocument.new();
720
+ * const requestId = ARID.new();
721
+ *
722
+ * // Create a successful sealed response
723
+ * const response = SealedResponse.newSuccess(requestId, sender)
724
+ * .withResult("Operation completed")
725
+ * .withState("next-page-state");
726
+ *
727
+ * // Convert to sealed envelope
728
+ * const envelope = response.toEnvelope(
729
+ * new Date(Date.now() + 60000), // Valid for 60 seconds
730
+ * senderPrivateKey,
731
+ * recipientXIDDocument
732
+ * );
733
+ * ```
734
+ */
735
+ var SealedResponse = class SealedResponse {
736
+ _response;
737
+ _sender;
738
+ _state;
739
+ _peerContinuation;
740
+ constructor(response, sender, state, peerContinuation) {
741
+ this._response = response;
742
+ this._sender = sender;
743
+ this._state = state;
744
+ this._peerContinuation = peerContinuation;
745
+ }
746
+ /**
747
+ * Creates a new successful sealed response.
748
+ *
749
+ * @param id - The request ID this response is for
750
+ * @param sender - The sender's XID document
751
+ */
752
+ static newSuccess(id, sender) {
753
+ return new SealedResponse(_bcts_envelope.Response.newSuccess(id), sender);
754
+ }
755
+ /**
756
+ * Creates a new failure sealed response.
757
+ *
758
+ * @param id - The request ID this response is for
759
+ * @param sender - The sender's XID document
760
+ */
761
+ static newFailure(id, sender) {
762
+ return new SealedResponse(_bcts_envelope.Response.newFailure(id), sender);
763
+ }
764
+ /**
765
+ * Creates a new early failure sealed response.
766
+ *
767
+ * An early failure takes place before the message has been decrypted,
768
+ * and therefore the ID and sender public key are not known.
769
+ *
770
+ * @param sender - The sender's XID document
771
+ */
772
+ static newEarlyFailure(sender) {
773
+ return new SealedResponse(_bcts_envelope.Response.newEarlyFailure(), sender);
774
+ }
775
+ /**
776
+ * Adds state to the response that the peer may return at some future time.
777
+ *
778
+ * @throws Error if called on a failed response
779
+ */
780
+ withState(state) {
781
+ if (!this._response.isOk()) throw new Error("Cannot set state on a failed response");
782
+ this._state = _bcts_envelope.Envelope.new(state);
783
+ return this;
784
+ }
785
+ /**
786
+ * Adds optional state to the response.
787
+ */
788
+ withOptionalState(state) {
789
+ if (state !== void 0) return this.withState(state);
790
+ this._state = void 0;
791
+ return this;
792
+ }
793
+ /**
794
+ * Adds a continuation previously received from the recipient.
795
+ */
796
+ withPeerContinuation(peerContinuation) {
797
+ this._peerContinuation = peerContinuation;
798
+ return this;
799
+ }
800
+ /**
801
+ * Returns the sender of the response.
802
+ */
803
+ sender() {
804
+ return this._sender;
805
+ }
806
+ /**
807
+ * Returns the state to be sent to the peer.
808
+ */
809
+ state() {
810
+ return this._state;
811
+ }
812
+ /**
813
+ * Returns the continuation received from the peer.
814
+ */
815
+ peerContinuation() {
816
+ return this._peerContinuation;
817
+ }
818
+ /**
819
+ * Sets the result value for a successful response.
820
+ */
821
+ withResult(result) {
822
+ this._response = this._response.withResult(result);
823
+ return this;
824
+ }
825
+ /**
826
+ * Sets an optional result value for a successful response.
827
+ * If the result is undefined, the value of the response will be the null envelope.
828
+ */
829
+ withOptionalResult(result) {
830
+ this._response = this._response.withOptionalResult(result);
831
+ return this;
832
+ }
833
+ /**
834
+ * Sets the error value for a failure response.
835
+ */
836
+ withError(error) {
837
+ this._response = this._response.withError(error);
838
+ return this;
839
+ }
840
+ /**
841
+ * Sets an optional error value for a failure response.
842
+ * If the error is undefined, the value of the response will be the unknown value.
843
+ */
844
+ withOptionalError(error) {
845
+ this._response = this._response.withOptionalError(error);
846
+ return this;
847
+ }
848
+ /**
849
+ * Returns true if this is a successful response.
850
+ */
851
+ isOk() {
852
+ return this._response.isOk();
853
+ }
854
+ /**
855
+ * Returns true if this is a failure response.
856
+ */
857
+ isErr() {
858
+ return this._response.isErr();
859
+ }
860
+ /**
861
+ * Returns the ID of the request this response is for, if known.
862
+ */
863
+ id() {
864
+ return this._response.id();
865
+ }
866
+ /**
867
+ * Returns the ID of the request this response is for.
868
+ * @throws Error if the ID is not known
869
+ */
870
+ expectId() {
871
+ return this._response.expectId();
872
+ }
873
+ /**
874
+ * Returns the result envelope if this is a successful response.
875
+ * @throws Error if this is a failure response
876
+ */
877
+ result() {
878
+ return this._response.result();
879
+ }
880
+ /**
881
+ * Extracts the result as a specific type.
882
+ */
883
+ extractResult(decoder) {
884
+ return this._response.extractResult(decoder);
885
+ }
886
+ /**
887
+ * Returns the error envelope if this is a failure response.
888
+ * @throws Error if this is a successful response
889
+ */
890
+ error() {
891
+ return this._response.error();
892
+ }
893
+ /**
894
+ * Extracts the error as a specific type.
895
+ */
896
+ extractError(decoder) {
897
+ return this._response.extractError(decoder);
898
+ }
899
+ /**
900
+ * Creates an envelope that can be decrypted by zero or one recipient.
901
+ *
902
+ * @param validUntil - Optional expiration date for the continuation
903
+ * @param signer - Optional signer for the envelope
904
+ * @param recipient - Optional recipient XID document for encryption
905
+ * @returns The sealed response as an envelope
906
+ */
907
+ toEnvelope(validUntil, signer, recipient) {
908
+ const recipients = recipient !== void 0 ? [recipient] : [];
909
+ return this.toEnvelopeForRecipients(validUntil, signer, recipients);
910
+ }
911
+ /**
912
+ * Creates an envelope that can be decrypted by zero or more recipients.
913
+ *
914
+ * @param validUntil - Optional expiration date for the continuation
915
+ * @param signer - Optional signer for the envelope
916
+ * @param recipients - Array of recipient XID documents for encryption
917
+ * @returns The sealed response as an envelope
918
+ */
919
+ toEnvelopeForRecipients(validUntil, signer, recipients) {
920
+ let senderContinuation;
921
+ if (this._state !== void 0) {
922
+ const continuation = new Continuation(this._state, void 0, validUntil);
923
+ const senderEncryptionKey = this._sender.inceptionKey()?.publicKeys()?.encapsulationPublicKey();
924
+ if (senderEncryptionKey === void 0) throw GstpError.senderMissingEncryptionKey();
925
+ senderContinuation = continuation.toEnvelope(senderEncryptionKey);
926
+ }
927
+ let result = this._response.toEnvelope();
928
+ result = result.addAssertion(_bcts_known_values.SENDER, this._sender.toEnvelope());
929
+ if (senderContinuation !== void 0) result = result.addAssertion(_bcts_known_values.SENDER_CONTINUATION, senderContinuation);
930
+ if (this._peerContinuation !== void 0) result = result.addAssertion(_bcts_known_values.RECIPIENT_CONTINUATION, this._peerContinuation);
931
+ if (signer !== void 0) result = result.sign(signer);
932
+ if (recipients !== void 0 && recipients.length > 0) {
933
+ const recipientKeys = recipients.map((recipient) => {
934
+ const key = recipient.encryptionKey();
935
+ if (key === void 0) throw GstpError.recipientMissingEncryptionKey();
936
+ return key;
937
+ });
938
+ result = result.wrap().encryptSubjectToRecipients(recipientKeys);
939
+ }
940
+ return result;
941
+ }
942
+ /**
943
+ * Parses a sealed response from an encrypted envelope.
944
+ *
945
+ * @param encryptedEnvelope - The encrypted envelope to parse
946
+ * @param expectedId - Optional expected request ID for validation
947
+ * @param now - Optional current time for continuation validation
948
+ * @param recipientPrivateKey - The recipient's private keys for decryption
949
+ * @returns The parsed sealed response
950
+ */
951
+ static tryFromEncryptedEnvelope(encryptedEnvelope, expectedId, now, recipientPrivateKey) {
952
+ let signedEnvelope;
953
+ try {
954
+ signedEnvelope = encryptedEnvelope.decryptToRecipient(recipientPrivateKey);
955
+ } catch (e) {
956
+ throw GstpError.envelope(e instanceof Error ? e : new Error(String(e)));
957
+ }
958
+ let sender;
959
+ try {
960
+ const senderEnvelope = signedEnvelope.tryUnwrap().objectForPredicate(_bcts_known_values.SENDER);
961
+ if (senderEnvelope === void 0) throw new Error("Missing sender");
962
+ sender = _bcts_xid.XIDDocument.fromEnvelope(senderEnvelope);
963
+ } catch (e) {
964
+ throw GstpError.xid(e instanceof Error ? e : new Error(String(e)));
965
+ }
966
+ const senderVerificationKey = sender.inceptionKey()?.publicKeys()?.signingPublicKey();
967
+ if (senderVerificationKey === void 0) throw GstpError.senderMissingVerificationKey();
968
+ let responseEnvelope;
969
+ try {
970
+ responseEnvelope = signedEnvelope.verify(senderVerificationKey);
971
+ } catch (e) {
972
+ throw GstpError.envelope(e instanceof Error ? e : new Error(String(e)));
973
+ }
974
+ const peerContinuation = responseEnvelope.optionalObjectForPredicate(_bcts_known_values.SENDER_CONTINUATION);
975
+ if (peerContinuation !== void 0) {
976
+ if (!peerContinuation.subject().isEncrypted()) throw GstpError.peerContinuationNotEncrypted();
977
+ }
978
+ const encryptedContinuation = responseEnvelope.optionalObjectForPredicate(_bcts_known_values.RECIPIENT_CONTINUATION);
979
+ let state;
980
+ if (encryptedContinuation !== void 0) {
981
+ const stateEnv = Continuation.tryFromEnvelope(encryptedContinuation, expectedId, now, recipientPrivateKey).state();
982
+ if (stateEnv.isNull()) state = void 0;
983
+ else state = stateEnv;
984
+ }
985
+ let response;
986
+ try {
987
+ response = _bcts_envelope.Response.fromEnvelope(responseEnvelope);
988
+ } catch (e) {
989
+ throw GstpError.envelope(e instanceof Error ? e : new Error(String(e)));
990
+ }
991
+ return new SealedResponse(response, sender, state, peerContinuation);
992
+ }
993
+ /**
994
+ * Returns a string representation of the sealed response.
995
+ */
996
+ toString() {
997
+ const stateStr = this._state !== void 0 ? this._state.formatFlat() : "None";
998
+ const peerStr = this._peerContinuation !== void 0 ? "Some" : "None";
999
+ return `SealedResponse(${this._response.summary()}, state: ${stateStr}, peer_continuation: ${peerStr})`;
1000
+ }
1001
+ /**
1002
+ * Checks equality with another sealed response.
1003
+ */
1004
+ equals(other) {
1005
+ if (!this._response.equals(other._response)) return false;
1006
+ if (!this._sender.xid().equals(other._sender.xid())) return false;
1007
+ if (this._state === void 0 && other._state === void 0) {} else if (this._state !== void 0 && other._state !== void 0) {
1008
+ if (!this._state.digest().equals(other._state.digest())) return false;
1009
+ } else return false;
1010
+ if (this._peerContinuation === void 0 && other._peerContinuation === void 0) {} else if (this._peerContinuation !== void 0 && other._peerContinuation !== void 0) {
1011
+ if (!this._peerContinuation.digest().equals(other._peerContinuation.digest())) return false;
1012
+ } else return false;
1013
+ return true;
1014
+ }
1015
+ };
1016
+
1017
+ //#endregion
1018
+ //#region src/sealed-event.ts
1019
+ /**
1020
+ * A sealed event that combines an Event with sender information and
1021
+ * state continuations for secure communication.
1022
+ *
1023
+ * @typeParam T - The type of content this event carries
1024
+ *
1025
+ * @example
1026
+ * ```typescript
1027
+ * import { SealedEvent, ARID } from '@bcts/gstp';
1028
+ * import { XIDDocument } from '@bcts/xid';
1029
+ *
1030
+ * // Create sender XID document
1031
+ * const sender = XIDDocument.new();
1032
+ * const eventId = ARID.new();
1033
+ *
1034
+ * // Create a sealed event
1035
+ * const event = SealedEvent.new("System notification", eventId, sender)
1036
+ * .withNote("Status update")
1037
+ * .withDate(new Date());
1038
+ *
1039
+ * // Convert to sealed envelope
1040
+ * const envelope = event.toEnvelope(
1041
+ * new Date(Date.now() + 60000), // Valid for 60 seconds
1042
+ * senderPrivateKey,
1043
+ * recipientXIDDocument
1044
+ * );
1045
+ * ```
1046
+ */
1047
+ var SealedEvent = class SealedEvent {
1048
+ _event;
1049
+ _sender;
1050
+ _state;
1051
+ _peerContinuation;
1052
+ constructor(event, sender, state, peerContinuation) {
1053
+ this._event = event;
1054
+ this._sender = sender;
1055
+ this._state = state;
1056
+ this._peerContinuation = peerContinuation;
1057
+ }
1058
+ /**
1059
+ * Creates a new sealed event with the given content, ID, and sender.
1060
+ *
1061
+ * @param content - The content of the event
1062
+ * @param id - The event ID
1063
+ * @param sender - The sender's XID document
1064
+ */
1065
+ static new(content, id, sender) {
1066
+ return new SealedEvent(_bcts_envelope.Event.new(content, id), sender);
1067
+ }
1068
+ /**
1069
+ * Adds a note to the event.
1070
+ */
1071
+ withNote(note) {
1072
+ this._event = this._event.withNote(note);
1073
+ return this;
1074
+ }
1075
+ /**
1076
+ * Adds a date to the event.
1077
+ */
1078
+ withDate(date) {
1079
+ this._event = this._event.withDate(date);
1080
+ return this;
1081
+ }
1082
+ /**
1083
+ * Returns the content of the event.
1084
+ */
1085
+ content() {
1086
+ return this._event.content();
1087
+ }
1088
+ /**
1089
+ * Returns the ID of the event.
1090
+ */
1091
+ id() {
1092
+ return this._event.id();
1093
+ }
1094
+ /**
1095
+ * Returns the note of the event.
1096
+ */
1097
+ note() {
1098
+ return this._event.note();
1099
+ }
1100
+ /**
1101
+ * Returns the date of the event.
1102
+ */
1103
+ date() {
1104
+ return this._event.date();
1105
+ }
1106
+ /**
1107
+ * Adds state to the event that the receiver must return in the response.
1108
+ */
1109
+ withState(state) {
1110
+ this._state = _bcts_envelope.Envelope.new(state);
1111
+ return this;
1112
+ }
1113
+ /**
1114
+ * Adds optional state to the event.
1115
+ */
1116
+ withOptionalState(state) {
1117
+ if (state !== void 0) return this.withState(state);
1118
+ this._state = void 0;
1119
+ return this;
1120
+ }
1121
+ /**
1122
+ * Adds a continuation previously received from the recipient.
1123
+ */
1124
+ withPeerContinuation(peerContinuation) {
1125
+ this._peerContinuation = peerContinuation;
1126
+ return this;
1127
+ }
1128
+ /**
1129
+ * Adds an optional continuation previously received from the recipient.
1130
+ */
1131
+ withOptionalPeerContinuation(peerContinuation) {
1132
+ this._peerContinuation = peerContinuation;
1133
+ return this;
1134
+ }
1135
+ /**
1136
+ * Returns the underlying event.
1137
+ */
1138
+ event() {
1139
+ return this._event;
1140
+ }
1141
+ /**
1142
+ * Returns the sender of the event.
1143
+ */
1144
+ sender() {
1145
+ return this._sender;
1146
+ }
1147
+ /**
1148
+ * Returns the state to be sent to the recipient.
1149
+ */
1150
+ state() {
1151
+ return this._state;
1152
+ }
1153
+ /**
1154
+ * Returns the continuation received from the recipient.
1155
+ */
1156
+ peerContinuation() {
1157
+ return this._peerContinuation;
1158
+ }
1159
+ /**
1160
+ * Converts the sealed event to an Event.
1161
+ */
1162
+ toEvent() {
1163
+ return this._event;
1164
+ }
1165
+ /**
1166
+ * Creates an envelope that can be decrypted by zero or one recipient.
1167
+ *
1168
+ * @param validUntil - Optional expiration date for the continuation
1169
+ * @param signer - Optional signer for the envelope
1170
+ * @param recipient - Optional recipient XID document for encryption
1171
+ * @returns The sealed event as an envelope
1172
+ */
1173
+ toEnvelope(validUntil, signer, recipient) {
1174
+ const recipients = recipient !== void 0 ? [recipient] : [];
1175
+ return this.toEnvelopeForRecipients(validUntil, signer, recipients);
1176
+ }
1177
+ /**
1178
+ * Creates an envelope that can be decrypted by zero or more recipients.
1179
+ *
1180
+ * @param validUntil - Optional expiration date for the continuation
1181
+ * @param signer - Optional signer for the envelope
1182
+ * @param recipients - Array of recipient XID documents for encryption
1183
+ * @returns The sealed event as an envelope
1184
+ */
1185
+ toEnvelopeForRecipients(validUntil, signer, recipients) {
1186
+ const senderEncryptionKey = this._sender.inceptionKey()?.publicKeys()?.encapsulationPublicKey();
1187
+ if (senderEncryptionKey === void 0) throw GstpError.senderMissingEncryptionKey();
1188
+ let senderContinuation;
1189
+ if (this._state !== void 0) senderContinuation = new Continuation(this._state, void 0, validUntil).toEnvelope(senderEncryptionKey);
1190
+ else if (validUntil !== void 0) senderContinuation = new Continuation(_bcts_envelope.Envelope.new(null), void 0, validUntil).toEnvelope(senderEncryptionKey);
1191
+ let result = this._event.toEnvelope();
1192
+ result = result.addAssertion(_bcts_known_values.SENDER, this._sender.toEnvelope());
1193
+ if (senderContinuation !== void 0) result = result.addAssertion(_bcts_known_values.SENDER_CONTINUATION, senderContinuation);
1194
+ if (this._peerContinuation !== void 0) result = result.addAssertion(_bcts_known_values.RECIPIENT_CONTINUATION, this._peerContinuation);
1195
+ if (signer !== void 0) result = result.sign(signer);
1196
+ if (recipients !== void 0 && recipients.length > 0) {
1197
+ const recipientKeys = recipients.map((recipient) => {
1198
+ const key = recipient.encryptionKey();
1199
+ if (key === void 0) throw GstpError.recipientMissingEncryptionKey();
1200
+ return key;
1201
+ });
1202
+ result = result.wrap().encryptSubjectToRecipients(recipientKeys);
1203
+ }
1204
+ return result;
1205
+ }
1206
+ /**
1207
+ * Parses a sealed event from an encrypted envelope.
1208
+ *
1209
+ * @param encryptedEnvelope - The encrypted envelope to parse
1210
+ * @param expectedId - Optional expected event ID for validation
1211
+ * @param now - Optional current time for continuation validation
1212
+ * @param recipientPrivateKey - The recipient's private keys for decryption
1213
+ * @param contentExtractor - Function to extract content from envelope
1214
+ * @returns The parsed sealed event
1215
+ */
1216
+ static tryFromEnvelope(encryptedEnvelope, expectedId, now, recipientPrivateKey, contentExtractor) {
1217
+ let signedEnvelope;
1218
+ try {
1219
+ signedEnvelope = encryptedEnvelope.decryptToRecipient(recipientPrivateKey);
1220
+ } catch (e) {
1221
+ throw GstpError.envelope(e instanceof Error ? e : new Error(String(e)));
1222
+ }
1223
+ let sender;
1224
+ try {
1225
+ const senderEnvelope = signedEnvelope.tryUnwrap().objectForPredicate(_bcts_known_values.SENDER);
1226
+ if (senderEnvelope === void 0) throw new Error("Missing sender");
1227
+ sender = _bcts_xid.XIDDocument.fromEnvelope(senderEnvelope);
1228
+ } catch (e) {
1229
+ throw GstpError.xid(e instanceof Error ? e : new Error(String(e)));
1230
+ }
1231
+ const senderVerificationKey = sender.inceptionKey()?.publicKeys()?.signingPublicKey();
1232
+ if (senderVerificationKey === void 0) throw GstpError.senderMissingVerificationKey();
1233
+ let eventEnvelope;
1234
+ try {
1235
+ eventEnvelope = signedEnvelope.verify(senderVerificationKey);
1236
+ } catch (e) {
1237
+ throw GstpError.envelope(e instanceof Error ? e : new Error(String(e)));
1238
+ }
1239
+ const peerContinuation = eventEnvelope.optionalObjectForPredicate(_bcts_known_values.SENDER_CONTINUATION);
1240
+ if (peerContinuation !== void 0) {
1241
+ if (!peerContinuation.subject().isEncrypted()) throw GstpError.peerContinuationNotEncrypted();
1242
+ }
1243
+ const encryptedContinuation = eventEnvelope.optionalObjectForPredicate(_bcts_known_values.RECIPIENT_CONTINUATION);
1244
+ let state;
1245
+ if (encryptedContinuation !== void 0) state = Continuation.tryFromEnvelope(encryptedContinuation, expectedId, now, recipientPrivateKey).state();
1246
+ let event;
1247
+ try {
1248
+ if (contentExtractor !== void 0) event = _bcts_envelope.Event.fromEnvelope(eventEnvelope, contentExtractor);
1249
+ else event = _bcts_envelope.Event.stringFromEnvelope(eventEnvelope);
1250
+ } catch (e) {
1251
+ throw GstpError.envelope(e instanceof Error ? e : new Error(String(e)));
1252
+ }
1253
+ return new SealedEvent(event, sender, state, peerContinuation);
1254
+ }
1255
+ /**
1256
+ * Returns a string representation of the sealed event.
1257
+ */
1258
+ toString() {
1259
+ const stateStr = this._state !== void 0 ? this._state.formatFlat() : "None";
1260
+ const peerStr = this._peerContinuation !== void 0 ? "Some" : "None";
1261
+ return `SealedEvent(${this._event.summary()}, state: ${stateStr}, peer_continuation: ${peerStr})`;
1262
+ }
1263
+ /**
1264
+ * Checks equality with another sealed event.
1265
+ */
1266
+ equals(other) {
1267
+ if (!this._event.equals(other._event)) return false;
1268
+ if (!this._sender.xid().equals(other._sender.xid())) return false;
1269
+ if (this._state === void 0 && other._state === void 0) {} else if (this._state !== void 0 && other._state !== void 0) {
1270
+ if (!this._state.digest().equals(other._state.digest())) return false;
1271
+ } else return false;
1272
+ if (this._peerContinuation === void 0 && other._peerContinuation === void 0) {} else if (this._peerContinuation !== void 0 && other._peerContinuation !== void 0) {
1273
+ if (!this._peerContinuation.digest().equals(other._peerContinuation.digest())) return false;
1274
+ } else return false;
1275
+ return true;
1276
+ }
1277
+ };
1278
+
1279
+ //#endregion
1280
+ //#region src/prelude.ts
1281
+ var prelude_exports = /* @__PURE__ */ __exportAll({
1282
+ Continuation: () => Continuation,
1283
+ GstpError: () => GstpError,
1284
+ GstpErrorCode: () => GstpErrorCode,
1285
+ SealedEvent: () => SealedEvent,
1286
+ SealedRequest: () => SealedRequest,
1287
+ SealedResponse: () => SealedResponse
1288
+ });
1289
+
1290
+ //#endregion
1291
+ //#region src/index.ts
1292
+ const VERSION = "0.13.0";
1293
+
1294
+ //#endregion
1295
+ exports.Continuation = Continuation;
1296
+ exports.GstpError = GstpError;
1297
+ exports.GstpErrorCode = GstpErrorCode;
1298
+ exports.SealedEvent = SealedEvent;
1299
+ exports.SealedRequest = SealedRequest;
1300
+ exports.SealedResponse = SealedResponse;
1301
+ exports.VERSION = VERSION;
1302
+ Object.defineProperty(exports, 'prelude', {
1303
+ enumerable: true,
1304
+ get: function () {
1305
+ return prelude_exports;
1306
+ }
1307
+ });
1308
+ //# sourceMappingURL=index.cjs.map