@shipfox/expression 1.2.0 → 2.0.0

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 (41) hide show
  1. package/README.md +25 -12
  2. package/dist/expression/create-workflow-expression.d.ts.map +1 -1
  3. package/dist/expression/create-workflow-expression.js +17 -3
  4. package/dist/expression/create-workflow-expression.js.map +1 -1
  5. package/dist/index.d.ts +4 -3
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +3 -2
  8. package/dist/index.js.map +1 -1
  9. package/dist/plan/context-key-access.d.ts +2 -0
  10. package/dist/plan/context-key-access.d.ts.map +1 -1
  11. package/dist/plan/context-key-access.js +3 -0
  12. package/dist/plan/context-key-access.js.map +1 -1
  13. package/dist/plan/evaluate-planned-predicate.d.ts.map +1 -1
  14. package/dist/plan/evaluate-planned-predicate.js +2 -2
  15. package/dist/plan/evaluate-planned-predicate.js.map +1 -1
  16. package/dist/run/hoist-run-command.d.ts +8 -0
  17. package/dist/run/hoist-run-command.d.ts.map +1 -1
  18. package/dist/run/hoist-run-command.js +28 -3
  19. package/dist/run/hoist-run-command.js.map +1 -1
  20. package/dist/run/shell-code-position.d.ts +21 -0
  21. package/dist/run/shell-code-position.d.ts.map +1 -0
  22. package/dist/run/shell-code-position.js +623 -0
  23. package/dist/run/shell-code-position.js.map +1 -0
  24. package/dist/run/shell-quoting.d.ts +5 -1
  25. package/dist/run/shell-quoting.d.ts.map +1 -1
  26. package/dist/run/shell-quoting.js +37 -6
  27. package/dist/run/shell-quoting.js.map +1 -1
  28. package/dist/tsconfig.test.tsbuildinfo +1 -1
  29. package/dist/workflow-context/workflow-context-docs.d.ts +185 -0
  30. package/dist/workflow-context/workflow-context-docs.d.ts.map +1 -0
  31. package/dist/workflow-context/workflow-context-docs.js +168 -0
  32. package/dist/workflow-context/workflow-context-docs.js.map +1 -0
  33. package/dist/workflow-context/workflow-context.d.ts +99 -114
  34. package/dist/workflow-context/workflow-context.d.ts.map +1 -1
  35. package/dist/workflow-context/workflow-context.js +201 -85
  36. package/dist/workflow-context/workflow-context.js.map +1 -1
  37. package/package.json +2 -2
  38. package/dist/template/extract-cel-untrusted-path-accesses.d.ts +0 -5
  39. package/dist/template/extract-cel-untrusted-path-accesses.d.ts.map +0 -1
  40. package/dist/template/extract-cel-untrusted-path-accesses.js +0 -140
  41. package/dist/template/extract-cel-untrusted-path-accesses.js.map +0 -1
package/README.md CHANGED
@@ -18,19 +18,25 @@ CEL checks and run-time evaluation for Shipfox workflow expressions.
18
18
  - **`MAX_RANGE_ELEMENTS`**: The per-evaluation range materialization limit,
19
19
  currently 1,000 values.
20
20
  - **`evaluateWorkflowPredicate`**: Returns `true` only for the boolean `true`.
21
+ - **`classifyShellCodePosition`**: Finds named workflow bindings passed directly
22
+ to shell positions that re-evaluate their arguments.
21
23
  - **`parseWorkflowTemplate`**: Splits strings with `${{ ... }}` spans into
22
24
  ordered literal and expression segments.
23
25
  - **`extractCelContextRoots`**: Returns the sorted top-level CEL identifiers mentioned
24
- by an expression for downstream context and trust checks.
26
+ by an expression for downstream context and agent-selection checks.
25
27
  - **Typed errors**: Reports bad text and run failures with stable error classes.
26
28
  - **`workflowContextDefinitions`**: Names the workflow contexts (`run`,
27
29
  `trigger`, `event`, `inputs`, `job`, `executions`, `execution`, `jobs`, `step`) and
28
- gives each a shape, trust tier, availability site, sensitivity, and host.
30
+ gives each a shape, availability site, sensitivity, and host.
29
31
  Known-shape contexts ship a typed environment; open ones use `syntax`.
30
- - **`workflowInterpolationFieldPolicies`**: Says which trust tier each
31
- interpolatable field accepts, and whether its value needs sanitizing before
32
- display. Use `workflowInterpolationFieldAcceptsContext` and
33
- `workflowInterpolationFieldAcceptsTrustTier` to run those checks.
32
+ - **`workflowInterpolationFieldPolicies`**: Defines the host, fill-site, and
33
+ failure constraints for each interpolatable field. Use
34
+ `workflowInterpolationFieldAcceptsHost` for host checks.
35
+ - **`workflowPredicateContextRoots`**: Defines the exact context roots each
36
+ predicate field receives. Read it with `getWorkflowPredicateContextRoots`,
37
+ narrow runtime context with `projectWorkflowPredicateContext`, and read
38
+ predicate-specific property shapes with
39
+ `getWorkflowPredicateFieldTypeEnvironment`.
34
40
 
35
41
  Use this package where workflow code accepts or runs expression text. It keeps
36
42
  the CEL parser behind a Shipfox API. Other packages do not need to depend on the
@@ -41,7 +47,7 @@ is wrong, stop there and show the error near that field. If the text is good,
41
47
  save the small value this package returns. Later, pass that value and plain data
42
48
  back to this package to get the result for one run.
43
49
 
44
- ## Installation / Setup
50
+ ## Installation and setup
45
51
 
46
52
  ```sh
47
53
  pnpm add @shipfox/expression
@@ -70,12 +76,15 @@ const passed = evaluateWorkflowPredicate(expression, {
70
76
  });
71
77
  ```
72
78
 
73
- ## Behavior Notes
79
+ ## Behavior notes
74
80
 
75
81
  - Use `syntax` when fields are not known yet.
76
82
  - Use `typed` when the caller knows the names and field types in scope.
77
- - Treat the `event`, `inputs`, and open `jobs` contexts as untrusted.
78
- Interpolation field policies decide what untrusted data may reach each field.
83
+ - Predicate evaluation narrows the supplied context to the roots
84
+ `workflowPredicateContextRoots` declares for that field, so a reference
85
+ outside the policy fails closed rather than reading an incidental value.
86
+ - Context values can include external data. Interpolatable fields rely on their
87
+ structural sink guarantees, while host and availability checks remain enforced.
79
88
  - Evaluation is deterministic and has no side effects.
80
89
  - Workflow evaluation does not include config-templating functions. Use a
81
90
  caller-owned environment when a custom function is intentionally needed.
