@salesforce/afv-skills 1.45.0 → 1.47.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 (171) 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/automation-flow-generate/SKILL.md +11 -5
  5. package/skills/consumer-goods-promotion-bo-api-deploy/SKILL.md +275 -0
  6. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/README.md +32 -0
  7. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/SetCommentValue.cls +75 -0
  8. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/SetCommentValue.cls-meta.xml +5 -0
  9. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/interview-answers.json +13 -0
  10. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/payloads/copy.json +10 -0
  11. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/payloads/create.json +20 -0
  12. package/skills/consumer-goods-promotion-bo-api-deploy/assets/set-comment-value/payloads/update.json +16 -0
  13. package/skills/consumer-goods-promotion-bo-api-deploy/references/conventions-and-payload-rules.md +273 -0
  14. package/skills/consumer-goods-promotion-bo-api-deploy/references/generate-and-wire.md +236 -0
  15. package/skills/consumer-goods-promotion-bo-api-deploy/references/reference-example-set-comment-value.md +132 -0
  16. package/skills/consumer-goods-promotion-bo-api-deploy/references/smoke-and-verify.md +211 -0
  17. package/skills/dx-code-analyzer-configure/scripts/validate-config.sh +14 -10
  18. package/skills/dx-code-analyzer-run/scripts/apply-fixes.js +45 -4
  19. package/skills/dx-code-analyzer-run/scripts/describe-rule.js +52 -32
  20. package/skills/dx-devops-project-manage/SKILL.md +197 -0
  21. package/skills/dx-devops-project-manage/examples/common-workflows.md +197 -0
  22. package/skills/dx-devops-project-manage/references/cli-commands.md +295 -0
  23. package/skills/dx-devops-project-manage/scripts/create-project.sh +48 -0
  24. package/skills/dx-devops-project-manage/scripts/list-projects.sh +51 -0
  25. package/skills/dx-devops-project-manage/scripts/update-project.sh +96 -0
  26. package/skills/education-cloud-academic-calendar-generate/SKILL.md +225 -0
  27. package/skills/education-cloud-academic-calendar-generate/examples/quarter-calendar.json +47 -0
  28. package/skills/education-cloud-academic-calendar-generate/examples/sample-output.md +57 -0
  29. package/skills/education-cloud-academic-calendar-generate/examples/semester-calendar.json +54 -0
  30. package/skills/education-cloud-academic-calendar-generate/references/calendar-systems.md +127 -0
  31. package/skills/education-cloud-academic-calendar-generate/references/date-validation.md +222 -0
  32. package/skills/education-cloud-academic-calendar-generate/references/foundation_prerequisites.md +40 -0
  33. package/skills/education-cloud-academic-calendar-generate/scripts/validate_calendar_dates.py +143 -0
  34. package/skills/education-cloud-course-catalog-migrate/SKILL.md +321 -0
  35. package/skills/education-cloud-course-catalog-migrate/references/gotchas-detail.md +16 -0
  36. package/skills/education-cloud-course-catalog-migrate/references/gotchas.md +16 -0
  37. package/skills/education-cloud-course-catalog-migrate/references/large-catalog-handling.md +42 -0
  38. package/skills/education-cloud-course-catalog-migrate/scripts/batch_courses.py +36 -0
  39. package/skills/education-cloud-course-catalog-migrate/scripts/detect_linked_courses.py +51 -0
  40. package/skills/education-cloud-course-catalog-migrate/scripts/detect_modality_variants.py +48 -0
  41. package/skills/education-cloud-course-catalog-migrate/scripts/resolve_api_version.py +43 -0
  42. package/skills/education-cloud-course-catalog-migrate/scripts/split_course_code.py +39 -0
  43. package/skills/education-cloud-course-catalog-migrate/scripts/validate_completeness.py +54 -0
  44. package/skills/education-cloud-multi-campus-configure/references/foundation_prerequisites.md +3 -5
  45. package/skills/education-cloud-student-recruitment-agent-configure/SKILL.md +177 -0
  46. package/skills/education-cloud-student-recruitment-agent-configure/references/agent-and-subagents.md +151 -0
  47. package/skills/education-cloud-student-recruitment-agent-configure/references/customer-narration.md +34 -0
  48. package/skills/education-cloud-student-recruitment-agent-configure/references/execution-model.md +54 -0
  49. package/skills/education-cloud-student-recruitment-agent-configure/references/flows.md +82 -0
  50. package/skills/education-cloud-student-recruitment-agent-configure/references/grounding.md +199 -0
  51. package/skills/education-cloud-student-recruitment-agent-configure/references/permissions.md +183 -0
  52. package/skills/education-cloud-student-recruitment-agent-configure/references/platform-enablement.md +82 -0
  53. package/skills/education-cloud-student-recruitment-agent-configure/references/prerequisites.md +158 -0
  54. package/skills/education-cloud-student-recruitment-agent-configure/references/routing.md +141 -0
  55. package/skills/experience-cms-brand-apply/SKILL.md +5 -5
  56. package/skills/experience-cms-brand-create/SKILL.md +2 -2
  57. package/skills/experience-cms-content-generate/SKILL.md +1 -0
  58. package/skills/experience-cms-content-render/SKILL.md +173 -0
  59. package/skills/experience-cms-content-render/assets/angular/DetailPage.component.ts +25 -0
  60. package/skills/experience-cms-content-render/assets/angular/MediaRenderer.component.ts +133 -0
  61. package/skills/experience-cms-content-render/assets/angular/TypeList.component.ts +38 -0
  62. package/skills/experience-cms-content-render/assets/angular/TypeRenderer.component.ts +90 -0
  63. package/skills/experience-cms-content-render/assets/angular/cms-content.component.ts +248 -0
  64. package/skills/experience-cms-content-render/assets/angular/cms-item.service.ts +100 -0
  65. package/skills/experience-cms-content-render/assets/react/DetailPage.tsx +20 -0
  66. package/skills/experience-cms-content-render/assets/react/MediaRenderer.tsx +129 -0
  67. package/skills/experience-cms-content-render/assets/react/TypeList.tsx +40 -0
  68. package/skills/experience-cms-content-render/assets/react/TypeRenderer.tsx +64 -0
  69. package/skills/experience-cms-content-render/assets/react/heuristicRenderer.tsx +310 -0
  70. package/skills/experience-cms-content-render/assets/react/useCmsItem.ts +129 -0
  71. package/skills/experience-cms-content-render/assets/shared/cmsContentType.ts +49 -0
  72. package/skills/experience-cms-content-render/assets/shared/cmsCore.types.ts +96 -0
  73. package/skills/experience-cms-content-render/assets/shared/externalRefs.ts +55 -0
  74. package/skills/experience-cms-content-render/references/bulk-loading.md +60 -0
  75. package/skills/experience-cms-content-render/references/codegen-guardrails.md +111 -0
  76. package/skills/experience-cms-content-render/references/detail-pages.md +87 -0
  77. package/skills/experience-cms-content-render/references/embed-recipes.md +127 -0
  78. package/skills/experience-cms-content-render/references/failure-modes.md +96 -0
  79. package/skills/experience-cms-content-render/references/heuristic-render-rules.md +131 -0
  80. package/skills/experience-cms-content-render/references/init-scaffold.md +122 -0
  81. package/skills/experience-cms-content-render/references/interaction-model.md +173 -0
  82. package/skills/experience-cms-content-render/references/package-api.md +106 -0
  83. package/skills/experience-cms-content-render/references/schema-sync.md +114 -0
  84. package/skills/experience-cms-content-render/references/styling-scopes.md +65 -0
  85. package/skills/experience-cms-content-render/references/verify.md +49 -0
  86. package/skills/experience-cms-content-type-generate/SKILL.md +2 -2
  87. package/skills/experience-content-media-stock-image-search/SKILL.md +5 -4
  88. package/skills/experience-search-coordinate/SKILL.md +198 -0
  89. package/skills/experience-search-coordinate/assets/search-payload-template.json +25 -0
  90. package/skills/experience-search-coordinate/references/content-route.md +313 -0
  91. package/skills/experience-search-coordinate/references/content-type-discovery.md +57 -0
  92. package/skills/experience-search-coordinate/references/media-route.md +172 -0
  93. package/skills/experience-search-coordinate/references/scope-resolution.md +14 -0
  94. package/skills/experience-ui-bundle-localize/SKILL.md +1 -1
  95. package/skills/experience-ui-bundle-localize/references/i18n-setup.md +5 -3
  96. package/skills/experience-ui-bundle-project-generate/SKILL.md +18 -14
  97. package/skills/experience-ui-bundle-project-generate/references/angular-project-generate.md +22 -0
  98. package/skills/experience-ui-bundle-project-generate/references/react-project-generate.md +20 -0
  99. package/skills/experience-ui-bundle-salesforce-data-access/SKILL.md +58 -54
  100. package/skills/experience-ui-bundle-salesforce-data-access/references/caching.md +6 -0
  101. package/skills/experience-ui-bundle-salesforce-data-access/references/graphiti-cli.md +2 -2
  102. package/skills/experience-ui-bundle-salesforce-data-access/references/migration.md +6 -0
  103. package/skills/experience-ui-bundle-salesforce-data-access/references/rest-and-integration.md +2 -1
  104. package/skills/experience-ui-bundle-salesforce-data-access/references/sdk-api.md +6 -0
  105. package/skills/experience-ui-bundle-site-generate/SKILL.md +59 -8
  106. package/skills/experience-ui-bundle-site-generate/references/configure-metadata-digital-experience.md +8 -3
  107. package/skills/experience-ui-bundle-site-generate/references/configure-metadata-language-settings.md +120 -0
  108. package/skills/life-sciences-fieldsalesrep-coordinate/SKILL.md +336 -0
  109. package/skills/life-sciences-fieldsalesrep-coordinate/references/orchestration-flow.md +143 -0
  110. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-application-flexipage-mapping.md +127 -0
  111. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-deploy-commands.md +116 -0
  112. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-lifesci-metadata-deploy.md +111 -0
  113. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-overview.md +312 -0
  114. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-profile-layout-assignments.md +171 -0
  115. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-state-tracking.md +64 -0
  116. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-2-starter-config-trigger-handlers.md +122 -0
  117. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-4-user-provisioning-overview.md +335 -0
  118. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-4-user-provisioning-user-provisioning-details.md +140 -0
  119. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-execution-state-and-recovery.md +196 -0
  120. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-metadata-cache-generation.md +155 -0
  121. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-overview.md +307 -0
  122. package/skills/life-sciences-fieldsalesrep-coordinate/references/stage-5-visit-creation-visit-creation-data.md +211 -0
  123. package/skills/life-sciences-fieldsalesrep-coordinate/references/state-machine-and-changes.md +108 -0
  124. package/skills/life-sciences-kam-coordinate/SKILL.md +241 -0
  125. package/skills/life-sciences-kam-coordinate/references/orchestration-flow.md +152 -0
  126. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-application-flexipage-mapping.md +79 -0
  127. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-deploy-commands.md +131 -0
  128. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-kam-config-records.md +85 -0
  129. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-lifesci-metadata-deploy.md +112 -0
  130. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-overview.md +202 -0
  131. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-profile-layout-assignments.md +67 -0
  132. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-state-tracking.md +65 -0
  133. package/skills/life-sciences-kam-coordinate/references/stage-2-starter-config-trigger-handlers.md +123 -0
  134. package/skills/life-sciences-kam-coordinate/references/stage-4-participant-role-and-sprint.md +89 -0
  135. package/skills/life-sciences-kam-coordinate/references/stage-5-data-and-plan-templates-overview.md +337 -0
  136. package/skills/life-sciences-kam-coordinate/references/stage-5-data-creation-data.md +248 -0
  137. package/skills/life-sciences-kam-coordinate/references/stage-6-ipad-validation-script.md +35 -0
  138. package/skills/life-sciences-kam-coordinate/references/stage-6-metadata-cache-generation.md +155 -0
  139. package/skills/life-sciences-kam-coordinate/references/stage-6-user-provisioning-details.md +146 -0
  140. package/skills/life-sciences-kam-coordinate/references/stage-6-user-provisioning-overview.md +89 -0
  141. package/skills/life-sciences-kam-coordinate/references/state-machine-and-changes.md +114 -0
  142. package/skills/life-sciences-prerequisites-validate/SKILL.md +138 -0
  143. package/skills/life-sciences-prerequisites-validate/references/checks-org-settings.md +190 -0
  144. package/skills/life-sciences-prerequisites-validate/references/checks-user-and-package.md +211 -0
  145. package/skills/life-sciences-territory-configure/SKILL.md +217 -0
  146. package/skills/life-sciences-territory-configure/references/territory-metadata.md +262 -0
  147. package/skills/platform-apex-logs-debug/SKILL.md +7 -7
  148. package/skills/platform-custom-application-generate/SKILL.md +4 -4
  149. package/skills/platform-custom-object-generate/SKILL.md +7 -7
  150. package/skills/platform-custom-tab-generate/SKILL.md +1 -1
  151. package/skills/platform-dsar-policy-manage/SKILL.md +272 -0
  152. package/skills/platform-dsar-policy-manage/references/configure.md +106 -0
  153. package/skills/platform-dsar-policy-manage/references/export-and-history.md +123 -0
  154. package/skills/platform-dsar-policy-manage/references/gap-analysis-guide.md +150 -0
  155. package/skills/platform-dsar-policy-manage/references/gap-scan.md +129 -0
  156. package/skills/platform-dsar-policy-manage/references/headless-sor.md +59 -0
  157. package/skills/platform-dsar-policy-manage/references/report-format.md +59 -0
  158. package/skills/platform-dsar-policy-manage/scripts/tests/__init__.py +0 -0
  159. package/skills/platform-dsar-policy-manage/scripts/tests/test_validate_policy_tree.py +76 -0
  160. package/skills/platform-dsar-policy-manage/scripts/validate-policy-tree.py +130 -0
  161. package/skills/platform-flexipage-generate/SKILL.md +4 -0
  162. package/skills/platform-list-view-generate/SKILL.md +1 -0
  163. package/skills/platform-salesforce-connect-adapter-generate/SKILL.md +359 -0
  164. package/skills/platform-salesforce-connect-adapter-generate/references/official-examples.md +69 -0
  165. package/skills/platform-salesforce-connect-adapter-generate/references/scenarios.md +187 -0
  166. package/skills/platform-soql-query/SKILL.md +8 -8
  167. package/skills/platform-value-set-generate/SKILL.md +2 -2
  168. package/skills/service-itsm-agentic-setup-cmdb-coordinate/SKILL.md +20 -27
  169. package/skills/service-native-voice-recording-transcription-configure/SKILL.md +47 -27
  170. package/skills/service-native-voice-recording-transcription-configure/references/thunderbird-voice-settings.md +13 -9
  171. package/skills/service-native-voice-recording-transcription-configure/scripts/enable-recording-transcription.sh +104 -45
