@salesforce/afv-skills 1.47.0 → 1.49.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 (160) hide show
  1. package/package.json +1 -1
  2. package/skills/education-cloud-domain-configure/SKILL.md +234 -0
  3. package/skills/education-cloud-domain-configure/references/dependent-features.md +198 -0
  4. package/skills/education-cloud-domain-configure/references/domain-features/academic-operations.md +386 -0
  5. package/skills/education-cloud-domain-configure/references/domain-features/alumni-relations.md +155 -0
  6. package/skills/education-cloud-domain-configure/references/domain-features/cross-domain-dependencies.md +18 -0
  7. package/skills/education-cloud-domain-configure/references/domain-features/industriessettings-toggle-reference.md +43 -0
  8. package/skills/education-cloud-domain-configure/references/domain-features/mentoring.md +198 -0
  9. package/skills/education-cloud-domain-configure/references/domain-features/recruitment-admissions.md +315 -0
  10. package/skills/education-cloud-domain-configure/references/domain-features/student-management.md +155 -0
  11. package/skills/education-cloud-domain-configure/references/domain-features/student-success.md +249 -0
  12. package/skills/education-cloud-domain-configure/references/domain-features.md +27 -0
  13. package/skills/education-cloud-domain-configure/references/gotchas-extended.md +23 -0
  14. package/skills/education-cloud-domain-configure/references/toggle-write-path.md +67 -0
  15. package/skills/education-cloud-domain-configure/scripts/check_license_provisioned.py +62 -0
  16. package/skills/education-cloud-domain-configure/scripts/check_org_edition.py +44 -0
  17. package/skills/education-cloud-domain-configure/scripts/check_permission_assigned.py +39 -0
  18. package/skills/education-cloud-multi-campus-configure/SKILL.md +2 -0
  19. package/skills/education-cloud-multi-campus-configure/references/foundation_prerequisites.md +4 -3
  20. package/skills/service-agentforce-channel-configure/SKILL.md +33 -28
  21. package/skills/service-agentforce-human-escalation-configure/SKILL.md +205 -0
  22. package/skills/service-agentforce-human-escalation-configure/assets/escalation-thresholds.instructions.md +37 -0
  23. package/skills/service-agentforce-human-escalation-configure/assets/force-app/main/default/flows/Human_Escalation_Outbound_Flow.flow-meta.xml +173 -0
  24. package/skills/service-agentforce-human-escalation-configure/assets/package.xml +8 -0
  25. package/skills/service-agentforce-human-escalation-configure/assets/sfdx-project.json +5 -0
  26. package/skills/service-agentforce-human-escalation-configure/references/classifier-contracts.md +103 -0
  27. package/skills/service-agentforce-human-escalation-configure/references/escalation-mechanism.md +63 -0
  28. package/skills/service-agentforce-human-escalation-configure/references/failure-policy.md +44 -0
  29. package/skills/service-agentforce-human-escalation-configure/references/nga-escalation.md +57 -0
  30. package/skills/service-agentforce-human-escalation-configure/references/runtime-verification.md +72 -0
  31. package/skills/service-agentforce-human-escalation-configure/scripts/classify-agent-active.mjs +49 -0
  32. package/skills/service-agentforce-human-escalation-configure/scripts/classify-nga-escalation.mjs +166 -0
  33. package/skills/service-agentforce-human-escalation-configure/scripts/extract-outbound-route.mjs +67 -0
  34. package/skills/service-agentforce-human-escalation-configure/scripts/patch-escalation-surfaces.mjs +131 -0
  35. package/skills/service-agentforce-human-escalation-configure/scripts/tests/__init__.py +0 -0
  36. package/skills/service-agentforce-human-escalation-configure/scripts/tests/_bootstrap.py +249 -0
  37. package/skills/service-agentforce-human-escalation-configure/scripts/tests/test_escalation_contracts.py +899 -0
  38. package/skills/service-agentforce-human-escalation-configure/scripts/verify-and-configure.sh +705 -0
  39. package/skills/service-agentforce-human-escalation-configure/scripts/verify-escalation-config.mjs +89 -0
  40. package/skills/service-de-channel-routing-configure/SKILL.md +13 -5
  41. package/skills/service-de-channel-routing-configure/scripts/tests/test_skill_contract.py +25 -0
  42. package/skills/service-itsm-agentic-setup-agentforce-coordinate/SKILL.md +23 -10
  43. package/skills/service-itsm-agentic-setup-agentforce-coordinate/examples/output-templates.md +63 -48
  44. package/skills/service-itsm-agentic-setup-agentforce-coordinate/scripts/verify-child-verdict.mjs +6 -2
  45. package/skills/service-omni-agent-users-create/SKILL.md +96 -0
  46. package/skills/service-omni-agent-users-create/assets/create-users.apex.template +80 -0
  47. package/skills/service-omni-agent-users-create/references/apex-patterns.md +135 -0
  48. package/skills/service-omni-agent-users-create/references/apex-template-notes.md +40 -0
  49. package/skills/service-omni-agent-users-create/scripts/detect-and-create.sh +206 -0
  50. package/skills/service-omni-agent-users-create/scripts/detect-existing.sh +122 -0
  51. package/skills/service-omni-agent-users-create/scripts/run-create.sh +298 -0
  52. package/skills/service-omni-agent-users-create/scripts/tests/test_user_create_security.py +171 -0
  53. package/skills/service-omni-agent-work-sharing-configure/SKILL.md +78 -0
  54. package/skills/service-omni-agent-work-sharing-configure/references/api-notes.md +31 -0
  55. package/skills/service-omni-agent-work-sharing-configure/scripts/configure-and-report.sh +186 -0
  56. package/skills/service-omni-agent-work-sharing-configure/scripts/tests/_bootstrap.py +120 -0
  57. package/skills/service-omni-agent-work-sharing-configure/scripts/tests/test_agent_work_sharing_contracts.py +93 -0
  58. package/skills/service-omni-base-settings-configure/SKILL.md +77 -0
  59. package/skills/service-omni-base-settings-configure/assets/force-app/main/default/settings/OmniChannel.settings-meta.xml +8 -0
  60. package/skills/service-omni-base-settings-configure/assets/package.xml +8 -0
  61. package/skills/service-omni-base-settings-configure/assets/sfdx-project.json +12 -0
  62. package/skills/service-omni-base-settings-configure/references/api-notes.md +121 -0
  63. package/skills/service-omni-base-settings-configure/scripts/configure-and-report.sh +164 -0
  64. package/skills/service-omni-base-settings-configure/scripts/detect-existing.sh +69 -0
  65. package/skills/service-omni-channel-setup-coordinate/SKILL.md +168 -0
  66. package/skills/service-omni-channel-setup-coordinate/examples/output-templates.md +161 -0
  67. package/skills/service-omni-channel-setup-coordinate/references/gap-catalog.md +99 -0
  68. package/skills/service-omni-channel-setup-coordinate/scripts/integration-driver.sh +1542 -0
  69. package/skills/service-omni-channel-setup-coordinate/scripts/tests/__init__.py +0 -0
  70. package/skills/service-omni-channel-setup-coordinate/scripts/tests/_bootstrap.py +223 -0
  71. package/skills/service-omni-channel-setup-coordinate/scripts/tests/test_omni_contracts.py +804 -0
  72. package/skills/service-omni-command-center-analyze/SKILL.md +84 -0
  73. package/skills/service-omni-command-center-analyze/references/api-notes.md +54 -0
  74. package/skills/service-omni-command-center-analyze/scripts/analyze.sh +198 -0
  75. package/skills/service-omni-command-center-analyze/scripts/tests/_bootstrap.py +115 -0
  76. package/skills/service-omni-command-center-analyze/scripts/tests/test_command_center_analyze_contracts.py +165 -0
  77. package/skills/service-omni-permission-set-assign/SKILL.md +88 -0
  78. package/skills/service-omni-permission-set-assign/assets/package.xml +8 -0
  79. package/skills/service-omni-permission-set-assign/references/api-notes.md +143 -0
  80. package/skills/service-omni-permission-set-assign/scripts/verify-and-assign.sh +397 -0
  81. package/skills/service-omni-presence-status-deploy/SKILL.md +87 -0
  82. package/skills/service-omni-presence-status-deploy/assets/package.xml +12 -0
  83. package/skills/service-omni-presence-status-deploy/references/api-notes.md +115 -0
  84. package/skills/service-omni-presence-status-deploy/scripts/deploy-and-report.sh +422 -0
  85. package/skills/service-omni-presence-user-config-deploy/SKILL.md +80 -0
  86. package/skills/service-omni-presence-user-config-deploy/references/api-notes.md +60 -0
  87. package/skills/service-omni-presence-user-config-deploy/scripts/deploy-and-report.sh +261 -0
  88. package/skills/service-omni-presence-user-config-deploy/scripts/tests/_bootstrap.py +106 -0
  89. package/skills/service-omni-presence-user-config-deploy/scripts/tests/test_presence_user_config_contracts.py +142 -0
  90. package/skills/service-omni-queue-deploy/SKILL.md +91 -0
  91. package/skills/service-omni-queue-deploy/references/api-notes.md +140 -0
  92. package/skills/service-omni-queue-deploy/scripts/verify-and-align.sh +470 -0
  93. package/skills/service-omni-queue-members-assign/SKILL.md +93 -0
  94. package/skills/service-omni-queue-members-assign/references/api-notes.md +144 -0
  95. package/skills/service-omni-queue-members-assign/scripts/tests/_bootstrap.py +67 -0
  96. package/skills/service-omni-queue-members-assign/scripts/tests/test_queue_members_contracts.py +73 -0
  97. package/skills/service-omni-queue-members-assign/scripts/verify-and-bind.sh +362 -0
  98. package/skills/service-omni-queue-routing-config-deploy/SKILL.md +101 -0
  99. package/skills/service-omni-queue-routing-config-deploy/references/api-notes.md +127 -0
  100. package/skills/service-omni-queue-routing-config-deploy/scripts/tests/_bootstrap.py +90 -0
  101. package/skills/service-omni-queue-routing-config-deploy/scripts/tests/test_queue_routing_config_contracts.py +70 -0
  102. package/skills/service-omni-queue-routing-config-deploy/scripts/upsert-and-report.sh +538 -0
  103. package/skills/service-omni-routing-flow-deploy/SKILL.md +111 -0
  104. package/skills/service-omni-routing-flow-deploy/assets/force-app/main/default/flows/Omni_Route_Case_Trigger.SkillsBased.flow-meta.xml +94 -0
  105. package/skills/service-omni-routing-flow-deploy/assets/force-app/main/default/flows/Omni_Route_Case_Trigger.flow-meta.xml +88 -0
  106. package/skills/service-omni-routing-flow-deploy/assets/force-app/main/default/flows/Omni_Route_Cases.flow-meta.xml +144 -0
  107. package/skills/service-omni-routing-flow-deploy/assets/force-app/main/default/flows/Omni_Route_VoiceCall_Trigger.SkillsBased.flow-meta.xml +94 -0
  108. package/skills/service-omni-routing-flow-deploy/assets/force-app/main/default/flows/Omni_Route_VoiceCall_Trigger.flow-meta.xml +88 -0
  109. package/skills/service-omni-routing-flow-deploy/assets/force-app/main/default/flows/Omni_Route_VoiceCalls.flow-meta.xml +144 -0
  110. package/skills/service-omni-routing-flow-deploy/assets/package.xml +11 -0
  111. package/skills/service-omni-routing-flow-deploy/assets/sfdx-project.json +11 -0
  112. package/skills/service-omni-routing-flow-deploy/references/api-notes.md +265 -0
  113. package/skills/service-omni-routing-flow-deploy/scripts/deploy-and-report.sh +684 -0
  114. package/skills/service-omni-service-channel-configure/SKILL.md +83 -0
  115. package/skills/service-omni-service-channel-configure/assets/force-app/main/default/serviceChannels/Cases.serviceChannel-meta.xml +9 -0
  116. package/skills/service-omni-service-channel-configure/assets/force-app/main/default/serviceChannels/Incidents.serviceChannel-meta.xml +9 -0
  117. package/skills/service-omni-service-channel-configure/assets/force-app/main/default/serviceChannels/MessagingSessions.serviceChannel-meta.xml +9 -0
  118. package/skills/service-omni-service-channel-configure/assets/force-app/main/default/serviceChannels/VoiceCalls.serviceChannel-meta.xml +9 -0
  119. package/skills/service-omni-service-channel-configure/assets/package.xml +11 -0
  120. package/skills/service-omni-service-channel-configure/assets/sfdx-project.json +12 -0
  121. package/skills/service-omni-service-channel-configure/references/api-notes.md +84 -0
  122. package/skills/service-omni-service-channel-configure/scripts/deploy-and-report.sh +383 -0
  123. package/skills/service-omni-sidebar-configure/SKILL.md +77 -0
  124. package/skills/service-omni-sidebar-configure/references/api-notes.md +51 -0
  125. package/skills/service-omni-sidebar-configure/scripts/enable-and-report.sh +315 -0
  126. package/skills/service-omni-sidebar-configure/scripts/tests/_bootstrap.py +142 -0
  127. package/skills/service-omni-sidebar-configure/scripts/tests/test_sidebar_contracts.py +139 -0
  128. package/skills/service-omni-skills-based-routing-configure/SKILL.md +81 -0
  129. package/skills/service-omni-skills-based-routing-configure/references/api-notes.md +50 -0
  130. package/skills/service-omni-skills-based-routing-configure/scripts/configure-and-report.sh +270 -0
  131. package/skills/service-omni-skills-based-routing-configure/scripts/tests/_bootstrap.py +120 -0
  132. package/skills/service-omni-skills-based-routing-configure/scripts/tests/test_sbr_contracts.py +129 -0
  133. package/skills/service-omni-supervisor-config-deploy/SKILL.md +97 -0
  134. package/skills/service-omni-supervisor-config-deploy/assets/force-app/main/default/omniSupervisorConfigs/Omni_Supervisor.omniSupervisorConfig-meta.xml +9 -0
  135. package/skills/service-omni-supervisor-config-deploy/assets/package.xml +8 -0
  136. package/skills/service-omni-supervisor-config-deploy/assets/sfdx-project.json +12 -0
  137. package/skills/service-omni-supervisor-config-deploy/references/api-notes.md +205 -0
  138. package/skills/service-omni-supervisor-config-deploy/scripts/deploy-and-report.sh +586 -0
  139. package/skills/service-omni-supervisor-config-deploy/scripts/tests/_bootstrap.py +153 -0
  140. package/skills/service-omni-supervisor-config-deploy/scripts/tests/test_supervisor_config_contracts.py +116 -0
  141. package/skills/service-omni-supervisor-permset-assign/SKILL.md +88 -0
  142. package/skills/service-omni-supervisor-permset-assign/references/api-notes.md +48 -0
  143. package/skills/service-omni-supervisor-permset-assign/scripts/verify-and-assign.sh +316 -0
  144. package/skills/service-omni-supervisor-surface-deploy/SKILL.md +85 -0
  145. package/skills/service-omni-supervisor-surface-deploy/references/api-notes.md +47 -0
  146. package/skills/service-omni-supervisor-surface-deploy/scripts/deploy-and-report.sh +216 -0
  147. package/skills/service-omni-supervisor-surface-deploy/scripts/tests/_bootstrap.py +95 -0
  148. package/skills/service-omni-supervisor-surface-deploy/scripts/tests/test_supervisor_surface_contracts.py +154 -0
  149. package/skills/service-omni-supervisor-users-create/SKILL.md +92 -0
  150. package/skills/service-omni-supervisor-users-create/assets/create-supervisors.apex.template +72 -0
  151. package/skills/service-omni-supervisor-users-create/references/apex-patterns.md +73 -0
  152. package/skills/service-omni-supervisor-users-create/references/apex-template-notes.md +41 -0
  153. package/skills/service-omni-supervisor-users-create/scripts/detect-and-create.sh +197 -0
  154. package/skills/service-omni-supervisor-users-create/scripts/detect-existing.sh +112 -0
  155. package/skills/service-omni-supervisor-users-create/scripts/run-create.sh +296 -0
  156. package/skills/service-omni-work-skill-routing-configure/SKILL.md +80 -0
  157. package/skills/service-omni-work-skill-routing-configure/references/api-notes.md +67 -0
  158. package/skills/service-omni-work-skill-routing-configure/scripts/configure-and-report.sh +262 -0
  159. package/skills/service-omni-work-skill-routing-configure/scripts/tests/_bootstrap.py +121 -0
  160. package/skills/service-omni-work-skill-routing-configure/scripts/tests/test_work_skill_routing_contracts.py +161 -0
