@agent-vm/secret-management 0.0.71 → 0.0.72

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.
@@ -9,6 +9,10 @@ type SecretRef = {
9
9
  } | {
10
10
  readonly source: 'environment';
11
11
  readonly ref: string;
12
+ } | {
13
+ readonly source: 'config';
14
+ readonly ref?: never;
15
+ readonly value: string;
12
16
  };
13
17
  interface SecretResolver {
14
18
  resolve(ref: SecretRef): Promise<string>;
package/dist/index.js CHANGED
@@ -10,11 +10,23 @@ function resolveEnvironmentSecret(ref, env) {
10
10
  if (value.trim().length === 0) throw new Error(`Environment variable '${ref.ref}' is set but empty.`);
11
11
  return value;
12
12
  }
13
+ function resolveConfigSecret(ref) {
14
+ if (ref.value.trim().length === 0) throw new Error("Config secret value is empty.");
15
+ return ref.value;
16
+ }
13
17
  function formatUnknownError$1(error) {
14
18
  return error instanceof Error ? error.message : String(error);
15
19
  }
20
+ function describeSecretRef(ref) {
21
+ switch (ref.source) {
22
+ case "1password":
23
+ case "environment": return ref.ref;
24
+ case "config": return "<config>";
25
+ default: return JSON.stringify(ref);
26
+ }
27
+ }
16
28
  function createSecretResolutionError(options) {
17
- return new Error(`Failed to resolve secret '${options.secretName}' from '${options.ref.ref}': ${formatUnknownError$1(options.cause)}`, { cause: options.cause });
29
+ return new Error(`Failed to resolve secret '${options.secretName}' from '${describeSecretRef(options.ref)}': ${formatUnknownError$1(options.cause)}`, { cause: options.cause });
18
30
  }
19
31
  function throwAggregateSecretResolutionError(failures) {
20
32
  if (failures.length > 0) throw new AggregateError(failures, `Failed to resolve ${String(failures.length)} secret(s).`);
@@ -27,6 +39,7 @@ function createCompositeSecretResolver(onePasswordResolver, env = process.env) {
27
39
  async resolve(ref) {
28
40
  switch (ref.source) {
29
41
  case "environment": return resolveEnvironmentSecret(ref, env);
42
+ case "config": return resolveConfigSecret(ref);
30
43
  case "1password":
31
44
  if (!onePasswordResolver) throw new Error("Secret with source '1password' requires host.secretsProvider to be configured.");
32
45
  return await onePasswordResolver.resolve(ref);
@@ -49,6 +62,17 @@ function createCompositeSecretResolver(onePasswordResolver, env = process.env) {
49
62
  }));
50
63
  }
51
64
  break;
65
+ case "config":
66
+ try {
67
+ resolved[name] = resolveConfigSecret(ref);
68
+ } catch (error) {
69
+ failures.push(createSecretResolutionError({
70
+ cause: error,
71
+ ref,
72
+ secretName: name
73
+ }));
74
+ }
75
+ break;
52
76
  case "1password":
53
77
  onePasswordRefs[name] = ref;
54
78
  break;
@@ -218,6 +242,40 @@ async function resolveServiceAccountToken(source, dependencies) {
218
242
  default: throw new Error(`Unsupported token source: ${JSON.stringify(source)}`);
219
243
  }
220
244
  }
245
+ function resolveConfigSecretValue(ref) {
246
+ if (ref.value.trim().length === 0) throw new Error("Config secret value is empty.");
247
+ return ref.value;
248
+ }
249
+ function createCompositeOnlySecretSourceError(source) {
250
+ return /* @__PURE__ */ new Error(`Secret source '${source}' must be resolved by the composite resolver before reaching the 1Password resolver.`);
251
+ }
252
+ function splitSecretRefs(refs) {
253
+ const onePasswordRefs = {};
254
+ const resolvedSecrets = {};
255
+ for (const [secretName, secretRef] of Object.entries(refs)) switch (secretRef.source) {
256
+ case "1password":
257
+ onePasswordRefs[secretName] = secretRef;
258
+ break;
259
+ case "config":
260
+ resolvedSecrets[secretName] = resolveConfigSecretValue(secretRef);
261
+ break;
262
+ case "environment": throw createCompositeOnlySecretSourceError(secretRef.source);
263
+ default: throw new Error(`Unsupported secret source: ${JSON.stringify(secretRef)}`);
264
+ }
265
+ return {
266
+ onePasswordRefs,
267
+ resolvedSecrets
268
+ };
269
+ }
270
+ function hasOnePasswordRefs(refs) {
271
+ return Object.keys(refs).length > 0;
272
+ }
273
+ function mergeResolvedSecrets(resolvedSecrets, onePasswordSecrets) {
274
+ return {
275
+ ...resolvedSecrets,
276
+ ...onePasswordSecrets
277
+ };
278
+ }
221
279
  async function resolveSecretWithOpCli(serviceAccountToken, secretReference, exec) {
222
280
  return stripOpReadStdoutTerminator((await exec("op", ["read", secretReference], {
223
281
  env: createOpCliServiceAccountEnv(serviceAccountToken),
@@ -429,6 +487,12 @@ async function createSecretResolver(options, dependencies = {}) {
429
487
  });
430
488
  return {
431
489
  resolve: async (ref) => {
490
+ switch (ref.source) {
491
+ case "config": return resolveConfigSecretValue(ref);
492
+ case "environment": throw createCompositeOnlySecretSourceError(ref.source);
493
+ case "1password": break;
494
+ default: throw new Error(`Unsupported secret source: ${JSON.stringify(ref)}`);
495
+ }
432
496
  try {
433
497
  return await client.secrets.resolve(ref.ref);
434
498
  } catch (error) {
@@ -445,12 +509,15 @@ async function createSecretResolver(options, dependencies = {}) {
445
509
  }
446
510
  },
447
511
  resolveAll: async (refs) => {
512
+ const splitRefs = splitSecretRefs(refs);
513
+ if (!hasOnePasswordRefs(splitRefs.onePasswordRefs)) return splitRefs.resolvedSecrets;
448
514
  try {
449
- return mapSdkResolveAllResponse(refs, await client.secrets.resolveAll(Object.values(refs).map((secretRef) => secretRef.ref)));
515
+ const response = await client.secrets.resolveAll(Object.values(splitRefs.onePasswordRefs).map((secretRef) => secretRef.ref));
516
+ return mergeResolvedSecrets(splitRefs.resolvedSecrets, mapSdkResolveAllResponse(splitRefs.onePasswordRefs, response));
450
517
  } catch (error) {
451
518
  const sdkResolveAllError = createFallbackStageError("1Password SDK resolveAll", error);
452
519
  try {
453
- return await resolveAllSecretsWithOpCli(options.serviceAccountToken, refs, exec);
520
+ return mergeResolvedSecrets(splitRefs.resolvedSecrets, await resolveAllSecretsWithOpCli(options.serviceAccountToken, splitRefs.onePasswordRefs, exec));
454
521
  } catch (fallbackError) {
455
522
  throw createFallbackFailureError({
456
523
  fallbackError,
@@ -465,6 +532,12 @@ async function createSecretResolver(options, dependencies = {}) {
465
532
  const sdkClientCreationError = createFallbackStageError("1Password SDK client creation", error);
466
533
  return {
467
534
  resolve: async (ref) => {
535
+ switch (ref.source) {
536
+ case "config": return resolveConfigSecretValue(ref);
537
+ case "environment": throw createCompositeOnlySecretSourceError(ref.source);
538
+ case "1password": break;
539
+ default: throw new Error(`Unsupported secret source: ${JSON.stringify(ref)}`, { cause: error });
540
+ }
468
541
  try {
469
542
  return await resolveSecretWithOpCli(options.serviceAccountToken, ref.ref, exec);
470
543
  } catch (fallbackError) {
@@ -476,8 +549,10 @@ async function createSecretResolver(options, dependencies = {}) {
476
549
  }
477
550
  },
478
551
  resolveAll: async (refs) => {
552
+ const splitRefs = splitSecretRefs(refs);
553
+ if (!hasOnePasswordRefs(splitRefs.onePasswordRefs)) return splitRefs.resolvedSecrets;
479
554
  try {
480
- return await resolveAllSecretsWithOpCli(options.serviceAccountToken, refs, exec);
555
+ return mergeResolvedSecrets(splitRefs.resolvedSecrets, await resolveAllSecretsWithOpCli(options.serviceAccountToken, splitRefs.onePasswordRefs, exec));
481
556
  } catch (fallbackError) {
482
557
  throw createFallbackFailureError({
483
558
  fallbackError,
@@ -492,8 +567,19 @@ async function createSecretResolver(options, dependencies = {}) {
492
567
  async function createOpCliSecretResolver(options, dependencies = {}) {
493
568
  const exec = dependencies.execFileAsync ?? execFileAsync;
494
569
  return {
495
- resolve: async (ref) => await resolveSecretWithOpCli(options.serviceAccountToken, ref.ref, exec),
496
- resolveAll: async (refs) => await resolveAllSecretsWithOpCli(options.serviceAccountToken, refs, exec)
570
+ resolve: async (ref) => {
571
+ switch (ref.source) {
572
+ case "config": return resolveConfigSecretValue(ref);
573
+ case "environment": throw createCompositeOnlySecretSourceError(ref.source);
574
+ case "1password": return await resolveSecretWithOpCli(options.serviceAccountToken, ref.ref, exec);
575
+ default: throw new Error(`Unsupported secret source: ${JSON.stringify(ref)}`);
576
+ }
577
+ },
578
+ resolveAll: async (refs) => {
579
+ const splitRefs = splitSecretRefs(refs);
580
+ if (!hasOnePasswordRefs(splitRefs.onePasswordRefs)) return splitRefs.resolvedSecrets;
581
+ return mergeResolvedSecrets(splitRefs.resolvedSecrets, await resolveAllSecretsWithOpCli(options.serviceAccountToken, splitRefs.onePasswordRefs, exec));
582
+ }
497
583
  };
498
584
  }
499
585
  //#endregion
package/dist/testing.js CHANGED
@@ -1,6 +1,7 @@
1
1
  //#region src/testing.ts
2
2
  function createStaticSecretResolver(values) {
3
3
  const resolve = async (ref) => {
4
+ if (ref.source === "config") return ref.value;
4
5
  const value = values[ref.ref];
5
6
  if (value === void 0) throw new Error(`No test secret value configured for '${ref.ref}'.`);
6
7
  return value;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-vm/secret-management",
3
- "version": "0.0.71",
3
+ "version": "0.0.72",
4
4
  "description": "Shared secret reference contracts and resolvers for agent-vm packages.",
5
5
  "homepage": "https://github.com/ShravanSunder/agent-vm#readme",
6
6
  "bugs": {