orbit-code-ai 0.1.37 → 0.1.39

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.
@@ -1,14 +1,14 @@
1
1
  ---
2
2
  name: apic-api
3
- description: Generate a complete IBM API Connect (APIC) API definition for the DataPower API Gateway — full OpenAPI 2.0 (or 3.0) YAML including the x-ibm-configuration assembly (middleware logging, JWT validate, token-expiration switch, ESB response envelope, and catch handlers). Standard NHC middleware is baked in with opt-out flags.
3
+ description: Generate a complete IBM API Connect (APIC) API definition for the DataPower API Gateway — full OpenAPI 2.0 (or 3.0) YAML including the x-ibm-configuration assembly (middleware logging, JWT validate, token-expiration switch, ESB response envelope, and catch handlers). Standard middleware is baked in with opt-out flags.
4
4
  trigger: /apic-api
5
5
  ---
6
6
 
7
7
  # /apic-api
8
8
 
9
9
  Generate a full APIC API definition (the `*.yaml` you import into API Connect / publish to the
10
- DataPower API Gateway). Output mirrors the house template used by the live AhelApp / Muamalaty /
11
- AmerApp APIs: a Swagger/OpenAPI contract **plus** the complete `x-ibm-configuration` assembly.
10
+ DataPower API Gateway). Output mirrors the house template, illustrated by three reference shapes (SamplePost / SampleFwd /
11
+ SampleDetect): a Swagger/OpenAPI contract **plus** the complete `x-ibm-configuration` assembly.
12
12
 
13
13
  ## Usage
14
14
 
@@ -18,25 +18,33 @@ AmerApp APIs: a Swagger/OpenAPI contract **plus** the complete `x-ibm-configurat
18
18
  Flags:
19
19
  --openapi 2.0|3.0 target spec version — USER'S CHOICE. If omitted, ask the user which one
20
20
  they want before generating. Orbit does not assume a version.
21
+ --pattern P integration pattern (see "Two integration patterns"):
22
+ backend (default) = APIC calls a raw backend and WRAPS the response in the
23
+ ESB {Header,Body} envelope.
24
+ wrapper = APIC publishes an existing integration service (ACE OR
25
+ webMethods) that ALREADY returns the ESB envelope, so
26
+ APIC is a thin proxy and does NOT re-wrap (implies
27
+ --no-envelope).
28
+ If unspecified, ASK which pattern before generating.
21
29
  --crypto <name> jws-crypto object for JWT validation (default: <appsegment>-crypto-object)
22
- --backend-auth <name> APIC variable injected as backend auth header (e.g. servicenow-auth)
30
+ --backend-auth <name> APIC variable injected as backend auth header (e.g. backend-auth)
23
31
  --jwt force JWT on (skip the prompt); --no-jwt forces it off. If neither is
24
32
  given, ASK the user whether JWT validation is required (see Clarify step).
25
33
  --no-jwt omit jwt-validate + Check Expiration + 400 throw + ExpiredToken catch
26
34
  (no token enforcement)
27
- --no-logging omit the middleware UpsertMDLogQ logging invoke (AmerApp-style)
35
+ --no-logging omit the middleware UpsertMDLogQ logging invoke (SampleDetect-style)
28
36
  --no-envelope return the raw backend body instead of the {Header,Body} ESB envelope
29
37
  --no-cors disable CORS
30
38
 
31
39
  Backend-call tuning (all optional — infer sensible values from the prompt if not given):
32
40
  --backend-verb V backend invoke verb: GET|POST|keep (default = API verb; "keep" forwards the
33
- caller's verb, AmerApp-style)
41
+ caller's verb, SampleDetect-style)
34
42
  --backend-type T backend response handling: json|detect (default json; "detect" =
35
- content-type based, used by AmerApp)
43
+ content-type based, used by SampleDetect)
36
44
  --invoke-version V backend invoke policy version: 2.2.0|2.3.0 (default 2.2.0; 2.3.0 adds
37
45
  stop-on-error + graphql-send-type)
38
46
  --backend-auth-header H header the --backend-auth value is set on (default Authorization;
39
- Muamalaty uses "Token")
47
+ SampleFwd uses "Token")
40
48
  --backend-headers k=v,... extra STATIC headers set before the backend call
41
49
  (e.g. REST-Framework-Version=4)
42
50
  --pass-headers a,b,... headers FORWARDED to the backend → invoke header-control allowlist
@@ -45,37 +53,43 @@ Flags:
45
53
  params. CRITICAL: every query param the backend needs must be listed, or the
46
54
  gateway strips it.
47
55
  --parse P backend parse: json (inline document_type json, default) | default
48
- (apic-default-parsesettings, AmerApp-style)
49
- --use-content-type add use-content-type: true to the backend parse (Muamalaty/AmerApp)
50
- --envelope-placement P where Prepare Response Header goes: in-case (default, Ahel/AmerApp) |
51
- top-level (after the switch, Muamalaty)
56
+ (apic-default-parsesettings, SampleDetect-style)
57
+ --use-content-type add use-content-type: true to the backend parse (SampleFwd/SampleDetect)
58
+ --envelope-placement P where Prepare Response Header goes: in-case (default, SamplePost/SampleDetect) |
59
+ top-level (after the switch, SampleFwd)
52
60
 
53
61
  Examples:
54
- /apic-api AmerAppGetUserInfo GET /v1/AmerApp \
55
- backend $(erp-base-url)/hcmRestApi/resources/latest/workers?onlyData=true; query param expand
56
- /apic-api AhelUpdateCustomer POST /v1/AhelApp \
57
- backend $(servicenow-url)api/.../UpdateCustomerPersonalInformation; --backend-auth servicenow-auth; \
62
+ /apic-api SampleGetUserInfo GET /v1/SampleApp \
63
+ backend $(backend-base-url)/api/resource/workers?onlyData=true; query param expand
64
+ /apic-api SampleUpdateCustomer POST /v1/SampleApp \
65
+ backend $(backend-base-url)/api/UpdateCustomer; --backend-auth backend-auth; \
58
66
  body fields: customerSysId,email,idNumber,name,avatar,gender,dateOfBirth,attachment_records
59
67
  ```
