Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
github avatar

Salesforce Apex Quality

  • 848 installs
  • 37.1k repo stars
  • Updated July 28, 2026
  • github/awesome-copilot

salesforce-apex-quality is an agent skill that enforces Apex bulk safety, sharing, CRUD/FLS, SOQL injection prevention, and PNB test coverage when reviewing or generating Salesforce code.

About

The salesforce-apex-quality skill applies guardrails when writing or reviewing Apex classes, trigger handlers, batch jobs, and test classes. Step one blocks SOQL and DML inside loops with refactor patterns that collect IDs and query or update once outside the loop. Step two requires explicit sharing declarations: with sharing, without sharing with justification, or inherited sharing. Step three enforces CRUD and FLS via Schema checks, WITH USER_MODE, or Database.query AccessLevel.USER_MODE on UI-callable code. Step four prevents SOQL injection with bind variables and field whitelists. Step five upgrades to modern Apex idioms such as safe navigation, null coalescing, and Assert.areEqual. Step six mandates Positive, Negative, and Bulk test paths with 200-251 records and meaningful assertions. Step seven enforces one trigger per object with handler-only trigger bodies.

  • Automatic fail on SOQL or DML inside for loops.
  • Requires explicit with sharing or documented without sharing.
  • CRUD/FLS enforcement for UI, REST, and InvocableMethod entry points.
  • PNB test checklist: positive, negative, and 200+ bulk paths.
  • Trigger architecture: one trigger per object, logic in handlers.

Salesforce Apex Quality by the numbers

  • 848 all-time installs (skills.sh)
  • +27 installs in the week ending Jul 28, 2026 (Skillselion tracking)
  • Ranked #163 of 1,382 Code Review & Quality skills by installs in the Skillselion catalog
  • Security screen: LOW risk (skills.sh audit)
  • Data as of Jul 28, 2026 (Skillselion catalog sync)
At a glance

salesforce-apex-quality capabilities & compatibility

Capabilities
soql/dml in loop detection · sharing model verification · crud/fls enforcement patterns · soql injection prevention · pnb test coverage checklist
Use cases
code review · security audit · testing
From the docs

What salesforce-apex-quality says it does

Apply these checks to every Apex class, trigger, and test file you write or review.
SKILL.md
npx skills add https://github.com/github/awesome-copilot --skill salesforce-apex-quality

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs848
repo stars37.1k
Security audit3 / 3 scanners passed
Last updatedJuly 28, 2026
Repositorygithub/awesome-copilot

Will my Apex classes, triggers, and tests pass governor limits, security checks, and deployment quality bars?

Review or generate Apex classes, triggers, and tests for governor limits, sharing, CRUD/FLS, SOQL injection, and PNB test coverage before Salesforce deployment.

Who is it for?

Salesforce developers reviewing or generating Apex, trigger handlers, and test classes before deployment.

Skip if: Skip for Salesforce Flow design, LWC UI work, or non-Apex platform configuration.

When should I use this skill?

User writes or reviews Apex classes, trigger handlers, batch jobs, or test classes for Salesforce.

What you get

Refactored or reviewed Apex with bulk-safe queries, declared sharing, enforced FLS, and complete positive-negative-bulk tests.

  • governor-limit scan results
  • security compliance notes
  • PNB test recommendations

Files

SKILL.mdMarkdownGitHub ↗

Salesforce Apex Quality Guardrails

Apply these checks to every Apex class, trigger, and test file you write or review.

Step 1 — Governor Limit Safety Check

Scan for these patterns before declaring any Apex file acceptable:

SOQL and DML in Loops — Automatic Fail

// ❌ NEVER — causes LimitException at scale
for (Account a : accounts) {
    List<Contact> contacts = [SELECT Id FROM Contact WHERE AccountId = :a.Id]; // SOQL in loop
    update a; // DML in loop
}

// ✅ ALWAYS — collect, then query/update once
Set<Id> accountIds = new Map<Id, Account>(accounts).keySet();
Map<Id, List<Contact>> contactsByAccount = new Map<Id, List<Contact>>();
for (Contact c : [SELECT Id, AccountId FROM Contact WHERE AccountId IN :accountIds]) {
    if (!contactsByAccount.containsKey(c.AccountId)) {
        contactsByAccount.put(c.AccountId, new List<Contact>());
    }
    contactsByAccount.get(c.AccountId).add(c);
}
update accounts; // DML once, outside the loop

