@salesforce/afv-skills 1.46.0 → 1.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (317) hide show
  1. package/package.json +1 -1
  2. package/skills/agentforce-observe/SKILL.md +32 -4
  3. package/skills/agentforce-observe/references/ahm-alerts.md +719 -0
  4. package/skills/consumer-goods-promotion-bo-api-deploy/SKILL.md +275 -0
  5. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/README.md +32 -0
  6. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/SetCommentValue.cls +75 -0
  7. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/SetCommentValue.cls-meta.xml +5 -0
  8. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/interview-answers.json +13 -0
  9. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/payloads/copy.json +10 -0
  10. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/payloads/create.json +20 -0
  11. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/payloads/update.json +16 -0
  12. package/skills/consumer-goods-promotion-bo-api-deploy/references/conventions-and-payload-rules.md +273 -0
  13. package/skills/consumer-goods-promotion-bo-api-deploy/references/generate-and-wire.md +236 -0
  14. package/skills/consumer-goods-promotion-bo-api-deploy/references/reference-example-set-comment-value.md +132 -0
  15. package/skills/consumer-goods-promotion-bo-api-deploy/references/smoke-and-verify.md +211 -0
  16. package/skills/dx-devops-project-manage/SKILL.md +197 -0
  17. package/skills/dx-devops-project-manage/examples/common-workflows.md +197 -0
  18. package/skills/dx-devops-project-manage/references/cli-commands.md +295 -0
  19. package/skills/dx-devops-project-manage/scripts/create-project.sh +48 -0
  20. package/skills/dx-devops-project-manage/scripts/list-projects.sh +51 -0
  21. package/skills/dx-devops-project-manage/scripts/update-project.sh +96 -0
  22. package/skills/education-cloud-academic-calendar-generate/SKILL.md +225 -0
  23. package/skills/education-cloud-academic-calendar-generate/examples/quarter-calendar.json +47 -0
  24. package/skills/education-cloud-academic-calendar-generate/examples/sample-output.md +57 -0
  25. package/skills/education-cloud-academic-calendar-generate/examples/semester-calendar.json +54 -0
  26. package/skills/education-cloud-academic-calendar-generate/references/calendar-systems.md +127 -0
  27. package/skills/education-cloud-academic-calendar-generate/references/date-validation.md +222 -0
  28. package/skills/education-cloud-academic-calendar-generate/references/foundation_prerequisites.md +40 -0
  29. package/skills/education-cloud-academic-calendar-generate/scripts/validate_calendar_dates.py +143 -0
  30. package/skills/education-cloud-course-catalog-migrate/SKILL.md +321 -0
  31. package/skills/education-cloud-course-catalog-migrate/references/gotchas-detail.md +16 -0
  32. package/skills/education-cloud-course-catalog-migrate/references/gotchas.md +16 -0
  33. package/skills/education-cloud-course-catalog-migrate/references/large-catalog-handling.md +42 -0
  34. package/skills/education-cloud-course-catalog-migrate/scripts/batch_courses.py +36 -0
  35. package/skills/education-cloud-course-catalog-migrate/scripts/detect_linked_courses.py +51 -0
  36. package/skills/education-cloud-course-catalog-migrate/scripts/detect_modality_variants.py +48 -0
  37. package/skills/education-cloud-course-catalog-migrate/scripts/resolve_api_version.py +43 -0
  38. package/skills/education-cloud-course-catalog-migrate/scripts/split_course_code.py +39 -0
  39. package/skills/education-cloud-course-catalog-migrate/scripts/validate_completeness.py +54 -0
  40. package/skills/education-cloud-domain-configure/SKILL.md +234 -0
  41. package/skills/education-cloud-domain-configure/references/dependent-features.md +198 -0
  42. package/skills/education-cloud-domain-configure/references/domain-features/academic-operations.md +386 -0
  43. package/skills/education-cloud-domain-configure/references/domain-features/alumni-relations.md +155 -0
  44. package/skills/education-cloud-domain-configure/references/domain-features/cross-domain-dependencies.md +18 -0
  45. package/skills/education-cloud-domain-configure/references/domain-features/industriessettings-toggle-reference.md +43 -0
  46. package/skills/education-cloud-domain-configure/references/domain-features/mentoring.md +198 -0
  47. package/skills/education-cloud-domain-configure/references/domain-features/recruitment-admissions.md +315 -0
  48. package/skills/education-cloud-domain-configure/references/domain-features/student-management.md +155 -0
  49. package/skills/education-cloud-domain-configure/references/domain-features/student-success.md +249 -0
  50. package/skills/education-cloud-domain-configure/references/domain-features.md +27 -0
  51. package/skills/education-cloud-domain-configure/references/gotchas-extended.md +23 -0
  52. package/skills/education-cloud-domain-configure/references/toggle-write-path.md +67 -0
  53. package/skills/education-cloud-domain-configure/scripts/check_license_provisioned.py +62 -0
  54. package/skills/education-cloud-domain-configure/scripts/check_org_edition.py +44 -0
  55. package/skills/education-cloud-domain-configure/scripts/check_permission_assigned.py +39 -0
  56. package/skills/education-cloud-multi-campus-configure/SKILL.md +7 -0
  57. package/skills/education-cloud-multi-campus-configure/references/foundation_prerequisites.md +1 -2
  58. package/skills/education-cloud-student-recruitment-agent-configure/SKILL.md +177 -0
  59. package/skills/education-cloud-student-recruitment-agent-configure/references/agent-and-subagents.md +151 -0
  60. package/skills/education-cloud-student-recruitment-agent-configure/references/customer-narration.md +34 -0
  61. package/skills/education-cloud-student-recruitment-agent-configure/references/execution-model.md +54 -0
  62. package/skills/education-cloud-student-recruitment-agent-configure/references/flows.md +82 -0
  63. package/skills/education-cloud-student-recruitment-agent-configure/references/grounding.md +199 -0
  64. package/skills/education-cloud-student-recruitment-agent-configure/references/permissions.md +183 -0
  65. package/skills/education-cloud-student-recruitment-agent-configure/references/platform-enablement.md +82 -0
  66. package/skills/education-cloud-student-recruitment-agent-configure/references/prerequisites.md +158 -0
  67. package/skills/education-cloud-student-recruitment-agent-configure/references/routing.md +141 -0
  68. package/skills/experience-cms-brand-apply/SKILL.md +5 -5
  69. package/skills/experience-cms-brand-create/SKILL.md +2 -2
  70. package/skills/experience-cms-content-generate/SKILL.md +1 -0
  71. package/skills/experience-cms-content-render/SKILL.md +173 -0
  72. package/skills/experience-cms-content-render/assets/angular/DetailPage.component.ts +25 -0
  73. package/skills/experience-cms-content-render/assets/angular/MediaRenderer.component.ts +133 -0
  74. package/skills/experience-cms-content-render/assets/angular/TypeList.component.ts +38 -0
  75. package/skills/experience-cms-content-render/assets/angular/TypeRenderer.component.ts +90 -0
  76. package/skills/experience-cms-content-render/assets/angular/cms-content.component.ts +248 -0
  77. package/skills/experience-cms-content-render/assets/angular/cms-item.service.ts +100 -0
  78. package/skills/experience-cms-content-render/assets/react/DetailPage.tsx +20 -0
  79. package/skills/experience-cms-content-render/assets/react/MediaRenderer.tsx +129 -0
  80. package/skills/experience-cms-content-render/assets/react/TypeList.tsx +40 -0
  81. package/skills/experience-cms-content-render/assets/react/TypeRenderer.tsx +64 -0
  82. package/skills/experience-cms-content-render/assets/react/heuristicRenderer.tsx +310 -0
  83. package/skills/experience-cms-content-render/assets/react/useCmsItem.ts +129 -0
  84. package/skills/experience-cms-content-render/assets/shared/cmsContentType.ts +49 -0
  85. package/skills/experience-cms-content-render/assets/shared/cmsCore.types.ts +96 -0
  86. package/skills/experience-cms-content-render/assets/shared/externalRefs.ts +55 -0
  87. package/skills/experience-cms-content-render/references/bulk-loading.md +60 -0
  88. package/skills/experience-cms-content-render/references/codegen-guardrails.md +111 -0
  89. package/skills/experience-cms-content-render/references/detail-pages.md +87 -0
  90. package/skills/experience-cms-content-render/references/embed-recipes.md +127 -0
  91. package/skills/experience-cms-content-render/references/failure-modes.md +96 -0
  92. package/skills/experience-cms-content-render/references/heuristic-render-rules.md +131 -0
  93. package/skills/experience-cms-content-render/references/init-scaffold.md +122 -0
  94. package/skills/experience-cms-content-render/references/interaction-model.md +173 -0
  95. package/skills/experience-cms-content-render/references/package-api.md +106 -0
  96. package/skills/experience-cms-content-render/references/schema-sync.md +114 -0
  97. package/skills/experience-cms-content-render/references/styling-scopes.md +65 -0
  98. package/skills/experience-cms-content-render/references/verify.md +49 -0
  99. package/skills/experience-cms-content-type-generate/SKILL.md +2 -2
  100. package/skills/experience-content-media-stock-image-search/SKILL.md +5 -4
  101. package/skills/experience-search-coordinate/SKILL.md +198 -0
  102. package/skills/experience-search-coordinate/assets/search-payload-template.json +25 -0
  103. package/skills/experience-search-coordinate/references/content-route.md +313 -0
  104. package/skills/experience-search-coordinate/references/content-type-discovery.md +57 -0
  105. package/skills/experience-search-coordinate/references/media-route.md +172 -0
  106. package/skills/experience-search-coordinate/references/scope-resolution.md +14 -0
  107. package/skills/experience-ui-bundle-localize/SKILL.md +1 -1
  108. package/skills/experience-ui-bundle-localize/references/i18n-setup.md +5 -3
  109. package/skills/experience-ui-bundle-project-generate/SKILL.md +18 -14
  110. package/skills/experience-ui-bundle-project-generate/references/angular-project-generate.md +22 -0
  111. package/skills/experience-ui-bundle-project-generate/references/react-project-generate.md +20 -0
  112. package/skills/experience-ui-bundle-salesforce-data-access/SKILL.md +58 -54
  113. package/skills/experience-ui-bundle-salesforce-data-access/references/caching.md +6 -0
  114. package/skills/experience-ui-bundle-salesforce-data-access/references/graphiti-cli.md +2 -2
  115. package/skills/experience-ui-bundle-salesforce-data-access/references/migration.md +6 -0
  116. package/skills/experience-ui-bundle-salesforce-data-access/references/rest-and-integration.md +2 -1
  117. package/skills/experience-ui-bundle-salesforce-data-access/references/sdk-api.md +6 -0
  118. package/skills/experience-ui-bundle-site-generate/SKILL.md +59 -8
  119. package/skills/experience-ui-bundle-site-generate/references/configure-metadata-digital-experience.md +8 -3
  120. package/skills/experience-ui-bundle-site-generate/references/configure-metadata-language-settings.md +120 -0
  121. package/skills/life-sciences-fieldsalesrep-coordinate/SKILL.md +336 -0
  122. package/skills/life-sciences-fieldsalesrep-coordinate/references/orchestration-flow.md +143 -0
  123. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-application-flexipage-mapping.md +127 -0
  124. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-deploy-commands.md +116 -0
  125. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-lifesci-metadata-deploy.md +111 -0
  126. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-overview.md +312 -0
  127. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-profile-layout-assignments.md +171 -0
  128. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-state-tracking.md +64 -0
  129. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-trigger-handlers.md +122 -0
  130. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-4-user-provisioning-overview.md +335 -0
  131. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-4-user-provisioning-user-provisioning-details.md +140 -0
  132. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-execution-state-and-recovery.md +196 -0
  133. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-metadata-cache-generation.md +155 -0
  134. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-overview.md +307 -0
  135. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-visit-creation-data.md +211 -0
  136. package/skills/life-sciences-fieldsalesrep-coordinate/references/state-machine-and-changes.md +108 -0
  137. package/skills/life-sciences-kam-coordinate/SKILL.md +241 -0
  138. package/skills/life-sciences-kam-coordinate/references/orchestration-flow.md +152 -0
  139. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-application-flexipage-mapping.md +79 -0
  140. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-deploy-commands.md +131 -0
  141. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-kam-config-records.md +85 -0
  142. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-lifesci-metadata-deploy.md +112 -0
  143. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-overview.md +202 -0
  144. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-profile-layout-assignments.md +67 -0
  145. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-state-tracking.md +65 -0
  146. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-trigger-handlers.md +123 -0
  147. package/skills/life-sciences-kam-coordinate/references/stage-4-participant-role-and-sprint.md +89 -0
  148. package/skills/life-sciences-kam-coordinate/references/stage-5-data-and-plan-templates-overview.md +337 -0
  149. package/skills/life-sciences-kam-coordinate/references/stage-5-data-creation-data.md +248 -0
  150. package/skills/life-sciences-kam-coordinate/references/stage-6-ipad-validation-script.md +35 -0
  151. package/skills/life-sciences-kam-coordinate/references/stage-6-metadata-cache-generation.md +155 -0
  152. package/skills/life-sciences-kam-coordinate/references/stage-6-user-provisioning-details.md +146 -0
  153. package/skills/life-sciences-kam-coordinate/references/stage-6-user-provisioning-overview.md +89 -0
  154. package/skills/life-sciences-kam-coordinate/references/state-machine-and-changes.md +114 -0
  155. package/skills/life-sciences-prerequisites-validate/SKILL.md +138 -0
  156. package/skills/life-sciences-prerequisites-validate/references/checks-org-settings.md +190 -0
  157. package/skills/life-sciences-prerequisites-validate/references/checks-user-and-package.md +211 -0
  158. package/skills/life-sciences-territory-configure/SKILL.md +217 -0
  159. package/skills/life-sciences-territory-configure/references/territory-metadata.md +262 -0
  160. package/skills/platform-dsar-policy-manage/SKILL.md +272 -0
  161. package/skills/platform-dsar-policy-manage/references/configure.md +106 -0
  162. package/skills/platform-dsar-policy-manage/references/export-and-history.md +123 -0
  163. package/skills/platform-dsar-policy-manage/references/gap-analysis-guide.md +150 -0
  164. package/skills/platform-dsar-policy-manage/references/gap-scan.md +129 -0
  165. package/skills/platform-dsar-policy-manage/references/headless-sor.md +59 -0
  166. package/skills/platform-dsar-policy-manage/references/report-format.md +59 -0
  167. package/skills/platform-dsar-policy-manage/scripts/tests/__init__.py +0 -0
  168. package/skills/platform-dsar-policy-manage/scripts/tests/test_validate_policy_tree.py +76 -0
  169. package/skills/platform-dsar-policy-manage/scripts/validate-policy-tree.py +130 -0
  170. package/skills/platform-salesforce-connect-adapter-generate/SKILL.md +359 -0
  171. package/skills/platform-salesforce-connect-adapter-generate/references/official-examples.md +69 -0
  172. package/skills/platform-salesforce-connect-adapter-generate/references/scenarios.md +187 -0
  173. package/skills/service-agentforce-channel-configure/SKILL.md +33 -28
  174. package/skills/service-agentforce-human-escalation-configure/SKILL.md +205 -0
  175. package/skills/service-agentforce-human-escalation-configure/assets/escalation-thresholds.instructions.md +37 -0
  176. package/skills/service-agentforce-human-escalation-configure/assets/force-app/main/default/flows/Human_Escalation_Outbound_Flow.flow-meta.xml +173 -0
  177. package/skills/service-agentforce-human-escalation-configure/assets/package.xml +8 -0
  178. package/skills/service-agentforce-human-escalation-configure/assets/sfdx-project.json +5 -0
  179. package/skills/service-agentforce-human-escalation-configure/references/classifier-contracts.md +103 -0
  180. package/skills/service-agentforce-human-escalation-configure/references/escalation-mechanism.md +63 -0
  181. package/skills/service-agentforce-human-escalation-configure/references/failure-policy.md +44 -0
  182. package/skills/service-agentforce-human-escalation-configure/references/nga-escalation.md +57 -0
  183. package/skills/service-agentforce-human-escalation-configure/references/runtime-verification.md +72 -0
  184. package/skills/service-agentforce-human-escalation-configure/scripts/classify-agent-active.mjs +49 -0
  185. package/skills/service-agentforce-human-escalation-configure/scripts/classify-nga-escalation.mjs +166 -0
  186. package/skills/service-agentforce-human-escalation-configure/scripts/extract-outbound-route.mjs +67 -0
  187. package/skills/service-agentforce-human-escalation-configure/scripts/patch-escalation-surfaces.mjs +131 -0
  188. package/skills/service-agentforce-human-escalation-configure/scripts/tests/__init__.py +0 -0
  189. package/skills/service-agentforce-human-escalation-configure/scripts/tests/_bootstrap.py +249 -0
  190. package/skills/service-agentforce-human-escalation-configure/scripts/tests/test_escalation_contracts.py +899 -0
  191. package/skills/service-agentforce-human-escalation-configure/scripts/verify-and-configure.sh +705 -0
  192. package/skills/service-agentforce-human-escalation-configure/scripts/verify-escalation-config.mjs +89 -0
  193. package/skills/service-de-channel-routing-configure/SKILL.md +13 -5
  194. package/skills/service-de-channel-routing-configure/scripts/tests/test_skill_contract.py +25 -0
  195. package/skills/service-itsm-agentic-setup-agentforce-coordinate/SKILL.md +23 -10
  196. package/skills/service-itsm-agentic-setup-agentforce-coordinate/examples/output-templates.md +63 -48
  197. package/skills/service-itsm-agentic-setup-agentforce-coordinate/scripts/verify-child-verdict.mjs +6 -2
  198. package/skills/service-itsm-agentic-setup-cmdb-coordinate/SKILL.md +20 -27
  199. package/skills/service-native-voice-recording-transcription-configure/SKILL.md +47 -27
  200. package/skills/service-native-voice-recording-transcription-configure/references/thunderbird-voice-settings.md +13 -9
  201. package/skills/service-native-voice-recording-transcription-configure/scripts/enable-recording-transcription.sh +104 -45
  202. package/skills/service-omni-agent-users-create/SKILL.md +96 -0
  203. package/skills/service-omni-agent-users-create/assets/create-users.apex.template +80 -0
  204. package/skills/service-omni-agent-users-create/references/apex-patterns.md +135 -0
  205. package/skills/service-omni-agent-users-create/references/apex-template-notes.md +40 -0
  206. package/skills/service-omni-agent-users-create/scripts/detect-and-create.sh +206 -0
  207. package/skills/service-omni-agent-users-create/scripts/detect-existing.sh +122 -0
  208. package/skills/service-omni-agent-users-create/scripts/run-create.sh +298 -0
  209. package/skills/service-omni-agent-users-create/scripts/tests/test_user_create_security.py +171 -0
  210. package/skills/service-omni-agent-work-sharing-configure/SKILL.md +78 -0
  211. package/skills/service-omni-agent-work-sharing-configure/references/api-notes.md +31 -0
  212. package/skills/service-omni-agent-work-sharing-configure/scripts/configure-and-report.sh +186 -0
  213. package/skills/service-omni-agent-work-sharing-configure/scripts/tests/_bootstrap.py +120 -0
  214. package/skills/service-omni-agent-work-sharing-configure/scripts/tests/test_agent_work_sharing_contracts.py +93 -0
  215. package/skills/service-omni-base-settings-configure/SKILL.md +77 -0
  216. package/skills/service-omni-base-settings-configure/assets/force-app/main/default/settings/OmniChannel.settings-meta.xml +8 -0
  217. package/skills/service-omni-base-settings-configure/assets/package.xml +8 -0
  218. package/skills/service-omni-base-settings-configure/assets/sfdx-project.json +12 -0
  219. package/skills/service-omni-base-settings-configure/references/api-notes.md +121 -0
  220. package/skills/service-omni-base-settings-configure/scripts/configure-and-report.sh +164 -0
  221. package/skills/service-omni-base-settings-configure/scripts/detect-existing.sh +69 -0
  222. package/skills/service-omni-channel-setup-coordinate/SKILL.md +168 -0
  223. package/skills/service-omni-channel-setup-coordinate/examples/output-templates.md +161 -0
  224. package/skills/service-omni-channel-setup-coordinate/references/gap-catalog.md +99 -0
  225. package/skills/service-omni-channel-setup-coordinate/scripts/integration-driver.sh +1542 -0
  226. package/skills/service-omni-channel-setup-coordinate/scripts/tests/__init__.py +0 -0
  227. package/skills/service-omni-channel-setup-coordinate/scripts/tests/_bootstrap.py +223 -0
  228. package/skills/service-omni-channel-setup-coordinate/scripts/tests/test_omni_contracts.py +804 -0
  229. package/skills/service-omni-command-center-analyze/SKILL.md +84 -0
  230. package/skills/service-omni-command-center-analyze/references/api-notes.md +54 -0
  231. package/skills/service-omni-command-center-analyze/scripts/analyze.sh +198 -0
  232. package/skills/service-omni-command-center-analyze/scripts/tests/_bootstrap.py +115 -0
  233. package/skills/service-omni-command-center-analyze/scripts/tests/test_command_center_analyze_contracts.py +165 -0
  234. package/skills/service-omni-permission-set-assign/SKILL.md +88 -0
  235. package/skills/service-omni-permission-set-assign/assets/package.xml +8 -0
  236. package/skills/service-omni-permission-set-assign/references/api-notes.md +143 -0
  237. package/skills/service-omni-permission-set-assign/scripts/verify-and-assign.sh +397 -0
  238. package/skills/service-omni-presence-status-deploy/SKILL.md +87 -0
  239. package/skills/service-omni-presence-status-deploy/assets/package.xml +12 -0
  240. package/skills/service-omni-presence-status-deploy/references/api-notes.md +115 -0
  241. package/skills/service-omni-presence-status-deploy/scripts/deploy-and-report.sh +422 -0
  242. package/skills/service-omni-presence-user-config-deploy/SKILL.md +80 -0
  243. package/skills/service-omni-presence-user-config-deploy/references/api-notes.md +60 -0
  244. package/skills/service-omni-presence-user-config-deploy/scripts/deploy-and-report.sh +261 -0
  245. package/skills/service-omni-presence-user-config-deploy/scripts/tests/_bootstrap.py +106 -0
  246. package/skills/service-omni-presence-user-config-deploy/scripts/tests/test_presence_user_config_contracts.py +142 -0
  247. package/skills/service-omni-queue-deploy/SKILL.md +91 -0
  248. package/skills/service-omni-queue-deploy/references/api-notes.md +140 -0
  249. package/skills/service-omni-queue-deploy/scripts/verify-and-align.sh +470 -0
  250. package/skills/service-omni-queue-members-assign/SKILL.md +93 -0
  251. package/skills/service-omni-queue-members-assign/references/api-notes.md +144 -0
  252. package/skills/service-omni-queue-members-assign/scripts/tests/_bootstrap.py +67 -0
  253. package/skills/service-omni-queue-members-assign/scripts/tests/test_queue_members_contracts.py +73 -0
  254. package/skills/service-omni-queue-members-assign/scripts/verify-and-bind.sh +362 -0
  255. package/skills/service-omni-queue-routing-config-deploy/SKILL.md +101 -0
  256. package/skills/service-omni-queue-routing-config-deploy/references/api-notes.md +127 -0
  257. package/skills/service-omni-queue-routing-config-deploy/scripts/tests/_bootstrap.py +90 -0
  258. package/skills/service-omni-queue-routing-config-deploy/scripts/tests/test_queue_routing_config_contracts.py +70 -0
  259. package/skills/service-omni-queue-routing-config-deploy/scripts/upsert-and-report.sh +538 -0
  260. package/skills/service-omni-routing-flow-deploy/SKILL.md +111 -0
  261. package/skills/service-omni-routing-flow-deploy/assets/force-app/main/default/flows/Omni_Route_Case_Trigger.SkillsBased.flow-meta.xml +94 -0
  262. package/skills/service-omni-routing-flow-deploy/assets/force-app/main/default/flows/Omni_Route_Case_Trigger.flow-meta.xml +88 -0
  263. package/skills/service-omni-routing-flow-deploy/assets/force-app/main/default/flows/Omni_Route_Cases.flow-meta.xml +144 -0
  264. package/skills/service-omni-routing-flow-deploy/assets/force-app/main/default/flows/Omni_Route_VoiceCall_Trigger.SkillsBased.flow-meta.xml +94 -0
  265. package/skills/service-omni-routing-flow-deploy/assets/force-app/main/default/flows/Omni_Route_VoiceCall_Trigger.flow-meta.xml +88 -0
  266. package/skills/service-omni-routing-flow-deploy/assets/force-app/main/default/flows/Omni_Route_VoiceCalls.flow-meta.xml +144 -0
  267. package/skills/service-omni-routing-flow-deploy/assets/package.xml +11 -0
  268. package/skills/service-omni-routing-flow-deploy/assets/sfdx-project.json +11 -0
  269. package/skills/service-omni-routing-flow-deploy/references/api-notes.md +265 -0
  270. package/skills/service-omni-routing-flow-deploy/scripts/deploy-and-report.sh +684 -0
  271. package/skills/service-omni-service-channel-configure/SKILL.md +83 -0
  272. package/skills/service-omni-service-channel-configure/assets/force-app/main/default/serviceChannels/Cases.serviceChannel-meta.xml +9 -0
  273. package/skills/service-omni-service-channel-configure/assets/force-app/main/default/serviceChannels/Incidents.serviceChannel-meta.xml +9 -0
  274. package/skills/service-omni-service-channel-configure/assets/force-app/main/default/serviceChannels/MessagingSessions.serviceChannel-meta.xml +9 -0
  275. package/skills/service-omni-service-channel-configure/assets/force-app/main/default/serviceChannels/VoiceCalls.serviceChannel-meta.xml +9 -0
  276. package/skills/service-omni-service-channel-configure/assets/package.xml +11 -0
  277. package/skills/service-omni-service-channel-configure/assets/sfdx-project.json +12 -0
  278. package/skills/service-omni-service-channel-configure/references/api-notes.md +84 -0
  279. package/skills/service-omni-service-channel-configure/scripts/deploy-and-report.sh +383 -0
  280. package/skills/service-omni-sidebar-configure/SKILL.md +77 -0
  281. package/skills/service-omni-sidebar-configure/references/api-notes.md +51 -0
  282. package/skills/service-omni-sidebar-configure/scripts/enable-and-report.sh +315 -0
  283. package/skills/service-omni-sidebar-configure/scripts/tests/_bootstrap.py +142 -0
  284. package/skills/service-omni-sidebar-configure/scripts/tests/test_sidebar_contracts.py +139 -0
  285. package/skills/service-omni-skills-based-routing-configure/SKILL.md +81 -0
  286. package/skills/service-omni-skills-based-routing-configure/references/api-notes.md +50 -0
  287. package/skills/service-omni-skills-based-routing-configure/scripts/configure-and-report.sh +270 -0
  288. package/skills/service-omni-skills-based-routing-configure/scripts/tests/_bootstrap.py +120 -0
  289. package/skills/service-omni-skills-based-routing-configure/scripts/tests/test_sbr_contracts.py +129 -0
  290. package/skills/service-omni-supervisor-config-deploy/SKILL.md +97 -0
  291. package/skills/service-omni-supervisor-config-deploy/assets/force-app/main/default/omniSupervisorConfigs/Omni_Supervisor.omniSupervisorConfig-meta.xml +9 -0
  292. package/skills/service-omni-supervisor-config-deploy/assets/package.xml +8 -0
  293. package/skills/service-omni-supervisor-config-deploy/assets/sfdx-project.json +12 -0
  294. package/skills/service-omni-supervisor-config-deploy/references/api-notes.md +205 -0
  295. package/skills/service-omni-supervisor-config-deploy/scripts/deploy-and-report.sh +586 -0
  296. package/skills/service-omni-supervisor-config-deploy/scripts/tests/_bootstrap.py +153 -0
  297. package/skills/service-omni-supervisor-config-deploy/scripts/tests/test_supervisor_config_contracts.py +116 -0
  298. package/skills/service-omni-supervisor-permset-assign/SKILL.md +88 -0
  299. package/skills/service-omni-supervisor-permset-assign/references/api-notes.md +48 -0
  300. package/skills/service-omni-supervisor-permset-assign/scripts/verify-and-assign.sh +316 -0
  301. package/skills/service-omni-supervisor-surface-deploy/SKILL.md +85 -0
  302. package/skills/service-omni-supervisor-surface-deploy/references/api-notes.md +47 -0
  303. package/skills/service-omni-supervisor-surface-deploy/scripts/deploy-and-report.sh +216 -0
  304. package/skills/service-omni-supervisor-surface-deploy/scripts/tests/_bootstrap.py +95 -0
  305. package/skills/service-omni-supervisor-surface-deploy/scripts/tests/test_supervisor_surface_contracts.py +154 -0
  306. package/skills/service-omni-supervisor-users-create/SKILL.md +92 -0
  307. package/skills/service-omni-supervisor-users-create/assets/create-supervisors.apex.template +72 -0
  308. package/skills/service-omni-supervisor-users-create/references/apex-patterns.md +73 -0
  309. package/skills/service-omni-supervisor-users-create/references/apex-template-notes.md +41 -0
  310. package/skills/service-omni-supervisor-users-create/scripts/detect-and-create.sh +197 -0
  311. package/skills/service-omni-supervisor-users-create/scripts/detect-existing.sh +112 -0
  312. package/skills/service-omni-supervisor-users-create/scripts/run-create.sh +296 -0
  313. package/skills/service-omni-work-skill-routing-configure/SKILL.md +80 -0
  314. package/skills/service-omni-work-skill-routing-configure/references/api-notes.md +67 -0
  315. package/skills/service-omni-work-skill-routing-configure/scripts/configure-and-report.sh +262 -0
  316. package/skills/service-omni-work-skill-routing-configure/scripts/tests/_bootstrap.py +121 -0
  317. package/skills/service-omni-work-skill-routing-configure/scripts/tests/test_work_skill_routing_contracts.py +161 -0
