@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.
Files changed (68) hide show
  1. package/README.md +14 -14
  2. package/dist/events/adapters/in-memory.test.js +25 -23
  3. package/dist/events/adapters/in-memory.test.js.map +1 -1
  4. package/dist/events/adapters/kinesis.d.ts.map +1 -1
  5. package/dist/events/adapters/kinesis.js.map +1 -1
  6. package/dist/events/adapters/kinesis.test.js +22 -20
  7. package/dist/events/adapters/kinesis.test.js.map +1 -1
  8. package/dist/events/emitter.test.js +15 -15
  9. package/dist/events/emitter.test.js.map +1 -1
  10. package/dist/events/types.d.ts +12 -12
  11. package/dist/events/types.d.ts.map +1 -1
  12. package/dist/events/types.js +1 -1
  13. package/dist/executor.d.ts +2 -2
  14. package/dist/executor.d.ts.map +1 -1
  15. package/dist/executor.js +33 -43
  16. package/dist/executor.js.map +1 -1
  17. package/dist/executor.test.js +102 -102
  18. package/dist/executor.test.js.map +1 -1
  19. package/dist/index.d.ts +4 -4
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +2 -2
  22. package/dist/index.js.map +1 -1
  23. package/dist/secrets/index.d.ts +4 -4
  24. package/dist/secrets/index.d.ts.map +1 -1
  25. package/dist/secrets/index.js +4 -4
  26. package/dist/secrets/index.js.map +1 -1
  27. package/dist/secrets/providers/aws.d.ts.map +1 -1
  28. package/dist/secrets/providers/aws.js +4 -5
  29. package/dist/secrets/providers/aws.js.map +1 -1
  30. package/dist/secrets/providers/env.js +1 -1
  31. package/dist/secrets/providers/env.js.map +1 -1
  32. package/dist/secrets/providers/vault.js +7 -7
  33. package/dist/secrets/providers/vault.js.map +1 -1
  34. package/dist/secrets/registry.d.ts +11 -33
  35. package/dist/secrets/registry.d.ts.map +1 -1
  36. package/dist/secrets/registry.js +65 -113
  37. package/dist/secrets/registry.js.map +1 -1
  38. package/dist/secrets/resolver.d.ts +12 -12
  39. package/dist/secrets/resolver.d.ts.map +1 -1
  40. package/dist/secrets/resolver.js +21 -21
  41. package/dist/secrets/resolver.js.map +1 -1
  42. package/dist/secrets/secrets.test.js +96 -120
  43. package/dist/secrets/secrets.test.js.map +1 -1
  44. package/dist/secrets/types.d.ts +2 -5
  45. package/dist/secrets/types.d.ts.map +1 -1
  46. package/dist/secrets/types.js +1 -4
  47. package/dist/secrets/types.js.map +1 -1
  48. package/dist/types.d.ts +2 -2
  49. package/package.json +4 -4
  50. package/src/events/adapters/README.md +7 -7
  51. package/src/events/adapters/in-memory.test.ts +27 -23
  52. package/src/events/adapters/kinesis.test.ts +23 -21
  53. package/src/events/adapters/kinesis.ts +6 -3
  54. package/src/events/emitter.test.ts +15 -15
  55. package/src/events/types.ts +13 -13
  56. package/src/executor.test.ts +103 -103
  57. package/src/executor.ts +40 -48
  58. package/src/index.ts +7 -7
  59. package/src/secrets/index.ts +5 -5
  60. package/src/secrets/providers/aws.ts +4 -5
  61. package/src/secrets/providers/env.ts +1 -1
  62. package/src/secrets/providers/vault.ts +7 -7
  63. package/src/secrets/registry.ts +75 -142
  64. package/src/secrets/resolver.ts +28 -26
  65. package/src/secrets/secrets.test.ts +124 -155
  66. package/src/secrets/types.ts +4 -13
  67. package/src/{test-plan-types.ts → test-monitor-types.ts} +1 -1
  68. package/src/types.ts +2 -2
package/src/executor.ts CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  UnaryPredicate,
5
5
  Assertions,
6
6
  Node,
7
- PlanV1,
7
+ MonitorV1,
8
8
  Wait,
9
9
  HttpRequest,
10
10
  } from "@griffin-app/griffin-hub-sdk";
