@pikku/inspector 0.12.41 → 0.12.43

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 (108) hide show
  1. package/CHANGELOG.md +104 -0
  2. package/dist/add/add-addon-bans.js +1 -0
  3. package/dist/add/add-ai-agent.d.ts +3 -1
  4. package/dist/add/add-ai-agent.js +82 -0
  5. package/dist/add/add-credential.js +3 -1
  6. package/dist/add/add-functions.js +10 -9
  7. package/dist/add/add-gateway.js +3 -0
  8. package/dist/add/add-http-route.js +2 -2
  9. package/dist/add/add-mcp-prompt.js +0 -1
  10. package/dist/add/add-mcp-resource.js +0 -1
  11. package/dist/add/add-permission.d.ts +1 -1
  12. package/dist/add/add-permission.js +3 -177
  13. package/dist/add/add-queue-worker.js +3 -0
  14. package/dist/add/add-schedule.js +3 -0
  15. package/dist/add/add-scope.d.ts +2 -0
  16. package/dist/add/add-scope.js +146 -0
  17. package/dist/add/add-trigger.js +3 -0
  18. package/dist/add/add-wire-remote-addon.d.ts +10 -0
  19. package/dist/add/add-wire-remote-addon.js +66 -0
  20. package/dist/add/add-workflow-graph.js +32 -3
  21. package/dist/error-codes.d.ts +3 -0
  22. package/dist/error-codes.js +4 -0
  23. package/dist/inspector.js +19 -7
  24. package/dist/types.d.ts +19 -13
  25. package/dist/utils/custom-types-generator.js +2 -1
  26. package/dist/utils/ensure-function-metadata.d.ts +15 -0
  27. package/dist/utils/ensure-function-metadata.js +24 -0
  28. package/dist/utils/filter-inspector-state.js +9 -0
  29. package/dist/utils/get-property-value.d.ts +7 -2
  30. package/dist/utils/get-property-value.js +48 -1
  31. package/dist/utils/load-addon-functions-meta.js +81 -6
  32. package/dist/utils/nested-project-filter.d.ts +1 -0
  33. package/dist/utils/nested-project-filter.js +29 -0
  34. package/dist/utils/permissions.d.ts +1 -21
  35. package/dist/utils/permissions.js +17 -108
  36. package/dist/utils/post-process.d.ts +30 -1
  37. package/dist/utils/post-process.js +150 -72
  38. package/dist/utils/serialize-inspector-state.d.ts +13 -8
  39. package/dist/utils/serialize-inspector-state.js +12 -6
  40. package/dist/utils/serialize-permissions-groups-meta.d.ts +0 -2
  41. package/dist/utils/serialize-permissions-groups-meta.js +0 -26
  42. package/dist/utils/workflow/derive-workflow-plan.js +9 -3
  43. package/dist/utils/workflow/dsl/extract-dsl-workflow.js +56 -1
  44. package/dist/utils/workflow/dsl/patterns.d.ts +10 -0
  45. package/dist/utils/workflow/dsl/patterns.js +24 -8
  46. package/dist/utils/workflow/dsl/validation.js +3 -4
  47. package/dist/utils/workflow/graph/convert-dsl-to-graph.js +14 -0
  48. package/dist/utils/workflow/graph/finalize-workflows.d.ts +7 -0
  49. package/dist/utils/workflow/graph/finalize-workflows.js +11 -2
  50. package/dist/utils/workflow/graph/serialize-workflow-graph.d.ts +2 -0
  51. package/dist/utils/workflow/graph/serialize-workflow-graph.js +4 -0
  52. package/dist/utils/workflow/graph/workflow-graph.types.d.ts +6 -2
  53. package/dist/visit.js +4 -0
  54. package/package.json +3 -3
  55. package/src/add/add-addon-bans.ts +1 -0
  56. package/src/add/add-ai-agent.test.ts +87 -0
  57. package/src/add/add-ai-agent.ts +122 -0
  58. package/src/add/add-credential.ts +6 -0
  59. package/src/add/add-functions.ts +10 -12
  60. package/src/add/add-gateway.ts +11 -0
  61. package/src/add/add-http-route.ts +2 -8
  62. package/src/add/add-mcp-prompt.ts +0 -1
  63. package/src/add/add-mcp-resource.ts +0 -1
  64. package/src/add/add-permission.ts +4 -242
  65. package/src/add/add-queue-worker.ts +11 -0
  66. package/src/add/add-schedule.ts +11 -0
  67. package/src/add/add-scope.test.ts +346 -0
  68. package/src/add/add-scope.ts +225 -0
  69. package/src/add/add-trigger.ts +11 -0
  70. package/src/add/add-wire-remote-addon.ts +77 -0
  71. package/src/add/add-workflow-graph-input.test.ts +94 -0
  72. package/src/add/add-workflow-graph-notes.test.ts +74 -0
  73. package/src/add/add-workflow-graph.ts +35 -3
  74. package/src/add/inline-wiring-function.test.ts +104 -0
  75. package/src/add/validate-workflow-graph-addons.test.ts +102 -0
  76. package/src/error-codes.ts +5 -0
  77. package/src/inspector.ts +22 -6
  78. package/src/types.ts +16 -17
  79. package/src/utils/custom-types-generator.test.ts +26 -1
  80. package/src/utils/custom-types-generator.ts +2 -1
  81. package/src/utils/ensure-function-metadata.ts +42 -0
  82. package/src/utils/filter-inspector-state.test.ts +0 -2
  83. package/src/utils/filter-inspector-state.ts +9 -0
  84. package/src/utils/get-property-value.test.ts +141 -0
  85. package/src/utils/get-property-value.ts +62 -1
  86. package/src/utils/load-addon-functions-meta.test.ts +157 -0
  87. package/src/utils/load-addon-functions-meta.ts +94 -6
  88. package/src/utils/load-addon-scopes.test.ts +138 -0
  89. package/src/utils/nested-project-filter.test.ts +53 -0
  90. package/src/utils/nested-project-filter.ts +28 -0
  91. package/src/utils/permissions.test.ts +7 -232
  92. package/src/utils/permissions.ts +20 -160
  93. package/src/utils/post-process.test.ts +269 -4
  94. package/src/utils/post-process.ts +216 -95
  95. package/src/utils/serialize-inspector-state.ts +22 -25
  96. package/src/utils/serialize-permissions-groups-meta.ts +0 -28
  97. package/src/utils/workflow/derive-workflow-plan.test.ts +41 -3
  98. package/src/utils/workflow/derive-workflow-plan.ts +11 -4
  99. package/src/utils/workflow/dsl/extract-dsl-workflow.ts +66 -0
  100. package/src/utils/workflow/dsl/patterns.ts +34 -8
  101. package/src/utils/workflow/dsl/validation.ts +3 -4
  102. package/src/utils/workflow/graph/convert-dsl-to-graph.ts +15 -0
  103. package/src/utils/workflow/graph/finalize-workflows.test.ts +50 -0
  104. package/src/utils/workflow/graph/finalize-workflows.ts +13 -2
  105. package/src/utils/workflow/graph/serialize-workflow-graph.ts +6 -0
  106. package/src/utils/workflow/graph/workflow-graph.types.ts +8 -0
  107. package/src/visit.ts +4 -0
  108. package/tsconfig.tsbuildinfo +1 -1