@@ -103,7 +112,7 @@ const passed = evaluateWorkflowPredicate(expression, {
103
112
  - Template closing scans are string-aware, line-comment-aware, and brace-aware,
104
113
  so `}}` inside CEL strings, `//` comments, or map literals does not close the
105
114
  expression span.
106
- - Context root extraction fails closed for trust decisions. It skips only identifiers
115
+ - Context root extraction fails closed for context checks. It skips only identifiers
107
116
  that are provably not context roots and may over-include comprehension variables or
108
117
  struct keys; downstream code maps context roots to the known workflow contexts.
109
118
  - Run command interpolation hoists expression values into generated environment
@@ -111,7 +120,11 @@ const passed = evaluateWorkflowPredicate(expression, {
111
120
  interpolated values from being parsed as shell syntax, but it does not make
112
121
  commands and shell positions that deliberately re-evaluate their arguments
113
122
  safe, such as `eval`, `sh -c "$value"`, `let`, `declare -i`, arithmetic
114
- expressions, or array subscripts like `array[$value]`.
123
+ expressions, or array subscripts like `array[$value]`. Use
124
+ `classifyShellCodePosition` with the generated binding names and workflow env
125
+ names to detect these direct code-position references. The analysis is pure,
126
+ intentionally shallow, and may miss indirect shell data flow; it is designed
127
+ to avoid false-positive warnings.
115
128
  Trigger filters can use `syntax` while integration event payloads are still open.
116
129
  Gate expressions can use `typed` because their local fields are known.
117
130
 
@@ -1 +1 @@
1
- {"version":3,"file":"create-workflow-expression.d.ts","sourceRoot":"","sources":["../../src/expression/create-workflow-expression.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,8BAA8B,EAI9B,kBAAkB,EACnB,MAAM,0BAA0B,CAAC;AAelC,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,8BAA8B,GACrC,kBAAkB,CAuDpB;AAED,wBAAgB,kCAAkC,CAAC,MAAM,EAAE;IACzD,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,kBAAkB,CAAC,OAAO,CAAC,CAAC;CACpC,GAAG,kBAAkB,CAOrB"}
1
+ {"version":3,"file":"create-workflow-expression.d.ts","sourceRoot":"","sources":["../../src/expression/create-workflow-expression.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,8BAA8B,EAI9B,kBAAkB,EACnB,MAAM,0BAA0B,CAAC;AAelC,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,8BAA8B,GACrC,kBAAkB,CAuDpB;AAoBD,wBAAgB,kCAAkC,CAAC,MAAM,EAAE;IACzD,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,kBAAkB,CAAC,OAAO,CAAC,CAAC;CACpC,GAAG,kBAAkB,CAOrB"}
@@ -26,9 +26,7 @@ export function createWorkflowExpression(params) {
26
26
  });
27
27
  }
28
28
  if (params.check.mode === 'typed') {
29
- const environment = new Environment({
30
- unlistedVariablesAreDyn: false
31
- });
29
+ const environment = createTypeCheckingEnvironment();
32
30
  for (const [name, type] of Object.entries(params.check.typeEnvironment ?? {})){
33
31
  const celType = toCelType(type, environment, name);
34
32
  if (typeof celType === 'string') {
@@ -64,6 +62,22 @@ export function createWorkflowExpression(params) {
64
62
  }
65
63
  };
66
64
  }
65
+ function createTypeCheckingEnvironment() {
66
+ const environment = new Environment({
67
+ unlistedVariablesAreDyn: false
68
+ });
69
+ // CEL evaluates numeric equality across types, but its static checker normally
70
+ // rejects the same expression. Match validation to the runtime contract.
71
+ environment.registerOperator('double == int', (left, right)=>{
72
+ return Number.isInteger(left) && BigInt(left) === right;
73
+ });
74
+ // Typed context fields may be absent at runtime while still exposing their
75
+ // known shape when present. CEL's built-in equality overloads do not allow a
76
+ // declared object type to compare with null, so keep null checks aligned with
77
+ // the runtime context contract.
78
+ environment.registerOperator('dyn != null', (left, right)=>left !== right);
79
+ return environment;
80
+ }
67
81
  export function unsafeWorkflowExpressionFromSource(params) {
68
82
  // Use only when rehydrating a source that was already validated before storage.
69
83
  return {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/expression/create-workflow-expression.ts"],"sourcesContent":["import {Environment, parse as parseCel} from '@marcbachmann/cel-js';\nimport {InvalidWorkflowExpressionError} from './errors.js';\nimport type {\n CreateWorkflowExpressionParams,\n ExpressionScalarType,\n ExpressionType,\n ValidCelExpression,\n WorkflowExpression,\n} from './workflow-expression.js';\n\nconst scalarTypeToCelType = {\n string: 'string',\n int: 'int',\n double: 'double',\n bool: 'bool',\n null: 'null',\n timestamp: 'google.protobuf.Timestamp',\n} satisfies Record<ExpressionScalarType, string>;\n\ntype CelSchema = {\n [field: string]: string | CelSchema;\n};\n\nexport function createWorkflowExpression(\n params: CreateWorkflowExpressionParams,\n): WorkflowExpression {\n const source = params.source.trim();\n let resultType: ExpressionType | undefined;\n if (source.length === 0) {\n throw new InvalidWorkflowExpressionError({\n source: params.source,\n reason: 'Expression source must not be empty.',\n });\n }\n\n try {\n parseCel(source);\n } catch (error) {\n throw new InvalidWorkflowExpressionError({\n source,\n reason: error instanceof Error ? error.message : 'Expression source could not be parsed.',\n });\n }\n\n if (params.check.mode === 'typed') {\n const environment = new Environment({unlistedVariablesAreDyn: false});\n for (const [name, type] of Object.entries(params.check.typeEnvironment ?? {})) {\n const celType = toCelType(type, environment, name);\n if (typeof celType === 'string') {\n environment.registerVariable(name, celType);\n } else {\n environment.registerVariable({name, schema: celType.schema});\n }\n }\n\n const typeCheckResult = environment.check(source);\n if (!typeCheckResult.valid) {\n throw new InvalidWorkflowExpressionError({\n source,\n reason: typeCheckResult.error?.message ?? 'Expression source did not type-check.',\n });\n }\n if (\n params.check.expectedResultType !== undefined &&\n typeCheckResult.type !== scalarTypeToCelType[params.check.expectedResultType]\n ) {\n throw new InvalidWorkflowExpressionError({\n source,\n reason: `Expression source must return ${scalarTypeToCelType[params.check.expectedResultType]}; got ${typeCheckResult.type ?? 'unknown'}.`,\n });\n }\n resultType = fromCelType(typeCheckResult.type);\n }\n\n return {\n language: 'cel',\n source: source as ValidCelExpression,\n check: params.check.mode,\n ...(resultType === undefined ? {} : {resultType}),\n };\n}\n\nexport function unsafeWorkflowExpressionFromSource(params: {\n source: string;\n check: WorkflowExpression['check'];\n}): WorkflowExpression {\n // Use only when rehydrating a source that was already validated before storage.\n return {\n language: 'cel',\n source: params.source as ValidCelExpression,\n check: params.check,\n };\n}\n\nfunction toCelType(\n type: ExpressionType,\n environment: Environment,\n variableName: string,\n): string | {schema: CelSchema} {\n if (typeof type === 'string') return scalarTypeToCelType[type];\n if (type.kind === 'list') {\n return `list<${toCelListElementType(type.element, environment, variableName)}>`;\n }\n if (type.kind === 'map') return 'map';\n\n return {\n schema: Object.fromEntries(\n Object.entries(type.fields).map(([name, field]) => [name, toCelSchemaType(field)]),\n ),\n };\n}\n\nfunction toCelSchemaType(type: ExpressionType): string | CelSchema {\n if (typeof type === 'string') return scalarTypeToCelType[type];\n if (type.kind === 'list') return `list<${toCelSchemaListElementType(type.element)}>`;\n if (type.kind === 'map') return 'map';\n return Object.fromEntries(\n Object.entries(type.fields).map(([name, field]) => [name, toCelSchemaType(field)]),\n );\n}\n\nfunction toCelSchemaListElementType(type: ExpressionType): string {\n if (typeof type === 'string') return scalarTypeToCelType[type];\n if (type.kind === 'map') return 'map';\n if (type.kind === 'object') return 'dyn';\n return `list<${toCelSchemaListElementType(type.element)}>`;\n}\n\nfunction toCelListElementType(\n type: ExpressionType,\n environment: Environment,\n variableName: string,\n): string {\n if (typeof type === 'string') return scalarTypeToCelType[type];\n if (type.kind === 'map') return 'map';\n if (type.kind === 'object') {\n const typeName = `$${variableName}.item`;\n environment.registerType({\n name: typeName,\n schema: Object.fromEntries(\n Object.entries(type.fields).map(([name, field]) => [name, toCelSchemaType(field)]),\n ),\n });\n return typeName;\n }\n return 'dyn';\n}\n\nfunction fromCelType(type: string | undefined): ExpressionType | undefined {\n if (type === undefined) return undefined;\n\n switch (type) {\n case 'string':\n return 'string';\n case 'int':\n return 'int';\n case 'double':\n return 'double';\n case 'bool':\n return 'bool';\n case 'null':\n return 'null';\n case 'google.protobuf.Timestamp':\n return 'timestamp';\n case 'map':\n return {kind: 'map'};\n case 'dyn':\n return 'string';\n default:\n // cel-js currently exposes custom/list element result types as opaque strings.\n // Keep the outer list shape when present, but erase element detail rather than\n // pretending we can round-trip the original schema.\n if (type.startsWith('list<')) return {kind: 'list', element: {kind: 'map'}};\n return {kind: 'map'};\n }\n}\n"],"names":["Environment","parse","parseCel","InvalidWorkflowExpressionError","scalarTypeToCelType","string","int","double","bool","null","timestamp","createWorkflowExpression","params","source","trim","resultType","length","reason","error","Error","message","check","mode","environment","unlistedVariablesAreDyn","name","type","Object","entries","typeEnvironment","celType","toCelType","registerVariable","schema","typeCheckResult","valid","expectedResultType","undefined","fromCelType","language","unsafeWorkflowExpressionFromSource","variableName","kind","toCelListElementType","element","fromEntries","fields","map","field","toCelSchemaType","toCelSchemaListElementType","typeName","registerType","startsWith"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/expression/create-workflow-expression.ts"],"sourcesContent":["import {Environment, parse as parseCel} from '@marcbachmann/cel-js';\nimport {InvalidWorkflowExpressionError} from './errors.js';\nimport type {\n CreateWorkflowExpressionParams,\n ExpressionScalarType,\n ExpressionType,\n ValidCelExpression,\n WorkflowExpression,\n} from './workflow-expression.js';\n\nconst scalarTypeToCelType = {\n string: 'string',\n int: 'int',\n double: 'double',\n bool: 'bool',\n null: 'null',\n timestamp: 'google.protobuf.Timestamp',\n} satisfies Record<ExpressionScalarType, string>;\n\ntype CelSchema = {\n [field: string]: string | CelSchema;\n};\n\nexport function createWorkflowExpression(\n params: CreateWorkflowExpressionParams,\n): WorkflowExpression {\n const source = params.source.trim();\n let resultType: ExpressionType | undefined;\n if (source.length === 0) {\n throw new InvalidWorkflowExpressionError({\n source: params.source,\n reason: 'Expression source must not be empty.',\n });\n }\n\n try {\n parseCel(source);\n } catch (error) {\n throw new InvalidWorkflowExpressionError({\n source,\n reason: error instanceof Error ? error.message : 'Expression source could not be parsed.',\n });\n }\n\n if (params.check.mode === 'typed') {\n const environment = createTypeCheckingEnvironment();\n for (const [name, type] of Object.entries(params.check.typeEnvironment ?? {})) {\n const celType = toCelType(type, environment, name);\n if (typeof celType === 'string') {\n environment.registerVariable(name, celType);\n } else {\n environment.registerVariable({name, schema: celType.schema});\n }\n }\n\n const typeCheckResult = environment.check(source);\n if (!typeCheckResult.valid) {\n throw new InvalidWorkflowExpressionError({\n source,\n reason: typeCheckResult.error?.message ?? 'Expression source did not type-check.',\n });\n }\n if (\n params.check.expectedResultType !== undefined &&\n typeCheckResult.type !== scalarTypeToCelType[params.check.expectedResultType]\n ) {\n throw new InvalidWorkflowExpressionError({\n source,\n reason: `Expression source must return ${scalarTypeToCelType[params.check.expectedResultType]}; got ${typeCheckResult.type ?? 'unknown'}.`,\n });\n }\n resultType = fromCelType(typeCheckResult.type);\n }\n\n return {\n language: 'cel',\n source: source as ValidCelExpression,\n check: params.check.mode,\n ...(resultType === undefined ? {} : {resultType}),\n };\n}\n\nfunction createTypeCheckingEnvironment(): Environment {\n const environment = new Environment({unlistedVariablesAreDyn: false});\n\n // CEL evaluates numeric equality across types, but its static checker normally\n // rejects the same expression. Match validation to the runtime contract.\n environment.registerOperator('double == int', (left: number, right: bigint) => {\n return Number.isInteger(left) && BigInt(left) === right;\n });\n\n // Typed context fields may be absent at runtime while still exposing their\n // known shape when present. CEL's built-in equality overloads do not allow a\n // declared object type to compare with null, so keep null checks aligned with\n // the runtime context contract.\n environment.registerOperator('dyn != null', (left: unknown, right: null) => left !== right);\n\n return environment;\n}\n\nexport function unsafeWorkflowExpressionFromSource(params: {\n source: string;\n check: WorkflowExpression['check'];\n}): WorkflowExpression {\n // Use only when rehydrating a source that was already validated before storage.\n return {\n language: 'cel',\n source: params.source as ValidCelExpression,\n check: params.check,\n };\n}\n\nfunction toCelType(\n type: ExpressionType,\n environment: Environment,\n variableName: string,\n): string | {schema: CelSchema} {\n if (typeof type === 'string') return scalarTypeToCelType[type];\n if (type.kind === 'list') {\n return `list<${toCelListElementType(type.element, environment, variableName)}>`;\n }\n if (type.kind === 'map') return 'map';\n\n return {\n schema: Object.fromEntries(\n Object.entries(type.fields).map(([name, field]) => [name, toCelSchemaType(field)]),\n ),\n };\n}\n\nfunction toCelSchemaType(type: ExpressionType): string | CelSchema {\n if (typeof type === 'string') return scalarTypeToCelType[type];\n if (type.kind === 'list') return `list<${toCelSchemaListElementType(type.element)}>`;\n if (type.kind === 'map') return 'map';\n return Object.fromEntries(\n Object.entries(type.fields).map(([name, field]) => [name, toCelSchemaType(field)]),\n );\n}\n\nfunction toCelSchemaListElementType(type: ExpressionType): string {\n if (typeof type === 'string') return scalarTypeToCelType[type];\n if (type.kind === 'map') return 'map';\n if (type.kind === 'object') return 'dyn';\n return `list<${toCelSchemaListElementType(type.element)}>`;\n}\n\nfunction toCelListElementType(\n type: ExpressionType,\n environment: Environment,\n variableName: string,\n): string {\n if (typeof type === 'string') return scalarTypeToCelType[type];\n if (type.kind === 'map') return 'map';\n if (type.kind === 'object') {\n const typeName = `$${variableName}.item`;\n environment.registerType({\n name: typeName,\n schema: Object.fromEntries(\n Object.entries(type.fields).map(([name, field]) => [name, toCelSchemaType(field)]),\n ),\n });\n return typeName;\n }\n return 'dyn';\n}\n\nfunction fromCelType(type: string | undefined): ExpressionType | undefined {\n if (type === undefined) return undefined;\n\n switch (type) {\n case 'string':\n return 'string';\n case 'int':\n return 'int';\n case 'double':\n return 'double';\n case 'bool':\n return 'bool';\n case 'null':\n return 'null';\n case 'google.protobuf.Timestamp':\n return 'timestamp';\n case 'map':\n return {kind: 'map'};\n case 'dyn':\n return 'string';\n default:\n // cel-js currently exposes custom/list element result types as opaque strings.\n // Keep the outer list shape when present, but erase element detail rather than\n // pretending we can round-trip the original schema.\n if (type.startsWith('list<')) return {kind: 'list', element: {kind: 'map'}};\n return {kind: 'map'};\n }\n}\n"],"names":["Environment","parse","parseCel","InvalidWorkflowExpressionError","scalarTypeToCelType","string","int","double","bool","null","timestamp","createWorkflowExpression","params","source","trim","resultType","length","reason","error","Error","message","check","mode","environment","createTypeCheckingEnvironment","name","type","Object","entries","typeEnvironment","celType","toCelType","registerVariable","schema","typeCheckResult","valid","expectedResultType","undefined","fromCelType","language","unlistedVariablesAreDyn","registerOperator","left","right","Number","isInteger","BigInt","unsafeWorkflowExpressionFromSource","variableName","kind","toCelListElementType","element","fromEntries","fields","map","field","toCelSchemaType","toCelSchemaListElementType","typeName","registerType","startsWith"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -18,11 +18,12 @@ export type { ResolvedField, ResolvedFieldDeferredSegment, ResolvedFieldLiteralS
18
18
  export { type RoutedExpression, routeExpression } from './plan/route-expression.js';
19
19
  export { type ServerEvaluabilityResult, type ServerEvaluabilityViolation, validateServerEvaluable, } from './plan/validate-server-evaluable.js';
20
20
  export { WorkflowTemplateResolutionError, workflowTemplateResolutionErrorCode, } from './resolver/errors.js';
21
- export { type HoistedPlannedRunCommand, hoistPlannedRunCommand, type PlannedRunCommandBinding, type RunCommandHoistOptions, UnsafeRunInterpolationError, unsafeRunInterpolationErrorCode, } from './run/hoist-run-command.js';
21
+ export { type HoistedPlannedRunCommand, hoistPlannedRunCommand, type PlannedRunCommandBinding, type RunCommandHoistOptions, type UnsafeRunInterpolation, UnsafeRunInterpolationError, unsafeRunInterpolationErrorCode, } from './run/hoist-run-command.js';
22
+ export { classifyShellCodePosition, type ShellCodePositionAnalysis, type ShellCodePositionMatch, type ShellReevaluatingConstruct, } from './run/shell-code-position.js';
22
23
  export { InvalidWorkflowTemplateError, invalidWorkflowTemplateErrorCode, } from './template/errors.js';
23
24
  export { extractCelContextRoots } from './template/extract-cel-context-roots.js';
24
- export { extractCelUntrustedPathAccesses } from './template/extract-cel-untrusted-path-accesses.js';
25
25
  export { parseWorkflowTemplate } from './template/parse-workflow-template.js';
26
26
  export type { WorkflowTemplateExprSegment, WorkflowTemplateLiteralSegment, WorkflowTemplateSegment, } from './template/template-segment.js';
27
- export { type AvailabilitySite, availabilitySites, buildTypedRootsEnvironment, type FillTarget, getWorkflowContextAvailability, getWorkflowContextDefinition, getWorkflowContextHost, getWorkflowContextSensitivity, getWorkflowContextTypeEnvironment, getWorkflowContextUntrustedPaths, getWorkflowInterpolationFieldFailurePolicy, getWorkflowPredicateFieldMinimumFillTarget, type OpenWorkflowContextDefinition, type ReservedRootDefinition, type RunnerWorkflowContextDefinition, resolveContextRootAvailability, resolveContextRootHost, rootsAvailableAt, runnerFillTarget, type TypedWorkflowContextDefinition, unavailableRootsAt, type WorkflowContextAvailabilityReferenceEntry, type WorkflowContextDefinition, type WorkflowContextHost, type WorkflowContextName, type WorkflowContextReservedRoot, type WorkflowContextSensitivity, type WorkflowContextShape, type WorkflowContextTrustTier, type WorkflowFieldFailurePolicy, type WorkflowInterpolationFailurePolicy, type WorkflowInterpolationField, type WorkflowInterpolationFieldPolicy, type WorkflowJobTypeOverlay, type WorkflowPredicateField, type WorkflowStepTypeOverlay, workflowContextAvailabilityReference, workflowContextDefinitions, workflowContextHosts, workflowContextNames, workflowContextReservedRoots, workflowContextRootRequiresLiteralKey, workflowContextSensitivities, workflowContextTrustTiers, workflowFieldFailurePolicies, workflowInterpolationFieldAcceptsContext, workflowInterpolationFieldAcceptsHost, workflowInterpolationFieldAcceptsTrustTier, workflowInterpolationFieldPolicies, workflowInterpolationFields, workflowPredicateFieldFailurePolicy, workflowPredicateFields, } from './workflow-context/workflow-context.js';
27
+ export { type AvailabilitySite, availabilitySites, buildTypedRootsEnvironment, contextRootsForField, type FillTarget, getWorkflowContextAvailability, getWorkflowContextDefinition, getWorkflowContextHost, getWorkflowContextSensitivity, getWorkflowContextTypeEnvironment, getWorkflowInterpolationFieldFailurePolicy, getWorkflowInterpolationFieldSelfReference, getWorkflowPredicateContextRoots, getWorkflowPredicateFieldMinimumFillTarget, getWorkflowPredicateFieldTypeEnvironment, isWorkflowPredicateField, type OpenWorkflowContextDefinition, projectWorkflowPredicateContext, type ReservedRootDefinition, type RunnerWorkflowContextDefinition, resolveContextRootAvailability, resolveContextRootHost, rootsAvailableAt, runnerFillTarget, type TypedWorkflowContextDefinition, unavailableRootsAt, type WorkflowContextAvailabilityReferenceEntry, type WorkflowContextDefinition, type WorkflowContextHost, type WorkflowContextName, type WorkflowContextReservedRoot, type WorkflowContextSensitivity, type WorkflowContextShape, type WorkflowFieldFailurePolicy, type WorkflowInterpolationFailurePolicy, type WorkflowInterpolationField, type WorkflowInterpolationFieldPolicy, type WorkflowJobTypeOverlay, type WorkflowPredicateContextRoot, type WorkflowPredicateField, type WorkflowStepTypeOverlay, workflowContextAvailabilityReference, workflowContextDefinitions, workflowContextHosts, workflowContextNames, workflowContextReservedRoots, workflowContextRootRequiresLiteralKey, workflowContextSensitivities, workflowFieldFailurePolicies, workflowInterpolationFieldAcceptsHost, workflowInterpolationFieldPolicies, workflowInterpolationFields, workflowPredicateContextRoots, workflowPredicateFieldFailurePolicy, workflowPredicateFields, } from './workflow-context/workflow-context.js';
28
+ export { type WorkflowContextDoc, workflowContextDocs, } from './workflow-context/workflow-context-docs.js';
28
29
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -17,10 +17,11 @@ export { routeExpression } from './plan/route-expression.js';
17
17
  export { validateServerEvaluable } from './plan/validate-server-evaluable.js';
18
18
  export { WorkflowTemplateResolutionError, workflowTemplateResolutionErrorCode } from './resolver/errors.js';
19
19
  export { hoistPlannedRunCommand, UnsafeRunInterpolationError, unsafeRunInterpolationErrorCode } from './run/hoist-run-command.js';
20
+ export { classifyShellCodePosition } from './run/shell-code-position.js';
20
21
  export { InvalidWorkflowTemplateError, invalidWorkflowTemplateErrorCode } from './template/errors.js';
21
22
  export { extractCelContextRoots } from './template/extract-cel-context-roots.js';
22
- export { extractCelUntrustedPathAccesses } from './template/extract-cel-untrusted-path-accesses.js';
23
23
  export { parseWorkflowTemplate } from './template/parse-workflow-template.js';
24
- export { availabilitySites, buildTypedRootsEnvironment, getWorkflowContextAvailability, getWorkflowContextDefinition, getWorkflowContextHost, getWorkflowContextSensitivity, getWorkflowContextTypeEnvironment, getWorkflowContextUntrustedPaths, getWorkflowInterpolationFieldFailurePolicy, getWorkflowPredicateFieldMinimumFillTarget, resolveContextRootAvailability, resolveContextRootHost, rootsAvailableAt, runnerFillTarget, unavailableRootsAt, workflowContextAvailabilityReference, workflowContextDefinitions, workflowContextHosts, workflowContextNames, workflowContextReservedRoots, workflowContextRootRequiresLiteralKey, workflowContextSensitivities, workflowContextTrustTiers, workflowFieldFailurePolicies, workflowInterpolationFieldAcceptsContext, workflowInterpolationFieldAcceptsHost, workflowInterpolationFieldAcceptsTrustTier, workflowInterpolationFieldPolicies, workflowInterpolationFields, workflowPredicateFieldFailurePolicy, workflowPredicateFields } from './workflow-context/workflow-context.js';
24
+ export { availabilitySites, buildTypedRootsEnvironment, contextRootsForField, getWorkflowContextAvailability, getWorkflowContextDefinition, getWorkflowContextHost, getWorkflowContextSensitivity, getWorkflowContextTypeEnvironment, getWorkflowInterpolationFieldFailurePolicy, getWorkflowInterpolationFieldSelfReference, getWorkflowPredicateContextRoots, getWorkflowPredicateFieldMinimumFillTarget, getWorkflowPredicateFieldTypeEnvironment, isWorkflowPredicateField, projectWorkflowPredicateContext, resolveContextRootAvailability, resolveContextRootHost, rootsAvailableAt, runnerFillTarget, unavailableRootsAt, workflowContextAvailabilityReference, workflowContextDefinitions, workflowContextHosts, workflowContextNames, workflowContextReservedRoots, workflowContextRootRequiresLiteralKey, workflowContextSensitivities, workflowFieldFailurePolicies, workflowInterpolationFieldAcceptsHost, workflowInterpolationFieldPolicies, workflowInterpolationFields, workflowPredicateContextRoots, workflowPredicateFieldFailurePolicy, workflowPredicateFields } from './workflow-context/workflow-context.js';
25
+ export { workflowContextDocs } from './workflow-context/workflow-context-docs.js';
25
26
 
26
27
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export {\n WorkflowExpressionEvaluationError,\n type WorkflowExpressionEvaluationFailureReason,\n workflowExpressionEvaluationErrorCode,\n} from './evaluator/errors.js';\nexport {\n evaluateWorkflowExpression,\n evaluateWorkflowExpressionWithEnvironment,\n evaluateWorkflowPredicate,\n evaluateWorkflowPredicateFailClosed,\n type FailClosedPredicateOutcome,\n type WorkflowExpressionEnvironment,\n type WorkflowExpressionEvaluationContext,\n type WorkflowExpressionEvaluationValue,\n} from './evaluator/evaluate-workflow-expression.js';\nexport {createRangeEnvironment, MAX_RANGE_ELEMENTS} from './evaluator/range.js';\nexport {\n createWorkflowExpression,\n unsafeWorkflowExpressionFromSource,\n} from './expression/create-workflow-expression.js';\nexport {\n InvalidWorkflowExpressionError,\n invalidWorkflowExpressionErrorCode,\n} from './expression/errors.js';\nexport type {\n CreateWorkflowExpressionParams,\n ExpressionScalarType,\n ExpressionType,\n ExpressionTypeEnvironment,\n ValidCelExpression,\n WorkflowExpression,\n WorkflowExpressionCheck,\n WorkflowExpressionCheckOptions,\n} from './expression/workflow-expression.js';\nexport {\n type CoerceStepOutputsResult,\n coerceStepOutputs,\n type JsonSchemaValidationResult,\n jsonSchemaToExpressionType,\n type OutputDeclarations,\n type OutputType,\n type OutputTypeDeclaration,\n outputDeclarationsToExpressionFields,\n outputDeclarationToExpressionType,\n outputTypes,\n type StepOutputCoercionError,\n type StepOutputCoercionErrorReason,\n validateJsonSchema,\n} from './outputs/index.js';\nexport {isBareContextReference} from './plan/bare-reference.js';\nexport {\n analyzeContextKeyAccess,\n analyzeContextRootKeyAccess,\n type ContextKeyAccessAnalysis,\n type ContextKeyAccessReference,\n type ContextKeyAccessViolation,\n type ContextRootKeyAccessAnalysis,\n type ContextRootKeyAccessReference,\n} from './plan/context-key-access.js';\nexport {evaluatePlannedPredicateAtSite} from './plan/evaluate-planned-predicate.js';\nexport {\n capTraceEntries,\n capTraceValue,\n EVALUATION_TRACE_MAX_ENTRIES,\n EVALUATION_TRACE_VALUE_CAP_BYTES,\n type EvaluationTraceEntry,\n type EvaluationTraceLimitEntry,\n type EvaluationTraceRowEntry,\n evaluationTraceEntry,\n predicateTraceEntry,\n} from './plan/evaluation-trace.js';\nexport {extractExactContextRoots} from './plan/extract-exact-context-roots.js';\nexport {\n type FrozenResolvedField,\n freezeResolvedFieldAtSite,\n resolveFieldAtSite,\n type SiteResolvedField,\n type WorkflowTemplateDiagnostic,\n type WorkflowTemplateFailurePolicy,\n} from './plan/freeze.js';\nexport {\n type FrozenPlannedRunCommand,\n freezePlannedRunCommandAtSite,\n} from './plan/freeze-run-command.js';\nexport {\n type FieldPlan,\n type FieldPlanResult,\n type PlanViolation,\n planInterpolationField,\n} from './plan/plan-field.js';\nexport {predicateSourceIsBooleanShaped} from './plan/predicate-shape.js';\nexport type {\n ResolvedField,\n ResolvedFieldDeferredSegment,\n ResolvedFieldLiteralSegment,\n ResolvedFieldSegment,\n} from './plan/resolved-field.js';\nexport {type RoutedExpression, routeExpression} from './plan/route-expression.js';\nexport {\n type ServerEvaluabilityResult,\n type ServerEvaluabilityViolation,\n validateServerEvaluable,\n} from './plan/validate-server-evaluable.js';\nexport {\n WorkflowTemplateResolutionError,\n workflowTemplateResolutionErrorCode,\n} from './resolver/errors.js';\nexport {\n type HoistedPlannedRunCommand,\n hoistPlannedRunCommand,\n type PlannedRunCommandBinding,\n type RunCommandHoistOptions,\n UnsafeRunInterpolationError,\n unsafeRunInterpolationErrorCode,\n} from './run/hoist-run-command.js';\nexport {\n InvalidWorkflowTemplateError,\n invalidWorkflowTemplateErrorCode,\n} from './template/errors.js';\nexport {extractCelContextRoots} from './template/extract-cel-context-roots.js';\nexport {extractCelUntrustedPathAccesses} from './template/extract-cel-untrusted-path-accesses.js';\nexport {parseWorkflowTemplate} from './template/parse-workflow-template.js';\nexport type {\n WorkflowTemplateExprSegment,\n WorkflowTemplateLiteralSegment,\n WorkflowTemplateSegment,\n} from './template/template-segment.js';\nexport {\n type AvailabilitySite,\n availabilitySites,\n buildTypedRootsEnvironment,\n type FillTarget,\n getWorkflowContextAvailability,\n getWorkflowContextDefinition,\n getWorkflowContextHost,\n getWorkflowContextSensitivity,\n getWorkflowContextTypeEnvironment,\n getWorkflowContextUntrustedPaths,\n getWorkflowInterpolationFieldFailurePolicy,\n getWorkflowPredicateFieldMinimumFillTarget,\n type OpenWorkflowContextDefinition,\n type ReservedRootDefinition,\n type RunnerWorkflowContextDefinition,\n resolveContextRootAvailability,\n resolveContextRootHost,\n rootsAvailableAt,\n runnerFillTarget,\n type TypedWorkflowContextDefinition,\n unavailableRootsAt,\n type WorkflowContextAvailabilityReferenceEntry,\n type WorkflowContextDefinition,\n type WorkflowContextHost,\n type WorkflowContextName,\n type WorkflowContextReservedRoot,\n type WorkflowContextSensitivity,\n type WorkflowContextShape,\n type WorkflowContextTrustTier,\n type WorkflowFieldFailurePolicy,\n type WorkflowInterpolationFailurePolicy,\n type WorkflowInterpolationField,\n type WorkflowInterpolationFieldPolicy,\n type WorkflowJobTypeOverlay,\n type WorkflowPredicateField,\n type WorkflowStepTypeOverlay,\n workflowContextAvailabilityReference,\n workflowContextDefinitions,\n workflowContextHosts,\n workflowContextNames,\n workflowContextReservedRoots,\n workflowContextRootRequiresLiteralKey,\n workflowContextSensitivities,\n workflowContextTrustTiers,\n workflowFieldFailurePolicies,\n workflowInterpolationFieldAcceptsContext,\n workflowInterpolationFieldAcceptsHost,\n workflowInterpolationFieldAcceptsTrustTier,\n workflowInterpolationFieldPolicies,\n workflowInterpolationFields,\n workflowPredicateFieldFailurePolicy,\n workflowPredicateFields,\n} from './workflow-context/workflow-context.js';\n"],"names":["WorkflowExpressionEvaluationError","workflowExpressionEvaluationErrorCode","evaluateWorkflowExpression","evaluateWorkflowExpressionWithEnvironment","evaluateWorkflowPredicate","evaluateWorkflowPredicateFailClosed","createRangeEnvironment","MAX_RANGE_ELEMENTS","createWorkflowExpression","unsafeWorkflowExpressionFromSource","InvalidWorkflowExpressionError","invalidWorkflowExpressionErrorCode","coerceStepOutputs","jsonSchemaToExpressionType","outputDeclarationsToExpressionFields","outputDeclarationToExpressionType","outputTypes","validateJsonSchema","isBareContextReference","analyzeContextKeyAccess","analyzeContextRootKeyAccess","evaluatePlannedPredicateAtSite","capTraceEntries","capTraceValue","EVALUATION_TRACE_MAX_ENTRIES","EVALUATION_TRACE_VALUE_CAP_BYTES","evaluationTraceEntry","predicateTraceEntry","extractExactContextRoots","freezeResolvedFieldAtSite","resolveFieldAtSite","freezePlannedRunCommandAtSite","planInterpolationField","predicateSourceIsBooleanShaped","routeExpression","validateServerEvaluable","WorkflowTemplateResolutionError","workflowTemplateResolutionErrorCode","hoistPlannedRunCommand","UnsafeRunInterpolationError","unsafeRunInterpolationErrorCode","InvalidWorkflowTemplateError","invalidWorkflowTemplateErrorCode","extractCelContextRoots","extractCelUntrustedPathAccesses","parseWorkflowTemplate","availabilitySites","buildTypedRootsEnvironment","getWorkflowContextAvailability","getWorkflowContextDefinition","getWorkflowContextHost","getWorkflowContextSensitivity","getWorkflowContextTypeEnvironment","getWorkflowContextUntrustedPaths","getWorkflowInterpolationFieldFailurePolicy","getWorkflowPredicateFieldMinimumFillTarget","resolveContextRootAvailability","resolveContextRootHost","rootsAvailableAt","runnerFillTarget","unavailableRootsAt","workflowContextAvailabilityReference","workflowContextDefinitions","workflowContextHosts","workflowContextNames","workflowContextReservedRoots","workflowContextRootRequiresLiteralKey","workflowContextSensitivities","workflowContextTrustTiers","workflowFieldFailurePolicies","workflowInterpolationFieldAcceptsContext","workflowInterpolationFieldAcceptsHost","workflowInterpolationFieldAcceptsTrustTier","workflowInterpolationFieldPolicies","workflowInterpolationFields","workflowPredicateFieldFailurePolicy","workflowPredicateFields"],"mappings":"AAAA,SACEA,iCAAiC,EAEjCC,qCAAqC,QAChC,wBAAwB;AAC/B,SACEC,0BAA0B,EAC1BC,yCAAyC,EACzCC,yBAAyB,EACzBC,mCAAmC,QAK9B,8CAA8C;AACrD,SAAQC,sBAAsB,EAAEC,kBAAkB,QAAO,uBAAuB;AAChF,SACEC,wBAAwB,EACxBC,kCAAkC,QAC7B,6CAA6C;AACpD,SACEC,8BAA8B,EAC9BC,kCAAkC,QAC7B,yBAAyB;AAWhC,SAEEC,iBAAiB,EAEjBC,0BAA0B,EAI1BC,oCAAoC,EACpCC,iCAAiC,EACjCC,WAAW,EAGXC,kBAAkB,QACb,qBAAqB;AAC5B,SAAQC,sBAAsB,QAAO,2BAA2B;AAChE,SACEC,uBAAuB,EACvBC,2BAA2B,QAMtB,+BAA+B;AACtC,SAAQC,8BAA8B,QAAO,uCAAuC;AACpF,SACEC,eAAe,EACfC,aAAa,EACbC,4BAA4B,EAC5BC,gCAAgC,EAIhCC,oBAAoB,EACpBC,mBAAmB,QACd,6BAA6B;AACpC,SAAQC,wBAAwB,QAAO,wCAAwC;AAC/E,SAEEC,yBAAyB,EACzBC,kBAAkB,QAIb,mBAAmB;AAC1B,SAEEC,6BAA6B,QACxB,+BAA+B;AACtC,SAIEC,sBAAsB,QACjB,uBAAuB;AAC9B,SAAQC,8BAA8B,QAAO,4BAA4B;AAOzE,SAA+BC,eAAe,QAAO,6BAA6B;AAClF,SAGEC,uBAAuB,QAClB,sCAAsC;AAC7C,SACEC,+BAA+B,EAC/BC,mCAAmC,QAC9B,uBAAuB;AAC9B,SAEEC,sBAAsB,EAGtBC,2BAA2B,EAC3BC,+BAA+B,QAC1B,6BAA6B;AACpC,SACEC,4BAA4B,EAC5BC,gCAAgC,QAC3B,uBAAuB;AAC9B,SAAQC,sBAAsB,QAAO,0CAA0C;AAC/E,SAAQC,+BAA+B,QAAO,oDAAoD;AAClG,SAAQC,qBAAqB,QAAO,wCAAwC;AAM5E,SAEEC,iBAAiB,EACjBC,0BAA0B,EAE1BC,8BAA8B,EAC9BC,4BAA4B,EAC5BC,sBAAsB,EACtBC,6BAA6B,EAC7BC,iCAAiC,EACjCC,gCAAgC,EAChCC,0CAA0C,EAC1CC,0CAA0C,EAI1CC,8BAA8B,EAC9BC,sBAAsB,EACtBC,gBAAgB,EAChBC,gBAAgB,EAEhBC,kBAAkB,EAgBlBC,oCAAoC,EACpCC,0BAA0B,EAC1BC,oBAAoB,EACpBC,oBAAoB,EACpBC,4BAA4B,EAC5BC,qCAAqC,EACrCC,4BAA4B,EAC5BC,yBAAyB,EACzBC,4BAA4B,EAC5BC,wCAAwC,EACxCC,qCAAqC,EACrCC,0CAA0C,EAC1CC,kCAAkC,EAClCC,2BAA2B,EAC3BC,mCAAmC,EACnCC,uBAAuB,QAClB,yCAAyC"}
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["export {\n WorkflowExpressionEvaluationError,\n type WorkflowExpressionEvaluationFailureReason,\n workflowExpressionEvaluationErrorCode,\n} from './evaluator/errors.js';\nexport {\n evaluateWorkflowExpression,\n evaluateWorkflowExpressionWithEnvironment,\n evaluateWorkflowPredicate,\n evaluateWorkflowPredicateFailClosed,\n type FailClosedPredicateOutcome,\n type WorkflowExpressionEnvironment,\n type WorkflowExpressionEvaluationContext,\n type WorkflowExpressionEvaluationValue,\n} from './evaluator/evaluate-workflow-expression.js';\nexport {createRangeEnvironment, MAX_RANGE_ELEMENTS} from './evaluator/range.js';\nexport {\n createWorkflowExpression,\n unsafeWorkflowExpressionFromSource,\n} from './expression/create-workflow-expression.js';\nexport {\n InvalidWorkflowExpressionError,\n invalidWorkflowExpressionErrorCode,\n} from './expression/errors.js';\nexport type {\n CreateWorkflowExpressionParams,\n ExpressionScalarType,\n ExpressionType,\n ExpressionTypeEnvironment,\n ValidCelExpression,\n WorkflowExpression,\n WorkflowExpressionCheck,\n WorkflowExpressionCheckOptions,\n} from './expression/workflow-expression.js';\nexport {\n type CoerceStepOutputsResult,\n coerceStepOutputs,\n type JsonSchemaValidationResult,\n jsonSchemaToExpressionType,\n type OutputDeclarations,\n type OutputType,\n type OutputTypeDeclaration,\n outputDeclarationsToExpressionFields,\n outputDeclarationToExpressionType,\n outputTypes,\n type StepOutputCoercionError,\n type StepOutputCoercionErrorReason,\n validateJsonSchema,\n} from './outputs/index.js';\nexport {isBareContextReference} from './plan/bare-reference.js';\nexport {\n analyzeContextKeyAccess,\n analyzeContextRootKeyAccess,\n type ContextKeyAccessAnalysis,\n type ContextKeyAccessReference,\n type ContextKeyAccessViolation,\n type ContextRootKeyAccessAnalysis,\n type ContextRootKeyAccessReference,\n} from './plan/context-key-access.js';\nexport {evaluatePlannedPredicateAtSite} from './plan/evaluate-planned-predicate.js';\nexport {\n capTraceEntries,\n capTraceValue,\n EVALUATION_TRACE_MAX_ENTRIES,\n EVALUATION_TRACE_VALUE_CAP_BYTES,\n type EvaluationTraceEntry,\n type EvaluationTraceLimitEntry,\n type EvaluationTraceRowEntry,\n evaluationTraceEntry,\n predicateTraceEntry,\n} from './plan/evaluation-trace.js';\nexport {extractExactContextRoots} from './plan/extract-exact-context-roots.js';\nexport {\n type FrozenResolvedField,\n freezeResolvedFieldAtSite,\n resolveFieldAtSite,\n type SiteResolvedField,\n type WorkflowTemplateDiagnostic,\n type WorkflowTemplateFailurePolicy,\n} from './plan/freeze.js';\nexport {\n type FrozenPlannedRunCommand,\n freezePlannedRunCommandAtSite,\n} from './plan/freeze-run-command.js';\nexport {\n type FieldPlan,\n type FieldPlanResult,\n type PlanViolation,\n planInterpolationField,\n} from './plan/plan-field.js';\nexport {predicateSourceIsBooleanShaped} from './plan/predicate-shape.js';\nexport type {\n ResolvedField,\n ResolvedFieldDeferredSegment,\n ResolvedFieldLiteralSegment,\n ResolvedFieldSegment,\n} from './plan/resolved-field.js';\nexport {type RoutedExpression, routeExpression} from './plan/route-expression.js';\nexport {\n type ServerEvaluabilityResult,\n type ServerEvaluabilityViolation,\n validateServerEvaluable,\n} from './plan/validate-server-evaluable.js';\nexport {\n WorkflowTemplateResolutionError,\n workflowTemplateResolutionErrorCode,\n} from './resolver/errors.js';\nexport {\n type HoistedPlannedRunCommand,\n hoistPlannedRunCommand,\n type PlannedRunCommandBinding,\n type RunCommandHoistOptions,\n type UnsafeRunInterpolation,\n UnsafeRunInterpolationError,\n unsafeRunInterpolationErrorCode,\n} from './run/hoist-run-command.js';\nexport {\n classifyShellCodePosition,\n type ShellCodePositionAnalysis,\n type ShellCodePositionMatch,\n type ShellReevaluatingConstruct,\n} from './run/shell-code-position.js';\nexport {\n InvalidWorkflowTemplateError,\n invalidWorkflowTemplateErrorCode,\n} from './template/errors.js';\nexport {extractCelContextRoots} from './template/extract-cel-context-roots.js';\nexport {parseWorkflowTemplate} from './template/parse-workflow-template.js';\nexport type {\n WorkflowTemplateExprSegment,\n WorkflowTemplateLiteralSegment,\n WorkflowTemplateSegment,\n} from './template/template-segment.js';\nexport {\n type AvailabilitySite,\n availabilitySites,\n buildTypedRootsEnvironment,\n contextRootsForField,\n type FillTarget,\n getWorkflowContextAvailability,\n getWorkflowContextDefinition,\n getWorkflowContextHost,\n getWorkflowContextSensitivity,\n getWorkflowContextTypeEnvironment,\n getWorkflowInterpolationFieldFailurePolicy,\n getWorkflowInterpolationFieldSelfReference,\n getWorkflowPredicateContextRoots,\n getWorkflowPredicateFieldMinimumFillTarget,\n getWorkflowPredicateFieldTypeEnvironment,\n isWorkflowPredicateField,\n type OpenWorkflowContextDefinition,\n projectWorkflowPredicateContext,\n type ReservedRootDefinition,\n type RunnerWorkflowContextDefinition,\n resolveContextRootAvailability,\n resolveContextRootHost,\n rootsAvailableAt,\n runnerFillTarget,\n type TypedWorkflowContextDefinition,\n unavailableRootsAt,\n type WorkflowContextAvailabilityReferenceEntry,\n type WorkflowContextDefinition,\n type WorkflowContextHost,\n type WorkflowContextName,\n type WorkflowContextReservedRoot,\n type WorkflowContextSensitivity,\n type WorkflowContextShape,\n type WorkflowFieldFailurePolicy,\n type WorkflowInterpolationFailurePolicy,\n type WorkflowInterpolationField,\n type WorkflowInterpolationFieldPolicy,\n type WorkflowJobTypeOverlay,\n type WorkflowPredicateContextRoot,\n type WorkflowPredicateField,\n type WorkflowStepTypeOverlay,\n workflowContextAvailabilityReference,\n workflowContextDefinitions,\n workflowContextHosts,\n workflowContextNames,\n workflowContextReservedRoots,\n workflowContextRootRequiresLiteralKey,\n workflowContextSensitivities,\n workflowFieldFailurePolicies,\n workflowInterpolationFieldAcceptsHost,\n workflowInterpolationFieldPolicies,\n workflowInterpolationFields,\n workflowPredicateContextRoots,\n workflowPredicateFieldFailurePolicy,\n workflowPredicateFields,\n} from './workflow-context/workflow-context.js';\nexport {\n type WorkflowContextDoc,\n workflowContextDocs,\n} from './workflow-context/workflow-context-docs.js';\n"],"names":["WorkflowExpressionEvaluationError","workflowExpressionEvaluationErrorCode","evaluateWorkflowExpression","evaluateWorkflowExpressionWithEnvironment","evaluateWorkflowPredicate","evaluateWorkflowPredicateFailClosed","createRangeEnvironment","MAX_RANGE_ELEMENTS","createWorkflowExpression","unsafeWorkflowExpressionFromSource","InvalidWorkflowExpressionError","invalidWorkflowExpressionErrorCode","coerceStepOutputs","jsonSchemaToExpressionType","outputDeclarationsToExpressionFields","outputDeclarationToExpressionType","outputTypes","validateJsonSchema","isBareContextReference","analyzeContextKeyAccess","analyzeContextRootKeyAccess","evaluatePlannedPredicateAtSite","capTraceEntries","capTraceValue","EVALUATION_TRACE_MAX_ENTRIES","EVALUATION_TRACE_VALUE_CAP_BYTES","evaluationTraceEntry","predicateTraceEntry","extractExactContextRoots","freezeResolvedFieldAtSite","resolveFieldAtSite","freezePlannedRunCommandAtSite","planInterpolationField","predicateSourceIsBooleanShaped","routeExpression","validateServerEvaluable","WorkflowTemplateResolutionError","workflowTemplateResolutionErrorCode","hoistPlannedRunCommand","UnsafeRunInterpolationError","unsafeRunInterpolationErrorCode","classifyShellCodePosition","InvalidWorkflowTemplateError","invalidWorkflowTemplateErrorCode","extractCelContextRoots","parseWorkflowTemplate","availabilitySites","buildTypedRootsEnvironment","contextRootsForField","getWorkflowContextAvailability","getWorkflowContextDefinition","getWorkflowContextHost","getWorkflowContextSensitivity","getWorkflowContextTypeEnvironment","getWorkflowInterpolationFieldFailurePolicy","getWorkflowInterpolationFieldSelfReference","getWorkflowPredicateContextRoots","getWorkflowPredicateFieldMinimumFillTarget","getWorkflowPredicateFieldTypeEnvironment","isWorkflowPredicateField","projectWorkflowPredicateContext","resolveContextRootAvailability","resolveContextRootHost","rootsAvailableAt","runnerFillTarget","unavailableRootsAt","workflowContextAvailabilityReference","workflowContextDefinitions","workflowContextHosts","workflowContextNames","workflowContextReservedRoots","workflowContextRootRequiresLiteralKey","workflowContextSensitivities","workflowFieldFailurePolicies","workflowInterpolationFieldAcceptsHost","workflowInterpolationFieldPolicies","workflowInterpolationFields","workflowPredicateContextRoots","workflowPredicateFieldFailurePolicy","workflowPredicateFields","workflowContextDocs"],"mappings":"AAAA,SACEA,iCAAiC,EAEjCC,qCAAqC,QAChC,wBAAwB;AAC/B,SACEC,0BAA0B,EAC1BC,yCAAyC,EACzCC,yBAAyB,EACzBC,mCAAmC,QAK9B,8CAA8C;AACrD,SAAQC,sBAAsB,EAAEC,kBAAkB,QAAO,uBAAuB;AAChF,SACEC,wBAAwB,EACxBC,kCAAkC,QAC7B,6CAA6C;AACpD,SACEC,8BAA8B,EAC9BC,kCAAkC,QAC7B,yBAAyB;AAWhC,SAEEC,iBAAiB,EAEjBC,0BAA0B,EAI1BC,oCAAoC,EACpCC,iCAAiC,EACjCC,WAAW,EAGXC,kBAAkB,QACb,qBAAqB;AAC5B,SAAQC,sBAAsB,QAAO,2BAA2B;AAChE,SACEC,uBAAuB,EACvBC,2BAA2B,QAMtB,+BAA+B;AACtC,SAAQC,8BAA8B,QAAO,uCAAuC;AACpF,SACEC,eAAe,EACfC,aAAa,EACbC,4BAA4B,EAC5BC,gCAAgC,EAIhCC,oBAAoB,EACpBC,mBAAmB,QACd,6BAA6B;AACpC,SAAQC,wBAAwB,QAAO,wCAAwC;AAC/E,SAEEC,yBAAyB,EACzBC,kBAAkB,QAIb,mBAAmB;AAC1B,SAEEC,6BAA6B,QACxB,+BAA+B;AACtC,SAIEC,sBAAsB,QACjB,uBAAuB;AAC9B,SAAQC,8BAA8B,QAAO,4BAA4B;AAOzE,SAA+BC,eAAe,QAAO,6BAA6B;AAClF,SAGEC,uBAAuB,QAClB,sCAAsC;AAC7C,SACEC,+BAA+B,EAC/BC,mCAAmC,QAC9B,uBAAuB;AAC9B,SAEEC,sBAAsB,EAItBC,2BAA2B,EAC3BC,+BAA+B,QAC1B,6BAA6B;AACpC,SACEC,yBAAyB,QAIpB,+BAA+B;AACtC,SACEC,4BAA4B,EAC5BC,gCAAgC,QAC3B,uBAAuB;AAC9B,SAAQC,sBAAsB,QAAO,0CAA0C;AAC/E,SAAQC,qBAAqB,QAAO,wCAAwC;AAM5E,SAEEC,iBAAiB,EACjBC,0BAA0B,EAC1BC,oBAAoB,EAEpBC,8BAA8B,EAC9BC,4BAA4B,EAC5BC,sBAAsB,EACtBC,6BAA6B,EAC7BC,iCAAiC,EACjCC,0CAA0C,EAC1CC,0CAA0C,EAC1CC,gCAAgC,EAChCC,0CAA0C,EAC1CC,wCAAwC,EACxCC,wBAAwB,EAExBC,+BAA+B,EAG/BC,8BAA8B,EAC9BC,sBAAsB,EACtBC,gBAAgB,EAChBC,gBAAgB,EAEhBC,kBAAkB,EAgBlBC,oCAAoC,EACpCC,0BAA0B,EAC1BC,oBAAoB,EACpBC,oBAAoB,EACpBC,4BAA4B,EAC5BC,qCAAqC,EACrCC,4BAA4B,EAC5BC,4BAA4B,EAC5BC,qCAAqC,EACrCC,kCAAkC,EAClCC,2BAA2B,EAC3BC,6BAA6B,EAC7BC,mCAAmC,EACnCC,uBAAuB,QAClB,yCAAyC;AAChD,SAEEC,mBAAmB,QACd,8CAA8C"}
@@ -6,6 +6,8 @@ export interface ContextKeyAccessReference {
6
6
  }
7
7
  export interface ContextKeyAccessViolation {
8
8
  readonly root: string;
9
+ /** First key when a computed access still uses a literal string key. */
10
+ readonly key?: string;
9
11
  readonly source: string;
10
12
  }
11
13
  export interface ContextKeyAccessAnalysis {
@@ -1 +1 @@
1
- {"version":3,"file":"context-key-access.d.ts","sourceRoot":"","sources":["../../src/plan/context-key-access.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,sCAAsC,CAAC;AAoB7E,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,UAAU,EAAE,SAAS,yBAAyB,EAAE,CAAC;IAC1D,QAAQ,CAAC,UAAU,EAAE,SAAS,yBAAyB,EAAE,CAAC;CAC3D;AAED,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,UAAU,EAAE,SAAS,6BAA6B,EAAE,CAAC;IAC9D,QAAQ,CAAC,UAAU,EAAE,SAAS,yBAAyB,EAAE,CAAC;CAC3D;AAaD,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,kBAAkB,GAAG,MAAM,GACtC,wBAAwB,CAY1B;AAED,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,kBAAkB,GAAG,MAAM,EACvC,KAAK,EAAE,SAAS,MAAM,EAAE,GACvB,4BAA4B,CAa9B"}
1
+ {"version":3,"file":"context-key-access.d.ts","sourceRoot":"","sources":["../../src/plan/context-key-access.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,sCAAsC,CAAC;AAoB7E,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,UAAU,EAAE,SAAS,yBAAyB,EAAE,CAAC;IAC1D,QAAQ,CAAC,UAAU,EAAE,SAAS,yBAAyB,EAAE,CAAC;CAC3D;AAED,MAAM,WAAW,6BAA6B;IAC5C,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,4BAA4B;IAC3C,QAAQ,CAAC,UAAU,EAAE,SAAS,6BAA6B,EAAE,CAAC;IAC9D,QAAQ,CAAC,UAAU,EAAE,SAAS,yBAAyB,EAAE,CAAC;CAC3D;AAaD,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,kBAAkB,GAAG,MAAM,GACtC,wBAAwB,CAY1B;AAED,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,kBAAkB,GAAG,MAAM,EACvC,KAAK,EAAE,SAAS,MAAM,EAAE,GACvB,4BAA4B,CAa9B"}
@@ -163,6 +163,9 @@ function recordContextRootKeyAccess(chain, source, references, violations) {
163
163
  if (chain.computed || key === undefined) {
164
164
  violations.push({
165
165
  root: chain.root,
166
+ ...key === undefined ? {} : {
167
+ key
168
+ },
166
169
  source
167
170
  });
168
171
  return;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/plan/context-key-access.ts"],"sourcesContent":["import {type ASTNode, type BinaryOperator, parse as parseCel} from '@marcbachmann/cel-js';\nimport type {WorkflowExpression} from '../expression/workflow-expression.js';\nimport {workflowContextRootRequiresLiteralKey} from '../workflow-context/workflow-context.js';\n\nconst binaryOperators = new Set<BinaryOperator>([\n '!=',\n '==',\n 'in',\n '+',\n '-',\n '*',\n '/',\n '%',\n '<',\n '<=',\n '>',\n '>=',\n]);\n\nconst comprehensionMethods = new Set(['all', 'exists', 'exists_one', 'filter', 'map']);\n\nexport interface ContextKeyAccessReference {\n readonly root: 'vars' | 'secrets';\n readonly store?: string;\n readonly key: string;\n}\n\nexport interface ContextKeyAccessViolation {\n readonly root: string;\n readonly source: string;\n}\n\nexport interface ContextKeyAccessAnalysis {\n readonly references: readonly ContextKeyAccessReference[];\n readonly violations: readonly ContextKeyAccessViolation[];\n}\n\nexport interface ContextRootKeyAccessReference {\n readonly root: string;\n readonly key: string;\n}\n\nexport interface ContextRootKeyAccessAnalysis {\n readonly references: readonly ContextRootKeyAccessReference[];\n readonly violations: readonly ContextKeyAccessViolation[];\n}\n\ninterface AccessChain {\n readonly root: string;\n readonly segments: readonly string[];\n readonly computed: boolean;\n}\n\ninterface ContextAccessVisitor {\n readonly shouldRecord: (chain: AccessChain) => boolean;\n readonly record: (chain: AccessChain, source: string) => void;\n}\n\nexport function analyzeContextKeyAccess(\n expression: WorkflowExpression | string,\n): ContextKeyAccessAnalysis {\n const source = typeof expression === 'string' ? expression : expression.source;\n const references: ContextKeyAccessReference[] = [];\n const violations: ContextKeyAccessViolation[] = [];\n\n collectContextAccesses(parseCel(source).ast, source, new Set(), {\n shouldRecord: (chain) => workflowContextRootRequiresLiteralKey(chain.root),\n record: (chain, expressionSource) =>\n recordLiteralKeyRootAccess(chain, expressionSource, references, violations),\n });\n\n return {references, violations};\n}\n\nexport function analyzeContextRootKeyAccess(\n expression: WorkflowExpression | string,\n roots: readonly string[],\n): ContextRootKeyAccessAnalysis {\n const source = typeof expression === 'string' ? expression : expression.source;\n const references: ContextRootKeyAccessReference[] = [];\n const violations: ContextKeyAccessViolation[] = [];\n const selectedRoots = new Set(roots);\n\n collectContextAccesses(parseCel(source).ast, source, new Set(), {\n shouldRecord: (chain) => selectedRoots.has(chain.root),\n record: (chain, expressionSource) =>\n recordContextRootKeyAccess(chain, expressionSource, references, violations),\n });\n\n return {references, violations};\n}\n\nfunction collectContextAccesses(\n node: ASTNode,\n source: string,\n scopedIdentifiers: ReadonlySet<string>,\n visitor: ContextAccessVisitor,\n): void {\n if (binaryOperators.has(node.op as BinaryOperator) || node.op === '||' || node.op === '&&') {\n collectBinaryContextAccesses(\n node.args as [ASTNode, ASTNode],\n source,\n scopedIdentifiers,\n visitor,\n );\n return;\n }\n\n const chain = accessChain(node, scopedIdentifiers);\n if (chain && visitor.shouldRecord(chain)) {\n visitor.record(chain, source);\n return;\n }\n\n switch (node.op) {\n case 'id':\n case 'value':\n return;\n case '.':\n case '.?':\n collectContextAccesses(node.args[0], source, scopedIdentifiers, visitor);\n return;\n case '[]':\n case '[?]':\n collectBinaryContextAccesses(node.args, source, scopedIdentifiers, visitor);\n return;\n case 'call':\n for (const argument of node.args[1]) {\n collectContextAccesses(argument, source, scopedIdentifiers, visitor);\n }\n return;\n case 'rcall': {\n const [method, receiver, args] = node.args as [string, ASTNode, ASTNode[]];\n collectContextAccesses(receiver, source, scopedIdentifiers, visitor);\n const binding = bindComprehensionAlias(method, args, scopedIdentifiers);\n for (const argument of args.slice(binding.skipArgs)) {\n collectContextAccesses(argument, source, binding.scopedIdentifiers, visitor);\n }\n return;\n }\n case 'list':\n for (const element of node.args) {\n collectContextAccesses(element, source, scopedIdentifiers, visitor);\n }\n return;\n case 'map':\n for (const [key, value] of node.args) {\n if (key.op !== 'id') {\n collectContextAccesses(key, source, scopedIdentifiers, visitor);\n }\n collectContextAccesses(value, source, scopedIdentifiers, visitor);\n }\n return;\n case '?:':\n collectContextAccesses(node.args[0], source, scopedIdentifiers, visitor);\n collectContextAccesses(node.args[1], source, scopedIdentifiers, visitor);\n collectContextAccesses(node.args[2], source, scopedIdentifiers, visitor);\n return;\n case '!_':\n case '-_':\n collectContextAccesses(node.args, source, scopedIdentifiers, visitor);\n return;\n }\n\n throw new Error(`Unsupported CEL AST operator: ${(node as {op: string}).op}`);\n}\n\nfunction collectBinaryContextAccesses(\n [left, right]: [ASTNode, ASTNode],\n source: string,\n scopedIdentifiers: ReadonlySet<string>,\n visitor: ContextAccessVisitor,\n): void {\n collectContextAccesses(left, source, scopedIdentifiers, visitor);\n collectContextAccesses(right, source, scopedIdentifiers, visitor);\n}\n\nfunction recordLiteralKeyRootAccess(\n chain: AccessChain,\n source: string,\n references: ContextKeyAccessReference[],\n violations: ContextKeyAccessViolation[],\n): void {\n if (chain.computed) {\n violations.push({root: chain.root, source});\n return;\n }\n\n if (chain.root === 'vars' && chain.segments.length === 1) {\n const key = chain.segments[0];\n if (key === undefined) throw new Error('Expected vars key segment');\n references.push({root: chain.root, key});\n return;\n }\n\n if (chain.root === 'secrets' && chain.segments.length === 1) {\n const key = chain.segments[0];\n if (key === undefined) throw new Error('Expected secret key segment');\n references.push({root: chain.root, key});\n return;\n }\n\n if (chain.root === 'secrets' && chain.segments.length === 2) {\n const store = chain.segments[0];\n const key = chain.segments[1];\n if (store === undefined || key === undefined) {\n throw new Error('Expected secret store and key segments');\n }\n references.push({root: chain.root, store, key});\n return;\n }\n\n violations.push({root: chain.root, source});\n}\n\nfunction recordContextRootKeyAccess(\n chain: AccessChain,\n source: string,\n references: ContextRootKeyAccessReference[],\n violations: ContextKeyAccessViolation[],\n): void {\n const [key] = chain.segments;\n if (chain.computed || key === undefined) {\n violations.push({root: chain.root, source});\n return;\n }\n\n references.push({root: chain.root, key});\n}\n\nfunction accessChain(\n node: ASTNode,\n scopedIdentifiers: ReadonlySet<string>,\n): AccessChain | undefined {\n switch (node.op) {\n case 'id':\n return scopedIdentifiers.has(node.args)\n ? undefined\n : {root: node.args, segments: [], computed: false};\n case '.': {\n const target = accessChain(node.args[0], scopedIdentifiers);\n if (target === undefined) return undefined;\n return {...target, segments: [...target.segments, node.args[1]]};\n }\n case '.?': {\n const target = accessChain(node.args[0], scopedIdentifiers);\n if (target === undefined) return undefined;\n return {...target, segments: [...target.segments, node.args[1]], computed: true};\n }\n case '[]':\n case '[?]': {\n const target = accessChain(node.args[0], scopedIdentifiers);\n if (target === undefined) return undefined;\n const literalSegment = literalStringValue(node.args[1]);\n return {\n ...target,\n segments:\n literalSegment === undefined ? target.segments : [...target.segments, literalSegment],\n computed: true,\n };\n }\n default:\n return undefined;\n }\n}\n\nfunction literalStringValue(node: ASTNode): string | undefined {\n return node.op === 'value' && typeof node.args === 'string' ? node.args : undefined;\n}\n\nfunction bindComprehensionAlias(\n method: string,\n args: readonly ASTNode[],\n scopedIdentifiers: ReadonlySet<string>,\n): {readonly scopedIdentifiers: ReadonlySet<string>; readonly skipArgs: number} {\n if (!comprehensionMethods.has(method)) return {scopedIdentifiers, skipArgs: 0};\n\n const [alias] = args;\n if (alias?.op !== 'id') return {scopedIdentifiers, skipArgs: 0};\n\n return {\n scopedIdentifiers: new Set([...scopedIdentifiers, alias.args]),\n skipArgs: 1,\n };\n}\n"],"names":["parse","parseCel","workflowContextRootRequiresLiteralKey","binaryOperators","Set","comprehensionMethods","analyzeContextKeyAccess","expression","source","references","violations","collectContextAccesses","ast","shouldRecord","chain","root","record","expressionSource","recordLiteralKeyRootAccess","analyzeContextRootKeyAccess","roots","selectedRoots","has","recordContextRootKeyAccess","node","scopedIdentifiers","visitor","op","collectBinaryContextAccesses","args","accessChain","argument","method","receiver","binding","bindComprehensionAlias","slice","skipArgs","element","key","value","Error","left","right","computed","push","segments","length","undefined","store","target","literalSegment","literalStringValue","alias"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/plan/context-key-access.ts"],"sourcesContent":["import {type ASTNode, type BinaryOperator, parse as parseCel} from '@marcbachmann/cel-js';\nimport type {WorkflowExpression} from '../expression/workflow-expression.js';\nimport {workflowContextRootRequiresLiteralKey} from '../workflow-context/workflow-context.js';\n\nconst binaryOperators = new Set<BinaryOperator>([\n '!=',\n '==',\n 'in',\n '+',\n '-',\n '*',\n '/',\n '%',\n '<',\n '<=',\n '>',\n '>=',\n]);\n\nconst comprehensionMethods = new Set(['all', 'exists', 'exists_one', 'filter', 'map']);\n\nexport interface ContextKeyAccessReference {\n readonly root: 'vars' | 'secrets';\n readonly store?: string;\n readonly key: string;\n}\n\nexport interface ContextKeyAccessViolation {\n readonly root: string;\n /** First key when a computed access still uses a literal string key. */\n readonly key?: string;\n readonly source: string;\n}\n\nexport interface ContextKeyAccessAnalysis {\n readonly references: readonly ContextKeyAccessReference[];\n readonly violations: readonly ContextKeyAccessViolation[];\n}\n\nexport interface ContextRootKeyAccessReference {\n readonly root: string;\n readonly key: string;\n}\n\nexport interface ContextRootKeyAccessAnalysis {\n readonly references: readonly ContextRootKeyAccessReference[];\n readonly violations: readonly ContextKeyAccessViolation[];\n}\n\ninterface AccessChain {\n readonly root: string;\n readonly segments: readonly string[];\n readonly computed: boolean;\n}\n\ninterface ContextAccessVisitor {\n readonly shouldRecord: (chain: AccessChain) => boolean;\n readonly record: (chain: AccessChain, source: string) => void;\n}\n\nexport function analyzeContextKeyAccess(\n expression: WorkflowExpression | string,\n): ContextKeyAccessAnalysis {\n const source = typeof expression === 'string' ? expression : expression.source;\n const references: ContextKeyAccessReference[] = [];\n const violations: ContextKeyAccessViolation[] = [];\n\n collectContextAccesses(parseCel(source).ast, source, new Set(), {\n shouldRecord: (chain) => workflowContextRootRequiresLiteralKey(chain.root),\n record: (chain, expressionSource) =>\n recordLiteralKeyRootAccess(chain, expressionSource, references, violations),\n });\n\n return {references, violations};\n}\n\nexport function analyzeContextRootKeyAccess(\n expression: WorkflowExpression | string,\n roots: readonly string[],\n): ContextRootKeyAccessAnalysis {\n const source = typeof expression === 'string' ? expression : expression.source;\n const references: ContextRootKeyAccessReference[] = [];\n const violations: ContextKeyAccessViolation[] = [];\n const selectedRoots = new Set(roots);\n\n collectContextAccesses(parseCel(source).ast, source, new Set(), {\n shouldRecord: (chain) => selectedRoots.has(chain.root),\n record: (chain, expressionSource) =>\n recordContextRootKeyAccess(chain, expressionSource, references, violations),\n });\n\n return {references, violations};\n}\n\nfunction collectContextAccesses(\n node: ASTNode,\n source: string,\n scopedIdentifiers: ReadonlySet<string>,\n visitor: ContextAccessVisitor,\n): void {\n if (binaryOperators.has(node.op as BinaryOperator) || node.op === '||' || node.op === '&&') {\n collectBinaryContextAccesses(\n node.args as [ASTNode, ASTNode],\n source,\n scopedIdentifiers,\n visitor,\n );\n return;\n }\n\n const chain = accessChain(node, scopedIdentifiers);\n if (chain && visitor.shouldRecord(chain)) {\n visitor.record(chain, source);\n return;\n }\n\n switch (node.op) {\n case 'id':\n case 'value':\n return;\n case '.':\n case '.?':\n collectContextAccesses(node.args[0], source, scopedIdentifiers, visitor);\n return;\n case '[]':\n case '[?]':\n collectBinaryContextAccesses(node.args, source, scopedIdentifiers, visitor);\n return;\n case 'call':\n for (const argument of node.args[1]) {\n collectContextAccesses(argument, source, scopedIdentifiers, visitor);\n }\n return;\n case 'rcall': {\n const [method, receiver, args] = node.args as [string, ASTNode, ASTNode[]];\n collectContextAccesses(receiver, source, scopedIdentifiers, visitor);\n const binding = bindComprehensionAlias(method, args, scopedIdentifiers);\n for (const argument of args.slice(binding.skipArgs)) {\n collectContextAccesses(argument, source, binding.scopedIdentifiers, visitor);\n }\n return;\n }\n case 'list':\n for (const element of node.args) {\n collectContextAccesses(element, source, scopedIdentifiers, visitor);\n }\n return;\n case 'map':\n for (const [key, value] of node.args) {\n if (key.op !== 'id') {\n collectContextAccesses(key, source, scopedIdentifiers, visitor);\n }\n collectContextAccesses(value, source, scopedIdentifiers, visitor);\n }\n return;\n case '?:':\n collectContextAccesses(node.args[0], source, scopedIdentifiers, visitor);\n collectContextAccesses(node.args[1], source, scopedIdentifiers, visitor);\n collectContextAccesses(node.args[2], source, scopedIdentifiers, visitor);\n return;\n case '!_':\n case '-_':\n collectContextAccesses(node.args, source, scopedIdentifiers, visitor);\n return;\n }\n\n throw new Error(`Unsupported CEL AST operator: ${(node as {op: string}).op}`);\n}\n\nfunction collectBinaryContextAccesses(\n [left, right]: [ASTNode, ASTNode],\n source: string,\n scopedIdentifiers: ReadonlySet<string>,\n visitor: ContextAccessVisitor,\n): void {\n collectContextAccesses(left, source, scopedIdentifiers, visitor);\n collectContextAccesses(right, source, scopedIdentifiers, visitor);\n}\n\nfunction recordLiteralKeyRootAccess(\n chain: AccessChain,\n source: string,\n references: ContextKeyAccessReference[],\n violations: ContextKeyAccessViolation[],\n): void {\n if (chain.computed) {\n violations.push({root: chain.root, source});\n return;\n }\n\n if (chain.root === 'vars' && chain.segments.length === 1) {\n const key = chain.segments[0];\n if (key === undefined) throw new Error('Expected vars key segment');\n references.push({root: chain.root, key});\n return;\n }\n\n if (chain.root === 'secrets' && chain.segments.length === 1) {\n const key = chain.segments[0];\n if (key === undefined) throw new Error('Expected secret key segment');\n references.push({root: chain.root, key});\n return;\n }\n\n if (chain.root === 'secrets' && chain.segments.length === 2) {\n const store = chain.segments[0];\n const key = chain.segments[1];\n if (store === undefined || key === undefined) {\n throw new Error('Expected secret store and key segments');\n }\n references.push({root: chain.root, store, key});\n return;\n }\n\n violations.push({root: chain.root, source});\n}\n\nfunction recordContextRootKeyAccess(\n chain: AccessChain,\n source: string,\n references: ContextRootKeyAccessReference[],\n violations: ContextKeyAccessViolation[],\n): void {\n const [key] = chain.segments;\n if (chain.computed || key === undefined) {\n violations.push({root: chain.root, ...(key === undefined ? {} : {key}), source});\n return;\n }\n\n references.push({root: chain.root, key});\n}\n\nfunction accessChain(\n node: ASTNode,\n scopedIdentifiers: ReadonlySet<string>,\n): AccessChain | undefined {\n switch (node.op) {\n case 'id':\n return scopedIdentifiers.has(node.args)\n ? undefined\n : {root: node.args, segments: [], computed: false};\n case '.': {\n const target = accessChain(node.args[0], scopedIdentifiers);\n if (target === undefined) return undefined;\n return {...target, segments: [...target.segments, node.args[1]]};\n }\n case '.?': {\n const target = accessChain(node.args[0], scopedIdentifiers);\n if (target === undefined) return undefined;\n return {...target, segments: [...target.segments, node.args[1]], computed: true};\n }\n case '[]':\n case '[?]': {\n const target = accessChain(node.args[0], scopedIdentifiers);\n if (target === undefined) return undefined;\n const literalSegment = literalStringValue(node.args[1]);\n return {\n ...target,\n segments:\n literalSegment === undefined ? target.segments : [...target.segments, literalSegment],\n computed: true,\n };\n }\n default:\n return undefined;\n }\n}\n\nfunction literalStringValue(node: ASTNode): string | undefined {\n return node.op === 'value' && typeof node.args === 'string' ? node.args : undefined;\n}\n\nfunction bindComprehensionAlias(\n method: string,\n args: readonly ASTNode[],\n scopedIdentifiers: ReadonlySet<string>,\n): {readonly scopedIdentifiers: ReadonlySet<string>; readonly skipArgs: number} {\n if (!comprehensionMethods.has(method)) return {scopedIdentifiers, skipArgs: 0};\n\n const [alias] = args;\n if (alias?.op !== 'id') return {scopedIdentifiers, skipArgs: 0};\n\n return {\n scopedIdentifiers: new Set([...scopedIdentifiers, alias.args]),\n skipArgs: 1,\n };\n}\n"],"names":["parse","parseCel","workflowContextRootRequiresLiteralKey","binaryOperators","Set","comprehensionMethods","analyzeContextKeyAccess","expression","source","references","violations","collectContextAccesses","ast","shouldRecord","chain","root","record","expressionSource","recordLiteralKeyRootAccess","analyzeContextRootKeyAccess","roots","selectedRoots","has","recordContextRootKeyAccess","node","scopedIdentifiers","visitor","op","collectBinaryContextAccesses","args","accessChain","argument","method","receiver","binding","bindComprehensionAlias","slice","skipArgs","element","key","value","Error","left","right","computed","push","segments","length","undefined","store","target","literalSegment","literalStringValue","alias"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"evaluate-planned-predicate.d.ts","sourceRoot":"","sources":["../../src/plan/evaluate-planned-predicate.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,0BAA0B,EAC/B,KAAK,mCAAmC,EACzC,MAAM,8CAA8C,CAAC;AACtD,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,sCAAsC,CAAC;AAC7E,OAAO,KAAK,EACV,gBAAgB,EAEhB,sBAAsB,EACvB,MAAM,yCAAyC,CAAC;AAGjD,OAAO,EAAC,KAAK,gBAAgB,EAAkB,MAAM,uBAAuB,CAAC;AAE7E,MAAM,WAAW,gCAAiC,SAAQ,0BAA0B;IAClF,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;CAClC;AAED,wBAAgB,8BAA8B,CAAC,MAAM,EAAE;IACrD,QAAQ,CAAC,UAAU,EAAE,kBAAkB,CAAC;IACxC,QAAQ,CAAC,KAAK,EAAE,sBAAsB,CAAC;IACvC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,mCAAmC,CAAC;CACvD,GAAG,gCAAgC,CAOnC"}
1
+ {"version":3,"file":"evaluate-planned-predicate.d.ts","sourceRoot":"","sources":["../../src/plan/evaluate-planned-predicate.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,0BAA0B,EAC/B,KAAK,mCAAmC,EACzC,MAAM,8CAA8C,CAAC;AACtD,OAAO,KAAK,EAAC,kBAAkB,EAAC,MAAM,sCAAsC,CAAC;AAC7E,OAAO,KAAK,EACV,gBAAgB,EAEhB,sBAAsB,EACvB,MAAM,yCAAyC,CAAC;AAMjD,OAAO,EAAC,KAAK,gBAAgB,EAAkB,MAAM,uBAAuB,CAAC;AAE7E,MAAM,WAAW,gCAAiC,SAAQ,0BAA0B;IAClF,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;CAClC;AAED,wBAAgB,8BAA8B,CAAC,MAAM,EAAE;IACrD,QAAQ,CAAC,UAAU,EAAE,kBAAkB,CAAC;IACxC,QAAQ,CAAC,KAAK,EAAE,sBAAsB,CAAC;IACvC,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAC;IAChC,QAAQ,CAAC,OAAO,EAAE,mCAAmC,CAAC;CACvD,GAAG,gCAAgC,CAanC"}
@@ -1,5 +1,5 @@
1
1
  import { evaluateWorkflowPredicateFailClosed } from '../evaluator/evaluate-workflow-expression.js';
2
- import { getWorkflowPredicateFieldMinimumFillTarget } from '../workflow-context/workflow-context.js';
2
+ import { getWorkflowPredicateFieldMinimumFillTarget, projectWorkflowPredicateContext } from '../workflow-context/workflow-context.js';
3
3
  import { shouldFillAtSite } from './fill.js';
4
4
  import { routeExpression } from './route-expression.js';
5
5
  export function evaluatePlannedPredicateAtSite(params) {
@@ -12,7 +12,7 @@ export function evaluatePlannedPredicateAtSite(params) {
12
12
  };
13
13
  }
14
14
  return {
15
- ...evaluateWorkflowPredicateFailClosed(params.expression, params.context),
15
+ ...evaluateWorkflowPredicateFailClosed(params.expression, projectWorkflowPredicateContext(params.field, params.context)),
16
16
  route
17
17
  };
18
18
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/plan/evaluate-planned-predicate.ts"],"sourcesContent":["import {\n evaluateWorkflowPredicateFailClosed,\n type FailClosedPredicateOutcome,\n type WorkflowExpressionEvaluationContext,\n} from '../evaluator/evaluate-workflow-expression.js';\nimport type {WorkflowExpression} from '../expression/workflow-expression.js';\nimport type {\n AvailabilitySite,\n FillTarget,\n WorkflowPredicateField,\n} from '../workflow-context/workflow-context.js';\nimport {getWorkflowPredicateFieldMinimumFillTarget} from '../workflow-context/workflow-context.js';\nimport {shouldFillAtSite} from './fill.js';\nimport {type RoutedExpression, routeExpression} from './route-expression.js';\n\nexport interface PlannedPredicateEvaluationResult extends FailClosedPredicateOutcome {\n readonly route: RoutedExpression;\n}\n\nexport function evaluatePlannedPredicateAtSite(params: {\n readonly expression: WorkflowExpression;\n readonly field: WorkflowPredicateField;\n readonly site: AvailabilitySite;\n readonly context: WorkflowExpressionEvaluationContext;\n}): PlannedPredicateEvaluationResult {\n const route = routePredicateExpression(params.expression, params.field);\n if (!shouldFillAtSite(route.fillTarget, params.site)) {\n return {value: false, evaluationFailed: true, route};\n }\n\n return {...evaluateWorkflowPredicateFailClosed(params.expression, params.context), route};\n}\n\nfunction routePredicateExpression(\n expression: WorkflowExpression,\n field: WorkflowPredicateField,\n): RoutedExpression {\n const route = routeExpression(expression);\n return {\n ...route,\n fillTarget: laterFillTarget(\n route.fillTarget,\n getWorkflowPredicateFieldMinimumFillTarget(field),\n ),\n };\n}\n\nfunction laterFillTarget(left: FillTarget, right: AvailabilitySite): FillTarget {\n if (left === 'runner-fill') return left;\n return shouldFillAtSite(right, left) ? left : right;\n}\n"],"names":["evaluateWorkflowPredicateFailClosed","getWorkflowPredicateFieldMinimumFillTarget","shouldFillAtSite","routeExpression","evaluatePlannedPredicateAtSite","params","route","routePredicateExpression","expression","field","fillTarget","site","value","evaluationFailed","context","laterFillTarget","left","right"],"mappings":"AAAA,SACEA,mCAAmC,QAG9B,+CAA+C;AAOtD,SAAQC,0CAA0C,QAAO,0CAA0C;AACnG,SAAQC,gBAAgB,QAAO,YAAY;AAC3C,SAA+BC,eAAe,QAAO,wBAAwB;AAM7E,OAAO,SAASC,+BAA+BC,MAK9C;IACC,MAAMC,QAAQC,yBAAyBF,OAAOG,UAAU,EAAEH,OAAOI,KAAK;IACtE,IAAI,CAACP,iBAAiBI,MAAMI,UAAU,EAAEL,OAAOM,IAAI,GAAG;QACpD,OAAO;YAACC,OAAO;YAAOC,kBAAkB;YAAMP;QAAK;IACrD;IAEA,OAAO;QAAC,GAAGN,oCAAoCK,OAAOG,UAAU,EAAEH,OAAOS,OAAO,CAAC;QAAER;IAAK;AAC1F;AAEA,SAASC,yBACPC,UAA8B,EAC9BC,KAA6B;IAE7B,MAAMH,QAAQH,gBAAgBK;IAC9B,OAAO;QACL,GAAGF,KAAK;QACRI,YAAYK,gBACVT,MAAMI,UAAU,EAChBT,2CAA2CQ;IAE/C;AACF;AAEA,SAASM,gBAAgBC,IAAgB,EAAEC,KAAuB;IAChE,IAAID,SAAS,eAAe,OAAOA;IACnC,OAAOd,iBAAiBe,OAAOD,QAAQA,OAAOC;AAChD"}
1
+ {"version":3,"sources":["../../src/plan/evaluate-planned-predicate.ts"],"sourcesContent":["import {\n evaluateWorkflowPredicateFailClosed,\n type FailClosedPredicateOutcome,\n type WorkflowExpressionEvaluationContext,\n} from '../evaluator/evaluate-workflow-expression.js';\nimport type {WorkflowExpression} from '../expression/workflow-expression.js';\nimport type {\n AvailabilitySite,\n FillTarget,\n WorkflowPredicateField,\n} from '../workflow-context/workflow-context.js';\nimport {\n getWorkflowPredicateFieldMinimumFillTarget,\n projectWorkflowPredicateContext,\n} from '../workflow-context/workflow-context.js';\nimport {shouldFillAtSite} from './fill.js';\nimport {type RoutedExpression, routeExpression} from './route-expression.js';\n\nexport interface PlannedPredicateEvaluationResult extends FailClosedPredicateOutcome {\n readonly route: RoutedExpression;\n}\n\nexport function evaluatePlannedPredicateAtSite(params: {\n readonly expression: WorkflowExpression;\n readonly field: WorkflowPredicateField;\n readonly site: AvailabilitySite;\n readonly context: WorkflowExpressionEvaluationContext;\n}): PlannedPredicateEvaluationResult {\n const route = routePredicateExpression(params.expression, params.field);\n if (!shouldFillAtSite(route.fillTarget, params.site)) {\n return {value: false, evaluationFailed: true, route};\n }\n\n return {\n ...evaluateWorkflowPredicateFailClosed(\n params.expression,\n projectWorkflowPredicateContext(params.field, params.context),\n ),\n route,\n };\n}\n\nfunction routePredicateExpression(\n expression: WorkflowExpression,\n field: WorkflowPredicateField,\n): RoutedExpression {\n const route = routeExpression(expression);\n return {\n ...route,\n fillTarget: laterFillTarget(\n route.fillTarget,\n getWorkflowPredicateFieldMinimumFillTarget(field),\n ),\n };\n}\n\nfunction laterFillTarget(left: FillTarget, right: AvailabilitySite): FillTarget {\n if (left === 'runner-fill') return left;\n return shouldFillAtSite(right, left) ? left : right;\n}\n"],"names":["evaluateWorkflowPredicateFailClosed","getWorkflowPredicateFieldMinimumFillTarget","projectWorkflowPredicateContext","shouldFillAtSite","routeExpression","evaluatePlannedPredicateAtSite","params","route","routePredicateExpression","expression","field","fillTarget","site","value","evaluationFailed","context","laterFillTarget","left","right"],"mappings":"AAAA,SACEA,mCAAmC,QAG9B,+CAA+C;AAOtD,SACEC,0CAA0C,EAC1CC,+BAA+B,QAC1B,0CAA0C;AACjD,SAAQC,gBAAgB,QAAO,YAAY;AAC3C,SAA+BC,eAAe,QAAO,wBAAwB;AAM7E,OAAO,SAASC,+BAA+BC,MAK9C;IACC,MAAMC,QAAQC,yBAAyBF,OAAOG,UAAU,EAAEH,OAAOI,KAAK;IACtE,IAAI,CAACP,iBAAiBI,MAAMI,UAAU,EAAEL,OAAOM,IAAI,GAAG;QACpD,OAAO;YAACC,OAAO;YAAOC,kBAAkB;YAAMP;QAAK;IACrD;IAEA,OAAO;QACL,GAAGP,oCACDM,OAAOG,UAAU,EACjBP,gCAAgCI,OAAOI,KAAK,EAAEJ,OAAOS,OAAO,EAC7D;QACDR;IACF;AACF;AAEA,SAASC,yBACPC,UAA8B,EAC9BC,KAA6B;IAE7B,MAAMH,QAAQH,gBAAgBK;IAC9B,OAAO;QACL,GAAGF,KAAK;QACRI,YAAYK,gBACVT,MAAMI,UAAU,EAChBV,2CAA2CS;IAE/C;AACF;AAEA,SAASM,gBAAgBC,IAAgB,EAAEC,KAAuB;IAChE,IAAID,SAAS,eAAe,OAAOA;IACnC,OAAOd,iBAAiBe,OAAOD,QAAQA,OAAOC;AAChD"}
@@ -12,13 +12,21 @@ export interface HoistedPlannedRunCommand {
12
12
  readonly command: string;
13
13
  readonly bindings: readonly PlannedRunCommandBinding[];
14
14
  }
15
+ export interface UnsafeRunInterpolation {
16
+ readonly region: ShellUnsafeRegion;
17
+ readonly source: string;
18
+ }
15
19
  export declare class UnsafeRunInterpolationError extends Error {
16
20
  readonly code = "unsafe-run-interpolation";
21
+ readonly occurrences: readonly UnsafeRunInterpolation[];
22
+ readonly partial: HoistedPlannedRunCommand | undefined;
17
23
  readonly region: ShellUnsafeRegion;
18
24
  readonly source: string;
19
25
  constructor(params: {
20
26
  readonly region: ShellUnsafeRegion;
21
27
  readonly source: string;
28
+ readonly occurrences?: readonly UnsafeRunInterpolation[];
29
+ readonly partial?: HoistedPlannedRunCommand;
22
30
  });
23
31
  }
24
32
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"hoist-run-command.d.ts","sourceRoot":"","sources":["../../src/run/hoist-run-command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,aAAa,EAAE,4BAA4B,EAAC,MAAM,2BAA2B,CAAC;AAC3F,OAAO,EAKL,KAAK,iBAAiB,EAEvB,MAAM,oBAAoB,CAAC;AAE5B,eAAO,MAAM,+BAA+B,6BAA6B,CAAC;AAK1E,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,4BAA4B,CAAC;CAChD;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,SAAS,wBAAwB,EAAE,CAAC;CACxD;AAED,qBAAa,2BAA4B,SAAQ,KAAK;IACpD,QAAQ,CAAC,IAAI,8BAAmC;IAChD,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,MAAM,EAAE;QAAC,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAC;CAQlF;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE;IAC7C,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;CAC3C,GAAG,wBAAwB,CAQ3B"}
1
+ {"version":3,"file":"hoist-run-command.d.ts","sourceRoot":"","sources":["../../src/run/hoist-run-command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,aAAa,EAAE,4BAA4B,EAAC,MAAM,2BAA2B,CAAC;AAC3F,OAAO,EAKL,KAAK,iBAAiB,EAEvB,MAAM,oBAAoB,CAAC;AAE5B,eAAO,MAAM,+BAA+B,6BAA6B,CAAC;AAK1E,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,4BAA4B,CAAC;CAChD;AAED,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,SAAS,wBAAwB,EAAE,CAAC;CACxD;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,qBAAa,2BAA4B,SAAQ,KAAK;IACpD,QAAQ,CAAC,IAAI,8BAAmC;IAChD,QAAQ,CAAC,WAAW,EAAE,SAAS,sBAAsB,EAAE,CAAC;IACxD,QAAQ,CAAC,OAAO,EAAE,wBAAwB,GAAG,SAAS,CAAC;IACvD,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,MAAM,EAAE;QAClB,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC;QACnC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QACxB,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,sBAAsB,EAAE,CAAC;QACzD,QAAQ,CAAC,OAAO,CAAC,EAAE,wBAAwB,CAAC;KAC7C;CAUF;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE;IAC7C,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAC;IAC9B,QAAQ,CAAC,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;CAC3C,GAAG,wBAAwB,CAmB3B"}
@@ -6,6 +6,13 @@ export class UnsafeRunInterpolationError extends Error {
6
6
  constructor(params){
7
7
  super(`Unsafe run interpolation inside ${params.region}. Bind the value to env and reference $VAR instead.`), this.code = unsafeRunInterpolationErrorCode;
8
8
  this.name = 'UnsafeRunInterpolationError';
9
+ this.occurrences = params.occurrences ?? [
10
+ {
11
+ region: params.region,
12
+ source: params.source
13
+ }
14
+ ];
15
+ this.partial = params.partial;
9
16
  this.region = params.region;
10
17
  this.source = params.source;
11
18
  }
@@ -15,7 +22,7 @@ export class UnsafeRunInterpolationError extends Error {
15
22
  * references. Literal segments are trusted authored shell text; only call this
16
23
  * on planned command fields that have not already been filled.
17
24
  */ export function hoistPlannedRunCommand(params) {
18
- return hoistCommandSegments({
25
+ const result = hoistCommandSegments({
19
26
  segments: params.field.segments,
20
27
  options: params.reservedNames === undefined ? {} : {
21
28
  reservedNames: params.reservedNames
@@ -23,11 +30,27 @@ export class UnsafeRunInterpolationError extends Error {
23
30
  literalText: (segment)=>segment.value,
24
31
  isBindingSegment: (segment)=>segment.kind === 'deferred'
25
32
  });
33
+ const firstUnsafeInterpolation = result.unsafeInterpolations[0];
34
+ if (firstUnsafeInterpolation !== undefined) {
35
+ throw new UnsafeRunInterpolationError({
36
+ ...firstUnsafeInterpolation,
37
+ occurrences: result.unsafeInterpolations,
38
+ partial: {
39
+ command: result.command,
40
+ bindings: result.bindings
41
+ }
42
+ });
43
+ }
44
+ return {
45
+ command: result.command,
46
+ bindings: result.bindings
47
+ };
26
48
  }
27
49
  function hoistCommandSegments(params) {
28
50
  let command = '';
29
51
  let state = initialShellScanState;
30
52
  const bindings = [];
53
+ const unsafeInterpolations = [];
31
54
  const reservedNames = new Set(params.options.reservedNames ?? []);
32
55
  let nextIndex = 0;
33
56
  for (const segment of params.segments){
@@ -40,10 +63,11 @@ function hoistCommandSegments(params) {
40
63
  if (!params.isBindingSegment(segment)) continue;
41
64
  const site = classifyShellSite(state);
42
65
  if (site.kind === 'unsafe') {
43
- throw new UnsafeRunInterpolationError({
66
+ unsafeInterpolations.push({
44
67
  region: site.region,
45
68
  source: segment.expression.source
46
69
  });
70
+ continue;
47
71
  }
48
72
  const name = nextGeneratedName(reservedNames, nextIndex);
49
73
  nextIndex = Number(name.slice(generatedNamePrefix.length)) + 1;
@@ -56,7 +80,8 @@ function hoistCommandSegments(params) {
56
80
  }
57
81
  return {
58
82
  command,
59
- bindings
83
+ bindings,
84
+ unsafeInterpolations
60
85
  };
61
86
  }
62
87
  function nextGeneratedName(reservedNames, startIndex) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/run/hoist-run-command.ts"],"sourcesContent":["import type {ResolvedField, ResolvedFieldDeferredSegment} from '../plan/resolved-field.js';\nimport {\n classifyShellSite,\n initialShellScanState,\n type ShellScanState,\n type ShellSiteContext,\n type ShellUnsafeRegion,\n scanShellLiteral,\n} from './shell-quoting.js';\n\nexport const unsafeRunInterpolationErrorCode = 'unsafe-run-interpolation';\n\nconst generatedNamePrefix = '__sf_';\nconst shellIdentifierPattern = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\nexport interface RunCommandHoistOptions {\n readonly reservedNames?: Iterable<string>;\n}\n\nexport interface PlannedRunCommandBinding {\n readonly name: string;\n readonly segment: ResolvedFieldDeferredSegment;\n}\n\nexport interface HoistedPlannedRunCommand {\n readonly command: string;\n readonly bindings: readonly PlannedRunCommandBinding[];\n}\n\nexport class UnsafeRunInterpolationError extends Error {\n readonly code = unsafeRunInterpolationErrorCode;\n readonly region: ShellUnsafeRegion;\n readonly source: string;\n\n constructor(params: {readonly region: ShellUnsafeRegion; readonly source: string}) {\n super(\n `Unsafe run interpolation inside ${params.region}. Bind the value to env and reference $VAR instead.`,\n );\n this.name = 'UnsafeRunInterpolationError';\n this.region = params.region;\n this.source = params.source;\n }\n}\n\n/**\n * Hoists unfilled planned run-command segments into generated shell env\n * references. Literal segments are trusted authored shell text; only call this\n * on planned command fields that have not already been filled.\n */\nexport function hoistPlannedRunCommand(params: {\n readonly field: ResolvedField;\n readonly reservedNames?: Iterable<string>;\n}): HoistedPlannedRunCommand {\n return hoistCommandSegments({\n segments: params.field.segments,\n options: params.reservedNames === undefined ? {} : {reservedNames: params.reservedNames},\n literalText: (segment) => segment.value,\n isBindingSegment: (segment): segment is ResolvedFieldDeferredSegment =>\n segment.kind === 'deferred',\n });\n}\n\nfunction hoistCommandSegments<\n Segment extends {readonly kind: string},\n BindingSegment extends Segment & {readonly expression: {readonly source: string}},\n>(params: {\n readonly segments: readonly Segment[];\n readonly options: RunCommandHoistOptions;\n readonly literalText: (segment: Extract<Segment, {readonly kind: 'literal'}>) => string;\n readonly isBindingSegment: (segment: Segment) => segment is BindingSegment;\n}): {\n readonly command: string;\n readonly bindings: readonly {readonly name: string; readonly segment: BindingSegment}[];\n} {\n let command = '';\n let state: ShellScanState = initialShellScanState;\n const bindings: {name: string; segment: BindingSegment}[] = [];\n const reservedNames = new Set(params.options.reservedNames ?? []);\n let nextIndex = 0;\n\n for (const segment of params.segments) {\n if (segment.kind === 'literal') {\n const text = params.literalText(segment as Extract<Segment, {readonly kind: 'literal'}>);\n command += text;\n state = scanShellLiteral(text, state);\n continue;\n }\n\n if (!params.isBindingSegment(segment)) continue;\n\n const site = classifyShellSite(state);\n if (site.kind === 'unsafe') {\n throw new UnsafeRunInterpolationError({\n region: site.region,\n source: segment.expression.source,\n });\n }\n\n const name = nextGeneratedName(reservedNames, nextIndex);\n nextIndex = Number(name.slice(generatedNamePrefix.length)) + 1;\n reservedNames.add(name);\n bindings.push({name, segment});\n command += shellReference(name, site);\n }\n\n return {command, bindings};\n}\n\nfunction nextGeneratedName(reservedNames: ReadonlySet<string>, startIndex: number): string {\n let index = startIndex;\n\n while (true) {\n const name = `${generatedNamePrefix}${index}`;\n if (!shellIdentifierPattern.test(name)) {\n throw new Error(`Generated run env name is not a shell identifier: ${name}`);\n }\n\n if (!reservedNames.has(name)) return name;\n index += 1;\n }\n}\n\nfunction shellReference(name: string, site: Exclude<ShellSiteContext, {readonly kind: 'unsafe'}>) {\n if (site.kind === 'double') return `\\${${name}}`;\n if (site.kind === 'single') return `'\"\\${${name}}\"'`;\n return `\"\\${${name}}\"`;\n}\n"],"names":["classifyShellSite","initialShellScanState","scanShellLiteral","unsafeRunInterpolationErrorCode","generatedNamePrefix","shellIdentifierPattern","UnsafeRunInterpolationError","Error","params","region","code","name","source","hoistPlannedRunCommand","hoistCommandSegments","segments","field","options","reservedNames","undefined","literalText","segment","value","isBindingSegment","kind","command","state","bindings","Set","nextIndex","text","site","expression","nextGeneratedName","Number","slice","length","add","push","shellReference","startIndex","index","test","has"],"mappings":"AACA,SACEA,iBAAiB,EACjBC,qBAAqB,EAIrBC,gBAAgB,QACX,qBAAqB;AAE5B,OAAO,MAAMC,kCAAkC,2BAA2B;AAE1E,MAAMC,sBAAsB;AAC5B,MAAMC,yBAAyB;AAgB/B,OAAO,MAAMC,oCAAoCC;IAK/C,YAAYC,MAAqE,CAAE;QACjF,KAAK,CACH,CAAC,gCAAgC,EAAEA,OAAOC,MAAM,CAAC,mDAAmD,CAAC,QANhGC,OAAOP;QAQd,IAAI,CAACQ,IAAI,GAAG;QACZ,IAAI,CAACF,MAAM,GAAGD,OAAOC,MAAM;QAC3B,IAAI,CAACG,MAAM,GAAGJ,OAAOI,MAAM;IAC7B;AACF;AAEA;;;;CAIC,GACD,OAAO,SAASC,uBAAuBL,MAGtC;IACC,OAAOM,qBAAqB;QAC1BC,UAAUP,OAAOQ,KAAK,CAACD,QAAQ;QAC/BE,SAAST,OAAOU,aAAa,KAAKC,YAAY,CAAC,IAAI;YAACD,eAAeV,OAAOU,aAAa;QAAA;QACvFE,aAAa,CAACC,UAAYA,QAAQC,KAAK;QACvCC,kBAAkB,CAACF,UACjBA,QAAQG,IAAI,KAAK;IACrB;AACF;AAEA,SAASV,qBAGPN,MAKD;IAIC,IAAIiB,UAAU;IACd,IAAIC,QAAwBzB;IAC5B,MAAM0B,WAAsD,EAAE;IAC9D,MAAMT,gBAAgB,IAAIU,IAAIpB,OAAOS,OAAO,CAACC,aAAa,IAAI,EAAE;IAChE,IAAIW,YAAY;IAEhB,KAAK,MAAMR,WAAWb,OAAOO,QAAQ,CAAE;QACrC,IAAIM,QAAQG,IAAI,KAAK,WAAW;YAC9B,MAAMM,OAAOtB,OAAOY,WAAW,CAACC;YAChCI,WAAWK;YACXJ,QAAQxB,iBAAiB4B,MAAMJ;YAC/B;QACF;QAEA,IAAI,CAAClB,OAAOe,gBAAgB,CAACF,UAAU;QAEvC,MAAMU,OAAO/B,kBAAkB0B;QAC/B,IAAIK,KAAKP,IAAI,KAAK,UAAU;YAC1B,MAAM,IAAIlB,4BAA4B;gBACpCG,QAAQsB,KAAKtB,MAAM;gBACnBG,QAAQS,QAAQW,UAAU,CAACpB,MAAM;YACnC;QACF;QAEA,MAAMD,OAAOsB,kBAAkBf,eAAeW;QAC9CA,YAAYK,OAAOvB,KAAKwB,KAAK,CAAC/B,oBAAoBgC,MAAM,KAAK;QAC7DlB,cAAcmB,GAAG,CAAC1B;QAClBgB,SAASW,IAAI,CAAC;YAAC3B;YAAMU;QAAO;QAC5BI,WAAWc,eAAe5B,MAAMoB;IAClC;IAEA,OAAO;QAACN;QAASE;IAAQ;AAC3B;AAEA,SAASM,kBAAkBf,aAAkC,EAAEsB,UAAkB;IAC/E,IAAIC,QAAQD;IAEZ,MAAO,KAAM;QACX,MAAM7B,OAAO,GAAGP,sBAAsBqC,OAAO;QAC7C,IAAI,CAACpC,uBAAuBqC,IAAI,CAAC/B,OAAO;YACtC,MAAM,IAAIJ,MAAM,CAAC,kDAAkD,EAAEI,MAAM;QAC7E;QAEA,IAAI,CAACO,cAAcyB,GAAG,CAAChC,OAAO,OAAOA;QACrC8B,SAAS;IACX;AACF;AAEA,SAASF,eAAe5B,IAAY,EAAEoB,IAA0D;IAC9F,IAAIA,KAAKP,IAAI,KAAK,UAAU,OAAO,CAAC,GAAG,EAAEb,KAAK,CAAC,CAAC;IAChD,IAAIoB,KAAKP,IAAI,KAAK,UAAU,OAAO,CAAC,KAAK,EAAEb,KAAK,GAAG,CAAC;IACpD,OAAO,CAAC,IAAI,EAAEA,KAAK,EAAE,CAAC;AACxB"}
1
+ {"version":3,"sources":["../../src/run/hoist-run-command.ts"],"sourcesContent":["import type {ResolvedField, ResolvedFieldDeferredSegment} from '../plan/resolved-field.js';\nimport {\n classifyShellSite,\n initialShellScanState,\n type ShellScanState,\n type ShellSiteContext,\n type ShellUnsafeRegion,\n scanShellLiteral,\n} from './shell-quoting.js';\n\nexport const unsafeRunInterpolationErrorCode = 'unsafe-run-interpolation';\n\nconst generatedNamePrefix = '__sf_';\nconst shellIdentifierPattern = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\nexport interface RunCommandHoistOptions {\n readonly reservedNames?: Iterable<string>;\n}\n\nexport interface PlannedRunCommandBinding {\n readonly name: string;\n readonly segment: ResolvedFieldDeferredSegment;\n}\n\nexport interface HoistedPlannedRunCommand {\n readonly command: string;\n readonly bindings: readonly PlannedRunCommandBinding[];\n}\n\nexport interface UnsafeRunInterpolation {\n readonly region: ShellUnsafeRegion;\n readonly source: string;\n}\n\nexport class UnsafeRunInterpolationError extends Error {\n readonly code = unsafeRunInterpolationErrorCode;\n readonly occurrences: readonly UnsafeRunInterpolation[];\n readonly partial: HoistedPlannedRunCommand | undefined;\n readonly region: ShellUnsafeRegion;\n readonly source: string;\n\n constructor(params: {\n readonly region: ShellUnsafeRegion;\n readonly source: string;\n readonly occurrences?: readonly UnsafeRunInterpolation[];\n readonly partial?: HoistedPlannedRunCommand;\n }) {\n super(\n `Unsafe run interpolation inside ${params.region}. Bind the value to env and reference $VAR instead.`,\n );\n this.name = 'UnsafeRunInterpolationError';\n this.occurrences = params.occurrences ?? [{region: params.region, source: params.source}];\n this.partial = params.partial;\n this.region = params.region;\n this.source = params.source;\n }\n}\n\n/**\n * Hoists unfilled planned run-command segments into generated shell env\n * references. Literal segments are trusted authored shell text; only call this\n * on planned command fields that have not already been filled.\n */\nexport function hoistPlannedRunCommand(params: {\n readonly field: ResolvedField;\n readonly reservedNames?: Iterable<string>;\n}): HoistedPlannedRunCommand {\n const result = hoistCommandSegments({\n segments: params.field.segments,\n options: params.reservedNames === undefined ? {} : {reservedNames: params.reservedNames},\n literalText: (segment) => segment.value,\n isBindingSegment: (segment): segment is ResolvedFieldDeferredSegment =>\n segment.kind === 'deferred',\n });\n\n const firstUnsafeInterpolation = result.unsafeInterpolations[0];\n if (firstUnsafeInterpolation !== undefined) {\n throw new UnsafeRunInterpolationError({\n ...firstUnsafeInterpolation,\n occurrences: result.unsafeInterpolations,\n partial: {command: result.command, bindings: result.bindings},\n });\n }\n\n return {command: result.command, bindings: result.bindings};\n}\n\nfunction hoistCommandSegments<\n Segment extends {readonly kind: string},\n BindingSegment extends Segment & {readonly expression: {readonly source: string}},\n>(params: {\n readonly segments: readonly Segment[];\n readonly options: RunCommandHoistOptions;\n readonly literalText: (segment: Extract<Segment, {readonly kind: 'literal'}>) => string;\n readonly isBindingSegment: (segment: Segment) => segment is BindingSegment;\n}): {\n readonly command: string;\n readonly bindings: readonly {readonly name: string; readonly segment: BindingSegment}[];\n readonly unsafeInterpolations: readonly UnsafeRunInterpolation[];\n} {\n let command = '';\n let state: ShellScanState = initialShellScanState;\n const bindings: {name: string; segment: BindingSegment}[] = [];\n const unsafeInterpolations: UnsafeRunInterpolation[] = [];\n const reservedNames = new Set(params.options.reservedNames ?? []);\n let nextIndex = 0;\n\n for (const segment of params.segments) {\n if (segment.kind === 'literal') {\n const text = params.literalText(segment as Extract<Segment, {readonly kind: 'literal'}>);\n command += text;\n state = scanShellLiteral(text, state);\n continue;\n }\n\n if (!params.isBindingSegment(segment)) continue;\n\n const site = classifyShellSite(state);\n if (site.kind === 'unsafe') {\n unsafeInterpolations.push({\n region: site.region,\n source: segment.expression.source,\n });\n continue;\n }\n\n const name = nextGeneratedName(reservedNames, nextIndex);\n nextIndex = Number(name.slice(generatedNamePrefix.length)) + 1;\n reservedNames.add(name);\n bindings.push({name, segment});\n command += shellReference(name, site);\n }\n\n return {command, bindings, unsafeInterpolations};\n}\n\nfunction nextGeneratedName(reservedNames: ReadonlySet<string>, startIndex: number): string {\n let index = startIndex;\n\n while (true) {\n const name = `${generatedNamePrefix}${index}`;\n if (!shellIdentifierPattern.test(name)) {\n throw new Error(`Generated run env name is not a shell identifier: ${name}`);\n }\n\n if (!reservedNames.has(name)) return name;\n index += 1;\n }\n}\n\nfunction shellReference(name: string, site: Exclude<ShellSiteContext, {readonly kind: 'unsafe'}>) {\n if (site.kind === 'double') return `\\${${name}}`;\n if (site.kind === 'single') return `'\"\\${${name}}\"'`;\n return `\"\\${${name}}\"`;\n}\n"],"names":["classifyShellSite","initialShellScanState","scanShellLiteral","unsafeRunInterpolationErrorCode","generatedNamePrefix","shellIdentifierPattern","UnsafeRunInterpolationError","Error","params","region","code","name","occurrences","source","partial","hoistPlannedRunCommand","result","hoistCommandSegments","segments","field","options","reservedNames","undefined","literalText","segment","value","isBindingSegment","kind","firstUnsafeInterpolation","unsafeInterpolations","command","bindings","state","Set","nextIndex","text","site","push","expression","nextGeneratedName","Number","slice","length","add","shellReference","startIndex","index","test","has"],"mappings":"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"}