selfstore 1.8.26 → 1.8.28

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.
Files changed (36) hide show
  1. package/dist/advanced.js +4 -4
  2. package/dist/backups.js +2 -2
  3. package/dist/{cache-lock-VVAB3CDB.js → cache-lock-RGP74GXQ.js} +3 -3
  4. package/dist/{cache-lock-VVAB3CDB.js.map → cache-lock-RGP74GXQ.js.map} +1 -1
  5. package/dist/{chunk-RVOBONZF.js → chunk-7U5XMKVP.js} +22 -11
  6. package/dist/chunk-7U5XMKVP.js.map +1 -0
  7. package/dist/{chunk-2PIYIIHY.js → chunk-A6OQP7DR.js} +4 -4
  8. package/dist/{chunk-2PIYIIHY.js.map → chunk-A6OQP7DR.js.map} +1 -1
  9. package/dist/{chunk-AZWS7YC3.js → chunk-GM47BISW.js} +52 -67
  10. package/dist/chunk-GM47BISW.js.map +1 -0
  11. package/dist/{chunk-5UYPKCDB.js → chunk-H2T4S3KM.js} +11 -8
  12. package/dist/chunk-H2T4S3KM.js.map +1 -0
  13. package/dist/{chunk-FQ5O4PHK.js → chunk-JDDWWQEB.js} +6 -6
  14. package/dist/{chunk-FQ5O4PHK.js.map → chunk-JDDWWQEB.js.map} +1 -1
  15. package/dist/{chunk-LQS7AMOD.js → chunk-Q3NO477P.js} +3 -3
  16. package/dist/{chunk-LQS7AMOD.js.map → chunk-Q3NO477P.js.map} +1 -1
  17. package/dist/flows.js +4 -4
  18. package/dist/groups.js +1 -1
  19. package/dist/index.js +9 -9
  20. package/dist/kdf-worker.js +136 -1853
  21. package/dist/kdf-worker.js.map +1 -1
  22. package/dist/local-S3WUZSDX.js +8 -0
  23. package/dist/{local-GGAMRY23.js.map → local-S3WUZSDX.js.map} +1 -1
  24. package/dist/{manager-drive-2IUE4WQ2.js → manager-drive-T3RXUWAY.js} +4 -4
  25. package/dist/{manager-drive-2IUE4WQ2.js.map → manager-drive-T3RXUWAY.js.map} +1 -1
  26. package/dist/{s3-ABKUTTXE.js → s3-ORDHS7G3.js} +4 -4
  27. package/dist/s3-ORDHS7G3.js.map +1 -0
  28. package/dist/{webdav-5SHNR7CL.js → webdav-PXKELPA4.js} +4 -4
  29. package/dist/{webdav-5SHNR7CL.js.map → webdav-PXKELPA4.js.map} +1 -1
  30. package/dist/widgets.js +5 -5
  31. package/package.json +4 -3
  32. package/dist/chunk-5UYPKCDB.js.map +0 -1
  33. package/dist/chunk-AZWS7YC3.js.map +0 -1
  34. package/dist/chunk-RVOBONZF.js.map +0 -1
  35. package/dist/local-GGAMRY23.js +0 -8
  36. package/dist/s3-ABKUTTXE.js.map +0 -1
@@ -0,0 +1,8 @@
1
+ export { datedName, downloadBlob, pickFromDisk, pickSaveHandle, saveToDisk, writeToHandle } from './chunk-Q3NO477P.js';
2
+ import './chunk-7U5XMKVP.js';
3
+ import './chunk-F4ZZEJ5H.js';
4
+ import './chunk-H2T4S3KM.js';
5
+ import './chunk-WXI2NAPA.js';
6
+ import './chunk-CSYEIXNY.js';
7
+ //# sourceMappingURL=local-S3WUZSDX.js.map
8
+ //# sourceMappingURL=local-S3WUZSDX.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"local-GGAMRY23.js"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"local-S3WUZSDX.js"}
@@ -2,10 +2,10 @@ export { createBackupsManager, driveBackupsHost } from './chunk-5DAPYC2K.js';
2
2
  import './chunk-2BNTCXQN.js';
