@pega/sdk 0.0.14 → 0.0.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/README.md +46 -6
  2. package/dist/index.js +50 -24
  3. package/package.json +42 -3
  4. package/templates/angular-sdk-reference/angular.json +1 -2
  5. package/templates/angular-sdk-reference/extra-webpack.config.cjs +23 -0
  6. package/templates/angular-sdk-reference/index.html +12 -0
  7. package/templates/angular-sdk-reference/package.json +0 -1
  8. package/templates/angular-sdk-reference/src/app/app.component.ts +15 -232
  9. package/templates/angular-sdk-reference/src/app/pconnect-renderer.component.ts +153 -0
  10. package/templates/angular-sdk-reference/src/components/fields/auto-complete/auto-complete.component.ts +58 -21
  11. package/templates/angular-sdk-reference/src/components/fields/checkbox/checkbox.component.ts +8 -3
  12. package/templates/angular-sdk-reference/src/components/fields/currency/currency.component.ts +22 -7
  13. package/templates/angular-sdk-reference/src/components/fields/date-input/date-input.component.ts +19 -6
  14. package/templates/angular-sdk-reference/src/components/fields/dropdown/dropdown.component.ts +24 -7
  15. package/templates/angular-sdk-reference/src/components/fields/email/email.component.ts +19 -6
  16. package/templates/angular-sdk-reference/src/components/fields/integer/integer.component.ts +19 -6
  17. package/templates/angular-sdk-reference/src/components/fields/phone/phone.component.ts +19 -6
  18. package/templates/angular-sdk-reference/src/components/fields/radio-buttons/radio-buttons.component.ts +16 -5
  19. package/templates/angular-sdk-reference/src/components/fields/text-area/text-area.component.ts +19 -6
  20. package/templates/angular-sdk-reference/src/components/fields/text-input/text-input.component.ts +19 -6
  21. package/templates/angular-sdk-reference/src/components/fields/url-input/url-input.component.ts +26 -7
  22. package/templates/angular-sdk-reference/src/components/helpers/sdk-helpers.ts +93 -0
  23. package/templates/angular-sdk-reference/src/components/infra/case-summary/case-summary.component.ts +8 -9
  24. package/templates/angular-sdk-reference/src/components/infra/case-view/case-view.component.ts +24 -12
  25. package/templates/angular-sdk-reference/src/components/infra/root-container/root-container.component.ts +21 -15
  26. package/templates/angular-sdk-reference/src/components/infra/stages/stages.component.ts +21 -10
  27. package/templates/angular-sdk-reference/src/components/infra/view/view.component.ts +14 -9
  28. package/templates/angular-sdk-reference/src/components/templates/default-form/default-form.component.ts +12 -8
  29. package/templates/angular-sdk-reference/tsconfig.app.json +13 -0
  30. package/templates/angular-sdk-reference/tsconfig.json +2 -5
  31. package/templates/react-sdk-reference/.ai-common/agents/embedded-flow-expert.md +65 -31
  32. package/templates/react-sdk-reference/.ai-common/agents/implementation-expert.md +74 -38
  33. package/templates/react-sdk-reference/.ai-common/global/ai-agent-instructions-embedded.md +33 -1
  34. package/templates/react-sdk-reference/.ai-common/global/ai-agent-instructions.md +57 -22
  35. package/templates/react-sdk-reference/.ai-common/instructions/embedded-component.md +25 -10
  36. package/templates/react-sdk-reference/.ai-common/prompts/add-component.md +40 -19
  37. package/templates/react-sdk-reference/.ai-common/prompts/component-manifest.json +55 -1
  38. package/templates/react-sdk-reference/.ai-common/prompts/embedded-component-manifest.md +26 -4
  39. package/templates/react-sdk-reference/.ai-common/prompts/generate-all-components.md +82 -33
  40. package/templates/react-sdk-reference/.ai-common/prompts/generate-dse-components.md +46 -26
  41. package/templates/react-sdk-reference/.ai-common/prompts/generate-embedded-components.md +28 -15
  42. package/templates/react-sdk-reference/.ai-common/prompts/generate-field-components.md +24 -6
  43. package/templates/react-sdk-reference/.ai-common/prompts/generate-infra-components.md +24 -6
  44. package/templates/react-sdk-reference/.ai-common/prompts/generate-template-components.md +24 -6
  45. package/templates/react-sdk-reference/.ai-common/prompts/generate-widget-components.md +24 -6
  46. package/templates/react-sdk-reference/.ai-common/prompts/identify-components.md +2 -0
  47. package/templates/react-sdk-reference/.ai-common/prompts/replace-design-system.md +44 -17
  48. package/templates/react-sdk-reference/.ai-common/skills/connect-pega-server.md +14 -1
  49. package/templates/react-sdk-reference/.ai-common/skills/design-system-extension-skills/AssignmentHeader.md +79 -0
  50. package/templates/react-sdk-reference/.ai-common/skills/design-system-extension-skills/Toast.md +96 -0
  51. package/templates/react-sdk-reference/.ai-common/skills/design-system-extension.md +56 -35
  52. package/templates/react-sdk-reference/.ai-common/skills/embedded-flow/analyze-customer-repo.md +29 -3
  53. package/templates/react-sdk-reference/.ai-common/skills/embedded-flow/run-and-verify-integration.md +97 -37
  54. package/templates/react-sdk-reference/.ai-common/skills/embedded-flow/wire-integration.md +91 -60
  55. package/templates/react-sdk-reference/.ai-common/skills/field-components.md +13 -1
  56. package/templates/react-sdk-reference/.ai-common/skills/infra-components.md +13 -1
  57. package/templates/react-sdk-reference/.ai-common/skills/portal-flow/run-and-verify-portal.md +290 -0
  58. package/templates/react-sdk-reference/.ai-common/skills/template-components.md +13 -1
  59. package/templates/react-sdk-reference/.ai-common/skills/widget-components.md +13 -1
  60. package/templates/react-sdk-reference/assets/icons/trash.svg +3 -0
  61. package/templates/react-sdk-reference/index.html +0 -1
  62. package/templates/react-sdk-reference/package.json +2 -2
  63. package/templates/react-sdk-reference/package.minimal.json +2 -2
  64. package/templates/react-sdk-reference/sdk-config.json +3 -3
  65. package/templates/react-sdk-reference/src/FallbackComponent.tsx +1 -1
  66. package/templates/react-sdk-reference/src/MashupApp.tsx +33 -78
  67. package/templates/react-sdk-reference/src/PortalApp.tsx +23 -100
  68. package/templates/react-sdk-reference/src/components/component-map.ts +15 -1
  69. package/templates/react-sdk-reference/src/components/designSystemExtension/AssignmentHeader/AssignmentHeader.tsx +15 -0
  70. package/templates/react-sdk-reference/src/components/designSystemExtension/AssignmentHeader/index.tsx +1 -0
  71. package/templates/react-sdk-reference/src/components/designSystemExtension/FieldGroup/FieldGroup.tsx +1 -1
  72. package/templates/react-sdk-reference/src/components/designSystemExtension/FieldGroupList/FieldGroupList.tsx +1 -1
  73. package/templates/react-sdk-reference/src/components/designSystemExtension/FieldValueList/FieldValueList.tsx +16 -4
  74. package/templates/react-sdk-reference/src/components/designSystemExtension/ModalDialog/ModalDialog.tsx +26 -0
  75. package/templates/react-sdk-reference/src/components/designSystemExtension/ModalDialog/index.tsx +1 -0
  76. package/templates/react-sdk-reference/src/components/designSystemExtension/Toast/Toast.tsx +35 -0
  77. package/templates/react-sdk-reference/src/components/designSystemExtension/Toast/index.tsx +1 -0
  78. package/templates/react-sdk-reference/src/components/field/AutoComplete/AutoComplete.tsx +362 -24
  79. package/templates/react-sdk-reference/src/components/field/CancelAlert/CancelAlert.tsx +1 -1
  80. package/templates/react-sdk-reference/src/components/field/Checkbox/Checkbox.tsx +3 -1
  81. package/templates/react-sdk-reference/src/components/field/Currency/Currency.tsx +6 -3
  82. package/templates/react-sdk-reference/src/components/field/Date/Date.tsx +2 -1
  83. package/templates/react-sdk-reference/src/components/field/DateTime/DateTime.tsx +2 -1
  84. package/templates/react-sdk-reference/src/components/field/Decimal/Decimal.tsx +4 -3
  85. package/templates/react-sdk-reference/src/components/field/Dropdown/Dropdown.tsx +2 -0
  86. package/templates/react-sdk-reference/src/components/field/Email/Email.tsx +2 -1
  87. package/templates/react-sdk-reference/src/components/field/EmbeddedDataMulti/EmbeddedDataMulti.tsx +121 -0
  88. package/templates/react-sdk-reference/src/components/field/EmbeddedDataMulti/config-ext.json +7 -0
  89. package/templates/react-sdk-reference/src/components/field/EmbeddedDataMulti/index.tsx +1 -0
  90. package/templates/react-sdk-reference/src/components/field/Integer/Integer.tsx +2 -1
  91. package/templates/react-sdk-reference/src/components/field/Location/Location.tsx +1 -1
  92. package/templates/react-sdk-reference/src/components/field/Multiselect/Multiselect.tsx +40 -20
  93. package/templates/react-sdk-reference/src/components/field/ObjectReference/ObjectReference.tsx +554 -49
  94. package/templates/react-sdk-reference/src/components/field/ObjectReference/utils.ts +111 -20
  95. package/templates/react-sdk-reference/src/components/field/Percentage/Percentage.tsx +4 -3
  96. package/templates/react-sdk-reference/src/components/field/Phone/Phone.tsx +2 -1
  97. package/templates/react-sdk-reference/src/components/field/SelectableCard/SelectableCard.tsx +2 -1
  98. package/templates/react-sdk-reference/src/components/field/TextArea/TextArea.tsx +2 -1
  99. package/templates/react-sdk-reference/src/components/field/TextInput/TextInput.tsx +2 -1
  100. package/templates/react-sdk-reference/src/components/field/Time/Time.tsx +2 -1
  101. package/templates/react-sdk-reference/src/components/field/URL/URL.tsx +2 -1
  102. package/templates/react-sdk-reference/src/components/field/UserReference/UserReference.tsx +1 -1
  103. package/templates/react-sdk-reference/src/components/helpers/field-utils.ts +44 -0
  104. package/templates/react-sdk-reference/src/components/helpers/simpleTableHelpers.ts +19 -7
  105. package/templates/react-sdk-reference/src/components/infra/ModalViewContainer/DataViewActionButtons/DataViewActionButtons.tsx +97 -0
  106. package/templates/react-sdk-reference/src/components/infra/ModalViewContainer/DataViewActionButtons/index.tsx +1 -0
  107. package/templates/react-sdk-reference/src/components/infra/ModalViewContainer/ListViewActionButtons/ListViewActionButtons.tsx +53 -0
  108. package/templates/react-sdk-reference/src/components/infra/ModalViewContainer/ListViewActionButtons/index.tsx +1 -0
  109. package/templates/react-sdk-reference/src/components/template/AdvancedSearch/SearchGroups/SearchGroups.tsx +2 -2
  110. package/templates/react-sdk-reference/src/components/template/CaseSummary/CaseSummary.tsx +3 -1
  111. package/templates/react-sdk-reference/src/components/template/DataReference/SearchForm.tsx +4 -4
  112. package/templates/react-sdk-reference/src/components/template/HierarchicalForm/HierarchicalForm.tsx +2 -2
  113. package/templates/react-sdk-reference/src/components/template/InlineDashboard/InlineDashboard.tsx +1 -1
  114. package/templates/react-sdk-reference/src/components/template/ListView/ListView.tsx +7 -3
  115. package/templates/react-sdk-reference/src/components/template/SimpleTable/SimpleTableManual/SimpleTableManual.tsx +173 -99
  116. package/templates/react-sdk-reference/src/components/template/SimpleTable/SimpleTableSelect/SimpleTableSelect.tsx +63 -56
  117. package/templates/react-sdk-reference/src/components/widget/ToDo/ToDo.tsx +1 -1
  118. package/templates/react-sdk-reference/vite.config.ts +26 -4
  119. package/templates/angular-sdk-reference/pega-constellationjs-0.26.3-local.tgz +0 -0
  120. package/templates/angular-sdk-reference/src/helpers/event-utils.ts +0 -18
  121. package/templates/angular-sdk-reference/src/helpers/utils.ts +0 -38
  122. package/templates/angular-sdk-reference/src/helpers/versionHelpers.ts +0 -14
  123. package/templates/react-sdk-reference/.ai-common/instructions/dse-component.md +0 -47
  124. package/templates/react-sdk-reference/.ai-common/instructions/field-component.md +0 -50
  125. package/templates/react-sdk-reference/.ai-common/instructions/infra-component.md +0 -76
  126. package/templates/react-sdk-reference/.ai-common/instructions/template-component.md +0 -43
  127. package/templates/react-sdk-reference/.ai-common/instructions/widget-component.md +0 -45
  128. package/templates/react-sdk-reference/.ai-common/skills/embedded-flow/authenticate.md +0 -311
  129. package/templates/react-sdk-reference/pega-constellationjs-0.26.3-local.tgz +0 -0
  130. package/templates/react-sdk-reference/pega-sdk-react-0.1.0.tgz +0 -0
