{"version":3,"sources":["../../../src/crypto/envelope/job.ts"],"sourcesContent":["/**\n * ECIES envelopes for encrypted job requests and results.\n *\n * Request plaintext is UTF-8 JSON with object keys sorted recursively and\n * array order preserved. Result bodies use a hybrid streaming envelope:\n * ECIES wraps a random AES key, nonce prefix, and result metadata, while fixed\n * chunks of the body are sealed independently with AES-256-GCM. The Request\n * ciphertext is base64 of `iv || ephemPub || ct || mac`, as specified by the\n * ECIES provider interface. Result ciphertext is the raw hybrid byte sequence\n * stored in object storage. The Gateway hashes raw ciphertext bytes, not\n * plaintext.\n * The builder verifies the decrypted result's job ID, scope, and version\n * bindings. The PS worker verifies\n * `auth.bodyHash === sha256(canonicalJobRequestBytes(request))`; the Gateway\n * never sees the plaintext. Flow: personal-server-ts\n * `docs/260903-jobs-contract.md`, section 1.\n *\n * @category Cryptography\n */\n\nimport { sha256 } from \"@noble/hashes/sha2\";\nimport { bytesToHex, fromHex, isAddress, isHex, toHex, type Hex } from \"viem\";\nimport { CURVE, FORMAT, MAC } from \"../ecies/constants\";\nimport {\n  deserializeECIES,\n  ECIESError,\n  serializeECIES,\n  type ECIESEncrypted,\n  type ECIESProvider,\n} from \"../ecies/interface\";\nimport {\n  JOB_OPERATIONS,\n  JOB_PROTOCOL_VERSION,\n  type JobOperation,\n  type JobRequest,\n  type JobRequestEnvelope,\n  type JobResult,\n} from \"../../protocol/jobs\";\nimport { fromBase64, toBase64 } from \"../../utils/encoding\";\n\nconst textDecoder = new TextDecoder();\nconst textEncoder = new TextEncoder();\n/** Result metadata is only a few short fields; cap it before decoding attacker-reachable bytes. */\nconst MAX_JOB_RESULT_HEADER_BYTES = 4096;\nconst WRAPPED_KEY_LENGTH_BYTES = 4;\nconst FRAME_LENGTH_BYTES = 4;\nconst FRAME_FLAGS_BYTES = 1;\nconst AES_KEY_BYTES = 32;\nconst AES_GCM_NONCE_BYTES = 12;\nconst AES_GCM_TAG_BYTES = 16;\nconst WRAPPED_METADATA_LENGTH_BYTES = 4;\nconst WRAPPED_KEY_PLAINTEXT_PREFIX_BYTES =\n  AES_KEY_BYTES + AES_GCM_NONCE_BYTES + WRAPPED_METADATA_LENGTH_BYTES;\nconst MAX_WRAPPED_KEY_BYTES = 8192;\nconst FINAL_FRAME_FLAG = 1;\nconst MAX_CHUNK_INDEX = 0xffffffff;\n\n/** Current hybrid sealed-result wire-format version. */\nexport const JOB_RESULT_FORMAT_VERSION = 2;\n/** Plaintext bytes authenticated independently in each result frame. */\nexport const JOB_RESULT_CHUNK_BYTES = 1024 * 1024;\n\n/** Result fields authenticated for every encrypted body chunk. */\nexport type JobResultMetadata = Omit<JobResult, \"body\">;\n\n/** Streaming sealer output. Write the header before transformed body frames. */\nexport interface SealedJobResultStream {\n  header: Uint8Array;\n  transform: TransformStream<Uint8Array, Uint8Array>;\n}\n\n/** Verified metadata and incrementally decrypted result body. */\nexport interface OpenedJobResultStream {\n  metadata: JobResultMetadata;\n  body: ReadableStream<Uint8Array>;\n}\n\n/** Builder-visible bindings checked before any result body chunk is yielded. */\nexport interface JobResultExpectation {\n  jobId: string;\n  scope?: string;\n  version?: string | null;\n}\n\n/** A job envelope or result did not match the jobs protocol. */\nexport class JobEnvelopeError extends Error {\n  constructor(message: string) {\n    super(message);\n    this.name = \"JobEnvelopeError\";\n  }\n}\n\nfunction sortJsonKeys(value: unknown): unknown {\n  if (Array.isArray(value)) {\n    return value.map(sortJsonKeys);\n  }\n  if (value !== null && typeof value === \"object\") {\n    return Object.fromEntries(\n      Object.keys(value)\n        .sort()\n        .map((key) => [\n          key,\n          sortJsonKeys((value as Record<string, unknown>)[key]),\n        ]),\n    );\n  }\n  return value;\n}\n\nfunction canonicalJsonBytes(value: unknown): Uint8Array {\n  return textEncoder.encode(JSON.stringify(sortJsonKeys(value)));\n}\n\n/**\n * Returns the canonical UTF-8 JSON bytes committed to by the auth body hash.\n *\n * @param request - Job request to validate and serialize canonically.\n * @returns Recursively key-sorted, whitespace-free UTF-8 JSON bytes.\n * @throws {JobEnvelopeError} If the request does not match the protocol schema.\n */\nexport function canonicalJobRequestBytes(request: JobRequest): Uint8Array {\n  validateJobRequest(request);\n  return canonicalJsonBytes(request);\n}\n\nfunction requestPlaintext(envelope: JobRequestEnvelope): Uint8Array {\n  validateRequestEnvelope(envelope);\n  return canonicalJsonBytes(envelope);\n}\n\nfunction resultMetadata(result: JobResult): JobResultMetadata {\n  return {\n    v: result.v,\n    jobId: result.jobId,\n    scope: result.scope,\n    version: result.version,\n    contentType: result.contentType,\n  };\n}\n\nfunction encryptedBytesToBase64(\n  encrypted: Awaited<ReturnType<ECIESProvider[\"encrypt\"]>>,\n): string {\n  return toBase64(fromHex(`0x${serializeECIES(encrypted)}`, \"bytes\"));\n}\n\nfunction encryptedToBytes(\n  encrypted: Awaited<ReturnType<ECIESProvider[\"encrypt\"]>>,\n): Uint8Array {\n  const bytes = new Uint8Array(\n    encrypted.iv.length +\n      encrypted.ephemPublicKey.length +\n      encrypted.ciphertext.length +\n      encrypted.mac.length,\n  );\n  let offset = 0;\n  bytes.set(encrypted.iv, offset);\n  offset += encrypted.iv.length;\n  bytes.set(encrypted.ephemPublicKey, offset);\n  offset += encrypted.ephemPublicKey.length;\n  bytes.set(encrypted.ciphertext, offset);\n  offset += encrypted.ciphertext.length;\n  bytes.set(encrypted.mac, offset);\n  return bytes;\n}\n\nfunction bytesToEncrypted(bytes: Uint8Array): ECIESEncrypted {\n  const absoluteMinLength = FORMAT.IV_LENGTH + 1 + MAC.LENGTH + 1;\n  if (bytes.length < absoluteMinLength) {\n    throw new ECIESError(\n      `Invalid ECIES data: too short (${bytes.length} bytes, minimum ${absoluteMinLength} bytes required)`,\n      \"DECRYPTION_FAILED\",\n    );\n  }\n\n  const prefix = bytes[FORMAT.EPHEMERAL_KEY_OFFSET];\n  if (prefix !== CURVE.PREFIX.UNCOMPRESSED) {\n    throw new ECIESError(\n      `Invalid ephemeral public key: must be uncompressed format (0x04 prefix), got 0x${prefix.toString(16).padStart(2, \"0\")}`,\n      \"DECRYPTION_FAILED\",\n    );\n  }\n\n  const ephemKeySize = CURVE.UNCOMPRESSED_PUBLIC_KEY_LENGTH;\n  const minLength = FORMAT.IV_LENGTH + ephemKeySize + MAC.LENGTH + 1;\n  if (bytes.length < minLength) {\n    throw new ECIESError(\n      `Invalid ECIES data: too short (${bytes.length} bytes, minimum ${minLength} bytes required)`,\n      \"DECRYPTION_FAILED\",\n    );\n  }\n\n  return {\n    iv: bytes.subarray(FORMAT.IV_OFFSET, FORMAT.IV_OFFSET + FORMAT.IV_LENGTH),\n    ephemPublicKey: bytes.subarray(\n      FORMAT.EPHEMERAL_KEY_OFFSET,\n      FORMAT.EPHEMERAL_KEY_OFFSET + ephemKeySize,\n    ),\n    ciphertext: bytes.subarray(\n      FORMAT.EPHEMERAL_KEY_OFFSET + ephemKeySize,\n      bytes.length - MAC.LENGTH,\n    ),\n    mac: bytes.subarray(bytes.length - MAC.LENGTH),\n  };\n}\n\nfunction base64ToEncrypted(ciphertext: string) {\n  return deserializeECIES(toHex(fromBase64(ciphertext)));\n}\n\nfunction parseObject(\n  plaintext: Uint8Array,\n  kind: string,\n): Record<string, unknown> {\n  try {\n    const value: unknown = JSON.parse(textDecoder.decode(plaintext));\n    if (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n      throw new JobEnvelopeError(`Invalid ${kind}: expected an object`);\n    }\n    return value as Record<string, unknown>;\n  } catch (error) {\n    if (error instanceof JobEnvelopeError) throw error;\n    throw new JobEnvelopeError(`Invalid ${kind}: malformed JSON`);\n  }\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n  if (value === null || typeof value !== \"object\") return false;\n  const prototype = Object.getPrototypeOf(value);\n  return prototype === Object.prototype || prototype === null;\n}\n\nfunction requirePlainObject(\n  value: unknown,\n  field: string,\n  kind: string,\n): asserts value is Record<string, unknown> {\n  if (!isPlainObject(value)) {\n    throw new JobEnvelopeError(`Invalid ${kind}: invalid ${field}`);\n  }\n}\n\nfunction requireExactKeys(\n  value: Record<string, unknown>,\n  expectedKeys: readonly string[],\n  kind: string,\n): void {\n  for (const key of expectedKeys) {\n    if (!Object.hasOwn(value, key) || value[key] === undefined) {\n      throw new JobEnvelopeError(`Invalid ${kind}: missing ${key}`);\n    }\n  }\n  const expected = new Set<PropertyKey>(expectedKeys);\n  for (const key of Reflect.ownKeys(value)) {\n    if (!expected.has(key)) {\n      throw new JobEnvelopeError(\n        `Invalid ${kind}: unknown field ${String(key)}`,\n      );\n    }\n  }\n}\n\nfunction requireString(\n  value: unknown,\n  field: string,\n  kind: string,\n): asserts value is string {\n  if (typeof value !== \"string\" || value.length === 0) {\n    throw new JobEnvelopeError(`Invalid ${kind}: missing ${field}`);\n  }\n}\n\nfunction validateJobRequest(value: unknown): JobRequest {\n  requirePlainObject(value, \"request\", \"job request\");\n  requireExactKeys(\n    value,\n    [\n      \"v\",\n      \"jobId\",\n      \"owner\",\n      \"builder\",\n      \"builderPublicKey\",\n      \"grantId\",\n      \"scope\",\n      \"operation\",\n      \"pinnedVersion\",\n      \"deadline\",\n    ],\n    \"job request\",\n  );\n  if (value.v !== JOB_PROTOCOL_VERSION) {\n    throw new JobEnvelopeError(\n      `Unsupported job request version: ${String(value.v)}`,\n    );\n  }\n  requireString(value.jobId, \"jobId\", \"job request\");\n  if (typeof value.owner !== \"string\" || !isAddress(value.owner)) {\n    throw new JobEnvelopeError(\"Invalid job request: invalid owner\");\n  }\n  if (typeof value.builder !== \"string\" || !isAddress(value.builder)) {\n    throw new JobEnvelopeError(\"Invalid job request: invalid builder\");\n  }\n  if (\n    typeof value.builderPublicKey !== \"string\" ||\n    !isHex(value.builderPublicKey)\n  ) {\n    throw new JobEnvelopeError(\"Invalid job request: invalid builderPublicKey\");\n  }\n  if (typeof value.grantId !== \"string\" || !isHex(value.grantId)) {\n    throw new JobEnvelopeError(\"Invalid job request: invalid grantId\");\n  }\n  requireString(value.scope, \"scope\", \"job request\");\n  if (!JOB_OPERATIONS.includes(value.operation as JobOperation)) {\n    throw new JobEnvelopeError(\"Invalid job request: invalid operation\");\n  }\n  if (value.pinnedVersion !== null && typeof value.pinnedVersion !== \"string\") {\n    throw new JobEnvelopeError(\"Invalid job request: missing pinnedVersion\");\n  }\n  if (\n    typeof value.deadline !== \"string\" ||\n    !Number.isFinite(Date.parse(value.deadline))\n  ) {\n    throw new JobEnvelopeError(\"Invalid job request: invalid deadline\");\n  }\n  return value as unknown as JobRequest;\n}\n\nfunction validateRequestEnvelope(value: unknown): JobRequestEnvelope {\n  requirePlainObject(value, \"envelope\", \"job request envelope\");\n  requireExactKeys(value, [\"request\", \"auth\"], \"job request envelope\");\n  validateJobRequest(value.request);\n  requireString(value.auth, \"auth\", \"job request envelope\");\n  return value as unknown as JobRequestEnvelope;\n}\n\nfunction validateResultMetadata(value: unknown): JobResultMetadata {\n  requirePlainObject(value, \"metadata\", \"job result\");\n  requireExactKeys(\n    value,\n    [\"v\", \"jobId\", \"scope\", \"version\", \"contentType\"],\n    \"job result\",\n  );\n  if (value.v !== JOB_PROTOCOL_VERSION) {\n    throw new JobEnvelopeError(\n      `Unsupported job result version: ${String(value.v)}`,\n    );\n  }\n  for (const field of [\"jobId\", \"scope\", \"contentType\"]) {\n    requireString(value[field], field, \"job result\");\n  }\n  if (value.version !== null && typeof value.version !== \"string\") {\n    throw new JobEnvelopeError(\"Invalid job result: missing version\");\n  }\n  return value as unknown as JobResultMetadata;\n}\n\nfunction validateResult(value: unknown): JobResult {\n  requirePlainObject(value, \"result\", \"job result\");\n  requireExactKeys(\n    value,\n    [\"v\", \"jobId\", \"scope\", \"version\", \"contentType\", \"body\"],\n    \"job result\",\n  );\n  validateResultMetadata(resultMetadata(value as unknown as JobResult));\n  if (!(value.body instanceof Uint8Array)) {\n    throw new JobEnvelopeError(\"Invalid job result: missing body\");\n  }\n  return value as unknown as JobResult;\n}\n\nfunction webCrypto(): Crypto {\n  if (\n    typeof globalThis.crypto === \"undefined\" ||\n    typeof globalThis.crypto.getRandomValues !== \"function\" ||\n    !globalThis.crypto.subtle\n  ) {\n    throw new JobEnvelopeError(\n      \"Job result streaming requires the Web Crypto API\",\n    );\n  }\n  return globalThis.crypto;\n}\n\nfunction uint32(value: number): Uint8Array {\n  const bytes = new Uint8Array(4);\n  new DataView(bytes.buffer).setUint32(0, value);\n  return bytes;\n}\n\nfunction readUint32(bytes: Uint8Array, offset = 0): number {\n  return new DataView(bytes.buffer, bytes.byteOffset + offset, 4).getUint32(0);\n}\n\nfunction wrappedKeyPlaintext(\n  contentKey: Uint8Array,\n  noncePrefix: Uint8Array,\n  metadataBytes: Uint8Array,\n): Uint8Array {\n  const plaintext = new Uint8Array(\n    WRAPPED_KEY_PLAINTEXT_PREFIX_BYTES + metadataBytes.length,\n  );\n  plaintext.set(contentKey, 0);\n  plaintext.set(noncePrefix, AES_KEY_BYTES);\n  new DataView(plaintext.buffer).setUint32(\n    AES_KEY_BYTES + AES_GCM_NONCE_BYTES,\n    metadataBytes.length,\n  );\n  plaintext.set(metadataBytes, WRAPPED_KEY_PLAINTEXT_PREFIX_BYTES);\n  return plaintext;\n}\n\nfunction parseWrappedKeyPlaintext(plaintext: Uint8Array): {\n  contentKey: Uint8Array;\n  noncePrefix: Uint8Array;\n  metadataBytes: Uint8Array;\n  metadata: JobResultMetadata;\n} {\n  if (plaintext.length < WRAPPED_KEY_PLAINTEXT_PREFIX_BYTES) {\n    throw new JobEnvelopeError(\"Invalid job result: wrapped key is truncated\");\n  }\n  const metadataLength = readUint32(\n    plaintext,\n    AES_KEY_BYTES + AES_GCM_NONCE_BYTES,\n  );\n  if (metadataLength > MAX_JOB_RESULT_HEADER_BYTES) {\n    throw new JobEnvelopeError(\n      `Invalid job result: header exceeds ${MAX_JOB_RESULT_HEADER_BYTES} bytes`,\n    );\n  }\n  if (\n    plaintext.length !==\n    WRAPPED_KEY_PLAINTEXT_PREFIX_BYTES + metadataLength\n  ) {\n    throw new JobEnvelopeError(\n      \"Invalid job result: header length exceeds payload\",\n    );\n  }\n  const metadataBytes = plaintext.slice(WRAPPED_KEY_PLAINTEXT_PREFIX_BYTES);\n  const metadata = validateResultMetadata(\n    parseObject(metadataBytes, \"job result header\"),\n  );\n  return {\n    contentKey: plaintext.slice(0, AES_KEY_BYTES),\n    noncePrefix: plaintext.slice(\n      AES_KEY_BYTES,\n      AES_KEY_BYTES + AES_GCM_NONCE_BYTES,\n    ),\n    metadataBytes,\n    metadata,\n  };\n}\n\nasync function importAesKey(\n  contentKey: Uint8Array,\n  usage: KeyUsage,\n): Promise<CryptoKey> {\n  return webCrypto().subtle.importKey(\n    \"raw\",\n    contentKey as BufferSource,\n    { name: \"AES-GCM\" },\n    false,\n    [usage],\n  );\n}\n\nfunction chunkNonce(noncePrefix: Uint8Array, chunkIndex: number): Uint8Array {\n  if (chunkIndex > MAX_CHUNK_INDEX) {\n    throw new JobEnvelopeError(\"Invalid job result: too many chunks\");\n  }\n  const nonce = noncePrefix.slice();\n  const view = new DataView(nonce.buffer, nonce.byteOffset, nonce.byteLength);\n  view.setUint32(8, view.getUint32(8) ^ chunkIndex);\n  return nonce;\n}\n\nfunction chunkAad(\n  metadataBytes: Uint8Array,\n  chunkIndex: number,\n  final: boolean,\n  plaintextLength: number,\n): Uint8Array {\n  const aad = new Uint8Array(14 + metadataBytes.length);\n  aad[0] = JOB_RESULT_FORMAT_VERSION;\n  aad.set(uint32(metadataBytes.length), 1);\n  aad.set(metadataBytes, 5);\n  aad.set(uint32(chunkIndex), 5 + metadataBytes.length);\n  aad[9 + metadataBytes.length] = final ? FINAL_FRAME_FLAG : 0;\n  aad.set(uint32(plaintextLength), 10 + metadataBytes.length);\n  return aad;\n}\n\nasync function encryptResultChunk(\n  key: CryptoKey,\n  noncePrefix: Uint8Array,\n  metadataBytes: Uint8Array,\n  plaintext: Uint8Array,\n  chunkIndex: number,\n  final: boolean,\n): Promise<Uint8Array> {\n  const encrypted = new Uint8Array(\n    await webCrypto().subtle.encrypt(\n      {\n        name: \"AES-GCM\",\n        iv: chunkNonce(noncePrefix, chunkIndex) as BufferSource,\n        additionalData: chunkAad(\n          metadataBytes,\n          chunkIndex,\n          final,\n          plaintext.length,\n        ) as BufferSource,\n        tagLength: AES_GCM_TAG_BYTES * 8,\n      },\n      key,\n      plaintext as BufferSource,\n    ),\n  );\n  const frame = new Uint8Array(\n    FRAME_LENGTH_BYTES + FRAME_FLAGS_BYTES + encrypted.length,\n  );\n  new DataView(frame.buffer).setUint32(0, encrypted.length);\n  frame[FRAME_LENGTH_BYTES] = final ? FINAL_FRAME_FLAG : 0;\n  frame.set(encrypted, FRAME_LENGTH_BYTES + FRAME_FLAGS_BYTES);\n  return frame;\n}\n\nfunction verifyResultBindings(\n  metadata: JobResultMetadata,\n  expect: JobResultExpectation,\n): void {\n  if (metadata.jobId !== expect.jobId) {\n    throw new JobEnvelopeError(\n      `Job result ID ${metadata.jobId} does not match expected job ID ${expect.jobId}`,\n    );\n  }\n  if (expect.scope !== undefined && metadata.scope !== expect.scope) {\n    throw new JobEnvelopeError(\n      `Job result scope ${metadata.scope} does not match expected scope ${expect.scope}`,\n    );\n  }\n  if (expect.version !== undefined && metadata.version !== expect.version) {\n    throw new JobEnvelopeError(\n      `Job result version ${String(metadata.version)} does not match expected version ${String(expect.version)}`,\n    );\n  }\n}\n\nclass ByteStreamReader {\n  private readonly reader: ReadableStreamDefaultReader<Uint8Array>;\n  private current: Uint8Array | undefined;\n  private offset = 0;\n  private ended = false;\n\n  constructor(stream: ReadableStream<Uint8Array>) {\n    this.reader = stream.getReader();\n  }\n\n  private async ensureBytes(): Promise<boolean> {\n    while (!this.current || this.offset === this.current.length) {\n      if (this.ended) return false;\n      const next = await this.reader.read();\n      if (next.done) {\n        this.ended = true;\n        this.current = undefined;\n        return false;\n      }\n      if (!(next.value instanceof Uint8Array)) {\n        throw new JobEnvelopeError(\n          \"Invalid job result: stream yielded non-byte data\",\n        );\n      }\n      this.current = next.value;\n      this.offset = 0;\n    }\n    return true;\n  }\n\n  async readExactOrNull(length: number): Promise<Uint8Array | null> {\n    if (!(await this.ensureBytes())) return null;\n    const bytes = new Uint8Array(length);\n    let written = 0;\n    while (written < length) {\n      if (!(await this.ensureBytes())) {\n        throw new JobEnvelopeError(\"Invalid job result: truncated payload\");\n      }\n      const available = this.current!.length - this.offset;\n      const count = Math.min(available, length - written);\n      bytes.set(\n        this.current!.subarray(this.offset, this.offset + count),\n        written,\n      );\n      this.offset += count;\n      written += count;\n    }\n    return bytes;\n  }\n\n  async readExact(length: number): Promise<Uint8Array> {\n    const bytes = await this.readExactOrNull(length);\n    if (!bytes) {\n      throw new JobEnvelopeError(\"Invalid job result: truncated payload\");\n    }\n    return bytes;\n  }\n\n  async hasRemaining(): Promise<boolean> {\n    return this.ensureBytes();\n  }\n\n  async cancel(reason?: unknown): Promise<void> {\n    await this.reader.cancel(reason);\n  }\n}\n\nfunction normalizeChunkError(error: unknown): Error {\n  if (error instanceof JobEnvelopeError) return error;\n  return new JobEnvelopeError(\n    `Invalid job result: chunk authentication failed${error instanceof Error ? `: ${error.message}` : \"\"}`,\n  );\n}\n\n/**\n * Encrypts a validated job request envelope for a Personal Server enclave.\n *\n * The PS worker verifies\n * `auth.bodyHash === sha256(canonicalJobRequestBytes(request))`; the Gateway\n * never sees the plaintext.\n *\n * @param envelope - Request and builder Web3Signed authorization to encrypt.\n * @param enclavePublicKey - Public key returned by `GET /v1/identity?owner=`.\n * @param ecies - Injected ECIES implementation.\n * @returns Base64 ciphertext encoded as `iv || ephemPub || ct || mac`.\n * @throws {JobEnvelopeError} If the envelope or request is invalid.\n * @throws If ECIES encryption fails or the enclave public key is invalid.\n *\n * @example\n * ```ts\n * const identity = await fetch(`/v1/identity?owner=${owner}`).then((response) =>\n *   response.json(),\n * );\n * const requestCiphertext = await sealJobRequest(\n *   requestEnvelope,\n *   identity.publicKey,\n *   ecies,\n * );\n * await fetch(\"/v1/jobs\", {\n *   method: \"POST\",\n *   body: JSON.stringify({ ...submission, requestCiphertext }),\n * });\n * ```\n */\nexport async function sealJobRequest(\n  envelope: JobRequestEnvelope,\n  enclavePublicKey: Hex,\n  ecies: ECIESProvider,\n): Promise<string> {\n  const encrypted = await ecies.encrypt(\n    fromHex(enclavePublicKey, \"bytes\"),\n    requestPlaintext(envelope),\n  );\n  return encryptedBytesToBase64(encrypted);\n}\n\n/**\n * Decrypts and validates a job request envelope inside the enclave.\n *\n * @param ciphertext - Base64 `iv || ephemPub || ct || mac` ciphertext.\n * @param privateKey - Enclave key bytes, supplied as `Uint8Array` so the agent can zero them after use.\n * @param ecies - Injected ECIES implementation.\n * @returns The validated request envelope exactly as parsed from plaintext.\n * @throws {JobEnvelopeError} If plaintext is malformed or fails schema validation.\n * @throws If ciphertext decoding or ECIES decryption fails.\n */\nexport async function openJobRequest(\n  ciphertext: string,\n  privateKey: Uint8Array,\n  ecies: ECIESProvider,\n): Promise<JobRequestEnvelope> {\n  const plaintext = await ecies.decrypt(\n    privateKey,\n    base64ToEncrypted(ciphertext),\n  );\n  return validateRequestEnvelope(\n    parseObject(plaintext, \"job request envelope\"),\n  );\n}\n\n/** Create a bounded-memory hybrid sealer for a job result body. */\nexport async function sealJobResultStream(\n  metadataValue: JobResultMetadata,\n  builderPublicKey: Hex,\n  ecies: ECIESProvider,\n): Promise<SealedJobResultStream> {\n  const metadata = validateResultMetadata(metadataValue);\n  const metadataBytes = canonicalJsonBytes(metadata);\n  if (metadataBytes.length > MAX_JOB_RESULT_HEADER_BYTES) {\n    throw new JobEnvelopeError(\n      `Invalid job result: header exceeds ${MAX_JOB_RESULT_HEADER_BYTES} bytes`,\n    );\n  }\n\n  const crypto = webCrypto();\n  const contentKey = crypto.getRandomValues(new Uint8Array(AES_KEY_BYTES));\n  const noncePrefix = crypto.getRandomValues(\n    new Uint8Array(AES_GCM_NONCE_BYTES),\n  );\n  const key = await importAesKey(contentKey, \"encrypt\");\n  const keyPlaintext = wrappedKeyPlaintext(\n    contentKey,\n    noncePrefix,\n    metadataBytes,\n  );\n  const encryptedKey = await ecies.encrypt(\n    fromHex(builderPublicKey, \"bytes\"),\n    keyPlaintext,\n  );\n  contentKey.fill(0);\n  keyPlaintext.fill(0);\n  const wrappedKey = encryptedToBytes(encryptedKey);\n  if (wrappedKey.length > MAX_WRAPPED_KEY_BYTES) {\n    throw new JobEnvelopeError(\"Invalid job result: wrapped key is too large\");\n  }\n  const header = new Uint8Array(\n    1 + WRAPPED_KEY_LENGTH_BYTES + wrappedKey.length,\n  );\n  header[0] = JOB_RESULT_FORMAT_VERSION;\n  new DataView(header.buffer).setUint32(1, wrappedKey.length);\n  header.set(wrappedKey, 1 + WRAPPED_KEY_LENGTH_BYTES);\n\n  let pending = new Uint8Array(JOB_RESULT_CHUNK_BYTES);\n  let pendingLength = 0;\n  let chunkIndex = 0;\n  const transform = new TransformStream<Uint8Array, Uint8Array>({\n    async transform(chunk, controller) {\n      if (!(chunk instanceof Uint8Array)) {\n        throw new JobEnvelopeError(\n          \"Invalid job result: stream yielded non-byte data\",\n        );\n      }\n      let offset = 0;\n      while (offset < chunk.length) {\n        if (pendingLength === JOB_RESULT_CHUNK_BYTES) {\n          controller.enqueue(\n            await encryptResultChunk(\n              key,\n              noncePrefix,\n              metadataBytes,\n              pending,\n              chunkIndex,\n              false,\n            ),\n          );\n          chunkIndex += 1;\n          pending = new Uint8Array(JOB_RESULT_CHUNK_BYTES);\n          pendingLength = 0;\n        }\n        const count = Math.min(\n          chunk.length - offset,\n          JOB_RESULT_CHUNK_BYTES - pendingLength,\n        );\n        pending.set(chunk.subarray(offset, offset + count), pendingLength);\n        pendingLength += count;\n        offset += count;\n      }\n    },\n    async flush(controller) {\n      controller.enqueue(\n        await encryptResultChunk(\n          key,\n          noncePrefix,\n          metadataBytes,\n          pending.subarray(0, pendingLength),\n          chunkIndex,\n          true,\n        ),\n      );\n    },\n  });\n\n  return { header, transform };\n}\n\n/**\n * Encrypts a validated job result for its builder and describes the ciphertext.\n *\n * This compatibility wrapper drives {@link sealJobResultStream} and allocates\n * the final sealed byte array once. `hash` and `size` retain their Gateway\n * object-storage semantics.\n */\nexport async function sealJobResult(\n  result: JobResult,\n  builderPublicKey: Hex,\n  ecies: ECIESProvider,\n): Promise<{ bytes: Uint8Array; hash: Hex; size: number }> {\n  validateResult(result);\n  const sealed = await sealJobResultStream(\n    resultMetadata(result),\n    builderPublicKey,\n    ecies,\n  );\n  const frameCount = Math.max(\n    1,\n    Math.ceil(result.body.length / JOB_RESULT_CHUNK_BYTES),\n  );\n  const size =\n    sealed.header.length +\n    result.body.length +\n    frameCount * (FRAME_LENGTH_BYTES + FRAME_FLAGS_BYTES + AES_GCM_TAG_BYTES);\n  const bytes = new Uint8Array(size);\n  bytes.set(sealed.header, 0);\n  let outputOffset = sealed.header.length;\n  const reader = sealed.transform.readable.getReader();\n  const drain = (async () => {\n    for (;;) {\n      const next = await reader.read();\n      if (next.done) break;\n      bytes.set(next.value, outputOffset);\n      outputOffset += next.value.length;\n    }\n  })();\n  const writer = sealed.transform.writable.getWriter();\n  const fill = (async () => {\n    for (\n      let offset = 0;\n      offset < result.body.length;\n      offset += JOB_RESULT_CHUNK_BYTES\n    ) {\n      await writer.write(\n        result.body.subarray(offset, offset + JOB_RESULT_CHUNK_BYTES),\n      );\n    }\n    await writer.close();\n  })();\n  await Promise.all([drain, fill]);\n  if (outputOffset !== bytes.length) {\n    throw new JobEnvelopeError(\"Invalid job result: sealed size mismatch\");\n  }\n  return { bytes, hash: bytesToHex(sha256(bytes)), size };\n}\n\n/** Open and authenticate a hybrid job result without buffering its body. */\nexport async function openJobResultStream(\n  bytesStream: ReadableStream<Uint8Array>,\n  builderPrivateKey: Hex,\n  ecies: ECIESProvider,\n  expect: JobResultExpectation,\n): Promise<OpenedJobResultStream> {\n  const reader = new ByteStreamReader(bytesStream);\n  const headerPrefix = await reader.readExact(1 + WRAPPED_KEY_LENGTH_BYTES);\n  const formatVersion = headerPrefix[0];\n  if (formatVersion !== JOB_RESULT_FORMAT_VERSION) {\n    throw new JobEnvelopeError(\n      `Unsupported job result format: ${String(formatVersion)}`,\n    );\n  }\n  const wrappedKeyLength = readUint32(headerPrefix, 1);\n  if (wrappedKeyLength === 0 || wrappedKeyLength > MAX_WRAPPED_KEY_BYTES) {\n    throw new JobEnvelopeError(\n      \"Invalid job result: invalid wrapped key length\",\n    );\n  }\n  const wrappedKey = await reader.readExact(wrappedKeyLength);\n  const keyPlaintext = await ecies.decrypt(\n    fromHex(builderPrivateKey, \"bytes\"),\n    bytesToEncrypted(wrappedKey),\n  );\n  const parsed = parseWrappedKeyPlaintext(keyPlaintext);\n  verifyResultBindings(parsed.metadata, expect);\n  const key = await importAesKey(parsed.contentKey, \"decrypt\");\n  parsed.contentKey.fill(0);\n  keyPlaintext.fill(0);\n\n  let chunkIndex = 0;\n  let finished = false;\n  const body = new ReadableStream<Uint8Array>({\n    async pull(controller) {\n      if (finished) {\n        controller.close();\n        return;\n      }\n      try {\n        const frameHeader = await reader.readExactOrNull(\n          FRAME_LENGTH_BYTES + FRAME_FLAGS_BYTES,\n        );\n        if (!frameHeader) {\n          throw new JobEnvelopeError(\"Invalid job result: missing final chunk\");\n        }\n        const encryptedLength = readUint32(frameHeader);\n        if (\n          encryptedLength < AES_GCM_TAG_BYTES ||\n          encryptedLength > JOB_RESULT_CHUNK_BYTES + AES_GCM_TAG_BYTES\n        ) {\n          throw new JobEnvelopeError(\n            \"Invalid job result: invalid chunk length\",\n          );\n        }\n        const flags = frameHeader[FRAME_LENGTH_BYTES];\n        if (flags !== 0 && flags !== FINAL_FRAME_FLAG) {\n          throw new JobEnvelopeError(\"Invalid job result: invalid chunk flags\");\n        }\n        const final = flags === FINAL_FRAME_FLAG;\n        const plaintextLength = encryptedLength - AES_GCM_TAG_BYTES;\n        if (!final && plaintextLength !== JOB_RESULT_CHUNK_BYTES) {\n          throw new JobEnvelopeError(\n            \"Invalid job result: short non-final chunk\",\n          );\n        }\n        const encrypted = await reader.readExact(encryptedLength);\n        const plaintext = new Uint8Array(\n          await webCrypto().subtle.decrypt(\n            {\n              name: \"AES-GCM\",\n              iv: chunkNonce(parsed.noncePrefix, chunkIndex) as BufferSource,\n              additionalData: chunkAad(\n                parsed.metadataBytes,\n                chunkIndex,\n                final,\n                plaintextLength,\n              ) as BufferSource,\n              tagLength: AES_GCM_TAG_BYTES * 8,\n            },\n            key,\n            encrypted as BufferSource,\n          ),\n        );\n        if (plaintext.length !== plaintextLength) {\n          throw new JobEnvelopeError(\n            \"Invalid job result: decrypted chunk length mismatch\",\n          );\n        }\n        chunkIndex += 1;\n        if (final) {\n          if (await reader.hasRemaining()) {\n            throw new JobEnvelopeError(\n              \"Invalid job result: bytes follow final chunk\",\n            );\n          }\n          finished = true;\n        }\n        controller.enqueue(plaintext);\n        if (finished) controller.close();\n      } catch (error) {\n        controller.error(normalizeChunkError(error));\n        void reader.cancel(error).catch(() => undefined);\n      }\n    },\n    cancel(reason) {\n      return reader.cancel(reason);\n    },\n  });\n\n  return { metadata: parsed.metadata, body };\n}\n\nfunction bufferedResultBodySize(sealedBytes: Uint8Array): number {\n  if (sealedBytes.length < 1 + WRAPPED_KEY_LENGTH_BYTES) {\n    throw new JobEnvelopeError(\"Invalid job result: truncated payload\");\n  }\n  if (sealedBytes[0] !== JOB_RESULT_FORMAT_VERSION) {\n    throw new JobEnvelopeError(\n      `Unsupported job result format: ${String(sealedBytes[0])}`,\n    );\n  }\n  const wrappedKeyLength = readUint32(sealedBytes, 1);\n  if (wrappedKeyLength === 0 || wrappedKeyLength > MAX_WRAPPED_KEY_BYTES) {\n    throw new JobEnvelopeError(\n      \"Invalid job result: invalid wrapped key length\",\n    );\n  }\n  let offset = 1 + WRAPPED_KEY_LENGTH_BYTES + wrappedKeyLength;\n  if (offset > sealedBytes.length) {\n    throw new JobEnvelopeError(\"Invalid job result: truncated payload\");\n  }\n  let bodySize = 0;\n  let sawFinal = false;\n  while (offset < sealedBytes.length) {\n    if (sealedBytes.length - offset < FRAME_LENGTH_BYTES + FRAME_FLAGS_BYTES) {\n      throw new JobEnvelopeError(\"Invalid job result: truncated payload\");\n    }\n    const encryptedLength = readUint32(sealedBytes, offset);\n    const flags = sealedBytes[offset + FRAME_LENGTH_BYTES];\n    if (\n      encryptedLength < AES_GCM_TAG_BYTES ||\n      encryptedLength > JOB_RESULT_CHUNK_BYTES + AES_GCM_TAG_BYTES ||\n      (flags !== 0 && flags !== FINAL_FRAME_FLAG)\n    ) {\n      throw new JobEnvelopeError(\"Invalid job result: invalid chunk framing\");\n    }\n    const plaintextLength = encryptedLength - AES_GCM_TAG_BYTES;\n    if (flags === 0 && plaintextLength !== JOB_RESULT_CHUNK_BYTES) {\n      throw new JobEnvelopeError(\"Invalid job result: short non-final chunk\");\n    }\n    offset += FRAME_LENGTH_BYTES + FRAME_FLAGS_BYTES;\n    if (encryptedLength > sealedBytes.length - offset) {\n      throw new JobEnvelopeError(\"Invalid job result: truncated payload\");\n    }\n    offset += encryptedLength;\n    bodySize += plaintextLength;\n    if (flags === FINAL_FRAME_FLAG) {\n      sawFinal = true;\n      if (offset !== sealedBytes.length) {\n        throw new JobEnvelopeError(\n          \"Invalid job result: bytes follow final chunk\",\n        );\n      }\n    }\n  }\n  if (!sawFinal) {\n    throw new JobEnvelopeError(\"Invalid job result: missing final chunk\");\n  }\n  return bodySize;\n}\n\n/**\n * Decrypts a job result and verifies its builder-visible protocol bindings.\n *\n * The builder private key is a `Hex` wallet key. For `expect.version`,\n * `undefined` skips the check while `null` requires a null result version.\n *\n * @param sealedBytes - Raw hybrid sealed-result bytes.\n * @param builderPrivateKey - Builder's wallet private key as hex.\n * @param ecies - Injected ECIES implementation.\n * @param expect - Required job ID and optional scope and version bindings.\n * @returns The validated result when every supplied binding matches.\n * @throws {JobEnvelopeError} If plaintext is malformed, invalid, or a binding differs.\n * @throws If ciphertext decoding or ECIES decryption fails.\n *\n * @example\n * ```ts\n * const sealedBytes = new Uint8Array(await response.arrayBuffer());\n * const result = await openJobResult(sealedBytes, key, ecies, {\n *   jobId,\n *   scope,\n * });\n * const text = new TextDecoder().decode(result.body);\n * ```\n */\nexport async function openJobResult(\n  sealedBytes: Uint8Array,\n  builderPrivateKey: Hex,\n  ecies: ECIESProvider,\n  expect: JobResultExpectation,\n): Promise<JobResult> {\n  const bodySize = bufferedResultBodySize(sealedBytes);\n  const stream = new ReadableStream<Uint8Array>({\n    start(controller) {\n      controller.enqueue(sealedBytes);\n      controller.close();\n    },\n  });\n  const opened = await openJobResultStream(\n    stream,\n    builderPrivateKey,\n    ecies,\n    expect,\n  );\n  const body = new Uint8Array(bodySize);\n  let offset = 0;\n  await opened.body.pipeTo(\n    new WritableStream({\n      write(chunk) {\n        body.set(chunk, offset);\n        offset += chunk.length;\n      },\n    }),\n  );\n  if (offset !== body.length) {\n    throw new JobEnvelopeError(\"Invalid job result: opened size mismatch\");\n  }\n  return { ...opened.metadata, body };\n}\n"],"mappings":"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","names":[]}