3
3
  import './chunk-25U6AKIX.js';
4
4
  import './chunk-LF3CC2P3.js';
5
- import './chunk-RVOBONZF.js';
5
+ import './chunk-7U5XMKVP.js';
6
6
  import './chunk-F4ZZEJ5H.js';
7
- import './chunk-5UYPKCDB.js';
7
+ import './chunk-H2T4S3KM.js';
8
8
  import './chunk-WXI2NAPA.js';
9
9
  import './chunk-CSYEIXNY.js';
10
- //# sourceMappingURL=manager-drive-2IUE4WQ2.js.map
11
- //# sourceMappingURL=manager-drive-2IUE4WQ2.js.map
10
+ //# sourceMappingURL=manager-drive-T3RXUWAY.js.map
11
+ //# sourceMappingURL=manager-drive-T3RXUWAY.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"manager-drive-2IUE4WQ2.js"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"manager-drive-T3RXUWAY.js"}
@@ -1,12 +1,12 @@
1
1
  export { connect, fromSession } from './chunk-IDW3WQKF.js';
2
2
  import './chunk-FJGWTBAL.js';
3
3
  import './chunk-LF3CC2P3.js';
4
- import './chunk-RVOBONZF.js';
4
+ import './chunk-7U5XMKVP.js';
5
5
  import './chunk-QBCU7OOP.js';
6
6
  import './chunk-F4ZZEJ5H.js';
7
- import './chunk-5UYPKCDB.js';
7
+ import './chunk-H2T4S3KM.js';
8
8
  import './chunk-QSLHEE2L.js';
9
9
  import './chunk-WXI2NAPA.js';
10
10
  import './chunk-CSYEIXNY.js';
11
- //# sourceMappingURL=s3-ABKUTTXE.js.map
12
- //# sourceMappingURL=s3-ABKUTTXE.js.map
11
+ //# sourceMappingURL=s3-ORDHS7G3.js.map
12
+ //# sourceMappingURL=s3-ORDHS7G3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"s3-ORDHS7G3.js"}
@@ -1,10 +1,10 @@
1
1
  export { connect, fromSession, peer } from './chunk-GHSHIDF3.js';
2
2
  import './chunk-LF3CC2P3.js';
3
- import './chunk-RVOBONZF.js';
3
+ import './chunk-7U5XMKVP.js';
4
4
  import './chunk-QBCU7OOP.js';
5
5
  import './chunk-F4ZZEJ5H.js';
6
- import './chunk-5UYPKCDB.js';
6
+ import './chunk-H2T4S3KM.js';
7
7
  import './chunk-WXI2NAPA.js';
8
8
  import './chunk-CSYEIXNY.js';
9
- //# sourceMappingURL=webdav-5SHNR7CL.js.map
10
- //# sourceMappingURL=webdav-5SHNR7CL.js.map
9
+ //# sourceMappingURL=webdav-PXKELPA4.js.map
10
+ //# sourceMappingURL=webdav-PXKELPA4.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"webdav-5SHNR7CL.js"}
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"webdav-PXKELPA4.js"}
package/dist/widgets.js CHANGED
@@ -1,13 +1,13 @@
1
- import { saveToDisk, datedName } from './chunk-LQS7AMOD.js';
2
- import { connectFlow, shareFlow, joinFlow } from './chunk-2PIYIIHY.js';
3
- import './chunk-FQ5O4PHK.js';
1
+ import { saveToDisk, datedName } from './chunk-Q3NO477P.js';
2
+ import { connectFlow, shareFlow, joinFlow } from './chunk-A6OQP7DR.js';
3
+ import './chunk-JDDWWQEB.js';
4
4
  import { isOpenSupported } from './chunk-2TIRUEXR.js';