@@ -107,9 +107,11 @@ A generic list of surfaces is not good enough. Draw the options from the applica
107
107
 
108
108
  Ask for both in a single exchange when both are missing. Two round trips for one decision is worse than one.
109
109
 
110
- #### Step 0.4 — The resolved target must survive a full-page reload
110
+ #### Step 0.4 — Authentication must not lose the launch context
111
111
 
112
- Whichever target Step 0.2 or Step 0.3 produced, it has to survive being reloaded. The SDK authenticates by redirecting the whole window to the Pega login form and back, so the application is torn down and re-created between the moment the user triggers the flow and the moment the flow can render. Anything holding the launch context only in memory is gone by then.
112
+ The embedded startup authenticates in a separate popup window and leaves the application page in place, so a launch context held in memory is still there when the flow becomes ready. Nothing needs persisting in that default.
113
+
114
+ The rest of this step applies only when the host has been configured for main-window redirect login instead. In that mode the SDK redirects the whole window to the Pega login form and back, so the application is torn down and re-created between the moment the user triggers the flow and the moment the flow can render. Anything holding the launch context only in memory is gone by then, so the resolved target has to survive being reloaded.
113
115
 
114
116
  This is a property of the target, not an edge case, and it must be handled while wiring rather than discovered later:
115
117
 
