# CRM Authorization Boundaries ## Source of Truth Resolved CRM access is the source of truth for CRM authorization. The effective model is: 1. Authenticated user 2. Active organization membership 3. CRM role assignments 4. Resolved permission union 5. Resolved branch scope 6. Resolved product scope 7. Resolved ownership scope 8. Resolved approval authority `memberships.businessRole` remains a compatibility fallback only inside the resolver path. ## Enforcement Layers ### Route permission gates Every CRM route must first require organization access plus at least one explicit permission. ### Service-level scope enforcement Sensitive list/detail/mutation services must additionally enforce: - branch scope - product scope - ownership visibility This is required because UI filtering is not a security boundary. ### Pricing visibility Pricing-bearing outputs require quotation pricing visibility: - quotation PDF preview/download - approved PDF - document preview/data - revenue dashboard/export - approved artifact download Denied pricing access is logged as `crm_security_access` with action `pricing_hidden`. ### Approval authority Approval step handling must use resolved CRM role unions instead of a single legacy business-role string. ## Current Ownership Model - `own`: creator or assigned owner/salesman - `team`: currently treated as broader-than-own, but still requires future team graph formalization - `organization`: organization-wide inside active tenant - `monitor`: read-oriented role with limited commercial visibility ## Customer Boundary Customer visibility is now enforced from resolved CRM access. - `organization` and admin scopes can see organization customers within branch scope - `team` currently behaves as branch/product-scoped broad visibility until a first-class team graph exists - `own` can see customers they created or customers linked to enquiries/quotations they can already access - `monitor` can see customers only when those customers are related to visible lead/enquiry records ## Contact Boundary Contact visibility is enforced through customer visibility plus contact ownership rules. - if a user can access the parent customer, they can access its contact list within their role boundary - contact creators retain access to their own contacts - admin/organization scope retains access - production contact sharing is persisted through `crm_contact_shares`, so explicit share grants are part of the live authorization boundary ## Approval Boundary Approval visibility is now narrower than generic approval-read permission. A user can see approval records only when at least one of these is true: 1. they can access the related quotation through resolved CRM scope 2. they are the current approval actor by resolved CRM role 3. they are admin / organization-wide CRM authority ## Artifact Boundary Artifact permission alone is not enough for approved quotation PDFs. The caller must satisfy: 1. artifact download permission 2. quotation pricing visibility when the artifact is an approved quotation PDF ## Dashboard Boundary Dashboard access is split: - base dashboard visibility: `crm.dashboard.read` - revenue/commercial visibility: quotation pricing visibility - approval widgets: approval read permission - export visibility: same scope as dashboard, with extra revenue export restriction Approval widgets additionally inherit approval-request visibility rules, not just a raw approval permission. ## Audit Events Security-sensitive denials are recorded under entity type `crm_security_access` with actions: - `access_denied` - `scope_violation` - `permission_violation` - `pricing_hidden`