From 039893ecf8e473627dbc8d5cddba773d9fdec287 Mon Sep 17 00:00:00 2001 From: James Simone <16430727+jamessimone@users.noreply.github.com> Date: Tue, 28 Jul 2026 10:18:05 -0400 Subject: [PATCH] API version 67.0 updates to better represent system/user mode distinctions --- .../examples/xpath-examples.md | 2 +- .../references/xpath-patterns-security.md | 2 +- skills/platform-apex-generate/SKILL.md | 7 ++++--- skills/platform-apex-test-generate/SKILL.md | 4 ++++ skills/platform-apex-test-run/SKILL.md | 1 + 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/skills/dx-code-analyzer-custom-rule-create/examples/xpath-examples.md b/skills/dx-code-analyzer-custom-rule-create/examples/xpath-examples.md index c022b49..f76998a 100644 --- a/skills/dx-code-analyzer-custom-rule-create/examples/xpath-examples.md +++ b/skills/dx-code-analyzer-custom-rule-create/examples/xpath-examples.md @@ -183,7 +183,7 @@ public class ComplexLogic { ## Example 6: Class Without Explicit Sharing Declaration -**Problem:** Classes without sharing default to "without sharing" — security risk. +**Problem:** Classes in API versions 66.0 and below without sharing default to "without sharing" — security risk. If the API version is 67.0 or higher, the below example does not apply. **Sample violating code:** ```apex diff --git a/skills/dx-code-analyzer-custom-rule-create/references/xpath-patterns-security.md b/skills/dx-code-analyzer-custom-rule-create/references/xpath-patterns-security.md index efffa3a..755d92a 100644 --- a/skills/dx-code-analyzer-custom-rule-create/references/xpath-patterns-security.md +++ b/skills/dx-code-analyzer-custom-rule-create/references/xpath-patterns-security.md @@ -13,7 +13,7 @@ ] ``` -**AST evidence:** `ModifierNode` has `@WithSharing`, `@WithoutSharing`, `@InheritedSharing` — all `false()` means no sharing keyword declared (implicit without sharing). +**AST evidence:** `ModifierNode` has `@WithSharing`, `@WithoutSharing`, `@InheritedSharing` — all `false()` means no sharing keyword declared (implicit without sharing in API versions 66.0 and below. In API versions 67.0 and higher, the default changes to implicit with sharing). Added `@Nested = false()` to exclude inner classes (which inherit from parent). diff --git a/skills/platform-apex-generate/SKILL.md b/skills/platform-apex-generate/SKILL.md index 80c043e..adf19f4 100644 --- a/skills/platform-apex-generate/SKILL.md +++ b/skills/platform-apex-generate/SKILL.md @@ -117,6 +117,7 @@ If any constraint would be violated in generated code, **stop and explain the pr - `SELECT *` does not exist in SOQL -- always specify the exact fields needed - Apply `LIMIT` clauses to bound result sets; use `ORDER BY` for deterministic results - When querying Custom Metadata Types (objects ending with `__mdt`), do NOT use SOQL — use the built-in methods (`{CustomMdt__mdt}.getAll().values()`, `getInstance()`, etc.) +- Queries executed in `without sharing` keyword classes with API versions 67.0 and up will throw when the running user does not have the proper field or object-level security. If API versions are being updated, ensure queries are safeguarded properly. Only by passing the `System.AccessLevel.SYSTEM_MODE` class to queries, or by using the `WITH SYSTEM_MODE` modifier after a query's `WHERE` clause will ensure backwards compatibility ### Caching @@ -126,7 +127,7 @@ If any constraint would be violated in generated code, **stop and explain the pr ### Security - Default to `with sharing`; document justification for `without sharing` or `inherited sharing` -- `WITH USER_MODE` in SOQL and `AccessLevel.USER_MODE` for `Database` DML for CRUD/FLS enforcement +- `WITH USER_MODE` in SOQL and `AccessLevel.USER_MODE` for `Database` DML for CRUD/FLS enforcement — these are the defaults for _all_ Apex classes with API versions of 67.0 or higher - Validate dynamic field/operator names via allowlist or `Schema.describe` - Named Credentials for all external credentials/API keys - `AuraHandledException` for `@AuraEnabled` user-facing errors (no internal details) @@ -153,7 +154,7 @@ Before finalizing, verify: CRUD/FLS enforced (SOQL + DML) · explicit sharing ke - Add guard clauses for null/empty inputs at the top of every public method; match style to context: `return` early in private/trigger-handler methods, `throw` exceptions in public APIs, `record.addError()` in validation services - Return empty collections instead of `null` - Use safe navigation (`?.`) for chained property access -- Never dereference `map.get(key)` inline unless presence is guaranteed; use `containsKey`, assignment+null check, or safe navigation first +- Never dereference `map.get(key)` inline unless presence is guaranteed; use `containsKey`, assignment + null check, or safe navigation first - Use null coalescing (`??`) for default values - Prefer `String.isBlank(value)` over manual checks like `value == null || value.trim().isEmpty()` @@ -220,7 +221,7 @@ Method-level format: ### Code Structure & Architecture - Single responsibility per class; max 500 lines -- split when exceeded -- Return Early: validate preconditions at method top, return/throw immediately +- Return early: validate preconditions at method top, return/throw immediately - Extract private helpers for methods over ~40 lines - Use Dependency Injection (constructor/method params) for testability - Prefer composition and narrow interfaces over deep inheritance; extend via new implementations, not modifications diff --git a/skills/platform-apex-test-generate/SKILL.md b/skills/platform-apex-test-generate/SKILL.md index eadf964..07a5063 100644 --- a/skills/platform-apex-test-generate/SKILL.md +++ b/skills/platform-apex-test-generate/SKILL.md @@ -189,6 +189,10 @@ Deliverables per test class: - `{ClassName}Test.cls` + `{ClassName}Test.cls-meta.xml` (match API version of class under test; default `66.0`) - `TestDataFactory.cls` + `TestDataFactory.cls-meta.xml` (if not already present) +## API version considerations + +Apex running in API versions 66.0 and below defaults to using the `without sharing` keyword when not explicitly specified and runs in system mode by default; Apex running in API versions 67.0 and higher defaults to running in user mode, which means that upgrading API versions to something that crosses the 67.0 boundary can cause downstream test failures without code having explicitly changed. This is especially true in test classes, where it's rare for the `sharing` keywords to have been declared at all. Whenever API versions are upgraded across this critical boundary, additional uplift may be necessary to ensure tests are properly passing. + ## Reference Files Load on demand for detailed patterns: diff --git a/skills/platform-apex-test-run/SKILL.md b/skills/platform-apex-test-run/SKILL.md index c17c1d7..bb26472 100644 --- a/skills/platform-apex-test-run/SKILL.md +++ b/skills/platform-apex-test-run/SKILL.md @@ -91,6 +91,7 @@ Cover: | "Uncommitted work pending" error in callout test | DML and HTTP callouts cannot be mixed in the same test context without `Test.startTest()` wrapping | | Mock not taking effect in test | Ensure `Test.setMock()` is called before the code that makes the callout | | `@TestSetup` data missing in test method | `@TestSetup` data is committed per test method — re-query it; do not store in static variables | +| API version 67.0 and higher without necessary access level checks | Ensuring user running test has the proper field and object-level permissions when performing DML or querying | ---