@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/LICENSE +48 -0
- package/README.md +17 -0
- package/dist/chunk-15K8U1wQ.mjs +18 -0
- package/dist/index.cjs +1308 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +853 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +851 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.iife.js +1308 -0
- package/dist/index.iife.js.map +1 -0
- package/dist/index.mjs +1280 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +92 -0
- package/src/continuation.ts +334 -0
- package/src/error.ts +145 -0
- package/src/index.ts +30 -0
- package/src/prelude.ts +24 -0
- package/src/sealed-event.ts +479 -0
- package/src/sealed-request.ts +580 -0
- package/src/sealed-response.ts +507 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.iife.js","names":["Envelope","ID","VALID_UNTIL","validId: ARID | undefined","ARID","validUntil: Date | undefined","Request","Envelope","recipients: XIDDocument[]","SENDER","SENDER_CONTINUATION","RECIPIENT_CONTINUATION","signedEnvelope: Envelope","sender: XIDDocument","XIDDocument","requestEnvelope: Envelope","state: Envelope | undefined","request: Request","Response","Envelope","recipients: XIDDocument[]","senderContinuation: Envelope | undefined","SENDER","SENDER_CONTINUATION","RECIPIENT_CONTINUATION","signedEnvelope: Envelope","sender: XIDDocument","XIDDocument","responseEnvelope: Envelope","state: Envelope | undefined","response: Response","Event","Envelope","recipients: XIDDocument[]","senderContinuation: Envelope | undefined","SENDER","SENDER_CONTINUATION","RECIPIENT_CONTINUATION","signedEnvelope: Envelope","sender: XIDDocument","XIDDocument","eventEnvelope: Envelope","state: Envelope | undefined","event: Event<T>"],"sources":["../src/error.ts","../src/continuation.ts","../src/sealed-request.ts","../src/sealed-response.ts","../src/sealed-event.ts","../src/prelude.ts","../src/index.ts"],"sourcesContent":["/**\n * GSTP Error Types\n *\n * Error types returned when operating on GSTP messages.\n * Ported from gstp-rust/src/error.rs\n */\n\n/**\n * Error codes for GSTP operations.\n */\nexport enum GstpErrorCode {\n /** Sender must have an encryption key. */\n SENDER_MISSING_ENCRYPTION_KEY = \"SENDER_MISSING_ENCRYPTION_KEY\",\n\n /** Recipient must have an encryption key. */\n RECIPIENT_MISSING_ENCRYPTION_KEY = \"RECIPIENT_MISSING_ENCRYPTION_KEY\",\n\n /** Sender must have a verification key. */\n SENDER_MISSING_VERIFICATION_KEY = \"SENDER_MISSING_VERIFICATION_KEY\",\n\n /** Continuation has expired. */\n CONTINUATION_EXPIRED = \"CONTINUATION_EXPIRED\",\n\n /** Continuation ID is invalid. */\n CONTINUATION_ID_INVALID = \"CONTINUATION_ID_INVALID\",\n\n /** Peer continuation must be encrypted. */\n PEER_CONTINUATION_NOT_ENCRYPTED = \"PEER_CONTINUATION_NOT_ENCRYPTED\",\n\n /** Requests must contain a peer continuation. */\n MISSING_PEER_CONTINUATION = \"MISSING_PEER_CONTINUATION\",\n\n /** Error from envelope operations. */\n ENVELOPE = \"ENVELOPE\",\n\n /** Error from XID operations. */\n XID = \"XID\",\n}\n\n/**\n * Error class for GSTP operations.\n *\n * Provides specific error types that can occur during GSTP message\n * creation, sealing, and parsing operations.\n */\nexport class GstpError extends Error {\n readonly code: GstpErrorCode;\n declare readonly cause?: Error;\n\n constructor(code: GstpErrorCode, message: string, cause?: Error) {\n super(message);\n this.name = \"GstpError\";\n this.code = code;\n if (cause !== undefined) {\n this.cause = cause;\n }\n\n // Maintains proper stack trace for where our error was thrown (only available on V8)\n if (\"captureStackTrace\" in Error) {\n (\n Error as {\n captureStackTrace(target: object, constructor: typeof GstpError): void;\n }\n ).captureStackTrace(this, GstpError);\n }\n }\n\n /**\n * Returned when the sender is missing an encryption key.\n */\n static senderMissingEncryptionKey(): GstpError {\n return new GstpError(\n GstpErrorCode.SENDER_MISSING_ENCRYPTION_KEY,\n \"sender must have an encryption key\",\n );\n }\n\n /**\n * Returned when the recipient is missing an encryption key.\n */\n static recipientMissingEncryptionKey(): GstpError {\n return new GstpError(\n GstpErrorCode.RECIPIENT_MISSING_ENCRYPTION_KEY,\n \"recipient must have an encryption key\",\n );\n }\n\n /**\n * Returned when the sender is missing a verification key.\n */\n static senderMissingVerificationKey(): GstpError {\n return new GstpError(\n GstpErrorCode.SENDER_MISSING_VERIFICATION_KEY,\n \"sender must have a verification key\",\n );\n }\n\n /**\n * Returned when the continuation has expired.\n */\n static continuationExpired(): GstpError {\n return new GstpError(GstpErrorCode.CONTINUATION_EXPIRED, \"continuation expired\");\n }\n\n /**\n * Returned when the continuation ID is invalid.\n */\n static continuationIdInvalid(): GstpError {\n return new GstpError(GstpErrorCode.CONTINUATION_ID_INVALID, \"continuation ID invalid\");\n }\n\n /**\n * Returned when the peer continuation is not encrypted.\n */\n static peerContinuationNotEncrypted(): GstpError {\n return new GstpError(\n GstpErrorCode.PEER_CONTINUATION_NOT_ENCRYPTED,\n \"peer continuation must be encrypted\",\n );\n }\n\n /**\n * Returned when a request is missing the peer continuation.\n */\n static missingPeerContinuation(): GstpError {\n return new GstpError(\n GstpErrorCode.MISSING_PEER_CONTINUATION,\n \"requests must contain a peer continuation\",\n );\n }\n\n /**\n * Envelope error wrapper.\n */\n static envelope(cause?: Error): GstpError {\n return new GstpError(GstpErrorCode.ENVELOPE, \"envelope error\", cause);\n }\n\n /**\n * XID error wrapper.\n */\n static xid(cause?: Error): GstpError {\n return new GstpError(GstpErrorCode.XID, \"XID error\", cause);\n }\n}\n","/**\n * Continuation - Encrypted State Continuations (ESC)\n *\n * Continuations embed encrypted state data directly into messages,\n * eliminating the need for local state storage and enhancing security\n * for devices with limited storage or requiring distributed state management.\n *\n * Ported from gstp-rust/src/continuation.rs\n */\n\nimport { ARID, type Encrypter, type PrivateKeys } from \"@bcts/components\";\nimport { Envelope, type EnvelopeEncodableValue } from \"@bcts/envelope\";\nimport { ID, VALID_UNTIL } from \"@bcts/known-values\";\nimport { GstpError } from \"./error\";\n\n/**\n * Represents an encrypted state continuation.\n *\n * Continuations provide a way to maintain state across message exchanges\n * without requiring local storage. The state is encrypted and embedded\n * directly in the message envelope.\n *\n * @example\n * ```typescript\n * import { Continuation } from '@bcts/gstp';\n *\n * // Create a continuation with state\n * const continuation = new Continuation(\"session state data\")\n * .withValidId(requestId)\n * .withValidUntil(new Date(Date.now() + 60000)); // Valid for 60 seconds\n *\n * // Convert to envelope (optionally encrypted)\n * const envelope = continuation.toEnvelope(recipientPublicKey);\n * ```\n */\nexport class Continuation {\n private readonly _state: Envelope;\n private readonly _validId: ARID | undefined;\n private readonly _validUntil: Date | undefined;\n\n /**\n * Creates a new Continuation with the given state.\n *\n * The state can be any value that implements EnvelopeEncodable.\n *\n * @param state - The state to embed in the continuation\n * @param validId - Optional ID for validation\n * @param validUntil - Optional expiration date\n */\n constructor(state: EnvelopeEncodableValue, validId?: ARID, validUntil?: Date) {\n this._state = Envelope.new(state);\n this._validId = validId;\n this._validUntil = validUntil;\n }\n\n /**\n * Creates a new continuation with a specific valid ID.\n *\n * @param validId - The ID to use for validation\n * @returns A new Continuation instance with the valid ID set\n */\n withValidId(validId: ARID): Continuation {\n return new Continuation(this._state, validId, this._validUntil);\n }\n\n /**\n * Creates a new continuation with an optional valid ID.\n *\n * @param validId - The ID to use for validation, or undefined\n * @returns A new Continuation instance with the valid ID set\n */\n withOptionalValidId(validId: ARID | undefined): Continuation {\n return new Continuation(this._state, validId, this._validUntil);\n }\n\n /**\n * Creates a new continuation with a specific valid until date.\n *\n * @param validUntil - The date until which the continuation is valid\n * @returns A new Continuation instance with the valid until date set\n */\n withValidUntil(validUntil: Date): Continuation {\n return new Continuation(this._state, this._validId, validUntil);\n }\n\n /**\n * Creates a new continuation with an optional valid until date.\n *\n * @param validUntil - The date until which the continuation is valid, or undefined\n * @returns A new Continuation instance with the valid until date set\n */\n withOptionalValidUntil(validUntil: Date | undefined): Continuation {\n return new Continuation(this._state, this._validId, validUntil);\n }\n\n /**\n * Creates a new continuation with a validity duration from now.\n *\n * @param durationMs - The duration in milliseconds for which the continuation is valid\n * @returns A new Continuation instance with the valid until date set\n */\n withValidDuration(durationMs: number): Continuation {\n const validUntil = new Date(Date.now() + durationMs);\n return new Continuation(this._state, this._validId, validUntil);\n }\n\n /**\n * Returns the state envelope of the continuation.\n */\n state(): Envelope {\n return this._state;\n }\n\n /**\n * Returns the valid ID of the continuation, if set.\n */\n id(): ARID | undefined {\n return this._validId;\n }\n\n /**\n * Returns the valid until date of the continuation, if set.\n */\n validUntil(): Date | undefined {\n return this._validUntil;\n }\n\n /**\n * Checks if the continuation is valid at the given time.\n *\n * If no valid_until is set, always returns true.\n * If no time is provided, always returns true.\n *\n * @param now - The time to check against, or undefined to skip time validation\n * @returns true if the continuation is valid at the given time\n */\n isValidDate(now?: Date): boolean {\n if (this._validUntil === undefined) {\n return true;\n }\n if (now === undefined) {\n return true;\n }\n return now.getTime() <= this._validUntil.getTime();\n }\n\n /**\n * Checks if the continuation has the expected ID.\n *\n * If no valid_id is set, always returns true.\n * If no ID is provided for checking, always returns true.\n *\n * @param id - The ID to check against, or undefined to skip ID validation\n * @returns true if the continuation has the expected ID\n */\n isValidId(id?: ARID): boolean {\n if (this._validId === undefined) {\n return true;\n }\n if (id === undefined) {\n return true;\n }\n return this._validId.equals(id);\n }\n\n /**\n * Checks if the continuation is valid (both date and ID).\n *\n * @param now - The time to check against, or undefined to skip time validation\n * @param id - The ID to check against, or undefined to skip ID validation\n * @returns true if the continuation is valid\n */\n isValid(now?: Date, id?: ARID): boolean {\n return this.isValidDate(now) && this.isValidId(id);\n }\n\n /**\n * Converts the continuation to an envelope.\n *\n * If a recipient is provided, the envelope is encrypted to that recipient.\n *\n * @param recipient - Optional recipient to encrypt the envelope to\n * @returns The continuation as an envelope\n */\n toEnvelope(recipient?: Encrypter): Envelope {\n let envelope = this._state;\n\n // Add ID assertion if set\n if (this._validId !== undefined) {\n envelope = envelope.addAssertion(ID, this._validId);\n }\n\n // Add valid_until assertion if set\n if (this._validUntil !== undefined) {\n envelope = envelope.addAssertion(VALID_UNTIL, this._validUntil.toISOString());\n }\n\n // Encrypt to recipient if provided\n if (recipient !== undefined) {\n envelope = envelope.encryptToRecipients([recipient]);\n }\n\n return envelope;\n }\n\n /**\n * Parses a continuation from an envelope.\n *\n * @param encryptedEnvelope - The envelope to parse\n * @param expectedId - Optional ID to validate against\n * @param now - Optional time to validate against\n * @param recipient - Optional private keys to decrypt with\n * @returns The parsed continuation\n * @throws GstpError if validation fails or parsing fails\n */\n static tryFromEnvelope(\n encryptedEnvelope: Envelope,\n expectedId?: ARID,\n now?: Date,\n recipient?: PrivateKeys,\n ): Continuation {\n // Decrypt if recipient is provided\n let envelope = encryptedEnvelope;\n if (recipient !== undefined) {\n try {\n envelope = encryptedEnvelope.decryptToRecipient(recipient);\n } catch (e) {\n throw GstpError.envelope(e instanceof Error ? e : new Error(String(e)));\n }\n }\n\n // Extract the state (the subject of the envelope)\n const state = envelope.subject();\n\n // Extract optional ID\n let validId: ARID | undefined;\n try {\n const idObj = envelope.objectForPredicate(ID);\n if (idObj !== undefined) {\n // The ID is stored as a leaf envelope containing the ARID's tagged CBOR\n const leafCbor = idObj.asLeaf();\n if (leafCbor !== undefined) {\n validId = ARID.fromTaggedCborData(leafCbor.toData());\n }\n }\n } catch {\n // ID is optional\n }\n\n // Extract optional valid_until\n let validUntil: Date | undefined;\n try {\n const validUntilObj = envelope.objectForPredicate(VALID_UNTIL);\n if (validUntilObj !== undefined) {\n const dateStr = validUntilObj.asText();\n if (dateStr !== undefined) {\n validUntil = new Date(dateStr);\n }\n }\n } catch {\n // valid_until is optional\n }\n\n // Create the continuation\n const continuation = new Continuation(state, validId, validUntil);\n\n // Validate date\n if (!continuation.isValidDate(now)) {\n throw GstpError.continuationExpired();\n }\n\n // Validate ID\n if (!continuation.isValidId(expectedId)) {\n throw GstpError.continuationIdInvalid();\n }\n\n return continuation;\n }\n\n /**\n * Checks equality with another continuation.\n *\n * Two continuations are equal if they have the same state, ID, and valid_until.\n *\n * @param other - The continuation to compare with\n * @returns true if the continuations are equal\n */\n equals(other: Continuation): boolean {\n // Compare state envelopes by their digests\n if (!this._state.digest().equals(other._state.digest())) {\n return false;\n }\n\n // Compare IDs\n if (this._validId === undefined && other._validId === undefined) {\n // Both undefined, equal\n } else if (this._validId !== undefined && other._validId !== undefined) {\n if (!this._validId.equals(other._validId)) {\n return false;\n }\n } else {\n // One is undefined, one is not\n return false;\n }\n\n // Compare valid_until\n if (this._validUntil === undefined && other._validUntil === undefined) {\n // Both undefined, equal\n } else if (this._validUntil !== undefined && other._validUntil !== undefined) {\n if (this._validUntil.getTime() !== other._validUntil.getTime()) {\n return false;\n }\n } else {\n // One is undefined, one is not\n return false;\n }\n\n return true;\n }\n\n /**\n * Returns a string representation of the continuation.\n */\n toString(): string {\n const parts = [`Continuation(state: ${this._state.formatFlat()}`];\n if (this._validId !== undefined) {\n parts.push(`id: ${this._validId.shortDescription()}`);\n }\n if (this._validUntil !== undefined) {\n parts.push(`validUntil: ${this._validUntil.toISOString()}`);\n }\n return `${parts.join(\", \")})`;\n }\n}\n","/**\n * SealedRequest - Sealed request messages for GSTP\n *\n * A SealedRequest wraps a Request with sender information and state\n * continuations for secure, authenticated request messages.\n *\n * Ported from gstp-rust/src/sealed_request.rs\n */\n\nimport type { ARID, PrivateKeys, Signer } from \"@bcts/components\";\nimport {\n Envelope,\n Request,\n type Expression,\n type Function,\n type EnvelopeEncodableValue,\n type ParameterID,\n} from \"@bcts/envelope\";\nimport { SENDER, SENDER_CONTINUATION, RECIPIENT_CONTINUATION } from \"@bcts/known-values\";\nimport { XIDDocument } from \"@bcts/xid\";\nimport { Continuation } from \"./continuation\";\nimport { GstpError } from \"./error\";\n\n/**\n * Interface that defines the behavior of a sealed request.\n *\n * Extends RequestBehavior with additional methods for managing\n * sender information and state continuations.\n */\nexport interface SealedRequestBehavior {\n /**\n * Adds state to the request that the receiver must return in the response.\n */\n withState(state: EnvelopeEncodableValue): SealedRequest;\n\n /**\n * Adds optional state to the request.\n */\n withOptionalState(state: EnvelopeEncodableValue | undefined): SealedRequest;\n\n /**\n * Adds a continuation previously received from the recipient.\n */\n withPeerContinuation(peerContinuation: Envelope): SealedRequest;\n\n /**\n * Adds an optional continuation previously received from the recipient.\n */\n withOptionalPeerContinuation(peerContinuation: Envelope | undefined): SealedRequest;\n\n /**\n * Returns the underlying request.\n */\n request(): Request;\n\n /**\n * Returns the sender of the request.\n */\n sender(): XIDDocument;\n\n /**\n * Returns the state to be sent to the recipient.\n */\n state(): Envelope | undefined;\n\n /**\n * Returns the continuation received from the recipient.\n */\n peerContinuation(): Envelope | undefined;\n}\n\n/**\n * A sealed request that combines a Request with sender information and\n * state continuations for secure communication.\n *\n * @example\n * ```typescript\n * import { SealedRequest, ARID } from '@bcts/gstp';\n * import { XIDDocument } from '@bcts/xid';\n *\n * // Create sender XID document\n * const sender = XIDDocument.new();\n * const requestId = ARID.new();\n *\n * // Create a sealed request\n * const request = SealedRequest.new(\"getBalance\", requestId, sender)\n * .withParameter(\"account\", \"alice\")\n * .withState(\"session-state-data\")\n * .withNote(\"Balance check\");\n *\n * // Convert to sealed envelope\n * const envelope = request.toEnvelope(\n * new Date(Date.now() + 60000), // Valid for 60 seconds\n * senderPrivateKey,\n * recipientXIDDocument\n * );\n * ```\n */\nexport class SealedRequest implements SealedRequestBehavior {\n private _request: Request;\n private readonly _sender: XIDDocument;\n private _state: Envelope | undefined;\n private _peerContinuation: Envelope | undefined;\n\n private constructor(\n request: Request,\n sender: XIDDocument,\n state?: Envelope,\n peerContinuation?: Envelope,\n ) {\n this._request = request;\n this._sender = sender;\n this._state = state;\n this._peerContinuation = peerContinuation;\n }\n\n /**\n * Creates a new sealed request with the given function, ID, and sender.\n *\n * @param func - The function to call (string name or Function object)\n * @param id - The request ID\n * @param sender - The sender's XID document\n */\n static new(func: string | number | Function, id: ARID, sender: XIDDocument): SealedRequest {\n return new SealedRequest(Request.new(func, id), sender);\n }\n\n /**\n * Creates a new sealed request with an expression body.\n *\n * @param body - The expression body\n * @param id - The request ID\n * @param sender - The sender's XID document\n */\n static newWithBody(body: Expression, id: ARID, sender: XIDDocument): SealedRequest {\n return new SealedRequest(Request.newWithBody(body, id), sender);\n }\n\n // ============================================================================\n // ExpressionBehavior implementation\n // ============================================================================\n\n /**\n * Adds a parameter to the request.\n */\n withParameter(parameter: ParameterID, value: EnvelopeEncodableValue): SealedRequest {\n this._request = this._request.withParameter(parameter, value);\n return this;\n }\n\n /**\n * Adds an optional parameter to the request.\n */\n withOptionalParameter(\n parameter: ParameterID,\n value: EnvelopeEncodableValue | undefined,\n ): SealedRequest {\n if (value !== undefined) {\n this._request = this._request.withParameter(parameter, value);\n }\n return this;\n }\n\n /**\n * Returns the function of the request.\n */\n function(): Function {\n return this._request.function();\n }\n\n /**\n * Returns the expression envelope of the request.\n */\n expressionEnvelope(): Envelope {\n return this._request.expressionEnvelope();\n }\n\n /**\n * Returns the object for a parameter.\n */\n objectForParameter(param: ParameterID): Envelope | undefined {\n return this._request.body().getParameter(param);\n }\n\n /**\n * Returns all objects for a parameter.\n */\n objectsForParameter(param: ParameterID): Envelope[] {\n const obj = this._request.body().getParameter(param);\n return obj !== undefined ? [obj] : [];\n }\n\n /**\n * Extracts an object for a parameter as a specific type.\n */\n extractObjectForParameter<T>(param: ParameterID): T {\n const envelope = this.objectForParameter(param);\n if (envelope === undefined) {\n throw GstpError.envelope(new Error(`Parameter not found: ${param}`));\n }\n return envelope.extractSubject((cbor) => {\n // Extract primitive value from CBOR\n if (cbor.isInteger()) return cbor.toInteger() as T;\n if (cbor.isText()) return cbor.toText() as T;\n if (cbor.isBool()) return cbor.toBool() as T;\n if (cbor.isNumber()) return cbor.toNumber() as T;\n if (cbor.isByteString()) return cbor.toByteString() as T;\n return cbor as T;\n });\n }\n\n /**\n * Extracts an optional object for a parameter.\n */\n extractOptionalObjectForParameter<T>(param: ParameterID): T | undefined {\n const envelope = this.objectForParameter(param);\n if (envelope === undefined) {\n return undefined;\n }\n return envelope.extractSubject((cbor) => {\n // Extract primitive value from CBOR\n if (cbor.isInteger()) return cbor.toInteger() as T;\n if (cbor.isText()) return cbor.toText() as T;\n if (cbor.isBool()) return cbor.toBool() as T;\n if (cbor.isNumber()) return cbor.toNumber() as T;\n if (cbor.isByteString()) return cbor.toByteString() as T;\n return cbor as T;\n });\n }\n\n /**\n * Extracts all objects for a parameter as a specific type.\n */\n extractObjectsForParameter<T>(param: ParameterID): T[] {\n return this.objectsForParameter(param).map((env) => env.extractSubject((cbor) => cbor as T));\n }\n\n // ============================================================================\n // RequestBehavior implementation\n // ============================================================================\n\n /**\n * Adds a note to the request.\n */\n withNote(note: string): SealedRequest {\n this._request = this._request.withNote(note);\n return this;\n }\n\n /**\n * Adds a date to the request.\n */\n withDate(date: Date): SealedRequest {\n this._request = this._request.withDate(date);\n return this;\n }\n\n /**\n * Returns the body of the request.\n */\n body(): Expression {\n return this._request.body();\n }\n\n /**\n * Returns the ID of the request.\n */\n id(): ARID {\n return this._request.id();\n }\n\n /**\n * Returns the note of the request.\n */\n note(): string {\n return this._request.note();\n }\n\n /**\n * Returns the date of the request.\n */\n date(): Date | undefined {\n return this._request.date();\n }\n\n // ============================================================================\n // SealedRequestBehavior implementation\n // ============================================================================\n\n /**\n * Adds state to the request that the receiver must return in the response.\n */\n withState(state: EnvelopeEncodableValue): SealedRequest {\n this._state = Envelope.new(state);\n return this;\n }\n\n /**\n * Adds optional state to the request.\n */\n withOptionalState(state: EnvelopeEncodableValue | undefined): SealedRequest {\n this._state = state !== undefined ? Envelope.new(state) : undefined;\n return this;\n }\n\n /**\n * Adds a continuation previously received from the recipient.\n */\n withPeerContinuation(peerContinuation: Envelope): SealedRequest {\n this._peerContinuation = peerContinuation;\n return this;\n }\n\n /**\n * Adds an optional continuation previously received from the recipient.\n */\n withOptionalPeerContinuation(peerContinuation: Envelope | undefined): SealedRequest {\n this._peerContinuation = peerContinuation;\n return this;\n }\n\n /**\n * Returns the underlying request.\n */\n request(): Request {\n return this._request;\n }\n\n /**\n * Returns the sender of the request.\n */\n sender(): XIDDocument {\n return this._sender;\n }\n\n /**\n * Returns the state to be sent to the recipient.\n */\n state(): Envelope | undefined {\n return this._state;\n }\n\n /**\n * Returns the continuation received from the recipient.\n */\n peerContinuation(): Envelope | undefined {\n return this._peerContinuation;\n }\n\n // ============================================================================\n // Conversion methods\n // ============================================================================\n\n /**\n * Converts the sealed request to a Request.\n */\n toRequest(): Request {\n return this._request;\n }\n\n /**\n * Converts the sealed request to an Expression.\n */\n toExpression(): Expression {\n return this._request.body();\n }\n\n // ============================================================================\n // Envelope methods\n // ============================================================================\n\n /**\n * Creates an envelope that can be decrypted by zero or one recipient.\n *\n * @param validUntil - Optional expiration date for the continuation\n * @param signer - Optional signer for the envelope\n * @param recipient - Optional recipient XID document for encryption\n * @returns The sealed request as an envelope\n */\n toEnvelope(validUntil?: Date, signer?: Signer, recipient?: XIDDocument): Envelope {\n const recipients: XIDDocument[] = recipient !== undefined ? [recipient] : [];\n return this.toEnvelopeForRecipients(validUntil, signer, recipients);\n }\n\n /**\n * Creates an envelope that can be decrypted by zero or more recipients.\n *\n * @param validUntil - Optional expiration date for the continuation\n * @param signer - Optional signer for the envelope\n * @param recipients - Array of recipient XID documents for encryption\n * @returns The sealed request as an envelope\n */\n toEnvelopeForRecipients(\n validUntil?: Date,\n signer?: Signer,\n recipients?: XIDDocument[],\n ): Envelope {\n // Even if no state is provided, requests always include a continuation\n // that at least specifies the required valid response ID.\n const stateEnvelope = this._state ?? Envelope.new(null);\n const continuation = new Continuation(stateEnvelope, this.id(), validUntil);\n\n // Get sender's encryption key (from inception key)\n const senderInceptionKey = this._sender.inceptionKey();\n const senderEncryptionKey = senderInceptionKey?.publicKeys()?.encapsulationPublicKey();\n if (senderEncryptionKey === undefined) {\n throw GstpError.senderMissingEncryptionKey();\n }\n\n // Create sender continuation (encrypted to sender)\n const senderContinuation = continuation.toEnvelope(senderEncryptionKey);\n\n // Build the request envelope\n let result = this._request.toEnvelope();\n\n // Add sender assertion\n result = result.addAssertion(SENDER, this._sender.toEnvelope());\n\n // Add sender continuation\n result = result.addAssertion(SENDER_CONTINUATION, senderContinuation);\n\n // Add peer continuation if present\n if (this._peerContinuation !== undefined) {\n result = result.addAssertion(RECIPIENT_CONTINUATION, this._peerContinuation);\n }\n\n // Sign if signer provided (sign() wraps first, then adds signature)\n if (signer !== undefined) {\n result = result.sign(signer);\n }\n\n // Encrypt to recipients if provided\n if (recipients !== undefined && recipients.length > 0) {\n const recipientKeys = recipients.map((recipient) => {\n const key = recipient.encryptionKey();\n if (key === undefined) {\n throw GstpError.recipientMissingEncryptionKey();\n }\n return key;\n });\n\n result = result.wrap().encryptSubjectToRecipients(recipientKeys);\n }\n\n return result;\n }\n\n /**\n * Parses a sealed request from an encrypted envelope.\n *\n * @param encryptedEnvelope - The encrypted envelope to parse\n * @param expectedId - Optional expected request ID for validation\n * @param now - Optional current time for continuation validation\n * @param recipient - The recipient's private keys for decryption\n * @returns The parsed sealed request\n */\n static tryFromEnvelope(\n encryptedEnvelope: Envelope,\n expectedId: ARID | undefined,\n now: Date | undefined,\n recipient: PrivateKeys,\n ): SealedRequest {\n // Decrypt the envelope\n let signedEnvelope: Envelope;\n try {\n signedEnvelope = encryptedEnvelope.decryptToRecipient(recipient);\n } catch (e) {\n throw GstpError.envelope(e instanceof Error ? e : new Error(String(e)));\n }\n\n // Extract sender from the unwrapped envelope\n let sender: XIDDocument;\n try {\n const unwrapped = signedEnvelope.tryUnwrap();\n const senderEnvelope = unwrapped.objectForPredicate(SENDER);\n if (senderEnvelope === undefined) {\n throw new Error(\"Missing sender\");\n }\n sender = XIDDocument.fromEnvelope(senderEnvelope);\n } catch (e) {\n throw GstpError.xid(e instanceof Error ? e : new Error(String(e)));\n }\n\n // Get sender's verification key and verify signature (from inception key)\n const senderInceptionKey = sender.inceptionKey();\n const senderVerificationKey = senderInceptionKey?.publicKeys()?.signingPublicKey();\n if (senderVerificationKey === undefined) {\n throw GstpError.senderMissingVerificationKey();\n }\n\n let requestEnvelope: Envelope;\n try {\n // verify() both verifies the signature AND unwraps the envelope\n requestEnvelope = signedEnvelope.verify(senderVerificationKey);\n } catch (e) {\n throw GstpError.envelope(e instanceof Error ? e : new Error(String(e)));\n }\n\n // Get peer continuation (sender_continuation from the request)\n const peerContinuation = requestEnvelope.optionalObjectForPredicate(SENDER_CONTINUATION);\n if (peerContinuation !== undefined) {\n // Verify peer continuation is encrypted\n if (!peerContinuation.subject().isEncrypted()) {\n throw GstpError.peerContinuationNotEncrypted();\n }\n } else {\n throw GstpError.missingPeerContinuation();\n }\n\n // Get and decrypt our continuation (recipient_continuation)\n const encryptedContinuation =\n requestEnvelope.optionalObjectForPredicate(RECIPIENT_CONTINUATION);\n let state: Envelope | undefined;\n if (encryptedContinuation !== undefined) {\n const continuation = Continuation.tryFromEnvelope(\n encryptedContinuation,\n expectedId,\n now,\n recipient,\n );\n state = continuation.state();\n }\n\n // Parse the request\n let request: Request;\n try {\n request = Request.fromEnvelope(requestEnvelope);\n } catch (e) {\n throw GstpError.envelope(e instanceof Error ? e : new Error(String(e)));\n }\n\n return new SealedRequest(request, sender, state, peerContinuation);\n }\n\n // ============================================================================\n // Display methods\n // ============================================================================\n\n /**\n * Returns a string representation of the sealed request.\n */\n toString(): string {\n const stateStr = this._state !== undefined ? this._state.formatFlat() : \"None\";\n const peerStr = this._peerContinuation !== undefined ? \"Some\" : \"None\";\n return `SealedRequest(${this._request.summary()}, state: ${stateStr}, peer_continuation: ${peerStr})`;\n }\n\n /**\n * Checks equality with another sealed request.\n */\n equals(other: SealedRequest): boolean {\n if (!this._request.equals(other._request)) {\n return false;\n }\n if (!this._sender.xid().equals(other._sender.xid())) {\n return false;\n }\n // Compare state\n if (this._state === undefined && other._state === undefined) {\n // Both undefined, equal\n } else if (this._state !== undefined && other._state !== undefined) {\n if (!this._state.digest().equals(other._state.digest())) {\n return false;\n }\n } else {\n return false;\n }\n // Compare peer continuation\n if (this._peerContinuation === undefined && other._peerContinuation === undefined) {\n // Both undefined, equal\n } else if (this._peerContinuation !== undefined && other._peerContinuation !== undefined) {\n if (!this._peerContinuation.digest().equals(other._peerContinuation.digest())) {\n return false;\n }\n } else {\n return false;\n }\n return true;\n }\n}\n","/**\n * SealedResponse - Sealed response messages for GSTP\n *\n * A SealedResponse wraps a Response with sender information and state\n * continuations for secure, authenticated response messages.\n *\n * Ported from gstp-rust/src/sealed_response.rs\n */\n\nimport type { ARID, PrivateKeys, Signer } from \"@bcts/components\";\nimport { Envelope, Response, type EnvelopeEncodableValue } from \"@bcts/envelope\";\nimport { SENDER, SENDER_CONTINUATION, RECIPIENT_CONTINUATION } from \"@bcts/known-values\";\nimport { XIDDocument } from \"@bcts/xid\";\nimport { Continuation } from \"./continuation\";\nimport { GstpError } from \"./error\";\n\n/**\n * Interface that defines the behavior of a sealed response.\n *\n * Extends ResponseBehavior with additional methods for managing\n * sender information and state continuations.\n */\nexport interface SealedResponseBehavior {\n /**\n * Adds state to the response that the peer may return at some future time.\n */\n withState(state: EnvelopeEncodableValue): SealedResponse;\n\n /**\n * Adds optional state to the response.\n */\n withOptionalState(state: EnvelopeEncodableValue | undefined): SealedResponse;\n\n /**\n * Adds a continuation previously received from the recipient.\n */\n withPeerContinuation(peerContinuation: Envelope | undefined): SealedResponse;\n\n /**\n * Returns the sender of the response.\n */\n sender(): XIDDocument;\n\n /**\n * Returns the state to be sent to the peer.\n */\n state(): Envelope | undefined;\n\n /**\n * Returns the continuation received from the peer.\n */\n peerContinuation(): Envelope | undefined;\n}\n\n/**\n * A sealed response that combines a Response with sender information and\n * state continuations for secure communication.\n *\n * @example\n * ```typescript\n * import { SealedResponse, ARID } from '@bcts/gstp';\n * import { XIDDocument } from '@bcts/xid';\n *\n * // Create sender XID document\n * const sender = XIDDocument.new();\n * const requestId = ARID.new();\n *\n * // Create a successful sealed response\n * const response = SealedResponse.newSuccess(requestId, sender)\n * .withResult(\"Operation completed\")\n * .withState(\"next-page-state\");\n *\n * // Convert to sealed envelope\n * const envelope = response.toEnvelope(\n * new Date(Date.now() + 60000), // Valid for 60 seconds\n * senderPrivateKey,\n * recipientXIDDocument\n * );\n * ```\n */\nexport class SealedResponse implements SealedResponseBehavior {\n private _response: Response;\n private readonly _sender: XIDDocument;\n private _state: Envelope | undefined;\n private _peerContinuation: Envelope | undefined;\n\n private constructor(\n response: Response,\n sender: XIDDocument,\n state?: Envelope,\n peerContinuation?: Envelope,\n ) {\n this._response = response;\n this._sender = sender;\n this._state = state;\n this._peerContinuation = peerContinuation;\n }\n\n // ============================================================================\n // Static Factory Methods\n // ============================================================================\n\n /**\n * Creates a new successful sealed response.\n *\n * @param id - The request ID this response is for\n * @param sender - The sender's XID document\n */\n static newSuccess(id: ARID, sender: XIDDocument): SealedResponse {\n return new SealedResponse(Response.newSuccess(id), sender);\n }\n\n /**\n * Creates a new failure sealed response.\n *\n * @param id - The request ID this response is for\n * @param sender - The sender's XID document\n */\n static newFailure(id: ARID, sender: XIDDocument): SealedResponse {\n return new SealedResponse(Response.newFailure(id), sender);\n }\n\n /**\n * Creates a new early failure sealed response.\n *\n * An early failure takes place before the message has been decrypted,\n * and therefore the ID and sender public key are not known.\n *\n * @param sender - The sender's XID document\n */\n static newEarlyFailure(sender: XIDDocument): SealedResponse {\n return new SealedResponse(Response.newEarlyFailure(), sender);\n }\n\n // ============================================================================\n // SealedResponseBehavior implementation\n // ============================================================================\n\n /**\n * Adds state to the response that the peer may return at some future time.\n *\n * @throws Error if called on a failed response\n */\n withState(state: EnvelopeEncodableValue): SealedResponse {\n if (!this._response.isOk()) {\n throw new Error(\"Cannot set state on a failed response\");\n }\n this._state = Envelope.new(state);\n return this;\n }\n\n /**\n * Adds optional state to the response.\n */\n withOptionalState(state: EnvelopeEncodableValue | undefined): SealedResponse {\n if (state !== undefined) {\n return this.withState(state);\n }\n this._state = undefined;\n return this;\n }\n\n /**\n * Adds a continuation previously received from the recipient.\n */\n withPeerContinuation(peerContinuation: Envelope | undefined): SealedResponse {\n this._peerContinuation = peerContinuation;\n return this;\n }\n\n /**\n * Returns the sender of the response.\n */\n sender(): XIDDocument {\n return this._sender;\n }\n\n /**\n * Returns the state to be sent to the peer.\n */\n state(): Envelope | undefined {\n return this._state;\n }\n\n /**\n * Returns the continuation received from the peer.\n */\n peerContinuation(): Envelope | undefined {\n return this._peerContinuation;\n }\n\n // ============================================================================\n // ResponseBehavior implementation\n // ============================================================================\n\n /**\n * Sets the result value for a successful response.\n */\n withResult(result: EnvelopeEncodableValue): SealedResponse {\n this._response = this._response.withResult(result);\n return this;\n }\n\n /**\n * Sets an optional result value for a successful response.\n * If the result is undefined, the value of the response will be the null envelope.\n */\n withOptionalResult(result: EnvelopeEncodableValue | undefined): SealedResponse {\n this._response = this._response.withOptionalResult(result);\n return this;\n }\n\n /**\n * Sets the error value for a failure response.\n */\n withError(error: EnvelopeEncodableValue): SealedResponse {\n this._response = this._response.withError(error);\n return this;\n }\n\n /**\n * Sets an optional error value for a failure response.\n * If the error is undefined, the value of the response will be the unknown value.\n */\n withOptionalError(error: EnvelopeEncodableValue | undefined): SealedResponse {\n this._response = this._response.withOptionalError(error);\n return this;\n }\n\n /**\n * Returns true if this is a successful response.\n */\n isOk(): boolean {\n return this._response.isOk();\n }\n\n /**\n * Returns true if this is a failure response.\n */\n isErr(): boolean {\n return this._response.isErr();\n }\n\n /**\n * Returns the ID of the request this response is for, if known.\n */\n id(): ARID | undefined {\n return this._response.id();\n }\n\n /**\n * Returns the ID of the request this response is for.\n * @throws Error if the ID is not known\n */\n expectId(): ARID {\n return this._response.expectId();\n }\n\n /**\n * Returns the result envelope if this is a successful response.\n * @throws Error if this is a failure response\n */\n result(): Envelope {\n return this._response.result();\n }\n\n /**\n * Extracts the result as a specific type.\n */\n extractResult<T>(decoder: (cbor: unknown) => T): T {\n return this._response.extractResult(decoder);\n }\n\n /**\n * Returns the error envelope if this is a failure response.\n * @throws Error if this is a successful response\n */\n error(): Envelope {\n return this._response.error();\n }\n\n /**\n * Extracts the error as a specific type.\n */\n extractError<T>(decoder: (cbor: unknown) => T): T {\n return this._response.extractError(decoder);\n }\n\n // ============================================================================\n // Envelope methods\n // ============================================================================\n\n /**\n * Creates an envelope that can be decrypted by zero or one recipient.\n *\n * @param validUntil - Optional expiration date for the continuation\n * @param signer - Optional signer for the envelope\n * @param recipient - Optional recipient XID document for encryption\n * @returns The sealed response as an envelope\n */\n toEnvelope(validUntil?: Date, signer?: Signer, recipient?: XIDDocument): Envelope {\n const recipients: XIDDocument[] = recipient !== undefined ? [recipient] : [];\n return this.toEnvelopeForRecipients(validUntil, signer, recipients);\n }\n\n /**\n * Creates an envelope that can be decrypted by zero or more recipients.\n *\n * @param validUntil - Optional expiration date for the continuation\n * @param signer - Optional signer for the envelope\n * @param recipients - Array of recipient XID documents for encryption\n * @returns The sealed response as an envelope\n */\n toEnvelopeForRecipients(\n validUntil?: Date,\n signer?: Signer,\n recipients?: XIDDocument[],\n ): Envelope {\n // Build sender continuation only if state is present\n let senderContinuation: Envelope | undefined;\n if (this._state !== undefined) {\n const continuation = new Continuation(this._state, undefined, validUntil);\n\n // Get sender's encryption key (from inception key)\n const senderInceptionKey = this._sender.inceptionKey();\n const senderEncryptionKey = senderInceptionKey?.publicKeys()?.encapsulationPublicKey();\n if (senderEncryptionKey === undefined) {\n throw GstpError.senderMissingEncryptionKey();\n }\n\n senderContinuation = continuation.toEnvelope(senderEncryptionKey);\n }\n\n // Build the response envelope\n let result = this._response.toEnvelope();\n\n // Add sender assertion\n result = result.addAssertion(SENDER, this._sender.toEnvelope());\n\n // Add sender continuation if present\n if (senderContinuation !== undefined) {\n result = result.addAssertion(SENDER_CONTINUATION, senderContinuation);\n }\n\n // Add peer continuation if present\n if (this._peerContinuation !== undefined) {\n result = result.addAssertion(RECIPIENT_CONTINUATION, this._peerContinuation);\n }\n\n // Sign if signer provided (sign() wraps first, then adds signature)\n if (signer !== undefined) {\n result = result.sign(signer);\n }\n\n // Encrypt to recipients if provided\n if (recipients !== undefined && recipients.length > 0) {\n const recipientKeys = recipients.map((recipient) => {\n const key = recipient.encryptionKey();\n if (key === undefined) {\n throw GstpError.recipientMissingEncryptionKey();\n }\n return key;\n });\n\n result = result.wrap().encryptSubjectToRecipients(recipientKeys);\n }\n\n return result;\n }\n\n /**\n * Parses a sealed response from an encrypted envelope.\n *\n * @param encryptedEnvelope - The encrypted envelope to parse\n * @param expectedId - Optional expected request ID for validation\n * @param now - Optional current time for continuation validation\n * @param recipientPrivateKey - The recipient's private keys for decryption\n * @returns The parsed sealed response\n */\n static tryFromEncryptedEnvelope(\n encryptedEnvelope: Envelope,\n expectedId: ARID | undefined,\n now: Date | undefined,\n recipientPrivateKey: PrivateKeys,\n ): SealedResponse {\n // Decrypt the envelope\n let signedEnvelope: Envelope;\n try {\n signedEnvelope = encryptedEnvelope.decryptToRecipient(recipientPrivateKey);\n } catch (e) {\n throw GstpError.envelope(e instanceof Error ? e : new Error(String(e)));\n }\n\n // Extract sender from the unwrapped envelope\n let sender: XIDDocument;\n try {\n const unwrapped = signedEnvelope.tryUnwrap();\n const senderEnvelope = unwrapped.objectForPredicate(SENDER);\n if (senderEnvelope === undefined) {\n throw new Error(\"Missing sender\");\n }\n sender = XIDDocument.fromEnvelope(senderEnvelope);\n } catch (e) {\n throw GstpError.xid(e instanceof Error ? e : new Error(String(e)));\n }\n\n // Get sender's verification key and verify signature (from inception key)\n const senderInceptionKey = sender.inceptionKey();\n const senderVerificationKey = senderInceptionKey?.publicKeys()?.signingPublicKey();\n if (senderVerificationKey === undefined) {\n throw GstpError.senderMissingVerificationKey();\n }\n\n let responseEnvelope: Envelope;\n try {\n // verify() both verifies the signature AND unwraps the envelope\n responseEnvelope = signedEnvelope.verify(senderVerificationKey);\n } catch (e) {\n throw GstpError.envelope(e instanceof Error ? e : new Error(String(e)));\n }\n\n // Get peer continuation (sender_continuation from the response)\n const peerContinuation = responseEnvelope.optionalObjectForPredicate(SENDER_CONTINUATION);\n if (peerContinuation !== undefined) {\n // Verify peer continuation is encrypted\n if (!peerContinuation.subject().isEncrypted()) {\n throw GstpError.peerContinuationNotEncrypted();\n }\n }\n\n // Get and decrypt our continuation (recipient_continuation)\n const encryptedContinuation =\n responseEnvelope.optionalObjectForPredicate(RECIPIENT_CONTINUATION);\n let state: Envelope | undefined;\n if (encryptedContinuation !== undefined) {\n const continuation = Continuation.tryFromEnvelope(\n encryptedContinuation,\n expectedId,\n now,\n recipientPrivateKey,\n );\n // Check if state is null\n const stateEnv = continuation.state();\n if (stateEnv.isNull()) {\n state = undefined;\n } else {\n state = stateEnv;\n }\n }\n\n // Parse the response\n let response: Response;\n try {\n response = Response.fromEnvelope(responseEnvelope);\n } catch (e) {\n throw GstpError.envelope(e instanceof Error ? e : new Error(String(e)));\n }\n\n return new SealedResponse(response, sender, state, peerContinuation);\n }\n\n // ============================================================================\n // Display methods\n // ============================================================================\n\n /**\n * Returns a string representation of the sealed response.\n */\n toString(): string {\n const stateStr = this._state !== undefined ? this._state.formatFlat() : \"None\";\n const peerStr = this._peerContinuation !== undefined ? \"Some\" : \"None\";\n return `SealedResponse(${this._response.summary()}, state: ${stateStr}, peer_continuation: ${peerStr})`;\n }\n\n /**\n * Checks equality with another sealed response.\n */\n equals(other: SealedResponse): boolean {\n if (!this._response.equals(other._response)) {\n return false;\n }\n if (!this._sender.xid().equals(other._sender.xid())) {\n return false;\n }\n // Compare state\n if (this._state === undefined && other._state === undefined) {\n // Both undefined, equal\n } else if (this._state !== undefined && other._state !== undefined) {\n if (!this._state.digest().equals(other._state.digest())) {\n return false;\n }\n } else {\n return false;\n }\n // Compare peer continuation\n if (this._peerContinuation === undefined && other._peerContinuation === undefined) {\n // Both undefined, equal\n } else if (this._peerContinuation !== undefined && other._peerContinuation !== undefined) {\n if (!this._peerContinuation.digest().equals(other._peerContinuation.digest())) {\n return false;\n }\n } else {\n return false;\n }\n return true;\n }\n}\n","/**\n * SealedEvent - Sealed event messages for GSTP\n *\n * A SealedEvent wraps an Event with sender information and state\n * continuations for secure, authenticated event messages.\n *\n * Unlike SealedRequest/SealedResponse which form a pair, SealedEvent\n * is a standalone message for broadcasting information, logging,\n * or publishing notifications.\n *\n * Ported from gstp-rust/src/sealed_event.rs\n */\n\nimport type { ARID, PrivateKeys, Signer } from \"@bcts/components\";\nimport { Envelope, Event, type EnvelopeEncodableValue } from \"@bcts/envelope\";\nimport { SENDER, SENDER_CONTINUATION, RECIPIENT_CONTINUATION } from \"@bcts/known-values\";\nimport { XIDDocument } from \"@bcts/xid\";\nimport { Continuation } from \"./continuation\";\nimport { GstpError } from \"./error\";\n\n/**\n * Interface that defines the behavior of a sealed event.\n *\n * Extends EventBehavior with additional methods for managing\n * sender information and state continuations.\n */\nexport interface SealedEventBehavior<T extends EnvelopeEncodableValue> {\n /**\n * Adds state to the event that the receiver must return in the response.\n */\n withState(state: EnvelopeEncodableValue): SealedEvent<T>;\n\n /**\n * Adds optional state to the event.\n */\n withOptionalState(state: EnvelopeEncodableValue | undefined): SealedEvent<T>;\n\n /**\n * Adds a continuation previously received from the recipient.\n */\n withPeerContinuation(peerContinuation: Envelope): SealedEvent<T>;\n\n /**\n * Adds an optional continuation previously received from the recipient.\n */\n withOptionalPeerContinuation(peerContinuation: Envelope | undefined): SealedEvent<T>;\n\n /**\n * Returns the underlying event.\n */\n event(): Event<T>;\n\n /**\n * Returns the sender of the event.\n */\n sender(): XIDDocument;\n\n /**\n * Returns the state to be sent to the recipient.\n */\n state(): Envelope | undefined;\n\n /**\n * Returns the continuation received from the recipient.\n */\n peerContinuation(): Envelope | undefined;\n}\n\n/**\n * A sealed event that combines an Event with sender information and\n * state continuations for secure communication.\n *\n * @typeParam T - The type of content this event carries\n *\n * @example\n * ```typescript\n * import { SealedEvent, ARID } from '@bcts/gstp';\n * import { XIDDocument } from '@bcts/xid';\n *\n * // Create sender XID document\n * const sender = XIDDocument.new();\n * const eventId = ARID.new();\n *\n * // Create a sealed event\n * const event = SealedEvent.new(\"System notification\", eventId, sender)\n * .withNote(\"Status update\")\n * .withDate(new Date());\n *\n * // Convert to sealed envelope\n * const envelope = event.toEnvelope(\n * new Date(Date.now() + 60000), // Valid for 60 seconds\n * senderPrivateKey,\n * recipientXIDDocument\n * );\n * ```\n */\nexport class SealedEvent<T extends EnvelopeEncodableValue> implements SealedEventBehavior<T> {\n private _event: Event<T>;\n private readonly _sender: XIDDocument;\n private _state: Envelope | undefined;\n private _peerContinuation: Envelope | undefined;\n\n private constructor(\n event: Event<T>,\n sender: XIDDocument,\n state?: Envelope,\n peerContinuation?: Envelope,\n ) {\n this._event = event;\n this._sender = sender;\n this._state = state;\n this._peerContinuation = peerContinuation;\n }\n\n /**\n * Creates a new sealed event with the given content, ID, and sender.\n *\n * @param content - The content of the event\n * @param id - The event ID\n * @param sender - The sender's XID document\n */\n static new<T extends EnvelopeEncodableValue>(\n content: T,\n id: ARID,\n sender: XIDDocument,\n ): SealedEvent<T> {\n return new SealedEvent(Event.new(content, id), sender);\n }\n\n // ============================================================================\n // EventBehavior implementation\n // ============================================================================\n\n /**\n * Adds a note to the event.\n */\n withNote(note: string): SealedEvent<T> {\n this._event = this._event.withNote(note);\n return this;\n }\n\n /**\n * Adds a date to the event.\n */\n withDate(date: Date): SealedEvent<T> {\n this._event = this._event.withDate(date);\n return this;\n }\n\n /**\n * Returns the content of the event.\n */\n content(): T {\n return this._event.content();\n }\n\n /**\n * Returns the ID of the event.\n */\n id(): ARID {\n return this._event.id();\n }\n\n /**\n * Returns the note of the event.\n */\n note(): string {\n return this._event.note();\n }\n\n /**\n * Returns the date of the event.\n */\n date(): Date | undefined {\n return this._event.date();\n }\n\n // ============================================================================\n // SealedEventBehavior implementation\n // ============================================================================\n\n /**\n * Adds state to the event that the receiver must return in the response.\n */\n withState(state: EnvelopeEncodableValue): SealedEvent<T> {\n this._state = Envelope.new(state);\n return this;\n }\n\n /**\n * Adds optional state to the event.\n */\n withOptionalState(state: EnvelopeEncodableValue | undefined): SealedEvent<T> {\n if (state !== undefined) {\n return this.withState(state);\n }\n this._state = undefined;\n return this;\n }\n\n /**\n * Adds a continuation previously received from the recipient.\n */\n withPeerContinuation(peerContinuation: Envelope): SealedEvent<T> {\n this._peerContinuation = peerContinuation;\n return this;\n }\n\n /**\n * Adds an optional continuation previously received from the recipient.\n */\n withOptionalPeerContinuation(peerContinuation: Envelope | undefined): SealedEvent<T> {\n this._peerContinuation = peerContinuation;\n return this;\n }\n\n /**\n * Returns the underlying event.\n */\n event(): Event<T> {\n return this._event;\n }\n\n /**\n * Returns the sender of the event.\n */\n sender(): XIDDocument {\n return this._sender;\n }\n\n /**\n * Returns the state to be sent to the recipient.\n */\n state(): Envelope | undefined {\n return this._state;\n }\n\n /**\n * Returns the continuation received from the recipient.\n */\n peerContinuation(): Envelope | undefined {\n return this._peerContinuation;\n }\n\n // ============================================================================\n // Conversion methods\n // ============================================================================\n\n /**\n * Converts the sealed event to an Event.\n */\n toEvent(): Event<T> {\n return this._event;\n }\n\n // ============================================================================\n // Envelope methods\n // ============================================================================\n\n /**\n * Creates an envelope that can be decrypted by zero or one recipient.\n *\n * @param validUntil - Optional expiration date for the continuation\n * @param signer - Optional signer for the envelope\n * @param recipient - Optional recipient XID document for encryption\n * @returns The sealed event as an envelope\n */\n toEnvelope(validUntil?: Date, signer?: Signer, recipient?: XIDDocument): Envelope {\n const recipients: XIDDocument[] = recipient !== undefined ? [recipient] : [];\n return this.toEnvelopeForRecipients(validUntil, signer, recipients);\n }\n\n /**\n * Creates an envelope that can be decrypted by zero or more recipients.\n *\n * @param validUntil - Optional expiration date for the continuation\n * @param signer - Optional signer for the envelope\n * @param recipients - Array of recipient XID documents for encryption\n * @returns The sealed event as an envelope\n */\n toEnvelopeForRecipients(\n validUntil?: Date,\n signer?: Signer,\n recipients?: XIDDocument[],\n ): Envelope {\n // Get sender's encryption key (from inception key)\n const senderInceptionKey = this._sender.inceptionKey();\n const senderEncryptionKey = senderInceptionKey?.publicKeys()?.encapsulationPublicKey();\n if (senderEncryptionKey === undefined) {\n throw GstpError.senderMissingEncryptionKey();\n }\n\n // Build sender continuation\n let senderContinuation: Envelope | undefined;\n if (this._state !== undefined) {\n // If state is present, create continuation with state and optional valid_until\n const continuation = new Continuation(this._state, undefined, validUntil);\n senderContinuation = continuation.toEnvelope(senderEncryptionKey);\n } else if (validUntil !== undefined) {\n // If only valid_until is present (no state), create continuation with null state\n const continuation = new Continuation(Envelope.new(null), undefined, validUntil);\n senderContinuation = continuation.toEnvelope(senderEncryptionKey);\n }\n\n // Build the event envelope\n let result = this._event.toEnvelope();\n\n // Add sender assertion\n result = result.addAssertion(SENDER, this._sender.toEnvelope());\n\n // Add sender continuation if present\n if (senderContinuation !== undefined) {\n result = result.addAssertion(SENDER_CONTINUATION, senderContinuation);\n }\n\n // Add peer continuation if present\n if (this._peerContinuation !== undefined) {\n result = result.addAssertion(RECIPIENT_CONTINUATION, this._peerContinuation);\n }\n\n // Sign if signer provided (sign() wraps first, then adds signature)\n if (signer !== undefined) {\n result = result.sign(signer);\n }\n\n // Encrypt to recipients if provided\n if (recipients !== undefined && recipients.length > 0) {\n const recipientKeys = recipients.map((recipient) => {\n const key = recipient.encryptionKey();\n if (key === undefined) {\n throw GstpError.recipientMissingEncryptionKey();\n }\n return key;\n });\n\n result = result.wrap().encryptSubjectToRecipients(recipientKeys);\n }\n\n return result;\n }\n\n /**\n * Parses a sealed event from an encrypted envelope.\n *\n * @param encryptedEnvelope - The encrypted envelope to parse\n * @param expectedId - Optional expected event ID for validation\n * @param now - Optional current time for continuation validation\n * @param recipientPrivateKey - The recipient's private keys for decryption\n * @param contentExtractor - Function to extract content from envelope\n * @returns The parsed sealed event\n */\n static tryFromEnvelope<T extends EnvelopeEncodableValue>(\n encryptedEnvelope: Envelope,\n expectedId: ARID | undefined,\n now: Date | undefined,\n recipientPrivateKey: PrivateKeys,\n contentExtractor?: (env: Envelope) => T,\n ): SealedEvent<T> {\n // Decrypt the envelope\n let signedEnvelope: Envelope;\n try {\n signedEnvelope = encryptedEnvelope.decryptToRecipient(recipientPrivateKey);\n } catch (e) {\n throw GstpError.envelope(e instanceof Error ? e : new Error(String(e)));\n }\n\n // Extract sender from the unwrapped envelope\n let sender: XIDDocument;\n try {\n const unwrapped = signedEnvelope.tryUnwrap();\n const senderEnvelope = unwrapped.objectForPredicate(SENDER);\n if (senderEnvelope === undefined) {\n throw new Error(\"Missing sender\");\n }\n sender = XIDDocument.fromEnvelope(senderEnvelope);\n } catch (e) {\n throw GstpError.xid(e instanceof Error ? e : new Error(String(e)));\n }\n\n // Get sender's verification key and verify signature (from inception key)\n const senderInceptionKey = sender.inceptionKey();\n const senderVerificationKey = senderInceptionKey?.publicKeys()?.signingPublicKey();\n if (senderVerificationKey === undefined) {\n throw GstpError.senderMissingVerificationKey();\n }\n\n let eventEnvelope: Envelope;\n try {\n // verify() both verifies the signature AND unwraps the envelope\n eventEnvelope = signedEnvelope.verify(senderVerificationKey);\n } catch (e) {\n throw GstpError.envelope(e instanceof Error ? e : new Error(String(e)));\n }\n\n // Get peer continuation (sender_continuation from the event)\n const peerContinuation = eventEnvelope.optionalObjectForPredicate(SENDER_CONTINUATION);\n if (peerContinuation !== undefined) {\n // Verify peer continuation is encrypted\n if (!peerContinuation.subject().isEncrypted()) {\n throw GstpError.peerContinuationNotEncrypted();\n }\n }\n\n // Get and decrypt our continuation (recipient_continuation)\n const encryptedContinuation = eventEnvelope.optionalObjectForPredicate(RECIPIENT_CONTINUATION);\n let state: Envelope | undefined;\n if (encryptedContinuation !== undefined) {\n const continuation = Continuation.tryFromEnvelope(\n encryptedContinuation,\n expectedId,\n now,\n recipientPrivateKey,\n );\n state = continuation.state();\n }\n\n // Parse the event\n let event: Event<T>;\n try {\n // Use the content extractor if provided, otherwise use default string extraction\n if (contentExtractor !== undefined) {\n event = Event.fromEnvelope(eventEnvelope, contentExtractor);\n } else {\n // Default to string extraction\n event = Event.stringFromEnvelope(eventEnvelope) as unknown as Event<T>;\n }\n } catch (e) {\n throw GstpError.envelope(e instanceof Error ? e : new Error(String(e)));\n }\n\n return new SealedEvent(event, sender, state, peerContinuation);\n }\n\n // ============================================================================\n // Display methods\n // ============================================================================\n\n /**\n * Returns a string representation of the sealed event.\n */\n toString(): string {\n const stateStr = this._state !== undefined ? this._state.formatFlat() : \"None\";\n const peerStr = this._peerContinuation !== undefined ? \"Some\" : \"None\";\n return `SealedEvent(${this._event.summary()}, state: ${stateStr}, peer_continuation: ${peerStr})`;\n }\n\n /**\n * Checks equality with another sealed event.\n */\n equals(other: SealedEvent<T>): boolean {\n if (!this._event.equals(other._event)) {\n return false;\n }\n if (!this._sender.xid().equals(other._sender.xid())) {\n return false;\n }\n // Compare state\n if (this._state === undefined && other._state === undefined) {\n // Both undefined, equal\n } else if (this._state !== undefined && other._state !== undefined) {\n if (!this._state.digest().equals(other._state.digest())) {\n return false;\n }\n } else {\n return false;\n }\n // Compare peer continuation\n if (this._peerContinuation === undefined && other._peerContinuation === undefined) {\n // Both undefined, equal\n } else if (this._peerContinuation !== undefined && other._peerContinuation !== undefined) {\n if (!this._peerContinuation.digest().equals(other._peerContinuation.digest())) {\n return false;\n }\n } else {\n return false;\n }\n return true;\n }\n}\n","/**\n * GSTP Prelude - Convenient re-exports for common usage\n *\n * Import from this module for a curated set of commonly used types:\n *\n * ```typescript\n * import { SealedRequest, SealedResponse, Continuation } from '@bcts/gstp/prelude';\n * ```\n *\n * Ported from gstp-rust/src/prelude.rs\n */\n\n// Error types\nexport { GstpError, GstpErrorCode } from \"./error\";\n\n// Core types\nexport { Continuation } from \"./continuation\";\n\n// Sealed message types\nexport { SealedRequest, type SealedRequestBehavior } from \"./sealed-request\";\n\nexport { SealedResponse, type SealedResponseBehavior } from \"./sealed-response\";\n\nexport { SealedEvent, type SealedEventBehavior } from \"./sealed-event\";\n","/**\n * GSTP - Gordian Sealed Transaction Protocol\n *\n * A secure, authenticated, transport-agnostic data exchange protocol with\n * distributed state management via Encrypted State Continuations (ESC).\n *\n * This is a 1:1 port of the Rust gstp library, maintaining the same\n * API structure and functionality.\n *\n * @module gstp\n */\n\n// Error types\nexport { GstpError, GstpErrorCode } from \"./error\";\n\n// Core types\nexport { Continuation } from \"./continuation\";\n\n// Sealed message types\nexport { SealedRequest, type SealedRequestBehavior } from \"./sealed-request\";\n\nexport { SealedResponse, type SealedResponseBehavior } from \"./sealed-response\";\n\nexport { SealedEvent, type SealedEventBehavior } from \"./sealed-event\";\n\n// Prelude for convenient imports\nexport * as prelude from \"./prelude\";\n\n// Version information (matches gstp-rust v0.13.0)\nexport const VERSION = \"0.13.0\";\n"],"mappings":"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"}
|