5
5
  import './chunk-2BNTCXQN.js';
6
6
  import './chunk-25U6AKIX.js';
7
7
  import './chunk-LF3CC2P3.js';
8
- import './chunk-RVOBONZF.js';
8
+ import './chunk-7U5XMKVP.js';
9
9
  import './chunk-F4ZZEJ5H.js';
10
- import './chunk-5UYPKCDB.js';
10
+ import './chunk-H2T4S3KM.js';
11
11
  import './chunk-WXI2NAPA.js';
12
12
  import './chunk-CSYEIXNY.js';
13
13
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "selfstore",
3
- "version": "1.8.26",
3
+ "version": "1.8.28",
4
4
  "description": "Local-first storage for browser apps: an IndexedDB working copy, portable encrypted ZIP backups (AES-256-GCM over Argon2id), durable homes (disk, Google Drive, WebDAV) and a serverless multi-device merge.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -102,7 +102,8 @@
102
102
  "audit": "npm audit --audit-level=high",
103
103
  "secrets": "gitleaks detect --source . --redact --no-banner",
104
104
  "paquet": "npm pack --dry-run",
105
- "verifier": "npm run gate && npm run audit && npm run secrets && npm run build && npm run paquet",
105
+ "worker-size": "node scripts/worker-size.mjs",
106
+ "verifier": "npm run gate && npm run audit && npm run secrets && npm run build && npm run worker-size && npm run paquet",
106
107
  "prepare": "simple-git-hooks",
107
108
  "prepublishOnly": "npm run typecheck && npm test && npm run build",
108
109
  "consumers": "node scripts/verify-consumers.mjs"
@@ -136,7 +137,7 @@
136
137
  "eslint-plugin-sonarjs": "^4.2.0",
137
138
  "fake-indexeddb": "^6.2.5",
138
139
  "globals": "^17.7.0",
139
- "happy-dom": "^20.10.6",
140
+ "happy-dom": "^21.0.1",
140
141
  "jscpd": "^5.0.12",
141
142
  "knip": "^6.29.0",
