@salesforce/afv-skills 1.29.0 → 1.30.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 (205) hide show
  1. package/README.md +2 -0
  2. package/package.json +1 -1
  3. package/skills/agentforce-architecture-analyze/README.md +2 -8
  4. package/skills/agentforce-architecture-analyze/SKILL.md +2 -2
  5. package/skills/agentforce-architecture-analyze/references/contract.json +4 -4
  6. package/skills/agentforce-architecture-analyze/references/soql_fields.md +1 -1
  7. package/skills/data360-activate/README.md +0 -1
  8. package/skills/data360-activate/SKILL.md +0 -2
  9. package/skills/data360-connect/README.md +0 -2
  10. package/skills/data360-connect/SKILL.md +0 -2
  11. package/skills/data360-harmonize/SKILL.md +0 -1
  12. package/skills/data360-orchestrate/README.md +0 -7
  13. package/skills/data360-orchestrate/SKILL.md +0 -2
  14. package/skills/data360-prepare/README.md +0 -1
  15. package/skills/data360-prepare/SKILL.md +0 -1
  16. package/skills/data360-query/README.md +0 -1
  17. package/skills/data360-query/SKILL.md +0 -1
  18. package/skills/data360-segment/README.md +0 -1
  19. package/skills/data360-segment/SKILL.md +0 -2
  20. package/skills/experience-cms-brand-apply/SKILL.md +47 -16
  21. package/skills/experience-lwc-generate/README.md +3 -2
  22. package/skills/experience-lwc-generate/references/async-notification-patterns.md +1 -1
  23. package/skills/experience-lwc-generate/references/component-patterns.md +3 -3
  24. package/skills/experience-lwc-generate/references/flow-integration-guide.md +1 -1
  25. package/skills/experience-lwc-generate/references/lwc-best-practices.md +4 -4
  26. package/skills/experience-lwc-generate/references/scoring-and-testing.md +1 -1
  27. package/skills/experience-lwc-generate/references/state-management.md +2 -2
  28. package/skills/experience-lwc-generate/references/triangle-pattern.md +3 -3
  29. package/skills/experience-lwc-generate/scripts/post-tool-validate.py +2 -2
  30. package/skills/experience-lwc-generate/scripts/template_validator.py +1 -1
  31. package/skills/external-diagram-mermaid-generate/README.md +2 -2
  32. package/skills/external-diagram-mermaid-generate/SKILL.md +1 -3
  33. package/skills/external-diagram-mermaid-generate/assets/agentforce/agent-flow.md +4 -4
  34. package/skills/external-diagram-mermaid-generate/assets/architecture/system-landscape.md +1 -1
  35. package/skills/external-diagram-mermaid-generate/assets/datamodel/b2b-commerce-erd.md +3 -3
  36. package/skills/external-diagram-mermaid-generate/assets/datamodel/campaigns-erd.md +1 -1
  37. package/skills/external-diagram-mermaid-generate/assets/datamodel/consent-erd.md +2 -2
  38. package/skills/external-diagram-mermaid-generate/assets/datamodel/files-erd.md +2 -2
  39. package/skills/external-diagram-mermaid-generate/assets/datamodel/forecasting-erd.md +2 -2
  40. package/skills/external-diagram-mermaid-generate/assets/datamodel/fsl-erd.md +2 -2
  41. package/skills/external-diagram-mermaid-generate/assets/datamodel/party-model-erd.md +1 -1
  42. package/skills/external-diagram-mermaid-generate/assets/datamodel/quote-order-erd.md +3 -3
  43. package/skills/external-diagram-mermaid-generate/assets/datamodel/revenue-cloud-erd.md +2 -2
  44. package/skills/external-diagram-mermaid-generate/assets/datamodel/sales-cloud-erd.md +1 -1
  45. package/skills/external-diagram-mermaid-generate/assets/datamodel/salesforce-erd.md +1 -1
  46. package/skills/external-diagram-mermaid-generate/assets/datamodel/scheduler-erd.md +2 -2
  47. package/skills/external-diagram-mermaid-generate/assets/datamodel/service-cloud-erd.md +3 -3
  48. package/skills/external-diagram-mermaid-generate/assets/datamodel/territory-management-erd.md +1 -1
  49. package/skills/external-diagram-mermaid-generate/assets/integration/api-sequence.md +1 -1
  50. package/skills/external-diagram-mermaid-generate/assets/oauth/authorization-code-pkce.md +1 -1
  51. package/skills/external-diagram-mermaid-generate/assets/oauth/authorization-code.md +1 -1
  52. package/skills/external-diagram-mermaid-generate/assets/oauth/client-credentials.md +1 -1
  53. package/skills/external-diagram-mermaid-generate/assets/oauth/device-authorization.md +2 -2
  54. package/skills/external-diagram-mermaid-generate/assets/oauth/jwt-bearer.md +2 -2
  55. package/skills/external-diagram-mermaid-generate/assets/oauth/refresh-token.md +1 -1
  56. package/skills/external-diagram-mermaid-generate/assets/oauth/user-agent-social-sign-on.md +2 -2
  57. package/skills/external-diagram-mermaid-generate/assets/role-hierarchy/user-hierarchy.md +1 -1
  58. package/skills/external-diagram-mermaid-generate/references/color-palette.md +13 -13
  59. package/skills/external-diagram-mermaid-generate/references/diagram-conventions.md +5 -5
  60. package/skills/external-diagram-mermaid-generate/references/erd-conventions.md +1 -1
  61. package/skills/external-diagram-mermaid-generate/references/mermaid-styling.md +2 -2
  62. package/skills/external-diagram-mermaid-generate/references/preview-guide.md +1 -1
  63. package/skills/external-diagram-mermaid-generate/references/usage-examples.md +9 -9
  64. package/skills/external-diagram-mermaid-generate/scripts/README.md +1 -1
  65. package/skills/integration-connectivity-connected-app-configure/README.md +4 -5
  66. package/skills/integration-connectivity-connected-app-configure/SKILL.md +2 -2
  67. package/skills/integration-connectivity-connected-app-configure/references/example-usage.md +7 -7
  68. package/skills/integration-connectivity-connected-app-configure/references/migration-guide.md +1 -1
  69. package/skills/integration-connectivity-connected-app-configure/references/oauth-flows-reference.md +1 -1
  70. package/skills/integration-connectivity-connected-app-configure/references/testing-validation-guide.md +3 -3
  71. package/skills/integration-connectivity-generate/README.md +1 -1
  72. package/skills/integration-connectivity-generate/SKILL.md +6 -0
  73. package/skills/integration-connectivity-generate/assets/callouts/rest-queueable-callout.cls +1 -1
  74. package/skills/integration-connectivity-generate/assets/external-services/external-service-operations.md +1 -1
  75. package/skills/integration-connectivity-generate/assets/soap/wsdl2apex-guide.md +1 -1
  76. package/skills/integration-connectivity-generate/references/callout-patterns.md +4 -0
  77. package/skills/integration-connectivity-generate/references/cdc-guide.md +2 -2
  78. package/skills/integration-connectivity-generate/references/event-driven-architecture-guide.md +5 -5
  79. package/skills/integration-connectivity-generate/references/event-patterns.md +3 -2
  80. package/skills/integration-connectivity-generate/references/external-services-guide.md +4 -1
  81. package/skills/integration-connectivity-generate/references/messaging-api-v2.md +2 -2
  82. package/skills/integration-connectivity-generate/references/named-credentials-automation.md +1 -1
  83. package/skills/integration-connectivity-generate/references/named-credentials-guide.md +12 -2
  84. package/skills/integration-connectivity-generate/references/platform-events-guide.md +3 -3
  85. package/skills/integration-connectivity-generate/references/rest-callout-patterns.md +1 -1
  86. package/skills/integration-connectivity-generate/references/scoring-rubric.md +1 -1
  87. package/skills/integration-connectivity-generate/references/security-best-practices.md +5 -2
  88. package/skills/integration-connectivity-generate/scripts/configure-named-credential.sh +16 -5
  89. package/skills/integration-connectivity-generate/scripts/set-api-credential.sh +11 -2
  90. package/skills/integration-connectivity-generate/scripts/suggest_credential_setup.py +4 -3
  91. package/skills/integration-connectivity-generate/scripts/validate_integration.py +1 -1
  92. package/skills/omnistudio-callable-apex-generate/README.md +1 -5
  93. package/skills/omnistudio-callable-apex-generate/SKILL.md +14 -4
  94. package/skills/omnistudio-callable-apex-generate/assets/pattern_callable_vanilla.cls +8 -1
  95. package/skills/omnistudio-callable-apex-generate/examples/Test_VlocityOpenInterface2Conversion/TRANSCRIPT.md +1 -1
  96. package/skills/omnistudio-callable-apex-generate/examples/Test_VlocityOpenInterfaceConversion/TRANSCRIPT.md +1 -1
  97. package/skills/omnistudio-datamapper-generate/SKILL.md +1 -1
  98. package/skills/omnistudio-datamapper-generate/assets/completion-summary-template.md +2 -2
  99. package/skills/omnistudio-datamapper-generate/references/best-practices.md +9 -9
  100. package/skills/omnistudio-datamapper-generate/references/naming-conventions.md +6 -6
  101. package/skills/omnistudio-datapacks-deploy/README.md +1 -1
  102. package/skills/omnistudio-datapacks-deploy/examples/business-internet-plus-bundle/deploy-business-internet-plus-bundle.yaml +1 -1
  103. package/skills/omnistudio-dependencies-analyze/SKILL.md +12 -5
  104. package/skills/omnistudio-dependencies-analyze/references/dependency-patterns.md +9 -9
  105. package/skills/omnistudio-dependencies-analyze/references/namespace-guide.md +1 -1
  106. package/skills/omnistudio-epc-catalog-generate/README.md +1 -1
  107. package/skills/omnistudio-flexcard-generate/SKILL.md +11 -4
  108. package/skills/omnistudio-flexcard-generate/references/best-practices.md +6 -6
  109. package/skills/omnistudio-flexcard-generate/references/data-binding-guide.md +9 -9
  110. package/skills/omnistudio-integration-procedure-generate/SKILL.md +9 -1
  111. package/skills/omnistudio-integration-procedure-generate/references/element-types.md +3 -3
  112. package/skills/omnistudio-omniscript-generate/SKILL.md +2 -2
  113. package/skills/omnistudio-omniscript-generate/references/best-practices.md +1 -1
  114. package/skills/omnistudio-omniscript-generate/scripts/check-duplicate-omniscript.sh +8 -0
  115. package/skills/omnistudio-omniscript-generate/scripts/deploy-omniscript.sh +8 -0
  116. package/skills/platform-apex-logs-debug/README.md +2 -2
  117. package/skills/platform-apex-logs-debug/references/cli-commands.md +2 -2
  118. package/skills/platform-apex-logs-debug/references/debug-log-reference.md +16 -16
  119. package/skills/platform-apex-logs-debug/references/log-analysis-tools.md +2 -2
  120. package/skills/platform-apex-test-run/README.md +1 -1
  121. package/skills/platform-apex-test-run/references/test-fix-loop.md +2 -2
  122. package/skills/platform-apex-test-run/references/testing-best-practices.md +3 -3
  123. package/skills/platform-data-manage/README.md +4 -4
  124. package/skills/platform-data-manage/references/bulk-testing-example.md +1 -1
  125. package/skills/platform-data-manage/references/crud-workflow-example.md +2 -2
  126. package/skills/platform-data-manage/references/orchestration.md +6 -6
  127. package/skills/platform-flexipage-generate/SKILL.md +281 -346
  128. package/skills/platform-flexipage-generate/references/cli_commands.md +39 -0
  129. package/skills/platform-flexipage-generate/references/flexipage_fieldSection.md +162 -0
  130. package/skills/platform-flexipage-generate/references/flexipage_richText.md +84 -0
  131. package/skills/platform-flexipage-generate/references/identifiers_and_regions.md +167 -0
  132. package/skills/platform-flexipage-generate/references/mcp_action_examples.md +104 -0
  133. package/skills/platform-flexipage-generate/references/record_flexipage_dynamicHighlights.md +119 -0
  134. package/skills/platform-flexipage-generate/references/xml_rules.md +335 -0
  135. package/skills/platform-flexipage-generate/scripts/resolve-component-instructions.sh +42 -0
  136. package/skills/platform-flexipage-generate/scripts/scan-lwc-components.sh +113 -0
  137. package/skills/platform-metadata-deploy/README.md +2 -2
  138. package/skills/platform-metadata-deploy/references/agent-deployment-guide.md +2 -2
  139. package/skills/platform-metadata-deploy/references/deployment-workflows.md +16 -16
  140. package/skills/platform-metadata-deploy/references/orchestration.md +3 -3
  141. package/skills/platform-metadata-deploy/references/trigger-deployment-safety.md +2 -2
  142. package/skills/platform-models-api-configure/SKILL.md +140 -0
  143. package/skills/platform-models-api-configure/scripts/get-orgjwt.sh +48 -0
  144. package/skills/platform-policy-rule-generate/SKILL.md +260 -0
  145. package/skills/platform-policy-rule-generate/references/deploy-errors.md +54 -0
  146. package/skills/platform-policy-rule-generate/references/fixtures-index.md +29 -0
  147. package/skills/platform-policy-rule-generate/references/policy-schema-full.md +250 -0
  148. package/skills/platform-policy-rule-generate/references/templates-access.md +132 -0
  149. package/skills/platform-policy-rule-generate/references/templates-advanced.md +58 -0
  150. package/skills/platform-policy-rule-generate/references/templates-record.md +75 -0
  151. package/skills/platform-policy-rule-generate/references/templates-transform.md +70 -0
  152. package/skills/platform-policy-rule-generate/references/templates.md +10 -0
  153. package/skills/platform-policy-rule-generate/references/ui-compatibility.md +142 -0
  154. package/skills/platform-soql-query/README.md +1 -1
  155. package/skills/platform-soql-query/SKILL.md +1 -1
  156. package/skills/platform-soql-query/references/anti-patterns.md +1 -1
  157. package/skills/platform-soql-query/references/field-coverage-rules.md +1 -1
  158. package/skills/platform-soql-query/references/query-optimization.md +1 -1
  159. package/skills/platform-soql-query/scripts/post-tool-validate.py +3 -3
  160. package/skills/data360-activate/CREDITS.md +0 -5
  161. package/skills/data360-connect/CREDITS.md +0 -5
  162. package/skills/data360-harmonize/CREDITS.md +0 -3
  163. package/skills/data360-orchestrate/CREDITS.md +0 -15
  164. package/skills/data360-orchestrate/UPSTREAM.md +0 -45
  165. package/skills/data360-prepare/CREDITS.md +0 -7
  166. package/skills/data360-query/CREDITS.md +0 -7
  167. package/skills/data360-segment/CREDITS.md +0 -3
  168. package/skills/experience-lwc-generate/CREDITS.md +0 -5
  169. package/skills/external-diagram-mermaid-generate/CREDITS.md +0 -46
  170. package/skills/external-diagram-visual-generate/CREDITS.md +0 -80
  171. package/skills/external-diagram-visual-generate/README.md +0 -83
  172. package/skills/external-diagram-visual-generate/SKILL.md +0 -207
  173. package/skills/external-diagram-visual-generate/assets/architecture/integration-flow.md +0 -55
  174. package/skills/external-diagram-visual-generate/assets/erd/core-objects.md +0 -131
  175. package/skills/external-diagram-visual-generate/assets/erd/custom-objects.md +0 -60
  176. package/skills/external-diagram-visual-generate/assets/lwc/dashboard-card.md +0 -45
  177. package/skills/external-diagram-visual-generate/assets/lwc/data-table.md +0 -57
  178. package/skills/external-diagram-visual-generate/assets/lwc/record-form.md +0 -60
  179. package/skills/external-diagram-visual-generate/assets/review/apex-review.md +0 -57
  180. package/skills/external-diagram-visual-generate/assets/review/lwc-review.md +0 -48
  181. package/skills/external-diagram-visual-generate/references/architect-aesthetic-guide.md +0 -257
  182. package/skills/external-diagram-visual-generate/references/examples-index.md +0 -35
  183. package/skills/external-diagram-visual-generate/references/gemini-cli-setup.md +0 -65
  184. package/skills/external-diagram-visual-generate/references/interview-questions.md +0 -529
  185. package/skills/external-diagram-visual-generate/references/iteration-workflow.md +0 -173
  186. package/skills/external-diagram-visual-generate/scripts/check-prerequisites.sh +0 -101
  187. package/skills/external-diagram-visual-generate/scripts/generate_image.py +0 -243
  188. package/skills/integration-connectivity-connected-app-configure/CREDITS.md +0 -3
  189. package/skills/integration-connectivity-generate/CREDITS.md +0 -5
  190. package/skills/omnistudio-callable-apex-generate/CREDITS.md +0 -9
  191. package/skills/omnistudio-datamapper-generate/CREDITS.md +0 -5
  192. package/skills/omnistudio-datapacks-deploy/CREDITS.md +0 -5
  193. package/skills/omnistudio-dependencies-analyze/CREDITS.md +0 -5
  194. package/skills/omnistudio-epc-catalog-generate/CREDITS.md +0 -14
  195. package/skills/omnistudio-flexcard-generate/CREDITS.md +0 -5
  196. package/skills/omnistudio-integration-procedure-generate/CREDITS.md +0 -5
  197. package/skills/omnistudio-omniscript-generate/CREDITS.md +0 -5
  198. package/skills/platform-apex-generate/CREDITS.md +0 -5
  199. package/skills/platform-apex-logs-debug/CREDITS.md +0 -22
  200. package/skills/platform-apex-test-generate/CREDITS.md +0 -5
  201. package/skills/platform-apex-test-run/CREDITS.md +0 -22
  202. package/skills/platform-data-manage/CREDITS.md +0 -5
  203. package/skills/platform-metadata-deploy/CREDITS.md +0 -25
  204. package/skills/platform-soql-query/CREDITS.md +0 -21
  205. /package/skills/omnistudio-callable-apex-generate/examples/Test_VlocityOpenInterfaceConversion/{MyCustomVlocityOpenInterface2.cls → MyCustomClass.cls} +0 -0