60
68
 
61
69
  ## Variables to Derive
62
70
 
63
71
  From the inputs:
64
- - `{ApiTitle}` = Title Case of ApiName, e.g. `AmerApp Get User Info`
65
- - `{x-ibm-name}` = kebab-case of ApiName, e.g. `amerapp-get-userinfo` (also the file stem)
66
- - `{AppSegment}` = the app portion of basePath after `/v1/`, e.g. `AmerApp`
67
- - `{appsegmentlower}` = lowercase AppSegment, e.g. `amerapp`
72
+ - `{ApiTitle}` = Title Case of ApiName, e.g. `SampleDetect Get User Info`
73
+ - `{x-ibm-name}` = kebab-case of ApiName, e.g. `sampledetect-get-userinfo` (also the file stem)
74
+ - `{AppSegment}` = the app portion of basePath after `/v1/`, e.g. `SampleDetect`
75
+ - `{appsegmentlower}` = lowercase AppSegment, e.g. `sampledetect`
68
76
  - `{version}` = `1.0.0` unless supplied
69
- - `{operation-path}` = the API's own path, **derived from the API name** (PascalCase, leading slash):
70
- `Get Customer Balance` `/GetCustomerBalance`, like `AmerApp Get User Info` `/GetUserInfo`.
71
- **NEVER** take it from the backend target-url's path (the backend path is unrelated to the
72
- exposed API path). Use a supplied path only if the user gives one explicitly.
77
+ - `{operation-path}` = the API's own exposed path.
78
+ - **If the user supplies an explicit path use it VERBATIM, exact casing, no re-derivation.**
79
+ Any of `path: /getCommodities`, `exposed path /getCommodities`, or a gateway path like
80
+ `commodity/api/v1.0/getCommodities` (→ take the segment after basePath: `/getCommodities`) counts
81
+ as explicit. A supplied `/getCommodities` must NOT become `/GetCommodities`.
82
+ - Only when NO path is supplied, derive it from the API name (PascalCase, leading slash):
83
+ `Get Customer Balance` → `/GetCustomerBalance`.
84
+ - **NEVER** take it from the backend target-url's path (the backend path is unrelated to the
85
+ exposed API path) — except the explicit-gateway-path case above, where the exposed segment is
86
+ stated by the user.
73
87
  - `{verb}` = GET or POST (lowercase in `paths`)
74
88
  - `{crypto-object}` = `--crypto` or `{appsegmentlower}-crypto-object`
75
89
  - `{backend-target-url}` = backend URL from the description (keep `$(...)` APIC vars verbatim,
76
90
  including claim injections like `?userEmail=$(decoded.claims.EmailAddress)`)
77
91
  - `{backend-auth-var}` = `--backend-auth` value (only emitted if provided)