@@ -23,14 +23,14 @@ import { createStateGraph, graphStore, StateGraphRegistry } from "ts-edge";
23
23
  import type { ExecutionEvent, BaseEvent } from "./events/index.js";
24
24
  import { randomUUID } from "crypto";
25
25
  import {
26
- resolveSecretsInPlan,
26
+ resolveSecretsInMonitor,
27
27
  planHasSecrets,
28
28
  SecretResolutionError,
29
29
  } from "./secrets/index.js";
30
30
  import { utcNow } from "./utils/dates.js";
31
31
  import {
32
32
  migrateToLatest,
33
- CURRENT_PLAN_VERSION,
33
+ CURRENT_MONITOR_VERSION,
34
34
  isSupportedVersion,
35
35
  } from "@griffin-app/griffin-ts";
36
36
 
@@ -41,7 +41,7 @@ interface NodeExecuteContext {
41
41
  }
42
42
 
43
43
  /**
44
- * Execution context that tracks event emission state throughout a plan execution.
44
+ * Execution context that tracks event emission state throughout a monitor execution.
45
45
  * Maintains sequence counter and provides event creation helpers.
46
46
  */
47
47
  class ExecutionContext {
@@ -49,7 +49,7 @@ class ExecutionContext {
49
49
 
50
50
  constructor(
51
51
  public readonly executionId: string,
52
- public readonly plan: PlanV1,
52
+ public readonly monitor: MonitorV1,
53
53
  public readonly organizationId: string,
54
54
  private readonly emitter?: ExecutionOptions["eventEmitter"],
55
55
  ) {}
@@ -62,7 +62,7 @@ class ExecutionContext {
62
62
  eventId: randomUUID(),
63
63
  seq: this.seq++,
64
64
  timestamp: Date.now(),
65
- planId: this.plan.id,
65
+ monitorId: this.monitor.id,
66
66
  executionId: this.executionId,
67
67
  organizationId: this.organizationId,
68
68
  };
@@ -121,7 +121,7 @@ interface ExecutionState {
121
121
  }
122
122
 
123
123
  function buildNode(
124
- plan: PlanV1,
124
+ monitor: MonitorV1,
125
125
  node: Node,
126
126
  options: ExecutionOptions,
127
127
  ): {
@@ -294,7 +294,7 @@ function buildNode(
294
294
  }
295
295
 
296
296
  function buildGraph(
297
- plan: PlanV1,
297
+ monitor: MonitorV1,
298
298
  options: ExecutionOptions,
299
299
  executionContext: ExecutionContext,
300
300
  ): DynamicStateGraph {
@@ -317,23 +317,24 @@ function buildGraph(
317
317
  }) as DynamicStateGraph;
318
318
 
319
319
  // Add all nodes - cast back to DynamicStateGraph to maintain our dynamic type
320
- const graphWithNodes = plan.nodes.reduce<DynamicStateGraph>(
321
- (g, node) => g.addNode(buildNode(plan, node, options)) as DynamicStateGraph,
320
+ const graphWithNodes = monitor.nodes.reduce<DynamicStateGraph>(
321
+ (g, node) =>
322
+ g.addNode(buildNode(monitor, node, options)) as DynamicStateGraph,
322
323
  graph,
323
324
  );
324
325
 
325
326
  // Add all edges
326
327
  // Cast the edge method to accept string arguments since ts-edge expects literal types
327
- // but we have runtime strings from the plan
328
- const graphWithEdges = plan.edges.reduce<DynamicStateGraph>((g, edge) => {
328
+ // but we have runtime strings from the monitor
329
+ const graphWithEdges = monitor.edges.reduce<DynamicStateGraph>((g, edge) => {
329
330
  const addEdge = g.edge as (from: string, to: string) => DynamicStateGraph;
330
331
  return addEdge(edge.from, edge.to);
331
332
  }, graphWithNodes);
332
333
 
333
334
  return graphWithEdges;
334
335
  }
335
- export async function executePlanV1(
336
- plan: PlanV1,
336
+ export async function executeMonitorV1(
337
+ monitor: MonitorV1,
337
338
  organizationId: string,
338
339
  options: ExecutionOptions,
339
340
  ): Promise<ExecutionResult> {
@@ -342,34 +343,22 @@ export async function executePlanV1(
342
343
  // Generate or use provided executionId
343
344
  const executionId = options.executionId || randomUUID();
344
345
 
345
- // Migrate plan to latest version if needed
346
- let migratedPlan = plan;
347
- if (plan.version !== CURRENT_PLAN_VERSION) {
348
- if (!isSupportedVersion(plan.version)) {
349
- throw new Error(
350
- `Unsupported plan version: ${plan.version}. Supported versions: ${CURRENT_PLAN_VERSION}`,
351
- );
352
- }
353
- // Migrate to latest version
354
- migratedPlan = migrateToLatest(plan as any) as PlanV1;
355
- }
356
-
357
346
  // Create execution context for event emission
358
347
  const executionContext = new ExecutionContext(
359
348
  executionId,
360
- migratedPlan,
349
+ monitor,
361
350
  organizationId,
362
351
  options.eventEmitter,
363
352
  );
364
353
 
365
354
  try {
366
- // Resolve secrets if the plan contains any
367
- let resolvedPlan = migratedPlan;
368
- if (planHasSecrets(plan)) {
355
+ // Resolve secrets if the monitor contains any
356
+ let resolvedMonitor = monitor;
357
+ if (planHasSecrets(monitor)) {
369
358
  if (!options.secretRegistry) {
370
359
  throw new SecretResolutionError(
371
- "Plan contains secret references but no secret registry was provided",
372
- { provider: "unknown", ref: "unknown" },
360
+ "Monitor contains secret references but no secret registry was provided",
361
+ { ref: "unknown" },
373
362
  );
374
363
  }
375
364
 
@@ -380,7 +369,10 @@ export async function executePlanV1(
380
369
  });
381
370
 
382
371
  try {
383
- resolvedPlan = await resolveSecretsInPlan(plan, options.secretRegistry);
372
+ resolvedMonitor = await resolveSecretsInMonitor(
373
+ monitor,
374
+ options.secretRegistry,
375
+ );
384
376
 
385
377
  executionContext.emit({
386
378
  type: "NODE_END",
@@ -402,13 +394,13 @@ export async function executePlanV1(
402
394
  }
403
395
  }
404
396
 
405
- // Emit PLAN_START event
397
+ // Emit MONITOR_START event
406
398
  executionContext.emit({
407
- type: "PLAN_START",
408
- planName: resolvedPlan.name,
409
- planVersion: resolvedPlan.version,
410
- nodeCount: resolvedPlan.nodes.length,
411
- edgeCount: resolvedPlan.edges.length,
399
+ type: "MONITOR_START",
400
+ monitorName: resolvedMonitor.name,
401
+ monitorVersion: resolvedMonitor.version,
402
+ nodeCount: resolvedMonitor.nodes.length,
403
+ edgeCount: resolvedMonitor.edges.length,
412
404
  });
413
405
 
414
406
  // Call onStart callback if provided
@@ -422,7 +414,7 @@ export async function executePlanV1(
422
414
  }
423
415
 
424
416
  // Build execution graph (state-based)
425
- const graph = buildGraph(resolvedPlan, options, executionContext);
417
+ const graph = buildGraph(resolvedMonitor, options, executionContext);
426
418
 
427
419
  // Compile and run the state graph
428
420
  const app = graph.compile(START, END);
@@ -436,9 +428,9 @@ export async function executePlanV1(
436
428
  const finalResults = graphResult.output?.results || [];
437
429
  const finalErrors = graphResult.output?.errors || [errorMessage];
438
430
 
439
- // Emit PLAN_END event
431
+ // Emit MONITOR_END event
440
432
  executionContext.emit({
441
- type: "PLAN_END",
433
+ type: "MONITOR_END",
442
434
  success: false,
443
435
  totalDuration_ms: Date.now() - startTime,
444
436
  nodeResultCount: finalResults.length,
@@ -477,9 +469,9 @@ export async function executePlanV1(
477
469
  const success = finalState.errors.length === 0;
478
470
  const duration = Date.now() - startTime;
479
471
 
480
- // Emit PLAN_END event
472
+ // Emit MONITOR_END event
481
473
  executionContext.emit({
482
- type: "PLAN_END",
474
+ type: "MONITOR_END",
483
475
  success,
484
476
  totalDuration_ms: duration,
485
477
  nodeResultCount: finalState.results.length,
@@ -519,9 +511,9 @@ export async function executePlanV1(
519
511
  const errorMessage = error instanceof Error ? error.message : String(error);
520
512
  const duration = Date.now() - startTime;
521
513
 
522
- // Emit PLAN_END event
514
+ // Emit MONITOR_END event
523
515
  executionContext.emit({
524
- type: "PLAN_END",
516
+ type: "MONITOR_END",
525
517
  success: false,
526
518
  totalDuration_ms: duration,
527
519
  nodeResultCount: 0,
@@ -572,12 +564,12 @@ async function executeHttpRequest(
572
564
  const path = endpoint.path;
573
565
  const url = `${baseUrl}${path}`;
574
566
 
575
- // TODO: Add retry configuration from plan (node-level or plan-level)
567
+ // TODO: Add retry configuration from monitor (node-level or monitor-level)
576
568
  // For now, we always attempt once (attempt: 1)
577
569
  const attempt = 1;
578
570
 
579
571
  // After secret resolution, headers are guaranteed to be plain strings
580
- // Cast is safe because resolveSecretsInPlan substitutes all SecretRefs
572
+ // Cast is safe because resolveSecretsInMonitor substitutes all SecretRefs
581
573
  const resolvedHeaders = endpoint.headers as
582
574
  | Record<string, string>
583
575
  | undefined;
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { executePlanV1 } from "./executor.js";
1
+ export { executeMonitorV1 } from "./executor.js";
2
2
  export type {
3
3
  ExecutionOptions,
4
4
  ExecutionResult,
@@ -10,12 +10,12 @@ export type {
10
10
  StatusCallbacks,
11
11
  } from "./types.js";
12
12
  export type {
13
- TestPlan,
13
+ TestMonitor,
14
14
  HttpRequest as HttpRequestNode,
15
15
  WaitNode,
16
16
  AssertionNode,
17
17
  Edge,
18
- } from "./test-plan-types.js";
18
+ } from "./test-monitor-types.js";
19
19
  export {
20
20
  AxiosAdapter,
21
21
  StubAdapter,
@@ -31,8 +31,8 @@ export {
31
31
  export type {
32
32
  ExecutionEvent,
33
33
  BaseEvent,
34
- PlanStartEvent,
35
- PlanEndEvent,
34
+ MonitorStartEvent,
35
+ MonitorEndEvent,
36
36
  NodeStartEvent,
37
37
  NodeEndEvent,
38
38
  HttpRequestEvent,
@@ -62,8 +62,8 @@ export {
62
62
  // Registry
63
63
  SecretProviderRegistry,
64
64
  // Resolution utilities
65
- resolveSecretsInPlan,
66
- collectSecretsFromPlan,
65
+ resolveSecretsInMonitor,
66
+ collectSecretsFromMonitor,
67
67
  planHasSecrets,
68
68
  // Providers
69
69
  EnvSecretProvider,
@@ -1,10 +1,10 @@
1
1
  /**
2
- * Secret management for griffin plan executor.
2
+ * Secret management for griffin monitor executor.
3
3
  *
4
4
  * This module provides:
5
5
  * - SecretProvider interface for implementing custom providers
6
- * - SecretProviderRegistry for managing multiple providers
7
- * - Secret resolution utilities for test plans
6
+ * - SecretProviderRegistry for the configured secret provider
7
+ * - Secret resolution utilities for test monitors
8
8
  * - Built-in providers: env, aws, vault
9
9
  */
10
10
 
@@ -24,8 +24,8 @@ export { SecretProviderRegistry } from "./registry.js";
24
24
 
25
25
  // Resolution utilities
26
26
  export {
27
- resolveSecretsInPlan,
28
- collectSecretsFromPlan,
27
+ resolveSecretsInMonitor,
28
+ collectSecretsFromMonitor,
29
29
  planHasSecrets,
30
30
  } from "./resolver.js";
31
31
 
@@ -81,7 +81,7 @@ export class AwsSecretsManagerProvider implements SecretProvider {
81
81
  if (!response.SecretString) {
82
82
  throw new SecretResolutionError(
83
83
  `Secret "${secretId}" does not contain a string value (binary secrets are not supported)`,
84
- { provider: this.name, ref },
84
+ { ref },
85
85
  );
86
86
  }
87
87
 
@@ -110,7 +110,6 @@ export class AwsSecretsManagerProvider implements SecretProvider {
110
110
  }
111
111
 
112
112
  throw new SecretResolutionError(message, {
113
- provider: this.name,
114
113
  ref,
115
114
  cause: error,
116
115
  });
@@ -135,7 +134,7 @@ export class AwsSecretsManagerProvider implements SecretProvider {
135
134
  if (typeof parsed !== "object" || parsed === null) {
136
135
  throw new SecretResolutionError(
137
136
  `Secret "${ref}" is not a JSON object, cannot extract field "${field}"`,
138
- { provider: this.name, ref },
137
+ { ref },
139
138
  );
140
139
  }
141
140
 
@@ -144,7 +143,7 @@ export class AwsSecretsManagerProvider implements SecretProvider {
144
143
  if (value === undefined) {
145
144
  throw new SecretResolutionError(
146
145
  `Field "${field}" not found in secret "${ref}"`,
147
- { provider: this.name, ref },
146
+ { ref },
148
147
  );
149
148
  }
150
149
 
@@ -159,7 +158,7 @@ export class AwsSecretsManagerProvider implements SecretProvider {
159
158
  `Failed to parse secret "${ref}" as JSON for field extraction: ${
160
159
  error instanceof Error ? error.message : String(error)
161
160
  }`,
162
- { provider: this.name, ref, cause: error },
161
+ { ref, cause: error },
163
162
  );
164
163
  }
165
164
  }
@@ -44,7 +44,7 @@ export class EnvSecretProvider implements SecretProvider {
44
44
  if (value === undefined) {
45
45
  throw new SecretResolutionError(
46
46
  `Environment variable "${envKey}" is not set`,
47
- { provider: this.name, ref },
47
+ { ref },
48
48
  );
49
49
  }
50
50
 
@@ -116,21 +116,21 @@ export class VaultProvider implements SecretProvider {
116
116
  if (response.status === 404) {
117
117
  throw new SecretResolutionError(
118
118
  `Secret "${secretPath}" not found in Vault`,
119
- { provider: this.name, ref },
119
+ { ref },
120
120
  );
121
121
  }
122
122
 
123
123
  if (response.status === 403) {
124
124
  throw new SecretResolutionError(
125
125
  `Access denied to secret "${secretPath}". Check Vault policies.`,
126
- { provider: this.name, ref },
126
+ { ref },
127
127
  );
128
128
  }
129
129
 
130
130
  if (response.status !== 200) {
131
131
  throw new SecretResolutionError(
132
132
  `Vault returned status ${response.status} for secret "${secretPath}"`,
133
- { provider: this.name, ref },
133
+ { ref },
134
134
  );
135
135
  }
136
136
 
@@ -149,7 +149,7 @@ export class VaultProvider implements SecretProvider {
149
149
  if (!kvData?.data) {
150
150
  throw new SecretResolutionError(
151
151
  `Invalid KV v2 response structure for secret "${secretPath}"`,
152
- { provider: this.name, ref },
152
+ { ref },
153
153
  );
154
154
  }
155
155
  secretData = kvData.data;
@@ -158,7 +158,7 @@ export class VaultProvider implements SecretProvider {
158
158
  if (!data?.data || typeof data.data !== "object") {
159
159
  throw new SecretResolutionError(
160
160
  `Invalid KV v1 response structure for secret "${secretPath}"`,
161
- { provider: this.name, ref },
161
+ { ref },
162
162
  );
163
163
  }
164
164
  secretData = data.data as Record<string, unknown>;
@@ -180,7 +180,7 @@ export class VaultProvider implements SecretProvider {
180
180
  `Failed to retrieve secret "${secretPath}" from Vault: ${
181
181
  error instanceof Error ? error.message : String(error)
182
182
  }`,
183
- { provider: this.name, ref, cause: error },
183
+ { ref, cause: error },
184
184
  );
185
185
  }
186
186
  }
@@ -204,7 +204,7 @@ export class VaultProvider implements SecretProvider {
204
204
  if (value === undefined) {
205
205
  throw new SecretResolutionError(
206
206
  `Field "${field}" not found in secret "${ref}"`,
207
- { provider: this.name, ref },
207
+ { ref },
208
208
  );
209
209
  }
210
210