@@ -63,9 +63,7 @@ function containsConditional(steps: WorkflowStepMeta[]): boolean {
63
63
  * e.g. "awaiting_approval" → "Awaiting approval", "building-image" → "Building image"
64
64
  */
65
65
  function reasonToLabel(reason: string): string {
66
- return reason
67
- .replace(/[-_]/g, ' ')
68
- .replace(/^(.)/, (c) => c.toUpperCase())
66
+ return reason.replace(/[-_]/g, ' ').replace(/^(.)/, (c) => c.toUpperCase())
69
67
  }
70
68
 
71
69
  /** Flatten named steps (rpc/inline/sleep/parallel children) in source order. */
@@ -88,13 +86,22 @@ function collectNamedSteps(steps: WorkflowStepMeta[]): WorkflowPlannedStep[] {
88
86
  displayName: reasonToLabel(step.reason),
89
87
  })
90
88
  break
89
+ case 'approval':
90
+ // Same as suspend, but namespaced `__workflow_approval:` to match the
91
+ // runtime's separate step key.
92
+ planned.push({
93
+ stepName: `__workflow_approval:${step.reason}`,
94
+ displayName: reasonToLabel(step.reason),
95
+ })
96
+ break
91
97
  case 'parallel':
92
98
  for (const child of step.children) {
93
99
  planned.push({ stepName: child.stepName })
94
100
  }
