@byok-sdk/keys 0.2.1 → 0.3.0

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/dist/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { z } from 'zod';
2
2
  import { spawn } from 'child_process';
3
+ import path, { dirname } from 'path';
3
4
  import { createHash } from 'crypto';
4
5
  import { mkdirSync, existsSync, chmodSync } from 'fs';
5
6
  import { createRequire } from 'module';
6
- import { dirname } from 'path';
7
7
  import { isCoreConflictError, contentHash } from '@byok-sdk/core';
8
8
 
9
9
  // src/errors.ts
@@ -588,8 +588,6 @@ var InMemorySecretStore = class _InMemorySecretStore {
588
588
  return `${this.#servicePrefix}.${assertSecretName(name)}`;
589
589
  }
590
590
  };
591
-
592
- // src/macos-keychain.ts
593
591
  var DEFAULT_KEYCHAIN_SECRET_STORAGE_PREFIX = "byok-b64-v1:";
594
592
  var SECURITY_ITEM_NOT_FOUND = 44;
595
593
  var MacOsKeychainSecretStore = class _MacOsKeychainSecretStore {
@@ -597,6 +595,7 @@ var MacOsKeychainSecretStore = class _MacOsKeychainSecretStore {
597
595
  #account;
598
596
  #allowUnprefixedRead;
599
597
  #commandRunner;
598
+ #keychainPath;
600
599
  #platform;
601
600
  #servicePrefix;
602
601
  #storagePrefix;
@@ -604,6 +603,7 @@ var MacOsKeychainSecretStore = class _MacOsKeychainSecretStore {
604
603
  this.#account = options.account ?? "local-device";
605
604
  this.#allowUnprefixedRead = options.allowUnprefixedRead ?? false;
606
605
  this.#commandRunner = options.commandRunner ?? runCommand;
606
+ this.#keychainPath = assertKeychainPath(options.keychainPath);
607
607
  this.#platform = options.platform ?? process.platform;
608
608
  this.#servicePrefix = options.servicePrefix ?? DEFAULT_SECRET_SERVICE_PREFIX;
609
609
  this.#storagePrefix = options.storagePrefix ?? DEFAULT_KEYCHAIN_SECRET_STORAGE_PREFIX;
@@ -611,9 +611,7 @@ var MacOsKeychainSecretStore = class _MacOsKeychainSecretStore {
611
611
  async available() {
612
612
  if (this.#platform !== "darwin") return false;
613
613
  const result = await this.#commandRunner("/usr/bin/security", [
614
- "default-keychain",
615
- "-d",
616
- "user"
614
+ ...this.#keychainPath === void 0 ? ["default-keychain", "-d", "user"] : ["show-keychain-info", this.#keychainPath]
617
615
  ]);
618
616
  return result.exitCode === 0;
619
617
  }
@@ -625,7 +623,8 @@ var MacOsKeychainSecretStore = class _MacOsKeychainSecretStore {
625
623
  "-a",
626
624
  this.#account,
627
625
  "-s",
628
- service
626
+ service,
627
+ ...this.#keychainPath === void 0 ? [] : [this.#keychainPath]
629
628
  ]);
630
629
  if (result.exitCode === SECURITY_ITEM_NOT_FOUND) return false;
631
630
  if (result.exitCode !== 0) {
@@ -645,7 +644,8 @@ var MacOsKeychainSecretStore = class _MacOsKeychainSecretStore {
645
644
  this.#account,
646
645
  "-s",
647
646
  service,
648
- "-w"
647
+ "-w",
648
+ ...this.#keychainPath === void 0 ? [] : [this.#keychainPath]
649
649
  ]);
650
650
  if (result.exitCode === SECURITY_ITEM_NOT_FOUND) return void 0;
651
651
  if (result.exitCode !== 0) {
@@ -664,6 +664,7 @@ var MacOsKeychainSecretStore = class _MacOsKeychainSecretStore {
664
664
  account: this.#account,
665
665
  allowUnprefixedRead: this.#allowUnprefixedRead,
666
666
  commandRunner: this.#commandRunner,
667
+ keychainPath: this.#keychainPath,
667
668
  platform: this.#platform,
668
669
  servicePrefix: `${this.#servicePrefix}.scope.${assertSecretNamespace(namespace)}`,
669
670
  storagePrefix: this.#storagePrefix
@@ -687,7 +688,8 @@ var MacOsKeychainSecretStore = class _MacOsKeychainSecretStore {
687
688
  "-s",
688
689
  quoteSecurityInteractiveArgument(service),
689
690
  "-w",
690
- quoteSecurityInteractiveArgument(storedSecret)
691
+ quoteSecurityInteractiveArgument(storedSecret),
692
+ ...this.#keychainPath === void 0 ? [] : [quoteSecurityInteractiveArgument(this.#keychainPath)]
691
693
  ].join(" ");
692
694
  const result = await this.#commandRunner(
693
695
  "/usr/bin/security",
@@ -746,6 +748,16 @@ function quoteSecurityInteractiveArgument(value) {
746
748
  }
747
749
  return `"${value.replaceAll("\\", "\\\\").replaceAll('"', '\\"')}"`;
748
750
  }
751
+ function assertKeychainPath(keychainPath) {
752
+ if (keychainPath === void 0) return void 0;
753
+ if (keychainPath.length === 0 || !path.posix.isAbsolute(keychainPath) || /[\u0000\r\n]/u.test(keychainPath)) {
754
+ throw new ByokKeysError(
755
+ "KEYCHAIN_ARGUMENT_INVALID",
756
+ "macOS keychain path must be a non-empty absolute single-line path"
757
+ );
758
+ }
759
+ return keychainPath;
760
+ }
749
761
 
750
762
  // src/windows-credential-manager.ts
751
763
  var CREDENTIAL_NOT_FOUND = 44;
@@ -1207,19 +1219,19 @@ function isSqliteAvailable() {
1207
1219
  return false;
1208
1220
  }
1209
1221
  }
1210
- function openSqliteDatabase(path, options, faults) {
1222
+ function openSqliteDatabase(path2, options, faults) {
1211
1223
  const { DatabaseSync } = loadSqliteModule();
1212
1224
  const readOnly = options?.readOnly === true;
1213
- if (path !== ":memory:" && !readOnly) {
1214
- mkdirSync(dirname(path), { mode: SECURE_DIR_MODE, recursive: true });
1225
+ if (path2 !== ":memory:" && !readOnly) {
1226
+ mkdirSync(dirname(path2), { mode: SECURE_DIR_MODE, recursive: true });
1215
1227
  }
1216
- const database = new DatabaseSync(path, {
1228
+ const database = new DatabaseSync(path2, {
1217
1229
  timeout: DEFAULT_BUSY_TIMEOUT_MS,
1218
1230
  ...options
1219
1231
  });
1220
1232
  try {
1221
1233
  faults?.onStep?.("after-open");
1222
- if (path !== ":memory:" && !readOnly) {
1234
+ if (path2 !== ":memory:" && !readOnly) {
1223
1235
  database.exec("PRAGMA journal_mode = WAL");
1224
1236
  faults?.onStep?.("after-wal");
1225
1237
  database.exec("PRAGMA synchronous = FULL");