@wishknish/knishio-client-ts 0.9.6 → 0.9.7

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.
@@ -20064,6 +20064,55 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20064
20064
  }
20065
20065
  });
20066
20066
 
20067
+ // src/exception/SecretStorageException.ts
20068
+ exports.SecretStorageException = void 0;
20069
+ var init_SecretStorageException = __esm({
20070
+ "src/exception/SecretStorageException.ts"() {
20071
+ init_BaseException();
20072
+ exports.SecretStorageException = class _SecretStorageException extends exports.BaseException {
20073
+ constructor(message = "Secret storage operation failed", options = {}) {
20074
+ super("WALLET_CREDENTIAL_ERROR", message, {
20075
+ code: "SECRET_STORAGE_ERROR",
20076
+ ...options
20077
+ });
20078
+ }
20079
+ /**
20080
+ * Secret not found for the requested bundle hash
20081
+ */
20082
+ static notFound(bundleHash) {
20083
+ return new _SecretStorageException(`Secret not found for bundle: ${bundleHash}`, {
20084
+ code: "SECRET_NOT_FOUND",
20085
+ details: { bundleHash }
20086
+ });
20087
+ }
20088
+ /**
20089
+ * Decryption failed (wrong passphrase or corrupted payload)
20090
+ */
20091
+ static decryptionFailed(reason) {
20092
+ return new _SecretStorageException(
20093
+ `Failed to decrypt master secret: ${reason || "Invalid passphrase or corrupted ciphertext"}`,
20094
+ {
20095
+ code: "DECRYPTION_FAILED",
20096
+ details: { reason }
20097
+ }
20098
+ );
20099
+ }
20100
+ /**
20101
+ * Provider is unavailable in current platform
20102
+ */
20103
+ static unavailable(provider, reason) {
20104
+ return new _SecretStorageException(
20105
+ `Secret storage provider '${provider}' is unavailable: ${reason || "Hardware or API not accessible"}`,
20106
+ {
20107
+ code: "STORAGE_UNAVAILABLE",
20108
+ details: { provider, reason }
20109
+ }
20110
+ );
20111
+ }
20112
+ };
20113
+ }
20114
+ });
20115
+
20067
20116
  // src/exception/InvalidResponseException.ts
20068
20117
  exports.InvalidResponseException = void 0;
20069
20118
  var init_InvalidResponseException = __esm({
@@ -20526,6 +20575,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
20526
20575
  init_SignatureMismatchException();
20527
20576
  init_TransferBalanceException();
20528
20577
  init_WalletCredentialException();
20578
+ init_SecretStorageException();
20529
20579
  init_InvalidResponseException();
20530
20580
  init_BalanceInsufficientException();
20531
20581
  init_BatchIdException();
@@ -43021,7 +43071,8 @@ ${operationTypes.join("\n")}
43021
43071
  socket: external_exports.unknown().optional(),
43022
43072
  serverSdkVersion: external_exports.number().int().min(1).optional(),
43023
43073
  logging: external_exports.boolean().optional(),
43024
- defaultRequestPolicy: external_exports.enum(["cache-first", "cache-only", "network-only", "cache-and-network"]).nullable().optional()
43074
+ defaultRequestPolicy: external_exports.enum(["cache-first", "cache-only", "network-only", "cache-and-network"]).nullable().optional(),
43075
+ secretStorage: external_exports.unknown().optional()
43025
43076
  }).strict();
43026
43077
  external_exports.object({
43027
43078
  token: external_exports.string().min(1, "Auth token cannot be empty"),
@@ -48251,7 +48302,9 @@ ${operationTypes.join("\n")}
48251
48302
  // Optional default urql request policy for reads (server/sync clients pass
48252
48303
  // 'network-only'). Permitted by the strict schema so the constructor option
48253
48304
  // isn't rejected.
48254
- defaultRequestPolicy: external_exports.enum(["cache-first", "cache-only", "network-only", "cache-and-network"]).nullable().optional()
48305
+ defaultRequestPolicy: external_exports.enum(["cache-first", "cache-only", "network-only", "cache-and-network"]).nullable().optional(),
48306
+ // Pluggable hardware envelope encryption secret storage provider
48307
+ secretStorage: external_exports.unknown().optional()
48255
48308
  }).strict();
