Concept
CRUD (object permissions) and FLS (field permissions) are granted via profiles and permission sets. They are enforced automatically in the standard UI, standard controllers, and Lightning Data Service — but NOT automatically in Apex, which runs in system mode by default on legacy API versions.
- Apex Enforcement: In Apex code, security must be explicitly opted into: SOQL queries with
WITH USER_MODE, DML withas user, orSecurity.stripInaccessible()to sanitize records. - Distinction: CRUD/FLS answers "which objects and fields", while record-level sharing answers "which rows".
- Client-Side: Lightning Data Service (LDS) enforces CRUD and FLS automatically for LWC components without requiring manual server checks.
Core Q&A
A: Prefer user-mode database operations: SELECT ... WITH USER_MODE and insert as user records — they enforce CRUD, FLS, and sharing together while reporting all violations.
WITH SECURITY_ENFORCEDis the older query-only clause that throws on the first violation, ignores polymorphic fields, and does nothing for DML.Security.stripInaccessible(AccessType.READABLE/CREATABLE, records)provides graceful degradation — instead of throwing an exception, it strips fields the user cannot access. This is ideal for integration-facing or bulk execution paths where partial success is acceptable.- Rule of Thumb: User mode as the default in new code,
stripInaccessiblewhen you must not throw exceptions, and manual Describe checks only for custom UI field-building logic.
Follow-ups (Scenario-Based)
A1: Because the Apex method runs in system mode: FLS was checked by the standard page layout, not by your custom SOQL query.
- Fix 1 (Apex): Enforce security in Apex using
WITH USER_MODEorSecurity.stripInaccessible()before returning data to the LWC. - Fix 2 (LWC): Eliminate custom Apex reads entirely and use Lightning Data Service (LDS) or the
getRecordwire adapter, which automatically enforces CRUD/FLS out of the box with client-side caching. - Architect Note: Option 2 is preferred whenever complex server-side data processing is not required.
A2: Implement a strict two-layer security model:
- Layer 1 (Configuration Access): Configuration objects carry their own strict CRUD/FLS, so only the "Approval Config Author" permission set can create or edit rules.
- Layer 2 (Execution Context): The engine's evaluation code reads rule configurations
without sharing(since system rules evaluate globally), but every action or update on target records executes inUSER_MODE. - An approver can never view or modify fields forbidden by their own FLS — the engine amplifies process authority, never data authority.
Recommended Reading: Reports, Dashboards & Analytics Architecture