@@ -0,0 +1,249 @@
1
+ # 1. Student Success
2
+
3
+ **Purpose**: Track student advising, success interventions, care plans, and wellness support.
4
+
5
+ **Prerequisites**:
6
+ - All Foundation prerequisites (Section 0)
7
+ - Cases enabled — advising uses case-based workflows
8
+ - Salesforce Scheduler — for advising appointment booking
9
+ - Experience Cloud license — for Learner Portal (student-facing)
10
+ - OmniStudio — for portal components and guided experiences
11
+ - CRM Analytics / Education Analytics — for Advisor Insights and KPI dashboards (optional)
12
+ - Einstein Generative AI — for Einstein Advising Summary (optional)
13
+
14
+ **Core features**:
15
+ - Student records (Person Accounts)
16
+ - Advising case management
17
+ - Success teams for collaborative support
18
+ - Care plans to track interventions
19
+ - Alerts and notifications
20
+ - Salesforce Scheduler for appointment booking
21
+
22
+ ### Sub-Feature Configuration
23
+
24
+ > **Executed order (from Student Success testing):** Support Process → Case Record Types → Success Teams (create `CaseTeamTemplate` first) → Care Plans → Support Programs → Salesforce Scheduler. Do Care Plans AFTER Success Teams and Support Programs BEFORE Scheduler.
25
+
26
+ > **License-gating on Care Plans / Support Programs / Scheduler writes.** These three toggle writes can return `400 INSUFFICIENT_ACCESS_OR_READONLY` (nothing written) on an under-licensed org — confirmed on a test org where the identical write failed on day 1 and succeeded (`success:true`) on day 2 after the org was given more licenses, with no skill/API change in between. Treat this error as **"check licensing on this org first,"** not as a fixed product limitation — retry after the admin confirms licensing rather than concluding the feature is unreachable via API.
27
+
28
+ > **`IndustriesSettings` tooling GET cold-verify can 500 org-wide.** `GET /services/data/v68.0/tooling/sobjects/IndustriesSettings/<DurableId>` has been observed returning HTTP 500 `UNKNOWN_EXCEPTION` on every value read (any field, any API version) in at least one org, root-caused to a null UDD `LogicalFieldDefinition` on one preference column in that org's data — an org-data defect, not a skill or transport bug (`describe` and `SELECT Id, DurableId` still return 200; only value reads fail). If this GET 500s on 3 consecutive attempts, stop retrying the API path and ask the admin to confirm the toggle's ON state in Setup UI instead — record that the write's `success:true` was confirmed via Setup UI, not cold-verified via API, and say so explicitly in any summary.
29
+
30
+ #### Step 1 — Create Support Process
31
+
32
+ **What it does**: Creates a Support Process named "Student Advising" to organize case statuses. Used as the `businessProcess` on the case record types in Step 2.
33
+
34
+ **API approach** (works — try first):
35
+ ```bash
36
+ POST /services/data/v68.0/sobjects/BusinessProcess
37
+ {"Name":"Student Advising","TableEnumOrId":"Case","Description":"Advising case support process"}
38
+ ```
39
+ Do **NOT** send `IsActive` on insert — it is `INVALID_FIELD_FOR_INSERT_UPDATE`. The BusinessProcess is active by default. Capture the returned `Id` and the `Name` ("Student Advising") — Step 2 references the process by **Name**, not Id.
40
+
41
+ **Setup path** (UI fallback):
42
+ 1. Navigate to Setup → Quick Find → "Support Processes" → Click New
43
+ 2. For "Existing Support Process", select Master
44
+ 3. Enter support process name: "Student Advising"
45
+ 4. Click Save; leave Case Status as default, click Save again
46
+
47
+ **Verification** (read back by the Id captured at creation — a SOQL `SELECT Id FROM <Object> WHERE ...` via `queryParams` also works if you need to re-find the record later):
48
+ ```http
49
+ GET /services/data/v68.0/sobjects/BusinessProcess/<id-captured-from-create-response>
50
+ ```
51
+
52
+ ---
53
+
54
+ #### Step 2 — Create Advising Case Record Types
55
+
56
+ **What it does**: Creates specialized case record types for different advising scenarios.
57
+
58
+ **API approach** (works — try first). Use the Tooling `RecordType` with the `FullName` + `Metadata` shape (NOT flat columns). `businessProcess` = the BusinessProcess **Name** from Step 1, not its Id:
59
+ ```http
60
+ POST /services/data/v68.0/tooling/sobjects/RecordType
61
+ {"FullName":"Case.Academic","Metadata":{"label":"Academic","active":true,"businessProcess":"Student Advising","description":"Academic advising cases"}}
62
+ ```
63
+ Repeat with `FullName` `Case.Health`, `Case.Wellbeing` (and `Case.FinancialAid` if used), changing `label`.
64
+
65
+ **Profile permissions (record type visibility) are NOT applied via this API** — the record type is created but not assigned to any profile. Assigning it to profiles is a separate step (Setup → Profiles → Record Type Settings, or a `Profile` metadata deploy).
66
+
67
+ **Setup path** (UI fallback):
68
+ 1. Setup → Quick Find → "Set Up Education Cloud" → Set Up Education Cloud → under "Create Advising Case Record Types" click "Create Case Record Types"
69
+ 2. On Case Record Types → New; for "Existing Record Type" select Master
70
+ 3. Enter label (e.g., "Academic"), Tab to auto-populate name
71
+ 4. For "Support Process" select "Student Advising"; select Active
72
+ 5. Select profile permissions → Next → Save
73
+ 6. Repeat for Health, Wellbeing (and optional Financial Aid)
74
+
75
+ **Verification** (RecordType is a tooling object — use `/tooling/sobjects` for GET-by-Id, or `/tooling/query` via `queryParams` for a SOQL lookup):
76
+ ```http
77
+ GET /services/data/v68.0/tooling/sobjects/RecordType/<id-captured-from-create-response>
78
+ ```
79
+ Repeat per record type created (Academic, Health, Wellbeing, and FinancialAid if used), using each one's Id from its own create response.
80
+
81
+ ---
82
+
83
+ #### Step 3 — Set Up Success Teams
84
+
85
+ **What it does**: Creates success teams for collaborative case management, keyed to a case record type.
86
+
87
+ **PREREQUISITE** — a `CaseTeamTemplate` must exist first; `SuccessTeam` references it by **Name** via `DefaultUnassignedCaseTeam`. Check existence first with `GET /services/data/v68.0/query` and `queryParams: {"q": "SELECT Id FROM CaseTeamTemplate WHERE Name='<name>'"}`; if none found, create directly and read back by the Id captured at creation:
88
+ ```http
89
+ POST /services/data/v68.0/sobjects/CaseTeamTemplate
90
+ {"Name":"Advising Team","Description":"Default advising success team"}
91
+ ```
92
+ ```http
93
+ GET /services/data/v68.0/sobjects/CaseTeamTemplate/<id-captured-from-create-response>
94
+ ```
95
+
96
+ **Create the Success Team** (`IsActive` IS writable here, unlike BusinessProcess). `CaseRecordTypeId` = the RecordType Id from Step 2; `DefaultUnassignedCaseTeam` = the CaseTeamTemplate **Name**:
97
+ ```http
98
+ POST /services/data/v68.0/sobjects/SuccessTeam
99
+ {"Name":"Academic Success Team","CaseRecordTypeId":"<Academic RecordType Id>","DefaultUnassignedCaseTeam":"Advising Team","IsActive":true}
100
+ ```
101
+ Repeat per case record type (Wellbeing, Health).
102
+
103
+ **Setup path** (UI fallback): Student Success app → Success Teams tab → New → name, select case record type, select/create case team → Save.
104
+
105
+ **Verification** (read back each by the Id captured at creation — a SOQL `SELECT Id FROM <Object> WHERE ...` via `queryParams` also works if you need to re-find records later):
106
+ ```http
107
+ GET /services/data/v68.0/sobjects/SuccessTeam/<id-captured-from-create-response>
108
+ ```
109
+ Repeat per case record type's Success Team created above.
110
+
111
+ ---
112
+
113
+ #### Step 4 — Enable Care Plans (after Success Teams)
114
+
115
+ **What it does**: Enables care plans to track intervention plans, goals, and progress for at-risk students.
116
+
117
+ **Write approach** (works — `IndustriesSettings` toggle). **IRREVERSIBLE.** Element is **`enableCarePlansPreference`** — do NOT use `enableCarePlans` (→ `FIELD_INTEGRITY_EXCEPTION`). Use the SKILL.md **Domain & Feature Toggle Write Path**:
118
+ ```json
119
+ {
120
+ "type": "IndustriesSettings",
121
+ "fullName": "Industries",
122
+ "xmlRep": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><IndustriesSettings xmlns=\"http://soap.sforce.com/2006/04/metadata\"><enableCarePlansPreference>true</enableCarePlansPreference></IndustriesSettings>"
123
+ }
124
+ ```
125
+ Do NOT use `setup/org/preferences/{name}` (404).
126
+
127
+ **Verification** (cold read — `success:true` alone unreliable): tooling GET `IndustriesSettings` by DurableId `bWRjLzBIRS9JbmR1c3RyaWVzU2V0dGluZ3M=` and confirm `.Metadata.enableCarePlansPreference` / flat `IsCarePlansPreferenceEnabled` is `true`. If the GET 500s, fall back to a Setup UI confirmation (see license-gating/cold-verify note above) rather than reporting unverified.
128
+
129
+ If the write itself 400s `INSUFFICIENT_ACCESS_OR_READONLY`, this is likely license-gated on this org — see note above.
130
+
131
+ ---
132
+
133
+ #### Step 5 — Enable Support Programs (before Scheduler)
134
+
135
+ **What it does**: Enables benefit/program management used by Student Success programs. Four toggles flip in a **single** metadata PUT.
136
+
137
+ **Write approach** (works — `IndustriesSettings` toggles). **IRREVERSIBLE.** One PUT with all four elements:
138
+ ```json
139
+ {
140
+ "type": "IndustriesSettings",
141
+ "fullName": "Industries",
142
+ "xmlRep": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><IndustriesSettings xmlns=\"http://soap.sforce.com/2006/04/metadata\"><enableBenefitManagementPreference>true</enableBenefitManagementPreference><enableBenefitAndGoalSharingPref>true</enableBenefitAndGoalSharingPref><allowBenefitAssignmentWithInactiveProgramEnrollment>true</allowBenefitAssignmentWithInactiveProgramEnrollment><enableProgramCohorts>true</enableProgramCohorts></IndustriesSettings>"
143
+ }
144
+ ```
145
+
146
+ **Verification** (cold read): tooling GET by DurableId; confirm `.Metadata.enableBenefitManagementPreference`, `enableBenefitAndGoalSharingPref`, `allowBenefitAssignmentWithInactiveProgramEnrollment`, and `enableProgramCohorts` are all `true`. If the GET 500s, fall back to Setup UI confirmation (see license-gating/cold-verify note above).
147
+
148
+ If the write itself 400s `INSUFFICIENT_ACCESS_OR_READONLY`, this is likely license-gated on this org — see note above.
149
+
150
+ ---
151
+
152
+ #### Step 6 — Enable Salesforce Scheduler (partial — for advising appointments)
153
+
154
+ **What it does**: Enables Salesforce Scheduler for students to book advising appointments. **Partially API-writable** — two org prefs flip via metadata PUT; the master enable + a couple settings are manual/UI only.
155
+
156
+ **API-writable** (`IndustriesSettings` toggles — one PUT):
157
+ ```json
158
+ {
159
+ "type": "IndustriesSettings",
160
+ "fullName": "Industries",
161
+ "xmlRep": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><IndustriesSettings xmlns=\"http://soap.sforce.com/2006/04/metadata\"><enableEventManagementOrgPref>true</enableEventManagementOrgPref><enableShareSaWithArOrgPref>true</enableShareSaWithArOrgPref></IndustriesSettings>"
162
+ }
163
+ ```
164
+ Cold-verify `enableEventManagementOrgPref` and `enableShareSaWithArOrgPref` are `true`. If the cold-verify GET 500s, fall back to Setup UI confirmation (see license-gating/cold-verify note above); if the write 400s `INSUFFICIENT_ACCESS_OR_READONLY`, check licensing on this org before concluding the toggle is unreachable via API.
165
+
166
+ **Manual / UI only** (NOT API-writable):
167
+ - **Scheduler master enable** — license-gated (Field Service). Setup → Quick Find → "Salesforce Scheduler Settings" → turn on Salesforce Scheduler. If no license, enablement fails.
168
+ - **Multiple Topics for Shifts** — skip (has its own prerequisites; not needed for advising).
169
+ - **Schedule Appointments Using Engagement Channels** — enable manually in Salesforce Scheduler Settings.
170
+
171
+ ---
172
+
173
+ #### Step 7 — Set Up the Advisor Console
174
+
175
+ **What it does**: Configures the Advisor Console app with care plans, alerts, success teams, and appointment scheduler components.
176
+
177
+ **Setup path**:
178
+ 1. Navigate to Setup → App Manager → Find "Advisor Console"
179
+ 2. Click Edit
180
+ 3. Assign page layouts and record types to advisor profiles
181
+ 4. Add relevant components to app:
182
+ - Care Plans
183
+ - Alerts
184
+ - Success Teams
185
+ - Appointment Scheduler
186
+ - Student 360 view
187
+ 5. Save and assign to advisor user profiles
188
+
189
+ **Verification**: Check App Launcher shows Advisor Console for advisor users.
190
+
191
+ ---
192
+
193
+ #### Step 8 — Set Up the Director Console (Student Success)
194
+
195
+ **What it does**: Configures the Director Console with KPI components for directors.
196
+
197
+ **Setup path**:
198
+ 1. Navigate to Setup → App Manager → Find "Director Console"
199
+ 2. Click Edit
200
+ 3. Configure visibility and KPI components for directors:
201
+ - Student Success KPIs
202
+ - Advisor performance metrics
203
+ - Care plan pipeline
204
+ 4. Save and assign to director user profiles
205
+
206
+ **Verification**: Check App Launcher shows Director Console for director users.
207
+
208
+ ---
209
+
210
+ #### Step 9 — Configure Performance Alerts
211
+
212
+ **What it does**: Configures alert types (attendance, grades, concerns) and maps them to Success Teams.
213
+
214
+ **Setup path**:
215
+ 1. Navigate to Student Success app → Alert Settings tab
216
+ 2. Configure alert types:
217
+ - Attendance alerts (threshold: < 80%)
218
+ - Grade alerts (threshold: < C average)
219
+ - Concern alerts (flagged by faculty)
220
+ 3. Map alerts to Success Teams and case record types
221
+ 4. Optionally connect to Care Plans via "Apply Care Plans to Alerts" feature
222
+ 5. Save
223
+
224
+ **Verification**: Check Alert Settings show configured alert types.
225
+
226
+ ---
227
+
228
+ #### Step 10 — Set Up the Learner Portal (Experience Cloud)
229
+
230
+ **What it does**: Deploys student-facing portal with Action Center, Pulse Checks, Career Planning, Degree Planning.
231
+
232
+ **Prerequisites**: Experience Cloud license required.
233
+
234
+ **Setup path**:
235
+ 1. Navigate to Setup → Digital Experiences → All Sites
236
+ 2. Create new Experience Cloud site or configure existing site
237
+ 3. Add Student Success components:
238
+ - Action Center (tasks, alerts)
239
+ - Pulse Checks (wellness check-ins)
240
+ - Career Planning
241
+ - Degree Planning
242
+ - Appointment booking
243
+ 4. Configure access for authenticated students
244
+ 5. Publish and activate the portal
245
+
246
+ **Verification**: Navigate to portal URL and verify components load for student users.
247
+
248
+ ---
249
+
@@ -0,0 +1,27 @@
1
+ # Education Cloud Domain Features — Complete Setup Guide
2
+
3
+ Configuration guide for each Education Cloud domain and its sub-features. Based on Salesforce Help Articles. Each domain's full setup steps live in its own reference file under `domain-features/` — open the one matching the domain being configured.
4
+
5
+ ## Domain Reference Files
6
+
7
+ | Domain | File |
8
+ |--------|------|
9
+ | 1. Student Success | [domain-features/student-success.md](domain-features/student-success.md) |
10
+ | 2. Recruitment & Admissions | [domain-features/recruitment-admissions.md](domain-features/recruitment-admissions.md) |
11
+ | 3. Academic Operations | [domain-features/academic-operations.md](domain-features/academic-operations.md) |
12
+ | 4. Alumni Relations | [domain-features/alumni-relations.md](domain-features/alumni-relations.md) |
13
+ | 5. Student Management | [domain-features/student-management.md](domain-features/student-management.md) |
14
+ | 6. Mentoring | [domain-features/mentoring.md](domain-features/mentoring.md) |
15
+ | Cross-Domain Dependencies | [domain-features/cross-domain-dependencies.md](domain-features/cross-domain-dependencies.md) |
16
+ | IndustriesSettings Toggle Fields — Quick Reference | [domain-features/industriessettings-toggle-reference.md](domain-features/industriessettings-toggle-reference.md) |
17
+
18
+ ## General Notes
19
+
20
+ - All domains require Education Cloud Foundation and Person Accounts enabled first
21
+ - Some sub-features require additional licenses (Field Service for Scheduler, Fundraising for gift management, Experience Cloud for portals)
22
+ - Object names may vary by Education Cloud version — check API version compatibility
23
+ - Verification queries may fail if objects are not yet provisioned (async provisioning) — wait 2-3 minutes and retry
24
+ - Setup menu paths may change with Salesforce UI updates — if path not found, search Setup for the feature name
25
+ - Write domain/feature toggles via the headless metadata PUT path (IndustriesSettings `xmlRep`, write `dispatch` tool); never `setup/org/preferences/{name}` (404). Fall back to UI instructions only on error
26
+ - EDU toggles are IRREVERSIBLE (`false → true` only) — warn the user, never promise a revert
27
+ - Student Management has no separate domain toggle — it is enabled when Academic Operations is configured with student enrollment records
@@ -0,0 +1,23 @@
1
+ # Additional Gotchas
2
+
3
+ Lower-frequency gotchas and toggle-write failure classes, split out of `SKILL.md`'s Gotchas table (kept to the 10 highest-impact entries). Read this when the top-10 table doesn't cover the error you're seeing.
4
+
5
+ | Issue | Resolution |
6
+ |-------|------------|
7
+ | Org edition not Enterprise+ | Education Cloud requires Enterprise, Performance, Unlimited, or Developer Edition — cannot install on lower editions |
8
+ | Some sub-features require additional licenses | If enablement fails with license error, inform user of required license (e.g., Salesforce Scheduler requires Field Service, Fundraising requires Advancement license, Experience Cloud license for portals) |
9
+ | Student Management has no separate domain toggle | Student Management is enabled when Academic Operations is configured with student enrollment records |
10
+ | Record creation (Business Process, Learning Programs) must be done manually or via API | Education Cloud does not auto-create these records — user must create via Setup, Data API, or Tooling API after domain is enabled |
11
+ | OmniStudio components must be activated separately | After OmniStudio is enabled, individual OmniScripts and FlexCards (Application Stages, Course Search, Matching Assessments) must be activated in Setup → OmniStudio |
12
+ | Experience Cloud portals require separate configuration | After domain is enabled, portals (Learner Portal, Applicant Portal, Alumni Portal, Mentoring Portal) must be created/configured in Experience Builder with domain-specific components |
13
+ | Sub-feature configuration steps vary significantly by domain | Always read the domain's file under `references/domain-features/` for domain-specific setup paths — Student Success, Recruitment & Admissions, and Academic Operations have 10+ sub-feature steps each |
14
+ | Verification queries may fail if objects not yet provisioned | Some domains provision objects asynchronously — retry after 2-3 minutes if query fails with "invalid object" error |
15
+ | `SELECT IsPersonAccountEnabled FROM Organization` returns `INVALID_FIELD` | No such column on `Organization` — verify Person Accounts via `Account/describe` (API, headless first) and check for `IsPersonAccount`/`Person*` fields, or `sf sobject describe -s Account` as fallback |
16
+ | Profile permissions on newly created RecordTypes (including LearningAchievement types) are NOT settable via API | Record type creates successfully but has no profile visibility — flag as a manual follow-up step (Setup → Profiles → Record Type Settings, or a `Profile` metadata deploy) |
17
+ | SOAP `updateMetadata` / `metadata/deployRequest` return `ROUTE_NOT_FOUND` | Blocked through the gateway — do NOT use; the headless metadata PUT is the supported write path (see "Endpoints that DO NOT work" in `SKILL.md`) |
18
+ | **Failure class — Aura-only, no MDAPI/Tooling/REST route at all** (e.g. Industries Cloud Common Decision Tables Access, `BREDecisionTableAccess`) | Backing call is an internal Aura action with no external route — manual UI only, do not keep probing endpoints |
19
+ | **Failure class — API write blocked at field level** (e.g. Intelligent Question Generation, `enableSmartAsmtQstnGeneration`) | Field exists and name is correct, but write returns `INSUFFICIENT_ACCESS_OR_READONLY: "cannot be accessed using the API"` — manual UI only |
20
+ | **Failure class — hard reject on disable-only** (e.g. Discovery Framework, `enableIndustriesAssessment`) | `true→false` returns HTTP 500 `UNKNOWN_EXCEPTION`; this is separate from the general one-way irreversibility — the enable (`false→true`) direction is untested where the field was already `true` |
21
+ | **Failure class — settings type invisible to Tooling/EntityDefinition but still MDAPI-writable** (e.g. Omnistudio Metadata, `OmniStudioSettings`, `fullName: OmniStudio`) | Metadata PUT write succeeds, but no GET/verify path exists via Tooling API — UI-confirmed only; if you encounter one of these, note it as write-succeeds-zero-verify-path rather than assuming failure |
22
+ | **Failure class — type-level UPDATE block** (e.g. Timeline `TimelineSettings`, Video Calls `VideoCallsSettings`) | PUT returns HTTP 400 `UNSUPPORTED_OPERATION: "MetadataCrud does not support UPDATE on type: X"` — block is on the whole type, no `fullName` variant fixes it; manual UI only |
23
+ | **Pattern — org preference API, not `IndustriesSettings`** (confirmed on Einstein Generative AI, `EinsteinGPTCopilotEnabled`) | Some toggles are Setup-Connect org preferences, not `IndustriesSettings` metadata fields — no `type`/`fullName`/`xmlRep`. Shape: `GET /services/data/v68.0/setup/org/preferences/<PrefName>` → `{"isPreferenceEnabled": bool}`; `PATCH` same path with `{"desiredState": true}` → response echoes post-write state. If a metadata PUT returns `FIELD_INTEGRITY_EXCEPTION: invalid at this location` for a plausible-looking element name, the field may not be on `IndustriesSettings` at all — try this org-preference path next before assuming manual-UI-only |
@@ -0,0 +1,67 @@
1
+ # Domain & Feature Toggle Write Path (authoritative)
2
+
3
+ Education Cloud domain toggles — `enableEducationCloud`, `enableStudentSuccess`, `enableAcademicOperations`, `enableMentoring`, `enableCorporateRelations`, `enableStudentManagement`, `enableFinancialAid`, `enableFundraising`, `enableOutcomes`, `enableProgramCohorts`, `enableStudentGoals`, `enableAlumniRelations`, `enableRNADynamicApplications`, and ~28 similar — are **fields inside the `IndustriesSettings` settings file**. They are NOT in Core's `ORG_PREFERENCES` allowlist.
4
+
5
+ > **IRREVERSIBLE — one-way by design.** These toggles are `false → true` only. `true → false` is rejected/unsupported. **WARN the user before flipping any toggle. Do NOT promise a revert or rollback.**
6
+
7
+ ## Endpoints that DO NOT work — never use these
8
+
9
+ | Attempt | Result |
10
+ |---------|--------|
11
+ | `PATCH setup/org/preferences/{name}` | 404 — name not in ORG_PREFERENCES allowlist |
12
+ | Tooling sObject `PATCH` on `IndustriesSettings` | 400 `JSON_PARSER_ERROR` (complexvalue fields) |
13
+ | SOAP `/services/Soap/m/XX.0` `updateMetadata` | `ROUTE_NOT_FOUND` through the gateway |
14
+ | `POST /services/data/vXX/metadata/deployRequest` (multipart zip) | `ROUTE_NOT_FOUND` through the gateway |
15
+
16
+ ## What writes via this path, what does not
17
+
18
+ | Category | API-writable via metadata PUT? |
19
+ |----------|-------------------------------|
20
+ | Domain toggles (`enableStudentSuccess`, …) — **once foundation is ON** | Yes |
21
+ | Sub-feature toggles (`enableCarePlansPreference`, Support Programs, Scheduler org prefs) — **once foundation is ON** | Yes |
22
+ | **Education Cloud foundation** (`enableEducationCloud`) | No — via metadata PUT. **Confirmed silent no-op** for this specific field (`success:true`, stays `false`); the metadata PUT path itself is proven to route AND flip real sub-feature toggles (verified: `enableStudentGoals` `false→true`), so this is feature-specific, not a transport failure. Yes — via the dedicated invoke endpoint instead (see "Enabling the foundation" below). |
23
+
24
+ ## Enabling the foundation (`enableEducationCloud`) — dedicated invoke endpoint
25
+
26
+ Root cause of the silent no-op: this toggle is AURA-IS-CANONICAL — the real enable action runs extra `ReleasableAction` provisioning wiring beyond a raw field flip, and only the dedicated controller endpoint below runs it. Do not attempt the metadata PUT for foundation.
27
+
28
+ Same `dispatch`/`dispatch_readonly` tools and headless-360 transport as the metadata path, different URL:
29
+ - READ: `GET /headless/invoke/platform/education-cloud-settings` (`dispatch_readonly` is fine) — inspect `educationCloudEnabled`.
30
+ - WRITE: `PATCH /headless/invoke/platform/education-cloud-settings/enable-education-cloud` (empty body, via the write-enabled `dispatch` tool).
31
+ - cold-VERIFY: repeat the GET above — confirm `educationCloudEnabled: true` on a fresh read. Also cold-check the `IndustriesSettings` tooling GET (`.Metadata.enableEducationCloud` / `IsEducationCloudEnabled`) as a secondary check — the invoke GET is authoritative if they disagree.
32
+ - If the invoke endpoint errors or cold-verify still shows `false`: fall back to manual UI — Setup → Quick Find → "Set Up Education Cloud" → Toggle "Enable Education Cloud" → Save. Warn this cannot be disabled after enabling. Wait for user confirmation, then cold-verify again.
33
+ | Person Accounts | No — manual UI only |
34
+ | License-gated features (Salesforce Scheduler master enable, Field Service) | No — manual UI only |
35
+
36
+ ## The correct sequence: READ → WRITE → VERIFY (cold-verify is mandatory)
37
+
38
+ **Constants:** API version `v68.0` · `IndustriesSettings` `DurableId` = `bWRjLzBIRS9JbmR1c3RyaWVzU2V0dGluZ3M=` (raw `=`, NOT url-encoded `%3D`).
39
+
40
+ **1. READ (pre-read current state)** — `dispatch_readonly` GET is fine here:
41
+ ```http
42
+ GET /services/data/v68.0/tooling/sobjects/IndustriesSettings/bWRjLzBIRS9JbmR1c3RyaWVzU2V0dGluZ3M=
43
+ ```
44
+ Inspect `.Metadata.enable*` (and the flat `Is<X>Enabled` fields) for current state.
45
+
46
+ > `SELECT ... FROM IndustriesSettings` returns **only `Id` and `DurableId` — NO `Metadata`.** You MUST GET the record by `DurableId` to read toggle state. Do NOT use the placeholder Id `000000000000000AAA`.
47
+
48
+ **2. WRITE (flip the toggle)** — use the **write-enabled `dispatch` tool** (NOT `dispatch_readonly` — read-only *fakes* write success, returning `success:true` without writing). Synchronous, no polling:
49
+ ```http
50
+ PUT /services/data/v68.0/headless/metadata
51
+ ```
52
+ Structured JSON body — `type` is literally `IndustriesSettings`, `fullName` is `Industries`, `xmlRep` includes the XML declaration. One PUT can flip **multiple** elements at once:
53
+ ```json
54
+ {
55
+ "type": "IndustriesSettings",
56
+ "fullName": "Industries",
57
+ "xmlRep": "<?xml version=\"1.0\" encoding=\"UTF-8\"?><IndustriesSettings xmlns=\"http://soap.sforce.com/2006/04/metadata\"><enableStudentSuccess>true</enableStudentSuccess></IndustriesSettings>"
58
+ }
59
+ ```
60
+
61
+ **3. VERIFY (cold read — REQUIRED)** — repeat step 1 and confirm `.Metadata.<element>` and/or the flat `Is<X>Enabled` field is now `true`.
62
+
63
+ > **`success:true` alone is unreliable — always cold-verify.** The foundation write returned `success:true` yet no-op'd. Only a fresh GET of the record confirms the toggle actually flipped.
64
+
65
+ > **Cold-verify fallback — the tooling GET can 500 org-wide.** Confirmed on a test org: `GET .../tooling/sobjects/IndustriesSettings/<DurableId>` returned HTTP 500 `UNKNOWN_EXCEPTION` on every value read (any field, any API version), root-caused to a null UDD `LogicalFieldDefinition` on one preference column in that org's data — an org-data defect, not a skill or transport bug (`describe` and `SELECT Id, DurableId` still returned 200). If this GET 500s on 3 consecutive attempts, stop retrying and ask the admin to confirm the toggle's state in Setup UI instead. Report it explicitly as "confirmed via Setup UI, not cold-verified via API" — never claim API cold-verify succeeded when it didn't.
66
+
67
+ > **License-gating on the write itself.** A toggle write can return `400 INSUFFICIENT_ACCESS_OR_READONLY` (nothing written) purely because the org lacks a license, not because the feature is unreachable via API — confirmed on a test org where the identical write failed, then succeeded after the admin added licenses with no other change. On this error, ask whether the org is fully licensed for the feature before concluding the API path doesn't work.
@@ -0,0 +1,62 @@
1
+ #!/usr/bin/env python3
2
+ """Decide whether Education Cloud is licensed/provisioned on the org.
3
+
4
+ Permission set names for Education Cloud vary by org/release, so a single
5
+ exact-name match is unreliable. Reads a JSON object from stdin:
6
+
7
+ {
8
+ "permissionSets": [ { "Id": "...", "Name": "..." }, ... ],
9
+ "businessProfileDescribe": { "createable": true, ... } | null
10
+ }
11
+
12
+ `permissionSets` is the `records` array from
13
+ `SELECT Id, Name FROM PermissionSet WHERE Name LIKE '%EducationCloud%'`.
14
+ `businessProfileDescribe` is the describe result for the `BusinessProfile`
15
+ sobject, or null/omitted if that describe call 404'd.
16
+
17
+ Rows found in `permissionSets` -> provisioned. Zero rows -> cross-check
18
+ `businessProfileDescribe.createable` before concluding not-provisioned.
19
+
20
+ Usage:
21
+ python3 scripts/check_license_provisioned.py <<'JSON'
22
+ {"permissionSets": [], "businessProfileDescribe": {"createable": true}}
23
+ JSON
24
+ """
25
+
26
+ from __future__ import annotations
27
+
28
+ import json
29
+ import sys
30
+
31
+
32
+ def main() -> int:
33
+ payload = json.load(sys.stdin)
34
+ permission_sets = payload.get("permissionSets") or []
35
+ describe = payload.get("businessProfileDescribe")
36
+
37
+ if permission_sets:
38
+ result = {
39
+ "provisioned": True,
40
+ "reason": "matching permission set(s) found",
41
+ "matchingPermissionSets": [ps.get("Name") for ps in permission_sets],
42
+ }
43
+ elif isinstance(describe, dict) and describe.get("createable") is True:
44
+ result = {
45
+ "provisioned": True,
46
+ "reason": "zero permission-set matches, but BusinessProfile is createable — treat as provisioned, note the mismatch",
47
+ "matchingPermissionSets": [],
48
+ }
49
+ else:
50
+ result = {
51
+ "provisioned": False,
52
+ "reason": "zero permission-set matches and BusinessProfile is not createable (404 or createable:false) — license not provisioned",
53
+ "matchingPermissionSets": [],
54
+ }
55
+
56
+ json.dump(result, sys.stdout, indent=2)
57
+ print()
58
+ return 0
59
+
60
+
61
+ if __name__ == "__main__":
62
+ sys.exit(main())
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env python3
2
+ """Check whether an org's edition meets Education Cloud's minimum requirement.
3
+
4
+ Reads a JSON object from stdin shaped like a SOQL query result for
5
+ `SELECT OrganizationType FROM Organization` (the `records` array, or a bare
6
+ list containing that one record). Prints a JSON verdict.
7
+
8
+ Usage:
9
+ python3 scripts/check_org_edition.py \
10
+ --allowed "Enterprise Edition,Performance Edition,Unlimited Edition,Developer Edition" <<'JSON'
11
+ {"records": [{"OrganizationType": "Enterprise Edition"}]}
12
+ JSON
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import argparse
18
+ import json
19
+ import sys
20
+
21
+
22
+ def main() -> int:
23
+ parser = argparse.ArgumentParser()
24
+ parser.add_argument("--allowed", required=True, help="Comma-separated list of qualifying OrganizationType values")
25
+ args = parser.parse_args()
26
+ allowed = [a.strip() for a in args.allowed.split(",") if a.strip()]
27
+
28
+ payload = json.load(sys.stdin)
29
+ records = payload.get("records", payload) if isinstance(payload, dict) else payload
30
+
31
+ if not records:
32
+ json.dump({"eligible": False, "organizationType": None, "reason": "no Organization record returned"}, sys.stdout, indent=2)
33
+ print()
34
+ return 0
35
+
36
+ org_type = records[0].get("OrganizationType")
37
+ result = {"eligible": org_type in allowed, "organizationType": org_type, "allowed": allowed}
38
+ json.dump(result, sys.stdout, indent=2)
39
+ print()
40
+ return 0
41
+
42
+
43
+ if __name__ == "__main__":
44
+ sys.exit(main())
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env python3
2
+ """Check whether the running user has one of the org's Education Cloud permission sets assigned.
3
+
4
+ Reads a JSON object from stdin shaped like a SOQL query result for
5
+ `SELECT Id, PermissionSet.Name FROM PermissionSetAssignment WHERE
6
+ AssigneeId='<id>' AND PermissionSet.Name LIKE '%EducationCloud%'` (the
7
+ `records` array, or a bare list). Prints a JSON verdict.
8
+
9
+ Usage:
10
+ python3 scripts/check_permission_assigned.py <<'JSON'
11
+ {"records": [{"PermissionSet": {"Name": "EducationCloudAccess"}}]}
12
+ JSON
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import json
18
+ import sys
19
+
20
+
21
+ def main() -> int:
22
+ payload = json.load(sys.stdin)
23
+ records = payload.get("records", payload) if isinstance(payload, dict) else payload
24
+
25
+ names = []
26
+ for rec in records or []:
27
+ permission_set = rec.get("PermissionSet") or {}
28
+ name = permission_set.get("Name")
29
+ if name:
30
+ names.append(name)
31
+
32
+ result = {"assigned": bool(names), "matchingPermissionSets": names}
33
+ json.dump(result, sys.stdout, indent=2)
34
+ print()
35
+ return 0
36
+
37
+
38
+ if __name__ == "__main__":
39
+ sys.exit(main())
@@ -6,6 +6,8 @@ metadata:
6
6
  minApiVersion: "65.0"
7
7
  domains:
8
8
  - "Education"
9
+ relatedSkills:
10
+ - "education-cloud-domain-configure"
9
11
  accessCheck:
10
12
  - type: "license"
11
13
  value: "Education Cloud"
@@ -1,9 +1,10 @@
1
1
  # Step 0 — Foundation Prerequisites
2
2
 
3
3
  This skill can run standalone, without any other Education Cloud setup skill running first. Verify
4
- these before Step 1 — they are shared across the EDU skill family. A gap here is a missing
5
- prerequisite to resolve, not a dead end — self-heal what's API-writable, ask/confirm before any
6
- write, otherwise instruct manual Setup and wait for confirmation.
4
+ these before Step 1 — they are shared across the EDU skill family (also required by
5
+ `education-cloud-domain-configure`). A gap here is a missing prerequisite to resolve, not a
6
+ dead end — self-heal what's API-writable, ask/confirm before any write, otherwise instruct manual
7
+ Setup and wait for confirmation.
7
8
 
8
9
  ## Checks (in order — each can stop the workflow if unresolved)
9
10