Skip to content

CAP-CRM-ENT-011Maintain responsibilities on organizational relationships

Markdown

CAP-CRM-ENT-011

Maintain responsibilities on organizational relationships

Markdown
  • DocumentApproved
  • Product intentProposed
  • ImplementationInconsistent

KindCapabilityProduct areaCRMModuleEntitiesRevision1Approved byAndrewApproved at2026-10-22

Read atservices-crm 7ea48a41react-console da630758

The Formal Contract

The narrative above explains; the sections below are authoritative — the rules, scenarios and tests this document binds.

Outcomes
Each role is a dated row on one affiliation, never outliving it.A person who joins an organization receives its automatic roles, and its first person the first-contact roles.An organization type's role restriction is enforced by the service and the pickers.
Surfaces
consoleapijob
Intent sources
services-crm:docs/milestones/CRM-M1-contacts-and-organizations.md#M1-D1services-crm:docs/milestones/CRM-M2-affiliations-roles-compliance.md#M2-D2services-crm:docs/milestones/CRM-M2-affiliations-roles-compliance.md#M2-D6services-crm:docs/milestones/CRM-M2-affiliations-roles-compliance.md#M2-D12services-crm:docs/milestones/CRM-M2-affiliations-roles-compliance.md#M2-D13services-crm:docs/milestones/CRM-M2-affiliations-roles-compliance.plan.md#A6

Controls

25 controls apply, from the corpus control catalogue.

TC-AZ-001 TC-AZ-002 TC-AZ-003 TC-AZ-004 TC-AZ-006 TC-DAT-001 TC-DAT-002 TC-DAT-003 TC-IAM-001 TC-IAM-005 TC-IAM-006 TC-LOG-004 TC-LOG-005 TC-MON-001 TC-MON-002 TC-PI-001 TC-PI-002 TC-PI-003 TC-PI-004 TC-PI-005 TC-PRV-001 TC-PRV-002 TC-TEN-001 TC-TEN-002 TC-TEN-003

Repositories Read

RepositoryPaths
undefined:modules/entities/
undefined:docs/milestones/CRM-M2-affiliations-roles-compliance.md
undefined:modules/entities/services/persistence/contact-affiliations.ts
undefined:modules/entities/tests/integration/services/affiliations/affiliation-date-reconciliation.follow-ups.integration.spec.js
undefined:modules/entities/tests/integration/services/contacts/role-assignment/automatic-role-reconciliation.integration.spec.js
undefined:modules/entities/tests/integration/services/contacts/role-assignment/contact-role-assignment.integration.spec.js
undefined:modules/entities/tests/integration/services/persistence/contact-affiliations.integration.spec.js
undefined:modules/entities/tests/unit/services/persistence/contact-affiliations.spec.js
undefined:app/(console)/console/[tenantId]/crm/contacts/
undefined:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0188.spec.ts
undefined:components/affiliations/affiliation-editor.tsx

Where It Lives

Permissions

KeyChecked atScope
crm.contacts.updateapitenant
crm.contact-roles.readapitenant

Business Rules

14 rules, 12 to be proved before approval. A rule's product intent is derived from its origin: 7 confirmed by a product decision, the rest inheriting this capability's proposed.

IdRuleKindEnforced atProvenance
01must prove
Proposed
Affiliation roles must reference a contact role in the tenant, whether active or inactive, and reject unknown or foreign roles.
validationservice, databaseobserved
02must prove
Proposed
Explicit role boundaries must fit within the affiliation period, while omitted boundaries inherit the corresponding affiliation boundary.
invariantservice, databasetest
03must prove
Confirmed
A role cannot overlap another period of the same role on one affiliation, may recur in separate periods or separate affiliations, and an affiliation supports at most 25 role rows.
invariantservice, databasetest
services-crm:modules/entities/tests/unit/services/persistence/contact-affiliations.spec.js#refuses the same role overlapping itself on one affiliation
04must prove
Proposed
Changing an affiliation end closes its open or later-ending role periods on that day, while an unchanged affiliation end leaves those periods alone.
lifecycleservicetest
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
05must prove
Confirmed
New or changed roles must satisfy the organization type’s restriction with a refusal naming the role, type and allowed list; unchanged roles bypass rechecking and pickers retain held roles alongside permitted choices.
validationservice, consoletest
06must prove
Proposed
Moving a contact’s primary organization assigns active automatic roles not already held on the new primary tie and first-contact roles when no other current affiliate exists, while an unchanged primary organization assigns nothing.
calculationservicetest
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
07must prove
Proposed
Future affiliations receive automatic roles no earlier than their local start day through a later save or reconciliation, and corrections to start or end dates determine whether and when assignment occurs.
lifecycleservicetest
08must prove
Proposed
Automatic roles inherit the affiliation’s dates, are only added, are not restored after deliberate removal and wait when the contact or affiliation is locked against updates.
policyservicetest
09must prove
Confirmed
Inactive and deceased contacts receive no new automatic roles, retain existing roles and still count as affiliates when deciding whether another contact is first.
policyservicetest
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
10must prove
Confirmed
Organization type restrictions suppress disallowed automatic roles and report the skipped roles with the restricting type.
policyservicetest
11must prove
Confirmed
Rejoining an organization assigns automatic roles to the new affiliation again while retaining the old affiliation’s ended role history.
policyservicedocumented
12must prove
Proposed
Concurrent joins to an empty organization give the first-contact roles to exactly one joining contact.
invariantservice, databasetest
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
13
Confirmed
The contact editor presents separate dated rows for repeated role periods and allows another period to be added.
policyconsoleobserved
14
Confirmed
The product should offer imports an Apply automatic roles option, initially off, in the imports milestone.
policydocumented

Scenarios

IdGivenWhenThenProvenance
01A tenant with an automatic Member Contact role and a first-contact Billing Contact role.The first person joins a new company as primary, then a second.The first holds both, the second only Member Contact.test
02Chapters restrict roles to President, Treasurer and Secretary.A staff member gives someone Billing Contact at a chapter.The save is rejected naming the allowed roles.test

Edge Cases

IdGivenWhenThenProvenance
03A non-primary affiliation added today and another starting tomorrow, both at organizations with automatic roles.The first is saved; the second reaches its start day.The first is given no automatic role; the second is given them by the reconciliation.unknown

The Markdown files under specs/ in rhythmsoftware/rhythm-v2-docs are the canonical source of truth. This reader is a generated, read-only projection of them.