---
id: CON-CRM-ENT-008
name: Organization Type
feature: FEAT-CRM-ENT-06
product_area: crm
module: entities
revision: 1
status: draft
product_intent: proposed
implementation_evidence: observed
source_sha:
  services-crm: 7ea48a414c42eade10d60753b8bcc323b1dd726f
  react-console: da63075876b2c5f4a6af07d457bb24ea8bf4c0c7
definition: >-
  An organization type classifies organizations and carries the workspace’s requirements for their
  roles.
owned_by: MOD-CRM-ENT
facets: []
evidence:
  - >-
    `services-crm` at `7ea48a414c42eade10d60753b8bcc323b1dd726f`:
    `modules/entities/db/organization-types.table.ts` records this concept.
narrative:
  status: verified
  review: NARRATIVE-REVIEW-2026-10-23
narrative_sources:
  - section: Why It Exists
    provenance: inferred
    source: >-
      services-crm:modules/entities/tests/e2e/contact-types.e2e.spec.js#answers 400 naming the field
      for a create whose name is nothing but spaces;
      services-crm:modules/entities/tests/e2e/contact-types.e2e.spec.js#answers 400 for an id that
      is not a configuration id, saying what an id may hold;
      services-crm:modules/entities/tests/e2e/address-types.e2e.spec.js#says which records keep the
      type when it refuses the delete;
      services-crm:modules/entities/tests/e2e/contact-types.e2e.spec.js#answers 400 for a reorder
      that leaves a type of the tenant out;
      services-crm:modules/entities/tests/e2e/phone-number-types.e2e.spec.js#answers only the types
      usable on organizations when the query asks for them;
      services-crm:modules/entities/tests/e2e/address-types.e2e.spec.js#answers 403 to a read-only
      caller’s reorder; services-crm:modules/entities/tests/e2e/contact-types.e2e.spec.js#then, when
      the version is off, refuses the change (409);
      react-console:acceptance/crm/playwright/journeys/contacts/CRM-ACC-0033.spec.ts#CRM-ACC-0033;
      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/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/tests/e2e/page-layouts.e2e.spec.js#is not answered the section
      it may not read: it is ABSENT, not null, so "forbidden" and "unset" never look alike;
      services-crm:modules/entities/tests/e2e/page-layouts.e2e.spec.js#writes NEITHER section for
      that refused save: the decision is made before anything is written;
      services-crm:modules/entities/tests/e2e/page-layouts.e2e.spec.js#refuses a save from a stale
      version (409);
      services-crm:modules/entities/tests/integration/services/persistence/crm-settings.integration.spec.js#refuses
      a definition of the wrong kind: a console form in the console page layout slot;
      services-crm:modules/entities/tests/e2e/page-layouts.e2e.spec.js#KEEPS all five through a PUT
      that does not mention them: an older client cannot wipe a tenant’s assignments;
      services-crm:modules/entities/tests/e2e/page-layouts.e2e.spec.js#falls back to the tenant’s
      default for a kind the type leaves empty;
      services-crm:modules/entities/tests/e2e/page-layouts.e2e.spec.js#is refused the tenant’s
      defaults (403): reading a record does not make one an administrator of layouts
    note: Business need inferred from the sourced behavior; no historical motivation is attributed.
  - section: What It Controls
    provenance: observed
    source: >-
      services-crm:modules/entities/tests/e2e/contact-types.e2e.spec.js#answers 400 naming the field
      for a create whose name is nothing but spaces;
      services-crm:modules/entities/tests/e2e/contact-types.e2e.spec.js#answers 400 for an id that
      is not a configuration id, saying what an id may hold;
      services-crm:modules/entities/tests/e2e/address-types.e2e.spec.js#says which records keep the
      type when it refuses the delete;
      services-crm:modules/entities/tests/e2e/contact-types.e2e.spec.js#answers 400 for a reorder
      that leaves a type of the tenant out;
      services-crm:modules/entities/tests/e2e/phone-number-types.e2e.spec.js#answers only the types
      usable on organizations when the query asks for them;
      services-crm:modules/entities/tests/e2e/address-types.e2e.spec.js#answers 403 to a read-only
      caller’s reorder; services-crm:modules/entities/tests/e2e/contact-types.e2e.spec.js#then, when
      the version is off, refuses the change (409);
      react-console:acceptance/crm/playwright/journeys/contacts/CRM-ACC-0033.spec.ts#CRM-ACC-0033;
      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/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/tests/e2e/page-layouts.e2e.spec.js#is not answered the section
      it may not read: it is ABSENT, not null, so "forbidden" and "unset" never look alike;
      services-crm:modules/entities/tests/e2e/page-layouts.e2e.spec.js#writes NEITHER section for
      that refused save: the decision is made before anything is written;
      services-crm:modules/entities/tests/e2e/page-layouts.e2e.spec.js#refuses a save from a stale
      version (409);
      services-crm:modules/entities/tests/integration/services/persistence/crm-settings.integration.spec.js#refuses
      a definition of the wrong kind: a console form in the console page layout slot;
      services-crm:modules/entities/tests/e2e/page-layouts.e2e.spec.js#KEEPS all five through a PUT
      that does not mention them: an older client cannot wipe a tenant’s assignments;
      services-crm:modules/entities/tests/e2e/page-layouts.e2e.spec.js#falls back to the tenant’s
      default for a kind the type leaves empty;
      services-crm:modules/entities/tests/e2e/page-layouts.e2e.spec.js#is refused the tenant’s
      defaults (403): reading a record does not make one an administrator of layouts
