---
id: CON-CRM-ENT-035
name: Organization Compliance
feature: FEAT-CRM-ENT-05
product_area: crm
module: entities
revision: 1
status: draft
product_intent: proposed
implementation_evidence: observed
source_sha:
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
definition: >-
  Organization compliance is the calculated assessment of effective contact-role coverage against an
  organization type’s configured expectations.
owned_by: MOD-CRM-ENT
facets:
  - name: Role-count rules
    meaning: Minimum and maximum holder bounds supplied by the organization type.
    used_for: Evaluating effective coverage.
  - name: Violations
    meaning: The recorded gaps or excess holders found by calculation.
    used_for: Explaining the assessment.
  - name: Notices and reprocessing
    meaning: Transition notice submission and durable reevaluation work.
    used_for: Responding to gaps and policy changes.
acted_on_by:
  - CAP-CRM-ENT-012
visible_to:
  - ACT-CRM-001
  - ACT-CRM-002
  - ACT-CRM-003
  - ACT-CRM-005
narrative:
  status: verified
  review: NARRATIVE-REVIEW-2026-10-23
narrative_sources:
  - section: Why It Exists
    provenance: inferred
    source: >-
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
      a type that holds it to no rule, or with no type: no status and no violations;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
      a type that holds it to rules: not in compliance, every rule with a minimum violated (it has
      no contact yet);
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#brings
      an organization into compliance for a role held on a current affiliation that is not primary;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-change-events.integration.spec.js#a
      contact saved with the notes DISABLE_CONTACT_ROLE_COMPLIANCE_CHECK: nothing (its delete still
      records);
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#writes
      nothing for a duplicate delivery, or a second run on an unchanged organization;
      services-crm:modules/entities/tests/e2e/organization-compliance.e2e.spec.js#keep them against
      a PUT that sends others back;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#is
      not submitted again while the organization stays out of compliance, nor for a type that does
      not notify;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-reads.integration.spec.js#leaves
      out the contact whose addresses sit past the primary slot, no secondary address standing in;
      services-crm:docs/entities-api.md#`compliance_notification_template`: the e-mail the type
      sends;
      services-crm:modules/entities/tests/integration/services/persistence/compliance-reprocesses.integration.spec.js#refuses
      a second running run for the tenant;
      services-crm:modules/entities/tests/e2e/email-previews.e2e.spec.js#answers 403 to a caller who
      may administer types but may not read the records the answer contains;
      services-crm:modules/entities/tests/e2e/organization-compliance.e2e.spec.js#answers 400 for a
      template both named and typed in, or neither;
      services-crm:modules/entities/services/persistence/organization-types.ts:organizationTypeProblems;
      services-crm:modules/entities/tests/integration/services/persistence/organization-attention-items.queries.integration.spec.js#answers
      the organizations out of compliance by id, and no other;
      services-crm:modules/entities/services/templates/compliance-notification-template.ts:effectiveTemplateChange;
      services-crm:modules/entities/services/persistence/organization-types.ts:updateOrganizationType;
      services-crm:modules/entities/tests/integration/services/templates/compliance-notification-template.integration.spec.js#keeps
      the delete and logs the type id when Platform cannot clear it: the type is gone either way;
      services-crm:modules/entities/services/persistence/contact-affiliations.ts:affiliationRefusal;
      services-crm:modules/entities/tests/unit/services/persistence/contact-affiliations.spec.js#refuses
      a role whose dates lie outside its affiliation's;
      services-crm:modules/entities/tests/unit/services/persistence/contact-affiliations.spec.js#refuses
      the same role overlapping itself on one affiliation;
      services-crm:modules/entities/tests/unit/services/persistence/contact-affiliations.spec.js#ends
      the open roles of an affiliation the save ends, on the same day;
      services-crm:modules/entities/tests/integration/services/persistence/contact-affiliations.integration.spec.js#refuses
      a role outside the list added to an existing affiliation;
      services-crm:modules/entities/tests/integration/services/contacts/role-assignment/contact-role-assignment.integration.spec.js#gives
      the organization's first contact the automatic and first-contact roles, besides the roles it
      states;
      services-crm:modules/entities/tests/integration/services/contacts/role-assignment/automatic-role-reconciliation.integration.spec.js#gives
      the automatic and first-contact roles on the start day in the tenant calendar;
      services-crm:modules/entities/tests/integration/services/contacts/role-assignment/automatic-role-reconciliation.integration.spec.js#does
      not give back a role a person removed after it was given;
      services-crm:modules/entities/tests/integration/services/contacts/role-assignment/contact-role-assignment.integration.spec.js#counts
      an inactive contact as already belonging to the organization, so the next contact is not its
      first;
      services-crm:modules/entities/tests/integration/services/affiliations/affiliation-date-reconciliation.follow-ups.integration.spec.js#skips
      the forbidden role on the start day;
      services-crm:docs/milestones/CRM-M2-affiliations-roles-compliance.md#M2-D12;
      services-crm:modules/entities/tests/integration/services/contacts/role-assignment/contact-role-assignment.integration.spec.js#gives
      the first-contact roles to exactly one of several contacts joining an empty organization at
      once; react-console:components/affiliations/affiliation-editor.tsx:Add Period;
      services-crm:docs/milestones/CRM-M2-affiliations-roles-compliance.md#M2-D13;
      services-crm:modules/entities/tests/integration/services/persistence/contact-affiliations.business-dates.integration.spec.js#refuses
      a primary starting on the tenant's tomorrow, though it is already UTC's and Sydney's today;
      services-crm:modules/entities/tests/integration/services/persistence/contact-affiliations.business-dates.integration.spec.js#reads
      a tie ending on the tenant's today as current;
      react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0186.spec.ts#CRM-ACC-0186;
      services-crm:modules/entities/tests/unit/services/affiliations/affiliation-date-window.spec.js#spans
      every day of a skipped weekend, so the next night makes them up;
      services-crm:modules/entities/tests/integration/services/affiliations/affiliation-date-reconciliation.integration.spec.js#takes
      the organization out of compliance the next morning, with no save of the contact;
      services-crm:modules/entities/tests/integration/services/affiliations/affiliation-date-reconciliation.integration.spec.js#finds
      the day settled and changes nothing, the organization’s version included;
      services-crm:modules/entities/tests/e2e/affiliation-date-reconciliation.e2e.spec.js#refuses a
      real run that names a day, 400 naming it; services-crm:docs/affiliations/README.md#5.6b The
      overnight date reconciliation (D-46; CRM-M2 A6 and A7)
    note: Business need inferred from the sourced behavior; no historical motivation is attributed.
  - section: How It Is Used
    provenance: unknown
    source: FND-CRM-ENT-031
    note: Attention publication is conditional; no current environment deployment is inspected by this narrative review.
  - section: What It Controls
    provenance: observed
    source: >-
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
      a type that holds it to no rule, or with no type: no status and no violations;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
      a type that holds it to rules: not in compliance, every rule with a minimum violated (it has
      no contact yet);
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#brings
      an organization into compliance for a role held on a current affiliation that is not primary;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-change-events.integration.spec.js#a
      contact saved with the notes DISABLE_CONTACT_ROLE_COMPLIANCE_CHECK: nothing (its delete still
      records);
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#writes
      nothing for a duplicate delivery, or a second run on an unchanged organization;
      services-crm:modules/entities/tests/e2e/organization-compliance.e2e.spec.js#keep them against
      a PUT that sends others back;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#is
      not submitted again while the organization stays out of compliance, nor for a type that does
      not notify;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-reads.integration.spec.js#leaves
      out the contact whose addresses sit past the primary slot, no secondary address standing in;
      services-crm:docs/entities-api.md#`compliance_notification_template`: the e-mail the type
      sends;
      services-crm:modules/entities/tests/integration/services/persistence/compliance-reprocesses.integration.spec.js#refuses
      a second running run for the tenant;
      services-crm:modules/entities/tests/e2e/email-previews.e2e.spec.js#answers 403 to a caller who
      may administer types but may not read the records the answer contains;
      services-crm:modules/entities/tests/e2e/organization-compliance.e2e.spec.js#answers 400 for a
      template both named and typed in, or neither;
      services-crm:modules/entities/services/persistence/organization-types.ts:organizationTypeProblems;
      services-crm:modules/entities/tests/integration/services/persistence/organization-attention-items.queries.integration.spec.js#answers
      the organizations out of compliance by id, and no other;
      services-crm:modules/entities/services/templates/compliance-notification-template.ts:effectiveTemplateChange;
      services-crm:modules/entities/services/persistence/organization-types.ts:updateOrganizationType;
      services-crm:modules/entities/tests/integration/services/templates/compliance-notification-template.integration.spec.js#keeps
      the delete and logs the type id when Platform cannot clear it: the type is gone either way;
      services-crm:modules/entities/services/persistence/contact-affiliations.ts:affiliationRefusal;
      services-crm:modules/entities/tests/unit/services/persistence/contact-affiliations.spec.js#refuses
      a role whose dates lie outside its affiliation's;
      services-crm:modules/entities/tests/unit/services/persistence/contact-affiliations.spec.js#refuses
      the same role overlapping itself on one affiliation;
      services-crm:modules/entities/tests/unit/services/persistence/contact-affiliations.spec.js#ends
      the open roles of an affiliation the save ends, on the same day;
      services-crm:modules/entities/tests/integration/services/persistence/contact-affiliations.integration.spec.js#refuses
      a role outside the list added to an existing affiliation;
      services-crm:modules/entities/tests/integration/services/contacts/role-assignment/contact-role-assignment.integration.spec.js#gives
      the organization's first contact the automatic and first-contact roles, besides the roles it
      states;
      services-crm:modules/entities/tests/integration/services/contacts/role-assignment/automatic-role-reconciliation.integration.spec.js#gives
      the automatic and first-contact roles on the start day in the tenant calendar;
      services-crm:modules/entities/tests/integration/services/contacts/role-assignment/automatic-role-reconciliation.integration.spec.js#does
      not give back a role a person removed after it was given;
      services-crm:modules/entities/tests/integration/services/contacts/role-assignment/contact-role-assignment.integration.spec.js#counts
      an inactive contact as already belonging to the organization, so the next contact is not its
      first;
      services-crm:modules/entities/tests/integration/services/affiliations/affiliation-date-reconciliation.follow-ups.integration.spec.js#skips
      the forbidden role on the start day;
      services-crm:docs/milestones/CRM-M2-affiliations-roles-compliance.md#M2-D12;
      services-crm:modules/entities/tests/integration/services/contacts/role-assignment/contact-role-assignment.integration.spec.js#gives
      the first-contact roles to exactly one of several contacts joining an empty organization at
      once; react-console:components/affiliations/affiliation-editor.tsx:Add Period;
      services-crm:docs/milestones/CRM-M2-affiliations-roles-compliance.md#M2-D13;
      services-crm:modules/entities/tests/integration/services/persistence/contact-affiliations.business-dates.integration.spec.js#refuses
      a primary starting on the tenant's tomorrow, though it is already UTC's and Sydney's today;
      services-crm:modules/entities/tests/integration/services/persistence/contact-affiliations.business-dates.integration.spec.js#reads
      a tie ending on the tenant's today as current;
      react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0186.spec.ts#CRM-ACC-0186;
      services-crm:modules/entities/tests/unit/services/affiliations/affiliation-date-window.spec.js#spans
      every day of a skipped weekend, so the next night makes them up;
      services-crm:modules/entities/tests/integration/services/affiliations/affiliation-date-reconciliation.integration.spec.js#takes
      the organization out of compliance the next morning, with no save of the contact;
      services-crm:modules/entities/tests/integration/services/affiliations/affiliation-date-reconciliation.integration.spec.js#finds
      the day settled and changes nothing, the organization’s version included;
      services-crm:modules/entities/tests/e2e/affiliation-date-reconciliation.e2e.spec.js#refuses a
      real run that names a day, 400 naming it; services-crm:docs/affiliations/README.md#5.6b The
      overnight date reconciliation (D-46; CRM-M2 A6 and A7)