@@ -7,7 +7,7 @@ This document details how platform-metadata-deploy fits into the multi-skill wor
7
7
 
8
8
  ## Standard Orchestration Order
9
9
 
10
- ```
10
+ ```text
11
11
  ┌─────────────────────────────────────────────────────────────────────────────┐
12
12
  │ STANDARD MULTI-SKILL ORCHESTRATION ORDER │
13
13
  ├─────────────────────────────────────────────────────────────────────────────┤
@@ -45,7 +45,7 @@ platform-metadata-deploy is the **bridge** between local files and the org:
45
45
 
46
46
  When deploying multiple metadata types:
47
47
 
48
- ```
48
+ ```text
49
49
  ┌─────────────────────────────────────────────────────────────────────────────┐
50
50
  │ INTERNAL DEPLOY ORDER │
51
51
  ├─────────────────────────────────────────────────────────────────────────────┤
@@ -78,7 +78,7 @@ When deploying multiple metadata types:
78
78
 
79
79
  When deploying agents with external API integrations:
80
80
 
81
- ```
81
+ ```text
82
82
  ┌─────────────────────────────────────────────────────────────────────────────┐
83
83
  │ AGENTFORCE DEPLOYMENT ORDER │
84
84
  ├─────────────────────────────────────────────────────────────────────────────┤
