vaultkeeper 0.5.1 → 0.5.3

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.cjs CHANGED
@@ -1617,7 +1617,13 @@ function validateConfig(config) {
1617
1617
  if (typeof config.defaults.ttlMinutes !== "number" || config.defaults.ttlMinutes <= 0) {
1618
1618
  throw new Error("Config defaults.ttlMinutes must be a positive number");
1619
1619
  }
1620
- const tier = config.defaults.trustTier;
1620
+ let tier = config.defaults.trustTier;
1621
+ if (typeof tier === "string") {
1622
+ const parsed = Number(tier);
1623
+ if (!Number.isNaN(parsed)) {
1624
+ tier = parsed;
1625
+ }
1626
+ }
1621
1627
  if (tier !== 1 && tier !== 2 && tier !== 3) {
1622
1628
  throw new Error("Config defaults.trustTier must be 1, 2, or 3");
1623
1629
  }
@@ -2019,7 +2025,6 @@ var SecretAccessorTarget = class {
2019
2025
  };
2020
2026
  function createSecretAccessor(secretValue) {
2021
2027
  let consumed = false;
2022
- const revokeHolder = { fn: void 0 };
2023
2028
  function readImpl(callback) {
2024
2029
  if (consumed) {
2025
2030
  throw new Error("SecretAccessor has already been consumed \u2014 call getSecret() again to obtain a new accessor");
@@ -2030,7 +2035,6 @@ function createSecretAccessor(secretValue) {
2030
2035
  callback(buf);
2031
2036
  } finally {
2032
2037
  buf.fill(0);
2033
- revokeHolder.fn?.();
2034
2038
  }
2035
2039
  }
2036
2040
  function inspectImpl() {
@@ -2088,9 +2092,7 @@ function createSecretAccessor(secretValue) {
2088
2092
  return ["read", INSPECT_CUSTOM];
2089
2093
  }
2090
2094
  };
2091
- const { proxy, revoke } = Proxy.revocable(target, handler);
2092
- revokeHolder.fn = revoke;
2093
- return proxy;
2095
+ return new Proxy(target, handler);
2094
2096
  }
2095
2097
 
2096
2098
  // src/access/sign-util.ts
@@ -2284,7 +2286,8 @@ async function runDoctor(options) {
2284
2286
  nextSteps: ["Unsupported platform. vaultkeeper supports macOS, Linux, and Windows."]
2285
2287
  };
2286
2288
  }
2287
- const entries = buildCheckList(platform);
2289
+ const enabledTypes = enabledBackendTypes(options?.backends);
2290
+ const entries = buildCheckList(platform, enabledTypes);
2288
2291
  const resolved = await Promise.all(
2289
2292
  entries.map(async ({ check, required }) => {
2290
2293
  const result = await check();
@@ -2318,24 +2321,48 @@ async function runDoctor(options) {
2318
2321
  const checks = resolved.map(({ result }) => result);
2319
2322
  return { checks, ready, warnings, nextSteps };
2320
2323
  }
2321
- function buildCheckList(platform) {
2324
+ function enabledBackendTypes(backends) {
2325
+ if (backends === void 0) return null;
2326
+ const types = /* @__PURE__ */ new Set();
2327
+ for (const b of backends) {
2328
+ if (b.enabled) types.add(b.type);
2329
+ }
2330
+ return types;
2331
+ }
2332
+ function buildCheckList(platform, enabledTypes) {
2322
2333
  const entries = [{ check: checkOpenssl, required: true }];
2323
2334
  if (platform === "darwin") {
2324
- entries.push({ check: checkSecurity, required: true });
2335
+ entries.push({
2336
+ check: checkSecurity,
2337
+ required: enabledTypes === null || enabledTypes.has("keychain")
2338
+ });
2325
2339
  entries.push({ check: checkBash, required: false });
2326
2340
  } else if (platform === "win32") {
2327
- entries.push({ check: checkPowershell, required: true });
2341
+ entries.push({
2342
+ check: checkPowershell,
2343
+ required: enabledTypes === null || enabledTypes.has("dpapi")
2344
+ });
2328
2345
  } else {
2329
2346
  entries.push({ check: checkBash, required: true });
2330
- entries.push({ check: checkSecretTool, required: true });
2347
+ entries.push({
2348
+ check: checkSecretTool,
2349
+ required: enabledTypes === null || enabledTypes.has("secret-tool")
2350
+ });
2331
2351
  }
2332
- entries.push({ check: checkOp, required: false });
2333
- entries.push({ check: checkYkman, required: false });
2352
+ entries.push({
2353
+ check: checkOp,
2354
+ required: enabledTypes?.has("1password") ?? false
2355
+ });
2356
+ entries.push({
2357
+ check: checkYkman,
2358
+ required: enabledTypes?.has("yubikey") ?? false
2359
+ });
2334
2360
  return entries;
2335
2361
  }
2336
2362
 
2337
2363
  // src/vault.ts
2338
2364
  var usageCounts = /* @__PURE__ */ new Map();
2365
+ var USAGE_MAP_MAX_SIZE = 1e4;
2339
2366
  var VaultKeeper = class _VaultKeeper {
2340
2367
  #config;
2341
2368
  #keyManager;
@@ -2351,23 +2378,29 @@ var VaultKeeper = class _VaultKeeper {
2351
2378
  * Runs doctor checks (unless skipped), loads config, and sets up the key manager.
2352
2379
  */
2353
2380
  static async init(options) {
2381
+ const configDir = options?.configDir ?? getDefaultConfigDir();
2382
+ const config = options?.config ?? await loadConfig(configDir);
2354
2383
  if (options?.skipDoctor !== true) {
2355
- const doctorResult = await runDoctor();
2384
+ const doctorResult = await runDoctor({ backends: config.backends });
2356
2385
  if (!doctorResult.ready) {
2357
2386
  throw new VaultError(
2358
2387
  `System not ready: ${doctorResult.nextSteps.join("; ")}`
2359
2388
  );
2360
2389
  }
2361
2390
  }
2362
- const configDir = options?.configDir ?? getDefaultConfigDir();
2363
- const config = options?.config ?? await loadConfig(configDir);
2364
2391
  const keyManager = new KeyManager();
2365
2392
  await keyManager.init();
2366
2393
  const vault = new _VaultKeeper(config, keyManager, configDir);
2367
2394
  vault.#backend = vault.#resolveBackend();
2368
2395
  return vault;
2369
2396
  }
2370
- /** Run doctor checks without full initialization. */
2397
+ /**
2398
+ * Run doctor checks without full initialization.
2399
+ *
2400
+ * Uses conservative platform defaults — all platform-native dependency
2401
+ * checks are treated as required regardless of any backend configuration.
2402
+ * For config-aware scoping, call `runDoctor({ backends })` directly.
2403
+ */
2371
2404
  static async doctor() {
2372
2405
  return runDoctor();
2373
2406
  }
@@ -2431,12 +2464,16 @@ var VaultKeeper = class _VaultKeeper {
2431
2464
  const jti = claims.jti;
2432
2465
  const currentCount = usageCounts.get(jti) ?? 0;
2433
2466
  validateClaims(claims, currentCount);
2434
- const newCount = currentCount + 1;
2435
- if (claims.use !== null && newCount >= claims.use) {
2436
- usageCounts.delete(jti);
2437
- blockToken(jti);
2438
- } else {
2467
+ if (claims.use !== null) {
2468
+ const newCount = currentCount + 1;
2439
2469
  usageCounts.set(jti, newCount);
2470
+ if (usageCounts.size > USAGE_MAP_MAX_SIZE) {
2471
+ const oldest = usageCounts.keys().next().value;
2472
+ if (oldest !== void 0) {
2473
+ usageCounts.delete(oldest);
2474
+ blockToken(oldest);
2475
+ }
2476
+ }
2440
2477
  }
2441
2478
  const token = createCapabilityToken(claims);
2442
2479
  const response = { keyStatus };