@@ -137,8 +139,8 @@ These two lifetimes are easy to collapse into one, because on a first launch the
137
139
  So:
138
140
 
139
141
  - **Keep the runtime for the lifetime of the page.** When the target is dismissed, hide it and leave the runtime in place. Never discard it to close the flow.
140
- - **Do not establish it at page start either**, if doing so would authenticate. The first launch is what puts a visitor in front of the login form, and nothing should send them there before they ask. Establish it on the first launch, then keep it.
141
- - **Drive case creation from the launch itself**, not from the runtime being set up, so that every launch creates a case and the second one behaves like the first.
142
+ - **Do not establish it at page start either**, since establishing it authenticates. The first launch is what opens the Pega login window for a visitor, and nothing should open it before they ask. Starting on the user's own launch action also keeps the browser from treating the login window as an unsolicited popup and blocking it. Establish it on the first launch, then keep it.
143
+ - **Drive case creation from the launch itself**, not from the runtime being set up, so that every launch creates a case and the second one behaves like the first. On the first launch the runtime is not ready when the user acts, so hold that launch until readiness is signalled and then create its case; on later launches create it immediately.
142
144
 
143
145
  **A single launch cannot detect any of this.** Set-up and first launch coincide, so the flow works, and the defect appears only on a second launch — which is why Step 7 requires the flow to be launched more than once.
144
146
 
@@ -148,40 +150,43 @@ So:
148
150
 
149
151
  Add the following Pega packages to the project's dependency manifest:
150
152
 