@@ -13,7 +13,7 @@ This guide covers deployment considerations for triggers, focusing on cascade fa
13
13
 
14
14
  When an exception in one trigger causes rollback of operations from preceding triggers in the chain.
15
15
 
16
- ```
16
+ ```text
17
17
  Account Insert → AccountTrigger → ContactTrigger → OpportunityTrigger
18
18
  ✓ ✓ ✗ (Exception)
19
19
 
@@ -230,7 +230,7 @@ trigger AccountChangedSubscriber on Account_Changed__e (after insert) {
230
230
 
231
231
  Before deploying triggers, analyze the cascade impact:
232
232
 
233
- ```
233
+ ```text
234
234
  CHECKLIST:
235
235
  □ List all triggers that fire on the same transaction
236
236
  □ Identify which operations are atomic (same business process)
@@ -0,0 +1,140 @@
1
+ ---
2
+ name: platform-models-api-configure
3
+ description: "Configure (or troubleshoot) an AI coding agent or CLI to route through the Salesforce Models API using a signed OrgJWT. Use this skill when pointing an agent at the Salesforce model endpoint (api.salesforce.com/ai/gpt/v1), setting up OrgJWT / Bedrock-mode auth, wiring the agent's settings, API-key helper, and credentials file for the Salesforce endpoint, or fixing Models API 401 / 404 / \"model not available\" errors. DO NOT TRIGGER when the user needs to create or configure the Salesforce Connected App itself (use integration-connectivity-connected-app-configure) or set up Named Credentials / callout auth (use integration-connectivity-generate)."
4
+ metadata:
5
+ version: "1.0"
6
+ ---
7
+
8
+ # Salesforce Models API setup for an AI coding agent
9
+
10
+ The Salesforce Models API (`https://api.salesforce.com/ai/gpt/v1`) is
11
+ authenticated with a signed **OrgJWT** (obtained via `client_credentials` with
12
+ the `sfap_api` scope — see `scripts/get-orgjwt.sh`; no proxy). That auth and the
13
+ base URL are the same for **any** agent. How each agent then talks to the
14
+ endpoint is agent-specific: Anthropic clients (**Claude Code** and the **Claude
15
+ Agent SDK**) route through **Bedrock mode** (the env vars in Step 3), whereas
16
+ other agents (e.g. Codex) use their own client config against the same endpoint
17
+ and token — Bedrock mode does **not** apply to them.
18
+
19
+ The steps below are the **Claude Code / Claude Agent SDK reference
20
+ implementation** (Bedrock mode + a JSON settings file + an API-key helper). For
21
+ a non-Bedrock agent, reuse the OrgJWT auth (Step 1) and the base URL, and apply
22
+ the equivalent client settings in that agent's own config location instead of
23
+ the Bedrock env vars.
24
+
25
+ Bundled scripts are in `scripts/`. Path placeholders below: `<SKILL>` = the
26
+ absolute path to **this skill's own directory** (the folder containing this
27
+ `SKILL.md`; resolve it from the skill path in context). `<ABS>` = the absolute
28
+ path to the user's project root. Always emit fully resolved absolute paths —
29
+ the API-key helper runs from an undefined working directory, so relative paths
30
+ break it.
31
+
32
+ ## Prerequisite
33
+
34
+ A connected app in the org with the **`sfap_api`** OAuth scope and the
35
+ **client_credentials** flow enabled (consumer key/secret + a run-as user).
36
+ Setup steps: https://developer.salesforce.com/docs/ai/agentforce/guide/access-models-api-with-rest.html
37
+ `curl` + `jq` installed.
38
+
39
+ ## Inputs to collect
40
+
41
+ - `SF_INSTANCE_URL` — org My Domain, e.g. `https://acme.my.salesforce.com`
42
+ - `SF_CLIENT_ID`, `SF_CLIENT_SECRET` — connected-app consumer key/secret
43
+ - Models API base URL: `https://api.salesforce.com/ai/gpt/v1`
44
+ - Model: a fully qualified `sfdc_ai__…` name, e.g.
45
+ `sfdc_ai__DefaultBedrockAnthropicClaude46Sonnet`
46
+ (full list: https://developer.salesforce.com/docs/ai/agentforce/guide/supported-models.html)
47
+ - Scope: project (`<cwd>/.claude/settings.json`, default) or user (`~/.claude/settings.json`) — reference-agent settings paths
48
+ - Headers — `<FEAT>` = `x-client-feature-id` (default `ai-platform-models-connected-app`),
49
+ `<APP>` = `x-sfdc-app-context` (default `EinsteinGPT`). Used in the Step 2 verify curl
50
+ and in `ANTHROPIC_CUSTOM_HEADERS`.
51
+
52
+ ## Steps (reference implementation)
53
+
54
+ Concrete values for a JSON-settings + API-key-helper agent. Reuse the OrgJWT
55
+ auth, verify curl, and base URL verbatim for any agent; adapt the settings-file
56
+ location and env-var wiring to the target agent.
57
+
58
+ 1. Write `<project>/.claude/.orgjwt.env` (chmod 600), gitignore it:
59
+ ```ini
60
+ SF_INSTANCE_URL="..."
61
+ SF_CLIENT_ID="..."
62
+ SF_CLIENT_SECRET="..."
63
+ ```
64
+ 2. Verify — must return `200` before writing settings:
65
+ ```bash
66
+ TOKEN=$(bash <SKILL>/scripts/get-orgjwt.sh <ABS>/.claude/.orgjwt.env)
67
+ curl -s -o /dev/null -w '%{http_code}\n' \
68
+ <MODELS_API_URL>/model/<MODEL>/invoke-with-response-stream \
69
+ -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
70
+ -H 'x-client-feature-id: <FEAT>' -H 'x-sfdc-app-context: <APP>' \
71
+ --data '{"anthropic_version":"bedrock-2023-05-31","max_tokens":16,"messages":[{"role":"user","content":"hi"}]}'
72
+ ```
73
+ 3. Write `.claude/settings.json` (merge into existing; keep other keys):
74
+ ```json
75
+ {
76
+ "apiKeyHelper": "bash <SKILL>/scripts/get-orgjwt.sh <ABS>/.claude/.orgjwt.env",
77
+ "model": "<MODEL>",
78
+ "env": {
79
+ "ANTHROPIC_AUTH_TOKEN": "",
80
+ "CLAUDE_CODE_USE_BEDROCK": "1",
81
+ "CLAUDE_CODE_SKIP_BEDROCK_AUTH": "1",
82
+ "ANTHROPIC_BEDROCK_BASE_URL": "<MODELS_API_URL>",
83
+ "ANTHROPIC_SMALL_FAST_MODEL": "<MODEL>",
84
+ "ANTHROPIC_DEFAULT_MODEL": "<MODEL>",
85
+ "ANTHROPIC_CUSTOM_HEADERS": "x-client-feature-id: <FEAT>\nx-sfdc-app-context: <APP>"
86
+ }
87
+ }
88
+ ```
89
+ Use absolute paths in `apiKeyHelper`. (`<FEAT>` / `<APP>` defaults are in
90
+ "Inputs to collect" above.)
91
+ 4. Tell the admin to fully restart the agent (`claude` for the reference agent) —
92
+ settings and the API-key helper load at startup only.
93
+
94
+ ### Capturing as a runbook (when asked to document, not apply)
95
+
96
+ If the user wants the setup written up for review instead of applied to their
97
+ machine (e.g. "save it as a Markdown runbook"), write **all** of the above into
98
+ the requested file (e.g. `models-api-setup-runbook.md`), in order and self-contained:
99
+ the exact `.orgjwt.env` contents, the `chmod 600` + gitignore note, the
100
+ verification curl (with the "must be `200` before writing settings" note), the
101
+ full `settings.json` block with every key from Step 3, and the final
102
+ "fully restart `claude`" step. Don't omit any of the nine `settings.json` keys.
103
+
104
+ ## Verify before finishing
105
+
106
+ - [ ] `.claude/.orgjwt.env` created, `chmod 600`, and gitignored
107
+ - [ ] Verification curl returned HTTP `200` before `settings.json` was written
108
+ - [ ] `ANTHROPIC_AUTH_TOKEN` set to `""` in `settings.json`
109
+ - [ ] `CLAUDE_CODE_USE_BEDROCK` set to `"1"`
110
+ - [ ] `CLAUDE_CODE_SKIP_BEDROCK_AUTH` set to `"1"`
111
+ - [ ] `ANTHROPIC_BEDROCK_BASE_URL` is exactly `https://api.salesforce.com/ai/gpt/v1` (no trailing slash/path)
112
+ - [ ] `model`, `ANTHROPIC_DEFAULT_MODEL`, and `ANTHROPIC_SMALL_FAST_MODEL` all use the fully qualified `sfdc_ai__…` alias
113
+ - [ ] `ANTHROPIC_CUSTOM_HEADERS` contains `x-client-feature-id` and `x-sfdc-app-context`
114
+ - [ ] `apiKeyHelper` uses absolute paths (`bash <SKILL>/scripts/get-orgjwt.sh <ABS>/.claude/.orgjwt.env`)
115
+ - [ ] User told to fully restart `claude`
116
+
117
+ ## Must be exact (each prevents a specific failure)
118
+
119
+ - `"ANTHROPIC_AUTH_TOKEN": ""` — clears any global token that would otherwise
120
+ outrank `apiKeyHelper` (precedence: `ANTHROPIC_AUTH_TOKEN` > `ANTHROPIC_API_KEY`
121
+ > `apiKeyHelper`). Without it → wrong/old bearer → 401/404.
122
+ - `CLAUDE_CODE_USE_BEDROCK=1` — activates the Bedrock API client; without it
123
+ Claude Code uses the standard Anthropic API protocol and ignores
124
+ `ANTHROPIC_BEDROCK_BASE_URL` entirely, so every call bypasses the Models API.
125
+ - `CLAUDE_CODE_SKIP_BEDROCK_AUTH=1` — else Claude Code overwrites `Authorization`
126
+ with AWS SigV4 and the OrgJWT never lands.
127
+ - `apiKeyHelper` must be invoked as `bash <path> <credsfile>` (avoids exit-126).
128
+ - Model must be a fully qualified `sfdc_ai__…` name (see supported models).
129
+ - Auth is the OrgJWT from `client_credentials` (a signed JWT, 2 dots, scope
130
+ `sfap_api`) — NOT `sf org display` (unsigned session token → 404). `sf` CLI
131
+ has no client_credentials command; the helper calls `/services/oauth2/token`.
132
+ - Only `ANTHROPIC_BEDROCK_BASE_URL` routes; no tenant-id header needed.
133
+
134
+ ## Diagnose
135
+
136
+ | Error | Meaning | Check first |
137
+ |-------|---------|-------------|
138
+ | `401` | Token is not a valid OrgJWT | Connected App `sfap_api` scope, `client_credentials` flow enabled, consumer key/secret in `.orgjwt.env`; `ANTHROPIC_AUTH_TOKEN` not cleared to `""` |
139
+ | `404` | Token valid but model/env/org not routable | Fully qualified `sfdc_ai__…` model alias, `ANTHROPIC_BEDROCK_BASE_URL` exactly `https://api.salesforce.com/ai/gpt/v1`, org entitled for the Models API, `ANTHROPIC_AUTH_TOKEN` cleared |
140
+ | `model not available` | Non-alias model id | Replace with a fully qualified `sfdc_ai__…` alias (see supported models) |
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/env bash
2
+ # Mint a signed OrgJWT (sfap_api scope) via the OAuth 2.0 client_credentials
3
+ # flow and print it to stdout. This is the value Claude Code sends as
4
+ # `Authorization: Bearer <jwt>` to the Salesforce Models API.
5
+ #
6
+ # Credentials come from an env file passed as $1 (recommended — that's what the
7
+ # generated settings.json does), or from the environment:
8
+ # SF_INSTANCE_URL e.g. https://my-org.my.salesforce.com
9
+ # SF_CLIENT_ID connected-app consumer key (app needs the sfap_api scope
10
+ # SF_CLIENT_SECRET connected-app consumer secret + client_credentials enabled)
11
+ #
12
+ # Usage (as apiKeyHelper): bash get-orgjwt.sh /path/to/.orgjwt.env
13
+ set -euo pipefail
14
+
15
+ command -v jq >/dev/null 2>&1 || { echo "get-orgjwt: jq is required but not found on PATH" >&2; exit 1; }
16
+
17
+ CREDS="${1:-${SFGW_CREDS:-}}"
18
+ if [ -n "$CREDS" ]; then
19
+ [ -f "$CREDS" ] || { echo "get-orgjwt: creds file not found: $CREDS" >&2; exit 1; }
20
+ # Read only the three expected KEY=VALUE assignments. We deliberately do NOT
21
+ # `source` the file — sourcing would execute any shell code a malformed or
22
+ # tampered creds file happened to contain (e.g. command substitution).
23
+ while IFS='=' read -r key val; do
24
+ case "$key" in
25
+ SF_INSTANCE_URL|SF_CLIENT_ID|SF_CLIENT_SECRET)
26
+ val="${val%\"}"; val="${val#\"}" # strip surrounding double quotes
27
+ export "$key=$val" ;;
28
+ esac
29
+ done < "$CREDS"
30
+ fi
31
+ : "${SF_INSTANCE_URL:?set SF_INSTANCE_URL (in creds file or env)}"
32
+ : "${SF_CLIENT_ID:?set SF_CLIENT_ID}"
33
+ : "${SF_CLIENT_SECRET:?set SF_CLIENT_SECRET}"
34
+
35
+ RESPONSE=$(curl -s --location "${SF_INSTANCE_URL%/}/services/oauth2/token" \
36
+ --header 'Content-Type: application/x-www-form-urlencoded' \
37
+ --data-urlencode "client_id=${SF_CLIENT_ID}" \
38
+ --data-urlencode "client_secret=${SF_CLIENT_SECRET}" \
39
+ --data-urlencode 'grant_type=client_credentials')
40
+
41
+ TOKEN=$(printf '%s' "$RESPONSE" | jq -r '.access_token // empty')
42
+ if [ -z "$TOKEN" ]; then
43
+ ERR=$(printf '%s' "$RESPONSE" | jq -r '.error_description // .error // empty' 2>/dev/null)
44
+ [ -n "$ERR" ] || ERR="check connected-app creds / sfap_api scope / client_credentials flow"
45
+ echo "get-orgjwt: token request failed — $ERR" >&2
46
+ exit 1
47
+ fi
48
+ printf '%s' "$TOKEN"
@@ -0,0 +1,260 @@
1
+ ---
2
+ name: platform-policy-rule-generate
3
+ description: "Use this skill when authoring PolicyRuleDefinition and PolicyRuleDefinitionSet metadata XML for the Salesforce Enforce-O-Matic MDAPI (Data Cloud governance policies), or when editing *.policyRuleDefinition / *.policyRuleDefinitionSet files. Covers the category decision tree, full schema for all policy variants (ACCESS, GOVERNANCE, RECORD, TRANSFORM), UI-compatibility rules for the Data Governance Policy Builder, and validation guardrails. Do NOT use this skill for UserAccessPolicy, AccessPolicy, SharingRules, PermissionSet, or any non-Enforce-O-Matic access-control metadata — those have their own types and live outside the PolicyRuleDefinition schema."
4
+ metadata:
5
+ version: "1.0"
6
+ minApiVersion: "64.0"
7
+ cliTools:
8
+ - tool: ["sf"]
9
+ semver: ">=2.0.0"
10
+ ---
11
+
12
+ # Authoring Policy Rule Definitions
13
+
14
+ **Gating:** `@WsdlGuard("EnforceOMatic.orgCanUsePolicyRuleMDAPI")` = `OrgPermissions.EnforceOMatic && OrgPermissions.PolicyRuleMDAPI`
15
+ **Min API version:** 64.0 (66.0 for conditions using `PolicyJsonExpression`)
16
+
17
+ > **For human maintainers (not the agent):** the Java source-of-truth lives at `enforce-o-matic-impl/java/src/enforce/o/matic/metadata/` and reference fixtures at `enforce-o-matic-impl/test/func/filemetadata/<name>/`. The agent should rely on the templates and reference docs in this skill bundle — those impl paths are not readable from the Vibes/MCP runtime.
18
+
19
+ This skill covers the **on-disk metadata XML format** for authoring policies. Use it whenever a task asks to write a `*.policyRuleDefinition` or `*.policyRuleDefinitionSet` file, add a fixture under `test/func/filemetadata/`, or ship a metadata package. The runtime side (RuleProvider, hooks) is out of scope.
20
+
21
+ ---
22
+
23
+ > **Eval coverage:** This skill is exercised by the team's ADK eval framework, not by `tests/evals/` under the skill directory. Five datasets covering the ACCESS / GOVERNANCE / RECORD / TRANSFORM variants live in `packages/adk-eval/eval/domains/platform-policy-rule-generate/datasets/`.
24
+
25
+ ## 1. Package Layout
26
+
27
+ A deployable package always contains:
28
+
29
+ ```text
30
+ <fixture>/
31
+ package.xml
32
+ policyRuleDefinitionSets/<setName>.policyRuleDefinitionSet
33
+ policyRuleDefinitions/<ruleName>.policyRuleDefinition
34
+ ```
35
+
36
+ `package.xml` template (use `<version>[ftest]</version>` for ftests, `64.0` or higher for real orgs):
37
+
38
+ ```xml
39
+ <?xml version="1.0" encoding="UTF-8"?>
40
+ <Package xmlns="http://soap.sforce.com/2006/04/metadata">
41
+ <types>
42
+ <members>Rule0</members>
43
+ <name>PolicyRuleDefinition</name>
44
+ </types>
45
+ <types>
46
+ <members>Set1</members>
47
+ <name>PolicyRuleDefinitionSet</name>
48
+ </types>
49
+ <version>64.0</version>
50
+ </Package>
51
+ ```
52
+
53
+ ---
54
+
55
+ ## 2. PolicyRuleDefinitionSet Schema
56
+
57
+ ```xml
58
+ <PolicyRuleDefinitionSet xmlns="http://soap.sforce.com/2006/04/metadata">
59
+ <label>Set1</label>
60
+ <description>Optional free text</description>
61
+ <replicated>false</replicated> <!-- MinAppVersion 260 -->
62
+ <builderCompatible>true</builderCompatible> <!-- MinAppVersion 262, author-settable -->
63
+ <!-- builderValidated: server-managed — do not set in authored XML -->
64
+ </PolicyRuleDefinitionSet>
65
+ ```
66
+
67
+ | Element | Req | Notes |
68
+ |---------|-----|-------|
69
+ | `<label>` | yes | Master label. File basename (devName) is the MDAPI identifier, not the label. |
70
+ | `<description>` | no | Free text. |
71
+ | `<replicated>` | no | `true` triggers placeholder transformation across companion orgs. Omit for null/false. |
72
+ | `<builderCompatible>` | no | `true` = rules audited per §7 checklist. `false` = API-only. Omit = unaudited. Informational only — no deploy/runtime effect. |
73
+ | `<builderValidated>` | no | **Server-managed. Never set in authored XML.** Server overwrites on validation. |
74
+
75
+ ---
76
+
77
+ ## 3. PolicyRuleDefinition — Core Fields
78
+
79
+ | Element | Req | Notes |
80
+ |---------|-----|-------|
81
+ | `<label>` | yes | MasterLabel. |
82
+ | `<category>` | yes | See §4. Drives `resourceScopeType` and whether `policyRuleResourceDomains`/`resourceTransform` are required. **Does NOT constrain `effect` outside of TRANSFORM.** |
83
+ | `<effect>` | yes | `Permit`, `Forbid`, or `Transform`. The only category-coupling enforced by core: `effect=Transform ↔ category=TRANSFORM_POLICY_RULE_DEFINITION` (bidirectional). All other categories accept Permit and Forbid freely. |
84
+ | `<action>` | yes (≥1) | `Read`, `TupleRead`, `Create`, etc. Multiple elements OR-combine. |
85
+ | `<policyRuleDefinitionSetName>` | yes | Developer name of parent set. |
86
+ | `<principalScopeType>` | yes | Always `ANY`. |
87
+ | `<resourceScopeType>` | yes | `ANY`, `FIELD`, `RECORD`, `DATASPACE`, or `SPAN`. Must match category (§4). |
88
+ | `<principalAuthenticationLevel>` | no | `INTERNAL`, `AUTHENTICATED`, `UNIDENTIFIED`, `IDENTIFIED`. |
89
+ | `<ruleConsumer>` | no | `ALL`, `DATACLOUD`, `MULESOFT`, `TABLEAU`, `CORE`. |
90
+ | `<policyRuleResourceDomains>` | no | Required for RECORD (RLS) and FIELD-scope TRANSFORM rules only. Forbidden on ACCESS/GOVERNANCE. |
91
+ | `<resourceTransform>` | no | Required (and only valid) when `category=TRANSFORM`. |
92
+ | `<whenPolicyRuleDefinitionClauseConjunction>` | no | WHEN conditions. |
93
+ | `<unlessPolicyRuleDefinitionClauseConjunction>` | no | UNLESS conditions. Not UI-editable — prefer WHEN + negated operator. |
94
+
95
+ ---
96
+
97
+ ## 4. Category Decision Tree
98
+
99
+ **Category names a domain (where in the platform's enforcement layers the rule applies). Effect names the action (allow / deny / transform). They are independent except for TRANSFORM.**
100
+
101
+ The **only** Category × Effect rule the platform validates
102
+ (`enforce-o-matic-api/java/src/enforce/o/matic/api/module/api/RuleBuilder.java`):
103
+
104
+ - `effect=Transform` ⇔ `category=TRANSFORM_POLICY_RULE_DEFINITION` (bidirectional; mismatched throws `INVALIDFORCATEGORY`).
105
+ - All other categories (`ACCESS`, `GOVERNANCE`, `RECORD`, `IDENTIFIED_RECORD`) accept either `Permit` or `Forbid`.
106
+
107
+ > **Note on the platform's auto-fill default:** When `<category>` is omitted from authored XML, the impl-side save hook (`PolicyRuleDefinitionObject.saveHook_Validate`) fills it in from `effect`: `Permit→ACCESS`, `Forbid→GOVERNANCE`, `Transform→TRANSFORM`. **This is a default-fill, not a validation.** If you author an explicit category that contradicts this default, it is accepted and persisted as-is.
108
+
109
+ ### Picking the category
110
+
111
+ ```text
112
+ What kind of policy?
113
+
114
+ ├── OLS/FLS allow/deny on tagged or classified resources
115
+ │ category = ACCESS_POLICY_RULE_DEFINITION (allow/deny attestation in the access plane)
116
+ │ | GOVERNANCE_POLICY_RULE_DEFINITION (governance-audited)
117
+ │ effect = Permit | Forbid (chosen independently from category)
118
+ │ resourceScopeType = ANY | FIELD | DATASPACE
119
+ │ NO <policyRuleResourceDomains>
120
+ │ condition: resourcePath=TAG|CLASSIFICATION CONTAINS_ANY <ref>
121
+ │ For "objects AND all their fields" → action=TupleRead + OR-of-ENTITYTYPE clause (§7)
122
+ │ Note: "Block access to Foo object" → tag Foo with <yourTag>, write rule on tag
123
+ │ Do NOT use <resourceDomain>Foo</resourceDomain> — forbidden for ACCESS/GOVERNANCE
124
+
125
+ ├── Row-level filter on a DMO/DLO
126
+ │ category = RECORD_POLICY_RULE_DEFINITION
127
+ │ effect = Permit | Forbid
128
+ │ resourceScopeType = RECORD
129
+ │ <policyRuleResourceDomains> = the DMO/DLO API name ← entity targeting allowed here
130
+
131
+ ├── Identified-Guest record access
132
+ │ NOT authorable via MDAPI — SESSION_CONSUMER_ID is not in RuleContextPathType
133
+ │ Must be implemented as a runtime RuleProvider.
134
+
135
+ └── Field masking
136
+ category = TRANSFORM_POLICY_RULE_DEFINITION ← required by RuleBuilder validator
137
+ effect = Transform ← required by RuleBuilder validator
138
+ resourceScopeType = FIELD (structured) or SPAN (unstructured)
139
+ <policyRuleResourceDomains> = the DMO whose field is masked
140
+ <resourceTransform> required (e.g. NULL_RESOURCE_TRANSFORM, LAST_N_CHARS_RESOURCE_TRANSFORM)
141
+ ```
142
+
143
+ ### ACCESS vs GOVERNANCE — how to choose
144
+
145
+ Both legally accept Permit and Forbid. Pick by *which enforcement layer should record/audit the rule* and **what the prompt literally asks for**:
146
+
147
+ | Use case | Pick | Reason |
148
+ |---|---|---|
149
+ | The prompt names "ACCESS policy rule" / "access rule" / "OLS/FLS" explicitly | `ACCESS_POLICY_RULE_DEFINITION` | Matches the prompt's vocabulary; sits in the data-access enforcement layer. |
150
+ | The prompt names "governance" / "audit" / "policy framework" / data-residency or compliance language | `GOVERNANCE_POLICY_RULE_DEFINITION` | Matches the prompt's vocabulary; rules surface in governance reporting. |
151
+ | Prompt is ambiguous and only describes allow/deny semantics | Default to `ACCESS` for Permit, `GOVERNANCE` for Forbid (mirrors the platform's auto-fill default; safe and deployable, but **not required**) |
152
+
153
+ > **Important — honor the explicit category in the prompt.** If the prompt says "ACCESS policy rule that denies …" or "GOVERNANCE policy rule that permits …", emit exactly that category. Do not silently swap to the auto-fill default just because effect is Forbid (or Permit). The platform accepts both. The agent must not override the user's stated intent.
154
+
155
+ **Scope × category compatibility** — any combination outside this matrix throws `INVALIDFORCATEGORY`:
156
+
157
+ | | `ACCESS` | `GOVERNANCE` | `TRANSFORM` | `RECORD` |
158
+ |------------|:--------:|:------------:|:-----------:|:--------:|
159
+ | `ANY` | Yes | Yes | No | No |
160
+ | `DATASPACE`| Yes | Yes | No | No |
161
+ | `FIELD` | Yes | Yes | Yes | No |
162
+ | `RECORD` | No | No | No | Yes |
163
+ | `SPAN` | No | No | Yes | No |
164
+
165
+ ---
166
+
167
+ ## 5. Condition Patterns (Quick Reference)
168
+
169
+ Every `<conditions>` block needs **all four**: `<clause>`, `<operator>`, one path element, and the value.
170
+
171
+ | Goal | path element | operator | value |
172
+ |------|-------------|----------|-------|
173
+ | Resource has tag | `<resourcePath>TAG</resourcePath>` | `CONTAINS_ANY` | `<valueReferenceType>CUSTOM_TAG` \| `STANDARD_TAG</valueReferenceType>` |
174
+ | Resource has classification | `<resourcePath>CLASSIFICATION</resourcePath>` | `CONTAINS_ANY` | `CUSTOM_CLASSIFICATION` \| `STANDARD_CLASSIFICATION` |
175
+ | Principal has permission | `<principalPath>ASSIGNED_PERMISSIONS_PATH</principalPath>` | `CONTAINS_ANY` \| `CONTAINS_NONE` | `<valueReferenceType>CUSTOM_PERMISSION</valueReferenceType>` |
176
+ | Session in dataspace | `<contextPath>SESSION_DATASPACE</contextPath>` | `CONTAINS_ANY` | `<valueReferenceType>DATASPACE</valueReferenceType>` |
177
+ | Record field = user attribute | `<resourcePath>RECORDFIELD</resourcePath>` + `<valueDomain>Schema:field</valueDomain>` | `EQUALS` | `<valuePrincipalPath>USER_ID` \| `ORGANIZATION_ID` \| `USER_ROLE_ID</valuePrincipalPath>` |
178
+ | Entity type check | `<resourcePath>ENTITYTYPE</resourcePath>` | `IS` | `<valueString>{"t":"Text","v":"FIELD"}</valueString>` |
179
+
180
+ `<conjunctionExpression>` is 1-indexed prefix notation: `1`, `(AND 1 2)`, `(OR 1 2)`, `(AND (OR 1 2) (AND 3))`. A bare top-level index like `1` is valid for **deploy** (impl fixtures use it) but **crashes the Data Governance Policy Builder UI** — see §7 if UI editability matters.
181
+
182
+ For full path enums (`RulePrincipalPathType`, `RuleResourcePathType`, `RuleContextPathType`), operators, and JSON expressions (PROJECTION / ARGLIST / SOQLTARGETLISTEXPR), see [`references/policy-schema-full.md`](references/policy-schema-full.md).
183
+ For copy-paste templates for all policy variants, see [`references/templates.md`](references/templates.md).
184
+
185
+ ---
186
+
187
+ ## 6. Validation Guardrails
188
+
189
+ 1. Every `<conditions>` needs an `<operator>`. Missing operator → reject.
190
+ 2. Every `<conditions>` needs at least one path element (`<resourcePath>`, `<principalPath>`, `<contextPath>`, or `<valueDomain>`).
191
+ 3. `<contextPath>` is exclusively `SESSION_DATASPACE`. Never put a resource path value there.
192
+ 4. Scope × category must be in the §4 matrix. Common offenders: ACCESS/GOVERNANCE + RECORD scope; RECORD + ANY/FIELD scope; TRANSFORM + ANY/RECORD scope. (Effect is independent of category except for TRANSFORM — see §4.)
193
+ 5. `<resourceTransform>` and `effect=Transform` are coupled. Transform effect needs a resourceTransform. Permit/Forbid must not have one.
194
+ 6. `<policyRuleResourceDomains>` is **required** for RECORD (RLS) and FIELD-scope TRANSFORM; **forbidden** on ACCESS/GOVERNANCE.
195
+ 7. `<conjunctionExpression>` indices must match actual `<conditions>` count. Off-by-one → reject.
196
+ 8. `<clause>` inside `<conditions>` must match the wrapper (`WHEN` inside `<when…>`, `UNLESS` inside `<unless…>`).
197
+ 9. JSON literals in `<valueString>` must escape `"` to `&quot;`. Wrong escaping silently corrupts the literal.
198
+ 10. Reference targets (`<valueReference>`, `<resourceDomain>`) must exist in the target org at deploy time.
199
+ 11. `SCALAR_ATTRIBUTE` / `PLURAL_ATTRIBUTE` are not in `RulePrincipalPathType` — not in MDAPI contract. Use a runtime RuleProvider for those shapes.
200
+ 12. `IDENTIFIED_RECORD` is not authorable via MDAPI — `SESSION_CONSUMER_ID` not in `RuleContextPathType`.
201
+ 13. Standard tag/classification dev names are fully-qualified dotted paths (e.g. `DataGovernanceTags.ExternalData.Visibility.Public`). Retrieve an existing rule to get the exact string before authoring.
202
+ 14. Min API versions: `PolicyRuleDefinition` = 64.0; `PolicyJsonExpression` conditions = 66.0; `<replicated>` = 260+; `<builderCompatible>` / `<builderValidated>` = 262+.
203
+
204
+ > **Note on `<conjunctionExpression>` shape:** A bare top-level index (e.g. `<conjunctionExpression>1</conjunctionExpression>`) deploys cleanly — the impl-side parser accepts bare tokens at the top level, and most positive single-condition fixtures in `enforce-o-matic-impl/test/func/filemetadata/` use it. It is **not** a deploy-time validation error. It does, however, crash the Data Governance Policy Builder UI on load — see §7.
205
+
206
+ ---
207
+
208
+ ## 7. UI Compatibility — Core Rules
209
+
210
+ The Data Governance Policy Builder edits a **strict subset** of the MDAPI. Default goal: produce UI-compatible policies. Always confirm with the operator before producing API-only XML.
211
+
212
+ **Hard blockers** — any of these make the policy uneditable (and several crash the builder on load):
213
+
214
+ - **Missing OR-of-ENTITYTYPE clause on ACCESS/GOVERNANCE rules** → hard crash: `Cannot use 'in' operator to search for 'Permit' in undefined`. Required even when paired with `TupleRead` (where it's functionally redundant at runtime). Must include `IS` conditions for `{"t":"Text","v":"OBJECT"}` and `{"t":"Text","v":"FIELD"}`.
215
+ - **Bare top-level condition index** in `<conjunctionExpression>` (e.g. `1`, or `(AND (OR 1 2) 3)`) → crash on builder load in `buildCriteria`. Deploy is unaffected, but the policy is uneditable in the UI. Always wrap: `(AND 1)` for a single condition; `(AND (OR 1 2) (AND 3))` instead of `(AND (OR 1 2) 3)`.
216
+ - `category = ACCESS_POLICY_RULE_DEFINITION` + `effect = Forbid` → the **Data Governance Policy Builder UI** (not MDAPI) collapses it to GOVERNANCE on save; round-trip via the builder will rewrite the category. MDAPI deploy is unaffected — the original ACCESS+Forbid combination is valid and deploys without modification. If your goal is UI round-trippability, prefer GOVERNANCE for Forbid; if the source of truth is MDAPI, ACCESS+Forbid is fine.
217
+ - Any `<unlessPolicyRuleDefinitionClauseConjunction>` block → silently dropped on first UI save.
218
+ - More than one `<action>` → only the first is kept.
219
+ - `ruleConsumer` ≠ `DATACLOUD` → UI hardcodes DATACLOUD on save.
220
+ - Top-level `(OR 1 2)` conjunction → triggers `// ERROR: Unsupported rule!` path, rule silently dropped.
221
+
222
+ **UI-compatible "unless" rewrite:**
223
+
224
+ | Author intent | UI-compatible shape |
225
+ |---|---|
226
+ | `unless principal has permission X` | `WHEN ASSIGNED_PERMISSIONS_PATH CONTAINS_NONE X` |
227
+ | `unless resource has tag X` | `WHEN TAG CONTAINS_NONE X` |
228
+ | `unless record field = value` | `WHEN RECORDFIELD NOT_EQUALS value` |
229
+
230
+ For the full UI-compatibility checklist, round-trip rules, and operator support matrix, see [`references/ui-compatibility.md`](references/ui-compatibility.md).
231
+
232
+ ---
233
+
234
+ ## 8. Authoring Workflow
235
+
236
+ 1. **Start from the closest template** in [`references/templates.md`](references/templates.md) — modify from there, don't start blank.
237
+ 2. **Pick category first** (§4). Category fixes effect, resourceScopeType, and whether policyRuleResourceDomains/resourceTransform are required.
238
+ 3. **Lay out the bare rule**: top-level fields only, no conditions. Match the category template in [`references/templates.md`](references/templates.md).
239
+ 4. **Add conditions one at a time**, each with all four anchors: `<clause>`, `<operator>`, one path element, and the value.
240
+ 5. **Update `<conjunctionExpression>`** — 1-indexed prefix notation. Bare top-level index (e.g. `1`) deploys but breaks the UI; wrap as `(AND 1)` if UI editability matters (§7).
241
+ 6. **Run the UI-compatibility check** (§7 / [`references/ui-compatibility.md`](references/ui-compatibility.md)). If any item trips, attempt the "unless" rewrite first; if not possible, get explicit operator confirmation before continuing.
242
+ 7. **Update `package.xml`** — list each `<members>` for both types.
243
+ 8. **Set `<builderCompatible>`** on the set to `true` if §7 checklist passes; `false` if intentionally API-only.
244
+ 9. **Sanity-check against §6 (guardrails)** before considering done.
245
+ 10. **Validate with dry-run** before any non-dry deploy to a persistent org. Surface errors using the error reference in [`references/deploy-errors.md`](references/deploy-errors.md).
246
+
247
+ **Three-layer correctness check** before done:
248
+ - **Runtime / Cedar** — does the rule enforce what's intended? (action choice, condition shape)
249
+ - **MDAPI deploy validity** — does it deploy? (§6 guardrails, scope×category, tag dev names, org perms)
250
+ - **UI editability** — can the builder render and re-save it? (§7 checklist, OR-of-ENTITYTYPE requirement)
251
+
252
+ ---
253
+
254
+ ## Reference Docs
255
+
256
+ | Detail | File |
257
+ |--------|------|
258
+ | Full path enums, operators, value sets, JSON expressions (PROJECTION / ARGLIST / SOQLTARGETLISTEXPR) | [`references/policy-schema-full.md`](references/policy-schema-full.md) |
259
+ | Copy-paste templates — index at [`references/templates.md`](references/templates.md); per-variant: [`templates-access.md`](references/templates-access.md), [`templates-record.md`](references/templates-record.md), [`templates-transform.md`](references/templates-transform.md), [`templates-advanced.md`](references/templates-advanced.md) |
260
+ | Full UI-compatibility checklist, round-trip rules, operator/path support matrix | [`references/ui-compatibility.md`](references/ui-compatibility.md) |
@@ -0,0 +1,54 @@
1
+ # Deploy Error Reference
2
+
3
+ When `sf project deploy start` fails, it prints a per-component status table. Below are the most common error families for `PolicyRuleDefinition` / `PolicyRuleDefinitionSet` metadata.
4
+
5
+ For verbose output when scripting:
6
+ ```bash
7
+ sf project deploy start --target-org <alias> --source-dir … --json --verbose \
8
+ | jq '.result.details.componentFailures'
9
+ ```
10
+
11
+ ---
12
+
13
+ ## Error Table
14
+
15
+ | Error fragment | Likely cause | Fix |
16
+ |---|---|---|
17
+ | `Not available for deploy for this organization` | Org has `EnforceOMatic` perm (entities visible) but lacks `PolicyRuleMDAPI` org perm | Internal license/feature provisioning — surface to the operator. Both `EnforceOMatic` AND `PolicyRuleMDAPI` are required (see §11.1 of policy.md). |
18
+ | `Cannot find … PolicyRuleDefinition` (older orgs) | Org missing `EnforceOMatic` entirely, or API version too low | Confirm both `EnforceOMatic` and `PolicyRuleMDAPI` perms; ensure `<version>` ≥ 64.0 in package.xml |
19
+ | `INVALIDFORCATEGORY` / `Resource scope … not valid for category …` | Scope × category mismatch (e.g., ACCESS/GOVERNANCE + RECORD scope, or TRANSFORM + ANY scope) | Match scope to category per the §4 matrix in SKILL.md. For OLS/FLS on tagged objects: use `ANY`/`FIELD` scope + tag/classification condition — **not** `<resourceDomain>`. |
20
+ | `Identified record category should use record field …` | Attempted to author an `IDENTIFIED_RECORD` policy with a non-`RECORDFIELD` resource path | Do not author `IDENTIFIED_RECORD` via MDAPI — use a runtime `RuleProvider` instead. |
21
+ | `Invalid resource domain - <name>` | `<resourceDomain>` references an entity that doesn't exist in the target org | Pre-deploy the DMO/entity, or remove the rule until the target is available. Namespaced DMOs (e.g. `ssot__Account__dlm`) need the namespace prefix in the XML. |
22
+ | `An unexpected error occurred. Please include this ErrorId… (-116061062)` (opaque gack on RLS deploy) | RLS rule references a `<valueDomain>` DMO field that exists in metadata but is **not mapped** in the target org's data streams. Server-side NPE instead of a clean validation error. | Verify each `<valueDomain>` field is mapped in Setup → Data Cloud → Data Explorer. Build the rule in the UI first — the UI surfaces field-mapping issues with usable errors where MDAPI doesn't. |
23
+ | `Metadata API received improper input. … Load of metadata from db failed for metadata of type:PolicyRuleDefinition and file name:<name>` (on **retrieve**) | UI-saved RLS rules can fail to round-trip back through MDAPI retrieve in some org states | No clean fix. Use the UI as source of truth for that rule, or hand-author from a known-deployable RLS template. |
24
+ | `Use the principal … with external record category.` | `EXTERNAL_RECORD` rule used a non-`IS_AUTHENTICATED`/`IS_INTERNAL` `principalPath` | Switch principal path or change category |
25
+ | `Unsupported … contextPath` | Used a context path outside `RuleContextPathType.SESSION_DATASPACE` | Not authorable via MDAPI XML — use a runtime `RuleProvider` |
26
+
27
+ ---
28
+
29
+ ## OrgPerm Gating
30
+
31
+ Two org permissions are **both** required for MDAPI authoring:
32
+
33
+ | Permission | Gate | Effect if missing |
34
+ |---|---|---|
35
+ | `EnforceOMatic` | `@WsdlGuard` master switch | Entities not visible in UI/Tooling API at all |
36
+ | `PolicyRuleMDAPI` | `orgCanUsePolicyRuleMDAPI` WSDL layer | Deploy fails with `Not available for deploy for this organization` |
37
+
38
+ `EnforcOMaticMDAPI` is a separate **packaging** gate (`isMdAPIAllowedInternal`) — only required for packaging/change sets, not for DX CLI deploys. After PR #98647 (merged 2026-06-08) the predicate is `DBContext.get().isDoingPackageInstall()`, so DX CLI deploys work with just the two perms above.
39
+
40
+ ---
41
+
42
+ ## Dry-Run First
43
+
44
+ Always validate before deploying to a long-lived org:
45
+
46
+ ```bash
47
+ sf project deploy start \
48
+ --target-org <alias> \
49
+ --source-dir force-app/main/default \
50
+ --dry-run \
51
+ --wait 10
52
+ ```
53
+
54
+ A `--dry-run` failure runs the full server-side validation hooks (including the `IDENTIFIED_RECORD` constraint at `PolicyRuleDefinitionCondObject.java:332-339`) without persisting. This catches all of the errors in the table above before they affect a real org.
@@ -0,0 +1,29 @@
1
+ # Fixtures Index
2
+
3
+ > **For human maintainers only.** This index requires a checkout of `enforce-o-matic-impl`. The agent should rely on [`templates.md`](templates.md), which reproduces the relevant XML shapes inline.
4
+
5
+ Quick lookup from "what I need" to "fixture that already does it".
6
+
7
+ All fixtures are under `enforce-o-matic-impl/test/func/filemetadata/<name>/`.
8
+
9
+ | If you need… | Fixture |
10
+ |---|---|
11
+ | Bare permit rule, no conditions | `baseSteelthread`, `steelthreadPayload` |
12
+ | Custom conjunction `(AND 1 2)` over UNLESS | `conjunctionExpressionSteelthread` |
13
+ | Tag check | `conditionTagValidSteelthread`, `conditionCustomTagValidDataMaskingSteelthread` |
14
+ | Classification check | `conditionClassificationValidClauseSteelthread`, `conditionClassificationValidDataMaskingSteelthread` |
15
+ | Dataspace / session dataspace | `conditionDataspaceValidSteelthread`, `conditionSessionDataspaceValidSteelthread` |
16
+ | Custom permission gate | `conditionAssignedPermPathValidSteelthread` |
17
+ | Plain RLS (record field = user ID) | `conditionRLSValidSteelthread` (1st condition), `conditionStandardIdRLSValidSteelthread` |
18
+ | RLS via PROJECTION join | `conditionRLSValidSteelthread` (2nd condition) |
19
+ | Scalar / plural SOQL principal (out-of-contract) | `conditionScalarAttributeValidSteelThread`, `conditionPluralAttributeValidSteelthread` |
20
+ | Hierarchy traversal | `conditionWithHierarchy` |
21
+ | Field masking transform | `conditionClassificationValidDataMaskingSteelthread`, `conditionInvalidDataMaskingSteelthread` (negative) |
22
+ | Field-scoped resource domain | `resourceDomainWithField` |
23
+ | Core standard object policy (Case) | `coreObjectCaseWithPolicy` (persistence-layer only; not a working IDENTIFIED_RECORD shape — see §8.4 of policy.md) |
24
+ | Extended steelthread (set referenced from sibling package) | `extendedSteelthread` |
25
+ | Negative: missing operator | `conditionMissingOperatorSteelthread` |
26
+ | Negative: missing path | `conditionMissingPathSteelthread` |
27
+ | Negative: invalid context path | `conditionInvalidContextPathSteelthread` |
28
+ | Negative: invalid data masking shape | `conditionInvalidDataMaskingSteelthread` |
29
+ | Negative: invalid payload | `invalidPayload` |