78
- - `{backend-auth-header}` = `--backend-auth-header` or `Authorization` (Muamalaty: `Token`)
92
+ - `{backend-auth-header}` = `--backend-auth-header` or `Authorization` (SampleFwd: `Token`)
79
93
  - `{backend-verb}` = `--backend-verb` or the API verb (may be `keep` — forwards caller's verb)
80
94
  - `{backend-type}` = `--backend-type` or `json` (or `detect`)
81
95
  - `{query}` = list of backend query params (from `--query` or inferred from the backend URL / prompt)
@@ -93,13 +107,18 @@ in a single batched follow-up** (alongside the 2.0/3.0 question). Do NOT invent
93
107
  values for these:
94
108
 
95
109
  - **OpenAPI version** — 2.0 or 3.0 (always ask if unspecified).
110
+ - **Integration pattern** — is APIC calling a **raw backend** (it must wrap the response in the ESB
111
+ envelope → `backend`), or **publishing an existing integration service (ACE or webMethods)** that
112
+ already returns the ESB envelope (APIC is a thin proxy, no re-wrap → `wrapper`)? Ask unless
113
+ `--pattern` is given or the prompt makes it clear (e.g. "expose our ACE flow", "wrap the webMethods
114
+ service", "the backend already returns the envelope").
96
115
  - **JWT validation** — **ASK whether this API requires JWT validation** unless `--jwt`/`--no-jwt`
97
116
  was passed or the prompt clearly states it. JWT is NOT assumed on. If **yes**, include the JWT
98
117
  policies and ask for the crypto object (below). If **no**, omit JWT entirely (see the
99
118
  "No-JWT shape" section) and do not ask for a crypto object.
100
- - **Channel / app + basePath** — e.g. `/v1/AmerApp`. The app segment also drives naming. There is
119
+ - **Channel / app + basePath** — e.g. `/v1/SampleDetect`. The app segment also drives naming. There is
101
120
  no way to infer this from the operation name; ask (offer the known channels if helpful).
102
- - **JWT crypto object** — e.g. `$(amerapp-crypto-object)`. Tied to the channel, not the operation.
121
+ - **JWT crypto object** — e.g. `$(sampledetect-crypto-object)`. Tied to the channel, not the operation.
103
122
  **Only ask this when JWT is enabled.** Do not derive it from the API name.
104
123
  - **Backend auth** — the APIC variable and the header it goes on (`Authorization` vs `Token`), if
105
124
  the backend needs auth. Ask only if the prompt implies the backend is protected.
@@ -108,6 +127,58 @@ If the user prefers not to answer, fall back to clearly-marked placeholders
108
127
  (`$(CHANGEME-crypto-object)`, `basePath: /v1/CHANGEME`) and list every placeholder in the summary —
109
128
  never a guess that looks real.
110
129
 
130
+ ## Two integration patterns
131
+
132
+ Every APIC API generated here is one of two shapes. Pick from `--pattern`, the prompt, or the
133
+ Clarify answer.
134
+
135
+ **`backend` (default) — APIC → raw backend.** APIC calls a backend service that returns a *raw*
136
+ body, so APIC is responsible for the ESB contract: it runs the full middleware and **wraps the
137
+ backend response** in the `{Header, Body}` envelope via the `Prepare Response Header` gatewayscript.
138
+ This is the skeleton exactly as written below.
139
+
140
+ **`wrapper` — APIC → existing integration service (TRUE thin proxy).** The backend *is* an existing
141
+ integration service — **ACE or webMethods** — that already owns the response contract (envelope,
142
+ business errors, correlation). APIC adds only gateway concerns (client-id/secret, optional JWT,
143
+ optional logging) and forwards the service's request/response **unchanged**. The pattern is identical
144
+ whichever platform sits behind it; only `{backend-target-url}` differs.
145
+
146
+ A thin wrapper must **NOT stamp house-specific conventions** onto a service that has its own. So,
147
+ unlike `backend`, wrapper mode drops all of these:
148
+ - **No `Prepare Response Header`** — do not re-wrap the success body (report "ESB envelope: off
149
+ (service-provided)").
150
+ - **No RefId-enforcing `Prepare Request`.** The frozen Prepare Request rejects on a missing `RefId`
151
+ header — that is one house's standard, not universal, and would reject a client that uses a
152
+ different correlation header. Omit it. If the spec names a correlation header (e.g. `X-Request-Id`),
153
+ optionally capture it with a **non-rejecting** `set-variable`; never `context.reject(...)`.
154
+ - **No ESB `{Header, Body}` error envelope in `catch`.** The frozen `DeFaultCatch` writes the house
155
+ envelope and depends on `context.customheaders.*` that a wrapper never sets. Use the **neutral
156
+ catch** below (surfaces the gateway error plainly). Business errors are unaffected — they come back
157
+ as a normal response body from the wrapped service.
158
+ - **Declare the spec's ACTUAL inbound headers** in `paths` (e.g. `X-Request-Id`), **not** the house
159
+ `RefId` / `CallerReqTime`.
160
+ - `{backend-target-url}` is the upstream service endpoint (an internal `$(...)` base-url variable),
161
+ not an external vendor URL.
162
+ - Keep security (client-id/secret); apply JWT / MW logging only as the flags/Clarify decide.
163
+
164
+ **For the actual YAML to emit in wrapper mode, use the complete standalone template in the
165
+ "## Wrapper skeleton (COMPLETE …)" section** — copy that entire file and fill the slots. Do NOT
166
+ assemble from the backend "## OpenAPI 2.0 skeleton"; the wrapper skeleton is self-contained and
167
+ already excludes the `Prepare Request`, `map`, `Prepare Response Header`, and ESB catch.
168
+
169
+ ## Configurable middleware / backend variables
170
+
171
+ The `$(...)` names below are **placeholders you map to your gateway's real APIC variables** — they
172
+ contain no organization-specific names:
173
+ - `$(mw-auth)` and `$(mw-log-base-url)` — the standard middleware logging auth + base URL. Set these
174
+ to whatever your DataPower catalog actually calls them. **Deploy-critical:** if the names don't
175
+ match real gateway variables, logging silently fails.
176
+ - `$(backend-auth)` and `$(backend-base-url)` — the backend's auth variable and base URL.
177
+ - `$({crypto-object})` — the JWT crypto object (only when JWT is on).
178
+
179
+ Never invent real-looking values for these; when unknown, keep the placeholder and list it in the
180
+ summary (see the Clarify rules).
181
+
111
182
  ## Generation rules
112
183
 
113
184
  1. **The spec version is the user's choice — Orbit supports both 2.0 and 3.0 equally.** Never
@@ -119,13 +190,27 @@ never a guess that looks real.
119
190
  2b. **JWT is optional and not assumed.** Decide JWT on/off from `--jwt`/`--no-jwt`, an explicit
120
191
  statement in the prompt, or the clarify answer. With JWT **off**, build the simpler "No-JWT shape"
121
192
  (no jwt-validate, no Check Expiration, no switch, no ExpiredToken catch) — see that section.
122
- 3. **Paste the frozen gatewayscript verbatim.** The JS strings below must be byte-exact — DataPower
123
- rejects malformed assembly. Do not "clean up" or reformat them.
124
- 4. **GET vs POST**: GET query/header params, no request `map`, no `definitions`. POST with body
125
- fields add a request `map` policy + a `Request` definition (AhelApp pattern).
193
+ 2c. **WRAPPER MODE IS A HARD OVERRIDE obey before anything below.** When `--pattern wrapper`, the
194
+ assembly is the **"Thin-wrapper assembly"** block (in "Two integration patterns") emit THAT,
195
+ not the main skeleton. Regardless of any "frozen/verbatim" rule below, in wrapper mode you MUST
196
+ **NOT emit** any of the following (they belong to `backend` only):
197
+ - ❌ the `Prepare Request` gatewayscript (the RefId `context.reject` guard) — omit entirely;
198
+ - ❌ the ESB `{Header, Body}` `DeFaultCatch` — use the **neutral catch** (`{code, message}`) instead;
199
+ - ❌ the `Prepare Response Header` gatewayscript — never re-wrap;
200
+ - ❌ the `RefId` / `CallerReqTime` path-level header params — declare the spec's real headers instead;
201
+ - ❌ any request `map` — a wrapper forwards the body **as-is** (no identity map, even for POST).
202
+ The frozen fragments' "paste verbatim" only means: IF a fragment is emitted, it is byte-exact. It
203
+ does NOT mean every fragment must appear. Wrapper mode emits fewer fragments — that is correct.
204
+ 3. **Paste the frozen gatewayscript verbatim** (in the `backend` pattern). The JS strings below must
205
+ be byte-exact — DataPower rejects malformed assembly. Do not "clean up" or reformat them. (Wrapper
206
+ mode omits several of them — see rule 2c.)
207
+ 4. **GET vs POST** (`backend` pattern): GET → query/header params, no request `map`, no `definitions`.
208
+ POST with body fields → add a request `map` policy + a `Request` definition (SamplePost pattern).
209
+ **Wrapper mode: NEVER add a request `map`** (the body is forwarded unchanged); still emit the
210
+ POST `definitions/Request` for the contract, and the leading `parse`.
126
211
  5. Respect opt-out flags by omitting the corresponding policy (see annotations in the skeleton).
127
212
  6. **Preserve every `$(...)` APIC variable reference exactly** — never strip the wrapper. In
128
- particular `jws-crypto` MUST be `$({crypto-object})` (e.g. `$(amerapp-crypto-object)`), not the
213
+ particular `jws-crypto` MUST be `$({crypto-object})` (e.g. `$(sampledetect-crypto-object)`), not the
129
214
  bare name. A bare value is treated by the gateway as a literal string, not a variable, and breaks
130
215
  JWT validation. Same for `target-url`, backend auth values, and any `$(...)` in the fragments.
131
216
  7. **Backend `parameter-control` allowlist MUST list every backend query param.** An empty allowlist
@@ -143,7 +228,7 @@ never a guess that looks real.
143
228
  10. **Do not hand-append allowlisted query params to the backend `target-url`.** Params listed in the
144
229
  invoke `parameter-control` allowlist are forwarded automatically. Only manually append values
145
230
  that are NOT request params — i.e. injected claims like `?userEmail=$(decoded.claims.EmailAddress)`
146
- (Muamalaty) or `&q=...$(decoded.claims.EmailAddress)` (AmerApp). Appending
231
+ (SampleFwd) or `&q=...$(decoded.claims.EmailAddress)` (SampleDetect). Appending
147
232
  `?accountId=$(request.parameters.accountId)` for an already-allowlisted `accountId` is wrong.
148
233
  11. **Reproduce every gatewayscript `source` character-for-character.** Do not strip comments, blank
149
234
  lines, or re-indent. The single-line quoted form (`"...\n..."`) is canonical and must be copied
@@ -153,7 +238,14 @@ never a guess that looks real.
153
238
 
154
239
  ## OpenAPI 2.0 skeleton
155
240
 
156
- Assemble the file in this order. Fill `{slots}`; paste frozen fragments unchanged.
241
+ > **`--pattern wrapper`: DO NOT USE THIS SKELETON AT ALL.** Skip straight to the **"## Wrapper
242
+ > skeleton (COMPLETE …)"** section below and emit that entire file instead. It is a complete,
243
+ > standalone document — there is nothing to copy from here. The `Prepare Request`, `map`,
244
+ > `Prepare Response Header`, and ESB `DeFaultCatch` fragments in this skeleton do NOT exist in wrapper
245
+ > output; if you paste any of them for a wrapper, it is a bug.
246
+
247
+ Assemble the file in this order. Fill `{slots}`; paste frozen fragments unchanged. **(`backend`
248
+ pattern — for `wrapper`, see the box above.)**
157
249
 
158
250
  ```yaml
159
251
  swagger: '2.0'
@@ -171,7 +263,7 @@ x-ibm-configuration:
171
263
  testable: true
172
264
  assembly:
173
265
  execute:
174
- # ── POST-WITH-BODY ONLY: leading parse of the incoming request (AhelApp). Omit for GET. ──
266
+ # ── POST-WITH-BODY ONLY: leading parse of the incoming request (SamplePost). Omit for GET. ──
175
267
  # Place this as the FIRST policy, before logging, so message.body is parsed for the map.
176
268
  - parse:
177
269
  version: 2.2.0
@@ -194,7 +286,7 @@ x-ibm-configuration:
194
286
  title: Log-set-variable
195
287
  actions:
196
288
  - set: message.headers.Authorization
197
- value: $(nhc-mw-auth)
289
+ value: $(mw-auth)
198
290
  type: string
199
291
  - invoke:
200
292
  version: 2.0.0
@@ -214,7 +306,7 @@ x-ibm-configuration:
214
306
  keep-payload: true
215
307
  output: outResp
216
308
  target-url: >-
217
- $(sakani-mw-base-url)/MW/MWLogServices/GeneralLog/UpsertMDLogQ?Environment=$(env.path)&ServiceName=$(api.name)&UserName=$(client.app.id)&RequestDt=$(system.datetime)
309
+ $(mw-log-base-url)/MW/MWLogServices/GeneralLog/UpsertMDLogQ?Environment=$(env.path)&ServiceName=$(api.name)&UserName=$(client.app.id)&RequestDt=$(system.datetime)
218
310
 
219
311
  # ── JWT (only when JWT is enabled). If JWT is OFF, omit jwt-validate + Check Expiration AND
220
312
  # drop the switch below — run the backend call directly. See "No-JWT shape". ──
@@ -237,8 +329,8 @@ x-ibm-configuration:
237
329
  - condition: ($statusCode() = 200)
238
330
  execute:
239
331
  # Backend auth + static headers — emit only if --backend-auth / --backend-headers given.
240
- # Header name = {backend-auth-header} (default Authorization; Muamalaty uses "Token").
241
- # Add one action per --backend-headers entry (e.g. REST-Framework-Version: '4', AmerApp).
332
+ # Header name = {backend-auth-header} (default Authorization; SampleFwd uses "Token").
333
+ # Add one action per --backend-headers entry (e.g. REST-Framework-Version: '4', SampleDetect).
242
334
  - set-variable:
243
335
  version: 2.0.0
244
336
  title: set-variable
@@ -253,15 +345,15 @@ x-ibm-configuration:
253
345
  # POST-with-body ONLY → request map (see "POST request map" section). Omit for GET.
254
346
 
255
347
  # ── Backend call ──
256
- # verb: {backend-verb} (GET|POST|keep — "keep" forwards caller's verb, AmerApp)
257
- # backend-type: {backend-type} (json default | detect, AmerApp)
348
+ # verb: {backend-verb} (GET|POST|keep — "keep" forwards caller's verb, SampleDetect)
349
+ # backend-type: {backend-type} (json default | detect, SampleDetect)
258
350
  # version 2.3.0 ⇒ also include stop-on-error: [] and graphql-send-type: detect (see variations ref)
259
351
  - invoke:
260
352
  version: 2.2.0 # or 2.3.0
261
353
  title: invoke
262
354
  backend-type: json # or detect
263
355
  header-control:
264
- type: blocklist # → allowlist with {pass-headers} when forwarding custom headers (Muamalaty: Token, rolename)
356
+ type: blocklist # → allowlist with {pass-headers} when forwarding custom headers (SampleFwd: Token, rolename)
265
357
  values: []
266
358
  parameter-control:
267
359
  type: allowlist
@@ -278,8 +370,8 @@ x-ibm-configuration:
278
370
  target-url: >-
279
371
  {backend-target-url}
280
372
  # Backend parse — pick ONE form (see --parse / variations ref):
281
- # inline json (default) ── or ── named default: apic-default-parsesettings (AmerApp)
282
- # add `use-content-type: true` when --use-content-type (Muamalaty/AmerApp).
373
+ # inline json (default) ── or ── named default: apic-default-parsesettings (SampleDetect)
374
+ # add `use-content-type: true` when --use-content-type (SampleFwd/SampleDetect).
283
375
  - parse:
284
376
  version: 2.2.0
285
377
  title: parse
@@ -288,8 +380,8 @@ x-ibm-configuration:
288
380
  document_type: json
289
381
 
290
382
  # ── FROZEN: Prepare Response Header — OMIT if --no-envelope. ──
291
- # Default placement: HERE (inside the 200 case, Ahel/AmerApp).
292
- # If --envelope-placement top-level (Muamalaty): move this policy OUT of the switch,
383
+ # Default placement: HERE (inside the 200 case, SamplePost/SampleDetect).
384
+ # If --envelope-placement top-level (SampleFwd): move this policy OUT of the switch,
293
385
  # to top-level execute AFTER the switch and BEFORE the log policy.
294
386
  - gatewayscript:
295
387
  version: 2.0.0
@@ -368,11 +460,15 @@ x-ibm-configuration:
368
460
  error-content: payload
369
461
  paths:
370
462
  {operation-path}:
371
- parameters: # path-level shared params (RefId may be required: true, Muamalaty)
463
+ # `backend` pattern: house correlation headers (RefId / CallerReqTime), as below.
464
+ # `wrapper` pattern: DELETE the RefId and CallerReqTime entries below entirely and put the spec's
465
+ # ACTUAL inbound headers here (e.g. X-Request-Id). Do NOT keep RefId/CallerReqTime AND add the
466
+ # spec header — replace, don't append. (See rule 2c.)
467
+ parameters: # path-level shared params (RefId may be required: true, SampleFwd)
372
468
  - name: RefId
373
469
  in: header
374
470
  type: string
375
- # required: true # add when RefId is mandatory (Muamalaty)
471
+ # required: true # add when RefId is mandatory (SampleFwd)
376
472
  - name: CallerReqTime
377
473
  in: header
378
474
  type: string
@@ -388,12 +484,12 @@ paths:
388
484
  # GET example: - { name: inboxId, in: query, type: string, required: true }
389
485
  # 2. POST-with-body: - { name: body, in: body, required: true, schema: { $ref: '#/definitions/Request' } }
390
486
  # 3. authorization header (below)
391
- # 4. any extra forwarded headers, e.g. rolename (Muamalaty, required: true)
487
+ # 4. any extra forwarded headers, e.g. rolename (SampleFwd, required: true)
392
488
  - name: authorization
393
489
  required: true
394
490
  in: header
395
491
  type: string
396
- # - name: rolename # example: custom forwarded header (Muamalaty)
492
+ # - name: rolename # example: custom forwarded header (SampleFwd)
397
493
  # required: true
398
494
  # in: header
399
495
  # type: string
@@ -417,6 +513,145 @@ basePath: {basePath}
417
513
 
418
514
  ---
419
515
 
516
+ ## Wrapper skeleton (COMPLETE — use this ENTIRE file for `--pattern wrapper`)
517
+
518
+ For `--pattern wrapper`, **emit exactly this file** and fill the `{slots}`. It already omits the
519
+ `Prepare Request`, the `map`, the `Prepare Response Header`, and the ESB catch — do NOT add any of
520
+ them back, and do NOT copy anything from the backend skeleton above. There is no subtraction to do:
521
+ this is the whole document. (If `--jwt` is on for a wrapper — rare — add `jwt-validate` +
522
+ `Check Expiration` + `switch` before `invoke` per the main skeleton, keeping everything else here.)
523
+
524
+ ```yaml
525
+ swagger: '2.0'
526
+ info:
527
+ title: {ApiTitle}
528
+ x-ibm-name: {x-ibm-name}
529
+ version: {version}
530
+ x-ibm-configuration:
531
+ cors:
532
+ enabled: true # --no-cors → false
533
+ gateway: datapower-api-gateway
534
+ type: rest
535
+ phase: realized
536
+ enforced: true
537
+ testable: true
538
+ assembly:
539
+ execute:
540
+ # POST-with-body ONLY: leading parse. Omit this policy entirely for GET.
541
+ - parse:
542
+ version: 2.2.0
543
+ title: parse
544
+ parse-settings-reference:
545
+ parse-settings:
546
+ document_type: json
547
+ max_value_length: 0
548
+ max_width: 0
549
+
550
+ # OPTIONAL correlation capture — ONLY if the spec names an inbound correlation header.
551
+ # Non-rejecting. Use the spec's real header name. Omit this whole policy if none.
552
+ - set-variable:
553
+ version: 2.0.0
554
+ title: Capture Correlation Id
555
+ actions:
556
+ - set: context.customheaders.CorrelationId
557
+ value: $(request.headers.X-Request-Id) # ← spec's real header
558
+ type: string
559
+
560
+ # MW logging — include the Log-set-variable + Log-invoke pair from the backend skeleton
561
+ # ONLY if NOT --no-logging. Omit both for --no-logging.
562
+ # Backend auth — include a set-variable ({backend-auth-header}: $({backend-auth-var}))
563
+ # ONLY if --backend-auth was given.
564
+
565
+ # ── Backend call → the ACE/webMethods service (direct, no switch) ──
566
+ - invoke:
567
+ version: 2.2.0
568
+ title: invoke
569
+ backend-type: json
570
+ header-control:
571
+ type: blocklist # → allowlist {pass-headers} if forwarding specific headers
572
+ values: []
573
+ parameter-control:
574
+ type: allowlist
575
+ values: [] # list every backend {query} param; empty = none forwarded
576
+ timeout: 60
577
+ verb: {verb}
578
+ http-version: HTTP/1.1
579
+ chunked-uploads: true
580
+ persistent-connection: true
581
+ cache-response: protocol
582
+ cache-ttl: 900
583
+ websocket-upgrade: false
584
+ target-url: >-
585
+ {backend-target-url}
586
+ - parse:
587
+ version: 2.2.0
588
+ title: parse
589
+ parse-settings-reference:
590
+ parse-settings:
591
+ document_type: json
592
+ - log:
593
+ version: 2.1.0
594
+ title: log
595
+ log-level: default
596
+ mode: gather-and-send
597
+ finally: []
598
+ # Neutral catch — surface the gateway error plainly. NO ESB {Header,Body} envelope.
599
+ catch:
600
+ - default:
601
+ - gatewayscript:
602
+ version: 2.0.0
603
+ title: DeFaultCatch
604
+ source: "var code = context.get('error.status.code');\nvar reason = context.get('error.message');\ncontext.message.statusCode = code;\nsession.output.write({ \"code\": code, \"message\": reason });"
605
+ properties:
606
+ target-url:
607
+ value: http://example.com/operation-name
608
+ description: The URL of the target service
609
+ encoded: false
610
+ activity-log:
611
+ enabled: true
612
+ success-content: activity
613
+ error-content: payload
614
+ paths:
615
+ {operation-path}:
616
+ parameters:
617
+ # The spec's REAL inbound headers ONLY. Example correlation header shown.
618
+ # Do NOT add RefId or CallerReqTime here.
619
+ - name: X-Request-Id # ← replace with the spec's actual header(s)
620
+ in: header
621
+ type: string
622
+ {verb}: # get: or post:
623
+ responses:
624
+ '200':
625
+ description: success
626
+ schema:
627
+ type: string
628
+ parameters:
629
+ # POST-with-body: body param (GET: omit). Plus any backend {query} params as in: query.
630
+ - name: body
631
+ in: body
632
+ required: true
633
+ schema:
634
+ $ref: '#/definitions/Request'
635
+ securityDefinitions:
636
+ clientID:
637
+ type: apiKey
638
+ in: header
639
+ name: X-IBM-Client-Id
640
+ clientSecret:
641
+ type: apiKey
642
+ name: X-IBM-Client-Secret
643
+ in: header
644
+ security:
645
+ - clientID: []
646
+ clientSecret: []
647
+ schemes:
648
+ - https
649
+ basePath: {basePath}
650
+ # definitions: only for POST-with-body — same Request block as the backend skeleton.
651
+ ```
652
+
653
+ ---
654
+
420
655
  ## No-JWT shape (when JWT validation is OFF)
421
656
 
422
657
  When the API does **not** require JWT, generate a simpler assembly: there's no token to validate, so
@@ -435,7 +670,7 @@ call runs directly, and the `catch` keeps only the `default` handler.
435
670
  source: "<<< the FROZEN Prepare Request source, verbatim >>>"
436
671
 
437
672
  # Middleware logging — include unless --no-logging (same as main skeleton)
438
- - set-variable: { version: 2.0.0, title: Log-set-variable, actions: [ { set: message.headers.Authorization, value: $(nhc-mw-auth), type: string } ] }
673
+ - set-variable: { version: 2.0.0, title: Log-set-variable, actions: [ { set: message.headers.Authorization, value: $(mw-auth), type: string } ] }
439
674
  - invoke: # ...the Log-invoke (UpsertMDLogQ) policy, verbatim...
440
675
 
441
676
  # Backend auth + static headers (only if --backend-auth / --backend-headers given)
@@ -497,7 +732,7 @@ Notes for the No-JWT shape:
497
732
  ## POST request map (only when body fields are given)
498
733
 
499
734
  Insert this `map` **inside the 200 case, before the backend `invoke`**, and add the matching
500
- `definitions` block. Pattern from AhelApp — first output field defaults from a JWT claim, the rest
735
+ `definitions` block. Pattern from SamplePost — first output field defaults from a JWT claim, the rest
501
736
  copy through from input:
502
737
 
503
738
  ```yaml
@@ -545,20 +780,20 @@ definitions:
545
780
  ## Policy variations reference (drawn from the three live samples)
546
781
 
547
782
  Use these exact forms when the prompt calls for them. The three samples map to:
548
- **AhelApp** = POST + leading parse + request map + logging(v2.3.0) + envelope in-case;
549
- **Muamalaty** = GET + logging(v2.0.0) + Token-header backend + forwarded headers + envelope top-level;
550
- **AmerApp** = GET + NO logging + verb keep + backend-type detect + named parse + envelope in-case.
783
+ **SamplePost** = POST + leading parse + request map + logging(v2.3.0) + envelope in-case;
784
+ **SampleFwd** = GET + logging(v2.0.0) + Token-header backend + forwarded headers + envelope top-level;
785
+ **SampleDetect** = GET + NO logging + verb keep + backend-type detect + named parse + envelope in-case.
551
786
 
552
- ### Logging invoke — two variants (omit entirely if `--no-logging`, AmerApp)
787
+ ### Logging invoke — two variants (omit entirely if `--no-logging`, SampleDetect)
553
788
 
554
- **(a) v2.0.0 "json" (Muamalaty)** — current skeleton default:
789
+ **(a) v2.0.0 "json" (SampleFwd)** — current skeleton default:
555
790
  ```yaml
556
791
  - invoke:
557
792
  version: 2.0.0
558
793
  title: Log-invoke
559
794
  verb: POST
560
795
  target-url: >-
561
- $(sakani-mw-base-url)/MW/MWLogServices/GeneralLog/UpsertMDLogQ?Environment=$(env.path)&ServiceName=$(api.name)&UserName=$(client.app.id)&RequestDt=$(system.datetime)
796
+ $(mw-log-base-url)/MW/MWLogServices/GeneralLog/UpsertMDLogQ?Environment=$(env.path)&ServiceName=$(api.name)&UserName=$(client.app.id)&RequestDt=$(system.datetime)
562
797
  follow-redirects: false
563
798
  timeout: 60
564
799
  parameter-control: { type: allowlist, values: [] }
@@ -570,7 +805,7 @@ Use these exact forms when the prompt calls for them. The three samples map to:
570
805
  keep-payload: true
571
806
  chunked-uploads: true
572
807
  ```
573
- **(b) v2.3.0 "detect" (AhelApp)** — preceded by its own `set-variable` setting `Authorization: $(nhc-mw-auth)`:
808
+ **(b) v2.3.0 "detect" (SamplePost)** — preceded by its own `set-variable` setting `Authorization: $(mw-auth)`:
574
809
  ```yaml
575
810
  - invoke:
576
811
  version: 2.3.0
@@ -589,11 +824,11 @@ Use these exact forms when the prompt calls for them. The three samples map to:
589
824
  websocket-upgrade: false
590
825
  graphql-send-type: detect
591
826
  target-url: >-
592
- $(sakani-mw-base-url)/MW/MWLogServices/GeneralLog/UpsertMDLogQ?Environment=$(env.path)&ServiceName=$(api.name)&UserName=$(client.app.id)&RequestDt=$(system.datetime)
827
+ $(mw-log-base-url)/MW/MWLogServices/GeneralLog/UpsertMDLogQ?Environment=$(env.path)&ServiceName=$(api.name)&UserName=$(client.app.id)&RequestDt=$(system.datetime)
593
828
  output: logResp
594
829
  ```
595
830
 
596
- ### Backend invoke — v2.3.0 / detect / keep (AmerApp)
831
+ ### Backend invoke — v2.3.0 / detect / keep (SampleDetect)
597
832
  Same as the skeleton invoke, but with these fields:
598
833
  ```yaml
599
834
  - invoke:
@@ -613,17 +848,17 @@ Same as the skeleton invoke, but with these fields:
613
848
  websocket-upgrade: false
614
849
  graphql-send-type: detect
615
850
  target-url: >-
616
- $(erp-base-url)/hcmRestApi/resources/latest/workers?onlyData=true&q=emails.EmailAddress='$(decoded.claims.EmailAddress)'
851
+ $(backend-base-url)/api/resource/workers?onlyData=true&q=emails.EmailAddress='$(decoded.claims.EmailAddress)'
617
852
  ```
618
853
 
619
- ### Backend with forwarded headers (Muamalaty) — Token auth + allowlist
854
+ ### Backend with forwarded headers (SampleFwd) — Token auth + allowlist
620
855
  ```yaml
621
856
  - set-variable:
622
857
  version: 2.0.0
623
858
  title: set-variable
624
859
  actions:
625
860
  - set: message.headers.Token
626
- value: $(nhc-cts-auth)
861
+ value: $(backend-auth)
627
862
  type: string
628
863
  - invoke:
629
864
  version: 2.2.0
@@ -639,24 +874,24 @@ Same as the skeleton invoke, but with these fields:
639
874
  verb: GET
640
875
  # ...rest as skeleton...
641
876
  target-url: >-
642
- $(nhc-cts-url)/CTSIPADUtilities/action/GetCorrespondences?userEmail=$(decoded.claims.EmailAddress)
877
+ $(backend-base-url)/api/GetCorrespondences?userEmail=$(decoded.claims.EmailAddress)
643
878
  ```
644
879
 
645
- ### Multi-action set-variable (AmerApp) — auth + static framework header
880
+ ### Multi-action set-variable (SampleDetect) — auth + static framework header
646
881
  ```yaml
647
882
  - set-variable:
648
883
  version: 2.0.0
649
884
  title: set-variable
650
885
  actions:
651
886
  - set: message.headers.Authorization
652
- value: $(erp-ameruser-auth)
887
+ value: $(backend-auth)
653
888
  type: string
654
889
  - set: message.headers.REST-Framework-Version
655
890
  value: '4'
656
891
  type: string
657
892
  ```
658
893
 
659
- ### Backend parse — named-default form (AmerApp)
894
+ ### Backend parse — named-default form (SampleDetect)
660
895
  ```yaml
661
896
  - parse:
662
897
  version: 2.2.0
@@ -666,13 +901,13 @@ Same as the skeleton invoke, but with these fields:
666
901
  use-content-type: true
667
902
  ```
668
903
 
669
- ### Envelope placement — top-level (Muamalaty)
904
+ ### Envelope placement — top-level (SampleFwd)
670
905
  The `Prepare Response Header` gatewayscript sits at **top-level execute, after the `switch`,
671
906
  before `log`** — not inside the 200 case. The `switch` there is `version: 2.1.0`.
672
907
 
673
908
  ### Quick per-sample knob table
674
909
 
675
- | Knob | AhelApp | Muamalaty | AmerApp |
910
+ | Knob | SamplePost | SampleFwd | SampleDetect |
676
911
  |---|---|---|---|
677
912
  | method | POST | GET | GET |
678
913
  | leading parse | yes | no | no |
@@ -680,7 +915,7 @@ before `log`** — not inside the 200 case. The `switch` there is `version: 2.1.
680
915
  | request map + definitions | yes | no | no |
681
916
  | backend version / type | 2.2.0 / json | 2.2.0 / json | 2.3.0 / detect |
682
917
  | backend verb | POST | GET | keep |
683
- | backend auth header | Authorization $(servicenow-auth) | Token $(nhc-cts-auth) | Authorization $(erp-ameruser-auth) + REST-Framework-Version '4' |
918
+ | backend auth header | Authorization $(backend-auth) | Token $(backend-auth) | Authorization $(backend-auth) + REST-Framework-Version '4' |
684
919
  | forwarded headers (allowlist) | — | Token, rolename | — |
685
920
  | query params (allowlist) | — | inboxId,index,pageSize,language,userEmail | expand |
686
921
  | backend parse | inline json | inline json (use-content-type) | default apic-default-parsesettings (use-content-type) |
@@ -720,12 +955,13 @@ below referencing the path you wrote.
720
955
  After the file is written, print a short summary:
721
956
 
722
957
  ```
723
- ✓ {ApiTitle} — APIC {2.0|3.0} definition generated → {x-ibm-name}_{version}.yaml
958
+ ✓ {ApiTitle} — APIC {2.0|3.0} definition generated → {x-ibm-name}_{version}.yaml [apic-skill rev-W2]
724
959
 
960
+ pattern {backend | wrapper (ACE/webMethods)}
725
961
  verb {VERB} {operation-path} (basePath {basePath})
726
962
  JWT validate {on|off} crypto: $({crypto-object})
727
963
  MW logging {on|off}
728
- ESB envelope {on|off}
964
+ ESB envelope {on|off (wrapper → off, service-provided)}
729
965
  backend {backend-target-url}
730
966
  request map {yes (N fields)|no}
731
967