@griffin-app/griffin-plan-executor 0.1.13 → 0.1.15
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/README.md +14 -14
- package/dist/events/adapters/in-memory.test.js +25 -23
- package/dist/events/adapters/in-memory.test.js.map +1 -1
- package/dist/events/adapters/kinesis.d.ts.map +1 -1
- package/dist/events/adapters/kinesis.js.map +1 -1
- package/dist/events/adapters/kinesis.test.js +22 -20
- package/dist/events/adapters/kinesis.test.js.map +1 -1
- package/dist/events/emitter.test.js +15 -15
- package/dist/events/emitter.test.js.map +1 -1
- package/dist/events/types.d.ts +12 -12
- package/dist/events/types.d.ts.map +1 -1
- package/dist/events/types.js +1 -1
- package/dist/executor.d.ts +2 -2
- package/dist/executor.d.ts.map +1 -1
- package/dist/executor.js +33 -43
- package/dist/executor.js.map +1 -1
- package/dist/executor.test.js +102 -102
- package/dist/executor.test.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/secrets/index.d.ts +4 -4
- package/dist/secrets/index.d.ts.map +1 -1
- package/dist/secrets/index.js +4 -4
- package/dist/secrets/index.js.map +1 -1
- package/dist/secrets/providers/aws.d.ts.map +1 -1
- package/dist/secrets/providers/aws.js +4 -5
- package/dist/secrets/providers/aws.js.map +1 -1
- package/dist/secrets/providers/env.js +1 -1
- package/dist/secrets/providers/env.js.map +1 -1
- package/dist/secrets/providers/vault.js +7 -7
- package/dist/secrets/providers/vault.js.map +1 -1
- package/dist/secrets/registry.d.ts +11 -33
- package/dist/secrets/registry.d.ts.map +1 -1
- package/dist/secrets/registry.js +65 -113
- package/dist/secrets/registry.js.map +1 -1
- package/dist/secrets/resolver.d.ts +12 -12
- package/dist/secrets/resolver.d.ts.map +1 -1
- package/dist/secrets/resolver.js +21 -21
- package/dist/secrets/resolver.js.map +1 -1
- package/dist/secrets/secrets.test.js +96 -120
- package/dist/secrets/secrets.test.js.map +1 -1
- package/dist/secrets/types.d.ts +2 -5
- package/dist/secrets/types.d.ts.map +1 -1
- package/dist/secrets/types.js +1 -4
- package/dist/secrets/types.js.map +1 -1
- package/dist/types.d.ts +2 -2
- package/package.json +4 -4
- package/src/events/adapters/README.md +7 -7
- package/src/events/adapters/in-memory.test.ts +27 -23
- package/src/events/adapters/kinesis.test.ts +23 -21
- package/src/events/adapters/kinesis.ts +6 -3
- package/src/events/emitter.test.ts +15 -15
- package/src/events/types.ts +13 -13
- package/src/executor.test.ts +103 -103
- package/src/executor.ts +40 -48
- package/src/index.ts +7 -7
- package/src/secrets/index.ts +5 -5
- package/src/secrets/providers/aws.ts +4 -5
- package/src/secrets/providers/env.ts +1 -1
- package/src/secrets/providers/vault.ts +7 -7
- package/src/secrets/registry.ts +75 -142
- package/src/secrets/resolver.ts +28 -26
- package/src/secrets/secrets.test.ts +124 -155
- package/src/secrets/types.ts +4 -13
- package/src/{test-plan-types.ts → test-monitor-types.ts} +1 -1
- package/src/types.ts +2 -2
package/dist/secrets/registry.js
CHANGED
|
@@ -1,67 +1,33 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Secret provider registry for managing
|
|
2
|
+
* Secret provider registry for managing the configured secret provider.
|
|
3
3
|
*/
|
|
4
4
|
import { SecretResolutionError } from "./types.js";
|
|
5
5
|
/**
|
|
6
|
-
* Registry for
|
|
7
|
-
* Supports multiple providers simultaneously (e.g., env + aws + vault).
|
|
6
|
+
* Registry for the single configured secret provider.
|
|
8
7
|
*/
|
|
9
8
|
export class SecretProviderRegistry {
|
|
10
|
-
|
|
9
|
+
provider = null;
|
|
11
10
|
/**
|
|
12
|
-
*
|
|
13
|
-
* @param provider - The provider to
|
|
14
|
-
* @throws Error if a provider with the same name is already registered
|
|
11
|
+
* Set the secret provider.
|
|
12
|
+
* @param provider - The provider to use for resolution
|
|
15
13
|
*/
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
throw new Error(`Secret provider "${provider.name}" is already registered`);
|
|
19
|
-
}
|
|
20
|
-
this.providers.set(provider.name, provider);
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Unregister a secret provider by name.
|
|
24
|
-
* @param name - The provider name to remove
|
|
25
|
-
* @returns true if the provider was removed, false if it wasn't registered
|
|
26
|
-
*/
|
|
27
|
-
unregister(name) {
|
|
28
|
-
return this.providers.delete(name);
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Get a registered provider by name.
|
|
32
|
-
* @param name - The provider name
|
|
33
|
-
* @throws Error if the provider is not registered
|
|
34
|
-
*/
|
|
35
|
-
get(name) {
|
|
36
|
-
const provider = this.providers.get(name);
|
|
37
|
-
if (!provider) {
|
|
38
|
-
const available = [...this.providers.keys()];
|
|
39
|
-
throw new SecretResolutionError(`Secret provider "${name}" is not configured. Available providers: ${available.length > 0 ? available.join(", ") : "(none)"}`, { provider: name, ref: "" });
|
|
40
|
-
}
|
|
41
|
-
return provider;
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Check if a provider is registered.
|
|
45
|
-
*/
|
|
46
|
-
has(name) {
|
|
47
|
-
return this.providers.has(name);
|
|
14
|
+
setProvider(provider) {
|
|
15
|
+
this.provider = provider;
|
|
48
16
|
}
|
|
49
17
|
/**
|
|
50
|
-
*
|
|
51
|
-
*/
|
|
52
|
-
getProviderNames() {
|
|
53
|
-
return [...this.providers.keys()];
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Resolve a secret reference using the appropriate provider.
|
|
18
|
+
* Resolve a secret reference using the configured provider.
|
|
57
19
|
* @param secretRef - The secret reference data
|
|
58
20
|
* @returns The resolved secret value
|
|
59
21
|
* @throws SecretResolutionError if resolution fails
|
|
60
22
|
*/
|
|
61
23
|
async resolve(secretRef) {
|
|
62
|
-
|
|
24
|
+
if (!this.provider) {
|
|
25
|
+
throw new SecretResolutionError("No secret provider configured", {
|
|
26
|
+
ref: secretRef.ref,
|
|
27
|
+
});
|
|
28
|
+
}
|
|
63
29
|
try {
|
|
64
|
-
return await provider.resolve(secretRef.ref, {
|
|
30
|
+
return await this.provider.resolve(secretRef.ref, {
|
|
65
31
|
version: secretRef.version,
|
|
66
32
|
field: secretRef.field,
|
|
67
33
|
});
|
|
@@ -70,100 +36,86 @@ export class SecretProviderRegistry {
|
|
|
70
36
|
if (error instanceof SecretResolutionError) {
|
|
71
37
|
throw error;
|
|
72
38
|
}
|
|
73
|
-
throw new SecretResolutionError(`Failed to resolve secret "${secretRef.
|
|
74
|
-
provider: secretRef.provider,
|
|
39
|
+
throw new SecretResolutionError(`Failed to resolve secret "${secretRef.ref}": ${error instanceof Error ? error.message : String(error)}`, {
|
|
75
40
|
ref: secretRef.ref,
|
|
76
41
|
cause: error,
|
|
77
42
|
});
|
|
78
43
|
}
|
|
79
44
|
}
|
|
80
45
|
/**
|
|
81
|
-
* Resolve multiple secrets
|
|
46
|
+
* Resolve multiple secrets using the configured provider.
|
|
82
47
|
* @param refs - Array of secret reference data
|
|
83
|
-
* @returns Map of
|
|
48
|
+
* @returns Map of key to resolved value
|
|
84
49
|
* @throws SecretResolutionError if any resolution fails (fail-fast)
|
|
85
50
|
*/
|
|
86
51
|
async resolveMany(refs) {
|
|
87
52
|
if (refs.length === 0) {
|
|
88
53
|
return new Map();
|
|
89
54
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const key = this.makeKey(secretRef);
|
|
94
|
-
const group = byProvider.get(secretRef.provider) || [];
|
|
95
|
-
group.push({
|
|
96
|
-
ref: secretRef.ref,
|
|
97
|
-
options: {
|
|
98
|
-
version: secretRef.version,
|
|
99
|
-
field: secretRef.field,
|
|
100
|
-
},
|
|
101
|
-
key,
|
|
55
|
+
if (!this.provider) {
|
|
56
|
+
throw new SecretResolutionError("No secret provider configured", {
|
|
57
|
+
ref: refs[0].ref,
|
|
102
58
|
});
|
|
103
|
-
byProvider.set(secretRef.provider, group);
|
|
104
59
|
}
|
|
105
|
-
// Resolve each provider's secrets
|
|
106
60
|
const results = new Map();
|
|
107
|
-
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
results.set(providerRef.key, value);
|
|
61
|
+
if (this.provider.resolveMany) {
|
|
62
|
+
const batchRefs = refs.map((r) => ({
|
|
63
|
+
ref: r.ref,
|
|
64
|
+
options: {
|
|
65
|
+
version: r.version,
|
|
66
|
+
field: r.field,
|
|
67
|
+
},
|
|
68
|
+
}));
|
|
69
|
+
try {
|
|
70
|
+
const batchResults = await this.provider.resolveMany(batchRefs);
|
|
71
|
+
for (const secretRef of refs) {
|
|
72
|
+
const value = batchResults.get(secretRef.ref);
|
|
73
|
+
if (value === undefined) {
|
|
74
|
+
throw new SecretResolutionError(`Secret "${secretRef.ref}" not found in batch results`, { ref: secretRef.ref });
|
|
123
75
|
}
|
|
76
|
+
results.set(this.makeKey(secretRef), value);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
catch (error) {
|
|
80
|
+
if (error instanceof SecretResolutionError) {
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
throw new SecretResolutionError(`Batch resolution failed: ${error instanceof Error ? error.message : String(error)}`, {
|
|
84
|
+
ref: refs[0].ref,
|
|
85
|
+
cause: error,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
for (const secretRef of refs) {
|
|
91
|
+
try {
|
|
92
|
+
const value = await this.provider.resolve(secretRef.ref, {
|
|
93
|
+
version: secretRef.version,
|
|
94
|
+
field: secretRef.field,
|
|
95
|
+
});
|
|
96
|
+
results.set(this.makeKey(secretRef), value);
|
|
124
97
|
}
|
|
125
98
|
catch (error) {
|
|
126
99
|
if (error instanceof SecretResolutionError) {
|
|
127
100
|
throw error;
|
|
128
101
|
}
|
|
129
|
-
throw new SecretResolutionError(`
|
|
130
|
-
provider: providerName,
|
|
131
|
-
ref: providerRefs[0]?.ref || "",
|
|
132
|
-
cause: error,
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
else {
|
|
137
|
-
// Resolve individually (fail-fast on first error)
|
|
138
|
-
for (const providerRef of providerRefs) {
|
|
139
|
-
try {
|
|
140
|
-
const value = await provider.resolve(providerRef.ref, providerRef.options);
|
|
141
|
-
results.set(providerRef.key, value);
|
|
142
|
-
}
|
|
143
|
-
catch (error) {
|
|
144
|
-
if (error instanceof SecretResolutionError) {
|
|
145
|
-
throw error;
|
|
146
|
-
}
|
|
147
|
-
throw new SecretResolutionError(`Failed to resolve secret "${providerName}:${providerRef.ref}": ${error instanceof Error ? error.message : String(error)}`, { provider: providerName, ref: providerRef.ref, cause: error });
|
|
148
|
-
}
|
|
102
|
+
throw new SecretResolutionError(`Failed to resolve secret "${secretRef.ref}": ${error instanceof Error ? error.message : String(error)}`, { ref: secretRef.ref, cause: error });
|
|
149
103
|
}
|
|
150
104
|
}
|
|
151
105
|
}
|
|
152
106
|
return results;
|
|
153
107
|
}
|
|
154
108
|
/**
|
|
155
|
-
* Validate
|
|
156
|
-
* @throws Error if
|
|
109
|
+
* Validate the configured provider.
|
|
110
|
+
* @throws Error if provider validation fails
|
|
157
111
|
*/
|
|
158
112
|
async validateAll() {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
throw new Error(`Provider "${name}" validation failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
166
|
-
}
|
|
113
|
+
if (this.provider?.validate) {
|
|
114
|
+
try {
|
|
115
|
+
await this.provider.validate();
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
throw new Error(`Provider validation failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
167
119
|
}
|
|
168
120
|
}
|
|
169
121
|
}
|
|
@@ -171,7 +123,7 @@ export class SecretProviderRegistry {
|
|
|
171
123
|
* Create a unique key for a secret reference (for caching/deduplication).
|
|
172
124
|
*/
|
|
173
125
|
makeKey(secretRef) {
|
|
174
|
-
const parts = [secretRef.
|
|
126
|
+
const parts = [secretRef.ref];
|
|
175
127
|
if (secretRef.version)
|
|
176
128
|
parts.push(`v:${secretRef.version}`);
|
|
177
129
|
if (secretRef.field)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/secrets/registry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEnD
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/secrets/registry.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,OAAO,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEnD;;GAEG;AACH,MAAM,OAAO,sBAAsB;IACzB,QAAQ,GAA0B,IAAI,CAAC;IAE/C;;;OAGG;IACH,WAAW,CAAC,QAAwB;QAClC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,OAAO,CAAC,SAAwB;QACpC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,MAAM,IAAI,qBAAqB,CAAC,+BAA+B,EAAE;gBAC/D,GAAG,EAAE,SAAS,CAAC,GAAG;aACnB,CAAC,CAAC;QACL,CAAC;QAED,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,EAAE;gBAChD,OAAO,EAAE,SAAS,CAAC,OAAO;gBAC1B,KAAK,EAAE,SAAS,CAAC,KAAK;aACvB,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,qBAAqB,EAAE,CAAC;gBAC3C,MAAM,KAAK,CAAC;YACd,CAAC;YACD,MAAM,IAAI,qBAAqB,CAC7B,6BAA6B,SAAS,CAAC,GAAG,MACxC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CACvD,EAAE,EACF;gBACE,GAAG,EAAE,SAAS,CAAC,GAAG;gBAClB,KAAK,EAAE,KAAK;aACb,CACF,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,WAAW,CAAC,IAAqB;QACrC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,OAAO,IAAI,GAAG,EAAE,CAAC;QACnB,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,MAAM,IAAI,qBAAqB,CAAC,+BAA+B,EAAE;gBAC/D,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG;aACjB,CAAC,CAAC;QACL,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC;QAE1C,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;YAC9B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACjC,GAAG,EAAE,CAAC,CAAC,GAAG;gBACV,OAAO,EAAE;oBACP,OAAO,EAAE,CAAC,CAAC,OAAO;oBAClB,KAAK,EAAE,CAAC,CAAC,KAAK;iBACS;aAC1B,CAAC,CAAC,CAAC;YAEJ,IAAI,CAAC;gBACH,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC;gBAEhE,KAAK,MAAM,SAAS,IAAI,IAAI,EAAE,CAAC;oBAC7B,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;oBAC9C,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;wBACxB,MAAM,IAAI,qBAAqB,CAC7B,WAAW,SAAS,CAAC,GAAG,8BAA8B,EACtD,EAAE,GAAG,EAAE,SAAS,CAAC,GAAG,EAAE,CACvB,CAAC;oBACJ,CAAC;oBACD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,CAAC;gBAC9C,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,IAAI,KAAK,YAAY,qBAAqB,EAAE,CAAC;oBAC3C,MAAM,KAAK,CAAC;gBACd,CAAC;gBACD,MAAM,IAAI,qBAAqB,CAC7B,4BACE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CACvD,EAAE,EACF;oBACE,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG;oBAChB,KAAK,EAAE,KAAK;iBACb,CACF,CAAC;YACJ,CAAC;QACH,CAAC;aAAM,CAAC;YACN,KAAK,MAAM,SAAS,IAAI,IAAI,EAAE,CAAC;gBAC7B,IAAI,CAAC;oBACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,EAAE;wBACvD,OAAO,EAAE,SAAS,CAAC,OAAO;wBAC1B,KAAK,EAAE,SAAS,CAAC,KAAK;qBACvB,CAAC,CAAC;oBACH,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,KAAK,CAAC,CAAC;gBAC9C,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,IAAI,KAAK,YAAY,qBAAqB,EAAE,CAAC;wBAC3C,MAAM,KAAK,CAAC;oBACd,CAAC;oBACD,MAAM,IAAI,qBAAqB,CAC7B,6BAA6B,SAAS,CAAC,GAAG,MACxC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CACvD,EAAE,EACF,EAAE,GAAG,EAAE,SAAS,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,CACrC,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,WAAW;QACf,IAAI,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,CAAC;YAC5B,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;YACjC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,IAAI,KAAK,CACb,+BACE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CACvD,EAAE,CACH,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,SAAwB;QAC9B,MAAM,KAAK,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,SAAS,CAAC,OAAO;YAAE,KAAK,CAAC,IAAI,CAAC,KAAK,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC;QAC5D,IAAI,SAAS,CAAC,KAAK;YAAE,KAAK,CAAC,IAAI,CAAC,KAAK,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC;QACxD,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;CACF"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Secret resolution utilities for test
|
|
2
|
+
* Secret resolution utilities for test monitors.
|
|
3
3
|
*/
|
|
4
|
-
import { type
|
|
4
|
+
import { type MonitorV1 } from "@griffin-app/griffin-hub-sdk";
|
|
5
5
|
import type { SecretProviderRegistry } from "./registry.js";
|
|
6
6
|
import type { SecretRefData } from "./types.js";
|
|
7
7
|
/**
|
|
8
|
-
* Collected secret references and literals from a
|
|
8
|
+
* Collected secret references and literals from a monitor.
|
|
9
9
|
*/
|
|
10
10
|
interface CollectedSecrets {
|
|
11
11
|
/** All unique secret references found */
|
|
@@ -22,24 +22,24 @@ interface CollectedSecrets {
|
|
|
22
22
|
}>;
|
|
23
23
|
}
|
|
24
24
|
/**
|
|
25
|
-
* Collect all secret references and string literals from a test
|
|
25
|
+
* Collect all secret references and string literals from a test monitor.
|
|
26
26
|
* Scans endpoint headers and bodies for $secret markers and $literal wrappers.
|
|
27
27
|
*/
|
|
28
|
-
export declare function
|
|
28
|
+
export declare function collectSecretsFromMonitor(monitor: MonitorV1): CollectedSecrets;
|
|
29
29
|
/**
|
|
30
|
-
* Resolve all secrets and unwrap string literals in a
|
|
31
|
-
* The original
|
|
30
|
+
* Resolve all secrets and unwrap string literals in a monitor and return a new monitor with substituted values.
|
|
31
|
+
* The original monitor is not modified.
|
|
32
32
|
*
|
|
33
|
-
* @param
|
|
33
|
+
* @param monitor - The test monitor containing secret references and string literals
|
|
34
34
|
* @param registry - The secret provider registry
|
|
35
|
-
* @returns A new
|
|
35
|
+
* @returns A new monitor with all secrets resolved to their values and literals unwrapped
|
|
36
36
|
* @throws SecretResolutionError if any secret cannot be resolved (fail-fast)
|
|
37
37
|
*/
|
|
38
|
-
export declare function
|
|
38
|
+
export declare function resolveSecretsInMonitor(monitor: MonitorV1, registry: SecretProviderRegistry): Promise<MonitorV1>;
|
|
39
39
|
/**
|
|
40
|
-
* Check if a
|
|
40
|
+
* Check if a monitor contains any secret references or string literals that need resolution.
|
|
41
41
|
* Useful for short-circuiting resolution when no secrets or literals are present.
|
|
42
42
|
*/
|
|
43
|
-
export declare function planHasSecrets(
|
|
43
|
+
export declare function planHasSecrets(monitor: MonitorV1): boolean;
|
|
44
44
|
export {};
|
|
45
45
|
//# sourceMappingURL=resolver.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/secrets/resolver.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,KAAK,
|
|
1
|
+
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../src/secrets/resolver.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAC9D,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,KAAK,EAAa,aAAa,EAAE,MAAM,YAAY,CAAC;AAG3D;;GAEG;AACH,UAAU,gBAAgB;IACxB,yCAAyC;IACzC,IAAI,EAAE,aAAa,EAAE,CAAC;IACtB,wDAAwD;IACxD,KAAK,EAAE,KAAK,CAAC;QACX,IAAI,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;QAC1B,SAAS,EAAE,aAAa,CAAC;KAC1B,CAAC,CAAC;IACH,8DAA8D;IAC9D,YAAY,EAAE,KAAK,CAAC;QAClB,IAAI,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;QAC1B,KAAK,EAAE,MAAM,CAAC;KACf,CAAC,CAAC;CACJ;AAgDD;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,SAAS,GACjB,gBAAgB,CAoDlB;AAsCD;;;;;;;;GAQG;AACH,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,SAAS,EAClB,QAAQ,EAAE,sBAAsB,GAC/B,OAAO,CAAC,SAAS,CAAC,CAuCpB;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,SAAS,GAAG,OAAO,CAsB1D"}
|
package/dist/secrets/resolver.js
CHANGED
|
@@ -37,17 +37,17 @@ function collectSecretsFromValue(value, currentPath, collected) {
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
/**
|
|
40
|
-
* Collect all secret references and string literals from a test
|
|
40
|
+
* Collect all secret references and string literals from a test monitor.
|
|
41
41
|
* Scans endpoint headers and bodies for $secret markers and $literal wrappers.
|
|
42
42
|
*/
|
|
43
|
-
export function
|
|
43
|
+
export function collectSecretsFromMonitor(monitor) {
|
|
44
44
|
const collected = {
|
|
45
45
|
refs: [],
|
|
46
46
|
paths: [],
|
|
47
47
|
literalPaths: [],
|
|
48
48
|
};
|
|
49
|
-
for (let nodeIndex = 0; nodeIndex <
|
|
50
|
-
const node =
|
|
49
|
+
for (let nodeIndex = 0; nodeIndex < monitor.nodes.length; nodeIndex++) {
|
|
50
|
+
const node = monitor.nodes[nodeIndex];
|
|
51
51
|
// Only endpoints can have secrets (in headers and body)
|
|
52
52
|
if (node.type !== "HTTP_REQUEST") {
|
|
53
53
|
continue;
|
|
@@ -68,7 +68,7 @@ export function collectSecretsFromPlan(plan) {
|
|
|
68
68
|
const seen = new Set();
|
|
69
69
|
const uniqueRefs = [];
|
|
70
70
|
for (const ref of collected.refs) {
|
|
71
|
-
const key = `${ref.
|
|
71
|
+
const key = `${ref.ref}:${ref.version || ""}:${ref.field || ""}`;
|
|
72
72
|
if (!seen.has(key)) {
|
|
73
73
|
seen.add(key);
|
|
74
74
|
uniqueRefs.push(ref);
|
|
@@ -106,49 +106,49 @@ function deepClone(value) {
|
|
|
106
106
|
return JSON.parse(JSON.stringify(value));
|
|
107
107
|
}
|
|
108
108
|
/**
|
|
109
|
-
* Resolve all secrets and unwrap string literals in a
|
|
110
|
-
* The original
|
|
109
|
+
* Resolve all secrets and unwrap string literals in a monitor and return a new monitor with substituted values.
|
|
110
|
+
* The original monitor is not modified.
|
|
111
111
|
*
|
|
112
|
-
* @param
|
|
112
|
+
* @param monitor - The test monitor containing secret references and string literals
|
|
113
113
|
* @param registry - The secret provider registry
|
|
114
|
-
* @returns A new
|
|
114
|
+
* @returns A new monitor with all secrets resolved to their values and literals unwrapped
|
|
115
115
|
* @throws SecretResolutionError if any secret cannot be resolved (fail-fast)
|
|
116
116
|
*/
|
|
117
|
-
export async function
|
|
117
|
+
export async function resolveSecretsInMonitor(monitor, registry) {
|
|
118
118
|
// Collect all secret references and string literals
|
|
119
|
-
const collected =
|
|
119
|
+
const collected = collectSecretsFromMonitor(monitor);
|
|
120
120
|
if (collected.refs.length === 0 && collected.literalPaths.length === 0) {
|
|
121
121
|
// No secrets or literals to resolve
|
|
122
|
-
return
|
|
122
|
+
return monitor;
|
|
123
123
|
}
|
|
124
124
|
// Resolve all secrets (fail-fast on any error)
|
|
125
125
|
const resolved = collected.refs.length > 0
|
|
126
126
|
? await registry.resolveMany(collected.refs)
|
|
127
127
|
: new Map();
|
|
128
|
-
// Clone the
|
|
129
|
-
const
|
|
128
|
+
// Clone the monitor for modification
|
|
129
|
+
const resolvedMonitor = deepClone(monitor);
|
|
130
130
|
// Substitute resolved secret values at each path
|
|
131
131
|
for (const { path, secretRef } of collected.paths) {
|
|
132
132
|
const key = registry.makeKey(secretRef);
|
|
133
133
|
const value = resolved.get(key);
|
|
134
134
|
if (value === undefined) {
|
|
135
135
|
// This shouldn't happen if resolveMany worked correctly
|
|
136
|
-
throw new Error(`Internal error: resolved value not found for secret "${secretRef.
|
|
136
|
+
throw new Error(`Internal error: resolved value not found for secret "${secretRef.ref}"`);
|
|
137
137
|
}
|
|
138
|
-
setAtPath(
|
|
138
|
+
setAtPath(resolvedMonitor, path, value);
|
|
139
139
|
}
|
|
140
140
|
// Unwrap string literals at each path
|
|
141
141
|
for (const { path, value } of collected.literalPaths) {
|
|
142
|
-
setAtPath(
|
|
142
|
+
setAtPath(resolvedMonitor, path, value);
|
|
143
143
|
}
|
|
144
|
-
return
|
|
144
|
+
return resolvedMonitor;
|
|
145
145
|
}
|
|
146
146
|
/**
|
|
147
|
-
* Check if a
|
|
147
|
+
* Check if a monitor contains any secret references or string literals that need resolution.
|
|
148
148
|
* Useful for short-circuiting resolution when no secrets or literals are present.
|
|
149
149
|
*/
|
|
150
|
-
export function planHasSecrets(
|
|
151
|
-
for (const node of
|
|
150
|
+
export function planHasSecrets(monitor) {
|
|
151
|
+
for (const node of monitor.nodes) {
|
|
152
152
|
if (node.type !== "HTTP_REQUEST") {
|
|
153
153
|
continue;
|
|
154
154
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../src/secrets/resolver.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAoB1D;;;;;GAKG;AACH,SAAS,uBAAuB,CAC9B,KAAc,EACd,WAAgC,EAChC,SAA2B;IAE3B,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QAC1C,OAAO;IACT,CAAC;IAED,IAAI,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC;QACvB,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACnC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC;YACnB,IAAI,EAAE,CAAC,GAAG,WAAW,CAAC;YACtB,SAAS,EAAE,KAAK,CAAC,OAAO;SACzB,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,IAAI,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3B,SAAS,CAAC,YAAY,CAAC,IAAI,CAAC;YAC1B,IAAI,EAAE,CAAC,GAAG,WAAW,CAAC;YACtB,KAAK,EAAE,KAAK,CAAC,QAAQ;SACtB,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,uBAAuB,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,WAAW,EAAE,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;QACpE,CAAC;QACD,OAAO;IACT,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,KAAK,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAC/C,uBAAuB,CAAC,GAAG,EAAE,CAAC,GAAG,WAAW,EAAE,GAAG,CAAC,EAAE,SAAS,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../src/secrets/resolver.ts"],"names":[],"mappings":"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"}
|