95
101
  break
96
102
  case 'branch':
97
- for (const b of step.branches) planned.push(...collectNamedSteps(b.steps))
103
+ for (const b of step.branches)
104
+ planned.push(...collectNamedSteps(b.steps))
98
105
  if (step.elseSteps) planned.push(...collectNamedSteps(step.elseSteps))
99
106
  break
100
107
  case 'switch':
@@ -8,6 +8,7 @@ import type {
8
8
  FanoutStepMeta,
9
9
  CancelStepMeta,
10
10
  SuspendStepMeta,
11
+ ApprovalStepMeta,
11
12
  SetStepMeta,
12
13
  SwitchStepMeta,
13
14
  SwitchCaseMeta,
@@ -25,6 +26,7 @@ import {
25
26
  extractActorFromOptions,
26
27
  isWorkflowSleepCall,
27
28
  isWorkflowSuspendCall,
29
+ isWorkflowApprovalCall,
28
30
  isThrowCancelException,
29
31
  extractCancelReason,
30
32
  isParallelFanout,
@@ -520,6 +522,22 @@ function extractExpressionStatement(
520
522
  return extractSuspendStep(call, context)
521
523
  }
522
524
 
525
+ if (isWorkflowApprovalCall(call, context.checker)) {
526
+ const step = extractApprovalStep(call, context, outputVar)
527
+
528
+ // Unlike suspend, an approval yields a value, so a downstream step can
529
+ // reference it — track the binding the same way workflow.do() does.
530
+ if (outputVar && step) {
531
+ const type = context.checker.getTypeAtLocation(expr)
532
+ context.outputVars.set(outputVar, { type, node: expr })
533
+ if (isArrayType(type, context.checker)) {
534
+ context.arrayVars.add(outputVar)
535
+ }
536
+ }
537
+
538
+ return step
539
+ }
540
+
523
541
  // Check for parallel group or fanout
524
542
  if (isParallelFanout(call)) {
525
543
  return extractParallelFanout(call, context)
@@ -738,6 +756,54 @@ function extractSuspendStep(
738
756
  }
739
757
  }
740
758
 
759
+ /**
760
+ * Extract approval step from workflow.approval() call
761
+ */
762
+ function extractApprovalStep(
763
+ call: ts.CallExpression,
764
+ context: ExtractionContext,
765
+ outputVar?: string
766
+ ): ApprovalStepMeta | null {
767
+ const args = call.arguments
768
+ if (args.length < 1) return null
769
+
770
+ try {
771
+ const reason = extractStringLiteral(args[0], context.checker)
772
+ const step: ApprovalStepMeta = {
773
+ type: 'approval',
774
+ reason,
775
+ }
776
+ if (outputVar) {
777
+ step.outputVar = outputVar
778
+ }
779
+ // The `schema` option is a runtime value validated inside the workflow body,
780
+ // so it is deliberately not serialized here — only `expiry`, which the graph
781
+ // and planned-step ladder need in order to describe the gate.
782
+ const options = args[1]
783
+ if (options && ts.isObjectLiteralExpression(options)) {
784
+ for (const prop of options.properties) {
785
+ if (
786
+ ts.isPropertyAssignment(prop) &&
787
+ prop.name.getText() === 'expiry' &&
788
+ (ts.isStringLiteral(prop.initializer) ||
789
+ ts.isNumericLiteral(prop.initializer))
790
+ ) {
791
+ step.expiry = ts.isNumericLiteral(prop.initializer)
792
+ ? Number(prop.initializer.text)
793
+ : prop.initializer.text
794
+ }
795
+ }
796
+ }
797
+ return step
798
+ } catch (error) {
799
+ context.errors.push({
800
+ message: `Failed to extract approval step: ${error instanceof Error ? error.message : String(error)}`,
801
+ node: call,
802
+ })
803
+ return null
804
+ }
805
+ }
806
+
741
807
  /**
742
808
  * Extract cancel step from throw WorkflowCancelledException statement
743
809
  */
@@ -4,6 +4,18 @@ import * as ts from 'typescript'
4
4
  * Pattern detection helpers for DSL workflow extraction
5
5
  */
6
6
 
7
+ /**
8
+ * The wire object handed to a DSL func is named `workflow` in a workflow and
9
+ * `scenario` in a scenario — both carry the same `do`/`sleep`/`suspend` DSL, so
10
+ * step extraction accepts either identifier.
11
+ */
12
+ export function isWorkflowWireIdentifier(expr: ts.Expression): boolean {
13
+ return (
14
+ ts.isIdentifier(expr) &&
15
+ (expr.text === 'workflow' || expr.text === 'scenario')
16
+ )
17
+ }
18
+
7
19
  /**
8
20
  * Check if a call expression is workflow.do() or workflow.expectEventually()
9
21
  * (both are RPC steps; expectEventually is the polling variant used by scenarios)
@@ -20,8 +32,7 @@ export function isWorkflowDoCall(
20
32
  return (
21
33
  (propAccess.name.text === 'do' ||
22
34
  propAccess.name.text === 'expectEventually') &&
23
- ts.isIdentifier(propAccess.expression) &&
24
- propAccess.expression.text === 'workflow'
35
+ isWorkflowWireIdentifier(propAccess.expression)
25
36
  )
26
37
  }
27
38
 
@@ -34,8 +45,7 @@ export function isWorkflowExpectEventuallyCall(
34
45
  return (
35
46
  ts.isPropertyAccessExpression(node.expression) &&
36
47
  node.expression.name.text === 'expectEventually' &&
37
- ts.isIdentifier(node.expression.expression) &&
38
- node.expression.expression.text === 'workflow'
48
+ isWorkflowWireIdentifier(node.expression.expression)
39
49
  )
40
50
  }
41
51
 
@@ -83,8 +93,7 @@ export function isWorkflowSleepCall(
83
93
  const propAccess = node.expression
84
94
  return (
85
95
  propAccess.name.text === 'sleep' &&
86
- ts.isIdentifier(propAccess.expression) &&
87
- propAccess.expression.text === 'workflow'
96
+ isWorkflowWireIdentifier(propAccess.expression)
88
97
  )
89
98
  }
90
99
 
@@ -102,8 +111,25 @@ export function isWorkflowSuspendCall(
102
111
  const propAccess = node.expression
103
112
  return (
104
113
  propAccess.name.text === 'suspend' &&
105
- ts.isIdentifier(propAccess.expression) &&
106
- propAccess.expression.text === 'workflow'
114
+ isWorkflowWireIdentifier(propAccess.expression)
115
+ )
116
+ }
117
+
118
+ /**
119
+ * Check if a call expression is workflow.approval()
120
+ */
121
+ export function isWorkflowApprovalCall(
122
+ node: ts.CallExpression,
123
+ _checker: ts.TypeChecker
124
+ ): boolean {
125
+ if (!ts.isPropertyAccessExpression(node.expression)) {
126
+ return false
127
+ }
128
+
129
+ const propAccess = node.expression
130
+ return (
131
+ propAccess.name.text === 'approval' &&
132
+ isWorkflowWireIdentifier(propAccess.expression)
107
133
  )
108
134
  }
109
135
 
@@ -1,4 +1,5 @@
1
1
  import * as ts from 'typescript'
2
+ import { isWorkflowWireIdentifier } from './patterns.js'
2
3
 
3
4
  /**
4
5
  * Validation rules for DSL workflows
@@ -78,8 +79,7 @@ export function validateNoDisallowedPatterns(
78
79
  const propAccess = node.expression
79
80
  if (
80
81
  propAccess.name.text === 'do' &&
81
- ts.isIdentifier(propAccess.expression) &&
82
- propAccess.expression.text === 'workflow'
82
+ isWorkflowWireIdentifier(propAccess.expression)
83
83
  ) {
84
84
  const secondArg = node.arguments[1]
85
85
  if (
@@ -154,8 +154,7 @@ export function validateAwaitedCalls(node: ts.Node): ValidationError[] {
154
154
  const propAccess = node.expression
155
155
  if (
156
156
  (propAccess.name.text === 'do' || propAccess.name.text === 'sleep') &&
157
- ts.isIdentifier(propAccess.expression) &&
158
- propAccess.expression.text === 'workflow'
157
+ isWorkflowWireIdentifier(propAccess.expression)
159
158
  ) {
160
159
  if (!parentIsAwait && !insidePromiseAll) {
161
160
  errors.push({
@@ -132,6 +132,21 @@ function convertStepToNode(
132
132
  return [node]
133
133
  }
134
134
 
135
+ case 'approval': {
136
+ // Unlike `suspend` — which has no output and so is deliberately absent
137
+ // from the graph — an approval yields a value a later step can reference,
138
+ // so it must be a real node for $ref resolution and graphHash to see it.
139
+ const node: FlowNode = {
140
+ nodeId,
141
+ flow: 'approval',
142
+ reason: step.reason,
143
+ outputVar: step.outputVar,
144
+ expiry: step.expiry,
145
+ next: nextNodeId,
146
+ }
147
+ return [node]
148
+ }
149
+
135
150
  case 'inline': {
136
151
  const node: FlowNode = {
137
152
  nodeId,
@@ -0,0 +1,50 @@
1
+ import { test } from 'node:test'
2
+ import assert from 'node:assert'
3
+ import { computeGraphHash } from './finalize-workflows.js'
4
+ import type {
5
+ SerializedWorkflowGraph,
6
+ FunctionNode,
7
+ } from './workflow-graph.types.js'
8
+
9
+ function graph(
10
+ overrides: Partial<SerializedWorkflowGraph> = {},
11
+ nodeOverrides: Partial<FunctionNode> = {}
12
+ ): SerializedWorkflowGraph {
13
+ const node: FunctionNode = {
14
+ nodeId: 'a',
15
+ rpcName: 'doThing',
16
+ input: { x: { $ref: 'trigger', path: 'x' } },
17
+ next: 'b',
18
+ ...nodeOverrides,
19
+ }
20
+ return {
21
+ name: 'wf',
22
+ pikkuFuncId: 'wf',
23
+ source: 'graph',
24
+ nodes: { a: node, b: { nodeId: 'b', rpcName: 'finish' } },
25
+ entryNodeIds: ['a'],
26
+ ...overrides,
27
+ }
28
+ }
29
+
30
+ test('computeGraphHash: node-level notes do not change the hash', () => {
31
+ const without = computeGraphHash(graph())
32
+ const withNote = computeGraphHash(
33
+ graph({}, { notes: 'imported node "Do Thing"' })
34
+ )
35
+ assert.strictEqual(withNote, without)
36
+ })
37
+
38
+ test('computeGraphHash: graph-level notes do not change the hash', () => {
39
+ const without = computeGraphHash(graph())
40
+ const withNotes = computeGraphHash(
41
+ graph({ notes: ['sticky note one', 'sticky note two'] })
42
+ )
43
+ assert.strictEqual(withNotes, without)
44
+ })
45
+
46
+ test('computeGraphHash: a topology change DOES change the hash', () => {
47
+ const base = computeGraphHash(graph())
48
+ const changed = computeGraphHash(graph({}, { next: 'c' }))
49
+ assert.notStrictEqual(changed, base)
50
+ })
@@ -102,12 +102,23 @@ function computeStepHashes(
102
102
  }
103
103
  }
104
104
 
105
- function computeGraphHash(graph: SerializedWorkflowGraph): string {
105
+ /**
106
+ * Hash of graph topology only. `notes` (node- and graph-level) is deliberately
107
+ * excluded so editing documentation never changes the hash / marks the workflow
108
+ * as a new version.
109
+ */
110
+ export function computeGraphHash(graph: SerializedWorkflowGraph): string {
111
+ const nodesForHash = Object.fromEntries(
112
+ Object.entries(graph.nodes).map(([nodeId, node]) => {
113
+ const { notes: _notes, ...rest } = node as { notes?: string }
114
+ return [nodeId, rest]
115
+ })
116
+ )
106
117
  return hashString(
107
118
  canonicalJSON({
108
119
  source: graph.source,
109
120
  context: graph.context,
110
- nodes: graph.nodes,
121
+ nodes: nodesForHash,
111
122
  entryNodeIds: graph.entryNodeIds,
112
123
  }),
113
124
  12
@@ -89,12 +89,14 @@ export function serializeWorkflowGraph(
89
89
  input?: (ref: any) => Record<string, unknown>
90
90
  next?: string | string[] | Record<string, string | string[]>
91
91
  onError?: string | string[]
92
+ notes?: string
92
93
  }
93
94
  >
94
95
  },
95
96
  options?: {
96
97
  description?: string
97
98
  tags?: string[]
99
+ notes?: string[]
98
100
  }
99
101
  ): SerializedWorkflowGraph {
100
102
  const nodes: Record<string, SerializedGraphNode> = {}
@@ -149,6 +151,9 @@ export function serializeWorkflowGraph(
149
151
  next: serializeNext(node.next),
150
152
  onError: node.onError,
151
153
  }
154
+ if (node.notes !== undefined) {
155
+ funcNode.notes = node.notes
156
+ }
152
157
  nodes[nodeId] = funcNode
153
158
 
154
159
  // Entry nodes have no incoming edges
@@ -163,6 +168,7 @@ export function serializeWorkflowGraph(
163
168
  source: 'graph' as const,
164
169
  description: options?.description,
165
170
  tags: options?.tags,
171
+ notes: options?.notes,
166
172
  nodes,
167
173
  entryNodeIds,
168
174
  }
@@ -76,6 +76,9 @@ export type SerializedNext =
76
76
  /** Default target if no conditions match */
77
77
  default?: string | string[]
78
78
  }
79
+ // Key-based branching: the running node picks a key via `graph.branch(key)`,
80
+ // routing to `next[key]`. Keys are branch/output identifiers, not predicates.
81
+ | Record<string, string | string[]>
79
82
 
80
83
  /**
81
84
  * Node execution options
@@ -94,6 +97,7 @@ export interface NodeOptions {
94
97
  */
95
98
  export type FlowType =
96
99
  | 'sleep'
100
+ | 'approval'
97
101
  | 'branch'
98
102
  | 'parallel'
99
103
  | 'fanout'
@@ -128,6 +132,8 @@ interface BaseNode {
128
132
  onError?: string | string[]
129
133
  /** Execution options */
130
134
  options?: NodeOptions
135
+ /** Free-text node documentation. Non-semantic — excluded from graphHash. */
136
+ notes?: string
131
137
  }
132
138
 
133
139
  /**
@@ -209,6 +215,8 @@ export interface SerializedWorkflowGraph {
209
215
  context?: WorkflowContext
210
216
  /** Serialized nodes */
211
217
  nodes: Record<string, SerializedGraphNode>
218
+ /** Graph-level free-text notes (e.g. imported sticky notes). Non-semantic — excluded from graphHash. */
219
+ notes?: string[]
212
220
  /** Entry node(s) - first nodes to execute */
213
221
  entryNodeIds: string[]
214
222
  /** Hash of graph topology (nodes, edges, input mappings) */
package/src/visit.ts CHANGED
@@ -20,12 +20,14 @@ import { addChannel } from './add/add-channel.js'
20
20
  import { addGateway } from './add/add-gateway.js'
21
21
  import { addRPCInvocations } from './add/add-rpc-invocations.js'
22
22
  import { addWireAddon } from './add/add-wire-addon.js'
23
+ import { addWireRemoteAddon } from './add/add-wire-remote-addon.js'
23
24
  import { addMiddleware } from './add/add-middleware.js'
24
25
  import { addPermission } from './add/add-permission.js'
25
26
  import { addCLI, addCLIRenderers } from './add/add-cli.js'
26
27
  import { addAuth } from './add/add-auth.js'
27
28
  import { addSecret } from './add/add-secret.js'
28
29
  import { addCredential } from './add/add-credential.js'
30
+ import { addScope } from './add/add-scope.js'
29
31
  import { addVariable } from './add/add-variable.js'
30
32
  import { addWorkflowGraph } from './add/add-workflow-graph.js'
31
33
  import { addAIAgent } from './add/add-ai-agent.js'
@@ -96,6 +98,7 @@ export const visitSetup = (
96
98
 
97
99
  addRPCInvocations(node, state, logger)
98
100
  addWireAddon(node, state, logger)
101
+ addWireRemoteAddon(node, state, logger)
99
102
  addMiddleware(logger, node, checker, state, options)
100
103
  addPermission(logger, node, checker, state, options)
101
104
  addApprovalDescription(logger, node, checker, state, options)
@@ -147,6 +150,7 @@ export const visitRoutes = (
147
150
  addAuth(logger, node, checker, state, nextOptions)
148
151
  addSecret(logger, node, checker, state, nextOptions)
149
152
  addCredential(logger, node, checker, state, nextOptions)
153
+ addScope(logger, node, checker, state, nextOptions)
150
154
  addVariable(logger, node, checker, state, nextOptions)
151
155
 
152
156
  addHTTPRoute(logger, node, checker, state, nextOptions)