@@ -0,0 +1,248 @@
1
+ # KAM Data Creation — Field Reference
2
+
3
+ > **Read the CSVs — do not treat these tables as authoritative.** The values below are a **snapshot** of one export of the `.lsc-starter-config/LSStarterConfig/Data/` CSV files, kept for orientation only. At execution time you MUST read the actual CSV for each object and use **only** the values it currently contains (one record per row). If a CSV differs from a table here — added/removed columns, changed values, extra rows — the **live CSV wins**. Never hardcode these values or reuse values from a previous run.
4
+ >
5
+ > **Do NOT narrate the difference to the user.** The example values here (e.g. `Immunexis 5mg`) are illustrative placeholders, not data — silently use whatever the live CSV contains and never tell the user that the live data differs from these examples, name a specific CSV row, or comment on the underlying data structure.
6
+
7
+ Field values for all KAM records, sourced from `.lsc-starter-config/LSStarterConfig/Data/` CSV files (plus the explicit HCO account bundle). **All records are created as the ADMIN** (`--target-org <admin>`) — in the KAM workflow the end user does not exist yet (Stage 6), so there is no rep/admin split and no login-as-rep step.
8
+
9
+ ## Source folder & object→CSV mapping
10
+
11
+ The CSVs come from <https://github.com/SalesforceLabs/LSStarterConfig.git>. As an embedded Stage 5, this stage is a pure consumer of `.lsc-starter-config/LSStarterConfig/` and MUST NOT download or delete it — the coordinator (`life-sciences-kam-coordinate`) owns the single download (start) and single delete (end). If the folder is absent when this stage runs, stop and report it must be provisioned by the coordinator.
12
+
13
+ | Object | CSV file |
14
+ |---|---|
15
+ | Account | `account.csv` |
16
+ | HealthcareProvider | `healthcareprovider.csv` |
17
+ | ContactPointAddress | `contactpointaddress.csv` |
18
+ | ObjectTerritory2Association | `objectterritory2association.csv` |
19
+ | ProviderAcctTerritoryInfo | `provideracctterritoryinfo.csv` |
20
+ | Product2 | `product2.csv` |
21
+ | LifeSciMarketableProduct | `lifescimarketableproduct.csv` |
22
+ | ProductTerritoryAvailability | `productterritoryavailability.csv` |
23
+
24
+ > **No Visit chain.** The KAM workflow does NOT create `Visit`, `ProviderVisit`, `ProviderVisitProdDetailing`, or `ProviderVisitProdDiscussion`. Ignore those CSVs.
25
+
26
+ ## HCP Account (RecordType: Health_Care_Provider)
27
+
28
+ This is the CSV-driven **person** account (an individual provider). The HCO (organization) account is a separate bundle below.
29
+
30
+ | Field | Value | Source |
31
+ |-------|-------|--------|
32
+ | FirstName | Aaron | account.csv |
33
+ | LastName | Morita | account.csv |
34
+ | Salutation | Dr. | account.csv |
35
+ | RecordType DeveloperName | Health_Care_Provider | account.csv |
36
+ | IsActive | True | account.csv (standard `IsActive` boolean — NOT `IsActive__c`) |
37
+
38
+ ## HealthcareProvider
39
+
40
+ | Field | Value | Source |
41
+ |-------|-------|--------|
42
+ | Name | Aaron Morita HP | healthcareprovider.csv |
43
+ | IsActive | True | healthcareprovider.csv |
44
+ | IsPrimaryProvider | True | healthcareprovider.csv |
45
+ | ProviderType | Medical Doctor | healthcareprovider.csv |
46
+ | Status | Active | healthcareprovider.csv |
47
+ | AccountId | (from Account) | FK |
48
+
49
+ > As admin you have FLS to all fields, so `NationalProviderIdentifier` and `IsSpeaker` may be set if the CSV lists them. If a create fails on a field, omit it and continue — those two are not required by any KAM downstream record.
50
+
51
+ ## ContactPointAddress
52
+
53
+ | Field | Value | Source |
54
+ |-------|-------|--------|
55
+ | Name | 415 Mission St | contactpointaddress.csv |
56
+ | AddressType | Billing | contactpointaddress.csv |
57
+ | Street | 415 Mission St | contactpointaddress.csv |
58
+ | City | San Francisco | contactpointaddress.csv |
59
+ | State | California | contactpointaddress.csv |
60
+ | StateCode | CA | contactpointaddress.csv |
61
+ | PostalCode | 94105 | contactpointaddress.csv |
62
+ | Country | United States | contactpointaddress.csv |
63
+ | CountryCode | US | contactpointaddress.csv |
64
+ | Latitude | 37.789853 | contactpointaddress.csv |
65
+ | Longitude | -122.396806 | contactpointaddress.csv |
66
+ | IsActive | True | contactpointaddress.csv |
67
+ | IsPrimary | True | contactpointaddress.csv |
68
+ | UsageType | Work | contactpointaddress.csv |
69
+ | ParentId | (from HCP Account) | FK |
70
+
71
+ ## HCO Account bundle — Partners Healthcare (explicit values, NOT from CSV)
72
+
73
+ In addition to the CSV-driven HCP account above, create a **Health Care Organization (HCO)** account and its provider and address. These three records use the **explicit values below** — they are **not** rows in any CSV (only the HCO ContactPointAddress reuses the CSV's address values). Both the Account and the HealthcareProvider use the **`Health_Care_Organization`** record type — look up each record type's Id by `DeveloperName` + `SobjectType` first (the DeveloperName is the same on both objects; the `SobjectType` differs):
74
+
75
+ ```bash
76
+ # RecordTypeId for the HCO Account
77
+ sf data query --query "SELECT Id FROM RecordType WHERE SobjectType='Account' AND DeveloperName='Health_Care_Organization'" --target-org <admin> --json
78
+ # RecordTypeId for the HCO HealthcareProvider
79
+ sf data query --query "SELECT Id FROM RecordType WHERE SobjectType='HealthcareProvider' AND DeveloperName='Health_Care_Organization'" --target-org <admin> --json
80
+ ```
81
+
82
+ ### HCO Account (RecordType: Health_Care_Organization)
83
+
84
+ An **organization** account — use the `Name` field, not FirstName/LastName.
85
+
86
+ | Field | Value | Source |
87
+ |-------|-------|--------|
88
+ | Name | Partners Healthcare | explicit |
89
+ | IsActive | True | explicit |
90
+ | RecordTypeId | Id of Account RecordType `Health_Care_Organization` | RecordType query above |
91
+
92
+ ```bash
93
+ sf data create record --sobject Account --target-org <admin> \
94
+ --values "Name='Partners Healthcare' IsActive=true RecordTypeId=<hcoAccountRecordTypeId>" --json
95
+ ```
96
+
97
+ Capture the returned **HCO Account Id** — the HCO HealthcareProvider (`AccountId`) and HCO ContactPointAddress (`ParentId`) both reference it.
98
+
99
+ ### HCO HealthcareProvider
100
+
101
+ | Field | Value | Source |
102
+ |-------|-------|--------|
103
+ | Name | Partners Healthcare HP | explicit |
104
+ | AccountId | (from HCO Account) | FK — the `Partners Healthcare` Account Id |
105
+ | IsActive | True | explicit |
106
+ | IsPrimaryProvider | True | explicit |
107
+ | RecordTypeId | Id of HealthcareProvider RecordType `Health_Care_Organization` | RecordType query above |
108
+ | Status | Active | explicit |
109
+
110
+ ```bash
111
+ sf data create record --sobject HealthcareProvider --target-org <admin> \
112
+ --values "Name='Partners Healthcare HP' AccountId=<hcoAccountId> IsActive=true IsPrimaryProvider=true RecordTypeId=<hcoProviderRecordTypeId> Status=Active" --json
113
+ ```
114
+
115
+ ### HCO ContactPointAddress
116
+
117
+ Reuse the **exact same address values from `contactpointaddress.csv`** used for the HCP ContactPointAddress above (Name, AddressType, Street, City, State, StateCode, PostalCode, Country, CountryCode, Latitude, Longitude, IsActive, IsPrimary, UsageType) — changing **only** the parent.
118
+
119
+ | Field | Value | Source |
120
+ |-------|-------|--------|
121
+ | (all address fields) | same as the HCP `ContactPointAddress` (from `contactpointaddress.csv`) | contactpointaddress.csv |
122
+ | ParentId | (from HCO Account `Partners Healthcare`) | FK — the HCO Account, **not** the HCP Account |
123
+
124
+ ```bash
125
+ # Same --values as the HCP ContactPointAddress, with ParentId pointing at the HCO Account instead.
126
+ sf data create record --sobject ContactPointAddress --target-org <admin> \
127
+ --values "<same address fields as the HCP ContactPointAddress> ParentId=<hcoAccountId>" --json
128
+ ```
129
+
130
+ Capture the returned **HCO ContactPointAddress Id** — the HCO `ProviderAcctTerritoryInfo` references it as `PreferredAddressId`.
131
+
132
+ ### HCO ObjectTerritory2Association
133
+
134
+ Same field values as the HCP `ObjectTerritory2Association` below, pointing at the HCO Account and the **same Stage-3 level-3 territory**.
135
+
136
+ | Field | Value | Source |
137
+ |-------|-------|--------|
138
+ | ObjectId | (from HCO Account `Partners Healthcare`) | FK |
139
+ | Territory2Id | (Stage-3 level-3 territory) | FK |
140
+ | AssociationCause | Territory2Manual | objectterritory2association.csv |
141
+
142
+ ```bash
143
+ sf data create record --sobject ObjectTerritory2Association --target-org <admin> \
144
+ --values "ObjectId=<hcoAccountId> Territory2Id=<territoryId> AssociationCause=Territory2Manual" --json
145
+ ```
146
+
147
+ ### HCO ProviderAcctTerritoryInfo
148
+
149
+ Same field values as the HCP `ProviderAcctTerritoryInfo` below, pointing at the HCO Account, its ContactPointAddress, and the **same Stage-3 level-3 territory**.
150
+
151
+ | Field | Value | Source |
152
+ |-------|-------|--------|
153
+ | AccountId | (from HCO Account `Partners Healthcare`) | FK |
154
+ | Territory2Id | (Stage-3 level-3 territory) | FK |
155
+ | PreferredAddressId | (from HCO ContactPointAddress) | FK |
156
+ | IsActive | True | provideracctterritoryinfo.csv |
157
+ | IsAvailableOffline | True | provideracctterritoryinfo.csv |
158
+ | IsTargetedAccount | True | provideracctterritoryinfo.csv |
159
+ | SourceType | Manual | provideracctterritoryinfo.csv |
160
+
161
+ ```bash
162
+ sf data create record --sobject ProviderAcctTerritoryInfo --target-org <admin> \
163
+ --values "AccountId=<hcoAccountId> Territory2Id=<territoryId> PreferredAddressId=<hcoContactPointAddressId> IsActive=true IsAvailableOffline=true IsTargetedAccount=true SourceType=Manual" --json
164
+ ```
165
+
166
+ ## ObjectTerritory2Association
167
+
168
+ | Field | Value | Source |
169
+ |-------|-------|--------|
170
+ | ObjectId | (from Account) | FK |
171
+ | Territory2Id | (Stage-3 level-3 territory) | FK |
172
+ | AssociationCause | Territory2Manual | objectterritory2association.csv |
173
+
174
+ ## ProviderAcctTerritoryInfo
175
+
176
+ | Field | Value | Source |
177
+ |-------|-------|--------|
178
+ | AccountId | (from Account) | FK |
179
+ | Territory2Id | (Stage-3 level-3 territory) | FK |
180
+ | PreferredAddressId | (from ContactPointAddress) | FK |
181
+ | IsActive | True | provideracctterritoryinfo.csv |
182
+ | IsAvailableOffline | True | provideracctterritoryinfo.csv |
183
+ | IsTargetedAccount | True | provideracctterritoryinfo.csv |
184
+ | SourceType | Manual | provideracctterritoryinfo.csv |
185
+
186
+ ## Product2 (NO RecordType)
187
+
188
+ | Field | Value | Source |
189
+ |-------|-------|--------|
190
+ | Name | Immunexis 5mg | product2.csv |
191
+ | ProductCode | IM001-5 | product2.csv |
192
+ | IsActive | True | product2.csv |
193
+
194
+ > Do NOT set RecordTypeId — explicit requirement.
195
+
196
+ ## LifeSciMarketableProduct
197
+
198
+ | Field | Value | Source |
199
+ |-------|-------|--------|
200
+ | Name | Immunexis 5mg | lifescimarketableproduct.csv |
201
+ | ProductId | (from Product2) | FK |
202
+ | IsActive | True | lifescimarketableproduct.csv |
203
+ | IsAvlForSamplingAllocation | True | lifescimarketableproduct.csv |
204
+ | Manufacturer | Makana Health | lifescimarketableproduct.csv |
205
+ | DistributionMethod | Drop | lifescimarketableproduct.csv |
206
+ | SignatureRequirementLevel | Mandatory | lifescimarketableproduct.csv |
207
+ | SortOrder | 100 | lifescimarketableproduct.csv |
208
+ | StartDate | 2026-07-01 | lifescimarketableproduct.csv |
209
+ | Type | Product | lifescimarketableproduct.csv |
210
+
211
+ > Capture the resulting `LifeSciMarketableProduct` Id — Part B (plan templates) of this stage references it as the `GoalDefinitionProduct.ProductId`.
212
+
213
+ ## ProductTerritoryAvailability
214
+
215
+ | Field | Value | Source |
216
+ |-------|-------|--------|
217
+ | ProductId | (from LifeSciMarketableProduct) | FK |
218
+ | TerritoryId | (Stage-3 level-3 territory) | FK |
219
+ | AlignmentType | Territory Inclusion | productterritoryavailability.csv |
220
+ | Purpose | Visit | productterritoryavailability.csv |
221
+ | Status | Draft | productterritoryavailability.csv |
222
+ | UsageType | LifeSciences | productterritoryavailability.csv |
223
+
224
+ > The `TerritoryId` MUST be the same Stage-3 level-3 territory later assigned to the KAM user (Stage 6). Otherwise the KAM user sees no product/account data.
225
+
226
+ ---
227
+
228
+ ## Dependency Chain
229
+
230
+ ```text
231
+ HCP Account (person, Health_Care_Provider)
232
+ ├── HealthcareProvider — AccountId
233
+ ├── ContactPointAddress — ParentId
234
+ ├── ObjectTerritory2Association — ObjectId, Territory2Id
235
+ └── ProviderAcctTerritoryInfo — AccountId, PreferredAddressId (ContactPointAddress), Territory2Id
236
+
237
+ HCO Account (organization, Health_Care_Organization — Partners Healthcare)
238
+ ├── HealthcareProvider (Partners Healthcare HP) — AccountId
239
+ ├── ContactPointAddress — ParentId (same CSV address values)
240
+ ├── ObjectTerritory2Association — ObjectId, Territory2Id
241
+ └── ProviderAcctTerritoryInfo — AccountId, PreferredAddressId (HCO ContactPointAddress), Territory2Id
242
+
243
+ Product2
244
+ └── LifeSciMarketableProduct — ProductId
245
+ └── ProductTerritoryAvailability — ProductId, TerritoryId
246
+ ```
247
+
248
+ Create in the order: HCP Account → HealthcareProvider → ContactPointAddress → ObjectTerritory2Association → ProviderAcctTerritoryInfo → HCO Account → HCO HealthcareProvider → HCO ContactPointAddress → HCO ObjectTerritory2Association → HCO ProviderAcctTerritoryInfo → Product2 → LifeSciMarketableProduct → ProductTerritoryAvailability.
@@ -0,0 +1,35 @@
1
+ # On-Device (iPad) Validation Script (KAM)
2
+
3
+ Shown to the admin at the very end of the workflow — **after the mobile metadata cache reaches `Status='Active'`** (Stage 6 gate passed) and the final summary is displayed. Display the script **verbatim** to the admin so they can hand it to the KAM user, then **wait for the user to confirm** each step succeeded on the device. Once the user confirms, the setup is complete.
4
+
5
+ The credentials in Step 1 are the KAM user created in Stage 6 (the user whose username contains `kam`). The account (`Partners Healthcare`), the objective/template (`Immunexis: Secure Q3 Formulary Position`), and its Assessment Tasks are the records created in Stage 5 — present them exactly as named below.
6
+
7
+ ## Script (display verbatim)
8
+
9
+ ```markdown
10
+ Here are the refined steps to validate on the Life Sciences Mobile Application (iPad).
11
+
12
+ Step 1 — Log in to the Life Sciences Mobile Application
13
+ Open the application on your iPad, enter your credentials, and verify that the home screen loads successfully.
14
+
15
+ Step 2 — Create a new Account Plan
16
+ Tap Account Plan in the top navigation bar, then tap New.
17
+ Enter an Account Plan Name.
18
+ Search for and select your target account (for example, Partners Healthcare).
19
+ Fill out the SWOT Analysis, Customer Landscape, and Competitive Landscape sections as needed.
20
+ Tap Save. You should now see your newly created Account Plan.
21
+
22
+ Step 3 — Import an objective template
23
+ Navigate to the Account Plan Objectives tab and tap Import Template.
24
+ Locate the template you want to use (such as Immunexis: Secure Q3 Formulary Position) and tap to expand the hierarchy.
25
+ Tap Select All, then tap Next.
26
+ Review your selections and tap Import.
27
+ The assessment tasks from the template will now appear under your Action Plan.
28
+
29
+ Step 4 — Complete a task and sync your data
30
+ Tap to edit any of your new tasks, change the status to Completed, and tap Done.
31
+ Once you are finished updating tasks, initiate a data sync on your device.
32
+ Note: Because your data calculates securely on the server, the progress bar on your Action Plan won't move the exact instant you tap "Completed." It will advance as soon as your sync finishes.
33
+ ```
34
+
35
+ Once the user confirms, this is the end of the setup.
@@ -0,0 +1,155 @@
1
+ # Metadata Cache Generation Reference
2
+
3
+ Detailed commands for the metadata-cache generation steps of Stage 6 (KAM User Provisioning). Run entirely as the **admin** (`--target-org <admin>`).
4
+
5
+ > **No permission set required.** The generate Connect API bypasses metadata
6
+ > validation itself, so the previously-documented `SkipMetadataValidation`
7
+ > permission set (`PermissionsSkipVldBefMetadataGeneration` /
8
+ > `PermissionsGenerateLifeSciencesMetadata`) is NOT needed. Verified empirically:
9
+ > generation enqueues and the async job runs with no such permission set assigned.
10
+
11
+ > **Parent-link field:** the parent-link field on `LifeSciMobileMetadataRecord` is
12
+ > `ParentMobileMetadataRecId` (used below). If you need to confirm the schema on your
13
+ > org, describe the object:
14
+ >
15
+ > ```bash
16
+ > sf sobject describe --sobject LifeSciMobileMetadataRecord --target-org <admin> --json \
17
+ > | grep -o '"name":"[^"]*"'
18
+ > ```
19
+
20
+ ## Step A: Create LifeSciMobileMetadataRecord Prerequisite
21
+
22
+ Create a **parent** record and a **child** record linked to the LSC Custom Profile.
23
+ Set **both** records to `ValidationCompleted` — the generate API in Step B rejects the
24
+ call unless the **parent** record's `Status` is `ValidationCompleted` (not just the
25
+ child's). The generate API is called with the **parent** record ID.
26
+
27
+ Run as admin (`--target-org <admin>`):
28
+
29
+ ```bash
30
+ sf apex run --target-org <admin> --json <<'EOF'
31
+ // Create parent record.
32
+ LifeSciMobileMetadataRecord parent = new LifeSciMobileMetadataRecord(
33
+ IntegrationStatus = 'New',
34
+ Status = 'New'
35
+ );
36
+ insert parent;
37
+
38
+ // Create child record for the LSC Custom Profile.
39
+ Profile pf = [SELECT Id FROM Profile WHERE Name = 'LSC Custom Profile'];
40
+ LifeSciMobileMetadataRecord child = new LifeSciMobileMetadataRecord(
41
+ ParentMobileMetadataRecId = parent.Id,
42
+ ProfileId = pf.Id,
43
+ IntegrationStatus = 'New',
44
+ Status = 'New'
45
+ );
46
+ insert child;
47
+
48
+ // Set BOTH parent and child to ValidationCompleted (the API requires the parent).
49
+ child.Status = 'ValidationCompleted';
50
+ update child;
51
+ parent.Status = 'ValidationCompleted';
52
+ update parent;
53
+
54
+ System.debug('Parent Id: ' + parent.Id);
55
+ System.debug('Child Id: ' + child.Id);
56
+ EOF
57
+ ```
58
+
59
+ Extract the **parent record ID** from the debug log output — it is required as the `parentMetadataRecordId` in Step B.
60
+
61
+ ---
62
+
63
+ ## Step B: Call the Metadata Generate Connect API
64
+
65
+ Use the CLI's own authenticated REST client (`sf api request rest`) — it builds the
66
+ `Authorization` header correctly. A hand-rolled `curl` with the token from
67
+ `sf org display` fails with `INVALID_AUTH_HEADER` (401), even though the same token
68
+ works for CLI data queries — do NOT use raw curl for this endpoint.
69
+
70
+ ### Build the request body
71
+
72
+ The body accepts `parentMetadataRecordId`, `apiVersion`, and `prefix`. Use `apiVersion`
73
+ `65.0` (verified working). Do NOT include `generateStandardTranslations` — the endpoint
74
+ rejects it with `JSON_PARSER_ERROR: Unrecognized field "generateStandardTranslations"`.
75
+
76
+ Write the body to a **project-local** relative file (never `/tmp` or any path outside the project); remove it after the call below:
77
+
78
+ ```bash
79
+ cat > .lsc-mdgen-body.json <<'EOF'
80
+ {
81
+ "parentMetadataRecordId": "<parentRecordId>",
82
+ "apiVersion": "65.0",
83
+ "prefix": "lsc4ce"
84
+ }
85
+ EOF
86
+ ```
87
+
88
+ ### Call the endpoint
89
+
90
+ Match the endpoint's `vXX.0` to the `apiVersion` in the body. Pass the body file with a
91
+ leading `@` (a bare path is sent as a literal string and triggers `JSON_PARSER_ERROR`):
92
+
93
+ ```bash
94
+ sf api request rest \
95
+ "/services/data/v65.0/connect/life-sciences/commercial/metadata/actions/generate" \
96
+ --method POST \
97
+ --body @.lsc-mdgen-body.json \
98
+ --target-org <admin>
99
+ rm -f .lsc-mdgen-body.json
100
+ ```
101
+
102
+ ### Expected response
103
+
104
+ Success is a JSON message (HTTP 200), not 202:
105
+
106
+ ```json
107
+ { "message": "Task enqueued for metadata cache generation." }
108
+ ```
109
+
110
+ Generation then runs asynchronously.
111
+
112
+ ### Verify completion
113
+
114
+ Query both the parent and its child records (use your org's parent-link field name):
115
+
116
+ ```bash
117
+ sf data query --query "SELECT Id, Status, IntegrationStatus, IntegrationErrorMessage, MetadataDocumentId, LastModifiedDate FROM LifeSciMobileMetadataRecord WHERE Id='<parentRecordId>' OR ParentMobileMetadataRecId='<parentRecordId>'" --target-org <admin> --json
118
+ ```
119
+
120
+ The records move through intermediate states (`New → InProgress → Loading → Processing`)
121
+ and then transition to `Status='Active'`. **`Active` is the success state** — it means the
122
+ cache was generated; the child record's `MetadataDocumentId` is populated with the generated
123
+ document Id. The enqueue message only confirms the task was accepted; keep polling the query
124
+ above until `Status='Active'` before treating generation as complete.
125
+
126
+ > **How to report progress while polling.** The async job can take several minutes; that is
127
+ > normal. As long as the records are advancing through the intermediate states, simply tell
128
+ > the user the generation **is progressing and you are polling for it to become `Active`** —
129
+ > then poll again. Do NOT frame it as a timeout, a missed deadline, or "it didn't complete
130
+ > within the N-minute window" — there is no fixed window, and that phrasing wrongly implies
131
+ > something is wrong when the job is running normally. Only surface a problem if the records
132
+ > go to `Inactive` or stop advancing entirely (see below).
133
+
134
+ A transition to `Inactive` (or a record that stays unchanged with an unchanged
135
+ `LastModifiedDate`) is **not** success — the async job ran but produced no cache, or
136
+ never ran. Check Setup → Apex Jobs for the failed generation job and its error, and
137
+ inspect the record's `IntegrationStatus` / `IntegrationErrorMessage` fields for detail.
138
+
139
+ ---
140
+
141
+ ## Error handling
142
+
143
+ | Error | Resolution |
144
+ |-------|------------|
145
+ | `LifeSciMobileMetadataRecord` sObject not found | LSC packages not installed or API < v65.0 |
146
+ | `Field does not exist: ParentMobileMetadataRecId` (or similar) on compile | Describe the object to confirm the parent-link field name on your org and use the reported name |
147
+ | `INVALID_AUTH_HEADER` (401) from Connect API | You used raw `curl` — switch to `sf api request rest`, which builds the auth header correctly |
148
+ | `JSON_PARSER_ERROR: Unrecognized field "generateStandardTranslations"` | Remove that field from the body — only `parentMetadataRecordId`, `apiVersion`, and `prefix` are accepted |
149
+ | `JSON_PARSER_ERROR: Unexpected character ('/')` | `--body` got a literal path — prefix the file with `@` (`--body @.lsc-mdgen-body.json`) |
150
+ | `Profile 'LSC Custom Profile' not found` | Run Stage 2 (Starter Config Deploy) first — the child record needs the profile Id |
151
+ | `...isn't ValidationCompleted` from Connect API | Set the **parent** record's `Status` to `ValidationCompleted` (the API requires the parent, not just the child), then retry |
152
+ | HTTP 400 from Connect API | Check: parentMetadataRecordId valid, parent Status='ValidationCompleted', prefix='lsc4ce' |
153
+ | HTTP 404 from Connect API | Endpoint not available — verify API version v65.0+ and LSC packages |
154
+ | Records never leave their status (LastModifiedDate unchanged) | Async job didn't run — wait 30s; check Setup → Apex Jobs for failures |
155
+ | Records go to `Inactive` instead of `Active` | Generation ran but produced no cache — this is a failure, not success. Check Setup → Apex Jobs and the record's `IntegrationErrorMessage` for the cause |
@@ -0,0 +1,146 @@
1
+ # KAM User Provisioning Details
2
+
3
+ ## Required Permission Sets
4
+
5
+ The KAM user gets **exactly four** permission sets:
6
+
7
+ | Permission Set Label | Expected API Name | Purpose |
8
+ |---------------------|-------------------|---------|
9
+ | Health Cloud Starter | HealthCloudStarter | Health Cloud foundation permissions |
10
+ | Life Sciences Key Account Management | LifeSciencesKeyAccountManager | Key account management permissions |
11
+ | Life Sciences Field Sales Representative | LifeSciencesFieldSalesRepresentative | Life Sciences field sales rep permissions |
12
+ | Life Sciences Core | LifeSciencesCore | Life Sciences core platform permissions |
13
+
14
+ > **Resolve by label, not API name.** The API names above are the expected values; managed-package sets may be namespace-prefixed. Always confirm the actual `Name` via the label query below before assigning.
15
+
16
+ ### Querying Permission Sets
17
+
18
+ Permission sets from managed packages may have namespace-prefixed API names. If the standard names don't return results, try:
19
+
20
+ ```bash
21
+ sf data query --query "SELECT Id, Name, NamespacePrefix, Label FROM PermissionSet WHERE Label LIKE '%Key Account%' OR Label LIKE '%Health Cloud%' OR Label LIKE '%Field Sales%' OR Label LIKE '%Life Sciences Core%'" --target-org <org> --json
22
+ ```
23
+
24
+ ---
25
+
26
+ ## Required User Fields
27
+
28
+ When creating a user via `sf data create record`, these fields are mandatory:
29
+
30
+ | Field | Description | Default Value | Admin can edit? |
31
+ |-------|-------------|---------------|-----------------|
32
+ | `FirstName` | User's first name | `Jordan` | Yes |
33
+ | `LastName` | User's last name | `Lee` | Yes |
34
+ | `Email` | User's email address | `jordan.lee@<orgdomain>` | Yes |
35
+ | `Username` | Globally unique username — **must contain the text `kam`** | `jordan.lee.kam@<orgdomain>` (auto-generated) | No — auto |
36
+ | `Alias` | Max 8 characters | `jlee` — first initial + last name (truncated) | No — auto |
37
+ | `ProfileId` | 18-char record ID | `LSC Custom Profile` (queried from org) | No — fixed |
38
+ | `IsActive` | Must be `true` | `true` | No — fixed |
39
+ | `TimeZoneSidKey` | User's timezone | `America/Los_Angeles` | No — default |
40
+ | `LocaleSidKey` | User's locale | `en_US` | No — default |
41
+ | `EmailEncodingKey` | Email encoding | `UTF-8` | No — default |
42
+ | `LanguageLocaleKey` | Language | `en_US` | No — default |
43
+
44
+ > **Username must contain `kam`.** The KAM spec requires the text `kam` in the username (e.g. `jordan.lee.kam@<orgdomain>`). The username is **auto-generated** from the (possibly edited) name — never asked for. If the derived form lacks `kam`, insert a `.kam` segment.
45
+
46
+ ## Default User Details & Confirmation (show BEFORE creating)
47
+
48
+ Before creating the user, present the default/derived details above as a table to the admin and get explicit confirmation. **The admin may edit `FirstName`, `LastName`, and `Email` only.** The `Username` and `Alias` are **auto-generated** (never asked for); the remaining fields are fixed defaults. If the admin edits the name, **re-derive the `Username` and `Alias` and re-display** before proceeding. **Do NOT create the user until the admin confirms** — this is the only user-detail confirmation in Stage 6 (permsets, territory, and password proceed automatically per the stage rules).
49
+
50
+ Example prompt: *"Before I create the KAM user, here are the details — First name **Jordan**, Last name **Lee**, Email **jordan.lee@\<orgdomain\>**. I'll auto-generate the username as **jordan.lee.kam@\<orgdomain\>** (Active, on LSC Custom Profile, en_US / America/Los_Angeles). Change the first/last name or email, or shall I create it as-is?"*
51
+
52
+ - **Username auto-generation:** derive from the (possibly edited) name as `<first>.<last>.kam@<orgdomain>` (lowercased); it MUST contain `kam`. `<orgdomain>` keeps it globally unique. On `DUPLICATE_USERNAME`, append a unique suffix while preserving `kam` (e.g. `.kam.dev`).
53
+ - **Alias auto-generation:** first initial + last name, truncated to 8 characters (e.g. `Jordan Lee` → `jlee`).
54
+
55
+ ### Optional Fields
56
+
57
+ | Field | Description |
58
+ |-------|-------------|
59
+ | `Title` | Job title (e.g., "KAM User") |
60
+ | `Department` | Department name |
61
+ | `Phone` / `MobilePhone` | Phone numbers |
62
+
63
+ ---
64
+
65
+ ## Territory Assignment
66
+
67
+ ### UserTerritory2Association Fields
68
+
69
+ | Field | Description |
70
+ |-------|-------------|
71
+ | `UserId` | 18-char User record ID |
72
+ | `Territory2Id` | 18-char Territory2 record ID — **the same Stage-3 level-3 territory used for ProductTerritoryAvailability in Stage 5** |
73
+ | `RoleInTerritory2` | Optional — leave blank unless the user specifies |
74
+
75
+ ### Identifying the Level-3 Territory
76
+
77
+ The level-3 territory is the leaf node in the 3-level hierarchy created (or reused) by `life-sciences-territory-configure` in Stage 3. The coordinator captured its ID in `OrchestrationState.territoryId`. **Use that exact territory** — it MUST match the territory used for `ProductTerritoryAvailability` in Stage 5, or the KAM user sees no product/account data. Query to confirm:
78
+
79
+ ```bash
80
+ sf data query --query "SELECT Id, Name, DeveloperName, ParentTerritory2.Name, ParentTerritory2.ParentTerritory2.Name FROM Territory2 WHERE ParentTerritory2.ParentTerritory2Id != null AND Territory2Model.State = 'Active'" --target-org <org> --json
81
+ ```
82
+
83
+ Both the KAM user **and** the admin are assigned to this same leaf territory.
84
+
85
+ ---
86
+
87
+ ## Error Handling
88
+
89
+ | Error | Cause | Fix |
90
+ |-------|-------|-----|
91
+ | `DUPLICATE_USERNAME` | Username exists in another org | Append a unique suffix while keeping `kam` (e.g., `.kam.dev`) |
92
+ | `DUPLICATE_VALUE` on PermissionSetAssignment | Permission set already assigned | Skip — not an error |
93
+ | `DUPLICATE_VALUE` on UserTerritory2Association | User already assigned to territory | Skip — not an error |
94
+ | `INVALID_CROSS_REFERENCE_KEY` on ProfileId | Profile ID wrong or from a different org | Re-query the profile ID |
95
+ | `FIELD_INTEGRITY_EXCEPTION` on Username | Username format invalid | Must be email-like format (contains `@`) |
96
+ | `REQUIRED_FIELD_MISSING` | A mandatory field was omitted | Check all required fields are provided |
97
+
98
+ ---
99
+
100
+ ## Setting the User's Password
101
+
102
+ A user created via `sf data create record` has **no password and receives no email** — they cannot log in until a password is set. Set one with anonymous Apex, writing the temp file to a **project-local** relative path (never `/tmp` or any path outside the project) and removing it right after:
103
+
104
+ ```bash
105
+ echo "System.setPassword('<newUserId>', '<password>');" > .lsc-setpw.apex
106
+ sf apex run --file .lsc-setpw.apex --target-org <org> --json
107
+ rm -f .lsc-setpw.apex
108
+ ```
109
+
110
+ Confirm `compiled: true` and `success: true`. The password must meet the org's policy (default: ≥8 chars, mixed case, at least one number and one symbol). The user is prompted to change it on first login.
111
+
112
+ **Do not use `sf org generate password --on-behalf-of <username>`** — it only works for users with a local CLI auth entry (e.g. created via `sf org create user`) and fails for API-created users with `NamedOrgNotFoundError`. Alternatively, an admin can reset the password from Setup → Users → <user> → Reset Password to email a set-password link.
113
+
114
+ Get the login URL for the credential handoff:
115
+
116
+ ```bash
117
+ sf org display --target-org <org> --json # use the instanceUrl field
118
+ ```
119
+
120
+ ---
121
+
122
+ ## Verification Queries
123
+
124
+ ### Verify user was created correctly
125
+
126
+ ```bash
127
+ sf data query --query "SELECT Id, Name, Username, Profile.Name, IsActive FROM User WHERE Username = '<username>'" --target-org <org> --json
128
+ ```
129
+
130
+ ### Verify permission set assignments (hard count = 4)
131
+
132
+ Filter out the profile-owned permission set (`IsOwnedByProfile = false`) so the result matches the 4 sets you assigned rather than a hidden profile-owned row:
133
+
134
+ ```bash
135
+ sf data query --query "SELECT PermissionSet.Label, PermissionSet.Name FROM PermissionSetAssignment WHERE AssigneeId = '<userId>' AND PermissionSet.IsOwnedByProfile = false" --target-org <org> --json
136
+ ```
137
+
138
+ This MUST return **exactly 4 rows**: `{HealthCloudStarter, LifeSciencesKeyAccountManager, LifeSciencesFieldSalesRepresentative, LifeSciencesCore}`.
139
+
140
+ ### Verify territory assignments
141
+
142
+ ```bash
143
+ sf data query --query "SELECT User.Name, User.Username, Territory2.Name, Territory2.DeveloperName FROM UserTerritory2Association WHERE Territory2Id = '<territoryId>'" --target-org <org> --json
144
+ ```
145
+
146
+ Expect at least 2 rows (the KAM user + the admin).