142
143
  "lint-staged": "^17.2.0",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/selfstore/argon2.ts","../src/selfstore/kdf.ts","../src/selfstore/crypto.ts"],"names":[],"mappings":"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","file":"chunk-5UYPKCDB.js","sourcesContent":["// The one Argon2id call, shared by the calling-thread fallback and the KDF\n// worker so both derive byte-identical keys. hash-wasm loads dynamically -\n// only when a password is actually used.\n\nimport { fromBase64 } from './base64';\n\n/** AES-256 key length. */\nexport const KEY_BYTES = 32;\n\n/** One key-derivation job (postMessage-friendly: plain fields only). */\nexport interface KdfJob {\n\tid: number;\n\tpassword: string;\n\t/** Base64, exactly as stored in the backup header. */\n\tsalt: string;\n\t/** Memory cost in KiB. */\n\tm: number;\n\t/** Iterations (passes). */\n\tt: number;\n\t/** Parallelism (lanes). */\n\tp: number;\n}\n\n/** The worker's reply: the raw key, or the failure message. */\nexport interface KdfReply {\n\tid: number;\n\tkey?: Uint8Array;\n\terror?: string;\n}\n\nexport async function runKdfJob(job: KdfJob): Promise<Uint8Array> {\n\tconst { argon2id } = await import('hash-wasm');\n\treturn argon2id({\n\t\tpassword: job.password,\n\t\tsalt: fromBase64(job.salt),\n\t\tparallelism: job.p,\n\t\titerations: job.t,\n\t\tmemorySize: job.m,\n\t\thashLength: KEY_BYTES,\n\t\toutputType: 'binary'\n\t});\n}\n","// Off-main-thread key derivation. Argon2id takes about a second at the\n// default cost, which would jank every encrypted push and pull if it ran on\n// the UI thread. One lazy dedicated worker, terminated after an idle window\n// so its ~46 MiB of WASM memory is not held forever. Any failure to spawn,\n// load, or answer falls back to the calling thread, which runs the exact\n// same runKdfJob - the worker is a responsiveness optimization, never a\n// correctness dependency.\n\nimport { runKdfJob, type KdfJob, type KdfReply } from './argon2';\nimport type { KdfParams } from './types';\n\n// Generous: a wedged worker is rerun on the calling thread, and Argon2id at\n// the default cost already takes a second or two on a phone.\nconst JOB_TIMEOUT_MS = 30_000;\nconst IDLE_TERMINATE_MS = 30_000;\n\ninterface Pending {\n\tjob: KdfJob;\n\tresolve: (key: Uint8Array) => void;\n\treject: (e: unknown) => void;\n\ttimer: ReturnType<typeof setTimeout>;\n}\n\nlet worker: Worker | null = null;\n// Once the worker path fails (blocked, missing asset), stay on the calling\n// thread for the rest of the session instead of failing again.\nlet broken = false;\nlet seq = 0;\nconst pending = new Map<number, Pending>();\nlet idleTimer: ReturnType<typeof setTimeout> | undefined;\n\nfunction armIdleStop(): void {\n\tclearTimeout(idleTimer);\n\tidleTimer = setTimeout(() => {\n\t\tif (pending.size === 0 && worker) {\n\t\t\tworker.terminate();\n\t\t\tworker = null; // respawned on the next job\n\t\t}\n\t}, IDLE_TERMINATE_MS);\n}\n\n/** Abandon the worker and finish every queued job on the calling thread. */\nfunction fallBack(): void {\n\tbroken = true;\n\tworker?.terminate();\n\tworker = null;\n\tclearTimeout(idleTimer);\n\tfor (const p of pending.values()) {\n\t\tclearTimeout(p.timer);\n\t\trunKdfJob(p.job).then(p.resolve, p.reject);\n\t}\n\tpending.clear();\n}\n\nfunction ensureWorker(): Worker | null {\n\tif (broken) return null;\n\tif (worker) return worker;\n\tif (typeof Worker === 'undefined') {\n\t\tbroken = true; // Node, old runtimes\n\t\treturn null;\n\t}\n\ttry {\n\t\t// Bundlers (Vite, webpack 5, Rollup) detect this exact\n\t\t// `new Worker(new URL(...), import.meta.url)` shape to ship the worker\n\t\t// file as an asset - do not refactor it away.\n\t\tworker = new Worker(new URL('./kdf-worker.js', import.meta.url), {\n\t\t\ttype: 'module',\n\t\t\tname: 'selfstore-kdf'\n\t\t});\n\t} catch {\n\t\tbroken = true;\n\t\treturn null;\n\t}\n\tworker.onmessage = (ev: MessageEvent<KdfReply>): void => {\n\t\tconst reply = ev.data;\n\t\tconst p = pending.get(reply.id);\n\t\tif (!p) return;\n\t\tpending.delete(reply.id);\n\t\tclearTimeout(p.timer);\n\t\tif (reply.key) p.resolve(reply.key);\n\t\telse p.reject(new Error(reply.error ?? 'key derivation failed in the worker'));\n\t\tarmIdleStop();\n\t};\n\t// Script 404, parse error, CSP: rerun the queued jobs locally.\n\tworker.onerror = (): void => fallBack();\n\treturn worker;\n}\n\n/** Derive the raw AES key for `kdf`, off the main thread when possible. */\nexport function deriveRaw(password: string, kdf: KdfParams): Promise<Uint8Array> {\n\tconst job: KdfJob = { id: ++seq, password, salt: kdf.salt, m: kdf.m, t: kdf.t, p: kdf.p };\n\tconst w = ensureWorker();\n\tif (!w) return runKdfJob(job);\n\treturn new Promise<Uint8Array>((resolve, reject) => {\n\t\tconst timer = setTimeout(() => {\n\t\t\t// fallBack() clears every OTHER pending timer, so no job runs twice.\n\t\t\tpending.delete(job.id);\n\t\t\tfallBack();\n\t\t\trunKdfJob(job).then(resolve, reject);\n\t\t}, JOB_TIMEOUT_MS);\n\t\tpending.set(job.id, { job, resolve, reject, timer });\n\t\tw.postMessage(job);\n\t});\n}\n","// AES-256-GCM via WebCrypto over an Argon2id-derived key (hash-wasm). The\n// derivation runs in a worker when the platform has one (see kdf.ts); the\n// WASM is imported dynamically so it only loads when a password is used.\n\nimport type { KdfParams, PasswordSlot, ExternalSlot } from './types';\nimport { deriveRaw } from './kdf';\nimport { toBase64, fromBase64 } from './base64';\nimport { SelfstoreError } from './errors';\n\nexport { toBase64, fromBase64 };\n\nconst IV_BYTES = 12;\nconst SALT_BYTES = 16;\n\n/**\n * Cost for new backups: 46 MiB, 3 passes - above the OWASP Argon2id minimum,\n * ~1-2 s on a phone. Params are stored per file, so older backups keep\n * decrypting with their own cost.\n */\nexport const DEFAULT_ARGON2 = { m: 47104, t: 3, p: 1 } as const;\n\n/**\n * Read-side ceiling (m is in KiB: 1 GiB, 10 passes, 4 lanes). Without it a\n * crafted file could declare m = 8_000_000 and make the reader allocate\n * gigabytes before any password check. Out-of-range params are\n * UNSUPPORTED_VERSION, not DECRYPT_FAILED - the file is not corrupt, its\n * parameters are just outside what this reader will run.\n */\nconst KDF_MAX = { m: 1024 * 1024, t: 10, p: 4 } as const;\nconst KDF_MIN = { m: 8, t: 1, p: 1 } as const;\n\n/** Throws UNSUPPORTED_VERSION on out-of-range Argon2 params. Call before touching the WASM. */\nexport function assertKdfBounds(kdf: KdfParams): void {\n\tconst { m, t, p } = kdf;\n\tconst ok =\n\t\tNumber.isInteger(m) &&\n\t\tNumber.isInteger(t) &&\n\t\tNumber.isInteger(p) &&\n\t\tm >= KDF_MIN.m &&\n\t\tm <= KDF_MAX.m &&\n\t\tt >= KDF_MIN.t &&\n\t\tt <= KDF_MAX.t &&\n\t\tp >= KDF_MIN.p &&\n\t\tp <= KDF_MAX.p;\n\tif (!ok) {\n\t\tthrow new SelfstoreError(\n\t\t\t'UNSUPPORTED_VERSION',\n\t\t\t`Argon2 parameters out of the supported range (m=${m} KiB, t=${t}, p=${p}).`\n\t\t);\n\t}\n}\n\nfunction randomBytes(n: number): Uint8Array {\n\tconst b = new Uint8Array(n);\n\tcrypto.getRandomValues(b);\n\treturn b;\n}\n\n/** Coerce to the ArrayBuffer-backed view WebCrypto's types want (always safe here). */\nfunction src(u8: Uint8Array): Uint8Array<ArrayBuffer> {\n\treturn u8 as Uint8Array<ArrayBuffer>;\n}\n\n/**\n * Derive the AES-256-GCM key for `kdf`, imported non-extractable. Shared by\n * the backup cipher and the identity vault's passphrase lock.\n */\nexport async function deriveKey(password: string, kdf: KdfParams): Promise<CryptoKey> {\n\tconst raw = await deriveRaw(password, kdf);\n\treturn crypto.subtle.importKey('raw', src(raw), 'AES-GCM', false, ['encrypt', 'decrypt']);\n}\n\n/** Fresh salt at the current default cost, for a new password-sealed write. */\nexport function freshKdfParams(): KdfParams {\n\treturn { algo: 'argon2id', salt: toBase64(randomBytes(SALT_BYTES)), ...DEFAULT_ARGON2 };\n}\n\n// --- Password envelope (format 3) slots --------------------------------------\n\n/**\n * Each slot costs one Argon2id trial on open, so an unbounded list would let\n * a crafted file demand unbounded memory-hard work. Same spirit as\n * assertKdfBounds.\n */\nexport const MAX_KEY_SLOTS = 8;\n\n/** Wrap the 32-byte data key under a key derived from `password`, fresh salt and IV. */\nexport async function mintSlot(\n\tpassword: string,\n\tdataKey: Uint8Array,\n\tid?: string\n): Promise<PasswordSlot> {\n\tconst kdf = freshKdfParams();\n\tconst key = await deriveKey(password, kdf);\n\tconst iv = randomBytes(IV_BYTES);\n\tconst wrapped = await crypto.subtle.encrypt({ name: 'AES-GCM', iv: src(iv) }, key, src(dataKey));\n\treturn {\n\t\tid: id ?? toBase64(randomBytes(6)),\n\t\tkdf,\n\t\tiv: toBase64(iv),\n\t\twrapped: toBase64(new Uint8Array(wrapped))\n\t};\n}\n\n/**\n * Returns the data key if `password` opens this slot, else null. GCM keeps\n * wrong-password and tampering indistinguishable (fail closed). Bounds are\n * checked before any derivation, and that refusal is never swallowed - a\n * memory-hard bomb must not hide behind \"wrong password\".\n */\nexport async function openSlot(slot: PasswordSlot, password: string): Promise<Uint8Array | null> {\n\tassertKdfBounds(slot.kdf);\n\ttry {\n\t\tconst key = await deriveKey(password, slot.kdf);\n\t\tconst pt = await crypto.subtle.decrypt(\n\t\t\t{ name: 'AES-GCM', iv: src(fromBase64(slot.iv)) },\n\t\t\tkey,\n\t\t\tsrc(fromBase64(slot.wrapped))\n\t\t);\n\t\tconst dataKey = new Uint8Array(pt);\n\t\treturn dataKey.length === 32 ? dataKey : null;\n\t} catch (e) {\n\t\tif (e instanceof SelfstoreError) throw e;\n\t\treturn null;\n\t}\n}\n\n// --- Authenticated envelope (format 3) data seal -----------------------------\n\n/**\n * Seal the inner ZIP under the data key with the header bytes as AAD.\n * Generation 3 passes the exact meta.json bytes here, which binds the slot\n * table to the ciphertext: write access to the file is not enough to strip or\n * swap a key slot without breaking the tag. The caller generates the iv (it\n * rides in meta.json, hence inside the AAD) so seal and open agree byte for\n * byte.\n */\nexport async function gcmSealAad(\n\tkey32: Uint8Array,\n\tiv: Uint8Array,\n\tplaintext: Uint8Array,\n\taad: Uint8Array\n): Promise<Uint8Array> {\n\tconst key = await crypto.subtle.importKey('raw', src(key32), 'AES-GCM', false, ['encrypt']);\n\tconst ct = await crypto.subtle.encrypt(\n\t\t{ name: 'AES-GCM', iv: src(iv), additionalData: src(aad) },\n\t\tkey,\n\t\tsrc(plaintext)\n\t);\n\treturn new Uint8Array(ct);\n}\n\n/**\n * Open sealed data. `aad` is the additional authenticated data bound at seal\n * time (the envelope binds its header bytes); pass none for seals that bound\n * none. Any tag failure - wrong key, corrupt data, altered header - is one\n * DECRYPT_FAILED.\n */\nexport async function gcmOpenAad(\n\tkey32: Uint8Array,\n\tiv: Uint8Array,\n\tciphertext: Uint8Array,\n\taad?: Uint8Array\n): Promise<Uint8Array> {\n\ttry {\n\t\tconst key = await crypto.subtle.importKey('raw', src(key32), 'AES-GCM', false, ['decrypt']);\n\t\tconst params: AesGcmParams = { name: 'AES-GCM', iv: src(iv) };\n\t\tif (aad) params.additionalData = src(aad);\n\t\tconst pt = await crypto.subtle.decrypt(params, key, src(ciphertext));\n\t\treturn new Uint8Array(pt);\n\t} catch {\n\t\tthrow new SelfstoreError(\n\t\t\t'DECRYPT_FAILED',\n\t\t\t'Corrupted, wrong-key, or altered-header ciphertext.'\n\t\t);\n\t}\n}\n\n// --- External-key slots ------------------------------------------------------\n\n// A passkey PRF output is 32 bytes; anything under 16 is too weak to key a backup.\nconst MIN_EXTERNAL_SECRET = 16;\n\nconst EXTERNAL_INFO = new TextEncoder().encode('selfstore-external-slot-v1');\n\n/**\n * KEK for an external slot. The secret is already high-entropy (passkey PRF,\n * hardware token), so one HKDF-SHA256 expansion is enough - Argon2 only\n * exists to stretch low-entropy passwords. The fixed info label\n * domain-separates this use from any other the same secret might see.\n */\nasync function externalKek(secret: Uint8Array): Promise<CryptoKey> {\n\tconst ikm = await crypto.subtle.importKey('raw', src(secret), 'HKDF', false, ['deriveBits']);\n\tconst bits = await crypto.subtle.deriveBits(\n\t\t{ name: 'HKDF', hash: 'SHA-256', salt: new Uint8Array(0), info: src(EXTERNAL_INFO) },\n\t\tikm,\n\t\t256\n\t);\n\treturn crypto.subtle.importKey('raw', src(new Uint8Array(bits)), 'AES-GCM', false, [\n\t\t'encrypt',\n\t\t'decrypt'\n\t]);\n}\n\n/** Wrap the data key under a KEK derived from `secret`; `keyRef` is carried verbatim. */\nexport async function mintExternalSlot(\n\tsecret: Uint8Array,\n\tkeyRef: string,\n\tdataKey: Uint8Array,\n\tid?: string\n): Promise<ExternalSlot> {\n\tif (secret.length < MIN_EXTERNAL_SECRET) {\n\t\tthrow new TypeError(\n\t\t\t`mintExternalSlot(): external secret must be >= ${MIN_EXTERNAL_SECRET} bytes.`\n\t\t);\n\t}\n\tconst key = await externalKek(secret);\n\tconst iv = randomBytes(IV_BYTES);\n\tconst wrapped = await crypto.subtle.encrypt({ name: 'AES-GCM', iv: src(iv) }, key, src(dataKey));\n\treturn {\n\t\tid: id ?? toBase64(randomBytes(6)),\n\t\tkind: 'external',\n\t\tkeyRef,\n\t\tiv: toBase64(iv),\n\t\twrapped: toBase64(new Uint8Array(wrapped))\n\t};\n}\n\n/** Returns the data key if `secret` opens this slot, else null. Fail closed, like openSlot. */\nexport async function openExternalSlot(\n\tslot: ExternalSlot,\n\tsecret: Uint8Array\n): Promise<Uint8Array | null> {\n\tif (secret.length < MIN_EXTERNAL_SECRET) return null;\n\ttry {\n\t\tconst key = await externalKek(secret);\n\t\tconst pt = await crypto.subtle.decrypt(\n\t\t\t{ name: 'AES-GCM', iv: src(fromBase64(slot.iv)) },\n\t\t\tkey,\n\t\t\tsrc(fromBase64(slot.wrapped))\n\t\t);\n\t\tconst dataKey = new Uint8Array(pt);\n\t\treturn dataKey.length === 32 ? dataKey : null;\n\t} catch {\n\t\treturn null;\n\t}\n}\n"]}