---

# Organization Compliance

## What It Is

Organization Compliance is the assessment of an organization's effective contact-role coverage against expectations configured on its Organization Type. It describes whether required representation exists or too many people hold a bounded responsibility. Stored violations explain the outcome role by role rather than presenting an unexplained good-or-bad label.

Its facets include role-count rules, calculated status and violations, transition notices, and durable reprocessing. Organizations without applicable enabled rules do not have the same assessment as organizations satisfying rules. The concept is therefore a policy-backed calculation and response process, not a generic status that every organization must carry.

## Why It Exists

Our reading is that associations need to recognize gaps in representation without manually inspecting every person's responsibilities. A member firm may require a billing contact and a chapter may require particular officers. A shared calculation relates those expectations to effective holders and provides an explanation staff can act on, while notices and reprocessing address changes in people and policy.

## What It Is Not

Organization Compliance is not membership eligibility, financial standing, or regulatory certification. Its scope is configured contact-role coverage. An allowed-role list limits what staff may assign; a compliance rule sets count expectations; a calculated violation describes the present assessment. Notice submission is also distinct from mail delivery, and a preview is neither a stored assessment nor a sent message.

## What It Controls

Effective role coverage determines stored violations and the assessment changes written to the organization. Distinct people count through current affiliations, including secondary connections. A changed violation result advances the organization version, while repeated unchanged calculation avoids redundant writes. Removing the applicable policy clears prior assessment when recalculation reaches the organization.

