scc-universal 1.1.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/.claude-plugin/plugin.json +44 -0
- package/.cursor/agents/deep-researcher.md +142 -0
- package/.cursor/agents/doc-updater.md +219 -0
- package/.cursor/agents/eval-runner.md +335 -0
- package/.cursor/agents/learning-engine.md +210 -0
- package/.cursor/agents/loop-operator.md +245 -0
- package/.cursor/agents/refactor-cleaner.md +119 -0
- package/.cursor/agents/sf-admin-agent.md +127 -0
- package/.cursor/agents/sf-agentforce-agent.md +126 -0
- package/.cursor/agents/sf-apex-agent.md +117 -0
- package/.cursor/agents/sf-architect.md +426 -0
- package/.cursor/agents/sf-aura-reviewer.md +369 -0
- package/.cursor/agents/sf-bugfix-agent.md +101 -0
- package/.cursor/agents/sf-flow-agent.md +155 -0
- package/.cursor/agents/sf-integration-agent.md +141 -0
- package/.cursor/agents/sf-lwc-agent.md +123 -0
- package/.cursor/agents/sf-review-agent.md +357 -0
- package/.cursor/agents/sf-visualforce-reviewer.md +465 -0
- package/.cursor/hooks/adapter.js +81 -0
- package/.cursor/hooks/after-file-edit.js +26 -0
- package/.cursor/hooks/after-mcp-execution.js +12 -0
- package/.cursor/hooks/after-shell-execution.js +30 -0
- package/.cursor/hooks/after-tab-file-edit.js +12 -0
- package/.cursor/hooks/before-mcp-execution.js +11 -0
- package/.cursor/hooks/before-read-file.js +13 -0
- package/.cursor/hooks/before-shell-execution.js +29 -0
- package/.cursor/hooks/before-submit-prompt.js +23 -0
- package/.cursor/hooks/pre-compact.js +7 -0
- package/.cursor/hooks/session-end.js +10 -0
- package/.cursor/hooks/session-start.js +10 -0
- package/.cursor/hooks/stop.js +18 -0
- package/.cursor/hooks/subagent-start.js +10 -0
- package/.cursor/hooks/subagent-stop.js +10 -0
- package/.cursor/hooks.json +107 -0
- package/.cursor/skills/aside/SKILL.md +115 -0
- package/.cursor/skills/checkpoint/SKILL.md +50 -0
- package/.cursor/skills/configure-scc/SKILL.md +160 -0
- package/.cursor/skills/continuous-agent-loop/SKILL.md +260 -0
- package/.cursor/skills/mcp-server-patterns/SKILL.md +142 -0
- package/.cursor/skills/model-route/SKILL.md +81 -0
- package/.cursor/skills/prompt-optimizer/SKILL.md +366 -0
- package/.cursor/skills/refactor-clean/SKILL.md +133 -0
- package/.cursor/skills/resume-session/SKILL.md +111 -0
- package/.cursor/skills/save-session/SKILL.md +183 -0
- package/.cursor/skills/search-first/SKILL.md +140 -0
- package/.cursor/skills/security-scan/SKILL.md +142 -0
- package/.cursor/skills/sessions/SKILL.md +124 -0
- package/.cursor/skills/sf-agentforce-development/SKILL.md +449 -0
- package/.cursor/skills/sf-apex-async-patterns/SKILL.md +324 -0
- package/.cursor/skills/sf-apex-best-practices/SKILL.md +421 -0
- package/.cursor/skills/sf-apex-constraints/SKILL.md +79 -0
- package/.cursor/skills/sf-apex-cursor/SKILL.md +336 -0
- package/.cursor/skills/sf-apex-enterprise-patterns/SKILL.md +344 -0
- package/.cursor/skills/sf-apex-testing/SKILL.md +407 -0
- package/.cursor/skills/sf-api-design/SKILL.md +237 -0
- package/.cursor/skills/sf-approval-processes/SKILL.md +312 -0
- package/.cursor/skills/sf-aura-development/SKILL.md +260 -0
- package/.cursor/skills/sf-build-fix/SKILL.md +120 -0
- package/.cursor/skills/sf-data-modeling/SKILL.md +274 -0
- package/.cursor/skills/sf-debugging/SKILL.md +362 -0
- package/.cursor/skills/sf-deployment/SKILL.md +291 -0
- package/.cursor/skills/sf-deployment-constraints/SKILL.md +153 -0
- package/.cursor/skills/sf-devops-ci-cd/SKILL.md +322 -0
- package/.cursor/skills/sf-docs-lookup/SKILL.md +100 -0
- package/.cursor/skills/sf-e2e-testing/SKILL.md +321 -0
- package/.cursor/skills/sf-experience-cloud/SKILL.md +248 -0
- package/.cursor/skills/sf-flow-development/SKILL.md +376 -0
- package/.cursor/skills/sf-governor-limits/SKILL.md +319 -0
- package/.cursor/skills/sf-harness-audit/SKILL.md +139 -0
- package/.cursor/skills/sf-help/SKILL.md +156 -0
- package/.cursor/skills/sf-integration/SKILL.md +479 -0
- package/.cursor/skills/sf-lwc-constraints/SKILL.md +128 -0
- package/.cursor/skills/sf-lwc-development/SKILL.md +302 -0
- package/.cursor/skills/sf-lwc-testing/SKILL.md +387 -0
- package/.cursor/skills/sf-metadata-management/SKILL.md +285 -0
- package/.cursor/skills/sf-platform-events-cdc/SKILL.md +372 -0
- package/.cursor/skills/sf-quickstart/SKILL.md +170 -0
- package/.cursor/skills/sf-security/SKILL.md +330 -0
- package/.cursor/skills/sf-security-constraints/SKILL.md +125 -0
- package/.cursor/skills/sf-soql-constraints/SKILL.md +129 -0
- package/.cursor/skills/sf-soql-optimization/SKILL.md +353 -0
- package/.cursor/skills/sf-tdd-workflow/SKILL.md +332 -0
- package/.cursor/skills/sf-testing-constraints/SKILL.md +198 -0
- package/.cursor/skills/sf-trigger-constraints/SKILL.md +88 -0
- package/.cursor/skills/sf-trigger-frameworks/SKILL.md +343 -0
- package/.cursor/skills/sf-visualforce-development/SKILL.md +259 -0
- package/.cursor/skills/strategic-compact/SKILL.md +205 -0
- package/.cursor/skills/update-docs/SKILL.md +162 -0
- package/.cursor/skills/update-platform-docs/SKILL.md +86 -0
- package/.cursor-plugin/plugin.json +26 -0
- package/LICENSE +21 -0
- package/README.md +522 -0
- package/agents/deep-researcher.md +145 -0
- package/agents/doc-updater.md +222 -0
- package/agents/eval-runner.md +340 -0
- package/agents/learning-engine.md +211 -0
- package/agents/loop-operator.md +247 -0
- package/agents/refactor-cleaner.md +122 -0
- package/agents/sf-admin-agent.md +131 -0
- package/agents/sf-agentforce-agent.md +132 -0
- package/agents/sf-apex-agent.md +124 -0
- package/agents/sf-architect.md +435 -0
- package/agents/sf-aura-reviewer.md +372 -0
- package/agents/sf-bugfix-agent.md +105 -0
- package/agents/sf-flow-agent.md +159 -0
- package/agents/sf-integration-agent.md +146 -0
- package/agents/sf-lwc-agent.md +127 -0
- package/agents/sf-review-agent.md +366 -0
- package/agents/sf-visualforce-reviewer.md +468 -0
- package/assets/logo.svg +18 -0
- package/docs/ARCHITECTURE.md +133 -0
- package/docs/authoring-guide.md +373 -0
- package/docs/hook-development.md +578 -0
- package/docs/token-optimization.md +139 -0
- package/docs/workflow-examples.md +645 -0
- package/examples/agentforce-action/README.md +227 -0
- package/examples/apex-trigger-handler/README.md +114 -0
- package/examples/devops-pipeline/README.md +325 -0
- package/examples/flow-automation/README.md +188 -0
- package/examples/integration-pattern/README.md +416 -0
- package/examples/lwc-component/README.md +180 -0
- package/examples/platform-events/README.md +492 -0
- package/examples/scratch-org-setup/README.md +138 -0
- package/examples/security-audit/README.md +244 -0
- package/examples/visualforce-migration/README.md +314 -0
- package/hooks/hooks.json +338 -0
- package/hooks/memory-persistence/README.md +73 -0
- package/manifests/install-modules.json +217 -0
- package/manifests/install-profiles.json +17 -0
- package/mcp-configs/mcp-servers.json +19 -0
- package/package.json +89 -0
- package/schemas/hooks.schema.json +123 -0
- package/schemas/install-modules.schema.json +76 -0
- package/schemas/install-profiles.schema.json +28 -0
- package/schemas/install-state.schema.json +73 -0
- package/schemas/package-manager.schema.json +18 -0
- package/schemas/plugin.schema.json +112 -0
- package/schemas/scc-install-config.schema.json +29 -0
- package/schemas/state-store.schema.json +111 -0
- package/scripts/cli/install-apply.js +170 -0
- package/scripts/cli/uninstall.js +193 -0
- package/scripts/hooks/check-console-log.js +101 -0
- package/scripts/hooks/check-hook-enabled.js +17 -0
- package/scripts/hooks/check-platform-docs-age.js +48 -0
- package/scripts/hooks/cost-tracker.js +78 -0
- package/scripts/hooks/doc-file-warning.js +63 -0
- package/scripts/hooks/evaluate-session.js +98 -0
- package/scripts/hooks/governor-check.js +220 -0
- package/scripts/hooks/learning-observe.sh +206 -0
- package/scripts/hooks/mcp-health-check.js +588 -0
- package/scripts/hooks/post-bash-build-complete.js +34 -0
- package/scripts/hooks/post-bash-pr-created.js +43 -0
- package/scripts/hooks/post-edit-console-warn.js +61 -0
- package/scripts/hooks/post-edit-format.js +79 -0
- package/scripts/hooks/post-edit-typecheck.js +98 -0
- package/scripts/hooks/post-write.js +168 -0
- package/scripts/hooks/pre-bash-git-push-reminder.js +35 -0
- package/scripts/hooks/pre-bash-tmux-reminder.js +47 -0
- package/scripts/hooks/pre-compact.js +51 -0
- package/scripts/hooks/pre-tool-use.js +163 -0
- package/scripts/hooks/pre-write-doc-warn.js +9 -0
- package/scripts/hooks/quality-gate.js +251 -0
- package/scripts/hooks/run-with-flags-shell.sh +32 -0
- package/scripts/hooks/run-with-flags.js +135 -0
- package/scripts/hooks/session-end-marker.js +29 -0
- package/scripts/hooks/session-end.js +311 -0
- package/scripts/hooks/session-start.js +202 -0
- package/scripts/hooks/sfdx-scanner-check.js +142 -0
- package/scripts/hooks/sfdx-validate.js +119 -0
- package/scripts/hooks/stop-hook.js +170 -0
- package/scripts/hooks/suggest-compact.js +67 -0
- package/scripts/lib/agent-adapter.js +82 -0
- package/scripts/lib/apex-analysis.js +194 -0
- package/scripts/lib/hook-flags.js +74 -0
- package/scripts/lib/install-config.js +73 -0
- package/scripts/lib/install-executor.js +363 -0
- package/scripts/lib/install-state.js +121 -0
- package/scripts/lib/orchestration-session.js +299 -0
- package/scripts/lib/package-manager.js +124 -0
- package/scripts/lib/project-detect.js +228 -0
- package/scripts/lib/schema-validator.js +190 -0
- package/scripts/lib/skill-adapter.js +100 -0
- package/scripts/lib/state-store.js +376 -0
- package/scripts/lib/tmux-worktree-orchestrator.js +598 -0
- package/scripts/lib/utils.js +313 -0
- package/scripts/scc.js +164 -0
- package/skills/_reference/AGENTFORCE_PATTERNS.md +112 -0
- package/skills/_reference/APEX_CURSOR.md +159 -0
- package/skills/_reference/API_VERSIONS.md +78 -0
- package/skills/_reference/APPROVAL_PROCESSES.md +105 -0
- package/skills/_reference/ASYNC_PATTERNS.md +163 -0
- package/skills/_reference/AURA_COMPONENTS.md +146 -0
- package/skills/_reference/DATA_MIGRATION_PATTERNS.md +151 -0
- package/skills/_reference/DATA_MODELING.md +124 -0
- package/skills/_reference/DEBUGGING_TOOLS.md +140 -0
- package/skills/_reference/DEPLOYMENT_CHECKLIST.md +87 -0
- package/skills/_reference/DEPRECATIONS.md +79 -0
- package/skills/_reference/DOCKER_CI_PATTERNS.md +138 -0
- package/skills/_reference/ENTERPRISE_PATTERNS.md +122 -0
- package/skills/_reference/EXPERIENCE_CLOUD.md +143 -0
- package/skills/_reference/FLOW_PATTERNS.md +113 -0
- package/skills/_reference/GOVERNOR_LIMITS.md +77 -0
- package/skills/_reference/INTEGRATION_PATTERNS.md +105 -0
- package/skills/_reference/LWC_PATTERNS.md +79 -0
- package/skills/_reference/METADATA_TYPES.md +115 -0
- package/skills/_reference/NAMING_CONVENTIONS.md +84 -0
- package/skills/_reference/PACKAGE_DEVELOPMENT.md +150 -0
- package/skills/_reference/PLATFORM_EVENTS.md +121 -0
- package/skills/_reference/REPORTING_API.md +143 -0
- package/skills/_reference/SCRATCH_ORG_PATTERNS.md +126 -0
- package/skills/_reference/SECURITY_PATTERNS.md +127 -0
- package/skills/_reference/SHARING_MODEL.md +120 -0
- package/skills/_reference/SOQL_PATTERNS.md +119 -0
- package/skills/_reference/TESTING_STANDARDS.md +96 -0
- package/skills/_reference/TRIGGER_PATTERNS.md +114 -0
- package/skills/_reference/VISUALFORCE_PATTERNS.md +121 -0
- package/skills/aside/SKILL.md +118 -0
- package/skills/checkpoint/SKILL.md +53 -0
- package/skills/configure-scc/SKILL.md +163 -0
- package/skills/continuous-agent-loop/SKILL.md +264 -0
- package/skills/mcp-server-patterns/SKILL.md +146 -0
- package/skills/model-route/SKILL.md +84 -0
- package/skills/prompt-optimizer/SKILL.md +369 -0
- package/skills/refactor-clean/SKILL.md +136 -0
- package/skills/resume-session/SKILL.md +114 -0
- package/skills/save-session/SKILL.md +186 -0
- package/skills/search-first/SKILL.md +144 -0
- package/skills/security-scan/SKILL.md +146 -0
- package/skills/sessions/SKILL.md +127 -0
- package/skills/sf-agentforce-development/SKILL.md +450 -0
- package/skills/sf-apex-async-patterns/SKILL.md +326 -0
- package/skills/sf-apex-best-practices/SKILL.md +425 -0
- package/skills/sf-apex-constraints/SKILL.md +81 -0
- package/skills/sf-apex-cursor/SKILL.md +338 -0
- package/skills/sf-apex-enterprise-patterns/SKILL.md +348 -0
- package/skills/sf-apex-testing/SKILL.md +409 -0
- package/skills/sf-api-design/SKILL.md +238 -0
- package/skills/sf-approval-processes/SKILL.md +315 -0
- package/skills/sf-aura-development/SKILL.md +263 -0
- package/skills/sf-build-fix/SKILL.md +121 -0
- package/skills/sf-data-modeling/SKILL.md +278 -0
- package/skills/sf-debugging/SKILL.md +363 -0
- package/skills/sf-deployment/SKILL.md +295 -0
- package/skills/sf-deployment-constraints/SKILL.md +155 -0
- package/skills/sf-devops-ci-cd/SKILL.md +325 -0
- package/skills/sf-docs-lookup/SKILL.md +103 -0
- package/skills/sf-e2e-testing/SKILL.md +324 -0
- package/skills/sf-experience-cloud/SKILL.md +249 -0
- package/skills/sf-flow-development/SKILL.md +377 -0
- package/skills/sf-governor-limits/SKILL.md +323 -0
- package/skills/sf-harness-audit/SKILL.md +142 -0
- package/skills/sf-help/SKILL.md +159 -0
- package/skills/sf-integration/SKILL.md +483 -0
- package/skills/sf-lwc-constraints/SKILL.md +130 -0
- package/skills/sf-lwc-development/SKILL.md +303 -0
- package/skills/sf-lwc-testing/SKILL.md +388 -0
- package/skills/sf-metadata-management/SKILL.md +288 -0
- package/skills/sf-platform-events-cdc/SKILL.md +375 -0
- package/skills/sf-quickstart/SKILL.md +173 -0
- package/skills/sf-security/SKILL.md +334 -0
- package/skills/sf-security-constraints/SKILL.md +127 -0
- package/skills/sf-soql-constraints/SKILL.md +131 -0
- package/skills/sf-soql-optimization/SKILL.md +354 -0
- package/skills/sf-tdd-workflow/SKILL.md +336 -0
- package/skills/sf-testing-constraints/SKILL.md +200 -0
- package/skills/sf-trigger-constraints/SKILL.md +90 -0
- package/skills/sf-trigger-frameworks/SKILL.md +347 -0
- package/skills/sf-visualforce-development/SKILL.md +260 -0
- package/skills/strategic-compact/SKILL.md +208 -0
- package/skills/update-docs/SKILL.md +165 -0
- package/skills/update-platform-docs/SKILL.md +90 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
<!-- Source: https://developer.salesforce.com/docs/atlas.en-us.sfdx_dev.meta/sfdx_dev/sfdx_dev_ci.htm -->
|
|
2
|
+
<!-- Last verified: API v66.0 — 2026-03-29 -->
|
|
3
|
+
|
|
4
|
+
# Docker & CI Patterns — Salesforce Reference
|
|
5
|
+
|
|
6
|
+
## Docker Images
|
|
7
|
+
|
|
8
|
+
| Image | Status | Notes |
|
|
9
|
+
|---|---|---|
|
|
10
|
+
| `salesforce/cli` (Docker Hub) | Active | Weekly releases; tags: `latest`, `latest-rc`, `{version}-full`, `{version}-slim` |
|
|
11
|
+
| `salesforce/salesforcedx` | Deprecated | Do not use; migrate to `salesforce/cli` |
|
|
12
|
+
| `node:20-slim` + `npm i -g @salesforce/cli` | Recommended alternative | Full control over base image; smaller footprint |
|
|
13
|
+
|
|
14
|
+
### Image Tag Variants
|
|
15
|
+
|
|
16
|
+
| Tag | Contents |
|
|
17
|
+
|---|---|
|
|
18
|
+
| `latest` | Current stable release (retagged weekly from `latest-rc`) |
|
|
19
|
+
| `latest-rc` | Release candidate (published each week) |
|
|
20
|
+
| `{version}-full` | Full Node.js LTS + `sf` installed via npm |
|
|
21
|
+
| `{version}-slim` | Minimal image, smaller footprint |
|
|
22
|
+
|
|
23
|
+
### Release Cadence
|
|
24
|
+
|
|
25
|
+
- New `latest-rc` image published **weekly**
|
|
26
|
+
- Retagged to `latest` the following week
|
|
27
|
+
- Versioned tags match CLI version (e.g., `2.70.7-slim`)
|
|
28
|
+
|
|
29
|
+
## CI Authentication Methods
|
|
30
|
+
|
|
31
|
+
| Method | Command | Best For |
|
|
32
|
+
|---|---|---|
|
|
33
|
+
| JWT Bearer Flow | `sf org login jwt --client-id $KEY --jwt-key-file server.key --username $USER` | CI/CD (headless, no browser) |
|
|
34
|
+
| SFDX Auth URL | `sf org login sfdx-url --sfdx-url-file auth.txt` | CI/CD (simpler setup) |
|
|
35
|
+
| Web Login | `sf org login web` | Local dev only (requires browser) |
|
|
36
|
+
|
|
37
|
+
JWT Bearer Flow is the **recommended** method for CI pipelines.
|
|
38
|
+
|
|
39
|
+
## CI Pipeline Structure
|
|
40
|
+
|
|
41
|
+
Salesforce recommends splitting CI into two jobs:
|
|
42
|
+
|
|
43
|
+
| Job | Tools | Purpose |
|
|
44
|
+
|---|---|---|
|
|
45
|
+
| Job 1: Lint & LWC Tests | Node.js, ESLint, Jest, Prettier | Format, lint, and unit-test LWC |
|
|
46
|
+
| Job 2: Deploy & Apex Tests | Salesforce CLI, Scratch Org | Deploy metadata, run Apex tests |
|
|
47
|
+
|
|
48
|
+
## Core CLI Commands for CI
|
|
49
|
+
|
|
50
|
+
| Command | Purpose |
|
|
51
|
+
|---|---|
|
|
52
|
+
| `sf org login jwt ...` | Authenticate to DevHub (headless) |
|
|
53
|
+
| `sf org login sfdx-url --sfdx-url-file auth.txt --set-default-dev-hub` | Auth via stored URL |
|
|
54
|
+
| `sf org create scratch --definition-file config/project-scratch-def.json --alias ci --duration-days 1` | Create ephemeral scratch org |
|
|
55
|
+
| `sf project deploy start --target-org ci` | Deploy source to scratch org |
|
|
56
|
+
| `sf apex run test --test-level RunLocalTests --code-coverage --result-format human --target-org ci` | Run Apex tests with coverage |
|
|
57
|
+
| `sf org delete scratch --target-org ci --no-prompt` | Cleanup scratch org |
|
|
58
|
+
| `sf code-analyzer run --target force-app --format table` | Static analysis (Code Analyzer) |
|
|
59
|
+
|
|
60
|
+
## Scratch Org Lifecycle in CI
|
|
61
|
+
|
|
62
|
+
| Step | Duration | Notes |
|
|
63
|
+
|---|---|---|
|
|
64
|
+
| Create | ~60-120s | Use `--duration-days 1` for auto-cleanup |
|
|
65
|
+
| Deploy | Varies | Full source push |
|
|
66
|
+
| Test | Varies | `RunLocalTests` excludes managed package tests |
|
|
67
|
+
| Delete | ~10s | Always run in `if: always()` / `post` block |
|
|
68
|
+
|
|
69
|
+
## Supported CI Platforms
|
|
70
|
+
|
|
71
|
+
| Platform | Sample Repos / Docs |
|
|
72
|
+
|---|---|
|
|
73
|
+
| GitHub Actions | `forcedotcom/sfdx-github-actions` |
|
|
74
|
+
| Jenkins | Salesforce DX Developer Guide: CI with Jenkins |
|
|
75
|
+
| CircleCI | Salesforce DX Developer Guide: CI with CircleCI |
|
|
76
|
+
| GitLab CI | Community examples; same CLI commands |
|
|
77
|
+
| Bitbucket Pipelines | Community examples; same CLI commands |
|
|
78
|
+
|
|
79
|
+
## GitHub Actions Workflow Pattern
|
|
80
|
+
|
|
81
|
+
```yaml
|
|
82
|
+
name: Salesforce CI
|
|
83
|
+
on: [push, pull_request]
|
|
84
|
+
jobs:
|
|
85
|
+
test:
|
|
86
|
+
runs-on: ubuntu-latest
|
|
87
|
+
container:
|
|
88
|
+
image: node:20-slim
|
|
89
|
+
steps:
|
|
90
|
+
- uses: actions/checkout@v4
|
|
91
|
+
- run: npm install -g @salesforce/cli
|
|
92
|
+
- name: Auth DevHub
|
|
93
|
+
run: |
|
|
94
|
+
echo "${{ secrets.SFDX_AUTH_URL }}" > auth.txt
|
|
95
|
+
sf org login sfdx-url --sfdx-url-file auth.txt --set-default-dev-hub
|
|
96
|
+
- name: Create Scratch Org
|
|
97
|
+
run: sf org create scratch --definition-file config/project-scratch-def.json --alias ci --duration-days 1
|
|
98
|
+
- name: Deploy
|
|
99
|
+
run: sf project deploy start --target-org ci
|
|
100
|
+
- name: Test
|
|
101
|
+
run: sf apex run test --test-level RunLocalTests --code-coverage --result-format human --target-org ci
|
|
102
|
+
- name: Cleanup
|
|
103
|
+
if: always()
|
|
104
|
+
run: |
|
|
105
|
+
rm -f auth.txt server.key
|
|
106
|
+
sf org delete scratch --target-org ci --no-prompt
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Security Hardening
|
|
110
|
+
|
|
111
|
+
| Practice | Implementation |
|
|
112
|
+
|---|---|
|
|
113
|
+
| Non-root user | `RUN adduser --system appuser` then `USER appuser` |
|
|
114
|
+
| Credential cleanup | `rm -f auth.txt server.key` after auth |
|
|
115
|
+
| Secret storage | GitHub Secrets / CI vault; never commit credentials |
|
|
116
|
+
| Auth volume | Named volume for `.sf` directory (dev only, not CI) |
|
|
117
|
+
|
|
118
|
+
## Cache Optimization
|
|
119
|
+
|
|
120
|
+
| Strategy | Implementation |
|
|
121
|
+
|---|---|
|
|
122
|
+
| Layer ordering | Install CLI first (rarely changes), copy source last |
|
|
123
|
+
| npm cache (GitHub Actions) | `actions/cache@v4` with `~/.npm` path, key on `package-lock.json` hash |
|
|
124
|
+
| Dependency install | `npm ci --omit=dev` for production builds |
|
|
125
|
+
| Multi-stage build | Stage 1: build + lint + scan; Stage 2: runtime with `sf` only |
|
|
126
|
+
|
|
127
|
+
## Best Practices
|
|
128
|
+
|
|
129
|
+
| Practice | Reason |
|
|
130
|
+
|---|---|
|
|
131
|
+
| Use `node:20-slim` + npm install | `salesforce/cli` images may lag; full control over base |
|
|
132
|
+
| Pin image versions (`node:20.19-slim`) | Reproducible builds |
|
|
133
|
+
| `--duration-days 1` for CI scratch orgs | Auto-cleanup if delete step fails |
|
|
134
|
+
| Always delete scratch orgs in `if: always()` | Prevent DevHub scratch org limit exhaustion |
|
|
135
|
+
| Store auth URLs / JWT keys as CI secrets | Never commit credentials |
|
|
136
|
+
| Run Code Analyzer in Docker | Consistent static analysis across machines |
|
|
137
|
+
| Multi-stage builds | Smaller final image; lint/scan in build stage only |
|
|
138
|
+
| Non-root container user | Security hardening for production |
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# Apex Enterprise Patterns (FFLIB) -- Reference
|
|
2
|
+
|
|
3
|
+
> Source: [fflib-apex-common](https://github.com/apex-enterprise-patterns/fflib-apex-common), [fflib.dev](https://fflib.dev/docs)
|
|
4
|
+
> Last verified: API v66.0, Spring '26 (2026-03-28)
|
|
5
|
+
|
|
6
|
+
## Layer Architecture
|
|
7
|
+
|
|
8
|
+
| Layer | Responsibility | Allowed Dependencies |
|
|
9
|
+
|---|---|---|
|
|
10
|
+
| **Selector** | All SOQL/SOSL queries for one SObject. No business logic. | None (data access only) |
|
|
11
|
+
| **Domain** | Single-object logic: validation, defaults, trigger handling. No cross-object ops, no direct SOQL. | Selector (same object) |
|
|
12
|
+
| **Service** | Multi-object orchestration, transaction control, business logic entry point. No direct SOQL/DML. | Domain, Selector, other Services, Unit of Work |
|
|
13
|
+
| **Unit of Work** | Transactional DML aggregation. Register ops, commit once. | None (passed into Service) |
|
|
14
|
+
| **Implementation** | Entry points: Controllers, Batch, Queueable, REST, Invocable. Minimal logic. | Service only |
|
|
15
|
+
|
|
16
|
+
**Call direction**: Implementation -> Service -> Domain / Selector. Never reverse.
|
|
17
|
+
|
|
18
|
+
## Class Naming Conventions
|
|
19
|
+
|
|
20
|
+
| Layer | Class Name | Interface Name | Example |
|
|
21
|
+
|---|---|---|---|
|
|
22
|
+
| Selector | `{Object}sSelector` | `I{Object}sSelector` | `AccountsSelector`, `IAccountsSelector` |
|
|
23
|
+
| Domain | `{Object}s` (plural) | `I{Object}s` | `Accounts`, `IAccounts` |
|
|
24
|
+
| Service | `{Object}sService` | `I{Object}sService` | `AccountsService`, `IAccountsService` |
|
|
25
|
+
| Unit of Work | (use `fflib_SObjectUnitOfWork`) | `fflib_ISObjectUnitOfWork` | -- |
|
|
26
|
+
| Trigger Handler | `{Object}sTriggerHandler` | -- | `AccountsTriggerHandler` |
|
|
27
|
+
|
|
28
|
+
Domain classes use **plural names** to emphasize bulk processing (e.g., `Opportunities`, not `Opportunity`).
|
|
29
|
+
|
|
30
|
+
## Application Factory Registration
|
|
31
|
+
|
|
32
|
+
| Factory | Constructor Argument | Maps To |
|
|
33
|
+
|---|---|---|
|
|
34
|
+
| `UnitOfWorkFactory` | `List<SObjectType>` (parent-first order) | `fflib_ISObjectUnitOfWork` |
|
|
35
|
+
| `ServiceFactory` | `Map<Type, Type>` (interface -> impl) | Service instances |
|
|
36
|
+
| `SelectorFactory` | `Map<SObjectType, Type>` (object -> selector class) | `fflib_ISObjectSelector` |
|
|
37
|
+
| `DomainFactory` | `Application.Selector` + `Map<SObjectType, Type>` | `fflib_ISObjectDomain` |
|
|
38
|
+
|
|
39
|
+
**UoW SObjectType order** matters -- parent objects first (respects DML dependency).
|
|
40
|
+
DomainFactory depends on SelectorFactory (domain construction queries via selector).
|
|
41
|
+
|
|
42
|
+
## Key Interfaces
|
|
43
|
+
|
|
44
|
+
### fflib_ISObjectSelector
|
|
45
|
+
|
|
46
|
+
| Method | Signature |
|
|
47
|
+
|---|---|
|
|
48
|
+
| `sObjectType` | `Schema.SObjectType sObjectType()` |
|
|
49
|
+
| `selectSObjectsById` | `List<SObject> selectSObjectsById(Set<Id> idSet)` |
|
|
50
|
+
|
|
51
|
+
### fflib_ISObjectDomain
|
|
52
|
+
|
|
53
|
+
| Method | Signature |
|
|
54
|
+
|---|---|
|
|
55
|
+
| `sObjectType` | `Schema.SObjectType sObjectType()` |
|
|
56
|
+
| `getRecords` | `List<SObject> getRecords()` |
|
|
57
|
+
|
|
58
|
+
### fflib_ISObjectUnitOfWork (key methods)
|
|
59
|
+
|
|
60
|
+
| Method | Signature |
|
|
61
|
+
|---|---|
|
|
62
|
+
| `registerNew` | `void registerNew(SObject record)` |
|
|
63
|
+
| `registerNew` | `void registerNew(SObject record, SObjectField relField, SObject parent)` |
|
|
64
|
+
| `registerDirty` | `void registerDirty(SObject record)` |
|
|
65
|
+
| `registerDirty` | `void registerDirty(SObject record, List<SObjectField> dirtyFields)` |
|
|
66
|
+
| `registerDeleted` | `void registerDeleted(SObject record)` |
|
|
67
|
+
| `registerRelationship` | `void registerRelationship(SObject record, SObjectField relField, SObject relTo)` |
|
|
68
|
+
| `registerUpsert` | `void registerUpsert(SObject record)` |
|
|
69
|
+
| `commitWork` | `void commitWork()` |
|
|
70
|
+
|
|
71
|
+
All `register*` methods also accept `List<SObject>` overloads.
|
|
72
|
+
|
|
73
|
+
## Base Class Methods to Override
|
|
74
|
+
|
|
75
|
+
### fflib_SObjectSelector (abstract)
|
|
76
|
+
|
|
77
|
+
| Type | Method |
|
|
78
|
+
|---|---|
|
|
79
|
+
| **abstract** | `Schema.SObjectType getSObjectType()` |
|
|
80
|
+
| **abstract** | `List<Schema.SObjectField> getSObjectFieldList()` |
|
|
81
|
+
| virtual | `String getOrderBy()` |
|
|
82
|
+
| virtual | `List<Schema.FieldSet> getSObjectFieldSetList()` |
|
|
83
|
+
|
|
84
|
+
Constructor options: `(Boolean includeFieldSetFields, Boolean enforceCRUD, Boolean enforceFLS)`.
|
|
85
|
+
|
|
86
|
+
### fflib_SObjectDomain (virtual trigger handlers)
|
|
87
|
+
|
|
88
|
+
| Phase | Method |
|
|
89
|
+
|---|---|
|
|
90
|
+
| Defaults | `void onApplyDefaults()` |
|
|
91
|
+
| Before | `void onBeforeInsert()` |
|
|
92
|
+
| Before | `void onBeforeUpdate(Map<Id,SObject> existing)` |
|
|
93
|
+
| Before | `void onBeforeDelete()` |
|
|
94
|
+
| Validation | `void onValidate()` |
|
|
95
|
+
| Validation | `void onValidate(Map<Id,SObject> existing)` |
|
|
96
|
+
| After | `void onAfterInsert()` |
|
|
97
|
+
| After | `void onAfterUpdate(Map<Id,SObject> existing)` |
|
|
98
|
+
| After | `void onAfterDelete()` |
|
|
99
|
+
| After | `void onAfterUndelete()` |
|
|
100
|
+
|
|
101
|
+
Constructor: `fflib_SObjectDomain(List<SObject> records)`.
|
|
102
|
+
|
|
103
|
+
## Dependency Rules (Strict)
|
|
104
|
+
|
|
105
|
+
| Rule | Description |
|
|
106
|
+
|---|---|
|
|
107
|
+
| Selectors never call Services or Domains | Query-only layer |
|
|
108
|
+
| Domains never call Services | Prevents circular dependencies |
|
|
109
|
+
| Services own the Unit of Work | Create UoW in Service, pass to Domain if needed |
|
|
110
|
+
| `Application.Domain` factory depends on `Application.Selector` | Domain construction queries records via Selector |
|
|
111
|
+
| No direct DML in Service or Domain | All DML through Unit of Work |
|
|
112
|
+
| No direct SOQL in Service | All queries through Selectors |
|
|
113
|
+
|
|
114
|
+
## Testing with Mocks
|
|
115
|
+
|
|
116
|
+
| Factory | setMock Signature |
|
|
117
|
+
|---|---|
|
|
118
|
+
| `Application.Selector` | `.setMock(SObjectType, fflib_ISObjectSelector)` |
|
|
119
|
+
| `Application.Domain` | `.setMock(SObjectType, fflib_ISObjectDomain)` |
|
|
120
|
+
| `Application.Service` | `.setMock(Type interfaceType, Object mockImpl)` |
|
|
121
|
+
|
|
122
|
+
Mocking via `fflib-apex-mocks` eliminates DML/SOQL in unit tests.
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
<!-- Source: https://developer.salesforce.com/docs/atlas.en-us.communities_dev.meta/communities_dev/communities_dev_intro.htm -->
|
|
2
|
+
<!-- Last verified: API v66.0 — 2026-03-29 -->
|
|
3
|
+
<!-- WARNING: Web fetch of canonical URL failed (LWR client-side rendering). Facts below extracted from sf-experience-cloud skill. -->
|
|
4
|
+
|
|
5
|
+
# Experience Cloud — Reference
|
|
6
|
+
|
|
7
|
+
## Site Types
|
|
8
|
+
|
|
9
|
+
| Site Type | Use Case | Key Features |
|
|
10
|
+
|-----------|----------|-------------|
|
|
11
|
+
| Customer Service | Self-service portal | Knowledge, Cases, Accounts |
|
|
12
|
+
| Partner Central | Channel partner management | Leads, Opportunities, deal registration |
|
|
13
|
+
| Build Your Own (LWR) | Custom branded site | Full customization, LWR framework |
|
|
14
|
+
| Help Center | Public knowledge base | Knowledge articles, search, no login required |
|
|
15
|
+
| Microsite | Event/campaign landing page | Lightweight, specific purpose |
|
|
16
|
+
|
|
17
|
+
## LWR vs Aura-Based Sites
|
|
18
|
+
|
|
19
|
+
| Aspect | LWR (Lightning Web Runtime) | Aura-Based |
|
|
20
|
+
|--------|----------------------------|------------|
|
|
21
|
+
| Performance | Faster, modern rendering | Heavier, legacy framework |
|
|
22
|
+
| Components | LWC only | Aura + LWC |
|
|
23
|
+
| SEO | Better (server-side rendering) | Limited |
|
|
24
|
+
| Theming | CSS custom properties, SLDS | Theme panel, limited CSS |
|
|
25
|
+
| CDN caching | Enabled by default | — |
|
|
26
|
+
| Light DOM | Supported (`static renderMode = 'light'`) | Not supported |
|
|
27
|
+
| Recommendation | New sites | Legacy/migration only |
|
|
28
|
+
|
|
29
|
+
## User Types and Licensing
|
|
30
|
+
|
|
31
|
+
| User Type | License | Access Level |
|
|
32
|
+
|-----------|---------|-------------|
|
|
33
|
+
| Customer Community | Community | Read/create own records only |
|
|
34
|
+
| Customer Community Plus | Community Plus | Read/create + sharing rules |
|
|
35
|
+
| Partner Community | Partner Community | Leads, Opps, deal registration |
|
|
36
|
+
| Guest User | None (unauthenticated) | Public read access only |
|
|
37
|
+
|
|
38
|
+
### External User Hierarchy (top = most access)
|
|
39
|
+
|
|
40
|
+
| Level | Access Model |
|
|
41
|
+
|-------|-------------|
|
|
42
|
+
| Internal Users | Full org access (role hierarchy) |
|
|
43
|
+
| Partner Users | Account-based + sharing rules |
|
|
44
|
+
| Customer Plus Users | Account-based + sharing rules |
|
|
45
|
+
| Customer Users | Own records only (no sharing rules) |
|
|
46
|
+
| Guest Users | Public records only (no login) |
|
|
47
|
+
|
|
48
|
+
## Guest User Security Rules
|
|
49
|
+
|
|
50
|
+
| Rule | Detail |
|
|
51
|
+
|------|--------|
|
|
52
|
+
| NEVER grant Create, Edit, or Delete | On ANY object for guest profile |
|
|
53
|
+
| ONLY grant Read | On objects explicitly needed for public display |
|
|
54
|
+
| NEVER grant View All Data / Modify All Data | Critical security violation |
|
|
55
|
+
| NEVER grant API access | To guest users |
|
|
56
|
+
| OWD setting | Must NOT be "Public Read/Write" for guest-accessible objects |
|
|
57
|
+
| Sharing rules | Use Guest User Sharing Rules (criteria-based) to control visible records |
|
|
58
|
+
| Apex controllers | MUST use `with sharing` (enforces record-level sharing) |
|
|
59
|
+
| SOQL in controllers | Use `WITH USER_MODE` (enforces CRUD/FLS) |
|
|
60
|
+
| `with sharing` alone | Necessary but NOT sufficient; Guest User Sharing Rules must also be configured |
|
|
61
|
+
|
|
62
|
+
## Sharing Model for External Users
|
|
63
|
+
|
|
64
|
+
| Mechanism | How It Works |
|
|
65
|
+
|-----------|-------------|
|
|
66
|
+
| Account-Based Sharing | External User -> Contact -> Account -> shared records |
|
|
67
|
+
| Sharing Sets | Grant access based on user's Account or Contact (admin config) |
|
|
68
|
+
| All Customer Portal Users | Auto share group for all community users |
|
|
69
|
+
| All Partner Users | Auto share group for all partner users |
|
|
70
|
+
| Apex Managed Sharing | `CustomObject__Share` with `RowCause = Manual` |
|
|
71
|
+
|
|
72
|
+
## LWC Targets for Experience Cloud
|
|
73
|
+
|
|
74
|
+
| Target | Purpose |
|
|
75
|
+
|--------|---------|
|
|
76
|
+
| `lightningCommunity__Page` | Experience Cloud page |
|
|
77
|
+
| `lightningCommunity__Default` | Default community context |
|
|
78
|
+
| `lightningCommunity__Page_Layout` | Page layout region |
|
|
79
|
+
|
|
80
|
+
### Community Context Imports
|
|
81
|
+
|
|
82
|
+
| Import | Module | Returns |
|
|
83
|
+
|--------|--------|---------|
|
|
84
|
+
| `communityId` | `@salesforce/community/Id` | Current community/site ID |
|
|
85
|
+
| `communityBasePath` | `@salesforce/community/basePath` | Site base URL path |
|
|
86
|
+
| `isGuest` | `@salesforce/user/isGuest` | Boolean: guest user check |
|
|
87
|
+
| `userId` | `@salesforce/user/Id` | Current user ID |
|
|
88
|
+
|
|
89
|
+
## Navigation in Experience Cloud
|
|
90
|
+
|
|
91
|
+
| Navigation Type | PageReference `type` | Key Attribute |
|
|
92
|
+
|----------------|---------------------|---------------|
|
|
93
|
+
| Record page | `standard__recordPage` | `recordId`, `actionName: 'view'` |
|
|
94
|
+
| Named community page | `comm__namedPage` | `name` (e.g., `'Home'`, `'Contact_Support'`) |
|
|
95
|
+
| External URL | `standard__webPage` | `url` |
|
|
96
|
+
|
|
97
|
+
## CMS Content
|
|
98
|
+
|
|
99
|
+
| Concept | Detail |
|
|
100
|
+
|---------|--------|
|
|
101
|
+
| CMS Workspace | Manages content types and items |
|
|
102
|
+
| Publishing | Content items published to Channels (Sites) |
|
|
103
|
+
| LWC API | `getContent` from `experience/cmsDeliveryApi` |
|
|
104
|
+
| Wire params | `channelId`, `contentKeyOrId` |
|
|
105
|
+
| Content fields | `data.title.value`, `data.body.value` |
|
|
106
|
+
|
|
107
|
+
## Deployment Metadata Types
|
|
108
|
+
|
|
109
|
+
| Metadata Type | Directory | Description |
|
|
110
|
+
|---------------|-----------|-------------|
|
|
111
|
+
| Network | `networks/` | Site definition (template, features, branding) |
|
|
112
|
+
| ExperienceBundle | `experiences/` | Pages, routes, views, themes |
|
|
113
|
+
| CustomSite | `sites/` | Site URL configuration |
|
|
114
|
+
| NavigationMenu | `navigationMenus/` | Site navigation structure |
|
|
115
|
+
| CommunityTemplateDefinition | `communityTemplateDefinitions/` | Template metadata |
|
|
116
|
+
|
|
117
|
+
### Deployment Commands
|
|
118
|
+
|
|
119
|
+
| Step | Command |
|
|
120
|
+
|------|---------|
|
|
121
|
+
| Retrieve Network | `sf project retrieve start --metadata Network:My_Community` |
|
|
122
|
+
| Retrieve ExperienceBundle | `sf project retrieve start --metadata ExperienceBundle:My_Community1` |
|
|
123
|
+
| Deploy experiences | `sf project deploy start --source-dir force-app/main/default/experiences` |
|
|
124
|
+
| Deploy networks | `sf project deploy start --source-dir force-app/main/default/networks` |
|
|
125
|
+
| Publish site | Via Experience Builder UI or `ConnectApi.Communities.publishCommunity(null, communityId)` in Apex |
|
|
126
|
+
|
|
127
|
+
**Note:** `sf community publish` CLI command was removed in SF CLI v2. Publish via UI or Apex only.
|
|
128
|
+
|
|
129
|
+
**Deploy order:** Network -> ExperienceBundle -> NavigationMenu -> dependent components (LWC, Apex, objects) -> Publish -> verify guest profile -> test with community user login.
|
|
130
|
+
|
|
131
|
+
## Performance, Auth, and SEO
|
|
132
|
+
|
|
133
|
+
| Area | Item | Detail |
|
|
134
|
+
|------|------|--------|
|
|
135
|
+
| Performance | CDN caching | Enabled by default (LWR sites) |
|
|
136
|
+
| Performance | Lazy loading | `loading="lazy"` on images |
|
|
137
|
+
| Performance | Apex caching | `@AuraEnabled(cacheable=true)` for read-only data |
|
|
138
|
+
| Auth | Custom Login Page | Settings > Login & Registration > Login Page Type |
|
|
139
|
+
| Auth | Self-Registration | Custom `Auth.RegistrationHandler` implementation |
|
|
140
|
+
| Auth | Social Login | Google, Facebook, Apple, LinkedIn out-of-box; custom via Auth Provider |
|
|
141
|
+
| SEO (LWR only) | Sitemap | Settings > SEO > Sitemap |
|
|
142
|
+
| SEO (LWR only) | Semantic URLs | `/orders/12345` not `/s/detail/a01xx...` |
|
|
143
|
+
| SEO (LWR only) | Multi-language | `/en/orders`, `/es/orders`; guest language from `Accept-Language` header |
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# Flow Patterns — Reference
|
|
2
|
+
|
|
3
|
+
> Source: <https://architect.salesforce.com/docs/architect/decision-guides/guide/record-triggered>
|
|
4
|
+
> Source: <https://help.salesforce.com/s/articleView?id=platform.flow_considerations_limit_transaction.htm>
|
|
5
|
+
> Source: <https://help.salesforce.com/s/articleView?id=platform.flow_concepts_bulkification.htm>
|
|
6
|
+
> Last verified: API v66.0, Spring '26 (2026-03-28)
|
|
7
|
+
|
|
8
|
+
## Flow Types
|
|
9
|
+
|
|
10
|
+
| Type | Trigger | Context | Key Constraints |
|
|
11
|
+
|---|---|---|---|
|
|
12
|
+
| **Screen Flow** | User interaction | Runs in user context | Pauses transaction at each screen element |
|
|
13
|
+
| **Record-Triggered (Before-Save)** | Record create/update | Same transaction, before commit | Assignment, Decision, Get Records, Loop only; no DML elements |
|
|
14
|
+
| **Record-Triggered (After-Save)** | Record create/update/delete | Same transaction, after commit | Full element set; shares governor limits with before-save |
|
|
15
|
+
| **Record-Triggered (Async)** | Record create/update | Separate transaction | Runs outside original transaction; own governor limits |
|
|
16
|
+
| **Record-Triggered (Scheduled Path)** | Record field date/time | Separate transaction (batched) | Evaluates hours/days/minutes offset from a date field |
|
|
17
|
+
| **Schedule-Triggered** | Cron schedule | Automated Process User | Runs as system; batch-processes matched records |
|
|
18
|
+
| **Platform Event-Triggered** | Platform Event message | Automated Process User | Subscribes to event channel; own transaction per batch |
|
|
19
|
+
| **Autolaunched (No Trigger)** | Apex, REST API, Process, button | Caller's context | Shares caller's transaction and governor limits |
|
|
20
|
+
|
|
21
|
+
## Per-Transaction Limits (Shared with Apex)
|
|
22
|
+
|
|
23
|
+
Flows execute under standard Apex governor limits. These are **per-transaction**, shared across all Flows and Apex in the same transaction.
|
|
24
|
+
|
|
25
|
+
| Resource | Limit |
|
|
26
|
+
|---|---|
|
|
27
|
+
| SOQL queries | 100 (sync) / 200 (async) |
|
|
28
|
+
| Records retrieved by SOQL | 50,000 |
|
|
29
|
+
| DML statements | 150 |
|
|
30
|
+
| Records processed by DML | 10,000 |
|
|
31
|
+
| CPU time | 10,000 ms (sync) / 60,000 ms (async) |
|
|
32
|
+
| Heap size | 6 MB (sync) / 12 MB (async) |
|
|
33
|
+
| Callouts | 100 |
|
|
34
|
+
| Executed flow elements per interview | No limit (API v57.0+); 2,000 (API v56.0 and earlier) |
|
|
35
|
+
| Duplicate updates to same record in one batch | 12 |
|
|
36
|
+
|
|
37
|
+
## General Org Limits
|
|
38
|
+
|
|
39
|
+
| Resource | Limit |
|
|
40
|
+
|---|---|
|
|
41
|
+
| Flow versions per flow | 50 |
|
|
42
|
+
| Active flows (Professional/Essentials editions) | 5 |
|
|
43
|
+
| Paused flow interviews per org | 50,000 (removed in Winter '24+) |
|
|
44
|
+
|
|
45
|
+
## Transaction Boundaries
|
|
46
|
+
|
|
47
|
+
Flows break into a **new transaction** at these elements (resetting governor limits):
|
|
48
|
+
|
|
49
|
+
- Screen elements
|
|
50
|
+
- Scheduled Paths
|
|
51
|
+
- Wait (Conditions / Amount of Time / Until Date)
|
|
52
|
+
- Run Asynchronously path
|
|
53
|
+
|
|
54
|
+
## Bulkification Rules
|
|
55
|
+
|
|
56
|
+
Record-triggered flows auto-bulkify: when a batch of records fires the trigger, the runtime groups interviews and consolidates SOQL/DML where possible. Manual best practices:
|
|
57
|
+
|
|
58
|
+
| Rule | Detail |
|
|
59
|
+
|---|---|
|
|
60
|
+
| **Never put SOQL inside a loop** | Get Records in a loop consumes 1 SOQL query per iteration; hits 100-query limit fast |
|
|
61
|
+
| **Never put DML inside a loop** | Create/Update/Delete Records in a loop consumes 1 DML per iteration; hits 150-DML limit fast |
|
|
62
|
+
| **Use collection variables** | Accumulate records in a collection inside the loop; perform single DML after the loop |
|
|
63
|
+
| **Filter early** | Apply entry conditions and Get Records filters to minimize records processed |
|
|
64
|
+
| **Before-save for same-record updates** | Avoids a second DML operation; most performant path for field updates on triggering record |
|
|
65
|
+
|
|
66
|
+
## Error Handling Patterns
|
|
67
|
+
|
|
68
|
+
| Pattern | How |
|
|
69
|
+
|---|---|
|
|
70
|
+
| **Fault path (per element)** | Connect a Fault Connector from any DML/callout element to a custom error handler |
|
|
71
|
+
| **Fault email** | Configure fault paths to send admin email with `{!$Flow.FaultMessage}` and `{!$Flow.CurrentDateTime}` |
|
|
72
|
+
| **Default fault behavior** | Without explicit fault path: rolls back transaction, shows unhandled-fault email to admin |
|
|
73
|
+
| **Screen flow fault** | Display `{!$Flow.FaultMessage}` on a Screen element so the user sees the error |
|
|
74
|
+
| **Rollback scope** | A fault on any after-save DML rolls back the entire transaction including before-save changes |
|
|
75
|
+
|
|
76
|
+
## Flow vs Apex — Decision Matrix
|
|
77
|
+
|
|
78
|
+
Based on Salesforce Architect decision guide using **automation density** as the heuristic.
|
|
79
|
+
|
|
80
|
+
| Density | Automations per Object | Batch Size | Downstream DML Ops | Recommended |
|
|
81
|
+
|---|---|---|---|---|
|
|
82
|
+
| **Low** | < 15 | 1–200 records | 0–1 | Record-Triggered Flow |
|
|
83
|
+
| **Medium** | 15–30 | Moderate batch | 2–4 | Hybrid: Flow + Invocable Apex |
|
|
84
|
+
| **High** | > 30 | 2,000–10,000+ | 5+ | Apex Trigger Framework |
|
|
85
|
+
|
|
86
|
+
### Use Flow When
|
|
87
|
+
|
|
88
|
+
- Simple to moderate field updates, notifications, record creation
|
|
89
|
+
- Scheduled processing relative to a date field (unique Flow strength)
|
|
90
|
+
- Email alerts on record changes
|
|
91
|
+
- Admin-maintainable logic without developer dependency
|
|
92
|
+
|
|
93
|
+
### Use Apex When
|
|
94
|
+
|
|
95
|
+
- Large data volumes or high-performance bulk processing
|
|
96
|
+
- Complex data structures (Maps, Sets, nested collections)
|
|
97
|
+
- Transaction control (savepoints, partial-success DML via `Database.update(records, false)`)
|
|
98
|
+
- After-undelete context (not supported in Flow)
|
|
99
|
+
- Recursive or self-referencing logic
|
|
100
|
+
|
|
101
|
+
### Hybrid Pattern (Invocable Apex)
|
|
102
|
+
|
|
103
|
+
- Flow handles entry criteria, routing, and orchestration
|
|
104
|
+
- `@InvocableMethod` Apex handles compute-heavy operations
|
|
105
|
+
- Invocable Apex only available in **after-save** context (not before-save)
|
|
106
|
+
- Maintains visibility in Flow Trigger Explorer
|
|
107
|
+
|
|
108
|
+
## Key Principles
|
|
109
|
+
|
|
110
|
+
1. **One automation entry point per object** — avoid mixing Flow triggers and Apex triggers on the same object.
|
|
111
|
+
2. **Before-save for same-record changes** — avoids extra DML, most performant path.
|
|
112
|
+
3. **Avoid mega-flows** — split into focused, well-conditioned flows rather than one monolith.
|
|
113
|
+
4. **Cascading automation shares limits** — Apex calling Flow (or vice versa) shares the same transaction governor limits.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Governor Limits — Salesforce Reference
|
|
2
|
+
|
|
3
|
+
> Last verified: API v66.0 (Spring '26)
|
|
4
|
+
> Source: <https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_gov_limits.htm>
|
|
5
|
+
|
|
6
|
+
Salesforce governor limits prevent any single Apex transaction from monopolizing shared infrastructure. Hitting a limit throws `System.LimitException`, which **cannot be caught** — it terminates the transaction immediately.
|
|
7
|
+
|
|
8
|
+
## Per-Transaction Limits
|
|
9
|
+
|
|
10
|
+
| Resource | Synchronous | @future / Queueable | Batch execute() | Batch start/finish |
|
|
11
|
+
|---|---|---|---|---|
|
|
12
|
+
| **SOQL queries** | 100 | 200 | 200 | 200 |
|
|
13
|
+
| **SOQL rows returned** | 50,000 | 50,000 | 50,000 | 50,000 |
|
|
14
|
+
| **SOQL rows for `FOR UPDATE`** | 200 | 200 | 200 | 200 |
|
|
15
|
+
| **DML statements** | 150 | 150 | 150 | 150 |
|
|
16
|
+
| **DML rows** | 10,000 | 10,000 | 10,000 | 10,000 |
|
|
17
|
+
| **CPU time (ms)** | 10,000 | 60,000 | 60,000 | 60,000 |
|
|
18
|
+
| **Heap size** | 6 MB | 12 MB | 12 MB | 12 MB |
|
|
19
|
+
| **Callouts** | 100 | 100 | 100 | 100 |
|
|
20
|
+
| **Total callout time (s)** | 120 | 120 | 120 | 120 |
|
|
21
|
+
| **Response size per callout** | 12 MB | 12 MB | 12 MB | 12 MB |
|
|
22
|
+
| **Email invocations** | 10 | 10 | 10 | 10 |
|
|
23
|
+
| **@future calls** | 50 | 0 (can't chain) | 50 | 50 |
|
|
24
|
+
| **Queueable jobs** | 50 | 1 (chain in prod) | 1 | 1 |
|
|
25
|
+
| **Push notifications** | 10 | 10 | 10 | 10 |
|
|
26
|
+
| **Query cursor timeout (s)** | 600 | 600 | 600 | 600 |
|
|
27
|
+
| **QueryLocator rows (Batch)** | N/A | N/A | 50M | N/A |
|
|
28
|
+
|
|
29
|
+
## SOQL Cursor Limits (Spring '26+, API v66.0)
|
|
30
|
+
|
|
31
|
+
| Constraint | Value |
|
|
32
|
+
|---|---|
|
|
33
|
+
| Max records per cursor | 50,000,000 |
|
|
34
|
+
| Cursor lifetime (sync) | 10 minutes |
|
|
35
|
+
| Cursor lifetime (async / Queueable) | 60 minutes |
|
|
36
|
+
| `fetch()` max page size | 2,000 rows per call |
|
|
37
|
+
| Max open cursors per transaction | 10 |
|
|
38
|
+
|
|
39
|
+
## Org-Wide Limits (Not Per-Transaction)
|
|
40
|
+
|
|
41
|
+
| Resource | Limit |
|
|
42
|
+
|---|---|
|
|
43
|
+
| Scheduled Apex jobs | 100 jobs scheduled at once |
|
|
44
|
+
| Concurrent long-running requests (>5s) | 10 |
|
|
45
|
+
| Batch jobs active (executing) | 5 concurrent; up to 100 in flex queue |
|
|
46
|
+
| Platform event publishes per hour | 250,000 |
|
|
47
|
+
|
|
48
|
+
## Limits Class — Programmatic Checking
|
|
49
|
+
|
|
50
|
+
| Method | Returns |
|
|
51
|
+
|---|---|
|
|
52
|
+
| `Limits.getQueries()` / `Limits.getLimitQueries()` | SOQL queries used / limit |
|
|
53
|
+
| `Limits.getQueryRows()` / `Limits.getLimitQueryRows()` | SOQL rows used / limit |
|
|
54
|
+
| `Limits.getDmlStatements()` / `Limits.getLimitDmlStatements()` | DML statements used / limit |
|
|
55
|
+
| `Limits.getDmlRows()` / `Limits.getLimitDmlRows()` | DML rows used / limit |
|
|
56
|
+
| `Limits.getCpuTime()` / `Limits.getLimitCpuTime()` | CPU ms used / limit |
|
|
57
|
+
| `Limits.getHeapSize()` / `Limits.getLimitHeapSize()` | Heap bytes used / limit |
|
|
58
|
+
| `Limits.getCallouts()` / `Limits.getLimitCallouts()` | Callouts used / limit |
|
|
59
|
+
| `Limits.getFutureCalls()` / `Limits.getLimitFutureCalls()` | @future calls used / limit |
|
|
60
|
+
| `Limits.getEmailInvocations()` / `Limits.getLimitEmailInvocations()` | Emails used / limit |
|
|
61
|
+
| `Limits.getQueueableJobs()` / `Limits.getLimitQueueableJobs()` | Queueable jobs used / limit |
|
|
62
|
+
|
|
63
|
+
## Key Anti-Patterns
|
|
64
|
+
|
|
65
|
+
| Anti-Pattern | Governor Impact | Correct Pattern |
|
|
66
|
+
|---|---|---|
|
|
67
|
+
| SOQL inside a loop | Exceeds 100 SOQL limit | Query once, store in Map |
|
|
68
|
+
| DML inside a loop | Exceeds 150 DML limit | Collect records, single DML after loop |
|
|
69
|
+
| Loading all fields when only ID needed | Heap exhaustion | SELECT only required fields |
|
|
70
|
+
| Nested loops for matching | CPU time exhaustion | Map/Set lookup (O(1) vs O(n)) |
|
|
71
|
+
| String concatenation in loops | Heap growth + CPU | List<String> + String.join() |
|
|
72
|
+
|
|
73
|
+
## Test.startTest() / Test.stopTest()
|
|
74
|
+
|
|
75
|
+
`Test.startTest()` resets all governor limit counters. Code between `startTest()` and `stopTest()` gets a fresh limit budget. Async work enqueued inside this block runs synchronously at `stopTest()`.
|
|
76
|
+
|
|
77
|
+
Always test triggers with 200 records (the standard trigger batch size) to validate bulk safety.
|