@usearazzo/runner 1.0.1-alpha.15 → 1.0.1-alpha.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usearazzo/runner",
3
- "version": "1.0.1-alpha.15",
3
+ "version": "1.0.1-alpha.17",
4
4
  "description": "Runner for Arazzo Workflows.",
5
5
  "keywords": [
6
6
  "arazzo",
@@ -56,7 +56,7 @@
56
56
  "author": "Vladimir Gorej <vladimir.gorej@gmail.com>",
57
57
  "license": "Apache-2.0",
58
58
  "dependencies": {
59
- "@babel/runtime-corejs3": "^8.0.7",
59
+ "@babel/runtime-corejs3": "^8.0.8",
60
60
  "@speclynx/apidom-core": "^6.1.0",
61
61
  "@speclynx/apidom-datamodel": "^6.1.0",
62
62
  "@speclynx/apidom-error": "^6.1.0",
@@ -73,8 +73,8 @@
73
73
  "@swaggerexpert/json-pointer": "^3.0.2",
74
74
  "@swaggerexpert/jsonpath": "^4.0.5",
75
75
  "@swaggerexpert/media-types": "^1.0.1",
76
- "@usearazzo/parser": "1.0.1-alpha.15",
77
- "@usearazzo/resolver": "1.0.1-alpha.15",
76
+ "@usearazzo/parser": "1.0.1-alpha.17",
77
+ "@usearazzo/resolver": "1.0.1-alpha.17",
78
78
  "@xmldom/xmldom": "^0.9.12",
79
79
  "fontoxpath": "^3.34.0",
80
80
  "ramda": "^0.32.0",
@@ -94,5 +94,5 @@
94
94
  "devDependencies": {
95
95
  "swagger-client": "^3.38.4"
96
96
  },
97
- "gitHead": "0afacecfa7179fd95b07a8e4a5194a2d7d1c0687"
97
+ "gitHead": "92ccbcd1dff00a1744e6c0543db9d17ee5a91ef2"
98
98
  }
@@ -4,10 +4,19 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
+ /**
8
+ * A key starting with an `in` value the client builds qualified keys from —
9
+ * the OpenAPI locations, including OpenAPI 2.0's `formData` and `body`. The
10
+ * client qualifies whatever `in` an operation declares, so a non-standard one
11
+ * is not covered.
12
+ */
13
+ const QUALIFIED_KEY = /^(?:path|query|header|cookie|formData|body)\./;
14
+
7
15
  /**
8
16
  * The outcome of claiming a delivery key: `claimed` for a first claim,
9
- * `duplicate` when the same `(name, in)` parameter claims its key again, and
10
- * `collision` when a *different* parameter produces an already-claimed key.
17
+ * `duplicate` when the same `(name, in)` parameter claims its key again,
18
+ * `collision` when a *different* parameter produces an already-claimed key,
19
+ * and `misaddressed` when a bare key has the shape of a qualified one.
11
20
  * @internal
12
21
  */
13
22
 
@@ -47,8 +56,16 @@ exports.default = void 0;
47
56
  * alone identifies the claimant. A bare key and a qualified key sharing one
48
57
  * name are a collision too, even though the keys differ — the client consults
49
58
  * the bare name first for every declared parameter bearing it, so the bare
50
- * entry would silently capture the qualified one. What to do about a
51
- * collision is the caller's policy — the map only reports it.
59
+ * entry would silently capture the qualified one.
60
+ *
61
+ * A bare key that starts with a location the client qualifies keys with
62
+ * (`querystring` named `header.X-Foo`) is misaddressed even when it claims
63
+ * alone: the client matches it as the qualified key of every declared
64
+ * parameter that location and the rest of the name identify, so the value
65
+ * would reach the header `X-Foo` — and `OpenAPIOperationExecutor` reads such
66
+ * a key the same way when it delivers undeclared parameters. What to do about
67
+ * a collision or a misaddressed key is the caller's policy — the map only
68
+ * reports it.
52
69
  *
53
70
  * Diff this against the vendored bundle's lookup when bumping swagger-client.
54
71
  * @internal
@@ -71,10 +88,16 @@ class ParameterDelivery {
71
88
  * Only a `claimed` outcome entitles the caller to {@link ParameterDelivery.set}
72
89
  * the key; a `duplicate` means the same parameter already holds it, and a
73
90
  * `collision` means a different parameter does — on the same key, or across
74
- * a bare/qualified pair sharing the name (see the class doc).
91
+ * a bare/qualified pair sharing the name (see the class doc). A
92
+ * `misaddressed` bare key is never claimed.
75
93
  */
76
94
  claim(location, name) {
77
95
  const key = ParameterDelivery.keyFor(location, name);
96
+ const bare = key === name;
97
+ if (bare && QUALIFIED_KEY.test(name)) return {
98
+ key,
99
+ outcome: 'misaddressed'
100
+ };
78
101
  const claimant = this.#claimedBy.get(key);
79
102
  if (claimant !== undefined) {
80
103
  return {
@@ -82,7 +105,6 @@ class ParameterDelivery {
82
105
  outcome: claimant === location ? 'duplicate' : 'collision'
83
106
  };
84
107
  }
85
- const bare = key === name;
86
108
  if (bare ? this.#qualifiedNames.has(name) : this.#bareNames.has(name)) {
87
109
  return {
88
110
  key,
@@ -1,7 +1,16 @@
1
+ /**
2
+ * A key starting with an `in` value the client builds qualified keys from —
3
+ * the OpenAPI locations, including OpenAPI 2.0's `formData` and `body`. The
4
+ * client qualifies whatever `in` an operation declares, so a non-standard one
5
+ * is not covered.
6
+ */
7
+ const QUALIFIED_KEY = /^(?:path|query|header|cookie|formData|body)\./;
8
+
1
9
  /**
2
10
  * The outcome of claiming a delivery key: `claimed` for a first claim,
3
- * `duplicate` when the same `(name, in)` parameter claims its key again, and
4
- * `collision` when a *different* parameter produces an already-claimed key.
11
+ * `duplicate` when the same `(name, in)` parameter claims its key again,
12
+ * `collision` when a *different* parameter produces an already-claimed key,
13
+ * and `misaddressed` when a bare key has the shape of a qualified one.
5
14
  * @internal
6
15
  */
7
16
 
@@ -41,8 +50,16 @@
41
50
  * alone identifies the claimant. A bare key and a qualified key sharing one
42
51
  * name are a collision too, even though the keys differ — the client consults
43
52
  * the bare name first for every declared parameter bearing it, so the bare
44
- * entry would silently capture the qualified one. What to do about a
45
- * collision is the caller's policy — the map only reports it.
53
+ * entry would silently capture the qualified one.
54
+ *
55
+ * A bare key that starts with a location the client qualifies keys with
56
+ * (`querystring` named `header.X-Foo`) is misaddressed even when it claims
57
+ * alone: the client matches it as the qualified key of every declared
58
+ * parameter that location and the rest of the name identify, so the value
59
+ * would reach the header `X-Foo` — and `OpenAPIOperationExecutor` reads such
60
+ * a key the same way when it delivers undeclared parameters. What to do about
61
+ * a collision or a misaddressed key is the caller's policy — the map only
62
+ * reports it.
46
63
  *
47
64
  * Diff this against the vendored bundle's lookup when bumping swagger-client.
48
65
  * @internal
@@ -65,10 +82,16 @@ class ParameterDelivery {
65
82
  * Only a `claimed` outcome entitles the caller to {@link ParameterDelivery.set}
66
83
  * the key; a `duplicate` means the same parameter already holds it, and a
67
84
  * `collision` means a different parameter does — on the same key, or across
68
- * a bare/qualified pair sharing the name (see the class doc).
85
+ * a bare/qualified pair sharing the name (see the class doc). A
86
+ * `misaddressed` bare key is never claimed.
69
87
  */
70
88
  claim(location, name) {
71
89
  const key = ParameterDelivery.keyFor(location, name);
90
+ const bare = key === name;
91
+ if (bare && QUALIFIED_KEY.test(name)) return {
92
+ key,
93
+ outcome: 'misaddressed'
94
+ };
72
95
  const claimant = this.#claimedBy.get(key);
73
96
  if (claimant !== undefined) {
74
97
  return {
@@ -76,7 +99,6 @@ class ParameterDelivery {
76
99
  outcome: claimant === location ? 'duplicate' : 'collision'
77
100
  };
78
101
  }
79
- const bare = key === name;
80
102
  if (bare ? this.#qualifiedNames.has(name) : this.#bareNames.has(name)) {
81
103
  return {
82
104
  key,
@@ -159,23 +159,32 @@ class ArazzoWorkflowNormalizer {
159
159
  }
160
160
 
161
161
  /**
162
- * Inherits the workflow's `successActions` / `failureActions` into each step
163
- * that declares no `onSuccess` / `onFailure` of its own.
162
+ * Merges the workflow's `successActions` / `failureActions` into each step's
163
+ * `onSuccess` / `onFailure`.
164
164
  *
165
- * Per Arazzo 1.0.1 both lists are "applicable for all steps described under
166
- * this workflow", and a step's own list **overrides** the corresponding
167
- * workflow one — wholesale, with no per-action merge, which is where this
168
- * differs from the parameters above. Success and failure fall back
169
- * independently: a step may override only its `onFailure` and still inherit
170
- * the workflow's `successActions`.
165
+ * Per Arazzo both lists are "applicable for all steps described under this
166
+ * workflow" and "can be overridden at the step level but cannot be removed
167
+ * there". The required action `name` is what makes both halves hold: a
168
+ * step's action replaces the workflow action of the same `name`, and every
169
+ * workflow action the step does not name still applies. The effective list is
170
+ * the step's own actions in order, then the workflow actions it did not
171
+ * override, in theirs — order matters, as selection is first-match-wins on
172
+ * `criteria`. So a step with no list, or with `[]`, gets every workflow
173
+ * action. The step's own list is kept exactly as written, even a duplicate
174
+ * `name` in it, which the validator reports: inheritance only adds to it.
175
+ * Within the workflow's list the first action with a given `name` wins.
176
+ * Success and failure merge independently.
171
177
  *
172
- * Presence is tested with `hasKey`, not truthiness: a step declaring an empty
173
- * list (`onSuccess: []`) has *overridden* the default with an empty set of
174
- * actions, not asked for one — it is skipped, as is a step whose `onSuccess`
175
- * is present but not a list, for the same reason the parameters pass leaves a
176
- * malformed list alone. Testing the key is also what makes the pass
177
- * idempotent: after the first run the step has it, so a workflow reached again
178
- * through the registry cache is skipped.
178
+ * An entry without a readable `name` (an unresolved Reusable Object, a
179
+ * scalar someone put in the list) neither overrides nor is overridden: it
180
+ * keeps its place, and is added only if that same element is not already in
181
+ * the list. A step whose `onSuccess` is present but not a list is left
182
+ * alone, for the same reason the parameters pass leaves a malformed list
183
+ * alone — overwriting it would erase what makes the document invalid.
184
+ *
185
+ * The pass is idempotent, so a workflow reached again through the registry
186
+ * cache is merged into once: on a second pass every inherited action is
187
+ * already in the step's list, under its own `name` or as the same element.
179
188
  *
180
189
  * Unlike parameters there is no step-kind filter — an action names a
181
190
  * transition within the workflow, which is as meaningful for a step targeting
@@ -202,13 +211,34 @@ class ArazzoWorkflowNormalizer {
202
211
  if (!inheritSuccess && !inheritFailure) return;
203
212
  for (const step of workflow.steps) {
204
213
  if (!(0, _apidomNsArazzo.isStepElement)(step)) continue;
205
- if (inheritSuccess && !step.hasKey('onSuccess')) {
206
- step.onSuccess = new _apidomNsArazzo.StepOnSuccessElement([...successActions]);
214
+ if (inheritSuccess && (!step.hasKey('onSuccess') || (0, _apidomDatamodel.isArrayElement)(step.onSuccess))) {
215
+ step.onSuccess = new _apidomNsArazzo.StepOnSuccessElement(ArazzoWorkflowNormalizer.#mergeActions([...(step.onSuccess ?? [])], [...successActions]));
216
+ }
217
+ if (inheritFailure && (!step.hasKey('onFailure') || (0, _apidomDatamodel.isArrayElement)(step.onFailure))) {
218
+ step.onFailure = new _apidomNsArazzo.StepOnFailureElement(ArazzoWorkflowNormalizer.#mergeActions([...(step.onFailure ?? [])], [...failureActions]));
207
219
  }
208
- if (inheritFailure && !step.hasKey('onFailure')) {
209
- step.onFailure = new _apidomNsArazzo.StepOnFailureElement([...failureActions]);
220
+ }
221
+ }
222
+
223
+ /**
224
+ * The step's actions as written, followed by each workflow action whose
225
+ * `name` neither the step nor an earlier workflow action carries; a nameless
226
+ * workflow entry is added unless that same element is already present.
227
+ */
228
+ static #mergeActions(own, inherited) {
229
+ const nameOf = action => (0, _apidomDatamodel.isObjectElement)(action) ? (0, _apidomCore.toValue)(action.get('name')) : undefined;
230
+ const names = new Set(own.map(nameOf));
231
+ const merged = [...own];
232
+ for (const action of inherited) {
233
+ const name = nameOf(action);
234
+ if (typeof name !== 'string') {
235
+ if (!merged.includes(action)) merged.push(action);
236
+ } else if (!names.has(name)) {
237
+ names.add(name);
238
+ merged.push(action);
210
239
  }
211
240
  }
241
+ return merged;
212
242
  }
213
243
  }
214
244
  var _default = exports.default = ArazzoWorkflowNormalizer;
@@ -1,7 +1,7 @@
1
1
  import { uniqWith } from 'ramda';
2
2
  import { isParameterElement, isStepElement, StepParametersElement, StepOnSuccessElement, StepOnFailureElement } from '@speclynx/apidom-ns-arazzo-1';
3
3
  import { toValue } from '@speclynx/apidom-core';
4
- import { isArrayElement, isStringElement } from '@speclynx/apidom-datamodel';
4
+ import { isArrayElement, isObjectElement, isStringElement } from '@speclynx/apidom-datamodel';
5
5
  import { dereferenceArazzoElement, defaultDereferenceArazzoOptions } from '@usearazzo/resolver';
6
6
  import { mergeOptions } from '@speclynx/apidom-reference/configuration/empty';
7
7
  import ParameterIdentity from "../document/ParameterIdentity.mjs";
@@ -151,23 +151,32 @@ class ArazzoWorkflowNormalizer {
151
151
  }
152
152
 
153
153
  /**
154
- * Inherits the workflow's `successActions` / `failureActions` into each step
155
- * that declares no `onSuccess` / `onFailure` of its own.
154
+ * Merges the workflow's `successActions` / `failureActions` into each step's
155
+ * `onSuccess` / `onFailure`.
156
156
  *
157
- * Per Arazzo 1.0.1 both lists are "applicable for all steps described under
158
- * this workflow", and a step's own list **overrides** the corresponding
159
- * workflow one — wholesale, with no per-action merge, which is where this
160
- * differs from the parameters above. Success and failure fall back
161
- * independently: a step may override only its `onFailure` and still inherit
162
- * the workflow's `successActions`.
157
+ * Per Arazzo both lists are "applicable for all steps described under this
158
+ * workflow" and "can be overridden at the step level but cannot be removed
159
+ * there". The required action `name` is what makes both halves hold: a
160
+ * step's action replaces the workflow action of the same `name`, and every
161
+ * workflow action the step does not name still applies. The effective list is
162
+ * the step's own actions in order, then the workflow actions it did not
163
+ * override, in theirs — order matters, as selection is first-match-wins on
164
+ * `criteria`. So a step with no list, or with `[]`, gets every workflow
165
+ * action. The step's own list is kept exactly as written, even a duplicate
166
+ * `name` in it, which the validator reports: inheritance only adds to it.
167
+ * Within the workflow's list the first action with a given `name` wins.
168
+ * Success and failure merge independently.
163
169
  *
164
- * Presence is tested with `hasKey`, not truthiness: a step declaring an empty
165
- * list (`onSuccess: []`) has *overridden* the default with an empty set of
166
- * actions, not asked for one — it is skipped, as is a step whose `onSuccess`
167
- * is present but not a list, for the same reason the parameters pass leaves a
168
- * malformed list alone. Testing the key is also what makes the pass
169
- * idempotent: after the first run the step has it, so a workflow reached again
170
- * through the registry cache is skipped.
170
+ * An entry without a readable `name` (an unresolved Reusable Object, a
171
+ * scalar someone put in the list) neither overrides nor is overridden: it
172
+ * keeps its place, and is added only if that same element is not already in
173
+ * the list. A step whose `onSuccess` is present but not a list is left
174
+ * alone, for the same reason the parameters pass leaves a malformed list
175
+ * alone — overwriting it would erase what makes the document invalid.
176
+ *
177
+ * The pass is idempotent, so a workflow reached again through the registry
178
+ * cache is merged into once: on a second pass every inherited action is
179
+ * already in the step's list, under its own `name` or as the same element.
171
180
  *
172
181
  * Unlike parameters there is no step-kind filter — an action names a
173
182
  * transition within the workflow, which is as meaningful for a step targeting
@@ -194,13 +203,34 @@ class ArazzoWorkflowNormalizer {
194
203
  if (!inheritSuccess && !inheritFailure) return;
195
204
  for (const step of workflow.steps) {
196
205
  if (!isStepElement(step)) continue;
197
- if (inheritSuccess && !step.hasKey('onSuccess')) {
198
- step.onSuccess = new StepOnSuccessElement([...successActions]);
206
+ if (inheritSuccess && (!step.hasKey('onSuccess') || isArrayElement(step.onSuccess))) {
207
+ step.onSuccess = new StepOnSuccessElement(ArazzoWorkflowNormalizer.#mergeActions([...(step.onSuccess ?? [])], [...successActions]));
208
+ }
209
+ if (inheritFailure && (!step.hasKey('onFailure') || isArrayElement(step.onFailure))) {
210
+ step.onFailure = new StepOnFailureElement(ArazzoWorkflowNormalizer.#mergeActions([...(step.onFailure ?? [])], [...failureActions]));
199
211
  }
200
- if (inheritFailure && !step.hasKey('onFailure')) {
201
- step.onFailure = new StepOnFailureElement([...failureActions]);
212
+ }
213
+ }
214
+
215
+ /**
216
+ * The step's actions as written, followed by each workflow action whose
217
+ * `name` neither the step nor an earlier workflow action carries; a nameless
218
+ * workflow entry is added unless that same element is already present.
219
+ */
220
+ static #mergeActions(own, inherited) {
221
+ const nameOf = action => isObjectElement(action) ? toValue(action.get('name')) : undefined;
222
+ const names = new Set(own.map(nameOf));
223
+ const merged = [...own];
224
+ for (const action of inherited) {
225
+ const name = nameOf(action);
226
+ if (typeof name !== 'string') {
227
+ if (!merged.includes(action)) merged.push(action);
228
+ } else if (!names.has(name)) {
229
+ names.add(name);
230
+ merged.push(action);
202
231
  }
203
232
  }
233
+ return merged;
204
234
  }
205
235
  }
206
236
  export default ArazzoWorkflowNormalizer;
@@ -41,12 +41,15 @@ var _StepParameterResolver = _interopRequireDefault(require("./StepParameterReso
41
41
  * against an OpenAPI 2.0 operation, bypassing the step's `requestBody`, while
42
42
  * an unknown location reaches nothing at all. And two *different* parameters the
43
43
  * map reports as colliding cannot both be delivered, so a collision throws
44
- * rather than silently dropping one — whether they collide on one key (the
45
- * scheme is not injective: a `querystring` parameter named `header.token` and
46
- * a header parameter named `token` both produce `header.token`) or across a
47
- * bare/qualified pair sharing a name (a `querystring` `token` next to a
48
- * header `token`), where the client would consult the bare name first and
49
- * silently capture the qualified value.
44
+ * rather than silently dropping one — a bare/qualified pair sharing a name (a
45
+ * `querystring` `token` next to a header `token`), where the client would
46
+ * consult the bare name first and silently capture the qualified value. A
47
+ * `querystring` parameter whose name starts with a location the client
48
+ * qualifies keys with (`header.X-Foo`) throws even alone: the client would
49
+ * match its bare key as the qualified key of a declared header `X-Foo` and
50
+ * deliver it there. The same check rejects it, in either order, next to a
51
+ * header parameter `X-Foo` producing that very key — the scheme is not
52
+ * injective, so the two could otherwise collide on one key.
50
53
  * @public
51
54
  */
52
55
  class OpenAPIOperationParameterResolver extends _StepParameterResolver.default {
@@ -113,8 +116,9 @@ class OpenAPIOperationParameterResolver extends _StepParameterResolver.default {
113
116
  } = delivery.claim(location, name);
114
117
  // the same parameter declared again: the earlier, more specific one won
115
118
  if (outcome === 'duplicate') continue;
116
- if (outcome === 'collision') {
117
- throw new _ResolverError.default(`Parameter "${name}" (in: ${location}) collides with another parameter on the ` + `delivery key "${key}" and cannot be delivered unambiguously`, {
119
+ if (outcome !== 'claimed') {
120
+ const why = outcome === 'collision' ? `collides with another parameter on the delivery key "${key}"` : 'has a name the client reads as the delivery key of another location';
121
+ throw new _ResolverError.default(`Parameter "${name}" (in: ${location}) ${why} and cannot be delivered unambiguously`, {
118
122
  ...scope,
119
123
  target: name,
120
124
  reason: 'ambiguous-delivery'
@@ -34,12 +34,15 @@ import StepParameterResolver from "./StepParameterResolver.mjs";
34
34
  * against an OpenAPI 2.0 operation, bypassing the step's `requestBody`, while
35
35
  * an unknown location reaches nothing at all. And two *different* parameters the
36
36
  * map reports as colliding cannot both be delivered, so a collision throws
37
- * rather than silently dropping one — whether they collide on one key (the
38
- * scheme is not injective: a `querystring` parameter named `header.token` and
39
- * a header parameter named `token` both produce `header.token`) or across a
40
- * bare/qualified pair sharing a name (a `querystring` `token` next to a
41
- * header `token`), where the client would consult the bare name first and
42
- * silently capture the qualified value.
37
+ * rather than silently dropping one — a bare/qualified pair sharing a name (a
38
+ * `querystring` `token` next to a header `token`), where the client would
39
+ * consult the bare name first and silently capture the qualified value. A
40
+ * `querystring` parameter whose name starts with a location the client
41
+ * qualifies keys with (`header.X-Foo`) throws even alone: the client would
42
+ * match its bare key as the qualified key of a declared header `X-Foo` and
43
+ * deliver it there. The same check rejects it, in either order, next to a
44
+ * header parameter `X-Foo` producing that very key — the scheme is not
45
+ * injective, so the two could otherwise collide on one key.
43
46
  * @public
44
47
  */
45
48
  class OpenAPIOperationParameterResolver extends StepParameterResolver {
@@ -106,8 +109,9 @@ class OpenAPIOperationParameterResolver extends StepParameterResolver {
106
109
  } = delivery.claim(location, name);
107
110
  // the same parameter declared again: the earlier, more specific one won
108
111
  if (outcome === 'duplicate') continue;
109
- if (outcome === 'collision') {
110
- throw new ResolverError(`Parameter "${name}" (in: ${location}) collides with another parameter on the ` + `delivery key "${key}" and cannot be delivered unambiguously`, {
112
+ if (outcome !== 'claimed') {
113
+ const why = outcome === 'collision' ? `collides with another parameter on the delivery key "${key}"` : 'has a name the client reads as the delivery key of another location';
114
+ throw new ResolverError(`Parameter "${name}" (in: ${location}) ${why} and cannot be delivered unambiguously`, {
111
115
  ...scope,
112
116
  target: name,
113
117
  reason: 'ambiguous-delivery'
package/types/runner.d.ts CHANGED
@@ -1202,12 +1202,15 @@ export declare interface OpenAPIOperationNormalizerOptions {
1202
1202
  * against an OpenAPI 2.0 operation, bypassing the step's `requestBody`, while
1203
1203
  * an unknown location reaches nothing at all. And two *different* parameters the
1204
1204
  * map reports as colliding cannot both be delivered, so a collision throws
1205
- * rather than silently dropping one — whether they collide on one key (the
1206
- * scheme is not injective: a `querystring` parameter named `header.token` and
1207
- * a header parameter named `token` both produce `header.token`) or across a
1208
- * bare/qualified pair sharing a name (a `querystring` `token` next to a
1209
- * header `token`), where the client would consult the bare name first and
1210
- * silently capture the qualified value.
1205
+ * rather than silently dropping one — a bare/qualified pair sharing a name (a
1206
+ * `querystring` `token` next to a header `token`), where the client would
1207
+ * consult the bare name first and silently capture the qualified value. A
1208
+ * `querystring` parameter whose name starts with a location the client
1209
+ * qualifies keys with (`header.X-Foo`) throws even alone: the client would
1210
+ * match its bare key as the qualified key of a declared header `X-Foo` and
1211
+ * deliver it there. The same check rejects it, in either order, next to a
1212
+ * header parameter `X-Foo` producing that very key — the scheme is not
1213
+ * injective, so the two could otherwise collide on one key.
1211
1214
  * @public
1212
1215
  */
1213
1216
  export declare class OpenAPIOperationParameterResolver extends StepParameterResolver {