@learncard/holder-continuity 0.2.0 → 0.2.2

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/BUNDLE_SPEC.md CHANGED
@@ -20,9 +20,9 @@ LearnCard's live wallet protects the key with 2-of-4 Shamir Secret Sharing (devi
20
20
 
21
21
  Consequences:
22
22
 
23
- - Anyone who obtains both the bundle and its password gains complete control of the wallet, bypassing SSS entirely.
24
- - The `keys/recovery-phrase.txt.enc` entry is derived from the current SSS recovery share. It is provided for reference and is **not** independently sufficient to recover the key on its own; recovery from a bundle uses the exported seed.
25
- - Treat the bundle like a password-vault backup: store it offline, use a strong unique password, and rotate the wallet if the bundle is exposed.
23
+ - Anyone who obtains both the bundle and its password gains complete control of the wallet, bypassing SSS entirely.
24
+ - The `keys/recovery-phrase.txt.enc` entry is derived from the current SSS recovery share. It is provided for reference and is **not** independently sufficient to recover the key on its own; recovery from a bundle uses the exported seed.
25
+ - Treat the bundle like a password-vault backup: store it offline, use a strong unique password, and rotate the wallet if the bundle is exposed.
26
26
 
27
27
  ## Paths
28
28
 
@@ -1 +1 @@
1
- {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,SAAS,UAAW,MAAM,GAAG,MAAM,KAAG,MACC,CAAC;AAErD,eAAO,MAAM,eAAe,UAAW,OAAO,KAAG,MAWhD,CAAC;AAEF,eAAO,MAAM,aAAa,cACX,MAAM,WACR;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,KACjD,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAShD,CAAC;AAEF,eAAO,MAAM,aAAa,WACd,MAAM,WACL;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,KACnD,OAAO,CAAC,MAAM,CAchB,CAAC"}
1
+ {"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,SAAS,UAAW,MAAM,GAAG,MAAM,KAAG,MACC,CAAC;AAErD,eAAO,MAAM,eAAe,UAAW,OAAO,KAAG,MAWhD,CAAC;AAEF,eAAO,MAAM,aAAa,cACX,MAAM,WACR;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,KACjD,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAUhD,CAAC;AAEF,eAAO,MAAM,aAAa,WACd,MAAM,WACL;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,KACnD,OAAO,CAAC,MAAM,CAehB,CAAC"}
@@ -66,7 +66,8 @@ var stableStringify = /* @__PURE__ */ __name((value) => {
66
66
  }, "stableStringify");
67
67
  var encodePayload = /* @__PURE__ */ __name(async (plaintext, options) => {
68
68
  if (!options.encrypt) return { stored: plaintext, encrypted: false };
69
- if (!options.password) throw new Error("A password is required for encrypted LearnCard exports");
69
+ if (!options.password)
70
+ throw new Error("A password is required for encrypted LearnCard exports");
70
71
  return {
71
72
  stored: JSON.stringify(await (0, import_sss_key_manager.encryptWithPassword)(plaintext, options.password), null, 2),
72
73
  encrypted: true
@@ -74,7 +75,8 @@ var encodePayload = /* @__PURE__ */ __name(async (plaintext, options) => {
74
75
  }, "encodePayload");
75
76
  var decodePayload = /* @__PURE__ */ __name(async (stored, options) => {
76
77
  if (!options.encrypted) return stored;
77
- if (!options.password) throw new Error("A password is required to decrypt this LearnCard export");
78
+ if (!options.password)
79
+ throw new Error("A password is required to decrypt this LearnCard export");
78
80
  const envelope = JSON.parse(stored);
79
81
  return (0, import_sss_key_manager.decryptWithPassword)(
80
82
  envelope.ciphertext,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts", "../src/exportBundle.ts", "../src/crypto.ts", "../src/manifest.ts", "../src/importBundle.ts", "../src/restoreBundle.ts"],
4
- "sourcesContent": ["export { createLearnCardBundle, exportLearnCardBundle } from './exportBundle';\nexport { importLearnCardBundle, readLearnCardBundle, readLearnCardBundleData } from './importBundle';\nexport { assertValidManifest, computePayloadSha256, finalizeManifest } from './manifest';\nexport {\n readLearnCardBundleSeed,\n readLearnCardBundleSeedData,\n restoreLearnCardFromBundle,\n restoreLearnCardFromBundleData,\n} from './restoreBundle';\nexport type {\n ExportLearnCardBundleOptions,\n ImportLearnCardBundleOptions,\n ImportLearnCardBundleReport,\n LearnCardBundleManifest,\n LearnCardBundleOptions,\n LearnCardBundleResult,\n LearnCardBundleWallet,\n ReadLearnCardBundleOptions,\n ReadLearnCardBundleResult,\n} from './types';\nexport type { RestoreLearnCardFromBundleOptions, RestoreLearnCardInit } from './restoreBundle';\n", "import { lookup } from 'node:dns/promises';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { isIP } from 'node:net';\nimport { dirname } from 'node:path';\n\nimport JSZip from 'jszip';\nimport { shareToRecoveryPhrase, splitPrivateKey } from '@learncard/sss-key-manager';\n\nimport type {\n BundleContentType,\n ExportLearnCardBundleOptions,\n JsonValue,\n LearnCardBundleEntryMetadata,\n LearnCardBundleOptions,\n LearnCardBundleResult,\n LearnCardBundleWallet,\n} from './types';\nimport { BUNDLE_README_MD, BUNDLE_SPEC_MD, finalizeManifest, SPEC_VERSION } from './manifest';\nimport { encodePayload, sha256Hex, stableStringify } from './crypto';\n\nconst ZIP_DATE = new Date('2024-01-01T00:00:00.000Z');\n\nconst DEFAULT_STATUS_LIST_FETCH_TIMEOUT_MS = 5000;\nconst DEFAULT_MAX_STATUS_LIST_BYTES = 5 * 1024 * 1024;\n\nconst stripIpv6Brackets = (hostname: string): string =>\n hostname.startsWith('[') && hostname.endsWith(']') ? hostname.slice(1, -1) : hostname;\n\nconst redactMalformedUrl = (value: string): string => {\n const queryIndex = value.indexOf('?');\n const ampIndex = value.indexOf('&');\n\n if (queryIndex === -1 && ampIndex === -1) return value;\n\n const redactionIndex =\n queryIndex === -1\n ? ampIndex\n : ampIndex === -1\n ? queryIndex\n : Math.min(queryIndex, ampIndex);\n\n return `${value.slice(0, redactionIndex)}?[redacted]`;\n};\n\nconst redactUrl = (value: string): string => {\n try {\n const url = new URL(value);\n const hostname = stripIpv6Brackets(url.hostname.toLowerCase());\n const shouldRedactHost =\n !hostname.includes('.') ||\n hostname === 'localhost' ||\n hostname.endsWith('.localhost') ||\n Boolean(isIP(hostname) && isPrivateAddress(hostname));\n const host = shouldRedactHost ? '[redacted-host]' : url.host;\n\n return `${url.protocol}//${host}${url.pathname}${url.search ? '?[redacted]' : ''}`;\n } catch {\n return redactMalformedUrl(value);\n }\n};\n\nconst urlEndDelimiters = new Set([' ', '\\n', '\\r', '\\t', \"'\", '\"', '<', '>']);\n\nconst findNextUrlStart = (value: string, fromIndex: number): number => {\n const httpIndex = value.indexOf('http://', fromIndex);\n const httpsIndex = value.indexOf('https://', fromIndex);\n\n if (httpIndex === -1) return httpsIndex;\n if (httpsIndex === -1) return httpIndex;\n\n return Math.min(httpIndex, httpsIndex);\n};\n\nconst findUrlEnd = (value: string, fromIndex: number): number => {\n let index = fromIndex;\n\n while (index < value.length && !urlEndDelimiters.has(value[index]!)) index += 1;\n\n return index;\n};\n\nconst redactText = (value: string): string => {\n let redacted = '';\n let index = 0;\n\n while (index < value.length) {\n const urlStart = findNextUrlStart(value, index);\n\n if (urlStart === -1) {\n redacted += value.slice(index);\n break;\n }\n\n const urlEnd = findUrlEnd(value, urlStart);\n\n redacted += value.slice(index, urlStart);\n redacted += redactUrl(value.slice(urlStart, urlEnd));\n index = urlEnd;\n }\n\n return redacted;\n};\n\nconst safeMessage = (error: unknown): string =>\n redactText(error instanceof Error ? error.message : String(error));\n\nconst isPrivateIPv4 = (address: string): boolean => {\n const parts = address.split('.').map(part => Number(part));\n\n if (parts.length !== 4 || parts.some(part => !Number.isInteger(part) || part < 0 || part > 255))\n return true;\n\n const [a, b] = parts;\n\n if (a === 0 || a === 10 || a === 127 || a >= 224) return true;\n if (a === 100 && b >= 64 && b <= 127) return true;\n if (a === 169 && b === 254) return true;\n if (a === 172 && b >= 16 && b <= 31) return true;\n if (a === 192 && b === 168) return true;\n if (a === 198 && (b === 18 || b === 19)) return true;\n\n return false;\n};\n\nconst isPrivateIPv6 = (address: string): boolean => {\n const normalized = address.toLowerCase();\n\n if (normalized === '::' || normalized === '::1') return true;\n if (normalized.startsWith('fc') || normalized.startsWith('fd')) return true;\n if (\n normalized.startsWith('fe8') ||\n normalized.startsWith('fe9') ||\n normalized.startsWith('fea') ||\n normalized.startsWith('feb')\n )\n return true;\n\n const ipv4Mapped = normalized.match(/::ffff:(\\d+\\.\\d+\\.\\d+\\.\\d+)$/);\n\n return ipv4Mapped ? isPrivateIPv4(ipv4Mapped[1]!) : false;\n};\n\nconst isPrivateAddress = (address: string): boolean => {\n const version = isIP(address);\n\n if (version === 4) return isPrivateIPv4(address);\n if (version === 6) return isPrivateIPv6(address);\n\n return true;\n};\n\nconst assertPublicHttpsUrl = async (uri: string): Promise<URL> => {\n const url = new URL(uri);\n const hostname = url.hostname.toLowerCase().replace(/^\\[|\\]$/g, '');\n\n if (url.protocol !== 'https:') throw new Error('status-list URL must use https');\n if (!hostname.includes('.') || hostname === 'localhost' || hostname.endsWith('.localhost')) {\n throw new Error('status-list URL host must be public');\n }\n\n if (isIP(hostname)) {\n if (isPrivateAddress(hostname)) throw new Error('status-list URL host must be public');\n\n return url;\n }\n\n const addresses = await lookup(hostname, { all: true, verbatim: true });\n\n if (addresses.length === 0 || addresses.some(address => isPrivateAddress(address.address))) {\n throw new Error('status-list URL host must resolve to public addresses');\n }\n\n return url;\n};\n\nconst readResponseText = async (response: Response, maxBytes: number): Promise<string> => {\n const contentLength = Number(response.headers.get('content-length'));\n\n if (Number.isFinite(contentLength) && contentLength > maxBytes) {\n throw new Error(`status-list response exceeds ${maxBytes} bytes`);\n }\n\n if (!response.body) {\n const text = await response.text();\n\n if (Buffer.byteLength(text, 'utf8') > maxBytes) {\n throw new Error(`status-list response exceeds ${maxBytes} bytes`);\n }\n\n return text;\n }\n\n const reader = response.body.getReader();\n const chunks: Buffer[] = [];\n let total = 0;\n\n while (true) {\n const { done, value } = await reader.read();\n\n if (done) break;\n\n total += value.byteLength;\n\n if (total > maxBytes) {\n await reader.cancel();\n\n throw new Error(`status-list response exceeds ${maxBytes} bytes`);\n }\n\n chunks.push(Buffer.from(value));\n }\n\n return Buffer.concat(chunks).toString('utf8');\n};\n\nconst fetchJsonWithTimeout = async (\n url: URL,\n timeoutMs: number,\n maxBytes: number\n): Promise<JsonValue> => {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n const response = await fetch(url, { signal: controller.signal });\n\n if (!response.ok) throw new Error(`HTTP ${response.status}`);\n\n return JSON.parse(await readResponseText(response, maxBytes)) as JsonValue;\n } finally {\n clearTimeout(timeout);\n }\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n Boolean(value) && typeof value === 'object' && !Array.isArray(value);\n\nconst stringArrayIncludes = (value: unknown, expected: string): boolean =>\n Array.isArray(value) && value.some(item => item === expected);\n\nconst json = (value: unknown): string => `${stableStringify(value)}\\n`;\n\nconst classifyPayload = (payload: JsonValue): BundleContentType => {\n if (!isRecord(payload)) return 'unknown-json';\n\n if (\n stringArrayIncludes(payload.type, 'VerifiablePresentation') ||\n payload.type === 'VerifiablePresentation'\n ) {\n return 'presentation';\n }\n\n if (\n stringArrayIncludes(payload.type, 'VerifiableCredential') ||\n payload.type === 'VerifiableCredential'\n ) {\n return 'credential';\n }\n\n return 'unknown-json';\n};\n\nconst pathForType = (type: BundleContentType, digest: string, encrypted: boolean): string => {\n const suffix = encrypted ? '.enc' : '';\n\n if (type === 'presentation') return `presentations/${digest}.json${suffix}`;\n\n if (type === 'consent-record') return `consent-records/${digest}.json${suffix}`;\n\n if (type === 'index-record') return `index-records/${digest}.json${suffix}`;\n if (type === 'status-cache') return `status-cache/${digest}.json${suffix}`;\n\n return `credentials/${digest}.json${suffix}`;\n};\n\nconst getCredentialId = (payload: JsonValue): string | undefined =>\n isRecord(payload) && typeof payload.id === 'string' ? payload.id : undefined;\n\nconst addZipText = (zip: JSZip, path: string, content: string): void => {\n zip.file(path, content, { date: ZIP_DATE });\n};\n\nconst collectDids = (wallet: LearnCardBundleWallet, warnings: string[]): Record<string, string> => {\n const dids: Record<string, string> = {};\n\n for (const method of [undefined, 'key', 'pkh:sol', 'tz', 'pkh:tz']) {\n try {\n dids[method ?? 'default'] = wallet.id.did(method);\n } catch (error) {\n warnings.push(\n `Could not derive DID method ${method ?? 'default'}: ${safeMessage(error)}`\n );\n }\n }\n\n return dids;\n};\n\nconst collectDidDocument = async (\n wallet: LearnCardBundleWallet,\n primaryDid: string,\n dids: Record<string, string>,\n warnings: string[]\n): Promise<JsonValue> => {\n if (!wallet.invoke.resolveDid) return { primaryDid, dids };\n\n try {\n return { primaryDid, dids, primaryDidDocument: await wallet.invoke.resolveDid(primaryDid) };\n } catch (error) {\n warnings.push(`Could not resolve primary DID document: ${safeMessage(error)}`);\n\n return { primaryDid, dids };\n }\n};\n\nconst collectKeyPayloads = async (\n wallet: LearnCardBundleWallet,\n warnings: string[]\n): Promise<\n Array<{ path: string; type: BundleContentType; content: string; encrypted: boolean }>\n> => {\n const payloads: Array<{\n path: string;\n type: BundleContentType;\n content: string;\n encrypted: boolean;\n }> = [];\n\n if (wallet.invoke.getKey) {\n try {\n const seed = wallet.invoke.getKey();\n const shares = await splitPrivateKey(seed);\n\n payloads.push({\n path: 'keys/private-key-seed.txt',\n type: 'key-private-seed',\n content: `${seed}\\n`,\n encrypted: true,\n });\n\n payloads.push({\n path: 'keys/recovery-phrase.txt',\n type: 'key-recovery-phrase',\n content: `${await shareToRecoveryPhrase(shares.recoveryShare)}\\n`,\n encrypted: true,\n });\n } catch (error) {\n warnings.push(`Could not export seed or recovery phrase: ${safeMessage(error)}`);\n }\n } else {\n warnings.push(\n 'Wallet does not expose invoke.getKey(); private seed and recovery phrase were not exported'\n );\n }\n\n if (wallet.id.keypair) {\n const jwks: Record<string, JsonValue> = {};\n\n for (const algorithm of ['ed25519', 'secp256k1'] as const) {\n try {\n jwks[algorithm] = wallet.id.keypair(algorithm);\n } catch (error) {\n warnings.push(`Could not export ${algorithm} JWK: ${safeMessage(error)}`);\n }\n }\n\n if (Object.keys(jwks).length > 0) {\n payloads.push({\n path: 'keys/jwks.json',\n type: 'key-jwks',\n content: json(jwks),\n encrypted: true,\n });\n }\n } else {\n warnings.push('Wallet does not expose id.keypair(); JWK key export was skipped');\n }\n\n return payloads;\n};\n\nconst extractStatusListUrls = (payload: JsonValue): string[] => {\n if (!isRecord(payload)) return [];\n\n const statuses = Array.isArray(payload.credentialStatus)\n ? payload.credentialStatus\n : payload.credentialStatus\n ? [payload.credentialStatus]\n : [];\n\n return statuses.flatMap(status =>\n isRecord(status) && typeof status.statusListCredential === 'string'\n ? [status.statusListCredential]\n : []\n );\n};\n\nconst collectStatusLists = async (\n payloads: JsonValue[],\n enabled: boolean,\n warnings: string[],\n timeoutMs = DEFAULT_STATUS_LIST_FETCH_TIMEOUT_MS,\n maxBytes = DEFAULT_MAX_STATUS_LIST_BYTES\n): Promise<Array<{ uri: string; content: JsonValue }>> => {\n if (!enabled) return [];\n\n const urls = [...new Set(payloads.flatMap(extractStatusListUrls))];\n const results: Array<{ uri: string; content: JsonValue }> = [];\n\n for (const uri of urls) {\n try {\n const url = await assertPublicHttpsUrl(uri);\n\n results.push({ uri, content: await fetchJsonWithTimeout(url, timeoutMs, maxBytes) });\n } catch (error) {\n warnings.push(\n `Could not cache status-list credential ${redactUrl(uri)}: ${safeMessage(error)}`\n );\n }\n }\n\n return results;\n};\n\nconst collectConsentRecords = async (\n wallet: LearnCardBundleWallet,\n warnings: string[]\n): Promise<JsonValue[]> => {\n if (wallet.invoke.getHolderExportMetadata) {\n try {\n const metadata = await wallet.invoke.getHolderExportMetadata();\n\n if (isRecord(metadata) && Array.isArray(metadata.warnings)) {\n warnings.push(\n ...metadata.warnings\n .filter(warning => typeof warning === 'string')\n .map(warning => redactText(warning))\n );\n }\n\n return isRecord(metadata) && Array.isArray(metadata.consentRecords)\n ? (metadata.consentRecords as JsonValue[])\n : [];\n } catch (error) {\n warnings.push(`Could not fetch holder export metadata: ${safeMessage(error)}`);\n }\n }\n\n if (!wallet.invoke.getConsentedContracts) return [];\n\n try {\n const response = await wallet.invoke.getConsentedContracts();\n\n if (!isRecord(response) || !Array.isArray(response.records)) return [];\n\n return response.records as JsonValue[];\n } catch (error) {\n warnings.push(`Could not fetch consented contracts fallback: ${safeMessage(error)}`);\n\n return [];\n }\n};\n\nexport const createLearnCardBundle = async (\n wallet: LearnCardBundleWallet,\n options: LearnCardBundleOptions = {}\n): Promise<LearnCardBundleResult> => {\n const encrypt = options.encrypt ?? true;\n\n if (encrypt && !options.password)\n throw new Error('A password is required for LearnCard export');\n\n const warnings: string[] = [];\n const zip = new JSZip();\n const contents: LearnCardBundleEntryMetadata[] = [];\n const primaryDid = wallet.id.did();\n const dids = collectDids(wallet, warnings);\n const didDocument = await collectDidDocument(wallet, primaryDid, dids, warnings);\n const credentialPayloads: JsonValue[] = [];\n\n const addStoredEntry = async (entry: {\n id: string;\n type: BundleContentType;\n path: string;\n content: string;\n encrypted: boolean;\n mediaType?: string;\n sourceUri?: string;\n credentialId?: string;\n indexRecordRef?: string;\n warnings?: string[];\n }): Promise<void> => {\n const encoded = await encodePayload(entry.content, {\n encrypt: entry.encrypted && encrypt,\n password: options.password,\n });\n const path =\n encoded.encrypted && !entry.path.endsWith('.enc') ? `${entry.path}.enc` : entry.path;\n\n addZipText(zip, path, encoded.stored);\n\n contents.push({\n id: entry.id,\n type: entry.type,\n path,\n mediaType: entry.mediaType ?? 'application/json',\n sha256: sha256Hex(encoded.stored),\n encrypted: encoded.encrypted,\n sourceUri: entry.sourceUri,\n credentialId: entry.credentialId,\n indexRecordRef: entry.indexRecordRef,\n warnings: entry.warnings,\n });\n };\n\n addZipText(zip, 'README.md', BUNDLE_README_MD);\n addZipText(zip, 'BUNDLE_SPEC.md', BUNDLE_SPEC_MD);\n\n await addStoredEntry({\n id: 'did-document',\n type: 'did-document',\n path: 'keys/did-document.json',\n content: json(didDocument),\n encrypted: false,\n });\n\n for (const payload of await collectKeyPayloads(wallet, warnings)) {\n await addStoredEntry({ ...payload, id: payload.path, mediaType: 'text/plain' });\n }\n\n const records = await wallet.index.LearnCloud.get();\n\n for (const [recordIndex, record] of records.entries()) {\n const entryWarnings: string[] = [];\n const digest = sha256Hex(\n stableStringify({ recordIndex, id: record.id ?? null, uri: record.uri ?? null })\n );\n\n try {\n const resolved = await wallet.read.get(record.uri);\n\n if (!resolved) {\n warnings.push(`Could not resolve wallet index URI ${redactUrl(record.uri)}`);\n continue;\n }\n\n credentialPayloads.push(resolved);\n const type = classifyPayload(resolved);\n const credentialId = getCredentialId(resolved);\n if (type === 'unknown-json') entryWarnings.push('Payload is not a recognized VC or VP');\n\n const indexRecordId = `urn:sha256:${digest}:index-record`;\n\n await addStoredEntry({\n id: indexRecordId,\n type: 'index-record',\n path: pathForType('index-record', digest, encrypt),\n content: json(record),\n encrypted: true,\n sourceUri: record.uri,\n credentialId,\n });\n\n await addStoredEntry({\n id: `urn:sha256:${digest}`,\n type,\n path: pathForType(type, digest, encrypt),\n content: json(resolved),\n encrypted: true,\n sourceUri: record.uri,\n credentialId,\n indexRecordRef: indexRecordId,\n warnings: entryWarnings.length > 0 ? entryWarnings : undefined,\n });\n } catch (error) {\n warnings.push(\n `Could not export wallet index URI ${redactUrl(record.uri)}: ${safeMessage(error)}`\n );\n }\n }\n\n const consentRecords = await collectConsentRecords(wallet, warnings);\n\n for (const consentRecord of consentRecords) {\n const digest = sha256Hex(stableStringify(consentRecord));\n\n await addStoredEntry({\n id: `urn:sha256:${digest}`,\n type: 'consent-record',\n path: pathForType('consent-record', digest, encrypt),\n content: json(consentRecord),\n encrypted: true,\n });\n }\n\n for (const statusList of await collectStatusLists(\n credentialPayloads,\n options.fetchStatusLists ?? true,\n warnings,\n options.statusListFetchTimeoutMs,\n options.maxStatusListBytes\n )) {\n const digest = sha256Hex(statusList.uri);\n\n await addStoredEntry({\n id: `urn:sha256:${digest}`,\n type: 'status-cache',\n path: pathForType('status-cache', digest, encrypt),\n content: json(statusList.content),\n encrypted: true,\n sourceUri: statusList.uri,\n });\n }\n\n const manifest = finalizeManifest({\n specVersion: SPEC_VERSION,\n createdAt: options.createdAt ?? new Date().toISOString(),\n primaryDid,\n walletName: 'LearnCard',\n encryption: encrypt\n ? {\n mode: 'argon2id-aes-256-gcm',\n encryptedPayloads: true,\n envelope: 'sss-key-manager-encryptWithPassword-v1',\n kdf: 'argon2id',\n cipher: 'AES-256-GCM',\n }\n : { mode: 'none', encryptedPayloads: false },\n contents,\n warnings,\n });\n\n addZipText(zip, 'manifest.json', `${JSON.stringify(manifest, null, 2)}\\n`);\n\n return {\n data: await zip.generateAsync({ type: 'nodebuffer', compression: 'DEFLATE' }),\n manifest,\n warnings,\n };\n};\n\nexport const exportLearnCardBundle = async (\n wallet: LearnCardBundleWallet,\n options: ExportLearnCardBundleOptions\n): Promise<LearnCardBundleResult> => {\n const bundle = await createLearnCardBundle(wallet, options);\n\n await mkdir(dirname(options.out), { recursive: true });\n await writeFile(options.out, bundle.data);\n\n return bundle;\n};\n", "import { createHash } from 'node:crypto';\n\nimport { decryptWithPassword, encryptWithPassword } from '@learncard/sss-key-manager';\n\nimport type { EncryptedPayloadEnvelope } from './types';\n\nexport const sha256Hex = (bytes: string | Buffer): string =>\n createHash('sha256').update(bytes).digest('hex');\n\nexport const stableStringify = (value: unknown): string => {\n if (value === null || typeof value !== 'object') return JSON.stringify(value);\n\n if (Array.isArray(value)) return `[${value.map(stableStringify).join(',')}]`;\n\n const object = value as Record<string, unknown>;\n\n return `{${Object.keys(object)\n .sort()\n .map(key => `${JSON.stringify(key)}:${stableStringify(object[key])}`)\n .join(',')}}`;\n};\n\nexport const encodePayload = async (\n plaintext: string,\n options: { encrypt: boolean; password?: string }\n): Promise<{ stored: string; encrypted: boolean }> => {\n if (!options.encrypt) return { stored: plaintext, encrypted: false };\n\n if (!options.password) throw new Error('A password is required for encrypted LearnCard exports');\n\n return {\n stored: JSON.stringify(await encryptWithPassword(plaintext, options.password), null, 2),\n encrypted: true,\n };\n};\n\nexport const decodePayload = async (\n stored: string,\n options: { encrypted: boolean; password?: string }\n): Promise<string> => {\n if (!options.encrypted) return stored;\n\n if (!options.password) throw new Error('A password is required to decrypt this LearnCard export');\n\n const envelope = JSON.parse(stored) as EncryptedPayloadEnvelope;\n\n return decryptWithPassword(\n envelope.ciphertext,\n envelope.iv,\n envelope.salt,\n options.password,\n envelope.kdfParams\n );\n};\n", "import type { LearnCardBundleEntryMetadata, LearnCardBundleManifest } from './types';\nimport { stableStringify, sha256Hex } from './crypto';\n\nexport const SPEC_VERSION = '1.0.0' as const;\n\nexport const BUNDLE_SPEC_MD = `# LearnCard Holder Continuity Bundle v1.0.0\n\nA LearnCard holder continuity bundle is a ZIP file with readable metadata and encrypted holder payloads.\n\n## Container\n\nRequired readable entries:\n\n- \\`manifest.json\\` \u2014 inventory, hashes, warnings, and encryption metadata.\n- \\`README.md\\` \u2014 human-readable recovery notes.\n- \\`BUNDLE_SPEC.md\\` \u2014 this format description.\n\nSensitive entries use JSON encryption envelopes produced by \\`@learncard/sss-key-manager\\` \\`encryptWithPassword\\`: Argon2id key derivation and AES-GCM authenticated encryption. The ZIP itself is not password encrypted.\n\n## Security model\n\nThis bundle exports the wallet's full raw private-key seed at \\`keys/private-key-seed.txt.enc\\`. LearnCard's live wallet protects the key with 2-of-4 Shamir Secret Sharing, where no single share can reconstruct it. The bundle does NOT preserve that threshold: the exported seed alone is sufficient to take full control of the identity, and the bundle password is the only barrier protecting it. \\`keys/recovery-phrase.txt.enc\\` is derived from the current recovery share for reference and is not independently sufficient to recover the key. Treat the bundle like a password-vault backup, use a strong unique password, and rotate the wallet if the bundle is exposed.\n\n## Paths\n\n- \\`keys/recovery-phrase.txt.enc\\`\n- \\`keys/private-key-seed.txt.enc\\`\n- \\`keys/jwks.json.enc\\`\n- \\`keys/did-document.json\\`\n- \\`credentials/<sha256>.json.enc\\`\n- \\`presentations/<sha256>.json.enc\\`\n- \\`index-records/<sha256>.json.enc\\`\n- \\`consent-records/<sha256>.json.enc\\`\n- \\`status-cache/<sha256>.json.enc\\`\n\nDebug exports MAY use plaintext payloads by setting \\`encrypt: false\\`; production exports MUST encrypt sensitive payloads.\n\nStatus-list snapshot fetching is HTTPS-only and rejects private, loopback, link-local, and single-label hosts. Exporters SHOULD keep the default timeout and response-size caps unless they are running in a trusted local environment.\n\n## Manifest hashing\n\nEach \\`contents[]\\` entry contains the SHA-256 hash of the bytes stored at \\`path\\`. \\`payloadSha256\\` is SHA-256 over a deterministic JSON serialization of \\`contents[]\\` with entries sorted by path.\n\nEach credential or presentation entry MAY reference an encrypted \\`index-record\\` companion entry via \\`indexRecordRef\\`; the readable manifest does not embed the original index record JSON.\n\n## Restore vs import\n\n\\`restoreLearnCardFromBundle(...)\\` decrypts \\`keys/private-key-seed.txt.enc\\` and passes that seed to \\`initLearnCard(...)\\`. It recreates the original wallet identity; it does not upload payloads or recreate index records.\n\n\\`importLearnCardBundle(...)\\` decrypts credential and presentation payloads, uploads them to the target wallet's LearnCloud store, and recreates index records from the encrypted \\`index-record\\` companions.\n\nImport writes bundle contents into the target wallet. A bundle author who knows the password can include arbitrary credentials, presentations, and index metadata. Use \\`verifyBeforeImport: true\\` to verify VC/VP signatures before upload when the target wallet exposes \\`invoke.verifyCredential\\` and \\`invoke.verifyPresentation\\`.\n\n## Size limits\n\nReaders enforce default compressed-bundle, per-entry, and JSON parse limits to avoid accidentally processing oversized ZIP or JSON payloads. Callers can override these with \\`maxBundleBytes\\`, \\`maxEntryBytes\\`, and \\`maxJsonBytes\\` for trusted local workflows.\n\n## Import expectations\n\nImporters MUST verify the stored bytes against each entry hash before trusting decrypted content. Importers SHOULD verify issuer signatures before upload and preserve issuer-signed credential and presentation payloads exactly.\n`;\n\nexport const BUNDLE_README_MD = `# LearnCard Holder Continuity Export\n\nThis archive contains a point-in-time holder export from a LearnCard wallet.\n\nKeep the password separately. Without it, encrypted credentials, key material, consent records, and status-list snapshots cannot be recovered.\n\nThis archive contains your full private-key seed (encrypted). Anyone with both this file and its password can take complete control of your wallet identity, so store it like a password-vault backup and rotate your wallet if it is exposed.\n\nThe readable manifest lists every payload and its SHA-256 hash. Third-party wallets can import individual W3C Verifiable Credentials or Verifiable Presentations from the decrypted JSON files even when they do not support the LearnCard ZIP bundle directly.\n`;\n\nexport const sortContents = (\n contents: LearnCardBundleEntryMetadata[]\n): LearnCardBundleEntryMetadata[] => [...contents].sort((a, b) => a.path.localeCompare(b.path));\n\nconst normalizeContents = (\n contents: LearnCardBundleEntryMetadata[]\n): LearnCardBundleEntryMetadata[] =>\n JSON.parse(JSON.stringify(sortContents(contents))) as LearnCardBundleEntryMetadata[];\n\nexport const computePayloadSha256 = (contents: LearnCardBundleEntryMetadata[]): string =>\n sha256Hex(stableStringify(normalizeContents(contents)));\n\nexport const finalizeManifest = (\n manifest: Omit<LearnCardBundleManifest, 'payloadSha256'>\n): LearnCardBundleManifest => ({\n ...manifest,\n contents: normalizeContents(manifest.contents),\n payloadSha256: computePayloadSha256(manifest.contents),\n});\n\nexport const assertValidManifest = (manifest: LearnCardBundleManifest): void => {\n if (manifest.specVersion !== SPEC_VERSION) {\n throw new Error(`Unsupported LearnCard bundle version: ${manifest.specVersion}`);\n }\n\n const expected = computePayloadSha256(manifest.contents);\n\n if (manifest.payloadSha256 !== expected)\n throw new Error('LearnCard bundle manifest hash mismatch');\n};\n", "import { readFile } from 'node:fs/promises';\n\nimport JSZip from 'jszip';\n\nimport type {\n ImportLearnCardBundleOptions,\n ImportLearnCardBundleReport,\n JsonValue,\n LearnCardBundleEntryMetadata,\n LearnCardBundleManifest,\n ReadLearnCardBundleOptions,\n ReadLearnCardBundleResult,\n} from './types';\nimport { assertValidManifest } from './manifest';\nimport { decodePayload, sha256Hex } from './crypto';\n\nconst DEFAULT_MAX_BUNDLE_BYTES = 100 * 1024 * 1024;\nconst DEFAULT_MAX_ENTRY_BYTES = 25 * 1024 * 1024;\nconst DEFAULT_MAX_JSON_BYTES = 25 * 1024 * 1024;\n\nconst byteLength = (content: string): number => Buffer.byteLength(content, 'utf8');\n\nconst assertSize = (label: string, size: number, max: number): void => {\n if (size > max) throw new Error(`${label} exceeds ${max} bytes`);\n};\n\nconst parseJson = (content: string, label: string, maxBytes: number): JsonValue => {\n assertSize(label, byteLength(content), maxBytes);\n\n return JSON.parse(content) as JsonValue;\n};\n\nconst safeMessage = (error: unknown): string =>\n error instanceof Error ? error.message : String(error);\n\nconst parseObject = (content: string, label: string, maxBytes: number): Record<string, unknown> => {\n const value = parseJson(content, label, maxBytes);\n\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error('Expected bundle metadata entry to contain a JSON object');\n }\n\n return value as Record<string, unknown>;\n};\n\nconst isImportableCredentialEntry = (entry: LearnCardBundleEntryMetadata): boolean =>\n entry.type === 'credential' || entry.type === 'presentation';\n\nconst isFailedVerification = (result: unknown): boolean => {\n if (Array.isArray(result)) {\n return result.some(item => {\n if (!item || typeof item !== 'object') return true;\n\n const status = 'status' in item ? item.status : undefined;\n\n return status === 'Failed' || status === 'Error';\n });\n }\n\n if (!result || typeof result !== 'object') return true;\n\n const errors = 'errors' in result ? result.errors : undefined;\n\n return !Array.isArray(errors) || errors.length > 0;\n};\n\nconst verifyImportableEntry = async (\n entry: LearnCardBundleEntryMetadata,\n content: JsonValue,\n options: ImportLearnCardBundleOptions\n): Promise<void> => {\n if (!options.verifyBeforeImport) return;\n\n if (entry.type === 'credential') {\n if (!options.wallet.invoke.verifyCredential) {\n throw new Error('Target wallet does not expose invoke.verifyCredential');\n }\n\n const verification = await options.wallet.invoke.verifyCredential(content);\n\n if (isFailedVerification(verification)) throw new Error('Credential verification failed');\n\n return;\n }\n\n if (!options.wallet.invoke.verifyPresentation) {\n throw new Error('Target wallet does not expose invoke.verifyPresentation');\n }\n\n const verification = await options.wallet.invoke.verifyPresentation(content);\n\n if (isFailedVerification(verification)) throw new Error('Presentation verification failed');\n};\n\nexport const readLearnCardBundleData = async (\n data: Buffer,\n options: ReadLearnCardBundleOptions = {}\n): Promise<ReadLearnCardBundleResult> => {\n const maxBundleBytes = options.maxBundleBytes ?? DEFAULT_MAX_BUNDLE_BYTES;\n const maxEntryBytes = options.maxEntryBytes ?? DEFAULT_MAX_ENTRY_BYTES;\n const maxJsonBytes = options.maxJsonBytes ?? DEFAULT_MAX_JSON_BYTES;\n\n assertSize('LearnCard bundle', data.byteLength, maxBundleBytes);\n\n const zip = await JSZip.loadAsync(data);\n const manifestFile = zip.file('manifest.json');\n\n if (!manifestFile) throw new Error('LearnCard bundle is missing manifest.json');\n\n const manifestContent = await manifestFile.async('string');\n\n assertSize('manifest.json', byteLength(manifestContent), maxJsonBytes);\n\n const manifest = JSON.parse(manifestContent) as LearnCardBundleManifest;\n\n assertValidManifest(manifest);\n\n const warnings = [...manifest.warnings];\n const entries: ReadLearnCardBundleResult['entries'] = [];\n const shouldDecrypt = options.decrypt ?? true;\n let totalEntryBytes = 0;\n\n for (const entry of manifest.contents) {\n const file = zip.file(entry.path);\n\n if (!file) throw new Error(`LearnCard bundle is missing ${entry.path}`);\n\n const stored = await file.async('string');\n const storedBytes = byteLength(stored);\n\n assertSize(entry.path, storedBytes, maxEntryBytes);\n\n totalEntryBytes += storedBytes;\n assertSize('LearnCard bundle entries', totalEntryBytes, maxBundleBytes);\n\n const actualSha = sha256Hex(stored);\n\n if (actualSha !== entry.sha256) {\n throw new Error(`SHA-256 mismatch for ${entry.path}`);\n }\n\n const content = shouldDecrypt\n ? await decodePayload(stored, {\n encrypted: entry.encrypted,\n password: options.password,\n })\n : stored;\n\n assertSize(`${entry.path} content`, byteLength(content), maxEntryBytes);\n\n entries.push({ ...entry, content });\n }\n\n return { manifest, entries, warnings };\n};\n\nexport const readLearnCardBundle = async (\n path: string,\n options: ReadLearnCardBundleOptions = {}\n): Promise<ReadLearnCardBundleResult> => readLearnCardBundleData(await readFile(path), options);\n\nexport const importLearnCardBundle = async (\n path: string,\n options: ImportLearnCardBundleOptions\n): Promise<ImportLearnCardBundleReport> => {\n const bundle = await readLearnCardBundle(path, options);\n const maxJsonBytes = options.maxJsonBytes ?? DEFAULT_MAX_JSON_BYTES;\n const report: ImportLearnCardBundleReport = {\n importedCredentials: 0,\n importedPresentations: 0,\n skipped: 0,\n skippedByType: {},\n errors: [],\n warnings: [...bundle.warnings],\n };\n\n if (!options.verifyBeforeImport) {\n report.warnings.push(\n 'Bundle credential signatures were not verified before import; only import bundles from sources you trust.'\n );\n }\n\n const entriesById = new Map(bundle.entries.map(entry => [entry.id, entry]));\n\n for (const entry of bundle.entries) {\n if (!isImportableCredentialEntry(entry)) {\n report.skipped += 1;\n report.skippedByType[entry.type] = (report.skippedByType[entry.type] ?? 0) + 1;\n continue;\n }\n\n try {\n const content = parseJson(entry.content, entry.path, maxJsonBytes);\n\n await verifyImportableEntry(entry, content, options);\n\n const upload =\n options.wallet.store.LearnCloud.uploadEncrypted ??\n options.wallet.store.LearnCloud.upload;\n\n if (!upload)\n throw new Error('Target wallet does not expose a LearnCloud upload method');\n\n const uri = await upload(content);\n const referencedIndexRecord = entry.indexRecordRef\n ? entriesById.get(entry.indexRecordRef)\n : undefined;\n\n if (entry.indexRecordRef && !referencedIndexRecord) {\n throw new Error(`Referenced index record ${entry.indexRecordRef} is missing`);\n }\n\n const indexRecord = referencedIndexRecord\n ? parseObject(\n referencedIndexRecord.content,\n referencedIndexRecord.path,\n maxJsonBytes\n )\n : { id: entry.id, uri };\n const recordId = typeof indexRecord.id === 'string' ? indexRecord.id : entry.id;\n\n await options.wallet.index.LearnCloud.add({\n ...indexRecord,\n id: recordId,\n uri,\n sourceExport: {\n manifestCreatedAt: bundle.manifest.createdAt,\n sourceUri: entry.sourceUri,\n sourcePath: entry.path,\n credentialId: entry.credentialId,\n },\n });\n\n if (entry.type === 'presentation') report.importedPresentations += 1;\n else report.importedCredentials += 1;\n } catch (error) {\n report.errors.push({ path: entry.path, message: safeMessage(error) });\n }\n }\n\n return report;\n};\n", "import { initLearnCard } from '@learncard/init';\nimport type { InitLearnCard } from '@learncard/init';\n\nimport { readLearnCardBundle, readLearnCardBundleData } from './importBundle';\nimport type { ReadLearnCardBundleOptions, ReadLearnCardBundleResult } from './types';\n\ntype SeededInitConfig = Extract<InitLearnCard['args'], { seed: string }>;\ntype DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;\n\nexport type RestoreLearnCardInit = DistributiveOmit<SeededInitConfig, 'seed'>;\n\nexport type RestoreLearnCardFromBundleOptions = ReadLearnCardBundleOptions & {\n init: RestoreLearnCardInit;\n};\n\nconst getSeedEntry = (bundle: ReadLearnCardBundleResult): string => {\n const seedEntry = bundle.entries.find(entry => entry.type === 'key-private-seed');\n\n if (!seedEntry) {\n throw new Error(\n 'LearnCard bundle does not contain key-private-seed and cannot be restored'\n );\n }\n\n const seed = seedEntry.content.trim();\n\n if (!/^[0-9a-f]{64}$/i.test(seed)) {\n throw new Error(\n 'LearnCard bundle key-private-seed must be exactly 64 hexadecimal characters'\n );\n }\n\n return seed;\n};\n\nexport const readLearnCardBundleSeedData = async (\n data: Buffer,\n options: ReadLearnCardBundleOptions = {}\n): Promise<string> => getSeedEntry(await readLearnCardBundleData(data, options));\n\nexport const readLearnCardBundleSeed = async (\n path: string,\n options: ReadLearnCardBundleOptions = {}\n): Promise<string> => getSeedEntry(await readLearnCardBundle(path, options));\n\nexport const restoreLearnCardFromBundleData = async (\n data: Buffer,\n options: RestoreLearnCardFromBundleOptions\n): Promise<InitLearnCard['returnValue']> => {\n const seed = await readLearnCardBundleSeedData(data, options);\n\n return initLearnCard({ ...options.init, seed } as SeededInitConfig);\n};\n\nexport const restoreLearnCardFromBundle = async (\n path: string,\n options: RestoreLearnCardFromBundleOptions\n): Promise<InitLearnCard['returnValue']> => {\n const seed = await readLearnCardBundleSeed(path, options);\n\n return initLearnCard({ ...options.init, seed } as SeededInitConfig);\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["export { createLearnCardBundle, exportLearnCardBundle } from './exportBundle';\nexport {\n importLearnCardBundle,\n readLearnCardBundle,\n readLearnCardBundleData,\n} from './importBundle';\nexport { assertValidManifest, computePayloadSha256, finalizeManifest } from './manifest';\nexport {\n readLearnCardBundleSeed,\n readLearnCardBundleSeedData,\n restoreLearnCardFromBundle,\n restoreLearnCardFromBundleData,\n} from './restoreBundle';\nexport type {\n ExportLearnCardBundleOptions,\n ImportLearnCardBundleOptions,\n ImportLearnCardBundleReport,\n LearnCardBundleManifest,\n LearnCardBundleOptions,\n LearnCardBundleResult,\n LearnCardBundleWallet,\n ReadLearnCardBundleOptions,\n ReadLearnCardBundleResult,\n} from './types';\nexport type { RestoreLearnCardFromBundleOptions, RestoreLearnCardInit } from './restoreBundle';\n", "import { lookup } from 'node:dns/promises';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { isIP } from 'node:net';\nimport { dirname } from 'node:path';\n\nimport JSZip from 'jszip';\nimport { shareToRecoveryPhrase, splitPrivateKey } from '@learncard/sss-key-manager';\n\nimport type {\n BundleContentType,\n ExportLearnCardBundleOptions,\n JsonValue,\n LearnCardBundleEntryMetadata,\n LearnCardBundleOptions,\n LearnCardBundleResult,\n LearnCardBundleWallet,\n} from './types';\nimport { BUNDLE_README_MD, BUNDLE_SPEC_MD, finalizeManifest, SPEC_VERSION } from './manifest';\nimport { encodePayload, sha256Hex, stableStringify } from './crypto';\n\nconst ZIP_DATE = new Date('2024-01-01T00:00:00.000Z');\n\nconst DEFAULT_STATUS_LIST_FETCH_TIMEOUT_MS = 5000;\nconst DEFAULT_MAX_STATUS_LIST_BYTES = 5 * 1024 * 1024;\n\nconst stripIpv6Brackets = (hostname: string): string =>\n hostname.startsWith('[') && hostname.endsWith(']') ? hostname.slice(1, -1) : hostname;\n\nconst redactMalformedUrl = (value: string): string => {\n const queryIndex = value.indexOf('?');\n const ampIndex = value.indexOf('&');\n\n if (queryIndex === -1 && ampIndex === -1) return value;\n\n const redactionIndex =\n queryIndex === -1\n ? ampIndex\n : ampIndex === -1\n ? queryIndex\n : Math.min(queryIndex, ampIndex);\n\n return `${value.slice(0, redactionIndex)}?[redacted]`;\n};\n\nconst redactUrl = (value: string): string => {\n try {\n const url = new URL(value);\n const hostname = stripIpv6Brackets(url.hostname.toLowerCase());\n const shouldRedactHost =\n !hostname.includes('.') ||\n hostname === 'localhost' ||\n hostname.endsWith('.localhost') ||\n Boolean(isIP(hostname) && isPrivateAddress(hostname));\n const host = shouldRedactHost ? '[redacted-host]' : url.host;\n\n return `${url.protocol}//${host}${url.pathname}${url.search ? '?[redacted]' : ''}`;\n } catch {\n return redactMalformedUrl(value);\n }\n};\n\nconst urlEndDelimiters = new Set([' ', '\\n', '\\r', '\\t', \"'\", '\"', '<', '>']);\n\nconst findNextUrlStart = (value: string, fromIndex: number): number => {\n const httpIndex = value.indexOf('http://', fromIndex);\n const httpsIndex = value.indexOf('https://', fromIndex);\n\n if (httpIndex === -1) return httpsIndex;\n if (httpsIndex === -1) return httpIndex;\n\n return Math.min(httpIndex, httpsIndex);\n};\n\nconst findUrlEnd = (value: string, fromIndex: number): number => {\n let index = fromIndex;\n\n while (index < value.length && !urlEndDelimiters.has(value[index]!)) index += 1;\n\n return index;\n};\n\nconst redactText = (value: string): string => {\n let redacted = '';\n let index = 0;\n\n while (index < value.length) {\n const urlStart = findNextUrlStart(value, index);\n\n if (urlStart === -1) {\n redacted += value.slice(index);\n break;\n }\n\n const urlEnd = findUrlEnd(value, urlStart);\n\n redacted += value.slice(index, urlStart);\n redacted += redactUrl(value.slice(urlStart, urlEnd));\n index = urlEnd;\n }\n\n return redacted;\n};\n\nconst safeMessage = (error: unknown): string =>\n redactText(error instanceof Error ? error.message : String(error));\n\nconst isPrivateIPv4 = (address: string): boolean => {\n const parts = address.split('.').map(part => Number(part));\n\n if (parts.length !== 4 || parts.some(part => !Number.isInteger(part) || part < 0 || part > 255))\n return true;\n\n const [a, b] = parts;\n\n if (a === 0 || a === 10 || a === 127 || a >= 224) return true;\n if (a === 100 && b >= 64 && b <= 127) return true;\n if (a === 169 && b === 254) return true;\n if (a === 172 && b >= 16 && b <= 31) return true;\n if (a === 192 && b === 168) return true;\n if (a === 198 && (b === 18 || b === 19)) return true;\n\n return false;\n};\n\nconst isPrivateIPv6 = (address: string): boolean => {\n const normalized = address.toLowerCase();\n\n if (normalized === '::' || normalized === '::1') return true;\n if (normalized.startsWith('fc') || normalized.startsWith('fd')) return true;\n if (\n normalized.startsWith('fe8') ||\n normalized.startsWith('fe9') ||\n normalized.startsWith('fea') ||\n normalized.startsWith('feb')\n )\n return true;\n\n const ipv4Mapped = normalized.match(/::ffff:(\\d+\\.\\d+\\.\\d+\\.\\d+)$/);\n\n return ipv4Mapped ? isPrivateIPv4(ipv4Mapped[1]!) : false;\n};\n\nconst isPrivateAddress = (address: string): boolean => {\n const version = isIP(address);\n\n if (version === 4) return isPrivateIPv4(address);\n if (version === 6) return isPrivateIPv6(address);\n\n return true;\n};\n\nconst assertPublicHttpsUrl = async (uri: string): Promise<URL> => {\n const url = new URL(uri);\n const hostname = url.hostname.toLowerCase().replace(/^\\[|\\]$/g, '');\n\n if (url.protocol !== 'https:') throw new Error('status-list URL must use https');\n if (!hostname.includes('.') || hostname === 'localhost' || hostname.endsWith('.localhost')) {\n throw new Error('status-list URL host must be public');\n }\n\n if (isIP(hostname)) {\n if (isPrivateAddress(hostname)) throw new Error('status-list URL host must be public');\n\n return url;\n }\n\n const addresses = await lookup(hostname, { all: true, verbatim: true });\n\n if (addresses.length === 0 || addresses.some(address => isPrivateAddress(address.address))) {\n throw new Error('status-list URL host must resolve to public addresses');\n }\n\n return url;\n};\n\nconst readResponseText = async (response: Response, maxBytes: number): Promise<string> => {\n const contentLength = Number(response.headers.get('content-length'));\n\n if (Number.isFinite(contentLength) && contentLength > maxBytes) {\n throw new Error(`status-list response exceeds ${maxBytes} bytes`);\n }\n\n if (!response.body) {\n const text = await response.text();\n\n if (Buffer.byteLength(text, 'utf8') > maxBytes) {\n throw new Error(`status-list response exceeds ${maxBytes} bytes`);\n }\n\n return text;\n }\n\n const reader = response.body.getReader();\n const chunks: Buffer[] = [];\n let total = 0;\n\n while (true) {\n const { done, value } = await reader.read();\n\n if (done) break;\n\n total += value.byteLength;\n\n if (total > maxBytes) {\n await reader.cancel();\n\n throw new Error(`status-list response exceeds ${maxBytes} bytes`);\n }\n\n chunks.push(Buffer.from(value));\n }\n\n return Buffer.concat(chunks).toString('utf8');\n};\n\nconst fetchJsonWithTimeout = async (\n url: URL,\n timeoutMs: number,\n maxBytes: number\n): Promise<JsonValue> => {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n const response = await fetch(url, { signal: controller.signal });\n\n if (!response.ok) throw new Error(`HTTP ${response.status}`);\n\n return JSON.parse(await readResponseText(response, maxBytes)) as JsonValue;\n } finally {\n clearTimeout(timeout);\n }\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n Boolean(value) && typeof value === 'object' && !Array.isArray(value);\n\nconst stringArrayIncludes = (value: unknown, expected: string): boolean =>\n Array.isArray(value) && value.some(item => item === expected);\n\nconst json = (value: unknown): string => `${stableStringify(value)}\\n`;\n\nconst classifyPayload = (payload: JsonValue): BundleContentType => {\n if (!isRecord(payload)) return 'unknown-json';\n\n if (\n stringArrayIncludes(payload.type, 'VerifiablePresentation') ||\n payload.type === 'VerifiablePresentation'\n ) {\n return 'presentation';\n }\n\n if (\n stringArrayIncludes(payload.type, 'VerifiableCredential') ||\n payload.type === 'VerifiableCredential'\n ) {\n return 'credential';\n }\n\n return 'unknown-json';\n};\n\nconst pathForType = (type: BundleContentType, digest: string, encrypted: boolean): string => {\n const suffix = encrypted ? '.enc' : '';\n\n if (type === 'presentation') return `presentations/${digest}.json${suffix}`;\n\n if (type === 'consent-record') return `consent-records/${digest}.json${suffix}`;\n\n if (type === 'index-record') return `index-records/${digest}.json${suffix}`;\n if (type === 'status-cache') return `status-cache/${digest}.json${suffix}`;\n\n return `credentials/${digest}.json${suffix}`;\n};\n\nconst getCredentialId = (payload: JsonValue): string | undefined =>\n isRecord(payload) && typeof payload.id === 'string' ? payload.id : undefined;\n\nconst addZipText = (zip: JSZip, path: string, content: string): void => {\n zip.file(path, content, { date: ZIP_DATE });\n};\n\nconst collectDids = (wallet: LearnCardBundleWallet, warnings: string[]): Record<string, string> => {\n const dids: Record<string, string> = {};\n\n for (const method of [undefined, 'key', 'pkh:sol', 'tz', 'pkh:tz']) {\n try {\n dids[method ?? 'default'] = wallet.id.did(method);\n } catch (error) {\n warnings.push(\n `Could not derive DID method ${method ?? 'default'}: ${safeMessage(error)}`\n );\n }\n }\n\n return dids;\n};\n\nconst collectDidDocument = async (\n wallet: LearnCardBundleWallet,\n primaryDid: string,\n dids: Record<string, string>,\n warnings: string[]\n): Promise<JsonValue> => {\n if (!wallet.invoke.resolveDid) return { primaryDid, dids };\n\n try {\n return { primaryDid, dids, primaryDidDocument: await wallet.invoke.resolveDid(primaryDid) };\n } catch (error) {\n warnings.push(`Could not resolve primary DID document: ${safeMessage(error)}`);\n\n return { primaryDid, dids };\n }\n};\n\nconst collectKeyPayloads = async (\n wallet: LearnCardBundleWallet,\n warnings: string[]\n): Promise<\n Array<{ path: string; type: BundleContentType; content: string; encrypted: boolean }>\n> => {\n const payloads: Array<{\n path: string;\n type: BundleContentType;\n content: string;\n encrypted: boolean;\n }> = [];\n\n if (wallet.invoke.getKey) {\n try {\n const seed = wallet.invoke.getKey();\n const shares = await splitPrivateKey(seed);\n\n payloads.push({\n path: 'keys/private-key-seed.txt',\n type: 'key-private-seed',\n content: `${seed}\\n`,\n encrypted: true,\n });\n\n payloads.push({\n path: 'keys/recovery-phrase.txt',\n type: 'key-recovery-phrase',\n content: `${await shareToRecoveryPhrase(shares.recoveryShare)}\\n`,\n encrypted: true,\n });\n } catch (error) {\n warnings.push(`Could not export seed or recovery phrase: ${safeMessage(error)}`);\n }\n } else {\n warnings.push(\n 'Wallet does not expose invoke.getKey(); private seed and recovery phrase were not exported'\n );\n }\n\n if (wallet.id.keypair) {\n const jwks: Record<string, JsonValue> = {};\n\n for (const algorithm of ['ed25519', 'secp256k1'] as const) {\n try {\n jwks[algorithm] = wallet.id.keypair(algorithm);\n } catch (error) {\n warnings.push(`Could not export ${algorithm} JWK: ${safeMessage(error)}`);\n }\n }\n\n if (Object.keys(jwks).length > 0) {\n payloads.push({\n path: 'keys/jwks.json',\n type: 'key-jwks',\n content: json(jwks),\n encrypted: true,\n });\n }\n } else {\n warnings.push('Wallet does not expose id.keypair(); JWK key export was skipped');\n }\n\n return payloads;\n};\n\nconst extractStatusListUrls = (payload: JsonValue): string[] => {\n if (!isRecord(payload)) return [];\n\n const statuses = Array.isArray(payload.credentialStatus)\n ? payload.credentialStatus\n : payload.credentialStatus\n ? [payload.credentialStatus]\n : [];\n\n return statuses.flatMap(status =>\n isRecord(status) && typeof status.statusListCredential === 'string'\n ? [status.statusListCredential]\n : []\n );\n};\n\nconst collectStatusLists = async (\n payloads: JsonValue[],\n enabled: boolean,\n warnings: string[],\n timeoutMs = DEFAULT_STATUS_LIST_FETCH_TIMEOUT_MS,\n maxBytes = DEFAULT_MAX_STATUS_LIST_BYTES\n): Promise<Array<{ uri: string; content: JsonValue }>> => {\n if (!enabled) return [];\n\n const urls = [...new Set(payloads.flatMap(extractStatusListUrls))];\n const results: Array<{ uri: string; content: JsonValue }> = [];\n\n for (const uri of urls) {\n try {\n const url = await assertPublicHttpsUrl(uri);\n\n results.push({ uri, content: await fetchJsonWithTimeout(url, timeoutMs, maxBytes) });\n } catch (error) {\n warnings.push(\n `Could not cache status-list credential ${redactUrl(uri)}: ${safeMessage(error)}`\n );\n }\n }\n\n return results;\n};\n\nconst collectConsentRecords = async (\n wallet: LearnCardBundleWallet,\n warnings: string[]\n): Promise<JsonValue[]> => {\n if (wallet.invoke.getHolderExportMetadata) {\n try {\n const metadata = await wallet.invoke.getHolderExportMetadata();\n\n if (isRecord(metadata) && Array.isArray(metadata.warnings)) {\n warnings.push(\n ...metadata.warnings\n .filter(warning => typeof warning === 'string')\n .map(warning => redactText(warning))\n );\n }\n\n return isRecord(metadata) && Array.isArray(metadata.consentRecords)\n ? (metadata.consentRecords as JsonValue[])\n : [];\n } catch (error) {\n warnings.push(`Could not fetch holder export metadata: ${safeMessage(error)}`);\n }\n }\n\n if (!wallet.invoke.getConsentedContracts) return [];\n\n try {\n const response = await wallet.invoke.getConsentedContracts();\n\n if (!isRecord(response) || !Array.isArray(response.records)) return [];\n\n return response.records as JsonValue[];\n } catch (error) {\n warnings.push(`Could not fetch consented contracts fallback: ${safeMessage(error)}`);\n\n return [];\n }\n};\n\nexport const createLearnCardBundle = async (\n wallet: LearnCardBundleWallet,\n options: LearnCardBundleOptions = {}\n): Promise<LearnCardBundleResult> => {\n const encrypt = options.encrypt ?? true;\n\n if (encrypt && !options.password)\n throw new Error('A password is required for LearnCard export');\n\n const warnings: string[] = [];\n const zip = new JSZip();\n const contents: LearnCardBundleEntryMetadata[] = [];\n const primaryDid = wallet.id.did();\n const dids = collectDids(wallet, warnings);\n const didDocument = await collectDidDocument(wallet, primaryDid, dids, warnings);\n const credentialPayloads: JsonValue[] = [];\n\n const addStoredEntry = async (entry: {\n id: string;\n type: BundleContentType;\n path: string;\n content: string;\n encrypted: boolean;\n mediaType?: string;\n sourceUri?: string;\n credentialId?: string;\n indexRecordRef?: string;\n warnings?: string[];\n }): Promise<void> => {\n const encoded = await encodePayload(entry.content, {\n encrypt: entry.encrypted && encrypt,\n password: options.password,\n });\n const path =\n encoded.encrypted && !entry.path.endsWith('.enc') ? `${entry.path}.enc` : entry.path;\n\n addZipText(zip, path, encoded.stored);\n\n contents.push({\n id: entry.id,\n type: entry.type,\n path,\n mediaType: entry.mediaType ?? 'application/json',\n sha256: sha256Hex(encoded.stored),\n encrypted: encoded.encrypted,\n sourceUri: entry.sourceUri,\n credentialId: entry.credentialId,\n indexRecordRef: entry.indexRecordRef,\n warnings: entry.warnings,\n });\n };\n\n addZipText(zip, 'README.md', BUNDLE_README_MD);\n addZipText(zip, 'BUNDLE_SPEC.md', BUNDLE_SPEC_MD);\n\n await addStoredEntry({\n id: 'did-document',\n type: 'did-document',\n path: 'keys/did-document.json',\n content: json(didDocument),\n encrypted: false,\n });\n\n for (const payload of await collectKeyPayloads(wallet, warnings)) {\n await addStoredEntry({ ...payload, id: payload.path, mediaType: 'text/plain' });\n }\n\n const records = await wallet.index.LearnCloud.get();\n\n for (const [recordIndex, record] of records.entries()) {\n const entryWarnings: string[] = [];\n const digest = sha256Hex(\n stableStringify({ recordIndex, id: record.id ?? null, uri: record.uri ?? null })\n );\n\n try {\n const resolved = await wallet.read.get(record.uri);\n\n if (!resolved) {\n warnings.push(`Could not resolve wallet index URI ${redactUrl(record.uri)}`);\n continue;\n }\n\n credentialPayloads.push(resolved);\n const type = classifyPayload(resolved);\n const credentialId = getCredentialId(resolved);\n if (type === 'unknown-json') entryWarnings.push('Payload is not a recognized VC or VP');\n\n const indexRecordId = `urn:sha256:${digest}:index-record`;\n\n await addStoredEntry({\n id: indexRecordId,\n type: 'index-record',\n path: pathForType('index-record', digest, encrypt),\n content: json(record),\n encrypted: true,\n sourceUri: record.uri,\n credentialId,\n });\n\n await addStoredEntry({\n id: `urn:sha256:${digest}`,\n type,\n path: pathForType(type, digest, encrypt),\n content: json(resolved),\n encrypted: true,\n sourceUri: record.uri,\n credentialId,\n indexRecordRef: indexRecordId,\n warnings: entryWarnings.length > 0 ? entryWarnings : undefined,\n });\n } catch (error) {\n warnings.push(\n `Could not export wallet index URI ${redactUrl(record.uri)}: ${safeMessage(error)}`\n );\n }\n }\n\n const consentRecords = await collectConsentRecords(wallet, warnings);\n\n for (const consentRecord of consentRecords) {\n const digest = sha256Hex(stableStringify(consentRecord));\n\n await addStoredEntry({\n id: `urn:sha256:${digest}`,\n type: 'consent-record',\n path: pathForType('consent-record', digest, encrypt),\n content: json(consentRecord),\n encrypted: true,\n });\n }\n\n for (const statusList of await collectStatusLists(\n credentialPayloads,\n options.fetchStatusLists ?? true,\n warnings,\n options.statusListFetchTimeoutMs,\n options.maxStatusListBytes\n )) {\n const digest = sha256Hex(statusList.uri);\n\n await addStoredEntry({\n id: `urn:sha256:${digest}`,\n type: 'status-cache',\n path: pathForType('status-cache', digest, encrypt),\n content: json(statusList.content),\n encrypted: true,\n sourceUri: statusList.uri,\n });\n }\n\n const manifest = finalizeManifest({\n specVersion: SPEC_VERSION,\n createdAt: options.createdAt ?? new Date().toISOString(),\n primaryDid,\n walletName: 'LearnCard',\n encryption: encrypt\n ? {\n mode: 'argon2id-aes-256-gcm',\n encryptedPayloads: true,\n envelope: 'sss-key-manager-encryptWithPassword-v1',\n kdf: 'argon2id',\n cipher: 'AES-256-GCM',\n }\n : { mode: 'none', encryptedPayloads: false },\n contents,\n warnings,\n });\n\n addZipText(zip, 'manifest.json', `${JSON.stringify(manifest, null, 2)}\\n`);\n\n return {\n data: await zip.generateAsync({ type: 'nodebuffer', compression: 'DEFLATE' }),\n manifest,\n warnings,\n };\n};\n\nexport const exportLearnCardBundle = async (\n wallet: LearnCardBundleWallet,\n options: ExportLearnCardBundleOptions\n): Promise<LearnCardBundleResult> => {\n const bundle = await createLearnCardBundle(wallet, options);\n\n await mkdir(dirname(options.out), { recursive: true });\n await writeFile(options.out, bundle.data);\n\n return bundle;\n};\n", "import { createHash } from 'node:crypto';\n\nimport { decryptWithPassword, encryptWithPassword } from '@learncard/sss-key-manager';\n\nimport type { EncryptedPayloadEnvelope } from './types';\n\nexport const sha256Hex = (bytes: string | Buffer): string =>\n createHash('sha256').update(bytes).digest('hex');\n\nexport const stableStringify = (value: unknown): string => {\n if (value === null || typeof value !== 'object') return JSON.stringify(value);\n\n if (Array.isArray(value)) return `[${value.map(stableStringify).join(',')}]`;\n\n const object = value as Record<string, unknown>;\n\n return `{${Object.keys(object)\n .sort()\n .map(key => `${JSON.stringify(key)}:${stableStringify(object[key])}`)\n .join(',')}}`;\n};\n\nexport const encodePayload = async (\n plaintext: string,\n options: { encrypt: boolean; password?: string }\n): Promise<{ stored: string; encrypted: boolean }> => {\n if (!options.encrypt) return { stored: plaintext, encrypted: false };\n\n if (!options.password)\n throw new Error('A password is required for encrypted LearnCard exports');\n\n return {\n stored: JSON.stringify(await encryptWithPassword(plaintext, options.password), null, 2),\n encrypted: true,\n };\n};\n\nexport const decodePayload = async (\n stored: string,\n options: { encrypted: boolean; password?: string }\n): Promise<string> => {\n if (!options.encrypted) return stored;\n\n if (!options.password)\n throw new Error('A password is required to decrypt this LearnCard export');\n\n const envelope = JSON.parse(stored) as EncryptedPayloadEnvelope;\n\n return decryptWithPassword(\n envelope.ciphertext,\n envelope.iv,\n envelope.salt,\n options.password,\n envelope.kdfParams\n );\n};\n", "import type { LearnCardBundleEntryMetadata, LearnCardBundleManifest } from './types';\nimport { stableStringify, sha256Hex } from './crypto';\n\nexport const SPEC_VERSION = '1.0.0' as const;\n\nexport const BUNDLE_SPEC_MD = `# LearnCard Holder Continuity Bundle v1.0.0\n\nA LearnCard holder continuity bundle is a ZIP file with readable metadata and encrypted holder payloads.\n\n## Container\n\nRequired readable entries:\n\n- \\`manifest.json\\` \u2014 inventory, hashes, warnings, and encryption metadata.\n- \\`README.md\\` \u2014 human-readable recovery notes.\n- \\`BUNDLE_SPEC.md\\` \u2014 this format description.\n\nSensitive entries use JSON encryption envelopes produced by \\`@learncard/sss-key-manager\\` \\`encryptWithPassword\\`: Argon2id key derivation and AES-GCM authenticated encryption. The ZIP itself is not password encrypted.\n\n## Security model\n\nThis bundle exports the wallet's full raw private-key seed at \\`keys/private-key-seed.txt.enc\\`. LearnCard's live wallet protects the key with 2-of-4 Shamir Secret Sharing, where no single share can reconstruct it. The bundle does NOT preserve that threshold: the exported seed alone is sufficient to take full control of the identity, and the bundle password is the only barrier protecting it. \\`keys/recovery-phrase.txt.enc\\` is derived from the current recovery share for reference and is not independently sufficient to recover the key. Treat the bundle like a password-vault backup, use a strong unique password, and rotate the wallet if the bundle is exposed.\n\n## Paths\n\n- \\`keys/recovery-phrase.txt.enc\\`\n- \\`keys/private-key-seed.txt.enc\\`\n- \\`keys/jwks.json.enc\\`\n- \\`keys/did-document.json\\`\n- \\`credentials/<sha256>.json.enc\\`\n- \\`presentations/<sha256>.json.enc\\`\n- \\`index-records/<sha256>.json.enc\\`\n- \\`consent-records/<sha256>.json.enc\\`\n- \\`status-cache/<sha256>.json.enc\\`\n\nDebug exports MAY use plaintext payloads by setting \\`encrypt: false\\`; production exports MUST encrypt sensitive payloads.\n\nStatus-list snapshot fetching is HTTPS-only and rejects private, loopback, link-local, and single-label hosts. Exporters SHOULD keep the default timeout and response-size caps unless they are running in a trusted local environment.\n\n## Manifest hashing\n\nEach \\`contents[]\\` entry contains the SHA-256 hash of the bytes stored at \\`path\\`. \\`payloadSha256\\` is SHA-256 over a deterministic JSON serialization of \\`contents[]\\` with entries sorted by path.\n\nEach credential or presentation entry MAY reference an encrypted \\`index-record\\` companion entry via \\`indexRecordRef\\`; the readable manifest does not embed the original index record JSON.\n\n## Restore vs import\n\n\\`restoreLearnCardFromBundle(...)\\` decrypts \\`keys/private-key-seed.txt.enc\\` and passes that seed to \\`initLearnCard(...)\\`. It recreates the original wallet identity; it does not upload payloads or recreate index records.\n\n\\`importLearnCardBundle(...)\\` decrypts credential and presentation payloads, uploads them to the target wallet's LearnCloud store, and recreates index records from the encrypted \\`index-record\\` companions.\n\nImport writes bundle contents into the target wallet. A bundle author who knows the password can include arbitrary credentials, presentations, and index metadata. Use \\`verifyBeforeImport: true\\` to verify VC/VP signatures before upload when the target wallet exposes \\`invoke.verifyCredential\\` and \\`invoke.verifyPresentation\\`.\n\n## Size limits\n\nReaders enforce default compressed-bundle, per-entry, and JSON parse limits to avoid accidentally processing oversized ZIP or JSON payloads. Callers can override these with \\`maxBundleBytes\\`, \\`maxEntryBytes\\`, and \\`maxJsonBytes\\` for trusted local workflows.\n\n## Import expectations\n\nImporters MUST verify the stored bytes against each entry hash before trusting decrypted content. Importers SHOULD verify issuer signatures before upload and preserve issuer-signed credential and presentation payloads exactly.\n`;\n\nexport const BUNDLE_README_MD = `# LearnCard Holder Continuity Export\n\nThis archive contains a point-in-time holder export from a LearnCard wallet.\n\nKeep the password separately. Without it, encrypted credentials, key material, consent records, and status-list snapshots cannot be recovered.\n\nThis archive contains your full private-key seed (encrypted). Anyone with both this file and its password can take complete control of your wallet identity, so store it like a password-vault backup and rotate your wallet if it is exposed.\n\nThe readable manifest lists every payload and its SHA-256 hash. Third-party wallets can import individual W3C Verifiable Credentials or Verifiable Presentations from the decrypted JSON files even when they do not support the LearnCard ZIP bundle directly.\n`;\n\nexport const sortContents = (\n contents: LearnCardBundleEntryMetadata[]\n): LearnCardBundleEntryMetadata[] => [...contents].sort((a, b) => a.path.localeCompare(b.path));\n\nconst normalizeContents = (\n contents: LearnCardBundleEntryMetadata[]\n): LearnCardBundleEntryMetadata[] =>\n JSON.parse(JSON.stringify(sortContents(contents))) as LearnCardBundleEntryMetadata[];\n\nexport const computePayloadSha256 = (contents: LearnCardBundleEntryMetadata[]): string =>\n sha256Hex(stableStringify(normalizeContents(contents)));\n\nexport const finalizeManifest = (\n manifest: Omit<LearnCardBundleManifest, 'payloadSha256'>\n): LearnCardBundleManifest => ({\n ...manifest,\n contents: normalizeContents(manifest.contents),\n payloadSha256: computePayloadSha256(manifest.contents),\n});\n\nexport const assertValidManifest = (manifest: LearnCardBundleManifest): void => {\n if (manifest.specVersion !== SPEC_VERSION) {\n throw new Error(`Unsupported LearnCard bundle version: ${manifest.specVersion}`);\n }\n\n const expected = computePayloadSha256(manifest.contents);\n\n if (manifest.payloadSha256 !== expected)\n throw new Error('LearnCard bundle manifest hash mismatch');\n};\n", "import { readFile } from 'node:fs/promises';\n\nimport JSZip from 'jszip';\n\nimport type {\n ImportLearnCardBundleOptions,\n ImportLearnCardBundleReport,\n JsonValue,\n LearnCardBundleEntryMetadata,\n LearnCardBundleManifest,\n ReadLearnCardBundleOptions,\n ReadLearnCardBundleResult,\n} from './types';\nimport { assertValidManifest } from './manifest';\nimport { decodePayload, sha256Hex } from './crypto';\n\nconst DEFAULT_MAX_BUNDLE_BYTES = 100 * 1024 * 1024;\nconst DEFAULT_MAX_ENTRY_BYTES = 25 * 1024 * 1024;\nconst DEFAULT_MAX_JSON_BYTES = 25 * 1024 * 1024;\n\nconst byteLength = (content: string): number => Buffer.byteLength(content, 'utf8');\n\nconst assertSize = (label: string, size: number, max: number): void => {\n if (size > max) throw new Error(`${label} exceeds ${max} bytes`);\n};\n\nconst parseJson = (content: string, label: string, maxBytes: number): JsonValue => {\n assertSize(label, byteLength(content), maxBytes);\n\n return JSON.parse(content) as JsonValue;\n};\n\nconst safeMessage = (error: unknown): string =>\n error instanceof Error ? error.message : String(error);\n\nconst parseObject = (content: string, label: string, maxBytes: number): Record<string, unknown> => {\n const value = parseJson(content, label, maxBytes);\n\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error('Expected bundle metadata entry to contain a JSON object');\n }\n\n return value as Record<string, unknown>;\n};\n\nconst isImportableCredentialEntry = (entry: LearnCardBundleEntryMetadata): boolean =>\n entry.type === 'credential' || entry.type === 'presentation';\n\nconst isFailedVerification = (result: unknown): boolean => {\n if (Array.isArray(result)) {\n return result.some(item => {\n if (!item || typeof item !== 'object') return true;\n\n const status = 'status' in item ? item.status : undefined;\n\n return status === 'Failed' || status === 'Error';\n });\n }\n\n if (!result || typeof result !== 'object') return true;\n\n const errors = 'errors' in result ? result.errors : undefined;\n\n return !Array.isArray(errors) || errors.length > 0;\n};\n\nconst verifyImportableEntry = async (\n entry: LearnCardBundleEntryMetadata,\n content: JsonValue,\n options: ImportLearnCardBundleOptions\n): Promise<void> => {\n if (!options.verifyBeforeImport) return;\n\n if (entry.type === 'credential') {\n if (!options.wallet.invoke.verifyCredential) {\n throw new Error('Target wallet does not expose invoke.verifyCredential');\n }\n\n const verification = await options.wallet.invoke.verifyCredential(content);\n\n if (isFailedVerification(verification)) throw new Error('Credential verification failed');\n\n return;\n }\n\n if (!options.wallet.invoke.verifyPresentation) {\n throw new Error('Target wallet does not expose invoke.verifyPresentation');\n }\n\n const verification = await options.wallet.invoke.verifyPresentation(content);\n\n if (isFailedVerification(verification)) throw new Error('Presentation verification failed');\n};\n\nexport const readLearnCardBundleData = async (\n data: Buffer,\n options: ReadLearnCardBundleOptions = {}\n): Promise<ReadLearnCardBundleResult> => {\n const maxBundleBytes = options.maxBundleBytes ?? DEFAULT_MAX_BUNDLE_BYTES;\n const maxEntryBytes = options.maxEntryBytes ?? DEFAULT_MAX_ENTRY_BYTES;\n const maxJsonBytes = options.maxJsonBytes ?? DEFAULT_MAX_JSON_BYTES;\n\n assertSize('LearnCard bundle', data.byteLength, maxBundleBytes);\n\n const zip = await JSZip.loadAsync(data);\n const manifestFile = zip.file('manifest.json');\n\n if (!manifestFile) throw new Error('LearnCard bundle is missing manifest.json');\n\n const manifestContent = await manifestFile.async('string');\n\n assertSize('manifest.json', byteLength(manifestContent), maxJsonBytes);\n\n const manifest = JSON.parse(manifestContent) as LearnCardBundleManifest;\n\n assertValidManifest(manifest);\n\n const warnings = [...manifest.warnings];\n const entries: ReadLearnCardBundleResult['entries'] = [];\n const shouldDecrypt = options.decrypt ?? true;\n let totalEntryBytes = 0;\n\n for (const entry of manifest.contents) {\n const file = zip.file(entry.path);\n\n if (!file) throw new Error(`LearnCard bundle is missing ${entry.path}`);\n\n const stored = await file.async('string');\n const storedBytes = byteLength(stored);\n\n assertSize(entry.path, storedBytes, maxEntryBytes);\n\n totalEntryBytes += storedBytes;\n assertSize('LearnCard bundle entries', totalEntryBytes, maxBundleBytes);\n\n const actualSha = sha256Hex(stored);\n\n if (actualSha !== entry.sha256) {\n throw new Error(`SHA-256 mismatch for ${entry.path}`);\n }\n\n const content = shouldDecrypt\n ? await decodePayload(stored, {\n encrypted: entry.encrypted,\n password: options.password,\n })\n : stored;\n\n assertSize(`${entry.path} content`, byteLength(content), maxEntryBytes);\n\n entries.push({ ...entry, content });\n }\n\n return { manifest, entries, warnings };\n};\n\nexport const readLearnCardBundle = async (\n path: string,\n options: ReadLearnCardBundleOptions = {}\n): Promise<ReadLearnCardBundleResult> => readLearnCardBundleData(await readFile(path), options);\n\nexport const importLearnCardBundle = async (\n path: string,\n options: ImportLearnCardBundleOptions\n): Promise<ImportLearnCardBundleReport> => {\n const bundle = await readLearnCardBundle(path, options);\n const maxJsonBytes = options.maxJsonBytes ?? DEFAULT_MAX_JSON_BYTES;\n const report: ImportLearnCardBundleReport = {\n importedCredentials: 0,\n importedPresentations: 0,\n skipped: 0,\n skippedByType: {},\n errors: [],\n warnings: [...bundle.warnings],\n };\n\n if (!options.verifyBeforeImport) {\n report.warnings.push(\n 'Bundle credential signatures were not verified before import; only import bundles from sources you trust.'\n );\n }\n\n const entriesById = new Map(bundle.entries.map(entry => [entry.id, entry]));\n\n for (const entry of bundle.entries) {\n if (!isImportableCredentialEntry(entry)) {\n report.skipped += 1;\n report.skippedByType[entry.type] = (report.skippedByType[entry.type] ?? 0) + 1;\n continue;\n }\n\n try {\n const content = parseJson(entry.content, entry.path, maxJsonBytes);\n\n await verifyImportableEntry(entry, content, options);\n\n const upload =\n options.wallet.store.LearnCloud.uploadEncrypted ??\n options.wallet.store.LearnCloud.upload;\n\n if (!upload)\n throw new Error('Target wallet does not expose a LearnCloud upload method');\n\n const uri = await upload(content);\n const referencedIndexRecord = entry.indexRecordRef\n ? entriesById.get(entry.indexRecordRef)\n : undefined;\n\n if (entry.indexRecordRef && !referencedIndexRecord) {\n throw new Error(`Referenced index record ${entry.indexRecordRef} is missing`);\n }\n\n const indexRecord = referencedIndexRecord\n ? parseObject(\n referencedIndexRecord.content,\n referencedIndexRecord.path,\n maxJsonBytes\n )\n : { id: entry.id, uri };\n const recordId = typeof indexRecord.id === 'string' ? indexRecord.id : entry.id;\n\n await options.wallet.index.LearnCloud.add({\n ...indexRecord,\n id: recordId,\n uri,\n sourceExport: {\n manifestCreatedAt: bundle.manifest.createdAt,\n sourceUri: entry.sourceUri,\n sourcePath: entry.path,\n credentialId: entry.credentialId,\n },\n });\n\n if (entry.type === 'presentation') report.importedPresentations += 1;\n else report.importedCredentials += 1;\n } catch (error) {\n report.errors.push({ path: entry.path, message: safeMessage(error) });\n }\n }\n\n return report;\n};\n", "import { initLearnCard } from '@learncard/init';\nimport type { InitLearnCard } from '@learncard/init';\n\nimport { readLearnCardBundle, readLearnCardBundleData } from './importBundle';\nimport type { ReadLearnCardBundleOptions, ReadLearnCardBundleResult } from './types';\n\ntype SeededInitConfig = Extract<InitLearnCard['args'], { seed: string }>;\ntype DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;\n\nexport type RestoreLearnCardInit = DistributiveOmit<SeededInitConfig, 'seed'>;\n\nexport type RestoreLearnCardFromBundleOptions = ReadLearnCardBundleOptions & {\n init: RestoreLearnCardInit;\n};\n\nconst getSeedEntry = (bundle: ReadLearnCardBundleResult): string => {\n const seedEntry = bundle.entries.find(entry => entry.type === 'key-private-seed');\n\n if (!seedEntry) {\n throw new Error(\n 'LearnCard bundle does not contain key-private-seed and cannot be restored'\n );\n }\n\n const seed = seedEntry.content.trim();\n\n if (!/^[0-9a-f]{64}$/i.test(seed)) {\n throw new Error(\n 'LearnCard bundle key-private-seed must be exactly 64 hexadecimal characters'\n );\n }\n\n return seed;\n};\n\nexport const readLearnCardBundleSeedData = async (\n data: Buffer,\n options: ReadLearnCardBundleOptions = {}\n): Promise<string> => getSeedEntry(await readLearnCardBundleData(data, options));\n\nexport const readLearnCardBundleSeed = async (\n path: string,\n options: ReadLearnCardBundleOptions = {}\n): Promise<string> => getSeedEntry(await readLearnCardBundle(path, options));\n\nexport const restoreLearnCardFromBundleData = async (\n data: Buffer,\n options: RestoreLearnCardFromBundleOptions\n): Promise<InitLearnCard['returnValue']> => {\n const seed = await readLearnCardBundleSeedData(data, options);\n\n return initLearnCard({ ...options.init, seed } as SeededInitConfig);\n};\n\nexport const restoreLearnCardFromBundle = async (\n path: string,\n options: RestoreLearnCardFromBundleOptions\n): Promise<InitLearnCard['returnValue']> => {\n const seed = await readLearnCardBundleSeed(path, options);\n\n return initLearnCard({ ...options.init, seed } as SeededInitConfig);\n};\n"],
5
+ "mappings": "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",
6
6
  "names": ["import_promises", "import_sss_key_manager", "JSZip", "import_promises", "import_jszip", "safeMessage", "verification", "JSZip"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts", "../src/exportBundle.ts", "../src/crypto.ts", "../src/manifest.ts", "../src/importBundle.ts", "../src/restoreBundle.ts"],
4
- "sourcesContent": ["export { createLearnCardBundle, exportLearnCardBundle } from './exportBundle';\nexport { importLearnCardBundle, readLearnCardBundle, readLearnCardBundleData } from './importBundle';\nexport { assertValidManifest, computePayloadSha256, finalizeManifest } from './manifest';\nexport {\n readLearnCardBundleSeed,\n readLearnCardBundleSeedData,\n restoreLearnCardFromBundle,\n restoreLearnCardFromBundleData,\n} from './restoreBundle';\nexport type {\n ExportLearnCardBundleOptions,\n ImportLearnCardBundleOptions,\n ImportLearnCardBundleReport,\n LearnCardBundleManifest,\n LearnCardBundleOptions,\n LearnCardBundleResult,\n LearnCardBundleWallet,\n ReadLearnCardBundleOptions,\n ReadLearnCardBundleResult,\n} from './types';\nexport type { RestoreLearnCardFromBundleOptions, RestoreLearnCardInit } from './restoreBundle';\n", "import { lookup } from 'node:dns/promises';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { isIP } from 'node:net';\nimport { dirname } from 'node:path';\n\nimport JSZip from 'jszip';\nimport { shareToRecoveryPhrase, splitPrivateKey } from '@learncard/sss-key-manager';\n\nimport type {\n BundleContentType,\n ExportLearnCardBundleOptions,\n JsonValue,\n LearnCardBundleEntryMetadata,\n LearnCardBundleOptions,\n LearnCardBundleResult,\n LearnCardBundleWallet,\n} from './types';\nimport { BUNDLE_README_MD, BUNDLE_SPEC_MD, finalizeManifest, SPEC_VERSION } from './manifest';\nimport { encodePayload, sha256Hex, stableStringify } from './crypto';\n\nconst ZIP_DATE = new Date('2024-01-01T00:00:00.000Z');\n\nconst DEFAULT_STATUS_LIST_FETCH_TIMEOUT_MS = 5000;\nconst DEFAULT_MAX_STATUS_LIST_BYTES = 5 * 1024 * 1024;\n\nconst stripIpv6Brackets = (hostname: string): string =>\n hostname.startsWith('[') && hostname.endsWith(']') ? hostname.slice(1, -1) : hostname;\n\nconst redactMalformedUrl = (value: string): string => {\n const queryIndex = value.indexOf('?');\n const ampIndex = value.indexOf('&');\n\n if (queryIndex === -1 && ampIndex === -1) return value;\n\n const redactionIndex =\n queryIndex === -1\n ? ampIndex\n : ampIndex === -1\n ? queryIndex\n : Math.min(queryIndex, ampIndex);\n\n return `${value.slice(0, redactionIndex)}?[redacted]`;\n};\n\nconst redactUrl = (value: string): string => {\n try {\n const url = new URL(value);\n const hostname = stripIpv6Brackets(url.hostname.toLowerCase());\n const shouldRedactHost =\n !hostname.includes('.') ||\n hostname === 'localhost' ||\n hostname.endsWith('.localhost') ||\n Boolean(isIP(hostname) && isPrivateAddress(hostname));\n const host = shouldRedactHost ? '[redacted-host]' : url.host;\n\n return `${url.protocol}//${host}${url.pathname}${url.search ? '?[redacted]' : ''}`;\n } catch {\n return redactMalformedUrl(value);\n }\n};\n\nconst urlEndDelimiters = new Set([' ', '\\n', '\\r', '\\t', \"'\", '\"', '<', '>']);\n\nconst findNextUrlStart = (value: string, fromIndex: number): number => {\n const httpIndex = value.indexOf('http://', fromIndex);\n const httpsIndex = value.indexOf('https://', fromIndex);\n\n if (httpIndex === -1) return httpsIndex;\n if (httpsIndex === -1) return httpIndex;\n\n return Math.min(httpIndex, httpsIndex);\n};\n\nconst findUrlEnd = (value: string, fromIndex: number): number => {\n let index = fromIndex;\n\n while (index < value.length && !urlEndDelimiters.has(value[index]!)) index += 1;\n\n return index;\n};\n\nconst redactText = (value: string): string => {\n let redacted = '';\n let index = 0;\n\n while (index < value.length) {\n const urlStart = findNextUrlStart(value, index);\n\n if (urlStart === -1) {\n redacted += value.slice(index);\n break;\n }\n\n const urlEnd = findUrlEnd(value, urlStart);\n\n redacted += value.slice(index, urlStart);\n redacted += redactUrl(value.slice(urlStart, urlEnd));\n index = urlEnd;\n }\n\n return redacted;\n};\n\nconst safeMessage = (error: unknown): string =>\n redactText(error instanceof Error ? error.message : String(error));\n\nconst isPrivateIPv4 = (address: string): boolean => {\n const parts = address.split('.').map(part => Number(part));\n\n if (parts.length !== 4 || parts.some(part => !Number.isInteger(part) || part < 0 || part > 255))\n return true;\n\n const [a, b] = parts;\n\n if (a === 0 || a === 10 || a === 127 || a >= 224) return true;\n if (a === 100 && b >= 64 && b <= 127) return true;\n if (a === 169 && b === 254) return true;\n if (a === 172 && b >= 16 && b <= 31) return true;\n if (a === 192 && b === 168) return true;\n if (a === 198 && (b === 18 || b === 19)) return true;\n\n return false;\n};\n\nconst isPrivateIPv6 = (address: string): boolean => {\n const normalized = address.toLowerCase();\n\n if (normalized === '::' || normalized === '::1') return true;\n if (normalized.startsWith('fc') || normalized.startsWith('fd')) return true;\n if (\n normalized.startsWith('fe8') ||\n normalized.startsWith('fe9') ||\n normalized.startsWith('fea') ||\n normalized.startsWith('feb')\n )\n return true;\n\n const ipv4Mapped = normalized.match(/::ffff:(\\d+\\.\\d+\\.\\d+\\.\\d+)$/);\n\n return ipv4Mapped ? isPrivateIPv4(ipv4Mapped[1]!) : false;\n};\n\nconst isPrivateAddress = (address: string): boolean => {\n const version = isIP(address);\n\n if (version === 4) return isPrivateIPv4(address);\n if (version === 6) return isPrivateIPv6(address);\n\n return true;\n};\n\nconst assertPublicHttpsUrl = async (uri: string): Promise<URL> => {\n const url = new URL(uri);\n const hostname = url.hostname.toLowerCase().replace(/^\\[|\\]$/g, '');\n\n if (url.protocol !== 'https:') throw new Error('status-list URL must use https');\n if (!hostname.includes('.') || hostname === 'localhost' || hostname.endsWith('.localhost')) {\n throw new Error('status-list URL host must be public');\n }\n\n if (isIP(hostname)) {\n if (isPrivateAddress(hostname)) throw new Error('status-list URL host must be public');\n\n return url;\n }\n\n const addresses = await lookup(hostname, { all: true, verbatim: true });\n\n if (addresses.length === 0 || addresses.some(address => isPrivateAddress(address.address))) {\n throw new Error('status-list URL host must resolve to public addresses');\n }\n\n return url;\n};\n\nconst readResponseText = async (response: Response, maxBytes: number): Promise<string> => {\n const contentLength = Number(response.headers.get('content-length'));\n\n if (Number.isFinite(contentLength) && contentLength > maxBytes) {\n throw new Error(`status-list response exceeds ${maxBytes} bytes`);\n }\n\n if (!response.body) {\n const text = await response.text();\n\n if (Buffer.byteLength(text, 'utf8') > maxBytes) {\n throw new Error(`status-list response exceeds ${maxBytes} bytes`);\n }\n\n return text;\n }\n\n const reader = response.body.getReader();\n const chunks: Buffer[] = [];\n let total = 0;\n\n while (true) {\n const { done, value } = await reader.read();\n\n if (done) break;\n\n total += value.byteLength;\n\n if (total > maxBytes) {\n await reader.cancel();\n\n throw new Error(`status-list response exceeds ${maxBytes} bytes`);\n }\n\n chunks.push(Buffer.from(value));\n }\n\n return Buffer.concat(chunks).toString('utf8');\n};\n\nconst fetchJsonWithTimeout = async (\n url: URL,\n timeoutMs: number,\n maxBytes: number\n): Promise<JsonValue> => {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n const response = await fetch(url, { signal: controller.signal });\n\n if (!response.ok) throw new Error(`HTTP ${response.status}`);\n\n return JSON.parse(await readResponseText(response, maxBytes)) as JsonValue;\n } finally {\n clearTimeout(timeout);\n }\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n Boolean(value) && typeof value === 'object' && !Array.isArray(value);\n\nconst stringArrayIncludes = (value: unknown, expected: string): boolean =>\n Array.isArray(value) && value.some(item => item === expected);\n\nconst json = (value: unknown): string => `${stableStringify(value)}\\n`;\n\nconst classifyPayload = (payload: JsonValue): BundleContentType => {\n if (!isRecord(payload)) return 'unknown-json';\n\n if (\n stringArrayIncludes(payload.type, 'VerifiablePresentation') ||\n payload.type === 'VerifiablePresentation'\n ) {\n return 'presentation';\n }\n\n if (\n stringArrayIncludes(payload.type, 'VerifiableCredential') ||\n payload.type === 'VerifiableCredential'\n ) {\n return 'credential';\n }\n\n return 'unknown-json';\n};\n\nconst pathForType = (type: BundleContentType, digest: string, encrypted: boolean): string => {\n const suffix = encrypted ? '.enc' : '';\n\n if (type === 'presentation') return `presentations/${digest}.json${suffix}`;\n\n if (type === 'consent-record') return `consent-records/${digest}.json${suffix}`;\n\n if (type === 'index-record') return `index-records/${digest}.json${suffix}`;\n if (type === 'status-cache') return `status-cache/${digest}.json${suffix}`;\n\n return `credentials/${digest}.json${suffix}`;\n};\n\nconst getCredentialId = (payload: JsonValue): string | undefined =>\n isRecord(payload) && typeof payload.id === 'string' ? payload.id : undefined;\n\nconst addZipText = (zip: JSZip, path: string, content: string): void => {\n zip.file(path, content, { date: ZIP_DATE });\n};\n\nconst collectDids = (wallet: LearnCardBundleWallet, warnings: string[]): Record<string, string> => {\n const dids: Record<string, string> = {};\n\n for (const method of [undefined, 'key', 'pkh:sol', 'tz', 'pkh:tz']) {\n try {\n dids[method ?? 'default'] = wallet.id.did(method);\n } catch (error) {\n warnings.push(\n `Could not derive DID method ${method ?? 'default'}: ${safeMessage(error)}`\n );\n }\n }\n\n return dids;\n};\n\nconst collectDidDocument = async (\n wallet: LearnCardBundleWallet,\n primaryDid: string,\n dids: Record<string, string>,\n warnings: string[]\n): Promise<JsonValue> => {\n if (!wallet.invoke.resolveDid) return { primaryDid, dids };\n\n try {\n return { primaryDid, dids, primaryDidDocument: await wallet.invoke.resolveDid(primaryDid) };\n } catch (error) {\n warnings.push(`Could not resolve primary DID document: ${safeMessage(error)}`);\n\n return { primaryDid, dids };\n }\n};\n\nconst collectKeyPayloads = async (\n wallet: LearnCardBundleWallet,\n warnings: string[]\n): Promise<\n Array<{ path: string; type: BundleContentType; content: string; encrypted: boolean }>\n> => {\n const payloads: Array<{\n path: string;\n type: BundleContentType;\n content: string;\n encrypted: boolean;\n }> = [];\n\n if (wallet.invoke.getKey) {\n try {\n const seed = wallet.invoke.getKey();\n const shares = await splitPrivateKey(seed);\n\n payloads.push({\n path: 'keys/private-key-seed.txt',\n type: 'key-private-seed',\n content: `${seed}\\n`,\n encrypted: true,\n });\n\n payloads.push({\n path: 'keys/recovery-phrase.txt',\n type: 'key-recovery-phrase',\n content: `${await shareToRecoveryPhrase(shares.recoveryShare)}\\n`,\n encrypted: true,\n });\n } catch (error) {\n warnings.push(`Could not export seed or recovery phrase: ${safeMessage(error)}`);\n }\n } else {\n warnings.push(\n 'Wallet does not expose invoke.getKey(); private seed and recovery phrase were not exported'\n );\n }\n\n if (wallet.id.keypair) {\n const jwks: Record<string, JsonValue> = {};\n\n for (const algorithm of ['ed25519', 'secp256k1'] as const) {\n try {\n jwks[algorithm] = wallet.id.keypair(algorithm);\n } catch (error) {\n warnings.push(`Could not export ${algorithm} JWK: ${safeMessage(error)}`);\n }\n }\n\n if (Object.keys(jwks).length > 0) {\n payloads.push({\n path: 'keys/jwks.json',\n type: 'key-jwks',\n content: json(jwks),\n encrypted: true,\n });\n }\n } else {\n warnings.push('Wallet does not expose id.keypair(); JWK key export was skipped');\n }\n\n return payloads;\n};\n\nconst extractStatusListUrls = (payload: JsonValue): string[] => {\n if (!isRecord(payload)) return [];\n\n const statuses = Array.isArray(payload.credentialStatus)\n ? payload.credentialStatus\n : payload.credentialStatus\n ? [payload.credentialStatus]\n : [];\n\n return statuses.flatMap(status =>\n isRecord(status) && typeof status.statusListCredential === 'string'\n ? [status.statusListCredential]\n : []\n );\n};\n\nconst collectStatusLists = async (\n payloads: JsonValue[],\n enabled: boolean,\n warnings: string[],\n timeoutMs = DEFAULT_STATUS_LIST_FETCH_TIMEOUT_MS,\n maxBytes = DEFAULT_MAX_STATUS_LIST_BYTES\n): Promise<Array<{ uri: string; content: JsonValue }>> => {\n if (!enabled) return [];\n\n const urls = [...new Set(payloads.flatMap(extractStatusListUrls))];\n const results: Array<{ uri: string; content: JsonValue }> = [];\n\n for (const uri of urls) {\n try {\n const url = await assertPublicHttpsUrl(uri);\n\n results.push({ uri, content: await fetchJsonWithTimeout(url, timeoutMs, maxBytes) });\n } catch (error) {\n warnings.push(\n `Could not cache status-list credential ${redactUrl(uri)}: ${safeMessage(error)}`\n );\n }\n }\n\n return results;\n};\n\nconst collectConsentRecords = async (\n wallet: LearnCardBundleWallet,\n warnings: string[]\n): Promise<JsonValue[]> => {\n if (wallet.invoke.getHolderExportMetadata) {\n try {\n const metadata = await wallet.invoke.getHolderExportMetadata();\n\n if (isRecord(metadata) && Array.isArray(metadata.warnings)) {\n warnings.push(\n ...metadata.warnings\n .filter(warning => typeof warning === 'string')\n .map(warning => redactText(warning))\n );\n }\n\n return isRecord(metadata) && Array.isArray(metadata.consentRecords)\n ? (metadata.consentRecords as JsonValue[])\n : [];\n } catch (error) {\n warnings.push(`Could not fetch holder export metadata: ${safeMessage(error)}`);\n }\n }\n\n if (!wallet.invoke.getConsentedContracts) return [];\n\n try {\n const response = await wallet.invoke.getConsentedContracts();\n\n if (!isRecord(response) || !Array.isArray(response.records)) return [];\n\n return response.records as JsonValue[];\n } catch (error) {\n warnings.push(`Could not fetch consented contracts fallback: ${safeMessage(error)}`);\n\n return [];\n }\n};\n\nexport const createLearnCardBundle = async (\n wallet: LearnCardBundleWallet,\n options: LearnCardBundleOptions = {}\n): Promise<LearnCardBundleResult> => {\n const encrypt = options.encrypt ?? true;\n\n if (encrypt && !options.password)\n throw new Error('A password is required for LearnCard export');\n\n const warnings: string[] = [];\n const zip = new JSZip();\n const contents: LearnCardBundleEntryMetadata[] = [];\n const primaryDid = wallet.id.did();\n const dids = collectDids(wallet, warnings);\n const didDocument = await collectDidDocument(wallet, primaryDid, dids, warnings);\n const credentialPayloads: JsonValue[] = [];\n\n const addStoredEntry = async (entry: {\n id: string;\n type: BundleContentType;\n path: string;\n content: string;\n encrypted: boolean;\n mediaType?: string;\n sourceUri?: string;\n credentialId?: string;\n indexRecordRef?: string;\n warnings?: string[];\n }): Promise<void> => {\n const encoded = await encodePayload(entry.content, {\n encrypt: entry.encrypted && encrypt,\n password: options.password,\n });\n const path =\n encoded.encrypted && !entry.path.endsWith('.enc') ? `${entry.path}.enc` : entry.path;\n\n addZipText(zip, path, encoded.stored);\n\n contents.push({\n id: entry.id,\n type: entry.type,\n path,\n mediaType: entry.mediaType ?? 'application/json',\n sha256: sha256Hex(encoded.stored),\n encrypted: encoded.encrypted,\n sourceUri: entry.sourceUri,\n credentialId: entry.credentialId,\n indexRecordRef: entry.indexRecordRef,\n warnings: entry.warnings,\n });\n };\n\n addZipText(zip, 'README.md', BUNDLE_README_MD);\n addZipText(zip, 'BUNDLE_SPEC.md', BUNDLE_SPEC_MD);\n\n await addStoredEntry({\n id: 'did-document',\n type: 'did-document',\n path: 'keys/did-document.json',\n content: json(didDocument),\n encrypted: false,\n });\n\n for (const payload of await collectKeyPayloads(wallet, warnings)) {\n await addStoredEntry({ ...payload, id: payload.path, mediaType: 'text/plain' });\n }\n\n const records = await wallet.index.LearnCloud.get();\n\n for (const [recordIndex, record] of records.entries()) {\n const entryWarnings: string[] = [];\n const digest = sha256Hex(\n stableStringify({ recordIndex, id: record.id ?? null, uri: record.uri ?? null })\n );\n\n try {\n const resolved = await wallet.read.get(record.uri);\n\n if (!resolved) {\n warnings.push(`Could not resolve wallet index URI ${redactUrl(record.uri)}`);\n continue;\n }\n\n credentialPayloads.push(resolved);\n const type = classifyPayload(resolved);\n const credentialId = getCredentialId(resolved);\n if (type === 'unknown-json') entryWarnings.push('Payload is not a recognized VC or VP');\n\n const indexRecordId = `urn:sha256:${digest}:index-record`;\n\n await addStoredEntry({\n id: indexRecordId,\n type: 'index-record',\n path: pathForType('index-record', digest, encrypt),\n content: json(record),\n encrypted: true,\n sourceUri: record.uri,\n credentialId,\n });\n\n await addStoredEntry({\n id: `urn:sha256:${digest}`,\n type,\n path: pathForType(type, digest, encrypt),\n content: json(resolved),\n encrypted: true,\n sourceUri: record.uri,\n credentialId,\n indexRecordRef: indexRecordId,\n warnings: entryWarnings.length > 0 ? entryWarnings : undefined,\n });\n } catch (error) {\n warnings.push(\n `Could not export wallet index URI ${redactUrl(record.uri)}: ${safeMessage(error)}`\n );\n }\n }\n\n const consentRecords = await collectConsentRecords(wallet, warnings);\n\n for (const consentRecord of consentRecords) {\n const digest = sha256Hex(stableStringify(consentRecord));\n\n await addStoredEntry({\n id: `urn:sha256:${digest}`,\n type: 'consent-record',\n path: pathForType('consent-record', digest, encrypt),\n content: json(consentRecord),\n encrypted: true,\n });\n }\n\n for (const statusList of await collectStatusLists(\n credentialPayloads,\n options.fetchStatusLists ?? true,\n warnings,\n options.statusListFetchTimeoutMs,\n options.maxStatusListBytes\n )) {\n const digest = sha256Hex(statusList.uri);\n\n await addStoredEntry({\n id: `urn:sha256:${digest}`,\n type: 'status-cache',\n path: pathForType('status-cache', digest, encrypt),\n content: json(statusList.content),\n encrypted: true,\n sourceUri: statusList.uri,\n });\n }\n\n const manifest = finalizeManifest({\n specVersion: SPEC_VERSION,\n createdAt: options.createdAt ?? new Date().toISOString(),\n primaryDid,\n walletName: 'LearnCard',\n encryption: encrypt\n ? {\n mode: 'argon2id-aes-256-gcm',\n encryptedPayloads: true,\n envelope: 'sss-key-manager-encryptWithPassword-v1',\n kdf: 'argon2id',\n cipher: 'AES-256-GCM',\n }\n : { mode: 'none', encryptedPayloads: false },\n contents,\n warnings,\n });\n\n addZipText(zip, 'manifest.json', `${JSON.stringify(manifest, null, 2)}\\n`);\n\n return {\n data: await zip.generateAsync({ type: 'nodebuffer', compression: 'DEFLATE' }),\n manifest,\n warnings,\n };\n};\n\nexport const exportLearnCardBundle = async (\n wallet: LearnCardBundleWallet,\n options: ExportLearnCardBundleOptions\n): Promise<LearnCardBundleResult> => {\n const bundle = await createLearnCardBundle(wallet, options);\n\n await mkdir(dirname(options.out), { recursive: true });\n await writeFile(options.out, bundle.data);\n\n return bundle;\n};\n", "import { createHash } from 'node:crypto';\n\nimport { decryptWithPassword, encryptWithPassword } from '@learncard/sss-key-manager';\n\nimport type { EncryptedPayloadEnvelope } from './types';\n\nexport const sha256Hex = (bytes: string | Buffer): string =>\n createHash('sha256').update(bytes).digest('hex');\n\nexport const stableStringify = (value: unknown): string => {\n if (value === null || typeof value !== 'object') return JSON.stringify(value);\n\n if (Array.isArray(value)) return `[${value.map(stableStringify).join(',')}]`;\n\n const object = value as Record<string, unknown>;\n\n return `{${Object.keys(object)\n .sort()\n .map(key => `${JSON.stringify(key)}:${stableStringify(object[key])}`)\n .join(',')}}`;\n};\n\nexport const encodePayload = async (\n plaintext: string,\n options: { encrypt: boolean; password?: string }\n): Promise<{ stored: string; encrypted: boolean }> => {\n if (!options.encrypt) return { stored: plaintext, encrypted: false };\n\n if (!options.password) throw new Error('A password is required for encrypted LearnCard exports');\n\n return {\n stored: JSON.stringify(await encryptWithPassword(plaintext, options.password), null, 2),\n encrypted: true,\n };\n};\n\nexport const decodePayload = async (\n stored: string,\n options: { encrypted: boolean; password?: string }\n): Promise<string> => {\n if (!options.encrypted) return stored;\n\n if (!options.password) throw new Error('A password is required to decrypt this LearnCard export');\n\n const envelope = JSON.parse(stored) as EncryptedPayloadEnvelope;\n\n return decryptWithPassword(\n envelope.ciphertext,\n envelope.iv,\n envelope.salt,\n options.password,\n envelope.kdfParams\n );\n};\n", "import type { LearnCardBundleEntryMetadata, LearnCardBundleManifest } from './types';\nimport { stableStringify, sha256Hex } from './crypto';\n\nexport const SPEC_VERSION = '1.0.0' as const;\n\nexport const BUNDLE_SPEC_MD = `# LearnCard Holder Continuity Bundle v1.0.0\n\nA LearnCard holder continuity bundle is a ZIP file with readable metadata and encrypted holder payloads.\n\n## Container\n\nRequired readable entries:\n\n- \\`manifest.json\\` \u2014 inventory, hashes, warnings, and encryption metadata.\n- \\`README.md\\` \u2014 human-readable recovery notes.\n- \\`BUNDLE_SPEC.md\\` \u2014 this format description.\n\nSensitive entries use JSON encryption envelopes produced by \\`@learncard/sss-key-manager\\` \\`encryptWithPassword\\`: Argon2id key derivation and AES-GCM authenticated encryption. The ZIP itself is not password encrypted.\n\n## Security model\n\nThis bundle exports the wallet's full raw private-key seed at \\`keys/private-key-seed.txt.enc\\`. LearnCard's live wallet protects the key with 2-of-4 Shamir Secret Sharing, where no single share can reconstruct it. The bundle does NOT preserve that threshold: the exported seed alone is sufficient to take full control of the identity, and the bundle password is the only barrier protecting it. \\`keys/recovery-phrase.txt.enc\\` is derived from the current recovery share for reference and is not independently sufficient to recover the key. Treat the bundle like a password-vault backup, use a strong unique password, and rotate the wallet if the bundle is exposed.\n\n## Paths\n\n- \\`keys/recovery-phrase.txt.enc\\`\n- \\`keys/private-key-seed.txt.enc\\`\n- \\`keys/jwks.json.enc\\`\n- \\`keys/did-document.json\\`\n- \\`credentials/<sha256>.json.enc\\`\n- \\`presentations/<sha256>.json.enc\\`\n- \\`index-records/<sha256>.json.enc\\`\n- \\`consent-records/<sha256>.json.enc\\`\n- \\`status-cache/<sha256>.json.enc\\`\n\nDebug exports MAY use plaintext payloads by setting \\`encrypt: false\\`; production exports MUST encrypt sensitive payloads.\n\nStatus-list snapshot fetching is HTTPS-only and rejects private, loopback, link-local, and single-label hosts. Exporters SHOULD keep the default timeout and response-size caps unless they are running in a trusted local environment.\n\n## Manifest hashing\n\nEach \\`contents[]\\` entry contains the SHA-256 hash of the bytes stored at \\`path\\`. \\`payloadSha256\\` is SHA-256 over a deterministic JSON serialization of \\`contents[]\\` with entries sorted by path.\n\nEach credential or presentation entry MAY reference an encrypted \\`index-record\\` companion entry via \\`indexRecordRef\\`; the readable manifest does not embed the original index record JSON.\n\n## Restore vs import\n\n\\`restoreLearnCardFromBundle(...)\\` decrypts \\`keys/private-key-seed.txt.enc\\` and passes that seed to \\`initLearnCard(...)\\`. It recreates the original wallet identity; it does not upload payloads or recreate index records.\n\n\\`importLearnCardBundle(...)\\` decrypts credential and presentation payloads, uploads them to the target wallet's LearnCloud store, and recreates index records from the encrypted \\`index-record\\` companions.\n\nImport writes bundle contents into the target wallet. A bundle author who knows the password can include arbitrary credentials, presentations, and index metadata. Use \\`verifyBeforeImport: true\\` to verify VC/VP signatures before upload when the target wallet exposes \\`invoke.verifyCredential\\` and \\`invoke.verifyPresentation\\`.\n\n## Size limits\n\nReaders enforce default compressed-bundle, per-entry, and JSON parse limits to avoid accidentally processing oversized ZIP or JSON payloads. Callers can override these with \\`maxBundleBytes\\`, \\`maxEntryBytes\\`, and \\`maxJsonBytes\\` for trusted local workflows.\n\n## Import expectations\n\nImporters MUST verify the stored bytes against each entry hash before trusting decrypted content. Importers SHOULD verify issuer signatures before upload and preserve issuer-signed credential and presentation payloads exactly.\n`;\n\nexport const BUNDLE_README_MD = `# LearnCard Holder Continuity Export\n\nThis archive contains a point-in-time holder export from a LearnCard wallet.\n\nKeep the password separately. Without it, encrypted credentials, key material, consent records, and status-list snapshots cannot be recovered.\n\nThis archive contains your full private-key seed (encrypted). Anyone with both this file and its password can take complete control of your wallet identity, so store it like a password-vault backup and rotate your wallet if it is exposed.\n\nThe readable manifest lists every payload and its SHA-256 hash. Third-party wallets can import individual W3C Verifiable Credentials or Verifiable Presentations from the decrypted JSON files even when they do not support the LearnCard ZIP bundle directly.\n`;\n\nexport const sortContents = (\n contents: LearnCardBundleEntryMetadata[]\n): LearnCardBundleEntryMetadata[] => [...contents].sort((a, b) => a.path.localeCompare(b.path));\n\nconst normalizeContents = (\n contents: LearnCardBundleEntryMetadata[]\n): LearnCardBundleEntryMetadata[] =>\n JSON.parse(JSON.stringify(sortContents(contents))) as LearnCardBundleEntryMetadata[];\n\nexport const computePayloadSha256 = (contents: LearnCardBundleEntryMetadata[]): string =>\n sha256Hex(stableStringify(normalizeContents(contents)));\n\nexport const finalizeManifest = (\n manifest: Omit<LearnCardBundleManifest, 'payloadSha256'>\n): LearnCardBundleManifest => ({\n ...manifest,\n contents: normalizeContents(manifest.contents),\n payloadSha256: computePayloadSha256(manifest.contents),\n});\n\nexport const assertValidManifest = (manifest: LearnCardBundleManifest): void => {\n if (manifest.specVersion !== SPEC_VERSION) {\n throw new Error(`Unsupported LearnCard bundle version: ${manifest.specVersion}`);\n }\n\n const expected = computePayloadSha256(manifest.contents);\n\n if (manifest.payloadSha256 !== expected)\n throw new Error('LearnCard bundle manifest hash mismatch');\n};\n", "import { readFile } from 'node:fs/promises';\n\nimport JSZip from 'jszip';\n\nimport type {\n ImportLearnCardBundleOptions,\n ImportLearnCardBundleReport,\n JsonValue,\n LearnCardBundleEntryMetadata,\n LearnCardBundleManifest,\n ReadLearnCardBundleOptions,\n ReadLearnCardBundleResult,\n} from './types';\nimport { assertValidManifest } from './manifest';\nimport { decodePayload, sha256Hex } from './crypto';\n\nconst DEFAULT_MAX_BUNDLE_BYTES = 100 * 1024 * 1024;\nconst DEFAULT_MAX_ENTRY_BYTES = 25 * 1024 * 1024;\nconst DEFAULT_MAX_JSON_BYTES = 25 * 1024 * 1024;\n\nconst byteLength = (content: string): number => Buffer.byteLength(content, 'utf8');\n\nconst assertSize = (label: string, size: number, max: number): void => {\n if (size > max) throw new Error(`${label} exceeds ${max} bytes`);\n};\n\nconst parseJson = (content: string, label: string, maxBytes: number): JsonValue => {\n assertSize(label, byteLength(content), maxBytes);\n\n return JSON.parse(content) as JsonValue;\n};\n\nconst safeMessage = (error: unknown): string =>\n error instanceof Error ? error.message : String(error);\n\nconst parseObject = (content: string, label: string, maxBytes: number): Record<string, unknown> => {\n const value = parseJson(content, label, maxBytes);\n\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error('Expected bundle metadata entry to contain a JSON object');\n }\n\n return value as Record<string, unknown>;\n};\n\nconst isImportableCredentialEntry = (entry: LearnCardBundleEntryMetadata): boolean =>\n entry.type === 'credential' || entry.type === 'presentation';\n\nconst isFailedVerification = (result: unknown): boolean => {\n if (Array.isArray(result)) {\n return result.some(item => {\n if (!item || typeof item !== 'object') return true;\n\n const status = 'status' in item ? item.status : undefined;\n\n return status === 'Failed' || status === 'Error';\n });\n }\n\n if (!result || typeof result !== 'object') return true;\n\n const errors = 'errors' in result ? result.errors : undefined;\n\n return !Array.isArray(errors) || errors.length > 0;\n};\n\nconst verifyImportableEntry = async (\n entry: LearnCardBundleEntryMetadata,\n content: JsonValue,\n options: ImportLearnCardBundleOptions\n): Promise<void> => {\n if (!options.verifyBeforeImport) return;\n\n if (entry.type === 'credential') {\n if (!options.wallet.invoke.verifyCredential) {\n throw new Error('Target wallet does not expose invoke.verifyCredential');\n }\n\n const verification = await options.wallet.invoke.verifyCredential(content);\n\n if (isFailedVerification(verification)) throw new Error('Credential verification failed');\n\n return;\n }\n\n if (!options.wallet.invoke.verifyPresentation) {\n throw new Error('Target wallet does not expose invoke.verifyPresentation');\n }\n\n const verification = await options.wallet.invoke.verifyPresentation(content);\n\n if (isFailedVerification(verification)) throw new Error('Presentation verification failed');\n};\n\nexport const readLearnCardBundleData = async (\n data: Buffer,\n options: ReadLearnCardBundleOptions = {}\n): Promise<ReadLearnCardBundleResult> => {\n const maxBundleBytes = options.maxBundleBytes ?? DEFAULT_MAX_BUNDLE_BYTES;\n const maxEntryBytes = options.maxEntryBytes ?? DEFAULT_MAX_ENTRY_BYTES;\n const maxJsonBytes = options.maxJsonBytes ?? DEFAULT_MAX_JSON_BYTES;\n\n assertSize('LearnCard bundle', data.byteLength, maxBundleBytes);\n\n const zip = await JSZip.loadAsync(data);\n const manifestFile = zip.file('manifest.json');\n\n if (!manifestFile) throw new Error('LearnCard bundle is missing manifest.json');\n\n const manifestContent = await manifestFile.async('string');\n\n assertSize('manifest.json', byteLength(manifestContent), maxJsonBytes);\n\n const manifest = JSON.parse(manifestContent) as LearnCardBundleManifest;\n\n assertValidManifest(manifest);\n\n const warnings = [...manifest.warnings];\n const entries: ReadLearnCardBundleResult['entries'] = [];\n const shouldDecrypt = options.decrypt ?? true;\n let totalEntryBytes = 0;\n\n for (const entry of manifest.contents) {\n const file = zip.file(entry.path);\n\n if (!file) throw new Error(`LearnCard bundle is missing ${entry.path}`);\n\n const stored = await file.async('string');\n const storedBytes = byteLength(stored);\n\n assertSize(entry.path, storedBytes, maxEntryBytes);\n\n totalEntryBytes += storedBytes;\n assertSize('LearnCard bundle entries', totalEntryBytes, maxBundleBytes);\n\n const actualSha = sha256Hex(stored);\n\n if (actualSha !== entry.sha256) {\n throw new Error(`SHA-256 mismatch for ${entry.path}`);\n }\n\n const content = shouldDecrypt\n ? await decodePayload(stored, {\n encrypted: entry.encrypted,\n password: options.password,\n })\n : stored;\n\n assertSize(`${entry.path} content`, byteLength(content), maxEntryBytes);\n\n entries.push({ ...entry, content });\n }\n\n return { manifest, entries, warnings };\n};\n\nexport const readLearnCardBundle = async (\n path: string,\n options: ReadLearnCardBundleOptions = {}\n): Promise<ReadLearnCardBundleResult> => readLearnCardBundleData(await readFile(path), options);\n\nexport const importLearnCardBundle = async (\n path: string,\n options: ImportLearnCardBundleOptions\n): Promise<ImportLearnCardBundleReport> => {\n const bundle = await readLearnCardBundle(path, options);\n const maxJsonBytes = options.maxJsonBytes ?? DEFAULT_MAX_JSON_BYTES;\n const report: ImportLearnCardBundleReport = {\n importedCredentials: 0,\n importedPresentations: 0,\n skipped: 0,\n skippedByType: {},\n errors: [],\n warnings: [...bundle.warnings],\n };\n\n if (!options.verifyBeforeImport) {\n report.warnings.push(\n 'Bundle credential signatures were not verified before import; only import bundles from sources you trust.'\n );\n }\n\n const entriesById = new Map(bundle.entries.map(entry => [entry.id, entry]));\n\n for (const entry of bundle.entries) {\n if (!isImportableCredentialEntry(entry)) {\n report.skipped += 1;\n report.skippedByType[entry.type] = (report.skippedByType[entry.type] ?? 0) + 1;\n continue;\n }\n\n try {\n const content = parseJson(entry.content, entry.path, maxJsonBytes);\n\n await verifyImportableEntry(entry, content, options);\n\n const upload =\n options.wallet.store.LearnCloud.uploadEncrypted ??\n options.wallet.store.LearnCloud.upload;\n\n if (!upload)\n throw new Error('Target wallet does not expose a LearnCloud upload method');\n\n const uri = await upload(content);\n const referencedIndexRecord = entry.indexRecordRef\n ? entriesById.get(entry.indexRecordRef)\n : undefined;\n\n if (entry.indexRecordRef && !referencedIndexRecord) {\n throw new Error(`Referenced index record ${entry.indexRecordRef} is missing`);\n }\n\n const indexRecord = referencedIndexRecord\n ? parseObject(\n referencedIndexRecord.content,\n referencedIndexRecord.path,\n maxJsonBytes\n )\n : { id: entry.id, uri };\n const recordId = typeof indexRecord.id === 'string' ? indexRecord.id : entry.id;\n\n await options.wallet.index.LearnCloud.add({\n ...indexRecord,\n id: recordId,\n uri,\n sourceExport: {\n manifestCreatedAt: bundle.manifest.createdAt,\n sourceUri: entry.sourceUri,\n sourcePath: entry.path,\n credentialId: entry.credentialId,\n },\n });\n\n if (entry.type === 'presentation') report.importedPresentations += 1;\n else report.importedCredentials += 1;\n } catch (error) {\n report.errors.push({ path: entry.path, message: safeMessage(error) });\n }\n }\n\n return report;\n};\n", "import { initLearnCard } from '@learncard/init';\nimport type { InitLearnCard } from '@learncard/init';\n\nimport { readLearnCardBundle, readLearnCardBundleData } from './importBundle';\nimport type { ReadLearnCardBundleOptions, ReadLearnCardBundleResult } from './types';\n\ntype SeededInitConfig = Extract<InitLearnCard['args'], { seed: string }>;\ntype DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;\n\nexport type RestoreLearnCardInit = DistributiveOmit<SeededInitConfig, 'seed'>;\n\nexport type RestoreLearnCardFromBundleOptions = ReadLearnCardBundleOptions & {\n init: RestoreLearnCardInit;\n};\n\nconst getSeedEntry = (bundle: ReadLearnCardBundleResult): string => {\n const seedEntry = bundle.entries.find(entry => entry.type === 'key-private-seed');\n\n if (!seedEntry) {\n throw new Error(\n 'LearnCard bundle does not contain key-private-seed and cannot be restored'\n );\n }\n\n const seed = seedEntry.content.trim();\n\n if (!/^[0-9a-f]{64}$/i.test(seed)) {\n throw new Error(\n 'LearnCard bundle key-private-seed must be exactly 64 hexadecimal characters'\n );\n }\n\n return seed;\n};\n\nexport const readLearnCardBundleSeedData = async (\n data: Buffer,\n options: ReadLearnCardBundleOptions = {}\n): Promise<string> => getSeedEntry(await readLearnCardBundleData(data, options));\n\nexport const readLearnCardBundleSeed = async (\n path: string,\n options: ReadLearnCardBundleOptions = {}\n): Promise<string> => getSeedEntry(await readLearnCardBundle(path, options));\n\nexport const restoreLearnCardFromBundleData = async (\n data: Buffer,\n options: RestoreLearnCardFromBundleOptions\n): Promise<InitLearnCard['returnValue']> => {\n const seed = await readLearnCardBundleSeedData(data, options);\n\n return initLearnCard({ ...options.init, seed } as SeededInitConfig);\n};\n\nexport const restoreLearnCardFromBundle = async (\n path: string,\n options: RestoreLearnCardFromBundleOptions\n): Promise<InitLearnCard['returnValue']> => {\n const seed = await readLearnCardBundleSeed(path, options);\n\n return initLearnCard({ ...options.init, seed } as SeededInitConfig);\n};\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["export { createLearnCardBundle, exportLearnCardBundle } from './exportBundle';\nexport {\n importLearnCardBundle,\n readLearnCardBundle,\n readLearnCardBundleData,\n} from './importBundle';\nexport { assertValidManifest, computePayloadSha256, finalizeManifest } from './manifest';\nexport {\n readLearnCardBundleSeed,\n readLearnCardBundleSeedData,\n restoreLearnCardFromBundle,\n restoreLearnCardFromBundleData,\n} from './restoreBundle';\nexport type {\n ExportLearnCardBundleOptions,\n ImportLearnCardBundleOptions,\n ImportLearnCardBundleReport,\n LearnCardBundleManifest,\n LearnCardBundleOptions,\n LearnCardBundleResult,\n LearnCardBundleWallet,\n ReadLearnCardBundleOptions,\n ReadLearnCardBundleResult,\n} from './types';\nexport type { RestoreLearnCardFromBundleOptions, RestoreLearnCardInit } from './restoreBundle';\n", "import { lookup } from 'node:dns/promises';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { isIP } from 'node:net';\nimport { dirname } from 'node:path';\n\nimport JSZip from 'jszip';\nimport { shareToRecoveryPhrase, splitPrivateKey } from '@learncard/sss-key-manager';\n\nimport type {\n BundleContentType,\n ExportLearnCardBundleOptions,\n JsonValue,\n LearnCardBundleEntryMetadata,\n LearnCardBundleOptions,\n LearnCardBundleResult,\n LearnCardBundleWallet,\n} from './types';\nimport { BUNDLE_README_MD, BUNDLE_SPEC_MD, finalizeManifest, SPEC_VERSION } from './manifest';\nimport { encodePayload, sha256Hex, stableStringify } from './crypto';\n\nconst ZIP_DATE = new Date('2024-01-01T00:00:00.000Z');\n\nconst DEFAULT_STATUS_LIST_FETCH_TIMEOUT_MS = 5000;\nconst DEFAULT_MAX_STATUS_LIST_BYTES = 5 * 1024 * 1024;\n\nconst stripIpv6Brackets = (hostname: string): string =>\n hostname.startsWith('[') && hostname.endsWith(']') ? hostname.slice(1, -1) : hostname;\n\nconst redactMalformedUrl = (value: string): string => {\n const queryIndex = value.indexOf('?');\n const ampIndex = value.indexOf('&');\n\n if (queryIndex === -1 && ampIndex === -1) return value;\n\n const redactionIndex =\n queryIndex === -1\n ? ampIndex\n : ampIndex === -1\n ? queryIndex\n : Math.min(queryIndex, ampIndex);\n\n return `${value.slice(0, redactionIndex)}?[redacted]`;\n};\n\nconst redactUrl = (value: string): string => {\n try {\n const url = new URL(value);\n const hostname = stripIpv6Brackets(url.hostname.toLowerCase());\n const shouldRedactHost =\n !hostname.includes('.') ||\n hostname === 'localhost' ||\n hostname.endsWith('.localhost') ||\n Boolean(isIP(hostname) && isPrivateAddress(hostname));\n const host = shouldRedactHost ? '[redacted-host]' : url.host;\n\n return `${url.protocol}//${host}${url.pathname}${url.search ? '?[redacted]' : ''}`;\n } catch {\n return redactMalformedUrl(value);\n }\n};\n\nconst urlEndDelimiters = new Set([' ', '\\n', '\\r', '\\t', \"'\", '\"', '<', '>']);\n\nconst findNextUrlStart = (value: string, fromIndex: number): number => {\n const httpIndex = value.indexOf('http://', fromIndex);\n const httpsIndex = value.indexOf('https://', fromIndex);\n\n if (httpIndex === -1) return httpsIndex;\n if (httpsIndex === -1) return httpIndex;\n\n return Math.min(httpIndex, httpsIndex);\n};\n\nconst findUrlEnd = (value: string, fromIndex: number): number => {\n let index = fromIndex;\n\n while (index < value.length && !urlEndDelimiters.has(value[index]!)) index += 1;\n\n return index;\n};\n\nconst redactText = (value: string): string => {\n let redacted = '';\n let index = 0;\n\n while (index < value.length) {\n const urlStart = findNextUrlStart(value, index);\n\n if (urlStart === -1) {\n redacted += value.slice(index);\n break;\n }\n\n const urlEnd = findUrlEnd(value, urlStart);\n\n redacted += value.slice(index, urlStart);\n redacted += redactUrl(value.slice(urlStart, urlEnd));\n index = urlEnd;\n }\n\n return redacted;\n};\n\nconst safeMessage = (error: unknown): string =>\n redactText(error instanceof Error ? error.message : String(error));\n\nconst isPrivateIPv4 = (address: string): boolean => {\n const parts = address.split('.').map(part => Number(part));\n\n if (parts.length !== 4 || parts.some(part => !Number.isInteger(part) || part < 0 || part > 255))\n return true;\n\n const [a, b] = parts;\n\n if (a === 0 || a === 10 || a === 127 || a >= 224) return true;\n if (a === 100 && b >= 64 && b <= 127) return true;\n if (a === 169 && b === 254) return true;\n if (a === 172 && b >= 16 && b <= 31) return true;\n if (a === 192 && b === 168) return true;\n if (a === 198 && (b === 18 || b === 19)) return true;\n\n return false;\n};\n\nconst isPrivateIPv6 = (address: string): boolean => {\n const normalized = address.toLowerCase();\n\n if (normalized === '::' || normalized === '::1') return true;\n if (normalized.startsWith('fc') || normalized.startsWith('fd')) return true;\n if (\n normalized.startsWith('fe8') ||\n normalized.startsWith('fe9') ||\n normalized.startsWith('fea') ||\n normalized.startsWith('feb')\n )\n return true;\n\n const ipv4Mapped = normalized.match(/::ffff:(\\d+\\.\\d+\\.\\d+\\.\\d+)$/);\n\n return ipv4Mapped ? isPrivateIPv4(ipv4Mapped[1]!) : false;\n};\n\nconst isPrivateAddress = (address: string): boolean => {\n const version = isIP(address);\n\n if (version === 4) return isPrivateIPv4(address);\n if (version === 6) return isPrivateIPv6(address);\n\n return true;\n};\n\nconst assertPublicHttpsUrl = async (uri: string): Promise<URL> => {\n const url = new URL(uri);\n const hostname = url.hostname.toLowerCase().replace(/^\\[|\\]$/g, '');\n\n if (url.protocol !== 'https:') throw new Error('status-list URL must use https');\n if (!hostname.includes('.') || hostname === 'localhost' || hostname.endsWith('.localhost')) {\n throw new Error('status-list URL host must be public');\n }\n\n if (isIP(hostname)) {\n if (isPrivateAddress(hostname)) throw new Error('status-list URL host must be public');\n\n return url;\n }\n\n const addresses = await lookup(hostname, { all: true, verbatim: true });\n\n if (addresses.length === 0 || addresses.some(address => isPrivateAddress(address.address))) {\n throw new Error('status-list URL host must resolve to public addresses');\n }\n\n return url;\n};\n\nconst readResponseText = async (response: Response, maxBytes: number): Promise<string> => {\n const contentLength = Number(response.headers.get('content-length'));\n\n if (Number.isFinite(contentLength) && contentLength > maxBytes) {\n throw new Error(`status-list response exceeds ${maxBytes} bytes`);\n }\n\n if (!response.body) {\n const text = await response.text();\n\n if (Buffer.byteLength(text, 'utf8') > maxBytes) {\n throw new Error(`status-list response exceeds ${maxBytes} bytes`);\n }\n\n return text;\n }\n\n const reader = response.body.getReader();\n const chunks: Buffer[] = [];\n let total = 0;\n\n while (true) {\n const { done, value } = await reader.read();\n\n if (done) break;\n\n total += value.byteLength;\n\n if (total > maxBytes) {\n await reader.cancel();\n\n throw new Error(`status-list response exceeds ${maxBytes} bytes`);\n }\n\n chunks.push(Buffer.from(value));\n }\n\n return Buffer.concat(chunks).toString('utf8');\n};\n\nconst fetchJsonWithTimeout = async (\n url: URL,\n timeoutMs: number,\n maxBytes: number\n): Promise<JsonValue> => {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n const response = await fetch(url, { signal: controller.signal });\n\n if (!response.ok) throw new Error(`HTTP ${response.status}`);\n\n return JSON.parse(await readResponseText(response, maxBytes)) as JsonValue;\n } finally {\n clearTimeout(timeout);\n }\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n Boolean(value) && typeof value === 'object' && !Array.isArray(value);\n\nconst stringArrayIncludes = (value: unknown, expected: string): boolean =>\n Array.isArray(value) && value.some(item => item === expected);\n\nconst json = (value: unknown): string => `${stableStringify(value)}\\n`;\n\nconst classifyPayload = (payload: JsonValue): BundleContentType => {\n if (!isRecord(payload)) return 'unknown-json';\n\n if (\n stringArrayIncludes(payload.type, 'VerifiablePresentation') ||\n payload.type === 'VerifiablePresentation'\n ) {\n return 'presentation';\n }\n\n if (\n stringArrayIncludes(payload.type, 'VerifiableCredential') ||\n payload.type === 'VerifiableCredential'\n ) {\n return 'credential';\n }\n\n return 'unknown-json';\n};\n\nconst pathForType = (type: BundleContentType, digest: string, encrypted: boolean): string => {\n const suffix = encrypted ? '.enc' : '';\n\n if (type === 'presentation') return `presentations/${digest}.json${suffix}`;\n\n if (type === 'consent-record') return `consent-records/${digest}.json${suffix}`;\n\n if (type === 'index-record') return `index-records/${digest}.json${suffix}`;\n if (type === 'status-cache') return `status-cache/${digest}.json${suffix}`;\n\n return `credentials/${digest}.json${suffix}`;\n};\n\nconst getCredentialId = (payload: JsonValue): string | undefined =>\n isRecord(payload) && typeof payload.id === 'string' ? payload.id : undefined;\n\nconst addZipText = (zip: JSZip, path: string, content: string): void => {\n zip.file(path, content, { date: ZIP_DATE });\n};\n\nconst collectDids = (wallet: LearnCardBundleWallet, warnings: string[]): Record<string, string> => {\n const dids: Record<string, string> = {};\n\n for (const method of [undefined, 'key', 'pkh:sol', 'tz', 'pkh:tz']) {\n try {\n dids[method ?? 'default'] = wallet.id.did(method);\n } catch (error) {\n warnings.push(\n `Could not derive DID method ${method ?? 'default'}: ${safeMessage(error)}`\n );\n }\n }\n\n return dids;\n};\n\nconst collectDidDocument = async (\n wallet: LearnCardBundleWallet,\n primaryDid: string,\n dids: Record<string, string>,\n warnings: string[]\n): Promise<JsonValue> => {\n if (!wallet.invoke.resolveDid) return { primaryDid, dids };\n\n try {\n return { primaryDid, dids, primaryDidDocument: await wallet.invoke.resolveDid(primaryDid) };\n } catch (error) {\n warnings.push(`Could not resolve primary DID document: ${safeMessage(error)}`);\n\n return { primaryDid, dids };\n }\n};\n\nconst collectKeyPayloads = async (\n wallet: LearnCardBundleWallet,\n warnings: string[]\n): Promise<\n Array<{ path: string; type: BundleContentType; content: string; encrypted: boolean }>\n> => {\n const payloads: Array<{\n path: string;\n type: BundleContentType;\n content: string;\n encrypted: boolean;\n }> = [];\n\n if (wallet.invoke.getKey) {\n try {\n const seed = wallet.invoke.getKey();\n const shares = await splitPrivateKey(seed);\n\n payloads.push({\n path: 'keys/private-key-seed.txt',\n type: 'key-private-seed',\n content: `${seed}\\n`,\n encrypted: true,\n });\n\n payloads.push({\n path: 'keys/recovery-phrase.txt',\n type: 'key-recovery-phrase',\n content: `${await shareToRecoveryPhrase(shares.recoveryShare)}\\n`,\n encrypted: true,\n });\n } catch (error) {\n warnings.push(`Could not export seed or recovery phrase: ${safeMessage(error)}`);\n }\n } else {\n warnings.push(\n 'Wallet does not expose invoke.getKey(); private seed and recovery phrase were not exported'\n );\n }\n\n if (wallet.id.keypair) {\n const jwks: Record<string, JsonValue> = {};\n\n for (const algorithm of ['ed25519', 'secp256k1'] as const) {\n try {\n jwks[algorithm] = wallet.id.keypair(algorithm);\n } catch (error) {\n warnings.push(`Could not export ${algorithm} JWK: ${safeMessage(error)}`);\n }\n }\n\n if (Object.keys(jwks).length > 0) {\n payloads.push({\n path: 'keys/jwks.json',\n type: 'key-jwks',\n content: json(jwks),\n encrypted: true,\n });\n }\n } else {\n warnings.push('Wallet does not expose id.keypair(); JWK key export was skipped');\n }\n\n return payloads;\n};\n\nconst extractStatusListUrls = (payload: JsonValue): string[] => {\n if (!isRecord(payload)) return [];\n\n const statuses = Array.isArray(payload.credentialStatus)\n ? payload.credentialStatus\n : payload.credentialStatus\n ? [payload.credentialStatus]\n : [];\n\n return statuses.flatMap(status =>\n isRecord(status) && typeof status.statusListCredential === 'string'\n ? [status.statusListCredential]\n : []\n );\n};\n\nconst collectStatusLists = async (\n payloads: JsonValue[],\n enabled: boolean,\n warnings: string[],\n timeoutMs = DEFAULT_STATUS_LIST_FETCH_TIMEOUT_MS,\n maxBytes = DEFAULT_MAX_STATUS_LIST_BYTES\n): Promise<Array<{ uri: string; content: JsonValue }>> => {\n if (!enabled) return [];\n\n const urls = [...new Set(payloads.flatMap(extractStatusListUrls))];\n const results: Array<{ uri: string; content: JsonValue }> = [];\n\n for (const uri of urls) {\n try {\n const url = await assertPublicHttpsUrl(uri);\n\n results.push({ uri, content: await fetchJsonWithTimeout(url, timeoutMs, maxBytes) });\n } catch (error) {\n warnings.push(\n `Could not cache status-list credential ${redactUrl(uri)}: ${safeMessage(error)}`\n );\n }\n }\n\n return results;\n};\n\nconst collectConsentRecords = async (\n wallet: LearnCardBundleWallet,\n warnings: string[]\n): Promise<JsonValue[]> => {\n if (wallet.invoke.getHolderExportMetadata) {\n try {\n const metadata = await wallet.invoke.getHolderExportMetadata();\n\n if (isRecord(metadata) && Array.isArray(metadata.warnings)) {\n warnings.push(\n ...metadata.warnings\n .filter(warning => typeof warning === 'string')\n .map(warning => redactText(warning))\n );\n }\n\n return isRecord(metadata) && Array.isArray(metadata.consentRecords)\n ? (metadata.consentRecords as JsonValue[])\n : [];\n } catch (error) {\n warnings.push(`Could not fetch holder export metadata: ${safeMessage(error)}`);\n }\n }\n\n if (!wallet.invoke.getConsentedContracts) return [];\n\n try {\n const response = await wallet.invoke.getConsentedContracts();\n\n if (!isRecord(response) || !Array.isArray(response.records)) return [];\n\n return response.records as JsonValue[];\n } catch (error) {\n warnings.push(`Could not fetch consented contracts fallback: ${safeMessage(error)}`);\n\n return [];\n }\n};\n\nexport const createLearnCardBundle = async (\n wallet: LearnCardBundleWallet,\n options: LearnCardBundleOptions = {}\n): Promise<LearnCardBundleResult> => {\n const encrypt = options.encrypt ?? true;\n\n if (encrypt && !options.password)\n throw new Error('A password is required for LearnCard export');\n\n const warnings: string[] = [];\n const zip = new JSZip();\n const contents: LearnCardBundleEntryMetadata[] = [];\n const primaryDid = wallet.id.did();\n const dids = collectDids(wallet, warnings);\n const didDocument = await collectDidDocument(wallet, primaryDid, dids, warnings);\n const credentialPayloads: JsonValue[] = [];\n\n const addStoredEntry = async (entry: {\n id: string;\n type: BundleContentType;\n path: string;\n content: string;\n encrypted: boolean;\n mediaType?: string;\n sourceUri?: string;\n credentialId?: string;\n indexRecordRef?: string;\n warnings?: string[];\n }): Promise<void> => {\n const encoded = await encodePayload(entry.content, {\n encrypt: entry.encrypted && encrypt,\n password: options.password,\n });\n const path =\n encoded.encrypted && !entry.path.endsWith('.enc') ? `${entry.path}.enc` : entry.path;\n\n addZipText(zip, path, encoded.stored);\n\n contents.push({\n id: entry.id,\n type: entry.type,\n path,\n mediaType: entry.mediaType ?? 'application/json',\n sha256: sha256Hex(encoded.stored),\n encrypted: encoded.encrypted,\n sourceUri: entry.sourceUri,\n credentialId: entry.credentialId,\n indexRecordRef: entry.indexRecordRef,\n warnings: entry.warnings,\n });\n };\n\n addZipText(zip, 'README.md', BUNDLE_README_MD);\n addZipText(zip, 'BUNDLE_SPEC.md', BUNDLE_SPEC_MD);\n\n await addStoredEntry({\n id: 'did-document',\n type: 'did-document',\n path: 'keys/did-document.json',\n content: json(didDocument),\n encrypted: false,\n });\n\n for (const payload of await collectKeyPayloads(wallet, warnings)) {\n await addStoredEntry({ ...payload, id: payload.path, mediaType: 'text/plain' });\n }\n\n const records = await wallet.index.LearnCloud.get();\n\n for (const [recordIndex, record] of records.entries()) {\n const entryWarnings: string[] = [];\n const digest = sha256Hex(\n stableStringify({ recordIndex, id: record.id ?? null, uri: record.uri ?? null })\n );\n\n try {\n const resolved = await wallet.read.get(record.uri);\n\n if (!resolved) {\n warnings.push(`Could not resolve wallet index URI ${redactUrl(record.uri)}`);\n continue;\n }\n\n credentialPayloads.push(resolved);\n const type = classifyPayload(resolved);\n const credentialId = getCredentialId(resolved);\n if (type === 'unknown-json') entryWarnings.push('Payload is not a recognized VC or VP');\n\n const indexRecordId = `urn:sha256:${digest}:index-record`;\n\n await addStoredEntry({\n id: indexRecordId,\n type: 'index-record',\n path: pathForType('index-record', digest, encrypt),\n content: json(record),\n encrypted: true,\n sourceUri: record.uri,\n credentialId,\n });\n\n await addStoredEntry({\n id: `urn:sha256:${digest}`,\n type,\n path: pathForType(type, digest, encrypt),\n content: json(resolved),\n encrypted: true,\n sourceUri: record.uri,\n credentialId,\n indexRecordRef: indexRecordId,\n warnings: entryWarnings.length > 0 ? entryWarnings : undefined,\n });\n } catch (error) {\n warnings.push(\n `Could not export wallet index URI ${redactUrl(record.uri)}: ${safeMessage(error)}`\n );\n }\n }\n\n const consentRecords = await collectConsentRecords(wallet, warnings);\n\n for (const consentRecord of consentRecords) {\n const digest = sha256Hex(stableStringify(consentRecord));\n\n await addStoredEntry({\n id: `urn:sha256:${digest}`,\n type: 'consent-record',\n path: pathForType('consent-record', digest, encrypt),\n content: json(consentRecord),\n encrypted: true,\n });\n }\n\n for (const statusList of await collectStatusLists(\n credentialPayloads,\n options.fetchStatusLists ?? true,\n warnings,\n options.statusListFetchTimeoutMs,\n options.maxStatusListBytes\n )) {\n const digest = sha256Hex(statusList.uri);\n\n await addStoredEntry({\n id: `urn:sha256:${digest}`,\n type: 'status-cache',\n path: pathForType('status-cache', digest, encrypt),\n content: json(statusList.content),\n encrypted: true,\n sourceUri: statusList.uri,\n });\n }\n\n const manifest = finalizeManifest({\n specVersion: SPEC_VERSION,\n createdAt: options.createdAt ?? new Date().toISOString(),\n primaryDid,\n walletName: 'LearnCard',\n encryption: encrypt\n ? {\n mode: 'argon2id-aes-256-gcm',\n encryptedPayloads: true,\n envelope: 'sss-key-manager-encryptWithPassword-v1',\n kdf: 'argon2id',\n cipher: 'AES-256-GCM',\n }\n : { mode: 'none', encryptedPayloads: false },\n contents,\n warnings,\n });\n\n addZipText(zip, 'manifest.json', `${JSON.stringify(manifest, null, 2)}\\n`);\n\n return {\n data: await zip.generateAsync({ type: 'nodebuffer', compression: 'DEFLATE' }),\n manifest,\n warnings,\n };\n};\n\nexport const exportLearnCardBundle = async (\n wallet: LearnCardBundleWallet,\n options: ExportLearnCardBundleOptions\n): Promise<LearnCardBundleResult> => {\n const bundle = await createLearnCardBundle(wallet, options);\n\n await mkdir(dirname(options.out), { recursive: true });\n await writeFile(options.out, bundle.data);\n\n return bundle;\n};\n", "import { createHash } from 'node:crypto';\n\nimport { decryptWithPassword, encryptWithPassword } from '@learncard/sss-key-manager';\n\nimport type { EncryptedPayloadEnvelope } from './types';\n\nexport const sha256Hex = (bytes: string | Buffer): string =>\n createHash('sha256').update(bytes).digest('hex');\n\nexport const stableStringify = (value: unknown): string => {\n if (value === null || typeof value !== 'object') return JSON.stringify(value);\n\n if (Array.isArray(value)) return `[${value.map(stableStringify).join(',')}]`;\n\n const object = value as Record<string, unknown>;\n\n return `{${Object.keys(object)\n .sort()\n .map(key => `${JSON.stringify(key)}:${stableStringify(object[key])}`)\n .join(',')}}`;\n};\n\nexport const encodePayload = async (\n plaintext: string,\n options: { encrypt: boolean; password?: string }\n): Promise<{ stored: string; encrypted: boolean }> => {\n if (!options.encrypt) return { stored: plaintext, encrypted: false };\n\n if (!options.password)\n throw new Error('A password is required for encrypted LearnCard exports');\n\n return {\n stored: JSON.stringify(await encryptWithPassword(plaintext, options.password), null, 2),\n encrypted: true,\n };\n};\n\nexport const decodePayload = async (\n stored: string,\n options: { encrypted: boolean; password?: string }\n): Promise<string> => {\n if (!options.encrypted) return stored;\n\n if (!options.password)\n throw new Error('A password is required to decrypt this LearnCard export');\n\n const envelope = JSON.parse(stored) as EncryptedPayloadEnvelope;\n\n return decryptWithPassword(\n envelope.ciphertext,\n envelope.iv,\n envelope.salt,\n options.password,\n envelope.kdfParams\n );\n};\n", "import type { LearnCardBundleEntryMetadata, LearnCardBundleManifest } from './types';\nimport { stableStringify, sha256Hex } from './crypto';\n\nexport const SPEC_VERSION = '1.0.0' as const;\n\nexport const BUNDLE_SPEC_MD = `# LearnCard Holder Continuity Bundle v1.0.0\n\nA LearnCard holder continuity bundle is a ZIP file with readable metadata and encrypted holder payloads.\n\n## Container\n\nRequired readable entries:\n\n- \\`manifest.json\\` \u2014 inventory, hashes, warnings, and encryption metadata.\n- \\`README.md\\` \u2014 human-readable recovery notes.\n- \\`BUNDLE_SPEC.md\\` \u2014 this format description.\n\nSensitive entries use JSON encryption envelopes produced by \\`@learncard/sss-key-manager\\` \\`encryptWithPassword\\`: Argon2id key derivation and AES-GCM authenticated encryption. The ZIP itself is not password encrypted.\n\n## Security model\n\nThis bundle exports the wallet's full raw private-key seed at \\`keys/private-key-seed.txt.enc\\`. LearnCard's live wallet protects the key with 2-of-4 Shamir Secret Sharing, where no single share can reconstruct it. The bundle does NOT preserve that threshold: the exported seed alone is sufficient to take full control of the identity, and the bundle password is the only barrier protecting it. \\`keys/recovery-phrase.txt.enc\\` is derived from the current recovery share for reference and is not independently sufficient to recover the key. Treat the bundle like a password-vault backup, use a strong unique password, and rotate the wallet if the bundle is exposed.\n\n## Paths\n\n- \\`keys/recovery-phrase.txt.enc\\`\n- \\`keys/private-key-seed.txt.enc\\`\n- \\`keys/jwks.json.enc\\`\n- \\`keys/did-document.json\\`\n- \\`credentials/<sha256>.json.enc\\`\n- \\`presentations/<sha256>.json.enc\\`\n- \\`index-records/<sha256>.json.enc\\`\n- \\`consent-records/<sha256>.json.enc\\`\n- \\`status-cache/<sha256>.json.enc\\`\n\nDebug exports MAY use plaintext payloads by setting \\`encrypt: false\\`; production exports MUST encrypt sensitive payloads.\n\nStatus-list snapshot fetching is HTTPS-only and rejects private, loopback, link-local, and single-label hosts. Exporters SHOULD keep the default timeout and response-size caps unless they are running in a trusted local environment.\n\n## Manifest hashing\n\nEach \\`contents[]\\` entry contains the SHA-256 hash of the bytes stored at \\`path\\`. \\`payloadSha256\\` is SHA-256 over a deterministic JSON serialization of \\`contents[]\\` with entries sorted by path.\n\nEach credential or presentation entry MAY reference an encrypted \\`index-record\\` companion entry via \\`indexRecordRef\\`; the readable manifest does not embed the original index record JSON.\n\n## Restore vs import\n\n\\`restoreLearnCardFromBundle(...)\\` decrypts \\`keys/private-key-seed.txt.enc\\` and passes that seed to \\`initLearnCard(...)\\`. It recreates the original wallet identity; it does not upload payloads or recreate index records.\n\n\\`importLearnCardBundle(...)\\` decrypts credential and presentation payloads, uploads them to the target wallet's LearnCloud store, and recreates index records from the encrypted \\`index-record\\` companions.\n\nImport writes bundle contents into the target wallet. A bundle author who knows the password can include arbitrary credentials, presentations, and index metadata. Use \\`verifyBeforeImport: true\\` to verify VC/VP signatures before upload when the target wallet exposes \\`invoke.verifyCredential\\` and \\`invoke.verifyPresentation\\`.\n\n## Size limits\n\nReaders enforce default compressed-bundle, per-entry, and JSON parse limits to avoid accidentally processing oversized ZIP or JSON payloads. Callers can override these with \\`maxBundleBytes\\`, \\`maxEntryBytes\\`, and \\`maxJsonBytes\\` for trusted local workflows.\n\n## Import expectations\n\nImporters MUST verify the stored bytes against each entry hash before trusting decrypted content. Importers SHOULD verify issuer signatures before upload and preserve issuer-signed credential and presentation payloads exactly.\n`;\n\nexport const BUNDLE_README_MD = `# LearnCard Holder Continuity Export\n\nThis archive contains a point-in-time holder export from a LearnCard wallet.\n\nKeep the password separately. Without it, encrypted credentials, key material, consent records, and status-list snapshots cannot be recovered.\n\nThis archive contains your full private-key seed (encrypted). Anyone with both this file and its password can take complete control of your wallet identity, so store it like a password-vault backup and rotate your wallet if it is exposed.\n\nThe readable manifest lists every payload and its SHA-256 hash. Third-party wallets can import individual W3C Verifiable Credentials or Verifiable Presentations from the decrypted JSON files even when they do not support the LearnCard ZIP bundle directly.\n`;\n\nexport const sortContents = (\n contents: LearnCardBundleEntryMetadata[]\n): LearnCardBundleEntryMetadata[] => [...contents].sort((a, b) => a.path.localeCompare(b.path));\n\nconst normalizeContents = (\n contents: LearnCardBundleEntryMetadata[]\n): LearnCardBundleEntryMetadata[] =>\n JSON.parse(JSON.stringify(sortContents(contents))) as LearnCardBundleEntryMetadata[];\n\nexport const computePayloadSha256 = (contents: LearnCardBundleEntryMetadata[]): string =>\n sha256Hex(stableStringify(normalizeContents(contents)));\n\nexport const finalizeManifest = (\n manifest: Omit<LearnCardBundleManifest, 'payloadSha256'>\n): LearnCardBundleManifest => ({\n ...manifest,\n contents: normalizeContents(manifest.contents),\n payloadSha256: computePayloadSha256(manifest.contents),\n});\n\nexport const assertValidManifest = (manifest: LearnCardBundleManifest): void => {\n if (manifest.specVersion !== SPEC_VERSION) {\n throw new Error(`Unsupported LearnCard bundle version: ${manifest.specVersion}`);\n }\n\n const expected = computePayloadSha256(manifest.contents);\n\n if (manifest.payloadSha256 !== expected)\n throw new Error('LearnCard bundle manifest hash mismatch');\n};\n", "import { readFile } from 'node:fs/promises';\n\nimport JSZip from 'jszip';\n\nimport type {\n ImportLearnCardBundleOptions,\n ImportLearnCardBundleReport,\n JsonValue,\n LearnCardBundleEntryMetadata,\n LearnCardBundleManifest,\n ReadLearnCardBundleOptions,\n ReadLearnCardBundleResult,\n} from './types';\nimport { assertValidManifest } from './manifest';\nimport { decodePayload, sha256Hex } from './crypto';\n\nconst DEFAULT_MAX_BUNDLE_BYTES = 100 * 1024 * 1024;\nconst DEFAULT_MAX_ENTRY_BYTES = 25 * 1024 * 1024;\nconst DEFAULT_MAX_JSON_BYTES = 25 * 1024 * 1024;\n\nconst byteLength = (content: string): number => Buffer.byteLength(content, 'utf8');\n\nconst assertSize = (label: string, size: number, max: number): void => {\n if (size > max) throw new Error(`${label} exceeds ${max} bytes`);\n};\n\nconst parseJson = (content: string, label: string, maxBytes: number): JsonValue => {\n assertSize(label, byteLength(content), maxBytes);\n\n return JSON.parse(content) as JsonValue;\n};\n\nconst safeMessage = (error: unknown): string =>\n error instanceof Error ? error.message : String(error);\n\nconst parseObject = (content: string, label: string, maxBytes: number): Record<string, unknown> => {\n const value = parseJson(content, label, maxBytes);\n\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error('Expected bundle metadata entry to contain a JSON object');\n }\n\n return value as Record<string, unknown>;\n};\n\nconst isImportableCredentialEntry = (entry: LearnCardBundleEntryMetadata): boolean =>\n entry.type === 'credential' || entry.type === 'presentation';\n\nconst isFailedVerification = (result: unknown): boolean => {\n if (Array.isArray(result)) {\n return result.some(item => {\n if (!item || typeof item !== 'object') return true;\n\n const status = 'status' in item ? item.status : undefined;\n\n return status === 'Failed' || status === 'Error';\n });\n }\n\n if (!result || typeof result !== 'object') return true;\n\n const errors = 'errors' in result ? result.errors : undefined;\n\n return !Array.isArray(errors) || errors.length > 0;\n};\n\nconst verifyImportableEntry = async (\n entry: LearnCardBundleEntryMetadata,\n content: JsonValue,\n options: ImportLearnCardBundleOptions\n): Promise<void> => {\n if (!options.verifyBeforeImport) return;\n\n if (entry.type === 'credential') {\n if (!options.wallet.invoke.verifyCredential) {\n throw new Error('Target wallet does not expose invoke.verifyCredential');\n }\n\n const verification = await options.wallet.invoke.verifyCredential(content);\n\n if (isFailedVerification(verification)) throw new Error('Credential verification failed');\n\n return;\n }\n\n if (!options.wallet.invoke.verifyPresentation) {\n throw new Error('Target wallet does not expose invoke.verifyPresentation');\n }\n\n const verification = await options.wallet.invoke.verifyPresentation(content);\n\n if (isFailedVerification(verification)) throw new Error('Presentation verification failed');\n};\n\nexport const readLearnCardBundleData = async (\n data: Buffer,\n options: ReadLearnCardBundleOptions = {}\n): Promise<ReadLearnCardBundleResult> => {\n const maxBundleBytes = options.maxBundleBytes ?? DEFAULT_MAX_BUNDLE_BYTES;\n const maxEntryBytes = options.maxEntryBytes ?? DEFAULT_MAX_ENTRY_BYTES;\n const maxJsonBytes = options.maxJsonBytes ?? DEFAULT_MAX_JSON_BYTES;\n\n assertSize('LearnCard bundle', data.byteLength, maxBundleBytes);\n\n const zip = await JSZip.loadAsync(data);\n const manifestFile = zip.file('manifest.json');\n\n if (!manifestFile) throw new Error('LearnCard bundle is missing manifest.json');\n\n const manifestContent = await manifestFile.async('string');\n\n assertSize('manifest.json', byteLength(manifestContent), maxJsonBytes);\n\n const manifest = JSON.parse(manifestContent) as LearnCardBundleManifest;\n\n assertValidManifest(manifest);\n\n const warnings = [...manifest.warnings];\n const entries: ReadLearnCardBundleResult['entries'] = [];\n const shouldDecrypt = options.decrypt ?? true;\n let totalEntryBytes = 0;\n\n for (const entry of manifest.contents) {\n const file = zip.file(entry.path);\n\n if (!file) throw new Error(`LearnCard bundle is missing ${entry.path}`);\n\n const stored = await file.async('string');\n const storedBytes = byteLength(stored);\n\n assertSize(entry.path, storedBytes, maxEntryBytes);\n\n totalEntryBytes += storedBytes;\n assertSize('LearnCard bundle entries', totalEntryBytes, maxBundleBytes);\n\n const actualSha = sha256Hex(stored);\n\n if (actualSha !== entry.sha256) {\n throw new Error(`SHA-256 mismatch for ${entry.path}`);\n }\n\n const content = shouldDecrypt\n ? await decodePayload(stored, {\n encrypted: entry.encrypted,\n password: options.password,\n })\n : stored;\n\n assertSize(`${entry.path} content`, byteLength(content), maxEntryBytes);\n\n entries.push({ ...entry, content });\n }\n\n return { manifest, entries, warnings };\n};\n\nexport const readLearnCardBundle = async (\n path: string,\n options: ReadLearnCardBundleOptions = {}\n): Promise<ReadLearnCardBundleResult> => readLearnCardBundleData(await readFile(path), options);\n\nexport const importLearnCardBundle = async (\n path: string,\n options: ImportLearnCardBundleOptions\n): Promise<ImportLearnCardBundleReport> => {\n const bundle = await readLearnCardBundle(path, options);\n const maxJsonBytes = options.maxJsonBytes ?? DEFAULT_MAX_JSON_BYTES;\n const report: ImportLearnCardBundleReport = {\n importedCredentials: 0,\n importedPresentations: 0,\n skipped: 0,\n skippedByType: {},\n errors: [],\n warnings: [...bundle.warnings],\n };\n\n if (!options.verifyBeforeImport) {\n report.warnings.push(\n 'Bundle credential signatures were not verified before import; only import bundles from sources you trust.'\n );\n }\n\n const entriesById = new Map(bundle.entries.map(entry => [entry.id, entry]));\n\n for (const entry of bundle.entries) {\n if (!isImportableCredentialEntry(entry)) {\n report.skipped += 1;\n report.skippedByType[entry.type] = (report.skippedByType[entry.type] ?? 0) + 1;\n continue;\n }\n\n try {\n const content = parseJson(entry.content, entry.path, maxJsonBytes);\n\n await verifyImportableEntry(entry, content, options);\n\n const upload =\n options.wallet.store.LearnCloud.uploadEncrypted ??\n options.wallet.store.LearnCloud.upload;\n\n if (!upload)\n throw new Error('Target wallet does not expose a LearnCloud upload method');\n\n const uri = await upload(content);\n const referencedIndexRecord = entry.indexRecordRef\n ? entriesById.get(entry.indexRecordRef)\n : undefined;\n\n if (entry.indexRecordRef && !referencedIndexRecord) {\n throw new Error(`Referenced index record ${entry.indexRecordRef} is missing`);\n }\n\n const indexRecord = referencedIndexRecord\n ? parseObject(\n referencedIndexRecord.content,\n referencedIndexRecord.path,\n maxJsonBytes\n )\n : { id: entry.id, uri };\n const recordId = typeof indexRecord.id === 'string' ? indexRecord.id : entry.id;\n\n await options.wallet.index.LearnCloud.add({\n ...indexRecord,\n id: recordId,\n uri,\n sourceExport: {\n manifestCreatedAt: bundle.manifest.createdAt,\n sourceUri: entry.sourceUri,\n sourcePath: entry.path,\n credentialId: entry.credentialId,\n },\n });\n\n if (entry.type === 'presentation') report.importedPresentations += 1;\n else report.importedCredentials += 1;\n } catch (error) {\n report.errors.push({ path: entry.path, message: safeMessage(error) });\n }\n }\n\n return report;\n};\n", "import { initLearnCard } from '@learncard/init';\nimport type { InitLearnCard } from '@learncard/init';\n\nimport { readLearnCardBundle, readLearnCardBundleData } from './importBundle';\nimport type { ReadLearnCardBundleOptions, ReadLearnCardBundleResult } from './types';\n\ntype SeededInitConfig = Extract<InitLearnCard['args'], { seed: string }>;\ntype DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;\n\nexport type RestoreLearnCardInit = DistributiveOmit<SeededInitConfig, 'seed'>;\n\nexport type RestoreLearnCardFromBundleOptions = ReadLearnCardBundleOptions & {\n init: RestoreLearnCardInit;\n};\n\nconst getSeedEntry = (bundle: ReadLearnCardBundleResult): string => {\n const seedEntry = bundle.entries.find(entry => entry.type === 'key-private-seed');\n\n if (!seedEntry) {\n throw new Error(\n 'LearnCard bundle does not contain key-private-seed and cannot be restored'\n );\n }\n\n const seed = seedEntry.content.trim();\n\n if (!/^[0-9a-f]{64}$/i.test(seed)) {\n throw new Error(\n 'LearnCard bundle key-private-seed must be exactly 64 hexadecimal characters'\n );\n }\n\n return seed;\n};\n\nexport const readLearnCardBundleSeedData = async (\n data: Buffer,\n options: ReadLearnCardBundleOptions = {}\n): Promise<string> => getSeedEntry(await readLearnCardBundleData(data, options));\n\nexport const readLearnCardBundleSeed = async (\n path: string,\n options: ReadLearnCardBundleOptions = {}\n): Promise<string> => getSeedEntry(await readLearnCardBundle(path, options));\n\nexport const restoreLearnCardFromBundleData = async (\n data: Buffer,\n options: RestoreLearnCardFromBundleOptions\n): Promise<InitLearnCard['returnValue']> => {\n const seed = await readLearnCardBundleSeedData(data, options);\n\n return initLearnCard({ ...options.init, seed } as SeededInitConfig);\n};\n\nexport const restoreLearnCardFromBundle = async (\n path: string,\n options: RestoreLearnCardFromBundleOptions\n): Promise<InitLearnCard['returnValue']> => {\n const seed = await readLearnCardBundleSeed(path, options);\n\n return initLearnCard({ ...options.init, seed } as SeededInitConfig);\n};\n"],
5
+ "mappings": "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",
6
6
  "names": ["index_exports", "__export", "assertValidManifest", "computePayloadSha256", "createLearnCardBundle", "exportLearnCardBundle", "finalizeManifest", "importLearnCardBundle", "readLearnCardBundle", "readLearnCardBundleData", "readLearnCardBundleSeed", "readLearnCardBundleSeedData", "restoreLearnCardFromBundle", "restoreLearnCardFromBundleData", "__toCommonJS", "import_promises", "import_node_net", "import_node_path", "import_jszip", "import_sss_key_manager", "import_node_crypto", "import_sss_key_manager", "sha256Hex", "__name", "bytes", "stableStringify", "value", "object", "key", "encodePayload", "plaintext", "options", "decodePayload", "stored", "envelope", "SPEC_VERSION", "BUNDLE_SPEC_MD", "BUNDLE_README_MD", "sortContents", "__name", "contents", "a", "b", "normalizeContents", "computePayloadSha256", "sha256Hex", "stableStringify", "finalizeManifest", "manifest", "assertValidManifest", "expected", "ZIP_DATE", "DEFAULT_STATUS_LIST_FETCH_TIMEOUT_MS", "DEFAULT_MAX_STATUS_LIST_BYTES", "stripIpv6Brackets", "__name", "hostname", "redactMalformedUrl", "value", "queryIndex", "ampIndex", "redactionIndex", "redactUrl", "url", "host", "isPrivateAddress", "urlEndDelimiters", "findNextUrlStart", "fromIndex", "httpIndex", "httpsIndex", "findUrlEnd", "index", "redactText", "redacted", "urlStart", "urlEnd", "safeMessage", "error", "isPrivateIPv4", "address", "parts", "part", "a", "b", "isPrivateIPv6", "normalized", "ipv4Mapped", "version", "assertPublicHttpsUrl", "uri", "addresses", "readResponseText", "response", "maxBytes", "contentLength", "text", "reader", "chunks", "total", "done", "fetchJsonWithTimeout", "timeoutMs", "controller", "timeout", "isRecord", "stringArrayIncludes", "expected", "item", "json", "stableStringify", "classifyPayload", "payload", "pathForType", "type", "digest", "encrypted", "suffix", "getCredentialId", "addZipText", "zip", "path", "content", "collectDids", "wallet", "warnings", "dids", "method", "collectDidDocument", "primaryDid", "collectKeyPayloads", "payloads", "seed", "shares", "jwks", "algorithm", "extractStatusListUrls", "status", "collectStatusLists", "enabled", "urls", "results", "collectConsentRecords", "metadata", "warning", "createLearnCardBundle", "options", "encrypt", "JSZip", "contents", "didDocument", "credentialPayloads", "addStoredEntry", "entry", "encoded", "encodePayload", "sha256Hex", "BUNDLE_README_MD", "BUNDLE_SPEC_MD", "records", "recordIndex", "record", "entryWarnings", "resolved", "credentialId", "indexRecordId", "consentRecords", "consentRecord", "statusList", "manifest", "finalizeManifest", "SPEC_VERSION", "exportLearnCardBundle", "bundle", "import_promises", "import_jszip", "DEFAULT_MAX_BUNDLE_BYTES", "DEFAULT_MAX_ENTRY_BYTES", "DEFAULT_MAX_JSON_BYTES", "byteLength", "__name", "content", "assertSize", "label", "size", "max", "parseJson", "maxBytes", "safeMessage", "error", "parseObject", "value", "isImportableCredentialEntry", "entry", "isFailedVerification", "result", "item", "status", "errors", "verifyImportableEntry", "options", "verification", "readLearnCardBundleData", "data", "maxBundleBytes", "maxEntryBytes", "maxJsonBytes", "zip", "JSZip", "manifestFile", "manifestContent", "manifest", "assertValidManifest", "warnings", "entries", "shouldDecrypt", "totalEntryBytes", "file", "stored", "storedBytes", "sha256Hex", "decodePayload", "readLearnCardBundle", "path", "importLearnCardBundle", "bundle", "report", "entriesById", "upload", "uri", "referencedIndexRecord", "indexRecord", "recordId", "import_init", "getSeedEntry", "__name", "bundle", "seedEntry", "entry", "seed", "readLearnCardBundleSeedData", "data", "options", "readLearnCardBundleData", "readLearnCardBundleSeed", "path", "readLearnCardBundle", "restoreLearnCardFromBundleData", "restoreLearnCardFromBundle"]
7
7
  }
@@ -21,7 +21,8 @@ var stableStringify = /* @__PURE__ */ __name((value) => {
21
21
  }, "stableStringify");
22
22
  var encodePayload = /* @__PURE__ */ __name(async (plaintext, options) => {
23
23
  if (!options.encrypt) return { stored: plaintext, encrypted: false };
24
- if (!options.password) throw new Error("A password is required for encrypted LearnCard exports");
24
+ if (!options.password)
25
+ throw new Error("A password is required for encrypted LearnCard exports");
25
26
  return {
26
27
  stored: JSON.stringify(await encryptWithPassword(plaintext, options.password), null, 2),
27
28
  encrypted: true
@@ -29,7 +30,8 @@ var encodePayload = /* @__PURE__ */ __name(async (plaintext, options) => {
29
30
  }, "encodePayload");
30
31
  var decodePayload = /* @__PURE__ */ __name(async (stored, options) => {
31
32
  if (!options.encrypted) return stored;
32
- if (!options.password) throw new Error("A password is required to decrypt this LearnCard export");
33
+ if (!options.password)
34
+ throw new Error("A password is required to decrypt this LearnCard export");
33
35
  const envelope = JSON.parse(stored);
34
36
  return decryptWithPassword(
35
37
  envelope.ciphertext,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/exportBundle.ts", "../src/crypto.ts", "../src/manifest.ts", "../src/importBundle.ts", "../src/restoreBundle.ts"],
4
- "sourcesContent": ["import { lookup } from 'node:dns/promises';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { isIP } from 'node:net';\nimport { dirname } from 'node:path';\n\nimport JSZip from 'jszip';\nimport { shareToRecoveryPhrase, splitPrivateKey } from '@learncard/sss-key-manager';\n\nimport type {\n BundleContentType,\n ExportLearnCardBundleOptions,\n JsonValue,\n LearnCardBundleEntryMetadata,\n LearnCardBundleOptions,\n LearnCardBundleResult,\n LearnCardBundleWallet,\n} from './types';\nimport { BUNDLE_README_MD, BUNDLE_SPEC_MD, finalizeManifest, SPEC_VERSION } from './manifest';\nimport { encodePayload, sha256Hex, stableStringify } from './crypto';\n\nconst ZIP_DATE = new Date('2024-01-01T00:00:00.000Z');\n\nconst DEFAULT_STATUS_LIST_FETCH_TIMEOUT_MS = 5000;\nconst DEFAULT_MAX_STATUS_LIST_BYTES = 5 * 1024 * 1024;\n\nconst stripIpv6Brackets = (hostname: string): string =>\n hostname.startsWith('[') && hostname.endsWith(']') ? hostname.slice(1, -1) : hostname;\n\nconst redactMalformedUrl = (value: string): string => {\n const queryIndex = value.indexOf('?');\n const ampIndex = value.indexOf('&');\n\n if (queryIndex === -1 && ampIndex === -1) return value;\n\n const redactionIndex =\n queryIndex === -1\n ? ampIndex\n : ampIndex === -1\n ? queryIndex\n : Math.min(queryIndex, ampIndex);\n\n return `${value.slice(0, redactionIndex)}?[redacted]`;\n};\n\nconst redactUrl = (value: string): string => {\n try {\n const url = new URL(value);\n const hostname = stripIpv6Brackets(url.hostname.toLowerCase());\n const shouldRedactHost =\n !hostname.includes('.') ||\n hostname === 'localhost' ||\n hostname.endsWith('.localhost') ||\n Boolean(isIP(hostname) && isPrivateAddress(hostname));\n const host = shouldRedactHost ? '[redacted-host]' : url.host;\n\n return `${url.protocol}//${host}${url.pathname}${url.search ? '?[redacted]' : ''}`;\n } catch {\n return redactMalformedUrl(value);\n }\n};\n\nconst urlEndDelimiters = new Set([' ', '\\n', '\\r', '\\t', \"'\", '\"', '<', '>']);\n\nconst findNextUrlStart = (value: string, fromIndex: number): number => {\n const httpIndex = value.indexOf('http://', fromIndex);\n const httpsIndex = value.indexOf('https://', fromIndex);\n\n if (httpIndex === -1) return httpsIndex;\n if (httpsIndex === -1) return httpIndex;\n\n return Math.min(httpIndex, httpsIndex);\n};\n\nconst findUrlEnd = (value: string, fromIndex: number): number => {\n let index = fromIndex;\n\n while (index < value.length && !urlEndDelimiters.has(value[index]!)) index += 1;\n\n return index;\n};\n\nconst redactText = (value: string): string => {\n let redacted = '';\n let index = 0;\n\n while (index < value.length) {\n const urlStart = findNextUrlStart(value, index);\n\n if (urlStart === -1) {\n redacted += value.slice(index);\n break;\n }\n\n const urlEnd = findUrlEnd(value, urlStart);\n\n redacted += value.slice(index, urlStart);\n redacted += redactUrl(value.slice(urlStart, urlEnd));\n index = urlEnd;\n }\n\n return redacted;\n};\n\nconst safeMessage = (error: unknown): string =>\n redactText(error instanceof Error ? error.message : String(error));\n\nconst isPrivateIPv4 = (address: string): boolean => {\n const parts = address.split('.').map(part => Number(part));\n\n if (parts.length !== 4 || parts.some(part => !Number.isInteger(part) || part < 0 || part > 255))\n return true;\n\n const [a, b] = parts;\n\n if (a === 0 || a === 10 || a === 127 || a >= 224) return true;\n if (a === 100 && b >= 64 && b <= 127) return true;\n if (a === 169 && b === 254) return true;\n if (a === 172 && b >= 16 && b <= 31) return true;\n if (a === 192 && b === 168) return true;\n if (a === 198 && (b === 18 || b === 19)) return true;\n\n return false;\n};\n\nconst isPrivateIPv6 = (address: string): boolean => {\n const normalized = address.toLowerCase();\n\n if (normalized === '::' || normalized === '::1') return true;\n if (normalized.startsWith('fc') || normalized.startsWith('fd')) return true;\n if (\n normalized.startsWith('fe8') ||\n normalized.startsWith('fe9') ||\n normalized.startsWith('fea') ||\n normalized.startsWith('feb')\n )\n return true;\n\n const ipv4Mapped = normalized.match(/::ffff:(\\d+\\.\\d+\\.\\d+\\.\\d+)$/);\n\n return ipv4Mapped ? isPrivateIPv4(ipv4Mapped[1]!) : false;\n};\n\nconst isPrivateAddress = (address: string): boolean => {\n const version = isIP(address);\n\n if (version === 4) return isPrivateIPv4(address);\n if (version === 6) return isPrivateIPv6(address);\n\n return true;\n};\n\nconst assertPublicHttpsUrl = async (uri: string): Promise<URL> => {\n const url = new URL(uri);\n const hostname = url.hostname.toLowerCase().replace(/^\\[|\\]$/g, '');\n\n if (url.protocol !== 'https:') throw new Error('status-list URL must use https');\n if (!hostname.includes('.') || hostname === 'localhost' || hostname.endsWith('.localhost')) {\n throw new Error('status-list URL host must be public');\n }\n\n if (isIP(hostname)) {\n if (isPrivateAddress(hostname)) throw new Error('status-list URL host must be public');\n\n return url;\n }\n\n const addresses = await lookup(hostname, { all: true, verbatim: true });\n\n if (addresses.length === 0 || addresses.some(address => isPrivateAddress(address.address))) {\n throw new Error('status-list URL host must resolve to public addresses');\n }\n\n return url;\n};\n\nconst readResponseText = async (response: Response, maxBytes: number): Promise<string> => {\n const contentLength = Number(response.headers.get('content-length'));\n\n if (Number.isFinite(contentLength) && contentLength > maxBytes) {\n throw new Error(`status-list response exceeds ${maxBytes} bytes`);\n }\n\n if (!response.body) {\n const text = await response.text();\n\n if (Buffer.byteLength(text, 'utf8') > maxBytes) {\n throw new Error(`status-list response exceeds ${maxBytes} bytes`);\n }\n\n return text;\n }\n\n const reader = response.body.getReader();\n const chunks: Buffer[] = [];\n let total = 0;\n\n while (true) {\n const { done, value } = await reader.read();\n\n if (done) break;\n\n total += value.byteLength;\n\n if (total > maxBytes) {\n await reader.cancel();\n\n throw new Error(`status-list response exceeds ${maxBytes} bytes`);\n }\n\n chunks.push(Buffer.from(value));\n }\n\n return Buffer.concat(chunks).toString('utf8');\n};\n\nconst fetchJsonWithTimeout = async (\n url: URL,\n timeoutMs: number,\n maxBytes: number\n): Promise<JsonValue> => {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n const response = await fetch(url, { signal: controller.signal });\n\n if (!response.ok) throw new Error(`HTTP ${response.status}`);\n\n return JSON.parse(await readResponseText(response, maxBytes)) as JsonValue;\n } finally {\n clearTimeout(timeout);\n }\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n Boolean(value) && typeof value === 'object' && !Array.isArray(value);\n\nconst stringArrayIncludes = (value: unknown, expected: string): boolean =>\n Array.isArray(value) && value.some(item => item === expected);\n\nconst json = (value: unknown): string => `${stableStringify(value)}\\n`;\n\nconst classifyPayload = (payload: JsonValue): BundleContentType => {\n if (!isRecord(payload)) return 'unknown-json';\n\n if (\n stringArrayIncludes(payload.type, 'VerifiablePresentation') ||\n payload.type === 'VerifiablePresentation'\n ) {\n return 'presentation';\n }\n\n if (\n stringArrayIncludes(payload.type, 'VerifiableCredential') ||\n payload.type === 'VerifiableCredential'\n ) {\n return 'credential';\n }\n\n return 'unknown-json';\n};\n\nconst pathForType = (type: BundleContentType, digest: string, encrypted: boolean): string => {\n const suffix = encrypted ? '.enc' : '';\n\n if (type === 'presentation') return `presentations/${digest}.json${suffix}`;\n\n if (type === 'consent-record') return `consent-records/${digest}.json${suffix}`;\n\n if (type === 'index-record') return `index-records/${digest}.json${suffix}`;\n if (type === 'status-cache') return `status-cache/${digest}.json${suffix}`;\n\n return `credentials/${digest}.json${suffix}`;\n};\n\nconst getCredentialId = (payload: JsonValue): string | undefined =>\n isRecord(payload) && typeof payload.id === 'string' ? payload.id : undefined;\n\nconst addZipText = (zip: JSZip, path: string, content: string): void => {\n zip.file(path, content, { date: ZIP_DATE });\n};\n\nconst collectDids = (wallet: LearnCardBundleWallet, warnings: string[]): Record<string, string> => {\n const dids: Record<string, string> = {};\n\n for (const method of [undefined, 'key', 'pkh:sol', 'tz', 'pkh:tz']) {\n try {\n dids[method ?? 'default'] = wallet.id.did(method);\n } catch (error) {\n warnings.push(\n `Could not derive DID method ${method ?? 'default'}: ${safeMessage(error)}`\n );\n }\n }\n\n return dids;\n};\n\nconst collectDidDocument = async (\n wallet: LearnCardBundleWallet,\n primaryDid: string,\n dids: Record<string, string>,\n warnings: string[]\n): Promise<JsonValue> => {\n if (!wallet.invoke.resolveDid) return { primaryDid, dids };\n\n try {\n return { primaryDid, dids, primaryDidDocument: await wallet.invoke.resolveDid(primaryDid) };\n } catch (error) {\n warnings.push(`Could not resolve primary DID document: ${safeMessage(error)}`);\n\n return { primaryDid, dids };\n }\n};\n\nconst collectKeyPayloads = async (\n wallet: LearnCardBundleWallet,\n warnings: string[]\n): Promise<\n Array<{ path: string; type: BundleContentType; content: string; encrypted: boolean }>\n> => {\n const payloads: Array<{\n path: string;\n type: BundleContentType;\n content: string;\n encrypted: boolean;\n }> = [];\n\n if (wallet.invoke.getKey) {\n try {\n const seed = wallet.invoke.getKey();\n const shares = await splitPrivateKey(seed);\n\n payloads.push({\n path: 'keys/private-key-seed.txt',\n type: 'key-private-seed',\n content: `${seed}\\n`,\n encrypted: true,\n });\n\n payloads.push({\n path: 'keys/recovery-phrase.txt',\n type: 'key-recovery-phrase',\n content: `${await shareToRecoveryPhrase(shares.recoveryShare)}\\n`,\n encrypted: true,\n });\n } catch (error) {\n warnings.push(`Could not export seed or recovery phrase: ${safeMessage(error)}`);\n }\n } else {\n warnings.push(\n 'Wallet does not expose invoke.getKey(); private seed and recovery phrase were not exported'\n );\n }\n\n if (wallet.id.keypair) {\n const jwks: Record<string, JsonValue> = {};\n\n for (const algorithm of ['ed25519', 'secp256k1'] as const) {\n try {\n jwks[algorithm] = wallet.id.keypair(algorithm);\n } catch (error) {\n warnings.push(`Could not export ${algorithm} JWK: ${safeMessage(error)}`);\n }\n }\n\n if (Object.keys(jwks).length > 0) {\n payloads.push({\n path: 'keys/jwks.json',\n type: 'key-jwks',\n content: json(jwks),\n encrypted: true,\n });\n }\n } else {\n warnings.push('Wallet does not expose id.keypair(); JWK key export was skipped');\n }\n\n return payloads;\n};\n\nconst extractStatusListUrls = (payload: JsonValue): string[] => {\n if (!isRecord(payload)) return [];\n\n const statuses = Array.isArray(payload.credentialStatus)\n ? payload.credentialStatus\n : payload.credentialStatus\n ? [payload.credentialStatus]\n : [];\n\n return statuses.flatMap(status =>\n isRecord(status) && typeof status.statusListCredential === 'string'\n ? [status.statusListCredential]\n : []\n );\n};\n\nconst collectStatusLists = async (\n payloads: JsonValue[],\n enabled: boolean,\n warnings: string[],\n timeoutMs = DEFAULT_STATUS_LIST_FETCH_TIMEOUT_MS,\n maxBytes = DEFAULT_MAX_STATUS_LIST_BYTES\n): Promise<Array<{ uri: string; content: JsonValue }>> => {\n if (!enabled) return [];\n\n const urls = [...new Set(payloads.flatMap(extractStatusListUrls))];\n const results: Array<{ uri: string; content: JsonValue }> = [];\n\n for (const uri of urls) {\n try {\n const url = await assertPublicHttpsUrl(uri);\n\n results.push({ uri, content: await fetchJsonWithTimeout(url, timeoutMs, maxBytes) });\n } catch (error) {\n warnings.push(\n `Could not cache status-list credential ${redactUrl(uri)}: ${safeMessage(error)}`\n );\n }\n }\n\n return results;\n};\n\nconst collectConsentRecords = async (\n wallet: LearnCardBundleWallet,\n warnings: string[]\n): Promise<JsonValue[]> => {\n if (wallet.invoke.getHolderExportMetadata) {\n try {\n const metadata = await wallet.invoke.getHolderExportMetadata();\n\n if (isRecord(metadata) && Array.isArray(metadata.warnings)) {\n warnings.push(\n ...metadata.warnings\n .filter(warning => typeof warning === 'string')\n .map(warning => redactText(warning))\n );\n }\n\n return isRecord(metadata) && Array.isArray(metadata.consentRecords)\n ? (metadata.consentRecords as JsonValue[])\n : [];\n } catch (error) {\n warnings.push(`Could not fetch holder export metadata: ${safeMessage(error)}`);\n }\n }\n\n if (!wallet.invoke.getConsentedContracts) return [];\n\n try {\n const response = await wallet.invoke.getConsentedContracts();\n\n if (!isRecord(response) || !Array.isArray(response.records)) return [];\n\n return response.records as JsonValue[];\n } catch (error) {\n warnings.push(`Could not fetch consented contracts fallback: ${safeMessage(error)}`);\n\n return [];\n }\n};\n\nexport const createLearnCardBundle = async (\n wallet: LearnCardBundleWallet,\n options: LearnCardBundleOptions = {}\n): Promise<LearnCardBundleResult> => {\n const encrypt = options.encrypt ?? true;\n\n if (encrypt && !options.password)\n throw new Error('A password is required for LearnCard export');\n\n const warnings: string[] = [];\n const zip = new JSZip();\n const contents: LearnCardBundleEntryMetadata[] = [];\n const primaryDid = wallet.id.did();\n const dids = collectDids(wallet, warnings);\n const didDocument = await collectDidDocument(wallet, primaryDid, dids, warnings);\n const credentialPayloads: JsonValue[] = [];\n\n const addStoredEntry = async (entry: {\n id: string;\n type: BundleContentType;\n path: string;\n content: string;\n encrypted: boolean;\n mediaType?: string;\n sourceUri?: string;\n credentialId?: string;\n indexRecordRef?: string;\n warnings?: string[];\n }): Promise<void> => {\n const encoded = await encodePayload(entry.content, {\n encrypt: entry.encrypted && encrypt,\n password: options.password,\n });\n const path =\n encoded.encrypted && !entry.path.endsWith('.enc') ? `${entry.path}.enc` : entry.path;\n\n addZipText(zip, path, encoded.stored);\n\n contents.push({\n id: entry.id,\n type: entry.type,\n path,\n mediaType: entry.mediaType ?? 'application/json',\n sha256: sha256Hex(encoded.stored),\n encrypted: encoded.encrypted,\n sourceUri: entry.sourceUri,\n credentialId: entry.credentialId,\n indexRecordRef: entry.indexRecordRef,\n warnings: entry.warnings,\n });\n };\n\n addZipText(zip, 'README.md', BUNDLE_README_MD);\n addZipText(zip, 'BUNDLE_SPEC.md', BUNDLE_SPEC_MD);\n\n await addStoredEntry({\n id: 'did-document',\n type: 'did-document',\n path: 'keys/did-document.json',\n content: json(didDocument),\n encrypted: false,\n });\n\n for (const payload of await collectKeyPayloads(wallet, warnings)) {\n await addStoredEntry({ ...payload, id: payload.path, mediaType: 'text/plain' });\n }\n\n const records = await wallet.index.LearnCloud.get();\n\n for (const [recordIndex, record] of records.entries()) {\n const entryWarnings: string[] = [];\n const digest = sha256Hex(\n stableStringify({ recordIndex, id: record.id ?? null, uri: record.uri ?? null })\n );\n\n try {\n const resolved = await wallet.read.get(record.uri);\n\n if (!resolved) {\n warnings.push(`Could not resolve wallet index URI ${redactUrl(record.uri)}`);\n continue;\n }\n\n credentialPayloads.push(resolved);\n const type = classifyPayload(resolved);\n const credentialId = getCredentialId(resolved);\n if (type === 'unknown-json') entryWarnings.push('Payload is not a recognized VC or VP');\n\n const indexRecordId = `urn:sha256:${digest}:index-record`;\n\n await addStoredEntry({\n id: indexRecordId,\n type: 'index-record',\n path: pathForType('index-record', digest, encrypt),\n content: json(record),\n encrypted: true,\n sourceUri: record.uri,\n credentialId,\n });\n\n await addStoredEntry({\n id: `urn:sha256:${digest}`,\n type,\n path: pathForType(type, digest, encrypt),\n content: json(resolved),\n encrypted: true,\n sourceUri: record.uri,\n credentialId,\n indexRecordRef: indexRecordId,\n warnings: entryWarnings.length > 0 ? entryWarnings : undefined,\n });\n } catch (error) {\n warnings.push(\n `Could not export wallet index URI ${redactUrl(record.uri)}: ${safeMessage(error)}`\n );\n }\n }\n\n const consentRecords = await collectConsentRecords(wallet, warnings);\n\n for (const consentRecord of consentRecords) {\n const digest = sha256Hex(stableStringify(consentRecord));\n\n await addStoredEntry({\n id: `urn:sha256:${digest}`,\n type: 'consent-record',\n path: pathForType('consent-record', digest, encrypt),\n content: json(consentRecord),\n encrypted: true,\n });\n }\n\n for (const statusList of await collectStatusLists(\n credentialPayloads,\n options.fetchStatusLists ?? true,\n warnings,\n options.statusListFetchTimeoutMs,\n options.maxStatusListBytes\n )) {\n const digest = sha256Hex(statusList.uri);\n\n await addStoredEntry({\n id: `urn:sha256:${digest}`,\n type: 'status-cache',\n path: pathForType('status-cache', digest, encrypt),\n content: json(statusList.content),\n encrypted: true,\n sourceUri: statusList.uri,\n });\n }\n\n const manifest = finalizeManifest({\n specVersion: SPEC_VERSION,\n createdAt: options.createdAt ?? new Date().toISOString(),\n primaryDid,\n walletName: 'LearnCard',\n encryption: encrypt\n ? {\n mode: 'argon2id-aes-256-gcm',\n encryptedPayloads: true,\n envelope: 'sss-key-manager-encryptWithPassword-v1',\n kdf: 'argon2id',\n cipher: 'AES-256-GCM',\n }\n : { mode: 'none', encryptedPayloads: false },\n contents,\n warnings,\n });\n\n addZipText(zip, 'manifest.json', `${JSON.stringify(manifest, null, 2)}\\n`);\n\n return {\n data: await zip.generateAsync({ type: 'nodebuffer', compression: 'DEFLATE' }),\n manifest,\n warnings,\n };\n};\n\nexport const exportLearnCardBundle = async (\n wallet: LearnCardBundleWallet,\n options: ExportLearnCardBundleOptions\n): Promise<LearnCardBundleResult> => {\n const bundle = await createLearnCardBundle(wallet, options);\n\n await mkdir(dirname(options.out), { recursive: true });\n await writeFile(options.out, bundle.data);\n\n return bundle;\n};\n", "import { createHash } from 'node:crypto';\n\nimport { decryptWithPassword, encryptWithPassword } from '@learncard/sss-key-manager';\n\nimport type { EncryptedPayloadEnvelope } from './types';\n\nexport const sha256Hex = (bytes: string | Buffer): string =>\n createHash('sha256').update(bytes).digest('hex');\n\nexport const stableStringify = (value: unknown): string => {\n if (value === null || typeof value !== 'object') return JSON.stringify(value);\n\n if (Array.isArray(value)) return `[${value.map(stableStringify).join(',')}]`;\n\n const object = value as Record<string, unknown>;\n\n return `{${Object.keys(object)\n .sort()\n .map(key => `${JSON.stringify(key)}:${stableStringify(object[key])}`)\n .join(',')}}`;\n};\n\nexport const encodePayload = async (\n plaintext: string,\n options: { encrypt: boolean; password?: string }\n): Promise<{ stored: string; encrypted: boolean }> => {\n if (!options.encrypt) return { stored: plaintext, encrypted: false };\n\n if (!options.password) throw new Error('A password is required for encrypted LearnCard exports');\n\n return {\n stored: JSON.stringify(await encryptWithPassword(plaintext, options.password), null, 2),\n encrypted: true,\n };\n};\n\nexport const decodePayload = async (\n stored: string,\n options: { encrypted: boolean; password?: string }\n): Promise<string> => {\n if (!options.encrypted) return stored;\n\n if (!options.password) throw new Error('A password is required to decrypt this LearnCard export');\n\n const envelope = JSON.parse(stored) as EncryptedPayloadEnvelope;\n\n return decryptWithPassword(\n envelope.ciphertext,\n envelope.iv,\n envelope.salt,\n options.password,\n envelope.kdfParams\n );\n};\n", "import type { LearnCardBundleEntryMetadata, LearnCardBundleManifest } from './types';\nimport { stableStringify, sha256Hex } from './crypto';\n\nexport const SPEC_VERSION = '1.0.0' as const;\n\nexport const BUNDLE_SPEC_MD = `# LearnCard Holder Continuity Bundle v1.0.0\n\nA LearnCard holder continuity bundle is a ZIP file with readable metadata and encrypted holder payloads.\n\n## Container\n\nRequired readable entries:\n\n- \\`manifest.json\\` \u2014 inventory, hashes, warnings, and encryption metadata.\n- \\`README.md\\` \u2014 human-readable recovery notes.\n- \\`BUNDLE_SPEC.md\\` \u2014 this format description.\n\nSensitive entries use JSON encryption envelopes produced by \\`@learncard/sss-key-manager\\` \\`encryptWithPassword\\`: Argon2id key derivation and AES-GCM authenticated encryption. The ZIP itself is not password encrypted.\n\n## Security model\n\nThis bundle exports the wallet's full raw private-key seed at \\`keys/private-key-seed.txt.enc\\`. LearnCard's live wallet protects the key with 2-of-4 Shamir Secret Sharing, where no single share can reconstruct it. The bundle does NOT preserve that threshold: the exported seed alone is sufficient to take full control of the identity, and the bundle password is the only barrier protecting it. \\`keys/recovery-phrase.txt.enc\\` is derived from the current recovery share for reference and is not independently sufficient to recover the key. Treat the bundle like a password-vault backup, use a strong unique password, and rotate the wallet if the bundle is exposed.\n\n## Paths\n\n- \\`keys/recovery-phrase.txt.enc\\`\n- \\`keys/private-key-seed.txt.enc\\`\n- \\`keys/jwks.json.enc\\`\n- \\`keys/did-document.json\\`\n- \\`credentials/<sha256>.json.enc\\`\n- \\`presentations/<sha256>.json.enc\\`\n- \\`index-records/<sha256>.json.enc\\`\n- \\`consent-records/<sha256>.json.enc\\`\n- \\`status-cache/<sha256>.json.enc\\`\n\nDebug exports MAY use plaintext payloads by setting \\`encrypt: false\\`; production exports MUST encrypt sensitive payloads.\n\nStatus-list snapshot fetching is HTTPS-only and rejects private, loopback, link-local, and single-label hosts. Exporters SHOULD keep the default timeout and response-size caps unless they are running in a trusted local environment.\n\n## Manifest hashing\n\nEach \\`contents[]\\` entry contains the SHA-256 hash of the bytes stored at \\`path\\`. \\`payloadSha256\\` is SHA-256 over a deterministic JSON serialization of \\`contents[]\\` with entries sorted by path.\n\nEach credential or presentation entry MAY reference an encrypted \\`index-record\\` companion entry via \\`indexRecordRef\\`; the readable manifest does not embed the original index record JSON.\n\n## Restore vs import\n\n\\`restoreLearnCardFromBundle(...)\\` decrypts \\`keys/private-key-seed.txt.enc\\` and passes that seed to \\`initLearnCard(...)\\`. It recreates the original wallet identity; it does not upload payloads or recreate index records.\n\n\\`importLearnCardBundle(...)\\` decrypts credential and presentation payloads, uploads them to the target wallet's LearnCloud store, and recreates index records from the encrypted \\`index-record\\` companions.\n\nImport writes bundle contents into the target wallet. A bundle author who knows the password can include arbitrary credentials, presentations, and index metadata. Use \\`verifyBeforeImport: true\\` to verify VC/VP signatures before upload when the target wallet exposes \\`invoke.verifyCredential\\` and \\`invoke.verifyPresentation\\`.\n\n## Size limits\n\nReaders enforce default compressed-bundle, per-entry, and JSON parse limits to avoid accidentally processing oversized ZIP or JSON payloads. Callers can override these with \\`maxBundleBytes\\`, \\`maxEntryBytes\\`, and \\`maxJsonBytes\\` for trusted local workflows.\n\n## Import expectations\n\nImporters MUST verify the stored bytes against each entry hash before trusting decrypted content. Importers SHOULD verify issuer signatures before upload and preserve issuer-signed credential and presentation payloads exactly.\n`;\n\nexport const BUNDLE_README_MD = `# LearnCard Holder Continuity Export\n\nThis archive contains a point-in-time holder export from a LearnCard wallet.\n\nKeep the password separately. Without it, encrypted credentials, key material, consent records, and status-list snapshots cannot be recovered.\n\nThis archive contains your full private-key seed (encrypted). Anyone with both this file and its password can take complete control of your wallet identity, so store it like a password-vault backup and rotate your wallet if it is exposed.\n\nThe readable manifest lists every payload and its SHA-256 hash. Third-party wallets can import individual W3C Verifiable Credentials or Verifiable Presentations from the decrypted JSON files even when they do not support the LearnCard ZIP bundle directly.\n`;\n\nexport const sortContents = (\n contents: LearnCardBundleEntryMetadata[]\n): LearnCardBundleEntryMetadata[] => [...contents].sort((a, b) => a.path.localeCompare(b.path));\n\nconst normalizeContents = (\n contents: LearnCardBundleEntryMetadata[]\n): LearnCardBundleEntryMetadata[] =>\n JSON.parse(JSON.stringify(sortContents(contents))) as LearnCardBundleEntryMetadata[];\n\nexport const computePayloadSha256 = (contents: LearnCardBundleEntryMetadata[]): string =>\n sha256Hex(stableStringify(normalizeContents(contents)));\n\nexport const finalizeManifest = (\n manifest: Omit<LearnCardBundleManifest, 'payloadSha256'>\n): LearnCardBundleManifest => ({\n ...manifest,\n contents: normalizeContents(manifest.contents),\n payloadSha256: computePayloadSha256(manifest.contents),\n});\n\nexport const assertValidManifest = (manifest: LearnCardBundleManifest): void => {\n if (manifest.specVersion !== SPEC_VERSION) {\n throw new Error(`Unsupported LearnCard bundle version: ${manifest.specVersion}`);\n }\n\n const expected = computePayloadSha256(manifest.contents);\n\n if (manifest.payloadSha256 !== expected)\n throw new Error('LearnCard bundle manifest hash mismatch');\n};\n", "import { readFile } from 'node:fs/promises';\n\nimport JSZip from 'jszip';\n\nimport type {\n ImportLearnCardBundleOptions,\n ImportLearnCardBundleReport,\n JsonValue,\n LearnCardBundleEntryMetadata,\n LearnCardBundleManifest,\n ReadLearnCardBundleOptions,\n ReadLearnCardBundleResult,\n} from './types';\nimport { assertValidManifest } from './manifest';\nimport { decodePayload, sha256Hex } from './crypto';\n\nconst DEFAULT_MAX_BUNDLE_BYTES = 100 * 1024 * 1024;\nconst DEFAULT_MAX_ENTRY_BYTES = 25 * 1024 * 1024;\nconst DEFAULT_MAX_JSON_BYTES = 25 * 1024 * 1024;\n\nconst byteLength = (content: string): number => Buffer.byteLength(content, 'utf8');\n\nconst assertSize = (label: string, size: number, max: number): void => {\n if (size > max) throw new Error(`${label} exceeds ${max} bytes`);\n};\n\nconst parseJson = (content: string, label: string, maxBytes: number): JsonValue => {\n assertSize(label, byteLength(content), maxBytes);\n\n return JSON.parse(content) as JsonValue;\n};\n\nconst safeMessage = (error: unknown): string =>\n error instanceof Error ? error.message : String(error);\n\nconst parseObject = (content: string, label: string, maxBytes: number): Record<string, unknown> => {\n const value = parseJson(content, label, maxBytes);\n\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error('Expected bundle metadata entry to contain a JSON object');\n }\n\n return value as Record<string, unknown>;\n};\n\nconst isImportableCredentialEntry = (entry: LearnCardBundleEntryMetadata): boolean =>\n entry.type === 'credential' || entry.type === 'presentation';\n\nconst isFailedVerification = (result: unknown): boolean => {\n if (Array.isArray(result)) {\n return result.some(item => {\n if (!item || typeof item !== 'object') return true;\n\n const status = 'status' in item ? item.status : undefined;\n\n return status === 'Failed' || status === 'Error';\n });\n }\n\n if (!result || typeof result !== 'object') return true;\n\n const errors = 'errors' in result ? result.errors : undefined;\n\n return !Array.isArray(errors) || errors.length > 0;\n};\n\nconst verifyImportableEntry = async (\n entry: LearnCardBundleEntryMetadata,\n content: JsonValue,\n options: ImportLearnCardBundleOptions\n): Promise<void> => {\n if (!options.verifyBeforeImport) return;\n\n if (entry.type === 'credential') {\n if (!options.wallet.invoke.verifyCredential) {\n throw new Error('Target wallet does not expose invoke.verifyCredential');\n }\n\n const verification = await options.wallet.invoke.verifyCredential(content);\n\n if (isFailedVerification(verification)) throw new Error('Credential verification failed');\n\n return;\n }\n\n if (!options.wallet.invoke.verifyPresentation) {\n throw new Error('Target wallet does not expose invoke.verifyPresentation');\n }\n\n const verification = await options.wallet.invoke.verifyPresentation(content);\n\n if (isFailedVerification(verification)) throw new Error('Presentation verification failed');\n};\n\nexport const readLearnCardBundleData = async (\n data: Buffer,\n options: ReadLearnCardBundleOptions = {}\n): Promise<ReadLearnCardBundleResult> => {\n const maxBundleBytes = options.maxBundleBytes ?? DEFAULT_MAX_BUNDLE_BYTES;\n const maxEntryBytes = options.maxEntryBytes ?? DEFAULT_MAX_ENTRY_BYTES;\n const maxJsonBytes = options.maxJsonBytes ?? DEFAULT_MAX_JSON_BYTES;\n\n assertSize('LearnCard bundle', data.byteLength, maxBundleBytes);\n\n const zip = await JSZip.loadAsync(data);\n const manifestFile = zip.file('manifest.json');\n\n if (!manifestFile) throw new Error('LearnCard bundle is missing manifest.json');\n\n const manifestContent = await manifestFile.async('string');\n\n assertSize('manifest.json', byteLength(manifestContent), maxJsonBytes);\n\n const manifest = JSON.parse(manifestContent) as LearnCardBundleManifest;\n\n assertValidManifest(manifest);\n\n const warnings = [...manifest.warnings];\n const entries: ReadLearnCardBundleResult['entries'] = [];\n const shouldDecrypt = options.decrypt ?? true;\n let totalEntryBytes = 0;\n\n for (const entry of manifest.contents) {\n const file = zip.file(entry.path);\n\n if (!file) throw new Error(`LearnCard bundle is missing ${entry.path}`);\n\n const stored = await file.async('string');\n const storedBytes = byteLength(stored);\n\n assertSize(entry.path, storedBytes, maxEntryBytes);\n\n totalEntryBytes += storedBytes;\n assertSize('LearnCard bundle entries', totalEntryBytes, maxBundleBytes);\n\n const actualSha = sha256Hex(stored);\n\n if (actualSha !== entry.sha256) {\n throw new Error(`SHA-256 mismatch for ${entry.path}`);\n }\n\n const content = shouldDecrypt\n ? await decodePayload(stored, {\n encrypted: entry.encrypted,\n password: options.password,\n })\n : stored;\n\n assertSize(`${entry.path} content`, byteLength(content), maxEntryBytes);\n\n entries.push({ ...entry, content });\n }\n\n return { manifest, entries, warnings };\n};\n\nexport const readLearnCardBundle = async (\n path: string,\n options: ReadLearnCardBundleOptions = {}\n): Promise<ReadLearnCardBundleResult> => readLearnCardBundleData(await readFile(path), options);\n\nexport const importLearnCardBundle = async (\n path: string,\n options: ImportLearnCardBundleOptions\n): Promise<ImportLearnCardBundleReport> => {\n const bundle = await readLearnCardBundle(path, options);\n const maxJsonBytes = options.maxJsonBytes ?? DEFAULT_MAX_JSON_BYTES;\n const report: ImportLearnCardBundleReport = {\n importedCredentials: 0,\n importedPresentations: 0,\n skipped: 0,\n skippedByType: {},\n errors: [],\n warnings: [...bundle.warnings],\n };\n\n if (!options.verifyBeforeImport) {\n report.warnings.push(\n 'Bundle credential signatures were not verified before import; only import bundles from sources you trust.'\n );\n }\n\n const entriesById = new Map(bundle.entries.map(entry => [entry.id, entry]));\n\n for (const entry of bundle.entries) {\n if (!isImportableCredentialEntry(entry)) {\n report.skipped += 1;\n report.skippedByType[entry.type] = (report.skippedByType[entry.type] ?? 0) + 1;\n continue;\n }\n\n try {\n const content = parseJson(entry.content, entry.path, maxJsonBytes);\n\n await verifyImportableEntry(entry, content, options);\n\n const upload =\n options.wallet.store.LearnCloud.uploadEncrypted ??\n options.wallet.store.LearnCloud.upload;\n\n if (!upload)\n throw new Error('Target wallet does not expose a LearnCloud upload method');\n\n const uri = await upload(content);\n const referencedIndexRecord = entry.indexRecordRef\n ? entriesById.get(entry.indexRecordRef)\n : undefined;\n\n if (entry.indexRecordRef && !referencedIndexRecord) {\n throw new Error(`Referenced index record ${entry.indexRecordRef} is missing`);\n }\n\n const indexRecord = referencedIndexRecord\n ? parseObject(\n referencedIndexRecord.content,\n referencedIndexRecord.path,\n maxJsonBytes\n )\n : { id: entry.id, uri };\n const recordId = typeof indexRecord.id === 'string' ? indexRecord.id : entry.id;\n\n await options.wallet.index.LearnCloud.add({\n ...indexRecord,\n id: recordId,\n uri,\n sourceExport: {\n manifestCreatedAt: bundle.manifest.createdAt,\n sourceUri: entry.sourceUri,\n sourcePath: entry.path,\n credentialId: entry.credentialId,\n },\n });\n\n if (entry.type === 'presentation') report.importedPresentations += 1;\n else report.importedCredentials += 1;\n } catch (error) {\n report.errors.push({ path: entry.path, message: safeMessage(error) });\n }\n }\n\n return report;\n};\n", "import { initLearnCard } from '@learncard/init';\nimport type { InitLearnCard } from '@learncard/init';\n\nimport { readLearnCardBundle, readLearnCardBundleData } from './importBundle';\nimport type { ReadLearnCardBundleOptions, ReadLearnCardBundleResult } from './types';\n\ntype SeededInitConfig = Extract<InitLearnCard['args'], { seed: string }>;\ntype DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;\n\nexport type RestoreLearnCardInit = DistributiveOmit<SeededInitConfig, 'seed'>;\n\nexport type RestoreLearnCardFromBundleOptions = ReadLearnCardBundleOptions & {\n init: RestoreLearnCardInit;\n};\n\nconst getSeedEntry = (bundle: ReadLearnCardBundleResult): string => {\n const seedEntry = bundle.entries.find(entry => entry.type === 'key-private-seed');\n\n if (!seedEntry) {\n throw new Error(\n 'LearnCard bundle does not contain key-private-seed and cannot be restored'\n );\n }\n\n const seed = seedEntry.content.trim();\n\n if (!/^[0-9a-f]{64}$/i.test(seed)) {\n throw new Error(\n 'LearnCard bundle key-private-seed must be exactly 64 hexadecimal characters'\n );\n }\n\n return seed;\n};\n\nexport const readLearnCardBundleSeedData = async (\n data: Buffer,\n options: ReadLearnCardBundleOptions = {}\n): Promise<string> => getSeedEntry(await readLearnCardBundleData(data, options));\n\nexport const readLearnCardBundleSeed = async (\n path: string,\n options: ReadLearnCardBundleOptions = {}\n): Promise<string> => getSeedEntry(await readLearnCardBundle(path, options));\n\nexport const restoreLearnCardFromBundleData = async (\n data: Buffer,\n options: RestoreLearnCardFromBundleOptions\n): Promise<InitLearnCard['returnValue']> => {\n const seed = await readLearnCardBundleSeedData(data, options);\n\n return initLearnCard({ ...options.init, seed } as SeededInitConfig);\n};\n\nexport const restoreLearnCardFromBundle = async (\n path: string,\n options: RestoreLearnCardFromBundleOptions\n): Promise<InitLearnCard['returnValue']> => {\n const seed = await readLearnCardBundleSeed(path, options);\n\n return initLearnCard({ ...options.init, seed } as SeededInitConfig);\n};\n"],
5
- "mappings": ";;;;AAAA,SAAS,cAAc;AACvB,SAAS,OAAO,iBAAiB;AACjC,SAAS,YAAY;AACrB,SAAS,eAAe;AAExB,OAAO,WAAW;AAClB,SAAS,uBAAuB,uBAAuB;;;ACNvD,SAAS,kBAAkB;AAE3B,SAAS,qBAAqB,2BAA2B;AAIlD,IAAM,YAAY,wBAAC,UACtB,WAAW,QAAQ,EAAE,OAAO,KAAK,EAAE,OAAO,KAAK,GAD1B;AAGlB,IAAM,kBAAkB,wBAAC,UAA2B;AACvD,MAAI,UAAU,QAAQ,OAAO,UAAU,SAAU,QAAO,KAAK,UAAU,KAAK;AAE5E,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,IAAI,MAAM,IAAI,eAAe,EAAE,KAAK,GAAG,CAAC;AAEzE,QAAM,SAAS;AAEf,SAAO,IAAI,OAAO,KAAK,MAAM,EACxB,KAAK,EACL,IAAI,SAAO,GAAG,KAAK,UAAU,GAAG,CAAC,IAAI,gBAAgB,OAAO,GAAG,CAAC,CAAC,EAAE,EACnE,KAAK,GAAG,CAAC;AAClB,GAX+B;AAaxB,IAAM,gBAAgB,8BACzB,WACA,YACkD;AAClD,MAAI,CAAC,QAAQ,QAAS,QAAO,EAAE,QAAQ,WAAW,WAAW,MAAM;AAEnE,MAAI,CAAC,QAAQ,SAAU,OAAM,IAAI,MAAM,wDAAwD;AAE/F,SAAO;AAAA,IACH,QAAQ,KAAK,UAAU,MAAM,oBAAoB,WAAW,QAAQ,QAAQ,GAAG,MAAM,CAAC;AAAA,IACtF,WAAW;AAAA,EACf;AACJ,GAZ6B;AActB,IAAM,gBAAgB,8BACzB,QACA,YACkB;AAClB,MAAI,CAAC,QAAQ,UAAW,QAAO;AAE/B,MAAI,CAAC,QAAQ,SAAU,OAAM,IAAI,MAAM,yDAAyD;AAEhG,QAAM,WAAW,KAAK,MAAM,MAAM;AAElC,SAAO;AAAA,IACH,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,SAAS;AAAA,EACb;AACJ,GAjB6B;;;ACjCtB,IAAM,eAAe;AAErB,IAAM,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAyDvB,IAAM,mBAAmB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWzB,IAAM,eAAe,wBACxB,aACiC,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC,GAFlE;AAI5B,IAAM,oBAAoB,wBACtB,aAEA,KAAK,MAAM,KAAK,UAAU,aAAa,QAAQ,CAAC,CAAC,GAH3B;AAKnB,IAAM,uBAAuB,wBAAC,aACjC,UAAU,gBAAgB,kBAAkB,QAAQ,CAAC,CAAC,GADtB;AAG7B,IAAM,mBAAmB,wBAC5B,cAC2B;AAAA,EAC3B,GAAG;AAAA,EACH,UAAU,kBAAkB,SAAS,QAAQ;AAAA,EAC7C,eAAe,qBAAqB,SAAS,QAAQ;AACzD,IANgC;AAQzB,IAAM,sBAAsB,wBAAC,aAA4C;AAC5E,MAAI,SAAS,gBAAgB,cAAc;AACvC,UAAM,IAAI,MAAM,yCAAyC,SAAS,WAAW,EAAE;AAAA,EACnF;AAEA,QAAM,WAAW,qBAAqB,SAAS,QAAQ;AAEvD,MAAI,SAAS,kBAAkB;AAC3B,UAAM,IAAI,MAAM,yCAAyC;AACjE,GATmC;;;AFzEnC,IAAM,WAAW,oBAAI,KAAK,0BAA0B;AAEpD,IAAM,uCAAuC;AAC7C,IAAM,gCAAgC,IAAI,OAAO;AAEjD,IAAM,oBAAoB,wBAAC,aACvB,SAAS,WAAW,GAAG,KAAK,SAAS,SAAS,GAAG,IAAI,SAAS,MAAM,GAAG,EAAE,IAAI,UADvD;AAG1B,IAAM,qBAAqB,wBAAC,UAA0B;AAClD,QAAM,aAAa,MAAM,QAAQ,GAAG;AACpC,QAAM,WAAW,MAAM,QAAQ,GAAG;AAElC,MAAI,eAAe,MAAM,aAAa,GAAI,QAAO;AAEjD,QAAM,iBACF,eAAe,KACT,WACA,aAAa,KACb,aACA,KAAK,IAAI,YAAY,QAAQ;AAEvC,SAAO,GAAG,MAAM,MAAM,GAAG,cAAc,CAAC;AAC5C,GAd2B;AAgB3B,IAAM,YAAY,wBAAC,UAA0B;AACzC,MAAI;AACA,UAAM,MAAM,IAAI,IAAI,KAAK;AACzB,UAAM,WAAW,kBAAkB,IAAI,SAAS,YAAY,CAAC;AAC7D,UAAM,mBACF,CAAC,SAAS,SAAS,GAAG,KACtB,aAAa,eACb,SAAS,SAAS,YAAY,KAC9B,QAAQ,KAAK,QAAQ,KAAK,iBAAiB,QAAQ,CAAC;AACxD,UAAM,OAAO,mBAAmB,oBAAoB,IAAI;AAExD,WAAO,GAAG,IAAI,QAAQ,KAAK,IAAI,GAAG,IAAI,QAAQ,GAAG,IAAI,SAAS,gBAAgB,EAAE;AAAA,EACpF,QAAQ;AACJ,WAAO,mBAAmB,KAAK;AAAA,EACnC;AACJ,GAfkB;AAiBlB,IAAM,mBAAmB,oBAAI,IAAI,CAAC,KAAK,MAAM,MAAM,KAAM,KAAK,KAAK,KAAK,GAAG,CAAC;AAE5E,IAAM,mBAAmB,wBAAC,OAAe,cAA8B;AACnE,QAAM,YAAY,MAAM,QAAQ,WAAW,SAAS;AACpD,QAAM,aAAa,MAAM,QAAQ,YAAY,SAAS;AAEtD,MAAI,cAAc,GAAI,QAAO;AAC7B,MAAI,eAAe,GAAI,QAAO;AAE9B,SAAO,KAAK,IAAI,WAAW,UAAU;AACzC,GARyB;AAUzB,IAAM,aAAa,wBAAC,OAAe,cAA8B;AAC7D,MAAI,QAAQ;AAEZ,SAAO,QAAQ,MAAM,UAAU,CAAC,iBAAiB,IAAI,MAAM,KAAK,CAAE,EAAG,UAAS;AAE9E,SAAO;AACX,GANmB;AAQnB,IAAM,aAAa,wBAAC,UAA0B;AAC1C,MAAI,WAAW;AACf,MAAI,QAAQ;AAEZ,SAAO,QAAQ,MAAM,QAAQ;AACzB,UAAM,WAAW,iBAAiB,OAAO,KAAK;AAE9C,QAAI,aAAa,IAAI;AACjB,kBAAY,MAAM,MAAM,KAAK;AAC7B;AAAA,IACJ;AAEA,UAAM,SAAS,WAAW,OAAO,QAAQ;AAEzC,gBAAY,MAAM,MAAM,OAAO,QAAQ;AACvC,gBAAY,UAAU,MAAM,MAAM,UAAU,MAAM,CAAC;AACnD,YAAQ;AAAA,EACZ;AAEA,SAAO;AACX,GApBmB;AAsBnB,IAAM,cAAc,wBAAC,UACjB,WAAW,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,GADjD;AAGpB,IAAM,gBAAgB,wBAAC,YAA6B;AAChD,QAAM,QAAQ,QAAQ,MAAM,GAAG,EAAE,IAAI,UAAQ,OAAO,IAAI,CAAC;AAEzD,MAAI,MAAM,WAAW,KAAK,MAAM,KAAK,UAAQ,CAAC,OAAO,UAAU,IAAI,KAAK,OAAO,KAAK,OAAO,GAAG;AAC1F,WAAO;AAEX,QAAM,CAAC,GAAG,CAAC,IAAI;AAEf,MAAI,MAAM,KAAK,MAAM,MAAM,MAAM,OAAO,KAAK,IAAK,QAAO;AACzD,MAAI,MAAM,OAAO,KAAK,MAAM,KAAK,IAAK,QAAO;AAC7C,MAAI,MAAM,OAAO,MAAM,IAAK,QAAO;AACnC,MAAI,MAAM,OAAO,KAAK,MAAM,KAAK,GAAI,QAAO;AAC5C,MAAI,MAAM,OAAO,MAAM,IAAK,QAAO;AACnC,MAAI,MAAM,QAAQ,MAAM,MAAM,MAAM,IAAK,QAAO;AAEhD,SAAO;AACX,GAhBsB;AAkBtB,IAAM,gBAAgB,wBAAC,YAA6B;AAChD,QAAM,aAAa,QAAQ,YAAY;AAEvC,MAAI,eAAe,QAAQ,eAAe,MAAO,QAAO;AACxD,MAAI,WAAW,WAAW,IAAI,KAAK,WAAW,WAAW,IAAI,EAAG,QAAO;AACvE,MACI,WAAW,WAAW,KAAK,KAC3B,WAAW,WAAW,KAAK,KAC3B,WAAW,WAAW,KAAK,KAC3B,WAAW,WAAW,KAAK;AAE3B,WAAO;AAEX,QAAM,aAAa,WAAW,MAAM,8BAA8B;AAElE,SAAO,aAAa,cAAc,WAAW,CAAC,CAAE,IAAI;AACxD,GAhBsB;AAkBtB,IAAM,mBAAmB,wBAAC,YAA6B;AACnD,QAAM,UAAU,KAAK,OAAO;AAE5B,MAAI,YAAY,EAAG,QAAO,cAAc,OAAO;AAC/C,MAAI,YAAY,EAAG,QAAO,cAAc,OAAO;AAE/C,SAAO;AACX,GAPyB;AASzB,IAAM,uBAAuB,8BAAO,QAA8B;AAC9D,QAAM,MAAM,IAAI,IAAI,GAAG;AACvB,QAAM,WAAW,IAAI,SAAS,YAAY,EAAE,QAAQ,YAAY,EAAE;AAElE,MAAI,IAAI,aAAa,SAAU,OAAM,IAAI,MAAM,gCAAgC;AAC/E,MAAI,CAAC,SAAS,SAAS,GAAG,KAAK,aAAa,eAAe,SAAS,SAAS,YAAY,GAAG;AACxF,UAAM,IAAI,MAAM,qCAAqC;AAAA,EACzD;AAEA,MAAI,KAAK,QAAQ,GAAG;AAChB,QAAI,iBAAiB,QAAQ,EAAG,OAAM,IAAI,MAAM,qCAAqC;AAErF,WAAO;AAAA,EACX;AAEA,QAAM,YAAY,MAAM,OAAO,UAAU,EAAE,KAAK,MAAM,UAAU,KAAK,CAAC;AAEtE,MAAI,UAAU,WAAW,KAAK,UAAU,KAAK,aAAW,iBAAiB,QAAQ,OAAO,CAAC,GAAG;AACxF,UAAM,IAAI,MAAM,uDAAuD;AAAA,EAC3E;AAEA,SAAO;AACX,GAtB6B;AAwB7B,IAAM,mBAAmB,8BAAO,UAAoB,aAAsC;AACtF,QAAM,gBAAgB,OAAO,SAAS,QAAQ,IAAI,gBAAgB,CAAC;AAEnE,MAAI,OAAO,SAAS,aAAa,KAAK,gBAAgB,UAAU;AAC5D,UAAM,IAAI,MAAM,gCAAgC,QAAQ,QAAQ;AAAA,EACpE;AAEA,MAAI,CAAC,SAAS,MAAM;AAChB,UAAM,OAAO,MAAM,SAAS,KAAK;AAEjC,QAAI,OAAO,WAAW,MAAM,MAAM,IAAI,UAAU;AAC5C,YAAM,IAAI,MAAM,gCAAgC,QAAQ,QAAQ;AAAA,IACpE;AAEA,WAAO;AAAA,EACX;AAEA,QAAM,SAAS,SAAS,KAAK,UAAU;AACvC,QAAM,SAAmB,CAAC;AAC1B,MAAI,QAAQ;AAEZ,SAAO,MAAM;AACT,UAAM,EAAE,MAAM,MAAM,IAAI,MAAM,OAAO,KAAK;AAE1C,QAAI,KAAM;AAEV,aAAS,MAAM;AAEf,QAAI,QAAQ,UAAU;AAClB,YAAM,OAAO,OAAO;AAEpB,YAAM,IAAI,MAAM,gCAAgC,QAAQ,QAAQ;AAAA,IACpE;AAEA,WAAO,KAAK,OAAO,KAAK,KAAK,CAAC;AAAA,EAClC;AAEA,SAAO,OAAO,OAAO,MAAM,EAAE,SAAS,MAAM;AAChD,GAtCyB;AAwCzB,IAAM,uBAAuB,8BACzB,KACA,WACA,aACqB;AACrB,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,UAAU,WAAW,MAAM,WAAW,MAAM,GAAG,SAAS;AAE9D,MAAI;AACA,UAAM,WAAW,MAAM,MAAM,KAAK,EAAE,QAAQ,WAAW,OAAO,CAAC;AAE/D,QAAI,CAAC,SAAS,GAAI,OAAM,IAAI,MAAM,QAAQ,SAAS,MAAM,EAAE;AAE3D,WAAO,KAAK,MAAM,MAAM,iBAAiB,UAAU,QAAQ,CAAC;AAAA,EAChE,UAAE;AACE,iBAAa,OAAO;AAAA,EACxB;AACJ,GAjB6B;AAmB7B,IAAM,WAAW,wBAAC,UACd,QAAQ,KAAK,KAAK,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,GADtD;AAGjB,IAAM,sBAAsB,wBAAC,OAAgB,aACzC,MAAM,QAAQ,KAAK,KAAK,MAAM,KAAK,UAAQ,SAAS,QAAQ,GADpC;AAG5B,IAAM,OAAO,wBAAC,UAA2B,GAAG,gBAAgB,KAAK,CAAC;AAAA,GAArD;AAEb,IAAM,kBAAkB,wBAAC,YAA0C;AAC/D,MAAI,CAAC,SAAS,OAAO,EAAG,QAAO;AAE/B,MACI,oBAAoB,QAAQ,MAAM,wBAAwB,KAC1D,QAAQ,SAAS,0BACnB;AACE,WAAO;AAAA,EACX;AAEA,MACI,oBAAoB,QAAQ,MAAM,sBAAsB,KACxD,QAAQ,SAAS,wBACnB;AACE,WAAO;AAAA,EACX;AAEA,SAAO;AACX,GAlBwB;AAoBxB,IAAM,cAAc,wBAAC,MAAyB,QAAgB,cAA+B;AACzF,QAAM,SAAS,YAAY,SAAS;AAEpC,MAAI,SAAS,eAAgB,QAAO,iBAAiB,MAAM,QAAQ,MAAM;AAEzE,MAAI,SAAS,iBAAkB,QAAO,mBAAmB,MAAM,QAAQ,MAAM;AAE7E,MAAI,SAAS,eAAgB,QAAO,iBAAiB,MAAM,QAAQ,MAAM;AACzE,MAAI,SAAS,eAAgB,QAAO,gBAAgB,MAAM,QAAQ,MAAM;AAExE,SAAO,eAAe,MAAM,QAAQ,MAAM;AAC9C,GAXoB;AAapB,IAAM,kBAAkB,wBAAC,YACrB,SAAS,OAAO,KAAK,OAAO,QAAQ,OAAO,WAAW,QAAQ,KAAK,QAD/C;AAGxB,IAAM,aAAa,wBAAC,KAAY,MAAc,YAA0B;AACpE,MAAI,KAAK,MAAM,SAAS,EAAE,MAAM,SAAS,CAAC;AAC9C,GAFmB;AAInB,IAAM,cAAc,wBAAC,QAA+B,aAA+C;AAC/F,QAAM,OAA+B,CAAC;AAEtC,aAAW,UAAU,CAAC,QAAW,OAAO,WAAW,MAAM,QAAQ,GAAG;AAChE,QAAI;AACA,WAAK,UAAU,SAAS,IAAI,OAAO,GAAG,IAAI,MAAM;AAAA,IACpD,SAAS,OAAO;AACZ,eAAS;AAAA,QACL,+BAA+B,UAAU,SAAS,KAAK,YAAY,KAAK,CAAC;AAAA,MAC7E;AAAA,IACJ;AAAA,EACJ;AAEA,SAAO;AACX,GAdoB;AAgBpB,IAAM,qBAAqB,8BACvB,QACA,YACA,MACA,aACqB;AACrB,MAAI,CAAC,OAAO,OAAO,WAAY,QAAO,EAAE,YAAY,KAAK;AAEzD,MAAI;AACA,WAAO,EAAE,YAAY,MAAM,oBAAoB,MAAM,OAAO,OAAO,WAAW,UAAU,EAAE;AAAA,EAC9F,SAAS,OAAO;AACZ,aAAS,KAAK,2CAA2C,YAAY,KAAK,CAAC,EAAE;AAE7E,WAAO,EAAE,YAAY,KAAK;AAAA,EAC9B;AACJ,GAf2B;AAiB3B,IAAM,qBAAqB,8BACvB,QACA,aAGC;AACD,QAAM,WAKD,CAAC;AAEN,MAAI,OAAO,OAAO,QAAQ;AACtB,QAAI;AACA,YAAM,OAAO,OAAO,OAAO,OAAO;AAClC,YAAM,SAAS,MAAM,gBAAgB,IAAI;AAEzC,eAAS,KAAK;AAAA,QACV,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS,GAAG,IAAI;AAAA;AAAA,QAChB,WAAW;AAAA,MACf,CAAC;AAED,eAAS,KAAK;AAAA,QACV,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS,GAAG,MAAM,sBAAsB,OAAO,aAAa,CAAC;AAAA;AAAA,QAC7D,WAAW;AAAA,MACf,CAAC;AAAA,IACL,SAAS,OAAO;AACZ,eAAS,KAAK,6CAA6C,YAAY,KAAK,CAAC,EAAE;AAAA,IACnF;AAAA,EACJ,OAAO;AACH,aAAS;AAAA,MACL;AAAA,IACJ;AAAA,EACJ;AAEA,MAAI,OAAO,GAAG,SAAS;AACnB,UAAM,OAAkC,CAAC;AAEzC,eAAW,aAAa,CAAC,WAAW,WAAW,GAAY;AACvD,UAAI;AACA,aAAK,SAAS,IAAI,OAAO,GAAG,QAAQ,SAAS;AAAA,MACjD,SAAS,OAAO;AACZ,iBAAS,KAAK,oBAAoB,SAAS,SAAS,YAAY,KAAK,CAAC,EAAE;AAAA,MAC5E;AAAA,IACJ;AAEA,QAAI,OAAO,KAAK,IAAI,EAAE,SAAS,GAAG;AAC9B,eAAS,KAAK;AAAA,QACV,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS,KAAK,IAAI;AAAA,QAClB,WAAW;AAAA,MACf,CAAC;AAAA,IACL;AAAA,EACJ,OAAO;AACH,aAAS,KAAK,iEAAiE;AAAA,EACnF;AAEA,SAAO;AACX,GAhE2B;AAkE3B,IAAM,wBAAwB,wBAAC,YAAiC;AAC5D,MAAI,CAAC,SAAS,OAAO,EAAG,QAAO,CAAC;AAEhC,QAAM,WAAW,MAAM,QAAQ,QAAQ,gBAAgB,IACjD,QAAQ,mBACR,QAAQ,mBACR,CAAC,QAAQ,gBAAgB,IACzB,CAAC;AAEP,SAAO,SAAS;AAAA,IAAQ,YACpB,SAAS,MAAM,KAAK,OAAO,OAAO,yBAAyB,WACrD,CAAC,OAAO,oBAAoB,IAC5B,CAAC;AAAA,EACX;AACJ,GAd8B;AAgB9B,IAAM,qBAAqB,8BACvB,UACA,SACA,UACA,YAAY,sCACZ,WAAW,kCAC2C;AACtD,MAAI,CAAC,QAAS,QAAO,CAAC;AAEtB,QAAM,OAAO,CAAC,GAAG,IAAI,IAAI,SAAS,QAAQ,qBAAqB,CAAC,CAAC;AACjE,QAAM,UAAsD,CAAC;AAE7D,aAAW,OAAO,MAAM;AACpB,QAAI;AACA,YAAM,MAAM,MAAM,qBAAqB,GAAG;AAE1C,cAAQ,KAAK,EAAE,KAAK,SAAS,MAAM,qBAAqB,KAAK,WAAW,QAAQ,EAAE,CAAC;AAAA,IACvF,SAAS,OAAO;AACZ,eAAS;AAAA,QACL,0CAA0C,UAAU,GAAG,CAAC,KAAK,YAAY,KAAK,CAAC;AAAA,MACnF;AAAA,IACJ;AAAA,EACJ;AAEA,SAAO;AACX,GAzB2B;AA2B3B,IAAM,wBAAwB,8BAC1B,QACA,aACuB;AACvB,MAAI,OAAO,OAAO,yBAAyB;AACvC,QAAI;AACA,YAAM,WAAW,MAAM,OAAO,OAAO,wBAAwB;AAE7D,UAAI,SAAS,QAAQ,KAAK,MAAM,QAAQ,SAAS,QAAQ,GAAG;AACxD,iBAAS;AAAA,UACL,GAAG,SAAS,SACP,OAAO,aAAW,OAAO,YAAY,QAAQ,EAC7C,IAAI,aAAW,WAAW,OAAO,CAAC;AAAA,QAC3C;AAAA,MACJ;AAEA,aAAO,SAAS,QAAQ,KAAK,MAAM,QAAQ,SAAS,cAAc,IAC3D,SAAS,iBACV,CAAC;AAAA,IACX,SAAS,OAAO;AACZ,eAAS,KAAK,2CAA2C,YAAY,KAAK,CAAC,EAAE;AAAA,IACjF;AAAA,EACJ;AAEA,MAAI,CAAC,OAAO,OAAO,sBAAuB,QAAO,CAAC;AAElD,MAAI;AACA,UAAM,WAAW,MAAM,OAAO,OAAO,sBAAsB;AAE3D,QAAI,CAAC,SAAS,QAAQ,KAAK,CAAC,MAAM,QAAQ,SAAS,OAAO,EAAG,QAAO,CAAC;AAErE,WAAO,SAAS;AAAA,EACpB,SAAS,OAAO;AACZ,aAAS,KAAK,iDAAiD,YAAY,KAAK,CAAC,EAAE;AAEnF,WAAO,CAAC;AAAA,EACZ;AACJ,GArC8B;AAuCvB,IAAM,wBAAwB,8BACjC,QACA,UAAkC,CAAC,MACF;AACjC,QAAM,UAAU,QAAQ,WAAW;AAEnC,MAAI,WAAW,CAAC,QAAQ;AACpB,UAAM,IAAI,MAAM,6CAA6C;AAEjE,QAAM,WAAqB,CAAC;AAC5B,QAAM,MAAM,IAAI,MAAM;AACtB,QAAM,WAA2C,CAAC;AAClD,QAAM,aAAa,OAAO,GAAG,IAAI;AACjC,QAAM,OAAO,YAAY,QAAQ,QAAQ;AACzC,QAAM,cAAc,MAAM,mBAAmB,QAAQ,YAAY,MAAM,QAAQ;AAC/E,QAAM,qBAAkC,CAAC;AAEzC,QAAM,iBAAiB,8BAAO,UAWT;AACjB,UAAM,UAAU,MAAM,cAAc,MAAM,SAAS;AAAA,MAC/C,SAAS,MAAM,aAAa;AAAA,MAC5B,UAAU,QAAQ;AAAA,IACtB,CAAC;AACD,UAAM,OACF,QAAQ,aAAa,CAAC,MAAM,KAAK,SAAS,MAAM,IAAI,GAAG,MAAM,IAAI,SAAS,MAAM;AAEpF,eAAW,KAAK,MAAM,QAAQ,MAAM;AAEpC,aAAS,KAAK;AAAA,MACV,IAAI,MAAM;AAAA,MACV,MAAM,MAAM;AAAA,MACZ;AAAA,MACA,WAAW,MAAM,aAAa;AAAA,MAC9B,QAAQ,UAAU,QAAQ,MAAM;AAAA,MAChC,WAAW,QAAQ;AAAA,MACnB,WAAW,MAAM;AAAA,MACjB,cAAc,MAAM;AAAA,MACpB,gBAAgB,MAAM;AAAA,MACtB,UAAU,MAAM;AAAA,IACpB,CAAC;AAAA,EACL,GAjCuB;AAmCvB,aAAW,KAAK,aAAa,gBAAgB;AAC7C,aAAW,KAAK,kBAAkB,cAAc;AAEhD,QAAM,eAAe;AAAA,IACjB,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,MAAM;AAAA,IACN,SAAS,KAAK,WAAW;AAAA,IACzB,WAAW;AAAA,EACf,CAAC;AAED,aAAW,WAAW,MAAM,mBAAmB,QAAQ,QAAQ,GAAG;AAC9D,UAAM,eAAe,EAAE,GAAG,SAAS,IAAI,QAAQ,MAAM,WAAW,aAAa,CAAC;AAAA,EAClF;AAEA,QAAM,UAAU,MAAM,OAAO,MAAM,WAAW,IAAI;AAElD,aAAW,CAAC,aAAa,MAAM,KAAK,QAAQ,QAAQ,GAAG;AACnD,UAAM,gBAA0B,CAAC;AACjC,UAAM,SAAS;AAAA,MACX,gBAAgB,EAAE,aAAa,IAAI,OAAO,MAAM,MAAM,KAAK,OAAO,OAAO,KAAK,CAAC;AAAA,IACnF;AAEA,QAAI;AACA,YAAM,WAAW,MAAM,OAAO,KAAK,IAAI,OAAO,GAAG;AAEjD,UAAI,CAAC,UAAU;AACX,iBAAS,KAAK,sCAAsC,UAAU,OAAO,GAAG,CAAC,EAAE;AAC3E;AAAA,MACJ;AAEA,yBAAmB,KAAK,QAAQ;AAChC,YAAM,OAAO,gBAAgB,QAAQ;AACrC,YAAM,eAAe,gBAAgB,QAAQ;AAC7C,UAAI,SAAS,eAAgB,eAAc,KAAK,sCAAsC;AAEtF,YAAM,gBAAgB,cAAc,MAAM;AAE1C,YAAM,eAAe;AAAA,QACjB,IAAI;AAAA,QACJ,MAAM;AAAA,QACN,MAAM,YAAY,gBAAgB,QAAQ,OAAO;AAAA,QACjD,SAAS,KAAK,MAAM;AAAA,QACpB,WAAW;AAAA,QACX,WAAW,OAAO;AAAA,QAClB;AAAA,MACJ,CAAC;AAED,YAAM,eAAe;AAAA,QACjB,IAAI,cAAc,MAAM;AAAA,QACxB;AAAA,QACA,MAAM,YAAY,MAAM,QAAQ,OAAO;AAAA,QACvC,SAAS,KAAK,QAAQ;AAAA,QACtB,WAAW;AAAA,QACX,WAAW,OAAO;AAAA,QAClB;AAAA,QACA,gBAAgB;AAAA,QAChB,UAAU,cAAc,SAAS,IAAI,gBAAgB;AAAA,MACzD,CAAC;AAAA,IACL,SAAS,OAAO;AACZ,eAAS;AAAA,QACL,qCAAqC,UAAU,OAAO,GAAG,CAAC,KAAK,YAAY,KAAK,CAAC;AAAA,MACrF;AAAA,IACJ;AAAA,EACJ;AAEA,QAAM,iBAAiB,MAAM,sBAAsB,QAAQ,QAAQ;AAEnE,aAAW,iBAAiB,gBAAgB;AACxC,UAAM,SAAS,UAAU,gBAAgB,aAAa,CAAC;AAEvD,UAAM,eAAe;AAAA,MACjB,IAAI,cAAc,MAAM;AAAA,MACxB,MAAM;AAAA,MACN,MAAM,YAAY,kBAAkB,QAAQ,OAAO;AAAA,MACnD,SAAS,KAAK,aAAa;AAAA,MAC3B,WAAW;AAAA,IACf,CAAC;AAAA,EACL;AAEA,aAAW,cAAc,MAAM;AAAA,IAC3B;AAAA,IACA,QAAQ,oBAAoB;AAAA,IAC5B;AAAA,IACA,QAAQ;AAAA,IACR,QAAQ;AAAA,EACZ,GAAG;AACC,UAAM,SAAS,UAAU,WAAW,GAAG;AAEvC,UAAM,eAAe;AAAA,MACjB,IAAI,cAAc,MAAM;AAAA,MACxB,MAAM;AAAA,MACN,MAAM,YAAY,gBAAgB,QAAQ,OAAO;AAAA,MACjD,SAAS,KAAK,WAAW,OAAO;AAAA,MAChC,WAAW;AAAA,MACX,WAAW,WAAW;AAAA,IAC1B,CAAC;AAAA,EACL;AAEA,QAAM,WAAW,iBAAiB;AAAA,IAC9B,aAAa;AAAA,IACb,WAAW,QAAQ,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,IACvD;AAAA,IACA,YAAY;AAAA,IACZ,YAAY,UACN;AAAA,MACI,MAAM;AAAA,MACN,mBAAmB;AAAA,MACnB,UAAU;AAAA,MACV,KAAK;AAAA,MACL,QAAQ;AAAA,IACZ,IACA,EAAE,MAAM,QAAQ,mBAAmB,MAAM;AAAA,IAC/C;AAAA,IACA;AAAA,EACJ,CAAC;AAED,aAAW,KAAK,iBAAiB,GAAG,KAAK,UAAU,UAAU,MAAM,CAAC,CAAC;AAAA,CAAI;AAEzE,SAAO;AAAA,IACH,MAAM,MAAM,IAAI,cAAc,EAAE,MAAM,cAAc,aAAa,UAAU,CAAC;AAAA,IAC5E;AAAA,IACA;AAAA,EACJ;AACJ,GAhLqC;AAkL9B,IAAM,wBAAwB,8BACjC,QACA,YACiC;AACjC,QAAM,SAAS,MAAM,sBAAsB,QAAQ,OAAO;AAE1D,QAAM,MAAM,QAAQ,QAAQ,GAAG,GAAG,EAAE,WAAW,KAAK,CAAC;AACrD,QAAM,UAAU,QAAQ,KAAK,OAAO,IAAI;AAExC,SAAO;AACX,GAVqC;;;AGjoBrC,SAAS,gBAAgB;AAEzB,OAAOA,YAAW;AAclB,IAAM,2BAA2B,MAAM,OAAO;AAC9C,IAAM,0BAA0B,KAAK,OAAO;AAC5C,IAAM,yBAAyB,KAAK,OAAO;AAE3C,IAAM,aAAa,wBAAC,YAA4B,OAAO,WAAW,SAAS,MAAM,GAA9D;AAEnB,IAAM,aAAa,wBAAC,OAAe,MAAc,QAAsB;AACnE,MAAI,OAAO,IAAK,OAAM,IAAI,MAAM,GAAG,KAAK,YAAY,GAAG,QAAQ;AACnE,GAFmB;AAInB,IAAM,YAAY,wBAAC,SAAiB,OAAe,aAAgC;AAC/E,aAAW,OAAO,WAAW,OAAO,GAAG,QAAQ;AAE/C,SAAO,KAAK,MAAM,OAAO;AAC7B,GAJkB;AAMlB,IAAMC,eAAc,wBAAC,UACjB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,GADrC;AAGpB,IAAM,cAAc,wBAAC,SAAiB,OAAe,aAA8C;AAC/F,QAAM,QAAQ,UAAU,SAAS,OAAO,QAAQ;AAEhD,MAAI,CAAC,SAAS,OAAO,UAAU,YAAY,MAAM,QAAQ,KAAK,GAAG;AAC7D,UAAM,IAAI,MAAM,yDAAyD;AAAA,EAC7E;AAEA,SAAO;AACX,GARoB;AAUpB,IAAM,8BAA8B,wBAAC,UACjC,MAAM,SAAS,gBAAgB,MAAM,SAAS,gBADd;AAGpC,IAAM,uBAAuB,wBAAC,WAA6B;AACvD,MAAI,MAAM,QAAQ,MAAM,GAAG;AACvB,WAAO,OAAO,KAAK,UAAQ;AACvB,UAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO;AAE9C,YAAM,SAAS,YAAY,OAAO,KAAK,SAAS;AAEhD,aAAO,WAAW,YAAY,WAAW;AAAA,IAC7C,CAAC;AAAA,EACL;AAEA,MAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO;AAElD,QAAM,SAAS,YAAY,SAAS,OAAO,SAAS;AAEpD,SAAO,CAAC,MAAM,QAAQ,MAAM,KAAK,OAAO,SAAS;AACrD,GAhB6B;AAkB7B,IAAM,wBAAwB,8BAC1B,OACA,SACA,YACgB;AAChB,MAAI,CAAC,QAAQ,mBAAoB;AAEjC,MAAI,MAAM,SAAS,cAAc;AAC7B,QAAI,CAAC,QAAQ,OAAO,OAAO,kBAAkB;AACzC,YAAM,IAAI,MAAM,uDAAuD;AAAA,IAC3E;AAEA,UAAMC,gBAAe,MAAM,QAAQ,OAAO,OAAO,iBAAiB,OAAO;AAEzE,QAAI,qBAAqBA,aAAY,EAAG,OAAM,IAAI,MAAM,gCAAgC;AAExF;AAAA,EACJ;AAEA,MAAI,CAAC,QAAQ,OAAO,OAAO,oBAAoB;AAC3C,UAAM,IAAI,MAAM,yDAAyD;AAAA,EAC7E;AAEA,QAAM,eAAe,MAAM,QAAQ,OAAO,OAAO,mBAAmB,OAAO;AAE3E,MAAI,qBAAqB,YAAY,EAAG,OAAM,IAAI,MAAM,kCAAkC;AAC9F,GA1B8B;AA4BvB,IAAM,0BAA0B,8BACnC,MACA,UAAsC,CAAC,MACF;AACrC,QAAM,iBAAiB,QAAQ,kBAAkB;AACjD,QAAM,gBAAgB,QAAQ,iBAAiB;AAC/C,QAAM,eAAe,QAAQ,gBAAgB;AAE7C,aAAW,oBAAoB,KAAK,YAAY,cAAc;AAE9D,QAAM,MAAM,MAAMC,OAAM,UAAU,IAAI;AACtC,QAAM,eAAe,IAAI,KAAK,eAAe;AAE7C,MAAI,CAAC,aAAc,OAAM,IAAI,MAAM,2CAA2C;AAE9E,QAAM,kBAAkB,MAAM,aAAa,MAAM,QAAQ;AAEzD,aAAW,iBAAiB,WAAW,eAAe,GAAG,YAAY;AAErE,QAAM,WAAW,KAAK,MAAM,eAAe;AAE3C,sBAAoB,QAAQ;AAE5B,QAAM,WAAW,CAAC,GAAG,SAAS,QAAQ;AACtC,QAAM,UAAgD,CAAC;AACvD,QAAM,gBAAgB,QAAQ,WAAW;AACzC,MAAI,kBAAkB;AAEtB,aAAW,SAAS,SAAS,UAAU;AACnC,UAAM,OAAO,IAAI,KAAK,MAAM,IAAI;AAEhC,QAAI,CAAC,KAAM,OAAM,IAAI,MAAM,+BAA+B,MAAM,IAAI,EAAE;AAEtE,UAAM,SAAS,MAAM,KAAK,MAAM,QAAQ;AACxC,UAAM,cAAc,WAAW,MAAM;AAErC,eAAW,MAAM,MAAM,aAAa,aAAa;AAEjD,uBAAmB;AACnB,eAAW,4BAA4B,iBAAiB,cAAc;AAEtE,UAAM,YAAY,UAAU,MAAM;AAElC,QAAI,cAAc,MAAM,QAAQ;AAC5B,YAAM,IAAI,MAAM,wBAAwB,MAAM,IAAI,EAAE;AAAA,IACxD;AAEA,UAAM,UAAU,gBACV,MAAM,cAAc,QAAQ;AAAA,MACxB,WAAW,MAAM;AAAA,MACjB,UAAU,QAAQ;AAAA,IACtB,CAAC,IACD;AAEN,eAAW,GAAG,MAAM,IAAI,YAAY,WAAW,OAAO,GAAG,aAAa;AAEtE,YAAQ,KAAK,EAAE,GAAG,OAAO,QAAQ,CAAC;AAAA,EACtC;AAEA,SAAO,EAAE,UAAU,SAAS,SAAS;AACzC,GA5DuC;AA8DhC,IAAM,sBAAsB,8BAC/B,MACA,UAAsC,CAAC,MACF,wBAAwB,MAAM,SAAS,IAAI,GAAG,OAAO,GAH3D;AAK5B,IAAM,wBAAwB,8BACjC,MACA,YACuC;AACvC,QAAM,SAAS,MAAM,oBAAoB,MAAM,OAAO;AACtD,QAAM,eAAe,QAAQ,gBAAgB;AAC7C,QAAM,SAAsC;AAAA,IACxC,qBAAqB;AAAA,IACrB,uBAAuB;AAAA,IACvB,SAAS;AAAA,IACT,eAAe,CAAC;AAAA,IAChB,QAAQ,CAAC;AAAA,IACT,UAAU,CAAC,GAAG,OAAO,QAAQ;AAAA,EACjC;AAEA,MAAI,CAAC,QAAQ,oBAAoB;AAC7B,WAAO,SAAS;AAAA,MACZ;AAAA,IACJ;AAAA,EACJ;AAEA,QAAM,cAAc,IAAI,IAAI,OAAO,QAAQ,IAAI,WAAS,CAAC,MAAM,IAAI,KAAK,CAAC,CAAC;AAE1E,aAAW,SAAS,OAAO,SAAS;AAChC,QAAI,CAAC,4BAA4B,KAAK,GAAG;AACrC,aAAO,WAAW;AAClB,aAAO,cAAc,MAAM,IAAI,KAAK,OAAO,cAAc,MAAM,IAAI,KAAK,KAAK;AAC7E;AAAA,IACJ;AAEA,QAAI;AACA,YAAM,UAAU,UAAU,MAAM,SAAS,MAAM,MAAM,YAAY;AAEjE,YAAM,sBAAsB,OAAO,SAAS,OAAO;AAEnD,YAAM,SACF,QAAQ,OAAO,MAAM,WAAW,mBAChC,QAAQ,OAAO,MAAM,WAAW;AAEpC,UAAI,CAAC;AACD,cAAM,IAAI,MAAM,0DAA0D;AAE9E,YAAM,MAAM,MAAM,OAAO,OAAO;AAChC,YAAM,wBAAwB,MAAM,iBAC9B,YAAY,IAAI,MAAM,cAAc,IACpC;AAEN,UAAI,MAAM,kBAAkB,CAAC,uBAAuB;AAChD,cAAM,IAAI,MAAM,2BAA2B,MAAM,cAAc,aAAa;AAAA,MAChF;AAEA,YAAM,cAAc,wBACd;AAAA,QACI,sBAAsB;AAAA,QACtB,sBAAsB;AAAA,QACtB;AAAA,MACJ,IACA,EAAE,IAAI,MAAM,IAAI,IAAI;AAC1B,YAAM,WAAW,OAAO,YAAY,OAAO,WAAW,YAAY,KAAK,MAAM;AAE7E,YAAM,QAAQ,OAAO,MAAM,WAAW,IAAI;AAAA,QACtC,GAAG;AAAA,QACH,IAAI;AAAA,QACJ;AAAA,QACA,cAAc;AAAA,UACV,mBAAmB,OAAO,SAAS;AAAA,UACnC,WAAW,MAAM;AAAA,UACjB,YAAY,MAAM;AAAA,UAClB,cAAc,MAAM;AAAA,QACxB;AAAA,MACJ,CAAC;AAED,UAAI,MAAM,SAAS,eAAgB,QAAO,yBAAyB;AAAA,UAC9D,QAAO,uBAAuB;AAAA,IACvC,SAAS,OAAO;AACZ,aAAO,OAAO,KAAK,EAAE,MAAM,MAAM,MAAM,SAASF,aAAY,KAAK,EAAE,CAAC;AAAA,IACxE;AAAA,EACJ;AAEA,SAAO;AACX,GAhFqC;;;ACjKrC,SAAS,qBAAqB;AAe9B,IAAM,eAAe,wBAAC,WAA8C;AAChE,QAAM,YAAY,OAAO,QAAQ,KAAK,WAAS,MAAM,SAAS,kBAAkB;AAEhF,MAAI,CAAC,WAAW;AACZ,UAAM,IAAI;AAAA,MACN;AAAA,IACJ;AAAA,EACJ;AAEA,QAAM,OAAO,UAAU,QAAQ,KAAK;AAEpC,MAAI,CAAC,kBAAkB,KAAK,IAAI,GAAG;AAC/B,UAAM,IAAI;AAAA,MACN;AAAA,IACJ;AAAA,EACJ;AAEA,SAAO;AACX,GAlBqB;AAoBd,IAAM,8BAA8B,8BACvC,MACA,UAAsC,CAAC,MACrB,aAAa,MAAM,wBAAwB,MAAM,OAAO,CAAC,GAHpC;AAKpC,IAAM,0BAA0B,8BACnC,MACA,UAAsC,CAAC,MACrB,aAAa,MAAM,oBAAoB,MAAM,OAAO,CAAC,GAHpC;AAKhC,IAAM,iCAAiC,8BAC1C,MACA,YACwC;AACxC,QAAM,OAAO,MAAM,4BAA4B,MAAM,OAAO;AAE5D,SAAO,cAAc,EAAE,GAAG,QAAQ,MAAM,KAAK,CAAqB;AACtE,GAP8C;AASvC,IAAM,6BAA6B,8BACtC,MACA,YACwC;AACxC,QAAM,OAAO,MAAM,wBAAwB,MAAM,OAAO;AAExD,SAAO,cAAc,EAAE,GAAG,QAAQ,MAAM,KAAK,CAAqB;AACtE,GAP0C;",
4
+ "sourcesContent": ["import { lookup } from 'node:dns/promises';\nimport { mkdir, writeFile } from 'node:fs/promises';\nimport { isIP } from 'node:net';\nimport { dirname } from 'node:path';\n\nimport JSZip from 'jszip';\nimport { shareToRecoveryPhrase, splitPrivateKey } from '@learncard/sss-key-manager';\n\nimport type {\n BundleContentType,\n ExportLearnCardBundleOptions,\n JsonValue,\n LearnCardBundleEntryMetadata,\n LearnCardBundleOptions,\n LearnCardBundleResult,\n LearnCardBundleWallet,\n} from './types';\nimport { BUNDLE_README_MD, BUNDLE_SPEC_MD, finalizeManifest, SPEC_VERSION } from './manifest';\nimport { encodePayload, sha256Hex, stableStringify } from './crypto';\n\nconst ZIP_DATE = new Date('2024-01-01T00:00:00.000Z');\n\nconst DEFAULT_STATUS_LIST_FETCH_TIMEOUT_MS = 5000;\nconst DEFAULT_MAX_STATUS_LIST_BYTES = 5 * 1024 * 1024;\n\nconst stripIpv6Brackets = (hostname: string): string =>\n hostname.startsWith('[') && hostname.endsWith(']') ? hostname.slice(1, -1) : hostname;\n\nconst redactMalformedUrl = (value: string): string => {\n const queryIndex = value.indexOf('?');\n const ampIndex = value.indexOf('&');\n\n if (queryIndex === -1 && ampIndex === -1) return value;\n\n const redactionIndex =\n queryIndex === -1\n ? ampIndex\n : ampIndex === -1\n ? queryIndex\n : Math.min(queryIndex, ampIndex);\n\n return `${value.slice(0, redactionIndex)}?[redacted]`;\n};\n\nconst redactUrl = (value: string): string => {\n try {\n const url = new URL(value);\n const hostname = stripIpv6Brackets(url.hostname.toLowerCase());\n const shouldRedactHost =\n !hostname.includes('.') ||\n hostname === 'localhost' ||\n hostname.endsWith('.localhost') ||\n Boolean(isIP(hostname) && isPrivateAddress(hostname));\n const host = shouldRedactHost ? '[redacted-host]' : url.host;\n\n return `${url.protocol}//${host}${url.pathname}${url.search ? '?[redacted]' : ''}`;\n } catch {\n return redactMalformedUrl(value);\n }\n};\n\nconst urlEndDelimiters = new Set([' ', '\\n', '\\r', '\\t', \"'\", '\"', '<', '>']);\n\nconst findNextUrlStart = (value: string, fromIndex: number): number => {\n const httpIndex = value.indexOf('http://', fromIndex);\n const httpsIndex = value.indexOf('https://', fromIndex);\n\n if (httpIndex === -1) return httpsIndex;\n if (httpsIndex === -1) return httpIndex;\n\n return Math.min(httpIndex, httpsIndex);\n};\n\nconst findUrlEnd = (value: string, fromIndex: number): number => {\n let index = fromIndex;\n\n while (index < value.length && !urlEndDelimiters.has(value[index]!)) index += 1;\n\n return index;\n};\n\nconst redactText = (value: string): string => {\n let redacted = '';\n let index = 0;\n\n while (index < value.length) {\n const urlStart = findNextUrlStart(value, index);\n\n if (urlStart === -1) {\n redacted += value.slice(index);\n break;\n }\n\n const urlEnd = findUrlEnd(value, urlStart);\n\n redacted += value.slice(index, urlStart);\n redacted += redactUrl(value.slice(urlStart, urlEnd));\n index = urlEnd;\n }\n\n return redacted;\n};\n\nconst safeMessage = (error: unknown): string =>\n redactText(error instanceof Error ? error.message : String(error));\n\nconst isPrivateIPv4 = (address: string): boolean => {\n const parts = address.split('.').map(part => Number(part));\n\n if (parts.length !== 4 || parts.some(part => !Number.isInteger(part) || part < 0 || part > 255))\n return true;\n\n const [a, b] = parts;\n\n if (a === 0 || a === 10 || a === 127 || a >= 224) return true;\n if (a === 100 && b >= 64 && b <= 127) return true;\n if (a === 169 && b === 254) return true;\n if (a === 172 && b >= 16 && b <= 31) return true;\n if (a === 192 && b === 168) return true;\n if (a === 198 && (b === 18 || b === 19)) return true;\n\n return false;\n};\n\nconst isPrivateIPv6 = (address: string): boolean => {\n const normalized = address.toLowerCase();\n\n if (normalized === '::' || normalized === '::1') return true;\n if (normalized.startsWith('fc') || normalized.startsWith('fd')) return true;\n if (\n normalized.startsWith('fe8') ||\n normalized.startsWith('fe9') ||\n normalized.startsWith('fea') ||\n normalized.startsWith('feb')\n )\n return true;\n\n const ipv4Mapped = normalized.match(/::ffff:(\\d+\\.\\d+\\.\\d+\\.\\d+)$/);\n\n return ipv4Mapped ? isPrivateIPv4(ipv4Mapped[1]!) : false;\n};\n\nconst isPrivateAddress = (address: string): boolean => {\n const version = isIP(address);\n\n if (version === 4) return isPrivateIPv4(address);\n if (version === 6) return isPrivateIPv6(address);\n\n return true;\n};\n\nconst assertPublicHttpsUrl = async (uri: string): Promise<URL> => {\n const url = new URL(uri);\n const hostname = url.hostname.toLowerCase().replace(/^\\[|\\]$/g, '');\n\n if (url.protocol !== 'https:') throw new Error('status-list URL must use https');\n if (!hostname.includes('.') || hostname === 'localhost' || hostname.endsWith('.localhost')) {\n throw new Error('status-list URL host must be public');\n }\n\n if (isIP(hostname)) {\n if (isPrivateAddress(hostname)) throw new Error('status-list URL host must be public');\n\n return url;\n }\n\n const addresses = await lookup(hostname, { all: true, verbatim: true });\n\n if (addresses.length === 0 || addresses.some(address => isPrivateAddress(address.address))) {\n throw new Error('status-list URL host must resolve to public addresses');\n }\n\n return url;\n};\n\nconst readResponseText = async (response: Response, maxBytes: number): Promise<string> => {\n const contentLength = Number(response.headers.get('content-length'));\n\n if (Number.isFinite(contentLength) && contentLength > maxBytes) {\n throw new Error(`status-list response exceeds ${maxBytes} bytes`);\n }\n\n if (!response.body) {\n const text = await response.text();\n\n if (Buffer.byteLength(text, 'utf8') > maxBytes) {\n throw new Error(`status-list response exceeds ${maxBytes} bytes`);\n }\n\n return text;\n }\n\n const reader = response.body.getReader();\n const chunks: Buffer[] = [];\n let total = 0;\n\n while (true) {\n const { done, value } = await reader.read();\n\n if (done) break;\n\n total += value.byteLength;\n\n if (total > maxBytes) {\n await reader.cancel();\n\n throw new Error(`status-list response exceeds ${maxBytes} bytes`);\n }\n\n chunks.push(Buffer.from(value));\n }\n\n return Buffer.concat(chunks).toString('utf8');\n};\n\nconst fetchJsonWithTimeout = async (\n url: URL,\n timeoutMs: number,\n maxBytes: number\n): Promise<JsonValue> => {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n const response = await fetch(url, { signal: controller.signal });\n\n if (!response.ok) throw new Error(`HTTP ${response.status}`);\n\n return JSON.parse(await readResponseText(response, maxBytes)) as JsonValue;\n } finally {\n clearTimeout(timeout);\n }\n};\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n Boolean(value) && typeof value === 'object' && !Array.isArray(value);\n\nconst stringArrayIncludes = (value: unknown, expected: string): boolean =>\n Array.isArray(value) && value.some(item => item === expected);\n\nconst json = (value: unknown): string => `${stableStringify(value)}\\n`;\n\nconst classifyPayload = (payload: JsonValue): BundleContentType => {\n if (!isRecord(payload)) return 'unknown-json';\n\n if (\n stringArrayIncludes(payload.type, 'VerifiablePresentation') ||\n payload.type === 'VerifiablePresentation'\n ) {\n return 'presentation';\n }\n\n if (\n stringArrayIncludes(payload.type, 'VerifiableCredential') ||\n payload.type === 'VerifiableCredential'\n ) {\n return 'credential';\n }\n\n return 'unknown-json';\n};\n\nconst pathForType = (type: BundleContentType, digest: string, encrypted: boolean): string => {\n const suffix = encrypted ? '.enc' : '';\n\n if (type === 'presentation') return `presentations/${digest}.json${suffix}`;\n\n if (type === 'consent-record') return `consent-records/${digest}.json${suffix}`;\n\n if (type === 'index-record') return `index-records/${digest}.json${suffix}`;\n if (type === 'status-cache') return `status-cache/${digest}.json${suffix}`;\n\n return `credentials/${digest}.json${suffix}`;\n};\n\nconst getCredentialId = (payload: JsonValue): string | undefined =>\n isRecord(payload) && typeof payload.id === 'string' ? payload.id : undefined;\n\nconst addZipText = (zip: JSZip, path: string, content: string): void => {\n zip.file(path, content, { date: ZIP_DATE });\n};\n\nconst collectDids = (wallet: LearnCardBundleWallet, warnings: string[]): Record<string, string> => {\n const dids: Record<string, string> = {};\n\n for (const method of [undefined, 'key', 'pkh:sol', 'tz', 'pkh:tz']) {\n try {\n dids[method ?? 'default'] = wallet.id.did(method);\n } catch (error) {\n warnings.push(\n `Could not derive DID method ${method ?? 'default'}: ${safeMessage(error)}`\n );\n }\n }\n\n return dids;\n};\n\nconst collectDidDocument = async (\n wallet: LearnCardBundleWallet,\n primaryDid: string,\n dids: Record<string, string>,\n warnings: string[]\n): Promise<JsonValue> => {\n if (!wallet.invoke.resolveDid) return { primaryDid, dids };\n\n try {\n return { primaryDid, dids, primaryDidDocument: await wallet.invoke.resolveDid(primaryDid) };\n } catch (error) {\n warnings.push(`Could not resolve primary DID document: ${safeMessage(error)}`);\n\n return { primaryDid, dids };\n }\n};\n\nconst collectKeyPayloads = async (\n wallet: LearnCardBundleWallet,\n warnings: string[]\n): Promise<\n Array<{ path: string; type: BundleContentType; content: string; encrypted: boolean }>\n> => {\n const payloads: Array<{\n path: string;\n type: BundleContentType;\n content: string;\n encrypted: boolean;\n }> = [];\n\n if (wallet.invoke.getKey) {\n try {\n const seed = wallet.invoke.getKey();\n const shares = await splitPrivateKey(seed);\n\n payloads.push({\n path: 'keys/private-key-seed.txt',\n type: 'key-private-seed',\n content: `${seed}\\n`,\n encrypted: true,\n });\n\n payloads.push({\n path: 'keys/recovery-phrase.txt',\n type: 'key-recovery-phrase',\n content: `${await shareToRecoveryPhrase(shares.recoveryShare)}\\n`,\n encrypted: true,\n });\n } catch (error) {\n warnings.push(`Could not export seed or recovery phrase: ${safeMessage(error)}`);\n }\n } else {\n warnings.push(\n 'Wallet does not expose invoke.getKey(); private seed and recovery phrase were not exported'\n );\n }\n\n if (wallet.id.keypair) {\n const jwks: Record<string, JsonValue> = {};\n\n for (const algorithm of ['ed25519', 'secp256k1'] as const) {\n try {\n jwks[algorithm] = wallet.id.keypair(algorithm);\n } catch (error) {\n warnings.push(`Could not export ${algorithm} JWK: ${safeMessage(error)}`);\n }\n }\n\n if (Object.keys(jwks).length > 0) {\n payloads.push({\n path: 'keys/jwks.json',\n type: 'key-jwks',\n content: json(jwks),\n encrypted: true,\n });\n }\n } else {\n warnings.push('Wallet does not expose id.keypair(); JWK key export was skipped');\n }\n\n return payloads;\n};\n\nconst extractStatusListUrls = (payload: JsonValue): string[] => {\n if (!isRecord(payload)) return [];\n\n const statuses = Array.isArray(payload.credentialStatus)\n ? payload.credentialStatus\n : payload.credentialStatus\n ? [payload.credentialStatus]\n : [];\n\n return statuses.flatMap(status =>\n isRecord(status) && typeof status.statusListCredential === 'string'\n ? [status.statusListCredential]\n : []\n );\n};\n\nconst collectStatusLists = async (\n payloads: JsonValue[],\n enabled: boolean,\n warnings: string[],\n timeoutMs = DEFAULT_STATUS_LIST_FETCH_TIMEOUT_MS,\n maxBytes = DEFAULT_MAX_STATUS_LIST_BYTES\n): Promise<Array<{ uri: string; content: JsonValue }>> => {\n if (!enabled) return [];\n\n const urls = [...new Set(payloads.flatMap(extractStatusListUrls))];\n const results: Array<{ uri: string; content: JsonValue }> = [];\n\n for (const uri of urls) {\n try {\n const url = await assertPublicHttpsUrl(uri);\n\n results.push({ uri, content: await fetchJsonWithTimeout(url, timeoutMs, maxBytes) });\n } catch (error) {\n warnings.push(\n `Could not cache status-list credential ${redactUrl(uri)}: ${safeMessage(error)}`\n );\n }\n }\n\n return results;\n};\n\nconst collectConsentRecords = async (\n wallet: LearnCardBundleWallet,\n warnings: string[]\n): Promise<JsonValue[]> => {\n if (wallet.invoke.getHolderExportMetadata) {\n try {\n const metadata = await wallet.invoke.getHolderExportMetadata();\n\n if (isRecord(metadata) && Array.isArray(metadata.warnings)) {\n warnings.push(\n ...metadata.warnings\n .filter(warning => typeof warning === 'string')\n .map(warning => redactText(warning))\n );\n }\n\n return isRecord(metadata) && Array.isArray(metadata.consentRecords)\n ? (metadata.consentRecords as JsonValue[])\n : [];\n } catch (error) {\n warnings.push(`Could not fetch holder export metadata: ${safeMessage(error)}`);\n }\n }\n\n if (!wallet.invoke.getConsentedContracts) return [];\n\n try {\n const response = await wallet.invoke.getConsentedContracts();\n\n if (!isRecord(response) || !Array.isArray(response.records)) return [];\n\n return response.records as JsonValue[];\n } catch (error) {\n warnings.push(`Could not fetch consented contracts fallback: ${safeMessage(error)}`);\n\n return [];\n }\n};\n\nexport const createLearnCardBundle = async (\n wallet: LearnCardBundleWallet,\n options: LearnCardBundleOptions = {}\n): Promise<LearnCardBundleResult> => {\n const encrypt = options.encrypt ?? true;\n\n if (encrypt && !options.password)\n throw new Error('A password is required for LearnCard export');\n\n const warnings: string[] = [];\n const zip = new JSZip();\n const contents: LearnCardBundleEntryMetadata[] = [];\n const primaryDid = wallet.id.did();\n const dids = collectDids(wallet, warnings);\n const didDocument = await collectDidDocument(wallet, primaryDid, dids, warnings);\n const credentialPayloads: JsonValue[] = [];\n\n const addStoredEntry = async (entry: {\n id: string;\n type: BundleContentType;\n path: string;\n content: string;\n encrypted: boolean;\n mediaType?: string;\n sourceUri?: string;\n credentialId?: string;\n indexRecordRef?: string;\n warnings?: string[];\n }): Promise<void> => {\n const encoded = await encodePayload(entry.content, {\n encrypt: entry.encrypted && encrypt,\n password: options.password,\n });\n const path =\n encoded.encrypted && !entry.path.endsWith('.enc') ? `${entry.path}.enc` : entry.path;\n\n addZipText(zip, path, encoded.stored);\n\n contents.push({\n id: entry.id,\n type: entry.type,\n path,\n mediaType: entry.mediaType ?? 'application/json',\n sha256: sha256Hex(encoded.stored),\n encrypted: encoded.encrypted,\n sourceUri: entry.sourceUri,\n credentialId: entry.credentialId,\n indexRecordRef: entry.indexRecordRef,\n warnings: entry.warnings,\n });\n };\n\n addZipText(zip, 'README.md', BUNDLE_README_MD);\n addZipText(zip, 'BUNDLE_SPEC.md', BUNDLE_SPEC_MD);\n\n await addStoredEntry({\n id: 'did-document',\n type: 'did-document',\n path: 'keys/did-document.json',\n content: json(didDocument),\n encrypted: false,\n });\n\n for (const payload of await collectKeyPayloads(wallet, warnings)) {\n await addStoredEntry({ ...payload, id: payload.path, mediaType: 'text/plain' });\n }\n\n const records = await wallet.index.LearnCloud.get();\n\n for (const [recordIndex, record] of records.entries()) {\n const entryWarnings: string[] = [];\n const digest = sha256Hex(\n stableStringify({ recordIndex, id: record.id ?? null, uri: record.uri ?? null })\n );\n\n try {\n const resolved = await wallet.read.get(record.uri);\n\n if (!resolved) {\n warnings.push(`Could not resolve wallet index URI ${redactUrl(record.uri)}`);\n continue;\n }\n\n credentialPayloads.push(resolved);\n const type = classifyPayload(resolved);\n const credentialId = getCredentialId(resolved);\n if (type === 'unknown-json') entryWarnings.push('Payload is not a recognized VC or VP');\n\n const indexRecordId = `urn:sha256:${digest}:index-record`;\n\n await addStoredEntry({\n id: indexRecordId,\n type: 'index-record',\n path: pathForType('index-record', digest, encrypt),\n content: json(record),\n encrypted: true,\n sourceUri: record.uri,\n credentialId,\n });\n\n await addStoredEntry({\n id: `urn:sha256:${digest}`,\n type,\n path: pathForType(type, digest, encrypt),\n content: json(resolved),\n encrypted: true,\n sourceUri: record.uri,\n credentialId,\n indexRecordRef: indexRecordId,\n warnings: entryWarnings.length > 0 ? entryWarnings : undefined,\n });\n } catch (error) {\n warnings.push(\n `Could not export wallet index URI ${redactUrl(record.uri)}: ${safeMessage(error)}`\n );\n }\n }\n\n const consentRecords = await collectConsentRecords(wallet, warnings);\n\n for (const consentRecord of consentRecords) {\n const digest = sha256Hex(stableStringify(consentRecord));\n\n await addStoredEntry({\n id: `urn:sha256:${digest}`,\n type: 'consent-record',\n path: pathForType('consent-record', digest, encrypt),\n content: json(consentRecord),\n encrypted: true,\n });\n }\n\n for (const statusList of await collectStatusLists(\n credentialPayloads,\n options.fetchStatusLists ?? true,\n warnings,\n options.statusListFetchTimeoutMs,\n options.maxStatusListBytes\n )) {\n const digest = sha256Hex(statusList.uri);\n\n await addStoredEntry({\n id: `urn:sha256:${digest}`,\n type: 'status-cache',\n path: pathForType('status-cache', digest, encrypt),\n content: json(statusList.content),\n encrypted: true,\n sourceUri: statusList.uri,\n });\n }\n\n const manifest = finalizeManifest({\n specVersion: SPEC_VERSION,\n createdAt: options.createdAt ?? new Date().toISOString(),\n primaryDid,\n walletName: 'LearnCard',\n encryption: encrypt\n ? {\n mode: 'argon2id-aes-256-gcm',\n encryptedPayloads: true,\n envelope: 'sss-key-manager-encryptWithPassword-v1',\n kdf: 'argon2id',\n cipher: 'AES-256-GCM',\n }\n : { mode: 'none', encryptedPayloads: false },\n contents,\n warnings,\n });\n\n addZipText(zip, 'manifest.json', `${JSON.stringify(manifest, null, 2)}\\n`);\n\n return {\n data: await zip.generateAsync({ type: 'nodebuffer', compression: 'DEFLATE' }),\n manifest,\n warnings,\n };\n};\n\nexport const exportLearnCardBundle = async (\n wallet: LearnCardBundleWallet,\n options: ExportLearnCardBundleOptions\n): Promise<LearnCardBundleResult> => {\n const bundle = await createLearnCardBundle(wallet, options);\n\n await mkdir(dirname(options.out), { recursive: true });\n await writeFile(options.out, bundle.data);\n\n return bundle;\n};\n", "import { createHash } from 'node:crypto';\n\nimport { decryptWithPassword, encryptWithPassword } from '@learncard/sss-key-manager';\n\nimport type { EncryptedPayloadEnvelope } from './types';\n\nexport const sha256Hex = (bytes: string | Buffer): string =>\n createHash('sha256').update(bytes).digest('hex');\n\nexport const stableStringify = (value: unknown): string => {\n if (value === null || typeof value !== 'object') return JSON.stringify(value);\n\n if (Array.isArray(value)) return `[${value.map(stableStringify).join(',')}]`;\n\n const object = value as Record<string, unknown>;\n\n return `{${Object.keys(object)\n .sort()\n .map(key => `${JSON.stringify(key)}:${stableStringify(object[key])}`)\n .join(',')}}`;\n};\n\nexport const encodePayload = async (\n plaintext: string,\n options: { encrypt: boolean; password?: string }\n): Promise<{ stored: string; encrypted: boolean }> => {\n if (!options.encrypt) return { stored: plaintext, encrypted: false };\n\n if (!options.password)\n throw new Error('A password is required for encrypted LearnCard exports');\n\n return {\n stored: JSON.stringify(await encryptWithPassword(plaintext, options.password), null, 2),\n encrypted: true,\n };\n};\n\nexport const decodePayload = async (\n stored: string,\n options: { encrypted: boolean; password?: string }\n): Promise<string> => {\n if (!options.encrypted) return stored;\n\n if (!options.password)\n throw new Error('A password is required to decrypt this LearnCard export');\n\n const envelope = JSON.parse(stored) as EncryptedPayloadEnvelope;\n\n return decryptWithPassword(\n envelope.ciphertext,\n envelope.iv,\n envelope.salt,\n options.password,\n envelope.kdfParams\n );\n};\n", "import type { LearnCardBundleEntryMetadata, LearnCardBundleManifest } from './types';\nimport { stableStringify, sha256Hex } from './crypto';\n\nexport const SPEC_VERSION = '1.0.0' as const;\n\nexport const BUNDLE_SPEC_MD = `# LearnCard Holder Continuity Bundle v1.0.0\n\nA LearnCard holder continuity bundle is a ZIP file with readable metadata and encrypted holder payloads.\n\n## Container\n\nRequired readable entries:\n\n- \\`manifest.json\\` \u2014 inventory, hashes, warnings, and encryption metadata.\n- \\`README.md\\` \u2014 human-readable recovery notes.\n- \\`BUNDLE_SPEC.md\\` \u2014 this format description.\n\nSensitive entries use JSON encryption envelopes produced by \\`@learncard/sss-key-manager\\` \\`encryptWithPassword\\`: Argon2id key derivation and AES-GCM authenticated encryption. The ZIP itself is not password encrypted.\n\n## Security model\n\nThis bundle exports the wallet's full raw private-key seed at \\`keys/private-key-seed.txt.enc\\`. LearnCard's live wallet protects the key with 2-of-4 Shamir Secret Sharing, where no single share can reconstruct it. The bundle does NOT preserve that threshold: the exported seed alone is sufficient to take full control of the identity, and the bundle password is the only barrier protecting it. \\`keys/recovery-phrase.txt.enc\\` is derived from the current recovery share for reference and is not independently sufficient to recover the key. Treat the bundle like a password-vault backup, use a strong unique password, and rotate the wallet if the bundle is exposed.\n\n## Paths\n\n- \\`keys/recovery-phrase.txt.enc\\`\n- \\`keys/private-key-seed.txt.enc\\`\n- \\`keys/jwks.json.enc\\`\n- \\`keys/did-document.json\\`\n- \\`credentials/<sha256>.json.enc\\`\n- \\`presentations/<sha256>.json.enc\\`\n- \\`index-records/<sha256>.json.enc\\`\n- \\`consent-records/<sha256>.json.enc\\`\n- \\`status-cache/<sha256>.json.enc\\`\n\nDebug exports MAY use plaintext payloads by setting \\`encrypt: false\\`; production exports MUST encrypt sensitive payloads.\n\nStatus-list snapshot fetching is HTTPS-only and rejects private, loopback, link-local, and single-label hosts. Exporters SHOULD keep the default timeout and response-size caps unless they are running in a trusted local environment.\n\n## Manifest hashing\n\nEach \\`contents[]\\` entry contains the SHA-256 hash of the bytes stored at \\`path\\`. \\`payloadSha256\\` is SHA-256 over a deterministic JSON serialization of \\`contents[]\\` with entries sorted by path.\n\nEach credential or presentation entry MAY reference an encrypted \\`index-record\\` companion entry via \\`indexRecordRef\\`; the readable manifest does not embed the original index record JSON.\n\n## Restore vs import\n\n\\`restoreLearnCardFromBundle(...)\\` decrypts \\`keys/private-key-seed.txt.enc\\` and passes that seed to \\`initLearnCard(...)\\`. It recreates the original wallet identity; it does not upload payloads or recreate index records.\n\n\\`importLearnCardBundle(...)\\` decrypts credential and presentation payloads, uploads them to the target wallet's LearnCloud store, and recreates index records from the encrypted \\`index-record\\` companions.\n\nImport writes bundle contents into the target wallet. A bundle author who knows the password can include arbitrary credentials, presentations, and index metadata. Use \\`verifyBeforeImport: true\\` to verify VC/VP signatures before upload when the target wallet exposes \\`invoke.verifyCredential\\` and \\`invoke.verifyPresentation\\`.\n\n## Size limits\n\nReaders enforce default compressed-bundle, per-entry, and JSON parse limits to avoid accidentally processing oversized ZIP or JSON payloads. Callers can override these with \\`maxBundleBytes\\`, \\`maxEntryBytes\\`, and \\`maxJsonBytes\\` for trusted local workflows.\n\n## Import expectations\n\nImporters MUST verify the stored bytes against each entry hash before trusting decrypted content. Importers SHOULD verify issuer signatures before upload and preserve issuer-signed credential and presentation payloads exactly.\n`;\n\nexport const BUNDLE_README_MD = `# LearnCard Holder Continuity Export\n\nThis archive contains a point-in-time holder export from a LearnCard wallet.\n\nKeep the password separately. Without it, encrypted credentials, key material, consent records, and status-list snapshots cannot be recovered.\n\nThis archive contains your full private-key seed (encrypted). Anyone with both this file and its password can take complete control of your wallet identity, so store it like a password-vault backup and rotate your wallet if it is exposed.\n\nThe readable manifest lists every payload and its SHA-256 hash. Third-party wallets can import individual W3C Verifiable Credentials or Verifiable Presentations from the decrypted JSON files even when they do not support the LearnCard ZIP bundle directly.\n`;\n\nexport const sortContents = (\n contents: LearnCardBundleEntryMetadata[]\n): LearnCardBundleEntryMetadata[] => [...contents].sort((a, b) => a.path.localeCompare(b.path));\n\nconst normalizeContents = (\n contents: LearnCardBundleEntryMetadata[]\n): LearnCardBundleEntryMetadata[] =>\n JSON.parse(JSON.stringify(sortContents(contents))) as LearnCardBundleEntryMetadata[];\n\nexport const computePayloadSha256 = (contents: LearnCardBundleEntryMetadata[]): string =>\n sha256Hex(stableStringify(normalizeContents(contents)));\n\nexport const finalizeManifest = (\n manifest: Omit<LearnCardBundleManifest, 'payloadSha256'>\n): LearnCardBundleManifest => ({\n ...manifest,\n contents: normalizeContents(manifest.contents),\n payloadSha256: computePayloadSha256(manifest.contents),\n});\n\nexport const assertValidManifest = (manifest: LearnCardBundleManifest): void => {\n if (manifest.specVersion !== SPEC_VERSION) {\n throw new Error(`Unsupported LearnCard bundle version: ${manifest.specVersion}`);\n }\n\n const expected = computePayloadSha256(manifest.contents);\n\n if (manifest.payloadSha256 !== expected)\n throw new Error('LearnCard bundle manifest hash mismatch');\n};\n", "import { readFile } from 'node:fs/promises';\n\nimport JSZip from 'jszip';\n\nimport type {\n ImportLearnCardBundleOptions,\n ImportLearnCardBundleReport,\n JsonValue,\n LearnCardBundleEntryMetadata,\n LearnCardBundleManifest,\n ReadLearnCardBundleOptions,\n ReadLearnCardBundleResult,\n} from './types';\nimport { assertValidManifest } from './manifest';\nimport { decodePayload, sha256Hex } from './crypto';\n\nconst DEFAULT_MAX_BUNDLE_BYTES = 100 * 1024 * 1024;\nconst DEFAULT_MAX_ENTRY_BYTES = 25 * 1024 * 1024;\nconst DEFAULT_MAX_JSON_BYTES = 25 * 1024 * 1024;\n\nconst byteLength = (content: string): number => Buffer.byteLength(content, 'utf8');\n\nconst assertSize = (label: string, size: number, max: number): void => {\n if (size > max) throw new Error(`${label} exceeds ${max} bytes`);\n};\n\nconst parseJson = (content: string, label: string, maxBytes: number): JsonValue => {\n assertSize(label, byteLength(content), maxBytes);\n\n return JSON.parse(content) as JsonValue;\n};\n\nconst safeMessage = (error: unknown): string =>\n error instanceof Error ? error.message : String(error);\n\nconst parseObject = (content: string, label: string, maxBytes: number): Record<string, unknown> => {\n const value = parseJson(content, label, maxBytes);\n\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n throw new Error('Expected bundle metadata entry to contain a JSON object');\n }\n\n return value as Record<string, unknown>;\n};\n\nconst isImportableCredentialEntry = (entry: LearnCardBundleEntryMetadata): boolean =>\n entry.type === 'credential' || entry.type === 'presentation';\n\nconst isFailedVerification = (result: unknown): boolean => {\n if (Array.isArray(result)) {\n return result.some(item => {\n if (!item || typeof item !== 'object') return true;\n\n const status = 'status' in item ? item.status : undefined;\n\n return status === 'Failed' || status === 'Error';\n });\n }\n\n if (!result || typeof result !== 'object') return true;\n\n const errors = 'errors' in result ? result.errors : undefined;\n\n return !Array.isArray(errors) || errors.length > 0;\n};\n\nconst verifyImportableEntry = async (\n entry: LearnCardBundleEntryMetadata,\n content: JsonValue,\n options: ImportLearnCardBundleOptions\n): Promise<void> => {\n if (!options.verifyBeforeImport) return;\n\n if (entry.type === 'credential') {\n if (!options.wallet.invoke.verifyCredential) {\n throw new Error('Target wallet does not expose invoke.verifyCredential');\n }\n\n const verification = await options.wallet.invoke.verifyCredential(content);\n\n if (isFailedVerification(verification)) throw new Error('Credential verification failed');\n\n return;\n }\n\n if (!options.wallet.invoke.verifyPresentation) {\n throw new Error('Target wallet does not expose invoke.verifyPresentation');\n }\n\n const verification = await options.wallet.invoke.verifyPresentation(content);\n\n if (isFailedVerification(verification)) throw new Error('Presentation verification failed');\n};\n\nexport const readLearnCardBundleData = async (\n data: Buffer,\n options: ReadLearnCardBundleOptions = {}\n): Promise<ReadLearnCardBundleResult> => {\n const maxBundleBytes = options.maxBundleBytes ?? DEFAULT_MAX_BUNDLE_BYTES;\n const maxEntryBytes = options.maxEntryBytes ?? DEFAULT_MAX_ENTRY_BYTES;\n const maxJsonBytes = options.maxJsonBytes ?? DEFAULT_MAX_JSON_BYTES;\n\n assertSize('LearnCard bundle', data.byteLength, maxBundleBytes);\n\n const zip = await JSZip.loadAsync(data);\n const manifestFile = zip.file('manifest.json');\n\n if (!manifestFile) throw new Error('LearnCard bundle is missing manifest.json');\n\n const manifestContent = await manifestFile.async('string');\n\n assertSize('manifest.json', byteLength(manifestContent), maxJsonBytes);\n\n const manifest = JSON.parse(manifestContent) as LearnCardBundleManifest;\n\n assertValidManifest(manifest);\n\n const warnings = [...manifest.warnings];\n const entries: ReadLearnCardBundleResult['entries'] = [];\n const shouldDecrypt = options.decrypt ?? true;\n let totalEntryBytes = 0;\n\n for (const entry of manifest.contents) {\n const file = zip.file(entry.path);\n\n if (!file) throw new Error(`LearnCard bundle is missing ${entry.path}`);\n\n const stored = await file.async('string');\n const storedBytes = byteLength(stored);\n\n assertSize(entry.path, storedBytes, maxEntryBytes);\n\n totalEntryBytes += storedBytes;\n assertSize('LearnCard bundle entries', totalEntryBytes, maxBundleBytes);\n\n const actualSha = sha256Hex(stored);\n\n if (actualSha !== entry.sha256) {\n throw new Error(`SHA-256 mismatch for ${entry.path}`);\n }\n\n const content = shouldDecrypt\n ? await decodePayload(stored, {\n encrypted: entry.encrypted,\n password: options.password,\n })\n : stored;\n\n assertSize(`${entry.path} content`, byteLength(content), maxEntryBytes);\n\n entries.push({ ...entry, content });\n }\n\n return { manifest, entries, warnings };\n};\n\nexport const readLearnCardBundle = async (\n path: string,\n options: ReadLearnCardBundleOptions = {}\n): Promise<ReadLearnCardBundleResult> => readLearnCardBundleData(await readFile(path), options);\n\nexport const importLearnCardBundle = async (\n path: string,\n options: ImportLearnCardBundleOptions\n): Promise<ImportLearnCardBundleReport> => {\n const bundle = await readLearnCardBundle(path, options);\n const maxJsonBytes = options.maxJsonBytes ?? DEFAULT_MAX_JSON_BYTES;\n const report: ImportLearnCardBundleReport = {\n importedCredentials: 0,\n importedPresentations: 0,\n skipped: 0,\n skippedByType: {},\n errors: [],\n warnings: [...bundle.warnings],\n };\n\n if (!options.verifyBeforeImport) {\n report.warnings.push(\n 'Bundle credential signatures were not verified before import; only import bundles from sources you trust.'\n );\n }\n\n const entriesById = new Map(bundle.entries.map(entry => [entry.id, entry]));\n\n for (const entry of bundle.entries) {\n if (!isImportableCredentialEntry(entry)) {\n report.skipped += 1;\n report.skippedByType[entry.type] = (report.skippedByType[entry.type] ?? 0) + 1;\n continue;\n }\n\n try {\n const content = parseJson(entry.content, entry.path, maxJsonBytes);\n\n await verifyImportableEntry(entry, content, options);\n\n const upload =\n options.wallet.store.LearnCloud.uploadEncrypted ??\n options.wallet.store.LearnCloud.upload;\n\n if (!upload)\n throw new Error('Target wallet does not expose a LearnCloud upload method');\n\n const uri = await upload(content);\n const referencedIndexRecord = entry.indexRecordRef\n ? entriesById.get(entry.indexRecordRef)\n : undefined;\n\n if (entry.indexRecordRef && !referencedIndexRecord) {\n throw new Error(`Referenced index record ${entry.indexRecordRef} is missing`);\n }\n\n const indexRecord = referencedIndexRecord\n ? parseObject(\n referencedIndexRecord.content,\n referencedIndexRecord.path,\n maxJsonBytes\n )\n : { id: entry.id, uri };\n const recordId = typeof indexRecord.id === 'string' ? indexRecord.id : entry.id;\n\n await options.wallet.index.LearnCloud.add({\n ...indexRecord,\n id: recordId,\n uri,\n sourceExport: {\n manifestCreatedAt: bundle.manifest.createdAt,\n sourceUri: entry.sourceUri,\n sourcePath: entry.path,\n credentialId: entry.credentialId,\n },\n });\n\n if (entry.type === 'presentation') report.importedPresentations += 1;\n else report.importedCredentials += 1;\n } catch (error) {\n report.errors.push({ path: entry.path, message: safeMessage(error) });\n }\n }\n\n return report;\n};\n", "import { initLearnCard } from '@learncard/init';\nimport type { InitLearnCard } from '@learncard/init';\n\nimport { readLearnCardBundle, readLearnCardBundleData } from './importBundle';\nimport type { ReadLearnCardBundleOptions, ReadLearnCardBundleResult } from './types';\n\ntype SeededInitConfig = Extract<InitLearnCard['args'], { seed: string }>;\ntype DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;\n\nexport type RestoreLearnCardInit = DistributiveOmit<SeededInitConfig, 'seed'>;\n\nexport type RestoreLearnCardFromBundleOptions = ReadLearnCardBundleOptions & {\n init: RestoreLearnCardInit;\n};\n\nconst getSeedEntry = (bundle: ReadLearnCardBundleResult): string => {\n const seedEntry = bundle.entries.find(entry => entry.type === 'key-private-seed');\n\n if (!seedEntry) {\n throw new Error(\n 'LearnCard bundle does not contain key-private-seed and cannot be restored'\n );\n }\n\n const seed = seedEntry.content.trim();\n\n if (!/^[0-9a-f]{64}$/i.test(seed)) {\n throw new Error(\n 'LearnCard bundle key-private-seed must be exactly 64 hexadecimal characters'\n );\n }\n\n return seed;\n};\n\nexport const readLearnCardBundleSeedData = async (\n data: Buffer,\n options: ReadLearnCardBundleOptions = {}\n): Promise<string> => getSeedEntry(await readLearnCardBundleData(data, options));\n\nexport const readLearnCardBundleSeed = async (\n path: string,\n options: ReadLearnCardBundleOptions = {}\n): Promise<string> => getSeedEntry(await readLearnCardBundle(path, options));\n\nexport const restoreLearnCardFromBundleData = async (\n data: Buffer,\n options: RestoreLearnCardFromBundleOptions\n): Promise<InitLearnCard['returnValue']> => {\n const seed = await readLearnCardBundleSeedData(data, options);\n\n return initLearnCard({ ...options.init, seed } as SeededInitConfig);\n};\n\nexport const restoreLearnCardFromBundle = async (\n path: string,\n options: RestoreLearnCardFromBundleOptions\n): Promise<InitLearnCard['returnValue']> => {\n const seed = await readLearnCardBundleSeed(path, options);\n\n return initLearnCard({ ...options.init, seed } as SeededInitConfig);\n};\n"],
5
+ "mappings": "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",
6
6
  "names": ["JSZip", "safeMessage", "verification", "JSZip"]
7
7
  }
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export { createLearnCardBundle, exportLearnCardBundle } from './exportBundle';
2
- export { importLearnCardBundle, readLearnCardBundle, readLearnCardBundleData } from './importBundle';
2
+ export { importLearnCardBundle, readLearnCardBundle, readLearnCardBundleData, } from './importBundle';
3
3
  export { assertValidManifest, computePayloadSha256, finalizeManifest } from './manifest';
4
4
  export { readLearnCardBundleSeed, readLearnCardBundleSeedData, restoreLearnCardFromBundle, restoreLearnCardFromBundleData, } from './restoreBundle';
5
5
  export type { ExportLearnCardBundleOptions, ImportLearnCardBundleOptions, ImportLearnCardBundleReport, LearnCardBundleManifest, LearnCardBundleOptions, LearnCardBundleResult, LearnCardBundleWallet, ReadLearnCardBundleOptions, ReadLearnCardBundleResult, } from './types';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAC9E,OAAO,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AACrG,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACzF,OAAO,EACH,uBAAuB,EACvB,2BAA2B,EAC3B,0BAA0B,EAC1B,8BAA8B,GACjC,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACR,4BAA4B,EAC5B,4BAA4B,EAC5B,2BAA2B,EAC3B,uBAAuB,EACvB,sBAAsB,EACtB,qBAAqB,EACrB,qBAAqB,EACrB,0BAA0B,EAC1B,yBAAyB,GAC5B,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,iCAAiC,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAC9E,OAAO,EACH,qBAAqB,EACrB,mBAAmB,EACnB,uBAAuB,GAC1B,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AACzF,OAAO,EACH,uBAAuB,EACvB,2BAA2B,EAC3B,0BAA0B,EAC1B,8BAA8B,GACjC,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACR,4BAA4B,EAC5B,4BAA4B,EAC5B,2BAA2B,EAC3B,uBAAuB,EACvB,sBAAsB,EACtB,qBAAqB,EACrB,qBAAqB,EACrB,0BAA0B,EAC1B,yBAAyB,GAC5B,MAAM,SAAS,CAAC;AACjB,YAAY,EAAE,iCAAiC,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@learncard/holder-continuity",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Holder continuity bundle helpers for LearnCard wallets",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/holder-continuity.esm.js",
@@ -22,9 +22,9 @@
22
22
  },
23
23
  "dependencies": {
24
24
  "jszip": "^3.10.1",
25
- "@learncard/init": "2.3.20",
26
- "@learncard/sss-key-manager": "0.1.10",
27
- "@learncard/types": "5.17.0"
25
+ "@learncard/sss-key-manager": "0.1.12",
26
+ "@learncard/init": "2.4.0",
27
+ "@learncard/types": "5.17.2"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@types/node": "^18.19.68",