From d4bfd686c2c979da502d6b483d1c213d6c7aba2d Mon Sep 17 00:00:00 2001 From: anatolii Date: Sat, 1 Aug 2026 16:23:35 +0300 Subject: [PATCH] replace SECURITY_ENFORCED with USER_MODE across SOQL/Apex skill examples --- .../assets/apex-controller/LwcController.cls | 12 ++++---- .../references/component-patterns.md | 8 ++--- .../references/lwc-best-practices.md | 4 +-- .../references/mocking-patterns.md | 2 +- skills/platform-soql-query/README.md | 2 +- .../assets/bulkified-query-pattern.cls | 10 +++---- .../assets/optimization-patterns.soql | 14 ++++----- .../assets/selector-class.cls | 10 +++---- .../references/query-optimization.md | 2 +- .../references/selector-patterns.md | 30 +++++++++---------- .../references/soql-reference.md | 10 +++---- 11 files changed, 52 insertions(+), 52 deletions(-) diff --git a/skills/experience-lwc-generate/assets/apex-controller/LwcController.cls b/skills/experience-lwc-generate/assets/apex-controller/LwcController.cls index 9921215..22f25e9 100644 --- a/skills/experience-lwc-generate/assets/apex-controller/LwcController.cls +++ b/skills/experience-lwc-generate/assets/apex-controller/LwcController.cls @@ -37,7 +37,7 @@ public with sharing class LwcController { SELECT Id, Name, Industry, AnnualRevenue, Phone, CreatedDate FROM Account WHERE Name LIKE :searchKey - WITH SECURITY_ENFORCED + WITH USER_MODE ORDER BY Name LIMIT :recordLimit ]; @@ -57,7 +57,7 @@ public with sharing class LwcController { (SELECT Id, FirstName, LastName, Email FROM Contacts LIMIT 5) FROM Account WHERE Id = :accountId - WITH SECURITY_ENFORCED + WITH USER_MODE LIMIT 1 ]; @@ -146,7 +146,7 @@ public with sharing class LwcController { List existing = [ SELECT Id FROM Account WHERE Id = :accountId - WITH SECURITY_ENFORCED + WITH USER_MODE LIMIT 1 ]; @@ -201,7 +201,7 @@ public with sharing class LwcController { List accountsToDelete = [ SELECT Id FROM Account WHERE Id IN :recordIds - WITH SECURITY_ENFORCED + WITH USER_MODE ]; if (accountsToDelete.size() != recordIds.size()) { @@ -280,14 +280,14 @@ public with sharing class LwcController { // Build dynamic query String query = 'SELECT Id, Name, Industry, AnnualRevenue, Phone, CreatedDate ' + 'FROM Account ' + - 'WITH SECURITY_ENFORCED ' + + 'WITH USER_MODE ' + 'ORDER BY ' + sortField + ' ' + sortDir + ' NULLS LAST ' + 'LIMIT :recordLimit OFFSET :recordOffset'; List records = Database.query(query); // Get total count - Integer totalCount = [SELECT COUNT() FROM Account WITH SECURITY_ENFORCED]; + Integer totalCount = [SELECT COUNT() FROM Account WITH USER_MODE]; return new PagedResult(records, totalCount); } catch (Exception e) { diff --git a/skills/experience-lwc-generate/references/component-patterns.md b/skills/experience-lwc-generate/references/component-patterns.md index b1d3a6b..345365a 100644 --- a/skills/experience-lwc-generate/references/component-patterns.md +++ b/skills/experience-lwc-generate/references/component-patterns.md @@ -138,7 +138,7 @@ public static List getAccounts(String searchTerm) { SELECT Id, Name, Industry FROM Account WHERE Name LIKE :searchKey - WITH SECURITY_ENFORCED + WITH USER_MODE LIMIT 50 ]; } @@ -1368,7 +1368,7 @@ public with sharing class LwcController { SELECT Id, Name, Industry, AnnualRevenue FROM Account WHERE Name LIKE :searchKey - WITH SECURITY_ENFORCED + WITH USER_MODE ORDER BY Name LIMIT 50 ]; @@ -1425,7 +1425,7 @@ public static void deleteAccounts(List accountIds) { List toDelete = [ SELECT Id FROM Account WHERE Id IN :accountIds - WITH SECURITY_ENFORCED + WITH USER_MODE ]; delete toDelete; @@ -1446,7 +1446,7 @@ public static List getContactsWithErrorHandling(Id accountId) { SELECT Id, Name, Email, Phone FROM Contact WHERE AccountId = :accountId - WITH SECURITY_ENFORCED + WITH USER_MODE ORDER BY Name LIMIT 100 ]; diff --git a/skills/experience-lwc-generate/references/lwc-best-practices.md b/skills/experience-lwc-generate/references/lwc-best-practices.md index 28b335c..4c95c1d 100644 --- a/skills/experience-lwc-generate/references/lwc-best-practices.md +++ b/skills/experience-lwc-generate/references/lwc-best-practices.md @@ -980,10 +980,10 @@ it('displays data', async () => { ### FLS Enforcement ```apex -// Always use SECURITY_ENFORCED or stripInaccessible +// Always use USER_MODE or stripInaccessible @AuraEnabled(cacheable=true) public static List getAccounts() { - return [SELECT Id, Name FROM Account WITH SECURITY_ENFORCED]; + return [SELECT Id, Name FROM Account WITH USER_MODE]; } // For DML operations diff --git a/skills/platform-apex-test-run/references/mocking-patterns.md b/skills/platform-apex-test-run/references/mocking-patterns.md index e4cc7c2..f580d32 100644 --- a/skills/platform-apex-test-run/references/mocking-patterns.md +++ b/skills/platform-apex-test-run/references/mocking-patterns.md @@ -435,7 +435,7 @@ public class AccountSelector { SELECT Id, Name, Industry FROM Account WHERE IsActive__c = true - WITH SECURITY_ENFORCED + WITH USER_MODE ]; } diff --git a/skills/platform-soql-query/README.md b/skills/platform-soql-query/README.md index 627a840..16ce460 100644 --- a/skills/platform-soql-query/README.md +++ b/skills/platform-soql-query/README.md @@ -7,7 +7,7 @@ Salesforce SOQL query generation, optimization, and analysis skill with 100-poin - **Natural Language to SOQL**: Convert requests into executable queries - **Query Optimization**: Improve selectivity, LIMIT usage, and field selection - **Relationship Queries**: Parent-child, child-parent, and polymorphic patterns -- **Security Guidance**: `WITH USER_MODE`, `WITH SECURITY_ENFORCED`, and Apex-safe usage +- **Security Guidance**: `WITH USER_MODE`, and Apex-safe usage - **100-Point Scoring**: Performance, correctness, security, and readability checks ## Quick Start diff --git a/skills/platform-soql-query/assets/bulkified-query-pattern.cls b/skills/platform-soql-query/assets/bulkified-query-pattern.cls index a3468f2..7ecef5e 100644 --- a/skills/platform-soql-query/assets/bulkified-query-pattern.cls +++ b/skills/platform-soql-query/assets/bulkified-query-pattern.cls @@ -47,7 +47,7 @@ public class BulkPatternExample { SELECT Id, Name FROM Account WHERE Id IN :accountIds - WITH SECURITY_ENFORCED + WITH USER_MODE ]); // Step 3: O(1) Map lookups @@ -86,7 +86,7 @@ public class GroupedChildPattern { SELECT Id, FirstName, LastName, Email, AccountId FROM Contact WHERE AccountId IN :accountIds - WITH SECURITY_ENFORCED + WITH USER_MODE ]) { contactsByAccount.get(c.AccountId).add(c); } @@ -137,7 +137,7 @@ public class MultiLevelLookupPattern { SELECT Id, Name, OwnerId, Owner.Name, Owner.Email FROM Account WHERE Id IN :accountIds - WITH SECURITY_ENFORCED + WITH USER_MODE ]); // Step 3: Use the data @@ -177,7 +177,7 @@ public class ConditionalQueryPattern { SELECT Id, Name, AnnualRevenue, Industry FROM Account WHERE Id IN :highValueAccountIds - WITH SECURITY_ENFORCED + WITH USER_MODE ]); // Step 3: Process only the high-value opportunities @@ -212,7 +212,7 @@ public class SharedQueryPattern { SELECT Id, Name, Industry, AnnualRevenue, OwnerId FROM Account WHERE Id IN :accountIds - WITH SECURITY_ENFORCED + WITH USER_MODE ]); } diff --git a/skills/platform-soql-query/assets/optimization-patterns.soql b/skills/platform-soql-query/assets/optimization-patterns.soql index c858848..053e8d8 100644 --- a/skills/platform-soql-query/assets/optimization-patterns.soql +++ b/skills/platform-soql-query/assets/optimization-patterns.soql @@ -184,19 +184,19 @@ SELECT Id, Status__c FROM Account WHERE Id = :accountId FOR UPDATE -- Adds overhead and can cause lock contention // ═══════════════════════════════════════════════════════════════════════════ -// SECURITY ENFORCEMENT +// SECURITY // ═══════════════════════════════════════════════════════════════════════════ --- ✅ Recommended: WITH SECURITY_ENFORCED +-- ✅ Recommended: WITH USER_MODE (API 54.0+) SELECT Id, Name, Phone FROM Account -WITH SECURITY_ENFORCED --- Throws exception if user lacks field access - --- Alternative: USER_MODE (API 54.0+) -SELECT Id, Name FROM Account WITH USER_MODE -- Respects sharing rules and FLS +-- Alternative: WITH SECURITY_ENFORCED (Removed in API version 67.0+, use USER_MODE instead) +SELECT Id, Name FROM Account +WITH SECURITY_ENFORCED +-- Throws exception if user lacks field access + -- For admin operations: SYSTEM_MODE SELECT Id, Name FROM Account WITH SYSTEM_MODE diff --git a/skills/platform-soql-query/assets/selector-class.cls b/skills/platform-soql-query/assets/selector-class.cls index 8f88fd0..ae19e64 100644 --- a/skills/platform-soql-query/assets/selector-class.cls +++ b/skills/platform-soql-query/assets/selector-class.cls @@ -83,7 +83,7 @@ public inherited sharing class ${OBJECT_NAME}Selector { SELECT Id, Name, OwnerId, CreatedDate, LastModifiedDate FROM ${OBJECT_NAME} WHERE Id IN :recordIds - WITH SECURITY_ENFORCED + WITH USER_MODE ]; } @@ -114,7 +114,7 @@ public inherited sharing class ${OBJECT_NAME}Selector { SELECT Id, Name, OwnerId, CreatedDate, LastModifiedDate FROM ${OBJECT_NAME} WHERE OwnerId = :ownerId - WITH SECURITY_ENFORCED + WITH USER_MODE ORDER BY LastModifiedDate DESC LIMIT 1000 ]; @@ -139,7 +139,7 @@ public inherited sharing class ${OBJECT_NAME}Selector { FROM ${OBJECT_NAME} WHERE CreatedDate >= :startDate AND CreatedDate <= :endDate - WITH SECURITY_ENFORCED + WITH USER_MODE ORDER BY CreatedDate DESC LIMIT 10000 ]; @@ -171,7 +171,7 @@ public inherited sharing class ${OBJECT_NAME}Selector { LIMIT 50) FROM ${OBJECT_NAME} WHERE Id IN :recordIds - WITH SECURITY_ENFORCED + WITH USER_MODE ]; } @@ -211,7 +211,7 @@ public inherited sharing class ${OBJECT_NAME}Selector { SELECT Id FROM ${OBJECT_NAME} WHERE Id = :recordId - WITH SECURITY_ENFORCED + WITH USER_MODE LIMIT 1 ]; return !results.isEmpty(); diff --git a/skills/platform-soql-query/references/query-optimization.md b/skills/platform-soql-query/references/query-optimization.md index 7a41e74..69e1c24 100644 --- a/skills/platform-soql-query/references/query-optimization.md +++ b/skills/platform-soql-query/references/query-optimization.md @@ -111,7 +111,7 @@ for (List accs : [SELECT Id, Name FROM Account]) { ## Security Patterns -### WITH SECURITY_ENFORCED +### WITH SECURITY_ENFORCED (Removed in API version 67.0+, use USER_MODE instead) ```sql -- Throws exception if user lacks FLS diff --git a/skills/platform-soql-query/references/selector-patterns.md b/skills/platform-soql-query/references/selector-patterns.md index e485949..7d7c687 100644 --- a/skills/platform-soql-query/references/selector-patterns.md +++ b/skills/platform-soql-query/references/selector-patterns.md @@ -41,7 +41,7 @@ public class AccountSelector { SELECT Id, Name, Industry FROM Account WHERE Id IN :accountIds - WITH SECURITY_ENFORCED + WITH USER_MODE ]; } } @@ -89,7 +89,7 @@ public inherited sharing class AccountSelector { SELECT Id, Name, Industry, AnnualRevenue, OwnerId FROM Account WHERE Id IN :accountIds - WITH SECURITY_ENFORCED + WITH USER_MODE ]; } @@ -101,7 +101,7 @@ public inherited sharing class AccountSelector { SELECT Id, Name, Industry, AnnualRevenue, OwnerId FROM Account WHERE OwnerId = :ownerId - WITH SECURITY_ENFORCED + WITH USER_MODE LIMIT 1000 ]; } @@ -118,7 +118,7 @@ public inherited sharing class AccountSelector { LIMIT 50) FROM Account WHERE Id IN :accountIds - WITH SECURITY_ENFORCED + WITH USER_MODE ]; } } @@ -207,7 +207,7 @@ public inherited sharing class OpportunitySelector { SELECT Id, Name, StageName, Amount, CloseDate, AccountId FROM Opportunity WHERE AccountId IN :accountIds - WITH SECURITY_ENFORCED + WITH USER_MODE ]; } @@ -402,7 +402,7 @@ public inherited sharing class BulkQueryHelper { SELECT Id, Name, Industry FROM Account WHERE Id IN :accountIds - WITH SECURITY_ENFORCED + WITH USER_MODE ]); } @@ -416,7 +416,7 @@ public inherited sharing class BulkQueryHelper { SELECT Id, FirstName, LastName, Email, AccountId FROM Contact WHERE AccountId IN :accountIds - WITH SECURITY_ENFORCED + WITH USER_MODE ]) { if (!contactsByAccount.containsKey(c.AccountId)) { contactsByAccount.put(c.AccountId, new List()); @@ -456,15 +456,15 @@ for (Opportunity opp : Trigger.new) { ## Best Practices Summary -| Practice | Benefit | -|----------|---------| +| Practice | Benefit | +|--------------------------------|---------| | Centralize in Selector classes | One place to update field lists | -| Use `WITH SECURITY_ENFORCED` | Automatic FLS enforcement | -| Return empty List, not null | Prevents NullPointerException | -| Use `inherited sharing` | Respects caller's sharing context | -| Make fields list a constant | Easy to update across queries | -| Add null/empty checks | Prevent unnecessary queries | -| Support mocking in tests | Faster tests, no database dependencies | +| Use `WITH USER_MODE` | Respects sharing rules and FLS | +| Return empty List, not null | Prevents NullPointerException | +| Use `inherited sharing` | Respects caller's sharing context | +| Make fields list a constant | Easy to update across queries | +| Add null/empty checks | Prevent unnecessary queries | +| Support mocking in tests | Faster tests, no database dependencies | --- diff --git a/skills/platform-soql-query/references/soql-reference.md b/skills/platform-soql-query/references/soql-reference.md index b19dd8c..d0cc191 100644 --- a/skills/platform-soql-query/references/soql-reference.md +++ b/skills/platform-soql-query/references/soql-reference.md @@ -165,11 +165,11 @@ SELECT Id, (SELECT Id FROM Children__r) FROM Parent__c ## WITH Clauses -| Clause | Description | -|--------|-------------| -| `WITH SECURITY_ENFORCED` | Enforce FLS (throws exception if no access) | -| `WITH USER_MODE` | Respect sharing and FLS | -| `WITH SYSTEM_MODE` | Bypass sharing rules | +| Clause | Description | +|--------|-----------------------------------------------------------------------------| +| `WITH SECURITY_ENFORCED` | Enforce FLS (throws exception if no access; removed in API version 67.0+) | +| `WITH USER_MODE` | Respect sharing and FLS | +| `WITH SYSTEM_MODE` | Bypass sharing rules | ---