151
- | Package | Purpose |
152
- | ---------------------------------------------------------------- | --------------------------------------------------------------- |
153
- | The Pega SDK adapter package (matching the customer's framework) | Bridge component, runtime context, component registry utilities |
154
- | The Pega auth package | OAuth authentication and token management |
155
- | The Pega SDK types package | Shared type definitions and interfaces |
156
- | The Pega ConstellationJS core package | Runtime engine that provides the PCore global |
153
+ | Package | Purpose |
154
+ | ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
155
+ | The Pega SDK adapter package (matching the customer's framework) | Bridge component, runtime context, component registry utilities |
156
+ | The Pega auth package | OAuth authentication and token management |
157
+ | The Pega SDK types package | Shared type definitions and interfaces |
158
+ | The Pega ConstellationJS core package | Runtime engine that provides the PCore global; its distribution files are served by the host (Step 1.1) |
157
159
 
158
160
  These are the only external additions. The generated components use the customer's existing UI library — no additional design system packages are needed.
159
161
 
160
162
  If SDK packages were provided as `.tgz` files (interim distribution), they should already be in the project root with `file:` references in the dependency manifest. Run the project's package install command to link them.
161
163
 
162
- ### Step 1.1 — Load the SDK core runtime script
164
+ ### Step 1.1 — Serve the SDK core runtime files
165
+
166
+ The Pega runtime is not loaded by the page. After login succeeds, the SDK's auth package loads the runtime's bootstrap shell from the content server, and the shell then fetches the core bundles and their lazily loaded chunks. The host application only has to make those files reachable. **Do not add a script reference for the core bundle.** Loading it ahead of the application is not how the supported startup works, and the `PCore` global is deliberately absent until authentication has completed.
163
167
 
164
- The Pega ConstellationJS core must be loaded **before** any SDK code executes. It provides the `PCore` global object that all Pega components depend on.
168
+ The files ship inside the ConstellationJS package, under its distribution directory. Serve them at these absolute URLs, in the development server and in the production build alike:
165
169
 
166
- The script ships inside the ConstellationJS package, under its distribution directory. Resolve the exact path from the installed package rather than copying the file anywhere.
170
+ | Served URL | Source in the ConstellationJS distribution directory |
171
+ | ----------------------------------- | ------------------------------------------------------------------------------------------ |
172
+ | `/constellation/bootstrap-shell.js` | The bootstrap shell |
173
+ | `/constellation/lib_asset.json` | The library manifest |
174
+ | `/constellation/prerequisite/` | The core bundle files — every file whose name starts with the `constellation-core.` prefix |
175
+ | `/constellation/prerequisite/js/` | The lazily loaded chunk folder, with its folder structure kept |
167
176
 
168
- **Where it goes depends on the shape of the project's entry point.** Identify which of these the customer's framework is, then apply it:
177
+ `serverConfig.sdkContentServerUrl` decides where the SDK requests these from; an empty value means the application's own origin (see Step 2).
169
178
 
170
- | Entry-point shape | How to load the core script |
171
- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
172
- | The project has a hand-editable HTML document that loads the application module | Add a script element ahead of the application's own module script, so it executes first |
173
- | The framework generates the HTML document and exposes a root layout or shell | Use the framework's mechanism for injecting a script that runs before application code — most provide an explicit "before interactive" or "head" placement for exactly this |
174
- | The framework renders on the server | The script must execute in the browser only. Use the framework's browser-only escape hatch; never let it run during a server render, where there is no `window` to attach `PCore` to |
179
+ Use whatever mechanism the toolchain already has for serving static files at fixed URLs — typically a development-server rule plus a build-time copy step, or a static-asset configuration entry. Resolve the source from the installed package every time the build or development server starts rather than committing a copy: a committed copy silently goes stale when the package is upgraded. Make sure the toolchain's fallback to the entry document does not answer these URLs with the application's HTML when a file is missing — a missing file must fail visibly.
175
180
 
176
- If the development server does not serve files from the dependency directory, either configure it to, or place a copy where the project already serves static assets and reference it from there. Prefer serving from the installed package when the toolchain allows it — a copy silently goes stale when the package is upgraded.
181
+ **Integrity map (optional):** the auth package looks for an import map in the HTML document that carries a hash for the bootstrap shell. Without one it logs a warning that it is falling back to an unverified URL. That warning is expected here and harmless.
177
182
 
178
183
  **Key requirements:**
179
184
 
180
- - The core script must load and execute **before** the application module runs
181
- - It must execute only in the browser, not during any server-side rendering phase
182
- - The reference must resolve from the route the flow launches at — see the document-relative discussion in Step 2, which applies to this script too
185
+ - The URLs are absolute, so they resolve identically from every route — unlike `sdk-config.json`, which is document-relative (Step 2)
186
+ - Nothing in the application's HTML or entry module references the core bundle
187
+ - Every file the shell requests under `/constellation/prerequisite/` is served, including the lazily loaded chunks; serving only the entry bundle fails later, when a component that needs a chunk first mounts
183
188
 
184
- **Verification criterion:** The browser's network panel shows the core script loaded successfully, and the `PCore` global object is available on `window` before application code executes.
189
+ **Verification criterion:** Requesting `<origin>/constellation/bootstrap-shell.js` and `<origin>/constellation/lib_asset.json` in the browser returns a script and JSON respectively, not the application's HTML. After login completes, the network panel shows the core bundle loaded from `/constellation/prerequisite/` and the `PCore` global is defined on `window`.
185
190
 
186
191
  ### Step 1.2 — Load SDK styles and OAuth callback assets
187
192
 
@@ -197,7 +202,7 @@ Import this stylesheet in the application's entry point, **before** the applicat
197
202
 
198
203
  **OAuth callback assets:**
199
204
 
200
- The SDK's auth package ships browser-facing assets used during the OAuth redirect flow:
205
+ The SDK's auth package ships browser-facing assets used by the login popup and its OAuth callback:
201
206
 
202
207
  | Asset | Source (in auth package) | Required served location |
203
208
  | ----------------------- | ---------------------------------------- | --------------------------------------------------------------- |
@@ -247,29 +252,44 @@ The file must contain two sections — `serverConfig` and `authConfig`:
247
252
  | `serverConfig` | `appMashupCaseType` | Fully qualified case type class to embed |
248
253
  | `serverConfig` | `excludePortals` | Array of portal names incompatible with the SDK (prevents auto-selection of admin/developer portals) |
249
254
  | `authConfig` | `authService` | Authentication service identifier (typically `"pega"`) |
250
- | `authConfig` | `mashupClientId` | OAuth client identifier for embedded/mashup mode |
255
+ | `authConfig` | `mashupClientId` | OAuth client identifier used by the embedded login popup |
251
256
  | `authConfig` | `mashupUserIdentifier` | Operator identifier for the embedded session |
252
257
  | `authConfig` | `mashupPassword` | Operator password (empty for OAuth-only flows) |
253
- | `authConfig` | `portalClientId` | OAuth client identifier used during main-window redirect authentication |
258
+ | `authConfig` | `portalClientId` | OAuth client identifier used only by main-window redirect login |
254
259
  | `authConfig` | `portalClientSecret` | Client secret for portal authentication (empty if public client) |
255
260
  | `authConfig` | `portalGrantType` | OAuth grant type for portal auth (empty for default authorization code flow) |
256
261
 
257
- **⚠️ CRITICAL — Portal credential keys and silent authentication hang:**
262
+ **⚠️ CRITICAL — The client identifier for the active login mode must be non-empty:**
258
263
 
259
- When the bootstrap module authenticates using a main-window redirect (which is the default for embedded mode), the SDK's configuration normalization reads the **portal-prefixed** credential keys (`portalClientId`, `portalClientSecret`, `portalGrantType`), not the mashup-prefixed ones.
264
+ The SDK's configuration normalization picks credential keys by login mode. The embedded startup authenticates in a popup, so it reads the **mashup-prefixed** keys (`mashupClientId` and its siblings). A main-window redirect login reads the **portal-prefixed** keys (`portalClientId`, `portalClientSecret`, `portalGrantType`) instead.
260
265
 
261
- If `portalClientId` is absent or empty, the authentication initializer classifies the session as custom-auth and returns **without ever resolving its readiness promise**. The result is a permanent silent hang:
266
+ If the client identifier for the active mode is absent or empty, treat it as the following failure. The observed case is an empty `portalClientId`: the authentication initializer classifies the session as custom-auth and returns **without ever resolving its readiness promise**. The result is a permanent silent hang:
262
267
 
263
268
  - No network requests are made
264
269
  - No error is thrown or logged
265
270
  - The readiness signal never fires
266
271
  - The UI remains in its "loading" state indefinitely
267
272
 
268
- **Prevention:** Always populate `portalClientId` — typically with the same value as `mashupClientId`. The `portalClientSecret` and `portalGrantType` fields should be present (even if empty strings) to ensure the normalizer finds them.
273
+ **Prevention:** Always populate both `mashupClientId` and `portalClientId` with the same value, so that neither login mode can hit it. The `portalClientSecret` and `portalGrantType` fields should be present (even if empty strings) to ensure the normalizer finds them.
274
+
275
+ ### Step 3 — Establish the runtime startup
276
+
277
+ Authentication, registry creation and bootstrap must run exactly once per page load, regardless of how many times the host framework invokes component lifecycle methods.
278
+
279
+ **Prefer the adapter package's runtime provider.** Check the exports of the SDK adapter package for the customer's framework. When it offers a top-level runtime provider, use it instead of hand-writing startup. It performs, in order: login, registry creation, registration of the host's components, registration of the component creator with the fallback, and bootstrap. It then supplies the readiness state, render context, registry and auth client through the runtime context. The host supplies only:
269
280
 
270
- ### Step 3 — Create the bootstrap module
281
+ - The embedded mode
282
+ - A registration callback that registers every component exported by the generated components folder's `component-map` registry file into the registry it is given
283
+ - The fallback component that renders when Pega requests a component with no registry entry
284
+ - Loading, error and logged-out renderings, built from the customer's own primitives
271
285
 
272
- Create a module that handles the Pega SDK lifecycle. **This module's initialization must execute exactly once per page load**, regardless of how many times the host framework invokes component lifecycle methods.
286
+ Rules for placing it:
287
+
288
+ - **Mount it once, on the first launch, and never unmount it.** Mounting it is what starts login (Step 0.5). Its start guard belongs to the single instance, so a provider that is torn down and re-created authenticates and bootstraps again, which stalls on an already-initialised runtime
289
+ - **Wrap only the Pega target, never the customer's application.** While it is loading, has failed, or has been logged out, it renders that state in place of its children. Wrapped around the whole application, it would replace the customer's UI with a loading, error or logged-out message
290
+ - **Supply the three renderings.** The defaults are bare text. The error rendering receives the error and a retry action; the logged-out rendering receives a log-in-again action, which reloads the page because the runtime stays initialised after logout and cannot re-bootstrap in place
291
+
292
+ **When the adapter has no runtime provider**, write a startup module that does the same work. **This module's initialization must execute exactly once per page load**, regardless of how many times the host framework invokes component lifecycle methods.
273
293
 
274
294
  **⚠️ CRITICAL — Initialization must be a module-scoped singleton:**
275
295
 
@@ -293,10 +313,10 @@ The module-scoped singleton avoids this entirely because it is immune to compone
293
313
 
294
314
  **Bootstrap responsibilities:**
295
315
 
296
- 1. **Authenticate** — use the SDK auth client to perform login (OAuth redirect or silent renewal)
297
- 2. **Bootstrap in embedded/mashup mode** — initialize the SDK runtime in mashup mode (not full portal), capturing the render context returned by bootstrap
298
- 3. **Create the component registry** — instantiate the SDK's component registry and register all components exported by the generated components folder's `component-map` registry file
299
- 4. **Register the component creator** — tell the SDK runtime to use the registered components for rendering
316
+ 1. **Authenticate in a popup** — use the SDK auth client to perform login with main-window redirect turned off. The SDK reports a blocked or closed login popup as an unhandled rejection rather than by rejecting the login call, so intercept those rejections and turn them into an error state with a retry action
317
+ 2. **Create the component registry** — only after login, because the SDK core is not available before it. Instantiate the SDK's component registry and register all components exported by the generated components folder's `component-map` registry file
318
+ 3. **Register the component creator** — tell the SDK runtime to use the registered components for rendering, with the fallback component
319
+ 4. **Bootstrap in embedded/mashup mode** — initialize the SDK runtime in mashup mode (not full portal), capturing the render context returned by bootstrap
300
320
 
301
321
  This module should expose:
302
322
 
@@ -311,7 +331,7 @@ The control was resolved and cleared in Step 0.1. If that gate was skipped, stop
311
331
 
312
332
  #### Step 4.1 — Attach the launch
313
333
 
314
- **Wait for the bootstrap readiness signal before calling anything.** The call below reads the `PCore` global, which does not exist until the bootstrap module from Step 3 has resolved. A trigger the user can activate before then throws on an undefined global — and because bootstrap usually wins the race on a warm reload, it fails intermittently and looks like a network fault. Gate the control on the readiness signal that Step 3's module exposes: keep it inert until the signal fires, or await the signal inside the handler before proceeding.
334
+ **Wait for the runtime to report ready before calling anything.** The call below reads the `PCore` global, which does not exist until authentication and bootstrap have completed. On the first launch that is after the user has signed in, so hold the launch until readiness is signalled, then make the call; on later launches the runtime is already ready and the call runs immediately. A call made earlier throws on an undefined global, and because only the first launch is ever early, it fails intermittently and looks like a network fault. Gate on the readiness signal that Step 3 exposes (the ready state of the runtime context when the adapter's runtime provider is used): keep the control's call inert until the signal fires, or await the signal inside the handler before proceeding.
315
335
 
316
336
  On the trigger, call the SDK's mashup API to create a case. It takes three arguments, and an embedded flow needs all three:
317
337
 
@@ -335,6 +355,8 @@ Therefore:
335
355
 
336
356
  **Report dropped pre-fill — do not let it disappear quietly.** When the customer's launch context had values that were clearly meant to seed the case and none of them map to a confirmed property, sending an empty object is correct but silent: the flow works, and the values the user already entered are simply gone. Tell them explicitly — name the properties the case type does accept, name the values that had no home, and state that pre-fill is off until the mapping is confirmed. That mapping is a question for whoever owns the case type; answer it with them, not by inference.
337
357
 
358
+ Phrase this for someone who does not know the case type's property names — for example: "Details your users typed before opening the form won't be filled in yet. Ask your Pega app owner which of these fields can be filled in at the start:" — then list the exact property names, since the case type owner needs them.
359
+
338
360
  **⚠️ CRITICAL — omitting `pageName` renders the wrong thing.**
339
361
 
340
362
  `pyEmbedAssignment` is what narrows the render to the assignment. Without it the runtime returns the **full case view** — stage navigation, a case summary panel, and Details / Case History tabs wrapped around the form. That is a portal experience, not an embedded one, and it is not what the customer asked to embed.
@@ -348,7 +370,7 @@ The failure is easy to miss because it still renders. Two tells:
348
370
 
349
371
  Then reveal the render target resolved in Step 0.2 — open the dialog, navigate to the route, or show the region — so the flow becomes visible where the customer expects it.
350
372
 
351
- If Step 0.4 established that the target does not survive a reload, this is where its first half goes: persist the launch context **before** the create call, since the authentication redirect can happen inside it. The restoring half belongs wherever the application starts up, so that the context is re-established before the flow is mounted.
373
+ If redirect login is configured and Step 0.4 established that the target does not survive a reload, this is where its first half goes: persist the launch context **before** the create call, since the authentication redirect can happen inside it. The restoring half belongs wherever the application starts up, so that the context is re-established before the flow is mounted.
352
374
 
353
375
  Per Step 0.5, this create call must run on **every** launch. Anything that makes it fire only the first time — a guard tied to the runtime being set up rather than to the launch — leaves every later launch showing an empty target. If a guard is needed to stop a single launch creating two cases, key it to the launch and release it when the flow is dismissed.
354
376
 
@@ -373,12 +395,16 @@ Mount the bridge once and keep it mounted, per Step 0.5. Dismissing the flow hid
373
395
  In that target:
374
396
 
375
397
  1. Render the SDK bridge component, passing:
376
- - The render context from bootstrap (contains the root `getPConnect` accessor)
398
+ - The render context from bootstrap (contains the root `getPConnect` accessor), read from the runtime context
377
399
  - The populated component registry
378
400
  - A fallback component (renders when a Pega-requested component is not in the registry)
379
- 2. Wrap with the SDK's required context providers (store context for state access, runtime context for environment)
401
+ 2. Make sure the SDK's required context providers are in place — store context for state access, and runtime context for environment (the runtime provider from Step 3 already supplies the latter)
380
402
  3. The bridge component will recursively resolve and render Pega components from the registry as the case flow progresses
381
403
 
404
+ **Keep the Pega area inside the host's look:**
405
+
406
+ The generated components inherit their font and base text colour rather than setting them, so the element that hosts the Pega container must sit inside the host's base text and theme scope recorded under Global Appearance in the Design Profile. That is usually automatic for a route or a page region. A surface that the host renders outside its application root — commonly a dialog or drawer attached elsewhere in the page — can fall outside that scope. When it does, apply the host's own mechanism for bringing a detached surface into its theme (the way its other dialogs receive it); never re-declare fonts or colours for the Pega container.
407
+
382
408
  **CSS isolation considerations:**
383
409
 
384
410
  Global CSS resets and normalizers commonly strip intrinsic sizing from inline vector graphics and remove default button styling. If the host application uses such resets, scope corrective rules to the Pega rendering container element rather than modifying the global styles:
@@ -386,23 +412,24 @@ Global CSS resets and normalizers commonly strip intrinsic sizing from inline ve
386
412
  - Inline vector graphics within the container should have constrained dimensions (not expand to fill their parent)
387
413
  - Interactive elements within the container should retain cursor indicators
388
414
 
389
- **Verification criterion:** After triggering a case launch, the form content (fields, labels, action controls) is visible and interactive within the resolved render target. The bridge is rendering — not just the container element alone.
415
+ **Verification criterion:** After triggering a case launch, the form content (fields, labels, action controls) is visible and interactive within the resolved render target. The bridge is rendering — not just the container element alone. Text inside the Pega container uses the same font family and base text colour as the host's own content around it.
390
416
 
391
417
  ### Step 6 — Handle flow lifecycle events
392
418
 
393
419
  Subscribe to SDK lifecycle events to manage what happens when the case flow ends. What "return to the customer's UI" means depends on the render target resolved in Step 0.2: a dialog closes, a route navigates back to where the trigger was, and a region reverts to what it showed before.
394
420
 
395
- | Event | Action |
396
- | -------------------------------------------- | ------------------------------------------------------------------------------ |
397
- | Cancellation | Dismiss the render target and return the user to where they triggered the flow |
398
- | Flow completion (assignment processing done) | Dismiss the target, optionally showing a success message or redirecting |
399
- | Error | Display an error state or fallback, log for debugging |
421
+ | Event | Action |
422
+ | -------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
423
+ | Cancellation | Dismiss the render target and return the user to where they triggered the flow |
424
+ | Flow completion (assignment processing done) | Dismiss the target, optionally showing a success message or redirecting |
425
+ | Error | Display an error state or fallback, log for debugging |
426
+ | Logged out | Show the customer's logged-out rendering. Signing in again needs a page reload, because the runtime cannot re-bootstrap in place |
400
427
 
401
428
  Unsubscribe from these events on component teardown to prevent memory leaks.
402
429
 
403
430
  ### Step 7 — Verify the integration
404
431
 
405
- Wiring is not finished until the flow has been observed running. Read and execute `{{SKILL_DIR}}/embedded-flow/run-and-verify-integration.md`, which turns the verification criteria stated throughout this skill into executed checks and defines what may be repaired automatically.
432
+ Wiring is not finished until the flow has been observed running. Read and execute `{{SKILL_DIR}}/embedded-flow/run-and-verify-integration{{SKILL_EXT}}`, which turns the verification criteria stated throughout this skill into executed checks and defines what may be repaired automatically.
406
433
 
407
434
  At minimum it must establish that:
408
435
 
@@ -412,6 +439,7 @@ At minimum it must establish that:
412
439
  4. A generated field retains its value after the commit event
413
440
  5. Completing or cancelling the flow returns the UI to its previous state
414
441
  6. No console errors occur during any of the above
442
+ 7. The form matches the host's base font and text colour, and its fields neither overlap nor overflow
415
443
 
416
444
  Do not report the integration as complete on static checks alone.
417
445
 
@@ -454,23 +482,26 @@ The Pega SDK repository includes a mashup/embedded sample application that demon
454
482
 
455
483
  Common integration failures and their resolutions. These are ordered by how they typically manifest during first-time setup.
456
484
 
457
- | Symptom | Cause | Resolution |
458
- | ---------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
459
- | Application hangs indefinitely on startup — no network requests, no errors in console, readiness signal never fires | The `portalClientId` field is missing or empty in `sdk-config.json`. The auth initializer classifies the session as custom-auth and returns without resolving. | Add `portalClientId` to the `authConfig` section (typically the same value as `mashupClientId`). Ensure `portalClientSecret` and `portalGrantType` are also present (even as empty strings). |
460
- | Authentication succeeds (network shows token exchange) but the readiness signal never fires; UI stays in loading state | The bootstrap initialization ran more than once and a lifecycle-cleanup cancellation flag aborted the in-flight run after auth completed. | Ensure bootstrap is a module-scoped singleton promise (see Step 3). Remove any guard + cancellation flag pattern. |
461
- | The Pega container is mounted but displays nothing — an empty box after case creation | The host application bootstrapped the SDK but never rendered the bridge component with the returned render context. | Confirm that after the readiness signal fires, the bridge component is rendered with the render context's `getPConnect` accessor, inside the SDK's store context provider (see Step 5). |
462
- | 404 errors for the ConstellationJS core script | The core script is not being served from the referenced path. | Verify the reference resolves from the route the flow launches at, and that the toolchain serves the dependency directory. If it does not, serve a copy from the static assets directory instead (see Step 1.1). |
463
- | 404 for `sdk-config.json` | The configuration file is not at the application's served web root, or the route depth at bootstrap time causes the relative fetch to resolve against a nested path. | Move the file to the project's served static directory. If bootstrapping from a nested route, set an explicit document base URL (see Step 2). |
464
- | Inline vector graphics (icons) render at enormous size, filling their parent container | Global CSS resets strip intrinsic sizing from SVG elements. | Scope size constraints on inline vector graphics to the Pega rendering container (see Step 5 CSS isolation note). |
465
- | Action buttons, stage indicators, or navigation controls render as unstyled text | The SDK adapter package's stylesheet is not imported. These components use class-based styling that requires the stylesheet to be loaded. | Import the stylesheet in the application entry point as described in Step 1.2. |
466
- | Case creation renders full case chrome (summary bar, stage progress, case history) instead of just the embedded form | The case was created without `pageName: 'pyEmbedAssignment'`. The server defaults to the full case view. | Pass all three arguments to the mashup API's case-creation call, including the embedded page name (see Step 4.1). |
467
- | OAuth redirect opens a blank page or fails silently | The OAuth callback assets (`auth.html`, `authDone.js`) are missing from the served web root. | Place the auth callback assets as described in Step 1.2. |
485
+ | Symptom | Cause | Resolution |
486
+ | ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
487
+ | Application hangs indefinitely on startup — no network requests, no errors in console, readiness signal never fires | The client identifier for the active login mode is missing or empty in `sdk-config.json` (the observed case is an empty `portalClientId`). The auth initializer classifies the session as custom-auth and returns without resolving. | Populate both `mashupClientId` and `portalClientId` in the `authConfig` section with the same value. Ensure `portalClientSecret` and `portalGrantType` are also present (even as empty strings). |
488
+ | Authentication succeeds (network shows token exchange) but the readiness signal never fires; UI stays in loading state | The bootstrap initialization ran more than once and a lifecycle-cleanup cancellation flag aborted the in-flight run after auth completed. | Ensure bootstrap is a module-scoped singleton promise (see Step 3). Remove any guard + cancellation flag pattern. |
489
+ | The Pega container is mounted but displays nothing — an empty box after case creation | The host application bootstrapped the SDK but never rendered the bridge component with the returned render context. | Confirm that after the readiness signal fires, the bridge component is rendered with the render context's `getPConnect` accessor, inside the SDK's store context provider (see Step 5). |
490
+ | 404 or HTML returned for `/constellation/` runtime files; runtime global never defined after login | The runtime files are not being served at their absolute `/constellation/` URLs, or the toolchain's fallback to the entry document is answering for a missing file. | Serve the bootstrap shell, library manifest, core bundles and lazily loaded chunks as described in Step 1.1, resolved from the installed package. Request each URL directly to confirm it returns the file and not HTML. |
491
+ | 404 for `sdk-config.json` | The configuration file is not at the application's served web root, or the route depth at bootstrap time causes the relative fetch to resolve against a nested path. | Move the file to the project's served static directory. If bootstrapping from a nested route, set an explicit document base URL (see Step 2). |
492
+ | Inline vector graphics (icons) render at enormous size, filling their parent container | Global CSS resets strip intrinsic sizing from SVG elements. | Scope size constraints on inline vector graphics to the Pega rendering container (see Step 5 CSS isolation note). |
493
+ | Action buttons, stage indicators, or navigation controls render as unstyled text | The SDK adapter package's stylesheet is not imported. These components use class-based styling that requires the stylesheet to be loaded. | Import the stylesheet in the application entry point as described in Step 1.2. |
494
+ | Case creation renders full case chrome (summary bar, stage progress, case history) instead of just the embedded form | The case was created without `pageName: 'pyEmbedAssignment'`. The server defaults to the full case view. | Pass all three arguments to the mashup API's case-creation call, including the embedded page name (see Step 4.1). |
495
+ | The login popup opens blank or fails silently | The OAuth callback assets (`auth.html`, `authDone.js`) are missing from the served web root. | Place the auth callback assets as described in Step 1.2. |
496
+ | The error state reports that the login popup was blocked or closed | The browser blocked the popup because login did not start from a user action, popups are disallowed for the site, or the user closed the window. | Start the runtime from the launch action itself (Step 0.5) and have the user allow popups; the retry action re-runs login. |
497
+ | The customer's whole page is replaced by a loading, error or logged-out message | The runtime provider wraps the application instead of only the Pega target. | Move the provider so it wraps only the Pega target (Step 3). |
498
+ | The second launch stalls with no request and the loading state never clears | The runtime provider was unmounted with the target and re-created, so it authenticated and bootstrapped again on an initialised runtime. | Mount the provider once and keep it mounted; hide the target instead of discarding it (Steps 0.5 and 3). |
468
499
 
469
500
  ---
470
501
 
471
502
  ## Notes
472
503
 
473
504
  - The generated components folder (its location is resolved during analysis and recorded in the Design Profile) has zero dependencies beyond the customer's existing UI library and the Pega SDK packages. No additional design system installation is needed.
474
- - The bootstrap module should handle token refresh/silent renewal automatically via the SDK auth client.
505
+ - The runtime startup should handle token refresh/silent renewal automatically via the SDK auth client.
475
506
  - If the customer's app already has authentication, coordinate with their auth flow — the SDK auth client can share tokens if the same OAuth provider is used.
476
507
  - The Pega rendering container can be a modal, a sidebar, an inline section, or a full page. Which one is not a matter of taste — it is resolved in Step 0.2 from what the user asked for or from what their application already does.
@@ -118,7 +118,7 @@ This pattern is design-system agnostic. It defines the **behavioral skeleton** e
118
118
 
119
119
  When implementing the render section with a specific design system:
120
120
 
121
- **1. Check the component-specific skill file** — `{{SKILL_DIR}}/field-skills/<ComponentName>.md` contains a **Design System Mapping** section that describes how to map the component's behavior to a DS primitive. Use it as a starting point.
121
+ **1. Check the component-specific skill file** — `{{SKILL_DIR}}/field-skills/<ComponentName>{{SKILL_EXT}}` contains a **Design System Mapping** section that describes how to map the component's behavior to a DS primitive. Use it as a starting point.
122
122
 
123
123
  **2. If the chosen design system is not covered** — use the **UI control type** field in the same skill file (e.g., `"Combobox / typeahead autocomplete input"`) to identify the closest DS primitive.
124
124
 
@@ -139,6 +139,18 @@ When implementing the render section with a specific design system:
139
139
 
140
140
  ---
141
141
 
142
+ ## Visual Preservation
143
+
144
+ When replacing an existing implementation, the replacement must look the same as the original:
145
+
146
+ 1. **Read the component's companion style file first** (for example a `.css` file in its folder). Note every class's visual intent — spacing, sizing, colours, and layout.
147
+ 2. Reproduce that intent through the new design system's inputs or variants, inline styles, or by keeping the style import — whichever gives the closest match.
148
+ 3. Never silently drop legacy styling utility classes — map each one to an equivalent style.
149
+
150
+ In the embedded flow there is no original to preserve: the customer's look, recorded in the Design Profile, decides instead.
151
+
152
+ ---
153
+
142
154
  ## Event Handling
143
155
 
144
156
  > ⚠️ **CRITICAL — DO NOT DUPLICATE IMPORTS FROM FIELD UTILITIES**
@@ -108,7 +108,7 @@ When an infrastructure component renders another Pega component, resolve it thro
108
108
 
109
109
  The runtime contract — inputs, callback signatures, derivation logic, and localization — is identical regardless of design system. Only the rendered markup changes.
110
110
 
111
- **1. Check the component-specific skill file** — `{{SKILL_DIR}}/infra-skills/<ComponentName>.md` contains a **Design System Mapping** section. Use it as a starting point.
111
+ **1. Check the component-specific skill file** — `{{SKILL_DIR}}/infra-skills/<ComponentName>{{SKILL_EXT}}` contains a **Design System Mapping** section. Use it as a starting point.
112
112
 
113
113
  **2. If the chosen design system is not covered** — use the component purpose description to identify the appropriate primitives (button, stepper, breadcrumb, divider, list).
114
114
 
@@ -129,6 +129,18 @@ The runtime contract — inputs, callback signatures, derivation logic, and loca
129
129
 
130
130
  ---
131
131
 
132
+ ## Visual Preservation
133
+
134
+ When replacing an existing implementation, the replacement must look the same as the original:
135
+
136
+ 1. **Read the component's companion style file first** (for example a `.css` file in its folder). Note every class's visual intent — spacing, sizing, colours, and layout.
137
+ 2. Reproduce that intent through the new design system's inputs or variants, inline styles, or by keeping the style import — whichever gives the closest match.
138
+ 3. Never silently drop legacy styling utility classes — map each one to an equivalent style.
139
+
140
+ In the embedded flow there is no original to preserve: the customer's look, recorded in the Design Profile, decides instead.
141
+
142
+ ---
143
+
132
144
  ## Registration
133
145
 
134
146
  Register infrastructure overrides in the project's component map under the component's Pega name. Because the SDK's own components are contributed as a spread of built-in entries, **an override must appear after that spread** — an entry listed before it is replaced by the SDK's version and the override silently does nothing.