Rule: if you see [SELECT or Database.query, insert, update, delete, upsert, merge inside a for loop body — stop and refactor before proceeding.

Step 2 — Sharing Model Verification

Every class must declare its sharing intent explicitly. Undeclared sharing inherits from the caller — unpredictable behaviour.

DeclarationWhen to use
public with sharing class FooDefault for all service, handler, selector, and controller classes
public without sharing class FooOnly when the class must run elevated (e.g. system-level logging, trigger bypass). Requires a code comment explaining why.
public inherited sharing class FooFramework entry points that should respect the caller's sharing context

If a class does not have one of these three declarations, add it before writing anything else.

Step 3 — CRUD / FLS Enforcement

Apex code that reads or writes records on behalf of a user must verify object and field access. The platform does not enforce FLS or CRUD automatically in Apex.

// Check before querying a field
if (!Schema.sObjectType.Contact.fields.Email.isAccessible()) {
    throw new System.NoAccessException();
}

// Or use WITH USER_MODE in SOQL (API 56.0+)
List<Contact> contacts = [SELECT Id, Email FROM Contact WHERE AccountId = :accId WITH USER_MODE];

// Or use Database.query with AccessLevel
List<Contact> contacts = Database.query('SELECT Id, Email FROM Contact', AccessLevel.USER_MODE);

Rule: any Apex method callable from a UI component, REST endpoint, or @InvocableMethod must enforce CRUD/FLS. Internal service methods called only from trusted contexts may use with sharing instead.

Step 4 — SOQL Injection Prevention

// ❌ NEVER — concatenates user input into SOQL string
String soql = 'SELECT Id FROM Account WHERE Name = \'' + userInput + '\'';

// ✅ ALWAYS — bind variable
String soql = [SELECT Id FROM Account WHERE Name = :userInput];

// ✅ For dynamic SOQL with user-controlled field names — validate against a whitelist
Set<String> allowedFields = new Set<String>{'Name', 'Industry', 'AnnualRevenue'};
if (!allowedFields.contains(userInput)) {
    throw new IllegalArgumentException('Field not permitted: ' + userInput);
}

Step 5 — Modern Apex Idioms

Prefer current language features (API 62.0 / Winter '25+):

Old patternModern replacement
if (obj != null) { x = obj.Field__c; }x = obj?.Field__c;
x = (y != null) ? y : defaultVal;x = y ?? defaultVal;
System.assertEquals(expected, actual)Assert.areEqual(expected, actual)
System.assert(condition)Assert.isTrue(condition)
[SELECT ... WHERE ...] with no sharing context[SELECT ... WHERE ... WITH USER_MODE]

Step 6 — PNB Test Coverage Checklist

Every feature must be tested across all three paths. Missing any one of these is a quality failure:

Positive Path

  • Expected input → expected output.
  • Assert the exact field values, record counts, or return values — not just that no exception was thrown.

Negative Path

  • Invalid input, null values, empty collections, and error conditions.
  • Assert that exceptions are thrown with the correct type and message.
  • Assert that no records were mutated when the operation should have failed cleanly.

Bulk Path

  • Insert/update/delete 200–251 records in a single test transaction.
  • Assert that all records processed correctly — no partial failures from governor limits.
  • Use Test.startTest() / Test.stopTest() to isolate governor limit counters for async work.

Test Class Rules

@isTest(SeeAllData=false)   // Required — no exceptions without a documented reason
private class AccountServiceTest {

    @TestSetup
    static void makeData() {
        // Create all test data here — use a factory if one exists in the project
    }

    @isTest
    static void givenValidInput_whenProcessAccounts_thenFieldsUpdated() {
        // Positive path
        List<Account> accounts = [SELECT Id FROM Account LIMIT 10];
        Test.startTest();
        AccountService.processAccounts(accounts);
        Test.stopTest();
        // Assert meaningful outcomes — not just no exception
        List<Account> updated = [SELECT Status__c FROM Account WHERE Id IN :accounts];
        Assert.areEqual('Processed', updated[0].Status__c, 'Status should be Processed');
    }
}

Step 7 — Trigger Architecture Checklist

  • [ ] One trigger per object. If a second trigger exists, consolidate into the handler.
  • [ ] Trigger body contains only: context checks, handler invocation, and routing logic.
  • [ ] No business logic, SOQL, or DML directly in the trigger body.
  • [ ] If a trigger framework (Trigger Actions Framework, ff-apex-common, custom base class) is already in use — extend it. Do not create a parallel pattern.
  • [ ] Handler class is with sharing unless the trigger requires elevated access.

Quick Reference — Hardcoded Anti-Patterns Summary

PatternAction
SOQL inside for loopRefactor: query before the loop, operate on collections
DML inside for loopRefactor: collect mutations, DML once after the loop
Class missing sharing declarationAdd with sharing (or document why without sharing)
escape="false" on user data (VF)Remove — auto-escaping enforces XSS prevention
Empty catch blockAdd logging and appropriate re-throw or error handling
String-concatenated SOQL with user inputReplace with bind variable or whitelist validation
Test with no assertionAdd a meaningful Assert.* call
System.assert / System.assertEquals styleUpgrade to Assert.isTrue / Assert.areEqual
Hardcoded record ID ('001...')Replace with queried or inserted test record ID

Related skills

FAQ

What does salesforce-apex-quality check first?

Governor limit safety - SOQL and DML must not appear inside for loops.

What test coverage does it require?

Positive, Negative, and Bulk paths with 200-251 records and meaningful Assert calls.

How does it handle CRUD and FLS?

UI-callable Apex must enforce access via Schema checks, WITH USER_MODE, or Database.query with USER_MODE.

Is Salesforce Apex Quality safe to install?

skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.

Code Review & Qualitybackendtesting

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.