48256
48309
  var EnvironmentConfigSchema = external_exports.object({
48257
48310
  NODE_ENV: external_exports.enum(["development", "production", "test"]).optional(),
@@ -51827,9 +51880,134 @@ ${operationTypes.join("\n")}
51827
51880
 
51828
51881
  // src/KnishIOClient.ts
51829
51882
  init_exception();
51883
+
51884
+ // src/storage/MemorySecretStorageProvider.ts
51885
+ init_SecretStorageException();
51886
+
51887
+ // src/libraries/secureMemory.ts
51888
+ var textEncoder = new TextEncoder();
51889
+ function zeroizeBytes(buffer) {
51890
+ if (buffer instanceof Uint8Array) {
51891
+ buffer.fill(0);
51892
+ } else if (Array.isArray(buffer)) {
51893
+ for (let i4 = 0; i4 < buffer.length; i4++) {
51894
+ buffer[i4] = 0;
51895
+ }
51896
+ }
51897
+ }
51898
+ async function withSecureBytes(bytes, fn) {
51899
+ try {
51900
+ return await fn(bytes);
51901
+ } finally {
51902
+ zeroizeBytes(bytes);
51903
+ }
51904
+ }
51905
+ async function withSecureString(secret, fn) {
51906
+ const bytes = textEncoder.encode(secret);
51907
+ try {
51908
+ return await fn(secret);
51909
+ } finally {
51910
+ zeroizeBytes(bytes);
51911
+ }
51912
+ }
51913
+ function constantTimeCompare(a3, b2) {
51914
+ const bytesA = typeof a3 === "string" ? textEncoder.encode(a3) : a3;
51915
+ const bytesB = typeof b2 === "string" ? textEncoder.encode(b2) : b2;
51916
+ let result = bytesA.length === bytesB.length ? 0 : 1;
51917
+ const len = Math.min(bytesA.length, bytesB.length);
51918
+ for (let i4 = 0; i4 < len; i4++) {
51919
+ const byteA = bytesA[i4] ?? 0;
51920
+ const byteB = bytesB[i4] ?? 0;
51921
+ result |= byteA ^ byteB;
51922
+ }
51923
+ if (typeof a3 === "string") zeroizeBytes(bytesA);
51924
+ if (typeof b2 === "string") zeroizeBytes(bytesB);
51925
+ return result === 0;
51926
+ }
51927
+
51928
+ // src/storage/MemorySecretStorageProvider.ts
51929
+ var MemorySecretStorageProvider = class {
51930
+ providerType = "memory";
51931
+ secrets = /* @__PURE__ */ new Map();
51932
+ /**
51933
+ * Memory storage is not hardware backed
51934
+ */
51935
+ isHardwareBacked() {
51936
+ return false;
51937
+ }
51938
+ /**
51939
+ * Memory storage is always available
51940
+ */
51941
+ async isAvailable() {
51942
+ return true;
51943
+ }
51944
+ /**
51945
+ * Store a secret in memory
51946
+ */
51947
+ async storeSecret(bundleHash, secret, options) {
51948
+ if (!bundleHash) {
51949
+ throw new exports.SecretStorageException("Bundle hash cannot be empty");
51950
+ }
51951
+ if (!secret) {
51952
+ throw new exports.SecretStorageException("Secret cannot be empty");
51953
+ }
51954
+ const metadata = {
51955
+ bundleHash,
51956
+ label: options?.label,
51957
+ createdAt: Date.now(),
51958
+ hardwareBacked: false,
51959
+ providerType: this.providerType
51960
+ };
51961
+ this.secrets.set(bundleHash, { secret, metadata });
51962
+ }
51963
+ /**
51964
+ * Retrieve a secret from memory
51965
+ */
51966
+ async retrieveSecret(bundleHash) {
51967
+ const entry = this.secrets.get(bundleHash);
51968
+ return entry ? entry.secret : null;
51969
+ }
51970
+ /**
51971
+ * Delete a stored secret
51972
+ */
51973
+ async deleteSecret(bundleHash) {
51974
+ return this.secrets.delete(bundleHash);
51975
+ }
51976
+ /**
51977
+ * Check if a secret exists
51978
+ */
51979
+ async hasSecret(bundleHash) {
51980
+ return this.secrets.has(bundleHash);
51981
+ }
51982
+ /**
51983
+ * List all stored secret metadata
51984
+ */
51985
+ async listSecrets() {
51986
+ return Array.from(this.secrets.values()).map((entry) => ({ ...entry.metadata }));
51987
+ }
51988
+ /**
51989
+ * Execute callback with unwrapped secret and ensure cleanup
51990
+ */
51991
+ async withSecret(bundleHash, fn) {
51992
+ const entry = this.secrets.get(bundleHash);
51993
+ if (!entry) {
51994
+ throw exports.SecretStorageException.notFound(bundleHash);
51995
+ }
51996
+ return withSecureString(entry.secret, fn);
51997
+ }
51998
+ /**
51999
+ * Clear all secrets from memory
52000
+ */
52001
+ clear() {
52002
+ this.secrets.clear();
52003
+ }
52004
+ };
52005
+
52006
+ // src/KnishIOClient.ts
51830
52007
  var KnishIOClient = class {
51831
52008
  $__secret = "";
51832
52009
  $__bundle = "";
52010
+ $__secretStorage = null;
51833
52011
  $__cellSlug = null;
51834
52012
  $__encrypt = false;
51835
52013
  $__uris = [];
@@ -51889,6 +52067,9 @@ ${operationTypes.join("\n")}
51889
52067
  logging,
51890
52068
  defaultRequestPolicy
51891
52069
  });
52070
+ if (config2.secretStorage) {
52071
+ this.$__secretStorage = config2.secretStorage;
52072
+ }
51892
52073
  }