---

# Organization Type

## What It Is

An Organization Type is the workspace's category for a body, such as Member Firm or Chapter. It is a named catalogue definition with a stable configuration identity, selected by organization records. The type can include presentation assignments and organizational policy, so its significance extends beyond a display label.

Its policy can restrict the roles staff add to affiliations and enable compliance with minimum or maximum role-holder expectations. Notice options identify relevant roles and a Platform-owned template. These facets configure how Organizations and their representatives are treated; individual affiliations and assessments remain separate records.

## Why It Exists

Our reading is that different association bodies need different expectations while sharing one organization model. A chapter and a member firm can both be organizations without requiring identical officers or representatives. A reusable type lets staff classify them and configure role policy consistently rather than embedding a competing set of rules in each individual organization or entry screen.

## What It Is Not

An Organization Type is not an Organization, an Affiliation Type, or a Contact Role. It classifies the body; an affiliation type describes how a person relates to that body, and roles describe responsibilities. A restriction says what may be assigned, while a coverage rule says how many effective holders are expected. Neither is the calculated compliance result itself.

## What It Controls

Role restrictions determine allowed new or changed responsibilities at organizations of that type. Compliance options supply the bounds evaluated by Organization Compliance, including meaningful maximum-zero cases. Notification roles and the type's template supply the policy for transition notices, subject to the separately owned recipient and delivery behavior.

Presentation assignments can override workspace forms and layouts for organizations. A changed type policy does not itself immediately refresh every organization's stored assessment; reaction, reconciliation, or reprocessing must reach them. References prevent deleting a used classification. Template changes cross Platform's service boundary and have their stated validation and compensation behavior rather than pretending to be one invisible local transaction.

## How It Is Used

The CRM Administrator configures types, role restrictions, coverage expectations, and notice content. The CRM Editor creates organizations and assigns responsibilities under those choices. The CRM Reader inspects classifications and assessments. Good administration distinguishes a new policy from already refreshed assessments and uses the compliance reprocess when existing organizations need reevaluation, with previews to inspect notice content without treating them as actual sends.

## Example

An association creates a Chapter type that allows officer roles and requires a billing representative. Harbor West Chapter uses it. A coordinator cannot add a disallowed new responsibility, and a compliance calculation reports missing billing coverage. When the administrator changes the minimum expectation, she requests reprocessing before assuming the chapter's saved status reflects that change. A draft preview checks the notice without storing or sending it.

## How It Relates

Organization Type classifies Organization and refers to Contact Role definitions in allowed lists, coverage rules, and recipient policy. Organization Compliance evaluates effective role periods on Affiliations. CRM Settings supplies presentation fallbacks, while Platform metadata owns forms and layouts and Platform notifications owns templates and delivery. Contact Type and Affiliation Type remain separate classifications for the person and relationship.