Entry into noncompliance can submit a deduplicated notice under the type's notification policy. Configured roles select eligible current recipients with primary e-mail addresses; Platform owns the template and actual sending. Reprocessing revisits existing organizations after policy changes through resumable work, rather than claiming every type edit recalculates them immediately. Preview and test-send actions provide separate tools for inspecting communication behavior.

## How It Is Used

The CRM Administrator configures the type's expectations, reviews notice content, and requests reevaluation of existing organizations. The CRM Editor changes the relationships and responsibility periods that supply coverage. The CRM Reader inspects violations and, where publication is enabled, attention items, and the CRM System processes reactions and date boundaries. Good use reads the violation explanation and understands what reevaluation has occurred before interpreting stored status as current policy coverage.

A changed assessment can be system-attributed and therefore make an open organization editor stale. The compliance result is not an editable assertion that an administrator can set directly. Preview authorization also protects the actual contact and organization information incorporated into a draft, even though the preview sends nothing.

## Example

Harbor West Chapter uses a type requiring one billing representative. Ruth supplies that role through a current secondary affiliation, so the assessment can count her even when her primary organization is her employer. When the period ends and reevaluation runs, the chapter records a missing-holder violation and can submit a transition notice if configured.

The same repeated event does not manufacture another assessment or notice. If administrators later change the required count, reprocessing revisits the chapter under the new expectations. Continuing noncompliance is still different from a fresh transition, and the presence of a submitted request alone does not prove delivery to a mailbox.

## How It Relates

Organization Type owns the policy choices and Contact Role supplies each responsibility's meaning. Affiliations and their role periods supply dated holders, using the workspace calendar. Organization carries the assessment and its version, while Record Protection and History explains committed system changes. CRM Settings participates in date processing through its watermark. Platform notifications owns templates and sending, with a separate service boundary for previews and requests.
