# Task L.3: Full CRM Scope Enforcement ## Summary Task L.3 starts hardening CRM security around resolved CRM access instead of relying on route-level permissions or legacy role strings alone. ## Implemented in this pass - Added centralized CRM security helpers in `src/features/crm/security/server/service.ts` - Added `canViewQuotationPricing()` guard for pricing-bearing quotation outputs - Applied pricing enforcement to: - document data - document preview - PDF preview - PDF download - approved PDF - approved quotation artifact download - Switched dashboard revenue visibility to pricing visibility instead of broad quotation-read semantics - Blocked revenue dashboard export when pricing visibility is missing - Updated quotation list/detail/create/update/delete routes to pass resolved CRM scope context - Added quotation service-side branch/product/own-scope enforcement - Updated approval step actor validation to use resolved CRM role unions - Added `crm_security_access` audit events for pricing-denied flows - Added security inventory and boundary documentation - Added `scripts/security/verify-crm-access.ts` ## Remaining gaps - Customers and contacts still need full ownership-scope enforcement - Approval list/detail visibility is still broader than the final resolved-quotation scope - Team-scope semantics remain approximate until the domain has a first-class team/subordinate model - Runtime seeded scenario verification is still needed beyond the current static regression script ## Verification - `npx tsc --noEmit` - `node --experimental-strip-types scripts/security/verify-crm-access.ts`