51893
52074
  /**
51894
52075
  * Initializes a new Knish.IO client session
@@ -51990,6 +52171,7 @@ ${operationTypes.join("\n")}
51990
52171
  reset() {
51991
52172
  this.$__secret = "";
51992
52173
  this.$__bundle = "";
52174
+ this.$__secretStorage = null;
51993
52175
  this.$__encrypt = false;
51994
52176
  this.$__cellSlug = null;
51995
52177
  this.$__authToken = null;
@@ -52051,7 +52233,7 @@ ${operationTypes.join("\n")}
52051
52233
  * Returns whether a secret is stored for this session
52052
52234
  */
52053
52235
  hasSecret() {
52054
- return !!this.$__secret && this.$__secret.length > 0;
52236
+ return !!this.$__secret && this.$__secret.length > 0 || !!this.$__secretStorage && !!this.$__bundle && this.$__bundle.length > 0;
52055
52237
  }
52056
52238
  /**
52057
52239
  * Returns the stored secret
@@ -52062,6 +52244,33 @@ ${operationTypes.join("\n")}
52062
52244
  }
52063
52245
  return this.$__secret;
52064
52246
  }
52247
+ /**
52248
+ * Sets the secret storage provider and optionally sets the bundle hash
52249
+ */
52250
+ setSecretStorage(storage, bundleHash) {
52251
+ this.$__secretStorage = storage;
52252
+ if (bundleHash) {
52253
+ this.$__bundle = bundleHash;
52254
+ }
52255
+ }
52256
+ /**
52257
+ * Returns current secret storage provider
52258
+ */
52259
+ getSecretStorage() {
52260
+ return this.$__secretStorage;
52261
+ }
52262
+ /**
52263
+ * Asynchronously retrieves the secret from storage or returns in-memory secret
52264
+ */
52265
+ async retrieveSecret(options) {
52266
+ if (this.$__secret && this.$__secret.length > 0) {
52267
+ return this.$__secret;
52268
+ }
52269
+ if (this.$__secretStorage && this.$__bundle && this.$__bundle.length > 0) {
52270
+ return await this.$__secretStorage.retrieveSecret(this.$__bundle, options);
52271
+ }
52272
+ return null;
52273
+ }
52065
52274
  /**
52066
52275
  * Returns whether a bundle hash is being stored for this session
52067
52276
  */
@@ -52100,6 +52309,13 @@ ${operationTypes.join("\n")}
52100
52309
  remainderWallet = null
52101
52310
  } = {}) {
52102
52311
  this.log("info", "KnishIOClient::createMolecule() - Creating a new molecule...");
52312
+ if (!secret) {
52313
+ if (this.$__secret && this.$__secret.length > 0) {
52314
+ secret = this.getSecret();
52315
+ } else if (this.$__secretStorage && this.$__bundle && this.$__bundle.length > 0) {
52316
+ secret = await this.$__secretStorage.retrieveSecret(this.$__bundle);
52317
+ }
52318
+ }
52103
52319
  secret = secret || this.getSecret();
52104
52320
  bundle = bundle || this.getBundle();
52105
52321
  let continuIdPosition = null;
@@ -52129,6 +52345,7 @@ ${operationTypes.join("\n")}
52129
52345
  }));