@@ -0,0 +1,296 @@
1
+ #!/usr/bin/env bash
2
+ # run-create.sh - INTERNAL (invoke via detect-and-create.sh, which enforces the safe_to_write guard): render Apex tokens, execute, parse created users, set passwords via separate System.setPassword; on password failure the user stays active + reset_required (never deactivated). Contract + security: SKILL.md + references/apex-template-notes.md.
3
+
4
+ set -euo pipefail
5
+
6
+ if [ $# -lt 4 ]; then
7
+ echo '{"error":"Usage: bash run-create.sh <org-alias> <count> <profile-id> <org-suffix>"}' >&2
8
+ exit 1
9
+ fi
10
+
11
+ ORG="$1"
12
+ COUNT="$2"
13
+ PROFILE_ID="$3"
14
+ SUFFIX="$4"
15
+
16
+ # Validate every arg BEFORE it is sed-substituted into anonymous Apex. These tokens are interpolated
17
+ # into executable Apex, so anything outside a strict grammar (Apex/sed metacharacters, code) is
18
+ # rejected up front rather than executed.
19
+ if ! [[ "$COUNT" =~ ^[1-9][0-9]{0,2}$ ]]; then
20
+ echo "{\"error\":\"Invalid count '$COUNT' (expected a positive integer 1-999).\"}" >&2; exit 1
21
+ fi
22
+ if ! [[ "$PROFILE_ID" =~ ^[A-Za-z0-9]{15}([A-Za-z0-9]{3})?$ ]]; then
23
+ echo "{\"error\":\"Invalid profile-id '$PROFILE_ID' (expected a 15- or 18-char Salesforce Id).\"}" >&2; exit 1
24
+ fi
25
+ if ! [[ "$SUFFIX" =~ ^[A-Za-z0-9]{1,18}$ ]]; then
26
+ echo "{\"error\":\"Invalid org-suffix '$SUFFIX' (expected 1-18 alphanumeric chars).\"}" >&2; exit 1
27
+ fi
28
+
29
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
30
+ TEMPLATE="$SCRIPT_DIR/../assets/create-supervisors.apex.template"
31
+
32
+ if [ ! -f "$TEMPLATE" ]; then
33
+ echo "{\"error\":\"Apex template not found: $TEMPLATE\"}" >&2
34
+ exit 1
35
+ fi
36
+
37
+ WORK="$(mktemp -d)"
38
+ trap 'rm -rf "$WORK"' EXIT
39
+ RESOLVED="$WORK/create-supervisors.resolved.apex"
40
+
41
+ sed -e "s|__COUNT__|${COUNT}|g" \
42
+ -e "s|__PROFILE_ID__|${PROFILE_ID}|g" \
43
+ -e "s|__SUFFIX__|${SUFFIX}|g" \
44
+ "$TEMPLATE" > "$RESOLVED"
45
+
46
+ APEX_JSON=$(sf apex run --target-org "$ORG" --file "$RESOLVED" --json 2>/dev/null || true)
47
+
48
+ # Strip C0 control chars: sf embeds an unescaped debug log in .result.logs, which jq>=1.7 rejects.
49
+ # This merges the log to one line; the grep below is anchored to tolerate that.
50
+ APEX_JSON=$(printf '%s' "$APEX_JSON" | tr -d '\000-\037')
51
+
52
+ CLI_STATUS=$(echo "$APEX_JSON" | jq -r '.status // 0' 2>/dev/null || echo "0")
53
+ COMPILE_SUCCESS=$(echo "$APEX_JSON" | jq -r '.result.compiled // false' 2>/dev/null || echo "false")
54
+ EXEC_SUCCESS=$(echo "$APEX_JSON" | jq -r '.result.success // false' 2>/dev/null || echo "false")
55
+
56
+ translate_error() {
57
+ local raw="$1"
58
+ case "$raw" in
59
+ *LICENSE_LIMIT_EXCEEDED*)
60
+ echo "Org has reached its user license limit. Free up a license slot (deactivate unused users in Setup > Users) or request a larger CDO from OrgFarm."
61
+ ;;
62
+ *DUPLICATE_USERNAME*)
63
+ echo "Username collision with another Salesforce org (globally unique constraint). Rare - retry the skill; if it persists, another agent may be concurrently running against the same suffix."
64
+ ;;
65
+ *INVALID_EMAIL_ADDRESS*)
66
+ echo "Salesforce rejected the @example.com email. This should never happen - likely a bug in the skill's Apex template. Escalate."
67
+ ;;
68
+ *INSUFFICIENT_ACCESS*|*NoAccessException*)
69
+ echo "Executing user lacks required permission. Ensure the sf-CLI-authenticated user has System Administrator profile or equivalent."
70
+ ;;
71
+ *INVALID_LOGIN*|*INVALID_SESSION_ID*)
72
+ echo "Salesforce session expired. Re-authenticate: sf org login web -a $ORG -r <my-domain-url>"
73
+ ;;
74
+ *)
75
+ echo "$raw"
76
+ ;;
77
+ esac
78
+ }
79
+
80
+ if [ "$CLI_STATUS" != "0" ]; then
81
+ CLI_ERR=$(echo "$APEX_JSON" | jq -r '.message // "Unknown CLI error"' 2>/dev/null)
82
+ FRIENDLY=$(translate_error "$CLI_ERR")
83
+ echo "{\"error\":\"$FRIENDLY\",\"raw\":$(echo "$CLI_ERR" | jq -R .)}" >&2
84
+ exit 1
85
+ fi
86
+
87
+ if [ "$COMPILE_SUCCESS" != "true" ]; then
88
+ COMPILE_ERR=$(echo "$APEX_JSON" | jq -r '.result.compileProblem // "Unknown compile error"' 2>/dev/null)
89
+ COMPILE_LINE=$(echo "$APEX_JSON" | jq -r '.result.line // "?"' 2>/dev/null)
90
+ echo "{\"error\":\"Apex compile failed at line $COMPILE_LINE: $COMPILE_ERR\"}" >&2
91
+ exit 1
92
+ fi
93
+
94
+ if [ "$EXEC_SUCCESS" != "true" ]; then
95
+ EXEC_ERR=$(echo "$APEX_JSON" | jq -r '.result.exceptionMessage // "Unknown execution error"' 2>/dev/null)
96
+ if [ -z "$EXEC_ERR" ] || [ "$EXEC_ERR" = "Unknown execution error" ] || [ "$EXEC_ERR" = "null" ]; then
97
+ EXEC_ERR=$(echo "$APEX_JSON" | jq -r '.message // "Unknown execution error"' 2>/dev/null)
98
+ fi
99
+ FRIENDLY=$(translate_error "$EXEC_ERR")
100
+ echo "{\"error\":\"$FRIENDLY\",\"raw\":$(echo "$EXEC_ERR" | jq -R .)}" >&2
101
+ exit 1
102
+ fi
103
+
104
+ # Parse SUPERVISOR_CREATED|<userId>|<username>|<email> from the log; decode the HTML-encoded pipe
105
+ # (&#124;) that sf emits, else the grep misses every user.
106
+ LOG=$(echo "$APEX_JSON" | jq -r '.result.logs // ""' 2>/dev/null | sed 's/&#124;/|/g')
107
+
108
+ # Anchor on a real 005 Id + @example.com domain so the match ignores the Apex source echoed in the merged log.
109
+ CREATED_RAW=$(echo "$LOG" | grep -oE 'SUPERVISOR_CREATED\|005[a-zA-Z0-9]{15}\|[^|]+@example\.com\|[^|]+@example\.com' || true)
110
+
111
+ if [ -z "$CREATED_RAW" ]; then
112
+ CREATED_USERS_JSON='[]'
113
+ else
114
+ CREATED_USERS_JSON=$(echo "$CREATED_RAW" \
115
+ | awk -F'|' '
116
+ BEGIN { print "[" }
117
+ NR > 1 { printf "," }
118
+ {
119
+ printf "{\"id\":\"%s\",\"username\":\"%s\",\"email\":\"%s\"}", $2, $3, $4
120
+ }
121
+ END { print "]" }
122
+ ')
123
+ if ! echo "$CREATED_USERS_JSON" | jq -c '.' >/dev/null 2>&1; then
124
+ echo "{\"error\":\"Internal parse error: SUPERVISOR_CREATED lines produced invalid JSON. Users may have been created but this script cannot capture them.\",\"raw_lines\":$(echo "$CREATED_RAW" | jq -Rs .)}" >&2
125
+ exit 1
126
+ fi
127
+ CREATED_USERS_JSON=$(echo "$CREATED_USERS_JSON" | jq -c '.')
128
+ fi
129
+
130
+ # Set each User's password via System.setPassword (the only working path for Apex-inserted users).
131
+ # Fail-closed on the TraceFlag gate below; on failure the User stays active + reset_required.
132
+ # Full security rationale: references/apex-template-notes.md.
133
+ ENRICHED_USERS='[]'
134
+ NEEDS_RESET='[]'
135
+ ROLLED_BACK='[]'
136
+
137
+ # Generated passwords are written to a restricted (0600) file and NEVER returned in stdout, so
138
+ # plaintext cannot enter an AI/tool transcript when this leaf is invoked directly. The coordinator
139
+ # passes OMNI_CREDENTIALS_FILE/OMNI_CREDENTIALS_KEY to escrow into its own file; standalone runs
140
+ # default to ./CREDENTIALS.json. File format: { "<key>": [ {username, password}, ... ] }.
141
+ # Secrets never touch argv/env (both visible via process inspection): each {username,password} pair is
142
+ # appended as one JSON line to this 0600 temp file (inside $WORK, mode 0700) and fed to jq only via
143
+ # stdin / --slurpfile. $WORK is removed by the EXIT trap, so the plaintext file never persists.
144
+ CRED_PAIRS_FILE="$WORK/cred-pairs.jsonl"
145
+ : > "$CRED_PAIRS_FILE"; chmod 600 "$CRED_PAIRS_FILE" 2>/dev/null || true
146
+ CRED_COUNT=0
147
+ CRED_FILE="${OMNI_CREDENTIALS_FILE:-$PWD/CREDENTIALS.json}"
148
+ CRED_KEY="${OMNI_CREDENTIALS_KEY:-service-omni-supervisor-users-create}"
149
+ CRED_WRITTEN="false"
150
+ write_credentials() {
151
+ # $1 = path to a JSONL file of {username,password} objects. Secret-bearing pairs are read via
152
+ # --slurpfile (a file, never argv); the existing credentials file is piped in via stdin.
153
+ local pairs_file="$1" existing='{}' tmp
154
+ [ -f "$CRED_FILE" ] && existing=$(cat "$CRED_FILE" 2>/dev/null || echo '{}')
155
+ tmp=$(mktemp) || return 1
156
+ if ! printf '%s' "$existing" | jq --arg k "$CRED_KEY" --slurpfile c "$pairs_file" '. + {($k): $c}' > "$tmp" 2>/dev/null || [ ! -s "$tmp" ]; then
157
+ rm -f "$tmp"; return 1
158
+ fi
159
+ if ! mv "$tmp" "$CRED_FILE" 2>/dev/null; then rm -f "$tmp"; return 1; fi
160
+ chmod 600 "$CRED_FILE" 2>/dev/null || true
161
+ return 0
162
+ }
163
+
164
+ set_password_via_apex() {
165
+ # $1=user_id $2=plaintext_password. Echoes "ok" on success, else the exception text.
166
+ local uid="$1" pw="$2" apex_file res
167
+ apex_file="$WORK/setpw.apex"
168
+ # uid (18-char Id) and pw ([A-Za-z0-9]) can't break out of the Apex string literal.
169
+ printf "System.setPassword('%s', '%s');\n" "$uid" "$pw" > "$apex_file"
170
+ res=$(sf apex run --target-org "$ORG" --file "$apex_file" --json 2>/dev/null | tr -d '\000-\037' || true)
171
+ rm -f "$apex_file"
172
+ if [ "$(echo "$res" | jq -r '.result.success // false' 2>/dev/null)" = "true" ]; then
173
+ echo "ok"
174
+ else
175
+ echo "$res" | jq -r '.result.exceptionMessage // .message // "setPassword failed"' 2>/dev/null
176
+ fi
177
+ }
178
+
179
+ # TraceFlag gate (fail-closed): prove no active TraceFlag exists for the running user BEFORE any
180
+ # System.setPassword, else a password literal could persist to a queryable ApexLog. Cannot prove safe
181
+ # => no password set, users left active + reset_required. See references/apex-template-notes.md.
182
+ TRACEFLAG_SAFE=false
183
+ TRACEFLAG_REASON="TraceFlag state could not be determined"
184
+ ME_UNAME=$(sf org display --target-org "$ORG" --json 2>/dev/null | jq -r '.result.username // empty' 2>/dev/null || true)
185
+ if [ -z "${ME_UNAME:-}" ]; then
186
+ TRACEFLAG_REASON="could not resolve the running user (sf org display failed)"
187
+ else
188
+ ME_UID=$(sf data query --target-org "$ORG" \
189
+ --query "SELECT Id FROM User WHERE Username='$ME_UNAME' LIMIT 1" \
190
+ --json 2>/dev/null | jq -r '.result.records[0].Id // empty' 2>/dev/null || true)
191
+ if [ -z "${ME_UID:-}" ]; then
192
+ TRACEFLAG_REASON="could not resolve the running user's Id"
193
+ else
194
+ NOW_UTC=$(date -u +%Y-%m-%dT%H:%M:%SZ)
195
+ if TF_JSON=$(sf data query --target-org "$ORG" --use-tooling-api \
196
+ --query "SELECT Id FROM TraceFlag WHERE TracedEntityId='$ME_UID' AND ExpirationDate > $NOW_UTC" \
197
+ --json 2>/dev/null) && [ -n "$TF_JSON" ]; then
198
+ TF_STATUS=$(echo "$TF_JSON" | jq -r '.status // 1' 2>/dev/null || echo 1)
199
+ if [ "$TF_STATUS" = "0" ]; then
200
+ TF_COUNT=$(echo "$TF_JSON" | jq -r 'if (.result.totalSize != null) then .result.totalSize elif (.result.records != null) then (.result.records | length) else "unknown" end' 2>/dev/null || echo "unknown")
201
+ if [ "$TF_COUNT" = "0" ]; then
202
+ TRACEFLAG_SAFE=true
203
+ TRACEFLAG_REASON=""
204
+ elif [ "$TF_COUNT" = "unknown" ]; then
205
+ TRACEFLAG_REASON="the TraceFlag query returned an unparseable result"
206
+ else
207
+ TRACEFLAG_REASON="an active Apex debug TraceFlag exists for the running user ($TF_COUNT found)"
208
+ fi
209
+ else
210
+ TRACEFLAG_REASON="the TraceFlag Tooling API query returned an error status"
211
+ fi
212
+ else
213
+ TRACEFLAG_REASON="the TraceFlag Tooling API query failed"
214
+ fi
215
+ fi
216
+ fi
217
+
218
+ if [ "$(echo "$CREATED_USERS_JSON" | jq -r 'length')" -gt 0 ]; then
219
+ while IFS= read -r row; do
220
+ USER_ID=$(echo "$row" | jq -r '.id')
221
+ UNAME=$(echo "$row" | jq -r '.username')
222
+ EMAIL=$(echo "$row" | jq -r '.email')
223
+
224
+ if [ "$TRACEFLAG_SAFE" != "true" ]; then
225
+ # Fail closed: skip setPassword, keep the User active + flag for manual reset.
226
+ NEEDS_RESET=$(echo "$NEEDS_RESET" | jq -c --arg u "$UNAME" '. + [$u]')
227
+ ENRICHED_USERS=$(echo "$ENRICHED_USERS" | jq -c \
228
+ --arg id "$USER_ID" --arg u "$UNAME" --arg e "$EMAIL" \
229
+ '. + [{id: $id, username: $u, email: $e, password: null, password_status: "reset_required", password_error: "skipped: TraceFlag safety could not be proven (fail-closed)"}]')
230
+ continue
231
+ fi
232
+
233
+ # Strong [A-Za-z0-9] password + fixed mixed-class suffix (Salesforce complexity). The || true
234
+ # swallows tr's SIGPIPE (head closes the pipe) so pipefail+set -e don't abort mid-insert.
235
+ RAND="$(LC_ALL=C tr -dc 'A-Za-z0-9' < /dev/urandom 2>/dev/null | head -c 14 || true)"
236
+ PW="${RAND}aB3"
237
+ SETPW_RESULT=$(set_password_via_apex "$USER_ID" "$PW")
238
+
239
+ if [ "$SETPW_RESULT" = "ok" ]; then
240
+ # Feed the SECRET via stdin (never argv/env); username is not secret so --arg is fine.
241
+ printf '%s' "$PW" | jq -Rsc --arg u "$UNAME" '{username: $u, password: .}' >> "$CRED_PAIRS_FILE"
242
+ CRED_COUNT=$((CRED_COUNT + 1))
243
+ ENRICHED_USERS=$(echo "$ENRICHED_USERS" | jq -c \
244
+ --arg id "$USER_ID" --arg u "$UNAME" --arg e "$EMAIL" \
245
+ '. + [{id: $id, username: $u, email: $e, password: null, password_status: "generated"}]')
246
+ else
247
+ # Non-destructive: keep the active User, flag it for a manual password reset.
248
+ NEEDS_RESET=$(echo "$NEEDS_RESET" | jq -c --arg u "$UNAME" '. + [$u]')
249
+ ENRICHED_USERS=$(echo "$ENRICHED_USERS" | jq -c \
250
+ --arg id "$USER_ID" --arg u "$UNAME" --arg e "$EMAIL" --arg r "$SETPW_RESULT" \
251
+ '. + [{id: $id, username: $u, email: $e, password: null, password_status: "reset_required", password_error: $r}]')
252
+ fi
253
+ done < <(echo "$CREATED_USERS_JSON" | jq -c '.[]')
254
+ fi
255
+
256
+ # Escrow generated passwords to the restricted file; never emit plaintext in stdout. Fail-closed:
257
+ # if escrow fails, the passwords were set on-org but cannot be handed back, so flag those users for a
258
+ # manual reset rather than leaking the plaintext.
259
+ CRED_WARNING=""
260
+ if [ "$CRED_COUNT" -gt 0 ]; then
261
+ if write_credentials "$CRED_PAIRS_FILE"; then
262
+ CRED_WRITTEN="true"
263
+ else
264
+ CRED_WARNING="Passwords were set on the created users but could NOT be escrowed to the credentials file ($CRED_FILE); plaintext was deliberately NOT emitted to stdout. Reset these users' passwords in Setup > Users."
265
+ # Escrow failed → the plaintext is unrecoverable, so these users genuinely need a manual reset:
266
+ # add them to users_needing_password_reset (not just the per-user status) before flipping status.
267
+ ESCROW_FAILED_UNAMES=$(echo "$ENRICHED_USERS" | jq -c '[ .[] | select(.password_status=="generated") | .username ]')
268
+ NEEDS_RESET=$(jq -c -n --argjson a "$NEEDS_RESET" --argjson b "$ESCROW_FAILED_UNAMES" '$a + $b | unique')
269
+ ENRICHED_USERS=$(echo "$ENRICHED_USERS" | jq -c '[ .[] | if .password_status=="generated" then (.password_status="reset_required" | .password_error="escrow_failed") else . end ]')
270
+ fi
271
+ fi
272
+
273
+ # Surface why password generation was skipped when the TraceFlag gate failed.
274
+ SECURITY_WARNING=""
275
+ if [ "$TRACEFLAG_SAFE" != "true" ]; then
276
+ SECURITY_WARNING="Password generation was SKIPPED (fail-closed) because ${TRACEFLAG_REASON}. No System.setPassword was executed, so no plaintext could enter an ApexLog. The created users are ACTIVE and flagged password_status:\"reset_required\" - set their passwords in Setup > Users after confirming no debug TraceFlag is active, or disable the TraceFlag and re-run."
277
+ fi
278
+ [ -n "$CRED_WARNING" ] && SECURITY_WARNING="${SECURITY_WARNING:+$SECURITY_WARNING }$CRED_WARNING"
279
+
280
+ jq -n \
281
+ --argjson created "$ENRICHED_USERS" \
282
+ --argjson needs_reset "$NEEDS_RESET" \
283
+ --argjson rolled_back "$ROLLED_BACK" \
284
+ --arg security_warning "$SECURITY_WARNING" \
285
+ --arg cred_written "$CRED_WRITTEN" \
286
+ --arg cred_file "$CRED_FILE" \
287
+ '{
288
+ created_users: $created,
289
+ created_count: ($created | length),
290
+ users_needing_password_reset: $needs_reset,
291
+ rolled_back_users: $rolled_back,
292
+ credentials_written: ($cred_written == "true"),
293
+ credentials_file: (if $cred_written == "true" then $cred_file else null end),
294
+ security_warning: (if $security_warning == "" then null else $security_warning end),
295
+ security_note: "Passwords are set via anonymous Apex System.setPassword. The plaintext appears in the inline executeAnonymous debug log and, ONLY when a debug-log TraceFlag is active for the running user, in a queryable ApexLog row. To avoid ever persisting plaintext to a log, this script FAILS CLOSED BEFORE the first System.setPassword: it proves via a SOQL-filtered Tooling API query (ExpirationDate > now) that no active TraceFlag exists for the running user. If safety cannot be positively proven - the running user cannot be resolved, the Tooling API query fails or is unparseable, or any active TraceFlag exists - NO password is generated at all; the created users are left ACTIVE and flagged password_status:\"reset_required\", and security_warning explains why. Generated passwords are NEVER returned in this output; they are written to a restricted 0600 credentials_file (default ./CREDENTIALS.json, or OMNI_CREDENTIALS_FILE) so plaintext cannot enter a tool/AI transcript. Read the file once, distribute securely, then delete it. Set passwords for reset_required users in Setup > Users after ensuring no debug TraceFlag is active (or disable the TraceFlag and re-run)."
296
+ }'
@@ -0,0 +1,80 @@
1
+ ---
2
+ name: service-omni-work-skill-routing-configure
3
+ description: "Use to author an Omni WorkSkillRouting rule (field-based skill criteria): map a related-entity field value to a required Omni Skill (e.g. add the Voice skill when Case.Origin = Phone), deployed as one WorkSkillRouting record via the Metadata API. Idempotent via the Metadata API files[].state signal; one rule per related entity. Triggers: add field-based skill routing, route by a Case field to a skill, route by a MessagingSession field to a skill, configure attribute-based skills routing, require an Omni skill for a field value. Do not use to create the Skill or bind agents to it (service-omni-skills-based-routing-configure), to create agent users, or to configure queues."
4
+ allowed-tools: Bash Read Write Edit Glob Grep
5
+ metadata:
6
+ version: "1.0"
7
+ domains: ["Service"]
8
+ minApiVersion: "66.0"
9
+ relatedSkills:
10
+ - "service-omni-base-settings-configure"
11
+ - "service-omni-channel-setup-coordinate"
12
+ - "service-omni-skills-based-routing-configure"
13
+ accessCheck:
14
+ - type: license
15
+ value: ServiceCloud
16
+ cliTools:
17
+ - tool: ["jq"]
18
+ semver: ">=1.6"
19
+ - tool: ["python3"]
20
+ semver: ">=3.8"
21
+ - tool: ["sf"]
22
+ semver: ">=2.139.6"
23
+ ---
24
+
25
+ # service-omni-work-skill-routing-configure
26
+
27
+ Author an Omni **WorkSkillRouting** rule so work is routed to agents by a **field value on the work record**, not just by skills the agent happens to hold. Where `service-omni-skills-based-routing-configure` makes an agent *routable* (Skill + ServiceResource + ServiceResourceSkill), this skill decides *which skill a work item requires* based on one of its fields — for example "when `Case.Origin` = `Phone`, require the `Voice` skill". The rule is one `WorkSkillRouting` record (a header plus one `workSkillRoutingAttributes` mapping) deployed via the Metadata API. It runs after the referenced Skill exists and belongs to the same routing family coordinated by `service-omni-channel-setup-coordinate`.
28
+
29
+ ## Inputs
30
+
31
+ ```bash
32
+ bash scripts/configure-and-report.sh <org-alias> <related_entity> <field> <skill> <value> [rule_master_label]
33
+ ```
34
+
35
+ - `org-alias` (required).
36
+ - `related_entity` (required). The sObject the rule applies to (e.g. `Case`, `MessagingSession`, `LiveChatTranscript`, `Lead`, `VoiceCall`).
37
+ - `field` (required). The field the attribute evaluates (e.g. `Case.Origin` or `Origin`). Bare standard fields are qualified with the related entity before deploy, so `Origin` becomes `Case.Origin` instead of being misread as a custom-field metadata name.
38
+ - `skill` (required). The Omni `Skill` DeveloperName required when the field matches (e.g. `Voice`).
39
+ - `value` (required). The field value that maps to the skill (e.g. `Phone`). Plain values only; XML-reserved characters are not supported.
40
+ - `rule_master_label` (optional). MasterLabel for the rule; defaults to `<related_entity> Skill Routing`.
41
+
42
+ Env overrides: `RULE_DEVELOPER_NAME` (fullName of the rule, default the related-entity name — one rule per entity), `IS_ACTIVE` (default `true`), `SKILL_LEVEL` (0–10), `SKILL_PRIORITY` (0–10, additional-skill drop order), `IS_ADDITIONAL_SKILL` (`true`/`false`).
43
+
44
+ ## Preconditions and safety
45
+
46
+ - Target org authenticated via `sf` CLI, Service Cloud license, `sf` CLI ≥ 2.139.6.
47
+ - Omni-Channel base settings enabled with **skills-based routing** turned on (`service-omni-base-settings-configure`).
48
+ - The referenced `Skill` already exists (`service-omni-skills-based-routing-configure`).
49
+ - The three-way `safe_to_write` production guard applies.
50
+
51
+ ## Run
52
+
53
+ 1. **safe_to_write** — query `Organization`; refuse to write to a real production org.
54
+ 2. **Skill prereq** — query `Skill` by DeveloperName; if absent, block and point at `service-omni-skills-based-routing-configure`.
55
+ 3. **Merge** — read the existing `WorkSkillRouting.Metadata` through the Tooling API, preserve unrelated attributes, and replace or append only the requested `(field, value)` mapping. An inconclusive read blocks the write; `WSR_REPLACE=1` is the explicit destructive-replacement escape hatch.
56
+ 4. **Deploy** — materialize the merged `WorkSkillRouting` record (elements in XSD/alphabetical order) and deploy it via the Metadata API (async + poll to a terminal state).
57
+ 5. **Classify** — read `files[].state` (`Created` / `Changed` / `Unchanged`) to report `created` / `updated` / `reused`.
58
+
59
+ ## Behavior
60
+
61
+ **Idempotent + merge-safe.** WorkSkillRouting permits a single rule per related entity, so the rule's fullName defaults to the entity name. Re-running the same mapping reports `reused`; a new mapping is merged into the existing attribute list; changing the same field/value mapping updates only that entry. The skill never silently replaces an existing rule when its current metadata could not be read.
62
+
63
+ **Graceful degradation.** WorkSkillRouting is not provisioned on every org (some trials/CDOs). A deploy failure shaped like `INVALID_TYPE` / "not available" / "WorkSkillRouting" is reported as `blocked` with a clear limitation message and a pointer to base settings — the skill surfaces the limitation rather than crashing.
64
+
65
+ ## Output contract
66
+
67
+ A single JSON object: `status` ∈ `created` | `updated` | `reused` | `blocked` (plus `action_needed` in plan mode), `rule` (`{developer_name, master_label, related_entity, is_active, state}`), `attribute` (`{field, skill, value, skill_level, skill_priority, is_additional_skill}`), `merge` (`{merged_from_existing, attribute_count, preserved_count}`), `deploy_id`, `manual_actions`, `blocking_issue`.
68
+
69
+ ## Limitations
70
+
71
+ - One field→skill mapping per invocation and one rule per related entity. Multiple invocations safely accumulate attributes on that rule.
72
+ - Does not create the Skill, ServiceResources, agent users, queues, or presence configuration.
73
+ - Field/value correctness is validated by the platform at deploy time; an invalid field or value surfaces as a `blocked` deploy failure.
74
+
75
+ ## References
76
+
77
+ | File | When to read |
78
+ |---|---|
79
+ | `references/api-notes.md` | WorkSkillRouting metadata shape, XSD element order, one-rule-per-entity constraint, attribute fields, and graceful-degradation triggers |
80
+ | `scripts/tests/test_work_skill_routing_contracts.py` | When validating changes — run `python3 scripts/tests/test_work_skill_routing_contracts.py` from this skill directory |
@@ -0,0 +1,67 @@
1
+ # WorkSkillRouting - API notes
2
+
3
+ ## Metadata type
4
+
5
+ `WorkSkillRouting` is a Metadata API type (also queryable via the Tooling API). It stores a set
6
+ of `WorkSkillRoutingAttribute` mappings that route a work item to an agent who holds the required
7
+ skills. It extends `Metadata` and inherits `fullName`.
8
+
9
+ Source path convention used by this skill:
10
+
11
+ ```text
12
+ force-app/main/default/workSkillRoutings/<fullName>.workSkillRouting-meta.xml
13
+ ```
14
+
15
+ ## Record shape (XSD / alphabetical element order)
16
+
17
+ ```xml
18
+ <?xml version="1.0" encoding="UTF-8"?>
19
+ <WorkSkillRouting xmlns="http://soap.sforce.com/2006/04/metadata">
20
+ <isActive>true</isActive>
21
+ <masterLabel>Case Skill Routing</masterLabel>
22
+ <relatedEntity>Case</relatedEntity>
23
+ <workSkillRoutingAttributes>
24
+ <field>Case.Origin</field>
25
+ <skill>Voice</skill>
26
+ <value>Phone</value>
27
+ </workSkillRoutingAttributes>
28
+ </WorkSkillRouting>
29
+ ```
30
+
31
+ Header fields:
32
+
33
+ | Field | Type | Notes |
34
+ |---|---|---|
35
+ | `isActive` | boolean | Required. Whether the rule is evaluated. |
36
+ | `masterLabel` | string | Required. Internal (untranslated) label. |
37
+ | `relatedEntity` | string | Required. The sObject the attributes apply to. |
38
+ | `workSkillRoutingAttributes` | array | One or more field-value -> skill mappings. |
39
+
40
+ Attribute fields (emitted alphabetically: `field`, `isAdditionalSkill`, `skill`, `skillLevel`,
41
+ `skillPriority`, `value`):
42
+
43
+ | Field | Type | Notes |
44
+ |---|---|---|
45
+ | `field` | string | Required. Field the attribute evaluates. |
46
+ | `isAdditionalSkill` | boolean | Additional skills are dropped after the routing-config timeout so a best-match agent can still take the work. |
47
+ | `skill` | string | Required. Skill DeveloperName required when the field matches `value`. |
48
+ | `skillLevel` | int | 0–10. |
49
+ | `skillPriority` | int | 0–10. Drop order for additional skills (9–10 dropped first, 0–1 last). API 49.0+. |
50
+ | `value` | string | Required. Field value mapped to the skill. |
51
+
52
+ ## One rule per entity
53
+
54
+ Only one `WorkSkillRouting` rule is permitted per `relatedEntity`. This skill therefore defaults the
55
+ rule fullName to the related-entity name (overridable via `RULE_DEVELOPER_NAME`), so re-runs converge
56
+ on the same record instead of creating duplicates. Idempotency is read from the Metadata API
57
+ `files[].state`: `Created` -> `created`, `Changed` -> `updated`, `Unchanged` -> `reused`.
58
+
59
+ ## Prerequisites and graceful degradation
60
+
61
+ - The referenced `Skill` must exist first (`service-omni-skills-based-routing-configure`); the skill
62
+ queries `Skill` by DeveloperName and blocks with that pointer when it is missing.
63
+ - Skills-based routing must be enabled in Omni-Channel settings
64
+ (`service-omni-base-settings-configure`).
65
+ - WorkSkillRouting is not provisioned on every org (some trials/CDOs). Deploy failures shaped like
66
+ `INVALID_TYPE`, "not available", or naming `WorkSkillRouting` are reported as `blocked` with a
67
+ limitation message rather than crashing, so a coordinator can continue.