@salesforce/afv-skills 1.41.0 → 1.43.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.
- package/package.json +2 -6
- package/skills/automation-sandbox-post-copy-config-generate/SKILL.md +3 -0
- package/skills/automation-sandbox-post-copy-configure/SKILL.md +4 -0
- package/skills/design-systems-slds-validate/SKILL.md +2 -2
- package/skills/dx-app-analytics-query/SKILL.md +1 -3
- package/skills/dx-devops-conflict-resolve/SKILL.md +205 -0
- package/skills/dx-devops-conflict-resolve/examples/conflict-workflows.md +165 -0
- package/skills/dx-devops-conflict-resolve/references/deploy-failure-resolution.md +75 -0
- package/skills/dx-devops-conflict-resolve/references/git-conflict-resolution.md +124 -0
- package/skills/dx-devops-conflict-resolve/scripts/detect-conflicts.sh +91 -0
- package/skills/dx-devops-conflict-resolve/scripts/diagnose-deploy-failure.sh +156 -0
- package/skills/dx-devops-request-status/SKILL.md +160 -0
- package/skills/dx-devops-request-status/examples/polling-workflows.md +101 -0
- package/skills/dx-devops-request-status/references/cli-commands.md +176 -0
- package/skills/dx-devops-request-status/scripts/poll-status.sh +134 -0
- package/skills/dx-devops-test-failures-analyze/SKILL.md +6 -6
- package/skills/dx-devops-test-pipeline-configure/SKILL.md +7 -7
- package/skills/dx-devops-test-suite-assignments-configure/SKILL.md +6 -6
- package/skills/dx-devops-test-suite-run/SKILL.md +6 -6
- package/skills/dx-devops-work-item-manage/SKILL.md +2 -0
- package/skills/dx-org-manage/references/creating-scratch-org.md +5 -2
- package/skills/dx-org-manage/references/creating-snapshot.md +1 -0
- package/skills/dx-org-shape-manage/SKILL.md +152 -0
- package/skills/dx-org-shape-manage/examples/create_error_output.json +9 -0
- package/skills/dx-org-shape-manage/examples/create_success_output.json +9 -0
- package/skills/dx-org-shape-manage/examples/delete_output.json +11 -0
- package/skills/dx-org-shape-manage/examples/list_inactive_output.json +32 -0
- package/skills/dx-org-shape-manage/examples/list_output.json +24 -0
- package/skills/dx-org-shape-manage/references/cli_flags.md +135 -0
- package/skills/dx-org-switch/SKILL.md +2 -2
- package/skills/dx-org-trial-expiration-check/SKILL.md +2 -0
- package/skills/dx-pkg-post-install-configure/SKILL.md +3 -0
- package/skills/education-cloud-multi-campus-configure/SKILL.md +211 -0
- package/skills/education-cloud-multi-campus-configure/examples/hierarchy_visualization.md +174 -0
- package/skills/education-cloud-multi-campus-configure/examples/output_examples.md +54 -0
- package/skills/education-cloud-multi-campus-configure/examples/sample_hierarchy_input.csv +29 -0
- package/skills/education-cloud-multi-campus-configure/examples/sample_hierarchy_input_edgecases.csv +16 -0
- package/skills/education-cloud-multi-campus-configure/references/account_recordtype_prerequisite.md +44 -0
- package/skills/education-cloud-multi-campus-configure/references/delta_computation.md +33 -0
- package/skills/education-cloud-multi-campus-configure/references/error_handling.md +198 -0
- package/skills/education-cloud-multi-campus-configure/references/foundation_prerequisites.md +54 -0
- package/skills/education-cloud-multi-campus-configure/references/gotchas.md +16 -0
- package/skills/education-cloud-multi-campus-configure/references/hierarchy_parsing_rules.md +133 -0
- package/skills/education-cloud-multi-campus-configure/references/mcp-invocation.md +75 -0
- package/skills/{experience-lwc-accessibility-validate → experience-accessibility-validate}/SKILL.md +1 -1
- package/skills/experience-cms-brand-apply/SKILL.md +4 -1
- package/skills/experience-cms-brand-create/SKILL.md +197 -0
- package/skills/experience-cms-brand-create/assets/brand-template.json +329 -0
- package/skills/experience-cms-brand-create/references/brand-anatomy.md +120 -0
- package/skills/experience-cms-brand-create/references/disk-contract.md +84 -0
- package/skills/experience-cms-content-generate/SKILL.md +190 -0
- package/skills/experience-cms-content-generate/assets/display-formats.md +84 -0
- package/skills/experience-cms-content-generate/assets/payloads/create-content-bulk.json +11 -0
- package/skills/experience-cms-content-generate/assets/payloads/create-content-single.json +11 -0
- package/skills/experience-cms-content-generate/assets/payloads/publish-content.json +4 -0
- package/skills/experience-cms-content-generate/assets/payloads/update-content.json +9 -0
- package/skills/experience-cms-content-generate/assets/questions.md +241 -0
- package/skills/experience-cms-content-generate/examples/create-content-call.md +81 -0
- package/skills/experience-cms-content-generate/references/bulk-batching.md +56 -0
- package/skills/experience-cms-content-generate/references/content-type-classification.md +88 -0
- package/skills/experience-cms-content-generate/references/content-write-tool.md +95 -0
- package/skills/experience-cms-content-generate/references/delegation-protocol.md +37 -0
- package/skills/experience-cms-content-generate/references/edit-publish-workflow.md +63 -0
- package/skills/experience-cms-content-generate/references/error-recovery.md +72 -0
- package/skills/experience-cms-content-generate/references/identifier-resolution.md +26 -0
- package/skills/experience-cms-content-generate/references/intent-routing.md +45 -0
- package/skills/experience-cms-content-generate/references/principles.md +19 -0
- package/skills/experience-cms-content-generate/references/ux-rules.md +68 -0
- package/skills/experience-cms-content-generate/references/workspace-resolution.md +33 -0
- package/skills/experience-cms-content-type-generate/SKILL.md +449 -0
- package/skills/experience-cms-content-type-generate/assets/discovery-prompts.md +79 -0
- package/skills/experience-cms-content-type-generate/assets/schema-example.json +70 -0
- package/skills/experience-cms-content-type-generate/references/agent-checklist.md +50 -0
- package/skills/experience-cms-content-type-generate/references/anti-patterns.md +39 -0
- package/skills/experience-cms-content-type-generate/references/deployment-errors.md +27 -0
- package/skills/experience-cms-content-type-generate/references/discovery-details.md +106 -0
- package/skills/experience-cms-content-type-generate/references/discovery-query-rules.md +85 -0
- package/skills/experience-cms-content-type-generate/references/edit-fields-loop.md +48 -0
- package/skills/experience-cms-content-type-generate/references/pre-deploy-checklist.md +21 -0
- package/skills/experience-cms-content-type-generate/references/retrieve-and-reconcile.md +105 -0
- package/skills/experience-cms-content-type-generate/references/schema-rules.md +51 -0
- package/skills/experience-cms-content-type-generate/references/schema-summary-format.md +60 -0
- package/skills/experience-lds-graphql-generate/SKILL.md +4 -0
- package/skills/experience-lwc-accessibility-jest-run/SKILL.md +79 -0
- package/skills/experience-lwc-accessibility-jest-run/references/running-sa11y-jest-tests.md +205 -0
- package/skills/experience-lwc-design-generate/SKILL.md +5 -4
- package/skills/experience-lwc-generate/SKILL.md +10 -9
- package/skills/experience-ui-bundle-deploy/references/dev-preview.md +21 -0
- package/skills/experience-ui-bundle-deploy/references/social-login.md +1 -0
- package/skills/experience-ui-bundle-file-upload-generate/SKILL.md +6 -6
- package/skills/experience-ui-bundle-localize/SKILL.md +30 -37
- package/skills/experience-ui-bundle-localize/references/gotchas.md +23 -7
- package/skills/experience-ui-bundle-localize/references/i18n-setup.md +48 -4
- package/skills/experience-ui-bundle-localize/references/label-xml.md +22 -8
- package/skills/experience-ui-bundle-localize/references/verifying.md +39 -11
- package/skills/experience-ui-bundle-localize/scripts/detect-bundle-type.sh +118 -15
- package/skills/experience-ui-bundle-localize/scripts/tests/test-detect-bundle-type.sh +187 -0
- package/skills/experience-ui-bundle-mfa-configure/SKILL.md +13 -2
- package/skills/experience-ui-bundle-mfa-configure/references/social-login.md +1 -0
- package/skills/experience-ui-bundle-project-generate/SKILL.md +2 -2
- package/skills/integration-connectivity-generate/SKILL.md +11 -10
- package/skills/integration-eventing-cdc-configure/SKILL.md +6 -6
- package/skills/integration-eventing-subscription-configure/SKILL.md +6 -5
- package/skills/mobile-platform-native-capabilities-integrate/SKILL.md +2 -2
- package/skills/mobile-platform-offline-validate/scripts/package.json +1 -1
- package/skills/platform-agentexchange-partner-offers-configure/SKILL.md +8 -8
- package/skills/platform-custom-application-generate/SKILL.md +2 -0
- package/skills/platform-custom-field-generate/SKILL.md +8 -6
- package/skills/platform-custom-metadata-type-generate/SKILL.md +460 -0
- package/skills/platform-custom-metadata-type-generate/references/cmdt-records.md +251 -0
- package/skills/platform-custom-metadata-type-generate/scripts/sanitize-developer-name.sh +46 -0
- package/skills/platform-custom-setting-generate/SKILL.md +419 -0
- package/skills/platform-dataspace-access-configure/SKILL.md +3 -3
- package/skills/platform-sharing-owd-configure/SKILL.md +3 -0
- package/skills/platform-value-set-generate/SKILL.md +2 -0
- package/skills/service-agentforce-channel-configure/SKILL.md +29 -20
- package/skills/service-agentforce-channel-configure/assets/BotEmailDefinition.botEmailDefinition-meta.xml +36 -0
- package/skills/service-agentforce-channel-configure/assets/email/unfiled$public/AgentforceForServiceEmailTemplate.email +17 -0
- package/skills/service-agentforce-channel-configure/assets/email/unfiled$public/AgentforceForServiceEmailTemplate.email-meta.xml +29 -0
- package/skills/service-agentforce-channel-configure/assets/mdapi-package.xml +25 -0
- package/skills/service-agentforce-channel-configure/assets/settings-mdapi-package.xml +30 -0
- package/skills/service-agentforce-channel-configure/references/agent-wiring.md +20 -0
- package/skills/service-agentforce-channel-configure/references/botemaildefinition.md +107 -0
- package/skills/service-agentforce-channel-configure/references/channel-branch-email.md +203 -50
- package/skills/service-agentforce-channel-configure/references/channel-types.md +30 -3
- package/skills/service-agentforce-channel-configure/references/queue-resolution.md +17 -8
- package/skills/service-agentforce-channel-configure/references/routing-flow.md +14 -3
- package/skills/service-agentforce-channel-configure/scripts/validate-botemaildefinition.py +126 -0
- package/skills/service-agentforce-channel-configure/scripts/validate-emailtemplate.py +133 -0
- package/skills/service-de-channel-activate/SKILL.md +271 -0
- package/skills/service-de-channel-activate/references/gotchas.md +31 -0
- package/skills/service-de-channel-activate/references/phone-verification.md +96 -0
- package/skills/service-de-channel-activate/references/worked-examples.md +14 -0
- package/skills/service-de-channel-consent-configure/SKILL.md +230 -0
- package/skills/service-de-channel-consent-configure/references/gotchas.md +41 -0
- package/skills/service-de-channel-consent-configure/references/language-keywords.md +84 -0
- package/skills/service-de-channel-consent-configure/references/worked-examples.md +134 -0
- package/skills/service-de-channel-create/SKILL.md +369 -0
- package/skills/service-de-channel-create/references/apple.md +59 -0
- package/skills/service-de-channel-create/references/connect-insert.md +84 -0
- package/skills/service-de-channel-create/references/facebook.md +154 -0
- package/skills/service-de-channel-create/references/line.md +66 -0
- package/skills/service-de-channel-create/references/sms.md +98 -0
- package/skills/service-de-channel-create/references/whatsapp.md +98 -0
- package/skills/service-de-channel-create/references/worked-examples.md +70 -0
- package/skills/service-de-channel-routing-configure/SKILL.md +345 -0
- package/skills/service-de-channel-routing-configure/references/asa-routing.md +90 -0
- package/skills/service-de-channel-routing-configure/references/gotchas.md +27 -0
- package/skills/service-de-channel-routing-configure/references/queue-creation.md +123 -0
- package/skills/service-de-channel-routing-configure/references/target-locate.md +98 -0
- package/skills/service-de-channel-routing-configure/references/worked-examples.md +174 -0
- package/skills/service-de-headless-channel-configure/SKILL.md +305 -0
- package/skills/service-de-headless-channel-configure/references/gotchas.md +27 -0
- package/skills/service-de-headless-channel-configure/references/inputs.md +49 -0
- package/skills/service-de-headless-channel-configure/references/output-envelopes.md +53 -0
- package/skills/service-de-headless-channel-configure/references/partial-success.md +24 -0
- package/skills/service-de-headless-channel-configure/references/terms-and-conditions.md +54 -0
- package/skills/service-de-headless-channel-configure/references/worked-examples.md +108 -0
- package/skills/service-de-waba-integrate/SKILL.md +227 -0
- package/skills/service-digital-engagement-channel-configure/scripts/check-api-version.sh +29 -0
- package/skills/service-digital-engagement-messaging-site-integrate/SKILL.md +10 -9
- package/skills/service-digital-engagement-messaging-site-integrate/references/lwr_patch.md +39 -21
- package/skills/service-digital-engagement-messaging-site-integrate/scripts/patch_lwr_bundle.sh +157 -96
- package/skills/service-email-to-case-configure/SKILL.md +190 -0
- package/skills/service-email-to-case-configure/assets/CaseSettings.settings-meta.xml +45 -0
- package/skills/service-email-to-case-configure/examples/CaseSettings-two-addresses.settings-meta.xml +36 -0
- package/skills/service-email-to-case-configure/references/apply-mechanics.md +73 -0
- package/skills/service-email-to-case-configure/references/routing_address_reference.md +73 -0
- package/skills/service-email-to-case-configure/references/troubleshooting.md +25 -0
- package/skills/service-email-to-case-configure/scripts/apply-casesettings.py +1315 -0
- package/skills/service-email-to-case-configure/scripts/check-agent-email-capability.sh +26 -0
- package/skills/service-email-to-case-configure/scripts/tests/__init__.py +0 -0
- package/skills/service-email-to-case-configure/scripts/tests/_bootstrap.py +45 -0
- package/skills/service-email-to-case-configure/scripts/tests/_fakeorg.py +366 -0
- package/skills/service-email-to-case-configure/scripts/tests/_run.py +84 -0
- package/skills/service-email-to-case-configure/scripts/tests/test_apply_org_scenarios.py +655 -0
- package/skills/service-email-to-case-configure/scripts/tests/test_get_session.py +134 -0
- package/skills/service-email-to-case-configure/scripts/tests/test_new_capabilities.py +193 -0
- package/skills/service-email-to-case-configure/scripts/tests/test_validate_casesettings.py +170 -0
- package/skills/service-email-to-case-configure/scripts/validate-casesettings.py +229 -0
- package/skills/service-itsm-agentic-setup-agentforce-coordinate/SKILL.md +33 -15
- package/skills/service-itsm-agentic-setup-agentforce-coordinate/examples/output-templates.md +63 -47
- package/skills/service-itsm-agentic-setup-agentforce-studio-configure/SKILL.md +17 -12
- package/skills/service-itsm-agentic-setup-agentforce-studio-configure/references/cli-invocation.md +5 -3
- package/skills/service-itsm-agentic-setup-agentforce-studio-configure/scripts/classify-enable-plan.mjs +11 -3
- package/skills/service-itsm-agentic-setup-agentforce-studio-validate/SKILL.md +8 -6
- package/skills/service-itsm-agentic-setup-agentforce-studio-validate/references/cli-invocation.md +3 -3
- package/skills/service-itsm-agentic-setup-agentforce-studio-validate/scripts/classify-readiness.mjs +11 -3
- package/skills/service-itsm-agentic-setup-configure/SKILL.md +5 -5
- package/skills/service-itsm-agentic-setup-configure/examples/output-templates.md +5 -5
- package/skills/service-itsm-agentic-setup-employee-agent-configure/SKILL.md +2 -2
- package/skills/service-itsm-agentic-setup-employee-agent-configure/references/report-format.md +11 -7
- package/skills/service-itsm-agentic-setup-employee-agent-configure/scripts/render-report.mjs +20 -7
- package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/SKILL.md +10 -6
- package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/references/action-availability.md +7 -7
- package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/references/report-format.md +11 -7
- package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/scripts/build-create-body.mjs +24 -17
- package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/scripts/classify-action-availability.mjs +98 -58
- package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/scripts/render-report.mjs +20 -7
- package/skills/service-itsm-agentic-setup-fulfiller-agent-configure/scripts/strip-release-management.mjs +176 -0
- package/skills/service-itsm-agentic-setup-itsm-agentforce-permset-assign/SKILL.md +19 -19
- package/skills/service-itsm-agentic-setup-itsm-agentforce-permset-assign/references/cli-invocation.md +3 -4
- package/skills/service-itsm-agentic-setup-itsm-agentforce-permset-assign/references/helper-contracts.md +6 -6
- package/skills/service-itsm-agentic-setup-itsm-agentforce-permset-assign/references/permset-topology.md +3 -10
- package/skills/service-itsm-agentic-setup-itsm-agentforce-permset-assign/scripts/classify-permset-availability.mjs +7 -9
- package/skills/service-itsm-incident-mgmt-configure/SKILL.md +2 -0
- package/skills/service-itsm-incident-priority-configure/SKILL.md +15 -12
- package/skills/service-itsm-incident-priority-configure/examples/matrix-operations.md +27 -1
- package/skills/service-itsm-incident-priority-configure/references/sf-cli-invocation.md +37 -6
- package/skills/service-native-voice-recording-transcription-configure/SKILL.md +146 -0
- package/skills/service-native-voice-recording-transcription-configure/assets/confirmation-output.json +16 -0
- package/skills/service-native-voice-recording-transcription-configure/assets/package.xml +22 -0
- package/skills/service-native-voice-recording-transcription-configure/references/thunderbird-voice-settings.md +101 -0
- package/skills/service-native-voice-recording-transcription-configure/scripts/enable-recording-transcription.sh +181 -0
- package/skills/data360-activate/README.md +0 -38
- package/skills/data360-activate/SKILL.md +0 -127
- package/skills/data360-connect/README.md +0 -57
- package/skills/data360-connect/SKILL.md +0 -163
- package/skills/data360-connect/examples/connections/heroku-postgres.json +0 -15
- package/skills/data360-connect/examples/connections/ingest-api-connection.json +0 -5
- package/skills/data360-connect/examples/connections/ingest-api-schema.json +0 -31
- package/skills/data360-connect/examples/connections/redshift.json +0 -16
- package/skills/data360-connect/examples/connections/sharepoint-unstructured.json +0 -20
- package/skills/data360-connect/examples/connections/snowflake-connection.json +0 -42
- package/skills/data360-harmonize/README.md +0 -31
- package/skills/data360-harmonize/SKILL.md +0 -126
- package/skills/data360-orchestrate/README.md +0 -120
- package/skills/data360-orchestrate/SKILL.md +0 -263
- package/skills/data360-orchestrate/assets/definitions/activation-target.template.json +0 -5
- package/skills/data360-orchestrate/assets/definitions/activation.template.json +0 -7
- package/skills/data360-orchestrate/assets/definitions/calculated-insight.template.json +0 -7
- package/skills/data360-orchestrate/assets/definitions/data-action-target.template.json +0 -5
- package/skills/data360-orchestrate/assets/definitions/data-action.template.json +0 -5
- package/skills/data360-orchestrate/assets/definitions/data-graph.template.json +0 -21
- package/skills/data360-orchestrate/assets/definitions/data-stream.template.json +0 -55
- package/skills/data360-orchestrate/assets/definitions/dmo.template.json +0 -17
- package/skills/data360-orchestrate/assets/definitions/identity-resolution.template.json +0 -30
- package/skills/data360-orchestrate/assets/definitions/mapping.template.json +0 -14
- package/skills/data360-orchestrate/assets/definitions/relationship.template.json +0 -12
- package/skills/data360-orchestrate/assets/definitions/search-index.template.json +0 -9
- package/skills/data360-orchestrate/assets/definitions/segment.template.json +0 -16
- package/skills/data360-orchestrate/references/feature-readiness.md +0 -157
- package/skills/data360-orchestrate/references/plugin-setup.md +0 -138
- package/skills/data360-orchestrate/scripts/bootstrap-plugin.sh +0 -53
- package/skills/data360-orchestrate/scripts/diagnose-org.mjs +0 -511
- package/skills/data360-orchestrate/scripts/generate-manifest.mjs +0 -68
- package/skills/data360-orchestrate/scripts/verify-plugin.sh +0 -58
- package/skills/data360-prepare/README.md +0 -50
- package/skills/data360-prepare/SKILL.md +0 -203
- package/skills/data360-prepare/examples/ingestion-api/.env.example +0 -8
- package/skills/data360-prepare/examples/ingestion-api/README.md +0 -48
- package/skills/data360-prepare/examples/ingestion-api/send-data.py +0 -144
- package/skills/data360-query/README.md +0 -43
- package/skills/data360-query/SKILL.md +0 -128
- package/skills/data360-query/examples/search-indexes/hybrid-structured.json +0 -44
- package/skills/data360-query/examples/search-indexes/vector-knowledge.json +0 -43
- package/skills/data360-segment/README.md +0 -35
- package/skills/data360-segment/SKILL.md +0 -123
- package/skills/service-helpagent-coordinate/references/channel-help-portal.md +0 -22
- /package/skills/{experience-lwc-accessibility-validate → experience-accessibility-validate}/references/reviewers/sc-1-1-1-non-text-content.md +0 -0
- /package/skills/{experience-lwc-accessibility-validate → experience-accessibility-validate}/references/reviewers/sc-1-3-1-i-lists.md +0 -0
- /package/skills/{experience-lwc-accessibility-validate → experience-accessibility-validate}/references/reviewers/sc-1-3-1-ii-tables.md +0 -0
- /package/skills/{experience-lwc-accessibility-validate → experience-accessibility-validate}/references/reviewers/sc-1-3-1-iii-form-labels.md +0 -0
- /package/skills/{experience-lwc-accessibility-validate → experience-accessibility-validate}/references/reviewers/sc-1-3-1-iv-regions.md +0 -0
- /package/skills/{experience-lwc-accessibility-validate → experience-accessibility-validate}/references/reviewers/sc-1-3-1-v-groups.md +0 -0
- /package/skills/{experience-lwc-accessibility-validate → experience-accessibility-validate}/references/reviewers/sc-1-3-5-identify-input.md +0 -0
- /package/skills/{experience-lwc-accessibility-validate → experience-accessibility-validate}/references/reviewers/sc-1-4-3-contrast.md +0 -0
- /package/skills/{experience-lwc-accessibility-validate → experience-accessibility-validate}/references/reviewers/sc-2-1-1-keyboard.md +0 -0
- /package/skills/{experience-lwc-accessibility-validate → experience-accessibility-validate}/references/reviewers/sc-2-4-4-link-purpose.md +0 -0
- /package/skills/{experience-lwc-accessibility-validate → experience-accessibility-validate}/references/reviewers/sc-2-4-6-headings-labels.md +0 -0
- /package/skills/{experience-lwc-accessibility-validate → experience-accessibility-validate}/references/reviewers/sc-2-5-1-pointer-gestures.md +0 -0
- /package/skills/{experience-lwc-accessibility-validate → experience-accessibility-validate}/references/reviewers/sc-2-5-2-pointer-cancellation.md +0 -0
- /package/skills/{experience-lwc-accessibility-validate → experience-accessibility-validate}/references/reviewers/sc-2-5-3-label-in-name.md +0 -0
- /package/skills/{experience-lwc-accessibility-validate → experience-accessibility-validate}/references/reviewers/sc-2-5-7-dragging-movement.md +0 -0
- /package/skills/{experience-lwc-accessibility-validate → experience-accessibility-validate}/references/reviewers/sc-3-2-1-on-focus.md +0 -0
- /package/skills/{experience-lwc-accessibility-validate → experience-accessibility-validate}/references/reviewers/sc-3-2-2-on-input.md +0 -0
- /package/skills/{experience-lwc-accessibility-validate → experience-accessibility-validate}/references/reviewers/sc-3-3-1-error-identification.md +0 -0
- /package/skills/{experience-lwc-accessibility-validate → experience-accessibility-validate}/references/reviewers/sc-3-3-2-labels-instructions.md +0 -0
- /package/skills/{experience-lwc-accessibility-validate → experience-accessibility-validate}/references/reviewers/sc-3-3-3-error-suggestion.md +0 -0
- /package/skills/{experience-lwc-accessibility-validate → experience-accessibility-validate}/references/reviewers/sc-4-1-2-i-name.md +0 -0
- /package/skills/{experience-lwc-accessibility-validate → experience-accessibility-validate}/references/reviewers/sc-4-1-2-ii-role.md +0 -0
- /package/skills/{experience-lwc-accessibility-validate → experience-accessibility-validate}/references/reviewers/sc-4-1-2-iii-value.md +0 -0
- /package/skills/{experience-lwc-accessibility-validate → experience-accessibility-validate}/references/vision/sc-1-1-1-non-text-content.md +0 -0
- /package/skills/{experience-lwc-accessibility-validate → experience-accessibility-validate}/references/vision/sc-1-4-1-use-of-color.md +0 -0
- /package/skills/{experience-lwc-accessibility-validate → experience-accessibility-validate}/references/vision/sc-1-4-10-resize-reflow.md +0 -0
- /package/skills/{experience-lwc-accessibility-validate → experience-accessibility-validate}/references/vision/sc-1-4-11-non-text-contrast.md +0 -0
- /package/skills/{experience-lwc-accessibility-validate → experience-accessibility-validate}/references/vision/sc-1-4-3-contrast.md +0 -0
- /package/skills/{experience-lwc-accessibility-validate → experience-accessibility-validate}/scripts/contrast-ratio.py +0 -0
|
@@ -1,55 +1,73 @@
|
|
|
1
|
-
# LWR — Patching
|
|
1
|
+
# LWR — Patching themeLayout footer (site-wide widget placement)
|
|
2
2
|
|
|
3
|
-
Target
|
|
3
|
+
Target files:
|
|
4
4
|
|
|
5
5
|
```text
|
|
6
|
-
digitalExperiences/site/<siteName>/
|
|
6
|
+
digitalExperiences/site/<siteName>/sfdc_cms__themeLayout/*/content.json
|
|
7
7
|
```
|
|
8
8
|
|
|
9
9
|
The patch is applied by `scripts/patch_lwr_bundle.sh`. Invoke as:
|
|
10
10
|
|
|
11
11
|
```bash
|
|
12
|
-
scripts/patch_lwr_bundle.sh <
|
|
12
|
+
scripts/patch_lwr_bundle.sh <site-dir> <deploymentName> <scrtUrl> <siteEndpoint>
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
where `<site-dir>` is the root of the retrieved bundle, e.g.:
|
|
16
|
+
`<retrieve-dir>/digitalExperiences/site/<siteName>`
|
|
17
|
+
|
|
18
|
+
Targeting the `sfdc_cms__themeLayout` footer (not `sfdc_cms__view/home/content.json`) places the widget as a site-wide floating overlay on every page — equivalent to the Aura `themeFooter` region placement.
|
|
16
19
|
|
|
17
20
|
## What the script does
|
|
18
21
|
|
|
19
|
-
1.
|
|
20
|
-
2.
|
|
21
|
-
3.
|
|
22
|
-
4.
|
|
22
|
+
1. Finds every `sfdc_cms__themeLayout/*/content.json` file under `<site-dir>`.
|
|
23
|
+
2. For each file, locates the `footer` region at `.contentBody.component.children[]` (where `.name == "footer"`).
|
|
24
|
+
3. Within that region, finds the existing `community_layout:section` wrapper (`.type == "component"`), then the inner slot region (`.type == "region"`) inside it — the inner region is where the widget goes (e.g. `footerSection`, `content`, etc.).
|
|
25
|
+
4. Recursively checks whether any descendant node already has `.definition == "experience_messaging:embeddedMessaging"`.
|
|
26
|
+
5. **If found** — updates that node's `.attributes` to the six standard values and **preserves the existing `.id`**:
|
|
23
27
|
- `deploymentName`, `scrtUrl`, `siteEndpoint` (from CLI args)
|
|
24
|
-
- `isExpSiteAuthMode: false`, `hideChatButtonOnLoad: "Default"`, `clientVersion: "
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
- `isExpSiteAuthMode: false`, `hideChatButtonOnLoad: "Default"`, `clientVersion: "WebV2"`
|
|
29
|
+
6. **If absent** — appends a fresh messaging component node directly into the inner region's `children[]`. The node has `"type": "component"` and `"definition": "experience_messaging:embeddedMessaging"`. No new `community_layout:section` wrapper is created — the section wrapper already exists in the footer region.
|
|
30
|
+
7. Handles the edge case where no wrapper section or inner region exists: falls back to appending directly to the footer's `children[]`.
|
|
31
|
+
8. Writes each file back with jq's 2-space indentation.
|
|
27
32
|
|
|
28
33
|
Re-running with the same arguments is a no-op (idempotent); re-running with new deployment coordinates refreshes the attributes in place without changing the component's `id`.
|
|
29
34
|
|
|
30
35
|
## How to verify
|
|
31
36
|
|
|
32
|
-
- Exactly one messaging node exists:
|
|
37
|
+
- Exactly one messaging node exists per themeLayout file:
|
|
33
38
|
|
|
34
39
|
```bash
|
|
35
|
-
jq '[.. | select(.definition? == "experience_messaging:embeddedMessaging")] | length'
|
|
40
|
+
jq '[.. | select(.definition? == "experience_messaging:embeddedMessaging")] | length' \
|
|
41
|
+
<site-dir>/sfdc_cms__themeLayout/<layoutName>/content.json
|
|
36
42
|
# → 1
|
|
37
43
|
```
|
|
38
44
|
|
|
39
|
-
-
|
|
45
|
+
- The node lives inside the footer region's subtree:
|
|
40
46
|
|
|
41
47
|
```bash
|
|
42
|
-
jq '
|
|
43
|
-
|
|
48
|
+
jq '
|
|
49
|
+
.contentBody.component.children[]
|
|
50
|
+
| select(.name? == "footer")
|
|
51
|
+
| [.. | select(.definition? == "experience_messaging:embeddedMessaging")]
|
|
52
|
+
| length
|
|
53
|
+
' <site-dir>/sfdc_cms__themeLayout/<layoutName>/content.json
|
|
54
|
+
# → 1
|
|
44
55
|
```
|
|
45
56
|
|
|
46
|
-
-
|
|
57
|
+
- `clientVersion` is `"WebV2"` (not `"WebV1"`):
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
jq '.. | select(.definition? == "experience_messaging:embeddedMessaging") | .attributes.clientVersion' \
|
|
61
|
+
<site-dir>/sfdc_cms__themeLayout/<layoutName>/content.json
|
|
62
|
+
# → "WebV2"
|
|
63
|
+
```
|
|
47
64
|
|
|
48
65
|
## Common failures
|
|
49
66
|
|
|
50
67
|
| Symptom | Cause |
|
|
51
68
|
|---------|-------|
|
|
52
|
-
|
|
|
53
|
-
|
|
|
69
|
+
| Widget only appears on the home page | Script was run against `sfdc_cms__view/home/content.json` instead of the themeLayout files |
|
|
70
|
+
| Widget appears on no pages after deploy | The footer region name differed from `"footer"` — inspect `.contentBody.component.children[].name` in the themeLayout |
|
|
71
|
+
| Two chat buttons after re-run | Detection did not descend into the full tree; the recursive `has_messaging` check avoids this |
|
|
54
72
|
| Deploy error "component not registered" | Used `componentName` (Aura shape) instead of `definition` (LWR shape) |
|
|
55
|
-
|
|
|
73
|
+
| `clientVersion: "WebV1"` — widget appears but Enhanced Web Chat fails | Script emitted `WebV1`; re-run the script (it defaults to `WebV2`) |
|
package/skills/service-digital-engagement-messaging-site-integrate/scripts/patch_lwr_bundle.sh
CHANGED
|
@@ -1,33 +1,32 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# patch_lwr_bundle.sh
|
|
3
3
|
# Idempotently inserts (or updates in place) the experience_messaging:embeddedMessaging
|
|
4
|
-
# component
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
# already exists inside .contentBody.component.children[] (recursively), its
|
|
8
|
-
# .attributes are refreshed and the existing .id is preserved. Otherwise a new
|
|
9
|
-
# community_layout:section wrapper is appended to the region whose
|
|
10
|
-
# .type == "region" AND .name == "content".
|
|
4
|
+
# component into the footer region of every sfdc_cms__themeLayout content.json in an
|
|
5
|
+
# LWR DigitalExperienceBundle. Targeting the themeLayout footer places the widget
|
|
6
|
+
# site-wide (as a floating overlay on every page), equivalent to the Aura themeFooter.
|
|
11
7
|
#
|
|
12
8
|
# Usage:
|
|
13
|
-
# patch_lwr_bundle.sh <
|
|
9
|
+
# patch_lwr_bundle.sh <site-dir> <deploymentName> <scrtUrl> <siteEndpoint>
|
|
10
|
+
#
|
|
11
|
+
# <site-dir> is the path to the site root, e.g.:
|
|
12
|
+
# force-app/main/default/digitalExperiences/site/<siteName>
|
|
14
13
|
#
|
|
15
14
|
# Requires: jq, uuidgen (or /proc/sys/kernel/random/uuid, or python3).
|
|
16
15
|
|
|
17
16
|
set -euo pipefail
|
|
18
17
|
|
|
19
18
|
if [ "$#" -ne 4 ]; then
|
|
20
|
-
echo "Usage: $0 <
|
|
19
|
+
echo "Usage: $0 <site-dir> <deploymentName> <scrtUrl> <siteEndpoint>" >&2
|
|
21
20
|
exit 1
|
|
22
21
|
fi
|
|
23
22
|
|
|
24
|
-
|
|
23
|
+
SITE_DIR="$1"
|
|
25
24
|
DEPLOYMENT_NAME="$2"
|
|
26
25
|
SCRT_URL="$3"
|
|
27
26
|
SITE_ENDPOINT="$4"
|
|
28
27
|
|
|
29
|
-
if [ ! -
|
|
30
|
-
echo "Error:
|
|
28
|
+
if [ ! -d "$SITE_DIR" ]; then
|
|
29
|
+
echo "Error: site directory not found: $SITE_DIR" >&2
|
|
31
30
|
exit 1
|
|
32
31
|
fi
|
|
33
32
|
|
|
@@ -46,87 +45,149 @@ gen_uuid() {
|
|
|
46
45
|
fi
|
|
47
46
|
}
|
|
48
47
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
48
|
+
# Find all themeLayout content.json files (skip mobile/tablet rendition subdirs)
|
|
49
|
+
THEME_LAYOUTS=$(find "$SITE_DIR/sfdc_cms__themeLayout" -maxdepth 2 -name "content.json" 2>/dev/null || true)
|
|
50
|
+
|
|
51
|
+
if [ -z "$THEME_LAYOUTS" ]; then
|
|
52
|
+
echo "Error: no sfdc_cms__themeLayout/*/content.json files found under $SITE_DIR" >&2
|
|
53
|
+
exit 1
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
PATCHED=0
|
|
57
|
+
SKIPPED=0
|
|
58
|
+
|
|
59
|
+
while IFS= read -r CONTENT_JSON; do
|
|
60
|
+
# Skip mobile/tablet rendition files (they live in a subdirectory of the layout dir)
|
|
61
|
+
LAYOUT_DIR=$(dirname "$CONTENT_JSON")
|
|
62
|
+
PARENT_DIR=$(dirname "$LAYOUT_DIR")
|
|
63
|
+
GRANDPARENT=$(basename "$PARENT_DIR")
|
|
64
|
+
if [ "$GRANDPARENT" != "sfdc_cms__themeLayout" ]; then
|
|
65
|
+
continue
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
UUID_MESSAGING="$(gen_uuid)"
|
|
69
|
+
TMP_OUT="$(mktemp)"
|
|
70
|
+
trap 'rm -f "$TMP_OUT"' EXIT
|
|
71
|
+
|
|
72
|
+
jq \
|
|
73
|
+
--arg deploymentName "$DEPLOYMENT_NAME" \
|
|
74
|
+
--arg scrtUrl "$SCRT_URL" \
|
|
75
|
+
--arg siteEndpoint "$SITE_ENDPOINT" \
|
|
76
|
+
--arg uuidMessaging "$UUID_MESSAGING" \
|
|
77
|
+
'
|
|
78
|
+
def attrs:
|
|
79
|
+
{
|
|
80
|
+
deploymentName: $deploymentName,
|
|
81
|
+
scrtUrl: $scrtUrl,
|
|
82
|
+
siteEndpoint: $siteEndpoint,
|
|
83
|
+
isExpSiteAuthMode: false,
|
|
84
|
+
hideChatButtonOnLoad: "Default",
|
|
85
|
+
clientVersion: "WebV2"
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
# Recursively check whether a messaging component already exists
|
|
89
|
+
def has_messaging:
|
|
90
|
+
. as $n |
|
|
91
|
+
if type == "array" then
|
|
92
|
+
any(.[]; has_messaging)
|
|
93
|
+
elif type == "object" then
|
|
94
|
+
((.definition? == "experience_messaging:embeddedMessaging") or
|
|
95
|
+
((.children // []) | has_messaging))
|
|
96
|
+
else false end;
|
|
97
|
+
|
|
98
|
+
# Recursively update attributes of existing messaging component in place
|
|
99
|
+
def update_messaging:
|
|
100
|
+
if type == "array" then map(update_messaging)
|
|
101
|
+
elif type == "object" then
|
|
102
|
+
if .definition? == "experience_messaging:embeddedMessaging" then
|
|
103
|
+
.attributes = attrs
|
|
104
|
+
elif (.children | type) == "array" then
|
|
105
|
+
.children |= update_messaging
|
|
106
|
+
else . end
|
|
107
|
+
else . end;
|
|
108
|
+
|
|
109
|
+
# New standalone messaging component node (no section wrapper — it is a
|
|
110
|
+
# floating overlay and does not need a layout container in the footer)
|
|
111
|
+
def new_messaging:
|
|
112
|
+
{
|
|
113
|
+
id: $uuidMessaging,
|
|
114
|
+
type: "component",
|
|
115
|
+
definition: "experience_messaging:embeddedMessaging",
|
|
116
|
+
attributes: attrs
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
# Inject into the footer region layout section. Two decisions, both made
|
|
120
|
+
# over the ENTIRE footer subtree so a stale widget anywhere in the footer
|
|
121
|
+
# is refreshed rather than duplicated:
|
|
122
|
+
# 1. If the footer subtree already has a messaging component (in any
|
|
123
|
+
# region or as a direct section child), run update_messaging over
|
|
124
|
+
# the whole footer — never append a second one.
|
|
125
|
+
# 2. Otherwise pick the best insertion slot: the first
|
|
126
|
+
# `community_layout:section` wrapper (by definition, since the footer
|
|
127
|
+
# can hold consent banners etc. before it) → its first inner region →
|
|
128
|
+
# else the section itself → else the footer root.
|
|
129
|
+
# All child accessors default to [] so a component-only or empty footer
|
|
130
|
+
# never pipes null into an array op (jq would abort).
|
|
131
|
+
def patch_footer_region:
|
|
132
|
+
. as $footer |
|
|
133
|
+
if ($footer.children // []) | has_messaging then
|
|
134
|
+
.children |= update_messaging
|
|
135
|
+
else
|
|
136
|
+
([ ($footer.children // []) | to_entries[]
|
|
137
|
+
| select(.value.type? == "component"
|
|
138
|
+
and .value.definition? == "community_layout:section") ]
|
|
139
|
+
| .[0].key) as $si |
|
|
140
|
+
if $si == null then
|
|
141
|
+
.children = ((.children // []) + [new_messaging])
|
|
142
|
+
else
|
|
143
|
+
((.children[$si].children // []) | to_entries
|
|
144
|
+
| map(select(.value.type? == "region")) | .[0].key) as $ri |
|
|
145
|
+
if $ri == null then
|
|
146
|
+
.children[$si].children =
|
|
147
|
+
((.children[$si].children // []) + [new_messaging])
|
|
148
|
+
else
|
|
149
|
+
.children[$si].children[$ri].children =
|
|
150
|
+
((.children[$si].children[$ri].children // []) + [new_messaging])
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end;
|
|
154
|
+
|
|
155
|
+
# Apply to every top-level footer region. Guard the children array so a
|
|
156
|
+
# component-only layout (children == null) is a no-op, not a crash.
|
|
157
|
+
.contentBody.component.children |= (
|
|
158
|
+
(. // []) | map(
|
|
159
|
+
if .type? == "region" and .name? == "footer" then
|
|
160
|
+
patch_footer_region
|
|
161
|
+
else . end
|
|
162
|
+
)
|
|
163
|
+
)
|
|
164
|
+
' "$CONTENT_JSON" > "$TMP_OUT"
|
|
165
|
+
|
|
166
|
+
mv "$TMP_OUT" "$CONTENT_JSON"
|
|
167
|
+
trap - EXIT
|
|
168
|
+
LAYOUT_NAME=$(basename "$(dirname "$CONTENT_JSON")")
|
|
169
|
+
# Confirm the widget landed inside a FOOTER region specifically — not just
|
|
170
|
+
# anywhere in the file. A stale messaging component elsewhere (e.g. the
|
|
171
|
+
# content region) must not make a footerless layout count as patched, or the
|
|
172
|
+
# script could exit 0 without ever placing the site-wide footer widget.
|
|
173
|
+
# Recurse only into the footer region subtree(s) and look for the component.
|
|
174
|
+
if jq -e '
|
|
175
|
+
[ .contentBody.component.children[]?
|
|
176
|
+
| select(.type? == "region" and .name? == "footer")
|
|
177
|
+
| .. | select(type == "object" and .definition? == "experience_messaging:embeddedMessaging")
|
|
178
|
+
] | length > 0
|
|
179
|
+
' "$CONTENT_JSON" >/dev/null; then
|
|
180
|
+
echo "Patched: $LAYOUT_NAME ($CONTENT_JSON)"
|
|
181
|
+
PATCHED=$((PATCHED + 1))
|
|
182
|
+
else
|
|
183
|
+
echo "Skipped (no footer region): $LAYOUT_NAME ($CONTENT_JSON)" >&2
|
|
184
|
+
SKIPPED=$((SKIPPED + 1))
|
|
185
|
+
fi
|
|
186
|
+
done <<< "$THEME_LAYOUTS"
|
|
187
|
+
|
|
188
|
+
echo "Done: $PATCHED themeLayout(s) patched, $SKIPPED skipped."
|
|
189
|
+
|
|
190
|
+
if [ "$PATCHED" -eq 0 ]; then
|
|
191
|
+
echo "Error: no themeLayout had a footer region to patch under $SITE_DIR" >&2
|
|
192
|
+
exit 1
|
|
193
|
+
fi
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: service-email-to-case-configure
|
|
3
|
+
description: "Use to configure Salesforce Email-to-Case in a headless flow via the Metadata API. Reads the current CaseSettings, applies the desired emailToCase configuration with the updateMetadata CRUD call, and verifies by re-reading. Also the entry point when the user wants an Agentforce service agent on Email-to-Case: this skill configures the E2C base, then delegates agent creation and channel wiring. Start here even when no agent exists yet. TRIGGER when the user says set up Email-to-Case, configure email to case, enable Email-to-Case routing addresses, add an email routing address, Email-to-Case Metadata API, or set up Email-to-Case with an Agentforce service agent (attach an agent to an email routing address). DO NOT TRIGGER when the user needs the interactive Service Easy Setup wizard for E2cEasy addresses, when configuring On-Demand Email-to-Case only, for general Case object or web-to-case setup, or when only creating an Agentforce agent with no Email-to-Case involved."
|
|
4
|
+
metadata:
|
|
5
|
+
version: "1.1"
|
|
6
|
+
domains: ["Service", "Agentforce"]
|
|
7
|
+
minApiVersion: "67.0"
|
|
8
|
+
relatedSkills:
|
|
9
|
+
- "agentforce-generate"
|
|
10
|
+
- "service-agentforce-channel-configure"
|
|
11
|
+
cliTools:
|
|
12
|
+
- tool: ["python3"]
|
|
13
|
+
semver: ">=3.9"
|
|
14
|
+
- tool: ["sf"]
|
|
15
|
+
semver: ">=2.0.0"
|
|
16
|
+
accessCheck:
|
|
17
|
+
- type: "orgPerm"
|
|
18
|
+
value: "OrgPermissions.HasEmailToCase"
|
|
19
|
+
- type: "userPerm"
|
|
20
|
+
value: "UserPermissions.CustomizeApplication"
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
# Configure Email-to-Case (Metadata API)
|
|
24
|
+
|
|
25
|
+
Configure Salesforce Email-to-Case entirely through the Metadata API (no Setup UI), for headless org configuration. The skill builds a `CaseSettings` source file for the desired `emailToCase` state, then applies it with `scripts/apply-casesettings.py`, which runs `updateMetadata` in **two phases** — the full `emailToCase` block + Support Settings (Phase A), then routing addresses (Phase B) — and verifies by re-reading. Two phases because a single deploy **fails on a fresh org**: On-Demand must be live before an address binds (see Rules / Constraints).
|
|
26
|
+
|
|
27
|
+
## Scope
|
|
28
|
+
|
|
29
|
+
- **In scope**: Enabling Email-to-Case org-wide and setting its toggles (full field lists in Required Inputs and step 4); creating `EmailToCase`, `Outlook`, and `GmailOAuth` routing addresses; applying the change to an sf-CLI-authenticated org via `apply-casesettings.py`; verifying by re-reading.
|
|
30
|
+
- **Out of scope**:
|
|
31
|
+
- **`E2cEasy` routing addresses** — created only through the Service Easy Setup wizard, not the Metadata API; route the user there.
|
|
32
|
+
- Authenticating the org — the user authenticates out-of-band (e.g. `sf org login web`); the script reuses that session and never handles passwords or tokens.
|
|
33
|
+
- Case object schema, layouts, assignment rules, or Web-to-Case.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Attaching an Agentforce service agent (delegation)
|
|
38
|
+
|
|
39
|
+
When the user wants an Agentforce Service Agent to answer these emails, configure the Email-to-Case base (the Workflow below), then delegate — this skill never creates or modifies agents.
|
|
40
|
+
|
|
41
|
+
**Gate on org capability first.** Attaching an agent needs the org entitled for Agentforce Email-to-Case; that entitlement surfaces as the `BotEmailDefinition` metadata type, so probe read-only **before delegating**:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
scripts/check-agent-email-capability.sh <target-org-alias> # pins describe to the org's API version
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Exit **3** → not entitled: **stop, tell the user, and configure the plain Email-to-Case base only — make no Agentforce agent or channel-wiring changes.** Any other non-zero is an unreachable org, not "not entitled" — fix auth and re-run. On exit **0**, delegate:
|
|
48
|
+
|
|
49
|
+
1. **Agent creation → `agentforce-generate`,** omitting the **Service Customer Verification topic** (unsupported on the email channel) and including an **Escalation subagent** so the agent can hand off to a human — on email, escalation transfers the case to a service rep, and without the subagent the agent can't escalate.
|
|
50
|
+
2. **Wiring → `service-agentforce-channel-configure` Branch C.**
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Required Inputs
|
|
55
|
+
|
|
56
|
+
Gather or infer before applying. Ask only when a wrong assumption would produce a broken or incorrect result:
|
|
57
|
+
|
|
58
|
+
- **Target org alias** — the sf CLI alias/username of an already-authenticated org. The script obtains the session with `sf org display` and `sf org auth show-access-token`; it does not log in for you.
|
|
59
|
+
- **Routing address(es)** — for each: `routingName` (unique label), `addressType` (`EmailToCase` default, or `Outlook` / `GmailOAuth`), `caseOrigin`, and `casePriority`. The platform rejects the address if `caseOrigin` or `casePriority` is missing, so treat all four as required in the source file.
|
|
60
|
+
- **Customer-facing email address per routing address** — **ask explicitly for each, in address order**; never guess, default, or reuse from earlier context. Not stored in the source file — passed at apply time via `--routing-email` (one per address; the script fails closed on a count mismatch).
|
|
61
|
+
- **Support Settings — Default Case Owner & Automated Case User** — preserve-first, never assumed:
|
|
62
|
+
- **Independent, preserved per field.** Each configured field is left untouched; change one only if the user asks (`--overwrite-support-settings`). Ask **only for the field(s) unset**.
|
|
63
|
+
- **For each unset field, ask** (never default to the authenticated user): Default Case Owner **type** (`User`/`Queue`) + **value** (active Username or Queue DeveloperName) → `--owner-type`/`--owner-value`; Automated Case User **type** (`User`/`System`) — `User` needs a **username**, `System` needs no value → `--automated-type`/`--automated-value` (+ optional `--system-user-email` for System when the org's automated user doesn't exist yet).
|
|
64
|
+
- **If any value is invalid**, the script fails — get a valid value and re-run; never substitute or guess.
|
|
65
|
+
- Pass `--use-authenticated-user` **only** if the user explicitly asks.
|
|
66
|
+
- **Case defaults per address** (optional) — `createTask`, `saveEmailHeaders`, and an optional **per-address Default Case Owner** (`caseOwner` + `caseOwnerType`), **opt-in per address** (see step 6): omitted by default so cases fall to the org Default Case Owner / assignment rules. When set, `caseOwner` (active Username or Queue DeveloperName) must be paired with `caseOwnerType` (`User`/`Queue`); the script validates it against the org, failing closed if absent.
|
|
67
|
+
- **Org-level toggles** (optional) — set only if the user asks. Two containers: the **`emailToCase` section** (`enableHtmlEmail`, `notifyOwnerOnNewCaseEmail`, `enableE2CDeduplicateAttachments`, `showWordCountInComposer`, plus `enableE2CSourceTracking`, `overEmailLimitAction`, `unauthorizedSenderAction`), and **top-level Support Settings** (`enableDraftEmails` — plural element name, a sibling of `emailToCase`). See step 4's table for container/UI-label mapping; top-level scalar toggles apply in Phase A.
|
|
68
|
+
|
|
69
|
+
Defaults: `enableEmailToCase` and `enableOnDemandEmailToCase` default to `true` (both required — On-Demand before routing addresses); `addressType` defaults to `EmailToCase`. Support Settings have **no default** — preserved if set, otherwise elicited (never the authenticated user).
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Workflow
|
|
74
|
+
|
|
75
|
+
All steps are sequential.
|
|
76
|
+
|
|
77
|
+
1. **Confirm the org (and its type)** — confirm the target org alias is authenticated (`sf org display --target-org <alias>`). The apply script checks the `Organization` row and **refuses to mutate a production org** (non-sandbox, non-trial) unless `--confirm-production` is passed — enabling Email-to-Case is permanent and org-wide. If production, tell the user and confirm before re-running with `--confirm-production`. Sandboxes, scratch orgs, and trials deploy without the flag.
|
|
78
|
+
|
|
79
|
+
2. **Elicit the routing email(s)** — ask the user for the exact customer-facing email address for each routing address (never assume, default, or carry a value over from earlier). Pass them to the script via `--routing-email` in the order the addresses appear in the source file.
|
|
80
|
+
|
|
81
|
+
3. **Load the template** — read `assets/CaseSettings.settings-meta.xml` for structure and field placement. Its comments are authoring guidance **for you** — never copy them into the output. Emit only the elements you set; the output must be comment-free, matching `examples/CaseSettings-two-addresses.settings-meta.xml`.
|
|
82
|
+
|
|
83
|
+
4. **Enable the E2C switches, then confirm the optional toggles** — set both `enableEmailToCase` and `enableOnDemandEmailToCase` to `true` (both required; On-Demand must be on before routing addresses can be created — the script enables it in Phase A before Phase B). Then handle the **non-required convenience settings**, which the template turns on by default:
|
|
84
|
+
|
|
85
|
+
| UI label | Field | Container |
|
|
86
|
+
|----------|-------|-----------|
|
|
87
|
+
| Enable HTML email | `enableHtmlEmail` | `emailToCase` |
|
|
88
|
+
| Eliminate duplicate email attachments | `enableE2CDeduplicateAttachments` | `emailToCase` |
|
|
89
|
+
| Show word count in composer | `showWordCountInComposer` | `emailToCase` |
|
|
90
|
+
| Notify case owners on new emails | `notifyOwnerOnNewCaseEmail` | `emailToCase` |
|
|
91
|
+
| Enable Email Drafts | `enableDraftEmails` (top-level `CaseSettings`) | Support Settings |
|
|
92
|
+
|
|
93
|
+
**Before enabling these, tell the user exactly which will be turned on and let them opt out** (e.g. "I'll also enable these optional settings: … — let me know if you'd like to skip any."). Remove any the user opts out of; keep the rest in their correct container (four inside `<emailToCase>`, `enableDraftEmails` at the root). Never silently enable these or any other optional flag the user didn't agree to. Confirmed toggles apply in Phase A.
|
|
94
|
+
|
|
95
|
+
5. **Pick the correct surface per routing address** — for each address, decide by `addressType` using `references/routing_address_reference.md`. If any requested address is `E2cEasy`, stop and route the user to the Service Easy Setup wizard instead of emitting Metadata for it.
|
|
96
|
+
|
|
97
|
+
6. **Populate routing-address fields** — for each `EmailToCase` / `Outlook` / `GmailOAuth` address, set `addressType`, `routingName`, `caseOrigin`, and `casePriority` (all required — the platform rejects the operation with "Missing caseOrigin"/"Missing casePriority" if either is absent), plus any optional case defaults. Do **not** put `emailAddress` in the source file — it is supplied at apply time via `--routing-email`. Do **not** set the read-only fields `emailServicesAddress` or `isVerified` — the platform manages them. See `examples/CaseSettings-two-addresses.settings-meta.xml` for a complete multi-address example.
|
|
98
|
+
|
|
99
|
+
**Per-address Default Case Owner (opt-in).** Ask one address at a time whether cases from *this* address go to a specific owner or fall to the org Default Case Owner / assignment rules (the default) — different addresses can route to different owners. If the user **declines**, leave `caseOwner`/`caseOwnerType` out of the source file entirely (the template ships them commented out). If the user **opts in**, ask for the **type** (`User`/`Queue`) and **value** (active Username or Queue DeveloperName) and set **both** `<caseOwnerType>` and `<caseOwner>` — the platform rejects `caseOwner` without its type. `apply-casesettings.py` validates it against the org and fails closed if absent. Do not guess or reuse the top-level Default Case Owner.
|
|
100
|
+
|
|
101
|
+
7. **Determine Support Settings (Default Case Owner + Automated Case User)** — run `python3 scripts/apply-casesettings.py --target-org <alias> --input <source-file> --verify-only` and inspect `defaultCaseOwner` / `defaultCaseUser` / `useSystemUserAsDefaultCaseUser`. **When the user names a value, write it into the source file** (`defaultCaseOwner` + `defaultCaseOwnerType`; `defaultCaseUser`, or `useSystemUserAsDefaultCaseUser` + optional `systemUserEmail`) — the scored, versionable artifact; the script also accepts these as flags. **Leave each field the org already has as-is** — omit it and it is preserved (override only if the user asks — then `--overwrite-support-settings`). For a field unset **and** unnamed, ask; never assume the authenticated user (`--use-authenticated-user` only if explicitly asked).
|
|
102
|
+
|
|
103
|
+
8. **Validate the source file** — run `python3 scripts/validate-casesettings.py <path-to-source-file>` and resolve any reported errors before applying.
|
|
104
|
+
|
|
105
|
+
9. **Apply to the org** — run:
|
|
106
|
+
```bash
|
|
107
|
+
python3 scripts/apply-casesettings.py --target-org <alias> --input <source-file> \
|
|
108
|
+
--routing-email <email-for-address-1> [--routing-email <email-for-address-2> ...] \
|
|
109
|
+
[--owner-type User|Queue --owner-value <username-or-queue-devname>] \
|
|
110
|
+
[--automated-type User --automated-value <username> | --automated-type System [--system-user-email <email>]] \
|
|
111
|
+
[--confirm-production]
|
|
112
|
+
```
|
|
113
|
+
Provide exactly one `--routing-email` per routing address, in document order. Supply the owner/automated flags **only when the org's Support Settings are not already configured** (step 7); if configured, omit them and they are preserved. If the script rejects a value as invalid, relay it, get a valid value, and re-run — never fall back to the authenticated user. **If the script reports production and exits, do not add `--confirm-production` yourself** — confirm with the user first (step 1). The script applies Phase A (support settings + toggles), then Phase B (routing addresses), re-reads to verify, and exits non-zero on any fault.
|
|
114
|
+
|
|
115
|
+
10. **Confirm the result** — check the JSON summary: `verified.enableEmailToCase` / `verified.enableOnDemandEmailToCase` are `true`, `verified.routingAddressCount` matches the address count, each `phaseB` entry is `status: created` (or `already_exists`), and `supportSettings.action` is `preserved-existing` / `set-from-input` / `set-from-authenticated-user`. Use `--verify-only` to re-read without writing.
|
|
116
|
+
|
|
117
|
+
Configuration is complete after step 10.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## After setup — post-completion guidance
|
|
122
|
+
|
|
123
|
+
The items below are **not** workflow steps — present them to the user once setup is confirmed.
|
|
124
|
+
|
|
125
|
+
### Forwarding (required for real inbound mail)
|
|
126
|
+
|
|
127
|
+
Always give the user this guidance — it is how inbound mail to the customer-facing address actually reaches Salesforce:
|
|
128
|
+
|
|
129
|
+
> Your routing address now has a Salesforce-generated **email services address**. To receive inbound mail, configure your email system to forward mail sent to your customer-facing address (e.g. `support@company.com`) to that generated services address.
|
|
130
|
+
|
|
131
|
+
### End-to-end proof (Act 3)
|
|
132
|
+
|
|
133
|
+
Offer to prove inbound email creates Cases — a live round-trip; skip it if the user declines. The skill never sends email — it orchestrates two human actions, then verifies with SOQL: (1) **Address ownership** — Salesforce emails a confirmation link; `isVerified` flips only when the human clicks it. Tell the user to click it and **wait**. (2) **Send a test email** — ask the user to send one real email from an external mailbox to the routing address's Salesforce-generated **email services address** (not the customer-facing address, which only receives mail once forwarding is configured), report the sender, and **wait**. (3) **Verify with evidence** — then run:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
python3 scripts/apply-casesettings.py --target-org <alias> --verify-cases \
|
|
137
|
+
[--supplied-email <external-sender-address>]
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Read-only: it queries `Case` where `Origin='Email'` (last 3 days, optionally narrowed by sender) plus the linked incoming `EmailMessage` rows (`Incoming=true`, `ParentId` = the new Case), and exits **non-zero if no matching Case has a linked incoming email** (mail not processed yet — wait and re-run — or address not verified). On success it prints the `Case` + `EmailMessage` evidence with `proven: true`.
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Rules / Constraints
|
|
145
|
+
|
|
146
|
+
| Constraint | Rationale |
|
|
147
|
+
|-----------|-----------|
|
|
148
|
+
| Apply via `apply-casesettings.py` (two-phase `updateMetadata`), never a plain deploy or a minimal `emailToCase` patch | A single deploy fails on a fresh org; the full `emailToCase` block (not a field-level flip) is what provisions On-Demand before addresses bind. See `references/apply-mechanics.md`. |
|
|
149
|
+
| Write only the top-level fields the skill owns; never echo the whole `CaseSettings` record | The platform re-validates every top-level field in the payload (e.g. Case Feed → Chatter); sending only `emailToCase` + `enableDraftEmails` + Support Settings avoids unrelated failures and needs no Chatter prerequisite. Omitted fields keep their values via field-level merge. |
|
|
150
|
+
| The customer-facing email must be explicit user input (`--routing-email`), never in the source file and never assumed | Prevents a guessed or stale address from being provisioned. The script fails closed if `--routing-email` count ≠ address count. |
|
|
151
|
+
| `CaseSettings` `fullName` is always `Case` | It is an org singleton settings type; the script targets `Case` automatically. |
|
|
152
|
+
| Support Settings are preserved **per field** if configured; never assumed if not | Default Case Owner and Automated Case User are independent — each configured field is left untouched (unless `--overwrite-support-settings`), and only an unset field requires an explicit, org-validated value (fails closed otherwise). The authenticated user is used only with `--use-authenticated-user`. |
|
|
153
|
+
| Automated Case User "System" and a named `defaultCaseUser` are mutually exclusive | `--automated-type System` sets `useSystemUserAsDefaultCaseUser` and must not carry a user value; the platform rejects both. |
|
|
154
|
+
| The script reads → patches → updates (append-only for addresses) | It merges onto current settings, so existing routing addresses are preserved; a duplicate `routingName`/`emailAddress` is reported as `already_exists`. New addresses are emitted **before** existing ones (`updateMetadata` replaces the collection wholesale and would drop an existing address that a new one follows; a runtime guard fails the run if any existing address is dropped). See `references/apply-mechanics.md`. |
|
|
155
|
+
| `EmailToCaseSettings` is never applied directly; `enableEmailToCase` cannot be turned off once on | It is written only as the `emailToCase` child of `CaseSettings`. The platform permanently enables the feature after the first `true` apply; never rely on setting it back to `false`. |
|
|
156
|
+
| Production orgs require explicit `--confirm-production`; never add the flag unprompted | Enabling Email-to-Case is permanent and org-wide. The script fails closed on a non-sandbox, non-trial org (and one whose type it can't read) until the user confirms. Sandboxes and trials are exempt. |
|
|
157
|
+
| Proving inbound Cases is a read-only step the user triggers; the skill never sends email | `--verify-cases` only queries `Case`/`EmailMessage` after the human verified the address and sent a test email. Fails closed until a Case with a linked incoming email exists. |
|
|
158
|
+
| `E2cEasy` addresses must use the Service Easy Setup wizard | The prebuilt `service_case` queue binding and `isVerified` flip are not reproducible through the Metadata API. |
|
|
159
|
+
| Never write `emailServicesAddress` or `isVerified` | Both are read-only, platform-generated; the script strips them if present. |
|
|
160
|
+
| The generated source file contains only the elements being set — **no XML comments** | Template/example comments are authoring guidance, not output. Copying them bloats the file (gold is comment-free) and CLI-example comments with `<placeholder>` tokens can fail XML validation. Put explanation in your chat reply, never in the `.settings-meta.xml`. |
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Gotchas
|
|
165
|
+
|
|
166
|
+
For the full symptom → resolution table (Phase B provisioning errors, Case Feed/Chatter, per-address owner half-fills, `GmailOAuth` conflicts, `--verify-cases` failures, and every toggle-placement pitfall), read `references/troubleshooting.md`.
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Output Expectations
|
|
171
|
+
|
|
172
|
+
Deliverables:
|
|
173
|
+
- A `CaseSettings` source file (e.g. `Case.settings-meta.xml`) for the desired `emailToCase` state — toggles and routing-address fields, **without** `emailAddress` (supplied at apply time), read-only fields, or XML comments. Structure follows `assets/CaseSettings.settings-meta.xml`.
|
|
174
|
+
- The applied org state from `apply-casesettings.py`, plus its JSON summary (resolved owner, per-address status, verification read).
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Reference File Index
|
|
179
|
+
|
|
180
|
+
| File | When to read / run |
|
|
181
|
+
|------|-------------|
|
|
182
|
+
| `assets/CaseSettings.settings-meta.xml` | Step 3 — the starting template for the source file |
|
|
183
|
+
| `references/apply-mechanics.md` | Read before touching how the script builds or sequences its `updateMetadata` payloads |
|
|
184
|
+
| `references/troubleshooting.md` | When the apply or verify step reports an error, or a configured setting doesn't behave — full symptom → resolution table |
|
|
185
|
+
| `references/routing_address_reference.md` | Steps 5–6 — routing-address field semantics and the `addressType` surface-selection rule |
|
|
186
|
+
| `examples/CaseSettings-two-addresses.settings-meta.xml` | Step 6 — to verify the source-file structure for multiple routing addresses |
|
|
187
|
+
| `scripts/check-agent-email-capability.sh` | Attaching an Agentforce service agent — the pre-delegation capability gate (probes for `BotEmailDefinition`) |
|
|
188
|
+
| `scripts/validate-casesettings.py` | Step 8 — deterministic structural validation before applying |
|
|
189
|
+
| `scripts/apply-casesettings.py` | Step 9 — applies the settings via two-phase `updateMetadata` and verifies |
|
|
190
|
+
| `scripts/tests/test_get_session.py` | Run when changing session-token acquisition (`get_session` / `_usable_access_token`) — the unit suite guarding token extraction and API-version resolution |
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!-- Template for headless Email-to-Case config. Fill in, then emit a COMMENT-FREE
|
|
3
|
+
source file (see SKILL.md step 3). fullName is implicitly "Case". Do not set
|
|
4
|
+
emailAddress (supply via --routing-email), emailServicesAddress, or isVerified. -->
|
|
5
|
+
<CaseSettings xmlns="http://soap.sforce.com/2006/04/metadata">
|
|
6
|
+
<!-- Support Settings (siblings of emailToCase). Set inline whatever the user
|
|
7
|
+
names; omit the rest. Default Case Owner: defaultCaseOwner (a Username or
|
|
8
|
+
Queue DeveloperName) with its defaultCaseOwnerType (User or Queue).
|
|
9
|
+
Automated Case User — pick ONE, they are mutually exclusive:
|
|
10
|
+
- a named person -> defaultCaseUser (a Username), OR
|
|
11
|
+
- the org's System user -> useSystemUserAsDefaultCaseUser true, plus
|
|
12
|
+
systemUserEmail when the user gives an email (do NOT also set
|
|
13
|
+
defaultCaseUser in this case).
|
|
14
|
+
apply-casesettings.py can also supply/validate these via flags and
|
|
15
|
+
preserves existing org values. Emit these fields ONLY when the user
|
|
16
|
+
names a value; a defaultCaseOwnerType without a defaultCaseOwner (or the
|
|
17
|
+
reverse) is a half-filled owner the platform rejects. -->
|
|
18
|
+
|
|
19
|
+
<!-- "Enable Email Drafts" — plural, top-level. Remove if the user opts out. -->
|
|
20
|
+
<enableDraftEmails>true</enableDraftEmails>
|
|
21
|
+
|
|
22
|
+
<emailToCase>
|
|
23
|
+
<!-- Required. On-Demand must be on before addresses bind. -->
|
|
24
|
+
<enableEmailToCase>true</enableEmailToCase>
|
|
25
|
+
<enableOnDemandEmailToCase>true</enableOnDemandEmailToCase>
|
|
26
|
+
|
|
27
|
+
<!-- Optional convenience toggles (on by default). Remove any the user opts out of. -->
|
|
28
|
+
<enableHtmlEmail>true</enableHtmlEmail>
|
|
29
|
+
<notifyOwnerOnNewCaseEmail>true</notifyOwnerOnNewCaseEmail>
|
|
30
|
+
<enableE2CDeduplicateAttachments>true</enableE2CDeduplicateAttachments>
|
|
31
|
+
<showWordCountInComposer>true</showWordCountInComposer>
|
|
32
|
+
|
|
33
|
+
<!-- One routingAddresses block per address. addressType: EmailToCase | Outlook
|
|
34
|
+
| GmailOAuth. Optional per-address caseOwner + caseOwnerType (opt-in, paired)
|
|
35
|
+
— see SKILL.md step 6. Placeholders below are filled per address. -->
|
|
36
|
+
<routingAddresses>
|
|
37
|
+
<addressType>EmailToCase</addressType>
|
|
38
|
+
<routingName>ROUTING_NAME</routingName>
|
|
39
|
+
<caseOrigin>CASE_ORIGIN</caseOrigin>
|
|
40
|
+
<casePriority>CASE_PRIORITY</casePriority>
|
|
41
|
+
<createTask>false</createTask>
|
|
42
|
+
<saveEmailHeaders>true</saveEmailHeaders>
|
|
43
|
+
</routingAddresses>
|
|
44
|
+
</emailToCase>
|
|
45
|
+
</CaseSettings>
|