52130
52346
  return new Molecule({
52131
52347
  secret,
52348
+ bundle,
52132
52349
  sourceWallet,
52133
52350
  remainderWallet: this.getRemainderWallet(),
52134
52351
  cellSlug: this.getCellSlug(),
@@ -52175,8 +52392,9 @@ ${operationTypes.join("\n")}
52175
52392
  async executeQuery(query, variables = null, context = {}) {
52176
52393
  if (this.$__authToken && this.$__authToken.isExpired() && !this.$__authInProcess) {
52177
52394
  this.log("info", "KnishIOClient::executeQuery() - Access token is expired. Getting new one...");
52395
+ const authSecret = this.$__secret || await this.retrieveSecret() || "";
52178
52396
  await this.requestAuthToken({
52179
- secret: this.$__secret,
52397
+ secret: authSecret,
52180
52398
  cellSlug: this.$__cellSlug,
52181
52399
  encrypt: this.$__encrypt
52182
52400
  });
@@ -52216,6 +52434,13 @@ ${operationTypes.join("\n")}
52216
52434
  setSecret(secret) {
52217
52435
  this.$__secret = secret;
52218
52436
  this.$__bundle = generateBundleHash(secret);
52437
+ if (!this.$__secretStorage) {
52438
+ const memStorage = new MemorySecretStorageProvider();
52439
+ memStorage.storeSecret(this.$__bundle, secret);
52440
+ this.$__secretStorage = memStorage;
52441
+ } else {
52442
+ this.$__secretStorage.storeSecret(this.$__bundle, secret);
52443
+ }
52219
52444
  }
52220
52445
  /**
52221
52446
  * Sets the auth token for this session
@@ -52399,6 +52624,9 @@ ${operationTypes.join("\n")}
52399
52624
  if (secret === null && seed) {
52400
52625
  secret = generateSecret(seed);
52401
52626
  }
52627
+ if (secret === null && this.$__secretStorage && this.$__bundle) {
52628
+ secret = await this.$__secretStorage.retrieveSecret(this.$__bundle);
52629
+ }
52402
52630
  if (cellSlug) {
52403
52631
  this.setCellSlug(cellSlug);
52404
52632
  }
@@ -53536,7 +53764,297 @@ ${operationTypes.join("\n")}
53536
53764
  // src/index.ts
53537
53765
  init_Response();
53538
53766
  init_exception();
53539
- var SDK_VERSION = "0.9.6";
53767
+
53768
+ // src/storage/WebCryptoSecretStorageProvider.ts
53769
+ init_SecretStorageException();
53770
+ var MemoryStorageBackend = class {
53771
+ store = /* @__PURE__ */ new Map();
53772
+ getItem(key) {
53773
+ return this.store.get(key) ?? null;
53774
+ }
53775
+ setItem(key, value2) {
53776
+ this.store.set(key, value2);
53777
+ }
53778
+ removeItem(key) {
53779
+ return this.store.delete(key);
53780
+ }
53781
+ keys() {
53782
+ return Array.from(this.store.keys());
53783
+ }
53784
+ };
53785
+ function uint8ArrayToBase642(bytes) {
53786
+ let binary = "";
53787
+ const len = bytes.byteLength;
53788
+ for (let i4 = 0; i4 < len; i4++) {
53789
+ const byte = bytes[i4];
53790
+ if (byte !== void 0) {
53791
+ binary += String.fromCharCode(byte);
53792
+ }
53793
+ }
53794
+ return btoa(binary);
53795
+ }
53796
+ function base64ToUint8Array2(base643) {
53797
+ const binary = atob(base643);
53798
+ const len = binary.length;
53799
+ const bytes = new Uint8Array(len);
53800
+ for (let i4 = 0; i4 < len; i4++) {
53801
+ bytes[i4] = binary.charCodeAt(i4);
53802
+ }
53803
+ return bytes;
53804
+ }
53805
+ var textEncoder2 = new TextEncoder();
53806
+ var textDecoder = new TextDecoder();
53807
+ var KEY_PREFIX = "knishio:secret:";
53808
+ var DEFAULT_ITERATIONS = 1e5;
53809
+ var WebCryptoSecretStorageProvider = class {
53810
+ providerType = "webcrypto-aes-gcm";
53811
+ backend;
53812
+ defaultPassphrase;
53813
+ hardwareBacked;
53814
+ constructor(options = {}) {
53815
+ this.backend = options.backend ?? new MemoryStorageBackend();
53816
+ this.defaultPassphrase = options.defaultPassphrase;
53817
+ this.hardwareBacked = options.hardwareBacked ?? false;
53818
+ }
53819
+ /**
53820
+ * Whether this provider is backed by hardware (e.g. WebAuthn PRF wrapping)
53821
+ */
53822
+ isHardwareBacked() {
53823
+ return this.hardwareBacked;
53824
+ }
53825
+ /**
53826
+ * Check if WebCrypto subtle API is available
53827
+ */
53828
+ async isAvailable() {
53829
+ return typeof globalThis.crypto !== "undefined" && typeof globalThis.crypto.subtle !== "undefined";
53830
+ }
53831
+ /**
53832
+ * Derive an AES-GCM CryptoKey from a passphrase and salt using PBKDF2
53833
+ */
53834
+ async deriveKey(passphrase, salt, iterations = DEFAULT_ITERATIONS) {
53835
+ if (!await this.isAvailable()) {
53836
+ throw exports.SecretStorageException.unavailable(this.providerType, "WebCrypto API is not available");
53837
+ }
53838
+ const passphraseBytes = textEncoder2.encode(passphrase);
53839
+ try {
53840
+ const baseKey = await globalThis.crypto.subtle.importKey(
53841
+ "raw",
53842
+ passphraseBytes,
53843
+ "PBKDF2",
53844
+ false,
53845
+ ["deriveKey"]
53846
+ );
53847
+ return await globalThis.crypto.subtle.deriveKey(
53848
+ {
53849
+ name: "PBKDF2",
53850
+ salt,
53851
+ iterations,
53852
+ hash: "SHA-256"
53853
+ },
53854
+ baseKey,
53855
+ { name: "AES-GCM", length: 256 },
53856
+ false,
53857
+ ["encrypt", "decrypt"]
53858
+ );
53859
+ } finally {
53860
+ zeroizeBytes(passphraseBytes);
53861
+ }
53862
+ }
53863
+ /**
53864
+ * Store and encrypt a master secret
53865
+ */
53866
+ async storeSecret(bundleHash, secret, options) {
53867
+ if (!bundleHash) {
53868
+ throw new exports.SecretStorageException("Bundle hash cannot be empty");
53869
+ }
53870
+ if (!secret) {
53871
+ throw new exports.SecretStorageException("Secret cannot be empty");
53872
+ }
53873
+ const passphrase = options?.passphrase ?? this.defaultPassphrase;
53874
+ if (!passphrase) {
53875
+ throw new exports.SecretStorageException("Passphrase required for envelope encryption");
53876
+ }
53877
+ const salt = new Uint8Array(16);
53878
+ const iv = new Uint8Array(12);
53879
+ globalThis.crypto.getRandomValues(salt);
53880
+ globalThis.crypto.getRandomValues(iv);
53881
+ const key = await this.deriveKey(passphrase, salt, DEFAULT_ITERATIONS);
53882
+ const secretBytes = textEncoder2.encode(secret);
53883
+ try {
53884
+ const encryptedBuffer = await globalThis.crypto.subtle.encrypt(
53885
+ {
53886
+ name: "AES-GCM",
53887
+ iv
53888
+ },
53889
+ key,
53890
+ secretBytes
53891
+ );
53892
+ const ciphertext = uint8ArrayToBase642(new Uint8Array(encryptedBuffer));
53893
+ const metadata = {
53894
+ bundleHash,
53895
+ label: options?.label,
53896
+ createdAt: Date.now(),
53897
+ hardwareBacked: this.hardwareBacked,
53898
+ providerType: this.providerType
53899
+ };
53900
+ const payload = {
53901
+ version: 1,
53902
+ ciphertext,
53903
+ iv: uint8ArrayToBase642(iv),
53904
+ salt: uint8ArrayToBase642(salt),
53905
+ algorithm: "AES-GCM",
53906
+ iterations: DEFAULT_ITERATIONS,
53907
+ metadata
53908
+ };
53909
+ await this.backend.setItem(`${KEY_PREFIX}${bundleHash}`, JSON.stringify(payload));
53910
+ } catch (err) {
53911
+ const msg = err instanceof Error ? err.message : String(err);
53912
+ throw new exports.SecretStorageException(`Encryption failed: ${msg}`);
53913
+ } finally {
53914
+ zeroizeBytes(secretBytes);
53915
+ }
53916
+ }
53917
+ /**
53918
+ * Retrieve and decrypt the master secret
53919
+ */
53920
+ async retrieveSecret(bundleHash, options) {
53921
+ const raw = await this.backend.getItem(`${KEY_PREFIX}${bundleHash}`);
53922
+ if (!raw) {
53923
+ return null;
53924
+ }
53925
+ let payload;
53926
+ try {
53927
+ payload = JSON.parse(raw);
53928
+ } catch {
53929
+ throw exports.SecretStorageException.decryptionFailed("Corrupted payload format");
53930
+ }
53931
+ const passphrase = options?.passphrase ?? this.defaultPassphrase;
53932
+ if (!passphrase) {
53933
+ throw new exports.SecretStorageException("Passphrase required for secret decryption");
53934
+ }
53935
+ const salt = base64ToUint8Array2(payload.salt);
53936
+ const iv = base64ToUint8Array2(payload.iv);
53937
+ const ciphertext = base64ToUint8Array2(payload.ciphertext);
53938
+ try {
53939
+ const key = await this.deriveKey(passphrase, salt, payload.iterations ?? DEFAULT_ITERATIONS);
53940
+ const decryptedBuffer = await globalThis.crypto.subtle.decrypt(
53941
+ {
53942
+ name: "AES-GCM",
53943
+ iv
53944
+ },
53945
+ key,
53946
+ ciphertext
53947
+ );
53948
+ const decryptedBytes = new Uint8Array(decryptedBuffer);
53949
+ try {
53950
+ return textDecoder.decode(decryptedBytes);
53951
+ } finally {
53952
+ zeroizeBytes(decryptedBytes);
53953
+ }
53954
+ } catch (err) {
53955
+ const msg = err instanceof Error ? err.message : String(err);
53956
+ throw exports.SecretStorageException.decryptionFailed(msg);
53957
+ }
53958
+ }
53959
+ /**
53960
+ * Delete a stored secret
53961
+ */
53962
+ async deleteSecret(bundleHash) {
53963
+ const key = `${KEY_PREFIX}${bundleHash}`;
53964
+ const result = await this.backend.removeItem(key);
53965
+ return result !== false;
53966
+ }
53967
+ /**
53968
+ * Check if a secret exists
53969
+ */
53970
+ async hasSecret(bundleHash) {
53971
+ const raw = await this.backend.getItem(`${KEY_PREFIX}${bundleHash}`);
53972
+ return raw !== null;
53973
+ }
53974
+ /**
53975
+ * List all stored secret metadata
53976
+ */
53977
+ async listSecrets() {
53978
+ const keys = await this.backend.keys();
53979
+ const matchingKeys = keys.filter((k2) => k2.startsWith(KEY_PREFIX));
53980
+ const results = [];
53981
+ for (const key of matchingKeys) {
53982
+ const raw = await this.backend.getItem(key);
53983
+ if (raw) {
53984
+ try {
53985
+ const payload = JSON.parse(raw);
53986
+ if (payload.metadata) {
53987
+ results.push(payload.metadata);
53988
+ }
53989
+ } catch {
53990
+ }
53991
+ }
53992
+ }
53993
+ return results;
53994
+ }
53995
+ /**
53996
+ * Execute callback with unwrapped secret, zeroizing the decrypted buffer upon completion
53997
+ */
53998
+ async withSecret(bundleHash, fn, options) {
53999
+ const raw = await this.backend.getItem(`${KEY_PREFIX}${bundleHash}`);
54000
+ if (!raw) {
54001
+ throw exports.SecretStorageException.notFound(bundleHash);
54002
+ }
54003
+ let payload;
54004
+ try {
54005
+ payload = JSON.parse(raw);
54006
+ } catch {
54007
+ throw exports.SecretStorageException.decryptionFailed("Corrupted payload format");
54008
+ }
54009
+ const passphrase = options?.passphrase ?? this.defaultPassphrase;
54010
+ if (!passphrase) {
54011
+ throw new exports.SecretStorageException("Passphrase required for secret decryption");
54012
+ }
54013
+ const salt = base64ToUint8Array2(payload.salt);
54014
+ const iv = base64ToUint8Array2(payload.iv);
54015
+ const ciphertext = base64ToUint8Array2(payload.ciphertext);
54016
+ try {
54017
+ const key = await this.deriveKey(passphrase, salt, payload.iterations ?? DEFAULT_ITERATIONS);
54018
+ const decryptedBuffer = await globalThis.crypto.subtle.decrypt(
54019
+ {
54020
+ name: "AES-GCM",
54021
+ iv
54022
+ },
54023
+ key,
54024
+ ciphertext
54025
+ );
54026
+ const decryptedBytes = new Uint8Array(decryptedBuffer);
54027
+ return await withSecureBytes(decryptedBytes, async (bytes) => {
54028
+ const secretString = textDecoder.decode(bytes);
54029
+ return await fn(secretString);
54030
+ });
54031
+ } catch (err) {
54032
+ if (err instanceof exports.SecretStorageException) {
54033
+ throw err;
54034
+ }
54035
+ const msg = err instanceof Error ? err.message : String(err);
54036
+ throw exports.SecretStorageException.decryptionFailed(msg);
54037
+ }
54038
+ }
54039
+ };
54040
+
54041
+ // src/storage/index.ts
54042
+ function createDefaultSecretStorage(options = {}) {
54043
+ if (options.type === "memory") {
54044
+ return new MemorySecretStorageProvider();
54045
+ }
54046
+ if (typeof globalThis.crypto !== "undefined" && typeof globalThis.crypto.subtle !== "undefined") {
54047
+ return new WebCryptoSecretStorageProvider({
54048
+ backend: options.backend,
54049
+ defaultPassphrase: options.defaultPassphrase,
54050
+ hardwareBacked: options.hardwareBacked
54051
+ });
54052
+ }
54053
+ return new MemorySecretStorageProvider();
54054
+ }
54055
+
54056
+ // src/index.ts
54057
+ var SDK_VERSION = "0.9.7";
53540
54058
  var SDK_NAME = "KnishIO-Client-TS";
53541
54059
  var COMPATIBLE_SERVER_VERSIONS = [4, 5];
53542
54060
  var SDK_INFO = {
@@ -53647,6 +54165,8 @@ ${operationTypes.join("\n")}
53647
54165
  exports.GraphQLClient = GraphQLClient;
53648
54166
  exports.KnishIO = KnishIO;
53649
54167
  exports.KnishIOClient = KnishIOClient;
54168
+ exports.MemorySecretStorageProvider = MemorySecretStorageProvider;
54169
+ exports.MemoryStorageBackend = MemoryStorageBackend;
53650
54170
  exports.Meta = Meta;
53651
54171
  exports.Molecule = Molecule;
53652
54172
  exports.Mutation = Mutation;
@@ -53692,6 +54212,7 @@ ${operationTypes.join("\n")}
53692
54212
  exports.SDK_VERSION = SDK_VERSION;
53693
54213
  exports.TokenUnit = TokenUnit;
53694
54214
  exports.Wallet = Wallet;
54215
+ exports.WebCryptoSecretStorageProvider = WebCryptoSecretStorageProvider;
53695
54216
  exports.base64ToHex = base64ToHex;
53696
54217
  exports.bufferToHexString = bufferToHexString;
53697
54218
  exports.capitalize = capitalize;
@@ -53699,8 +54220,10 @@ ${operationTypes.join("\n")}
53699
54220
  exports.chunkArray = chunkArray;
53700
54221
  exports.chunkSubstr = chunkSubstr;
53701
54222
  exports.configureSDK = configureSDK;
54223
+ exports.constantTimeCompare = constantTimeCompare;
53702
54224
  exports.convertToBase17 = convertToBase17;
53703
54225
  exports.createBundleHash = createBundleHash;
54226
+ exports.createDefaultSecretStorage = createDefaultSecretStorage;
53704
54227
  exports.createMolecularHash = createMolecularHash;
53705
54228
  exports.createPosition = createPosition;
53706
54229
  exports.createTokenSlug = createTokenSlug;
@@ -53742,6 +54265,9 @@ ${operationTypes.join("\n")}
53742
54265
  exports.validateSecret = validateSecret;
53743
54266
  exports.validateWalletAddress = validateWalletAddress;
53744
54267
  exports.verifyOTSSignature = verifyOTSSignature;
54268
+ exports.withSecureBytes = withSecureBytes;
54269
+ exports.withSecureString = withSecureString;
54270
+ exports.zeroizeBytes = zeroizeBytes;
53745
54271
 
53746
54272
  return exports;
53747
54273