---
title: CRM → Entities independent examination
examined_at: '2026-10-22'
examiner: codex
source_sha:
  services-crm: 7ea48a414c42eade10d60753b8bcc323b1dd726f
  react-console: da63075876b2c5f4a6af07d457bb24ea8bf4c0c7
branch: agent/crm-ent-exam-2
evidence:
  - repository: services-crm
    read: >-
      Registered Entities source scope and milestone records; the original examination catalog is
      retained below in frontmatter.
  - repository: react-console
    read: 'Registered CRM console components, inventories, journeys and browser specifications.'
examination_catalog: |

  # CRM → Entities examination

  ## Verdict for Andrew

  The planning layer provides a sourced description of the scoped Entities behavior at the pinned commits, with disputed behavior and unproved contracts explicitly separated from observations. Its weakest evidence is browser behavior exercised through API fallbacks, together with replacement semantics, disabled deployment switches and cross-module duplicate contracts. Before design starts, Andrew should resolve the replacement and ownership questions and commission direct proof for the open refusal, compensation and session-restoration scenarios.

  ## Scope and method

  This is an independent OpenAI examination and final-language pass over the Opus draft. The work stays on the supplied fleet branch and descends from its starting commit. The task’s explicit actor-file requirement authorizes the product-area actor file despite the general directory restriction; all other changes stay in Entities and the authorized product-area registry. No application source, reader, checker, template, workflow or deployment changes are made.

  The examination reads the registered route, schema, service, table, document, component and test sources. Each structured source, origin, intent-source and test binding is checked against the pinned repository content for path and anchor existence. Assertions are read as test evidence; the CRM and console product suites are not executed in this job. Corpus validation is executed separately. Code comments do not become product approvals, and all new feature-tree artifacts remain draft and proposed.

  ## Counts examined

  | Artifact or evidence | Count |
  |---|---|
  | Module charter | 1 |
  | Capability specifications | 19 |
  | Journey specifications | 5 |
  | Acceptance test sets | 19 |
  | Capability rules | 205 |
  | Must-prove rules | 174 |
  | Acceptance scenarios | 181 |
  | Acceptance scenarios with bindings | 175 |
  | Features written and checked | 7 |
  | Key concepts written and checked | 32 |
  | Product-area actors written and checked | 5 |
  | Findings reviewed | 30 |
  | Open questions reviewed | 4 |
  | Structured pinned-code references checked | 1380 |
  | Distinct pinned-code files opened for those references | 201 |
  | Missing source paths or anchors at final audit | 0 |

  All 19 capabilities describe outcomes. Their grain does not require a split or merge; their identifiers remain permanent. Every capability and journey has exactly one feature home. Every must-prove rule has an acceptance scenario or a cited finding; a proposed scenario remains a proof obligation rather than a claim of existing execution.

  ## Coverage

  | Evidence inventory | Covered / total | Uncovered names |
  |---|---|---|
  | Distinct literal route operation IDs | 53 / 53 | None |
  | Operations after shared factory expansion | 91 / 91 | None |
  | Entities table files | 26 / 26 | None |
  | Published keys in the eight Entities permission groups | 57 / 57 catalog or dependency mappings | None unmapped; six bulk keys lack Entities routes, FND-CRM-ENT-013 |
  | E2E specification files | 25 / 25 | None |
  | E2E directory files including support code | 26 / 26 | None; e2e-security.js is support code |

  Coverage means a named specification or evidence home, not passing execution or complete behavioral proof. The brief’s 52-operation and 26-specification totals do not match the pinned source; FND-CRM-ENT-015 preserves that discrepancy. Bulk and merge ownership stays with neighboring CRM modules, and query execution stays with Platform.

  ### Literal operation IDs

  - `archiveContact`
  - `archiveOrganization`
  - `createAffiliationType`
  - `createContact`
  - `createContactRole`
  - `createContactType`
  - `createOrganization`
  - `createOrganizationType`
  - `deleteAffiliationType`
  - `deleteContact`
  - `deleteContactRole`
  - `deleteContactType`
  - `deleteOrganization`
  - `deleteOrganizationType`
  - `getAffiliationType`
  - `getContact`
  - `getContactMailingAddress`
  - `getContactRole`
  - `getContactType`
  - `getCrmSettings`
  - `getEffectiveDefinitions`
  - `getOrganization`
  - `getOrganizationType`
  - `listAffiliationTypes`
  - `listContactRoles`
  - `listContactTypes`
  - `listContacts`
  - `listOrganizationAffiliations`
  - `listOrganizationTypes`
  - `listOrganizations`
  - `patchAffiliationType`
  - `patchContact`
  - `patchContactRole`
  - `patchContactType`
  - `patchCrmSettings`
  - `patchOrganization`
  - `patchOrganizationType`
  - `previewContactRoleComplianceEmail`
  - `reconcileAffiliationDates`
  - `recursivelyListContactsForOrganizationId`
  - `renderEmailPreview`
  - `reorderContactRoles`
  - `reorderContactTypes`
  - `reorderOrganizationTypes`
  - `reprocessCompliance`
  - `unarchiveContact`
  - `unarchiveOrganization`
  - `updateAffiliationType`
  - `updateContact`
  - `updateContactRole`
  - `updateContactType`
  - `updateOrganization`
  - `updateOrganizationType`

  ### Named operation, table and E2E homes

  #### Operations

  | Operation | Capability |
  |---|---|
  | `archiveContact` | `CAP-CRM-ENT-013` |
  | `archiveOrganization` | `CAP-CRM-ENT-013` |
  | `createAddressType` | `CAP-CRM-ENT-018` |
  | `createAffiliationType` | `CAP-CRM-ENT-017` |
  | `createContact` | `CAP-CRM-ENT-001` |
  | `createContactRole` | `CAP-CRM-ENT-017` |
  | `createContactType` | `CAP-CRM-ENT-018` |
  | `createOrganization` | `CAP-CRM-ENT-002` |
  | `createOrganizationType` | `CAP-CRM-ENT-018` |
  | `createPhoneNumberType` | `CAP-CRM-ENT-018` |
  | `deleteAddressType` | `CAP-CRM-ENT-018` |
  | `deleteAffiliationType` | `CAP-CRM-ENT-017` |
  | `deleteContact` | `CAP-CRM-ENT-014` |
  | `deleteContactRole` | `CAP-CRM-ENT-017` |
  | `deleteContactType` | `CAP-CRM-ENT-018` |
  | `deleteOrganization` | `CAP-CRM-ENT-014` |
  | `deleteOrganizationType` | `CAP-CRM-ENT-018` |
  | `deletePhoneNumberType` | `CAP-CRM-ENT-018` |
  | `getAddressType` | `CAP-CRM-ENT-018` |
  | `getAffiliationType` | `CAP-CRM-ENT-017` |
  | `getContact` | `CAP-CRM-ENT-003` |
  | `getContactMailingAddress` | `CAP-CRM-ENT-005` |
  | `getContactRevision` | `CAP-CRM-ENT-016` |
  | `getContactRole` | `CAP-CRM-ENT-017` |
  | `getContactType` | `CAP-CRM-ENT-018` |
  | `getCrmSettings` | `CAP-CRM-ENT-019` |
  | `getEffectiveDefinitions` | `CAP-CRM-ENT-019` |
  | `getMergedContactRevision` | `CAP-CRM-ENT-016` |
  | `getOrganization` | `CAP-CRM-ENT-003` |
  | `getOrganizationRevision` | `CAP-CRM-ENT-016` |
  | `getOrganizationType` | `CAP-CRM-ENT-018` |
  | `getPhoneNumberType` | `CAP-CRM-ENT-018` |
  | `listAddressTypes` | `CAP-CRM-ENT-018` |
  | `listAffiliationTypes` | `CAP-CRM-ENT-017` |
  | `listContactHistory` | `CAP-CRM-ENT-016` |
  | `listContactHistoryActors` | `CAP-CRM-ENT-016` |
  | `listContactLockChanges` | `CAP-CRM-ENT-015` |
  | `listContactRoleLockChanges` | `CAP-CRM-ENT-015` |
  | `listContactRoles` | `CAP-CRM-ENT-017` |
  | `listContactTypes` | `CAP-CRM-ENT-018` |
  | `listContacts` | `CAP-CRM-ENT-003` |
  | `listMergedContactHistory` | `CAP-CRM-ENT-016` |
  | `listMergedContactHistoryActors` | `CAP-CRM-ENT-016` |
  | `listOrganizationAffiliations` | `CAP-CRM-ENT-009` |
  | `listOrganizationHistory` | `CAP-CRM-ENT-016` |
  | `listOrganizationHistoryActors` | `CAP-CRM-ENT-016` |
  | `listOrganizationLockChanges` | `CAP-CRM-ENT-015` |
  | `listOrganizationTypes` | `CAP-CRM-ENT-018` |
  | `listOrganizations` | `CAP-CRM-ENT-003` |
  | `listPhoneNumberTypes` | `CAP-CRM-ENT-018` |
  | `lockContact` | `CAP-CRM-ENT-015` |
  | `lockContactRole` | `CAP-CRM-ENT-015` |
  | `lockOrganization` | `CAP-CRM-ENT-015` |
  | `patchAddressType` | `CAP-CRM-ENT-018` |
  | `patchAffiliationType` | `CAP-CRM-ENT-017` |
  | `patchContact` | `CAP-CRM-ENT-004` |
  | `patchContactRole` | `CAP-CRM-ENT-017` |
  | `patchContactType` | `CAP-CRM-ENT-018` |
  | `patchCrmSettings` | `CAP-CRM-ENT-019` |
  | `patchOrganization` | `CAP-CRM-ENT-004` |
  | `patchOrganizationType` | `CAP-CRM-ENT-018` |
  | `patchPhoneNumberType` | `CAP-CRM-ENT-018` |
  | `previewContactRoleComplianceEmail` | `CAP-CRM-ENT-012` |
  | `reconcileAffiliationDates` | `CAP-CRM-ENT-010` |
  | `recursivelyListContactsForOrganizationId` | `CAP-CRM-ENT-003` |
  | `relinkContactAddress` | `CAP-CRM-ENT-006` |
  | `relinkContactPhoneNumber` | `CAP-CRM-ENT-006` |
  | `removeContactAddress` | `CAP-CRM-ENT-006` |
  | `removeContactPhoneNumber` | `CAP-CRM-ENT-006` |
  | `renderEmailPreview` | `CAP-CRM-ENT-012` |
  | `reorderAddressTypes` | `CAP-CRM-ENT-018` |
  | `reorderContactRoles` | `CAP-CRM-ENT-017` |
  | `reorderContactTypes` | `CAP-CRM-ENT-018` |
  | `reorderOrganizationTypes` | `CAP-CRM-ENT-018` |
  | `reorderPhoneNumberTypes` | `CAP-CRM-ENT-018` |
  | `reprocessCompliance` | `CAP-CRM-ENT-012` |
  | `unarchiveContact` | `CAP-CRM-ENT-013` |
  | `unarchiveOrganization` | `CAP-CRM-ENT-013` |
  | `unlockContact` | `CAP-CRM-ENT-015` |
  | `unlockContactRole` | `CAP-CRM-ENT-015` |
  | `unlockOrganization` | `CAP-CRM-ENT-015` |
  | `updateAddressType` | `CAP-CRM-ENT-018` |
  | `updateAffiliationType` | `CAP-CRM-ENT-017` |
  | `updateContact` | `CAP-CRM-ENT-004` |
  | `updateContactRole` | `CAP-CRM-ENT-017` |
  | `updateContactType` | `CAP-CRM-ENT-018` |
  | `updateOrganization` | `CAP-CRM-ENT-004` |
  | `updateOrganizationType` | `CAP-CRM-ENT-018` |
  | `updatePhoneNumberType` | `CAP-CRM-ENT-018` |
  | `verifyContactAddress` | `CAP-CRM-ENT-006` |
  | `verifyContactPhoneNumber` | `CAP-CRM-ENT-006` |

  #### Tables

  | Table file | Capabilities |
  |---|---|
  | `address-types.table.ts` | `CAP-CRM-ENT-018` |
  | `affiliation-type-contact-info-defaults.table.ts` | `CAP-CRM-ENT-017` |
  | `affiliation-types.table.ts` | `CAP-CRM-ENT-017` |
  | `compliance-reprocesses.table.ts` | `CAP-CRM-ENT-012` |
  | `contact-addresses.table.ts` | `CAP-CRM-ENT-005`, `CAP-CRM-ENT-006` |
  | `contact-communication-preferences.table.ts` | `CAP-CRM-ENT-007` |
  | `contact-custom-field-values.table.ts` | `CAP-CRM-ENT-008` |
  | `contact-email-addresses.table.ts` | `CAP-CRM-ENT-005` |
  | `contact-organization-affiliations.table.ts` | `CAP-CRM-ENT-009` |
  | `contact-organization-roles.table.ts` | `CAP-CRM-ENT-011` |
  | `contact-phone-numbers.table.ts` | `CAP-CRM-ENT-005`, `CAP-CRM-ENT-006` |
  | `contact-roles.table.ts` | `CAP-CRM-ENT-017` |
  | `contact-types.table.ts` | `CAP-CRM-ENT-018` |
  | `contacts.table.ts` | `CAP-CRM-ENT-001`, `CAP-CRM-ENT-007` |
  | `crm-settings.table.ts` | `CAP-CRM-ENT-010`, `CAP-CRM-ENT-019` |
  | `managed-assets.table.ts` | `CAP-CRM-ENT-001`, `CAP-CRM-ENT-002` |
  | `organization-addresses.table.ts` | `CAP-CRM-ENT-005` |
  | `organization-compliance-violations.table.ts` | `CAP-CRM-ENT-012` |
  | `organization-custom-field-values.table.ts` | `CAP-CRM-ENT-008` |
  | `organization-phone-numbers.table.ts` | `CAP-CRM-ENT-005` |
  | `organization-types.table.ts` | `CAP-CRM-ENT-018` |
  | `organizations.table.ts` | `CAP-CRM-ENT-002` |
  | `phone-number-types.table.ts` | `CAP-CRM-ENT-018` |
  | `protected-records.table.ts` | `CAP-CRM-ENT-015` |
  | `record-lock-changes.table.ts` | `CAP-CRM-ENT-015` |
  | `record-revisions.table.ts` | `CAP-CRM-ENT-016` |

  #### E2E specifications

  | Spec file | Capabilities |
  |---|---|
  | `address-types.e2e.spec.js` | `CAP-CRM-ENT-018` |
  | `affiliation-date-reconciliation.e2e.spec.js` | `CAP-CRM-ENT-010` |
  | `affiliation-types.e2e.spec.js` | `CAP-CRM-ENT-017` |
  | `application-access-enforced.e2e.spec.js` | `CAP-CRM-ENT-003` |
  | `archive.e2e.spec.js` | `CAP-CRM-ENT-013` |
  | `contact-affiliations.e2e.spec.js` | `CAP-CRM-ENT-009` |
  | `contact-information-sources.e2e.spec.js` | `CAP-CRM-ENT-006`, `CAP-CRM-ENT-009` |
  | `contact-roles.e2e.spec.js` | `CAP-CRM-ENT-008`, `CAP-CRM-ENT-017` |
  | `contact-types.e2e.spec.js` | `CAP-CRM-ENT-018` |
  | `contacts-custom-fields.e2e.spec.js` | `CAP-CRM-ENT-008` |
  | `contacts-disconnected.e2e.spec.js` | `CAP-CRM-ENT-006` |
  | `contacts-history.e2e.spec.js` | `CAP-CRM-ENT-014`, `CAP-CRM-ENT-016` |
  | `contacts-names.e2e.spec.js` | `CAP-CRM-ENT-001` |
  | `contacts.e2e.spec.js` | `CAP-CRM-ENT-001`, `CAP-CRM-ENT-003`, `CAP-CRM-ENT-004`, `CAP-CRM-ENT-005`, `CAP-CRM-ENT-014`, `CAP-CRM-ENT-015` |
  | `display-links.e2e.spec.js` | `CAP-CRM-ENT-003` |
  | `email-previews.e2e.spec.js` | `CAP-CRM-ENT-012` |
  | `organization-compliance.e2e.spec.js` | `CAP-CRM-ENT-012` |
  | `organization-types.e2e.spec.js` | `CAP-CRM-ENT-002`, `CAP-CRM-ENT-012`, `CAP-CRM-ENT-018` |
  | `organizations-custom-fields.e2e.spec.js` | `CAP-CRM-ENT-008` |
  | `organizations-domain-name.e2e.spec.js` | `CAP-CRM-ENT-002` |
  | `organizations-history.e2e.spec.js` | `CAP-CRM-ENT-016` |
  | `organizations.e2e.spec.js` | `CAP-CRM-ENT-002`, `CAP-CRM-ENT-003`, `CAP-CRM-ENT-004`, `CAP-CRM-ENT-014`, `CAP-CRM-ENT-015` |
  | `page-layouts.e2e.spec.js` | `CAP-CRM-ENT-019` |
  | `phone-number-types.e2e.spec.js` | `CAP-CRM-ENT-018` |
  | `platform-scope.e2e.spec.js` | `CAP-CRM-ENT-003` |


  `e2e-security.js` supplies the identities and policies used to prove CAP-CRM-ENT-003 access control.

  ### Named permission-key homes

  | Key | Capability or dependency evidence |
  |---|---|
  | `crm.contacts.read` | CAP-CRM-ENT-003, CAP-CRM-ENT-005, CAP-CRM-ENT-007, CAP-CRM-ENT-008, CAP-CRM-ENT-009, CAP-CRM-ENT-010, CAP-CRM-ENT-012, CAP-CRM-ENT-015, CAP-CRM-ENT-016, CAP-CRM-ENT-019 |
  | `crm.contacts.create` | CAP-CRM-ENT-001 |
  | `crm.contacts.update` | CAP-CRM-ENT-004, CAP-CRM-ENT-005, CAP-CRM-ENT-006, CAP-CRM-ENT-007, CAP-CRM-ENT-008, CAP-CRM-ENT-009, CAP-CRM-ENT-011 |
  | `crm.contacts.delete` | CAP-CRM-ENT-014 |
  | `crm.contacts.bulk` | MOD-CRM-DJ dependency; CAP-CRM-ENT-001 evidence |
  | `crm.contacts.query` | Platform dependency; CAP-CRM-ENT-003 evidence |
  | `crm.contacts.history` | CAP-CRM-ENT-016 |
  | `crm.contacts.merge` | MOD-CRM-DQ dependency; CAP-CRM-ENT-003 evidence |
  | `crm.contacts.create-despite-duplicate-block` | CAP-CRM-ENT-001 |
  | `crm.contacts.lock` | CAP-CRM-ENT-015 |
  | `crm.contacts.unlock` | CAP-CRM-ENT-004, CAP-CRM-ENT-015 |
  | `crm.contacts.archive` | CAP-CRM-ENT-013 |
  | `crm.organizations.read` | CAP-CRM-ENT-003, CAP-CRM-ENT-008, CAP-CRM-ENT-009, CAP-CRM-ENT-012, CAP-CRM-ENT-015, CAP-CRM-ENT-016, CAP-CRM-ENT-019 |
  | `crm.organizations.create` | CAP-CRM-ENT-002 |
  | `crm.organizations.update` | CAP-CRM-ENT-004, CAP-CRM-ENT-005, CAP-CRM-ENT-006, CAP-CRM-ENT-008, CAP-CRM-ENT-012 |
  | `crm.organizations.delete` | CAP-CRM-ENT-014 |
  | `crm.organizations.bulk` | MOD-CRM-DJ dependency; CAP-CRM-ENT-002 evidence |
  | `crm.organizations.query` | Platform dependency; CAP-CRM-ENT-003 evidence |
  | `crm.organizations.history` | CAP-CRM-ENT-016 |
  | `crm.organizations.merge` | MOD-CRM-DQ dependency; CAP-CRM-ENT-003 evidence |
  | `crm.organizations.create-despite-duplicate-block` | CAP-CRM-ENT-002 |
  | `crm.organizations.lock` | CAP-CRM-ENT-015 |
  | `crm.organizations.unlock` | CAP-CRM-ENT-004, CAP-CRM-ENT-015 |
  | `crm.organizations.archive` | CAP-CRM-ENT-013 |
  | `crm.contact-roles.read` | CAP-CRM-ENT-011, CAP-CRM-ENT-015, CAP-CRM-ENT-017 |
  | `crm.contact-roles.create` | CAP-CRM-ENT-017 |
  | `crm.contact-roles.update` | CAP-CRM-ENT-017 |
  | `crm.contact-roles.delete` | CAP-CRM-ENT-017 |
  | `crm.contact-roles.bulk` | FND-CRM-ENT-013; CAP-CRM-ENT-017 evidence |
  | `crm.contact-roles.lock` | CAP-CRM-ENT-015 |
  | `crm.contact-roles.unlock` | CAP-CRM-ENT-015 |
  | `crm.contact-types.read` | CAP-CRM-ENT-001, CAP-CRM-ENT-018 |
  | `crm.contact-types.create` | CAP-CRM-ENT-018 |
  | `crm.contact-types.update` | CAP-CRM-ENT-018 |
  | `crm.contact-types.delete` | CAP-CRM-ENT-018 |
  | `crm.contact-types.bulk` | FND-CRM-ENT-013; CAP-CRM-ENT-018 evidence |
  | `crm.organization-types.read` | CAP-CRM-ENT-002, CAP-CRM-ENT-018 |
  | `crm.organization-types.create` | CAP-CRM-ENT-018 |
  | `crm.organization-types.update` | CAP-CRM-ENT-012, CAP-CRM-ENT-018 |
  | `crm.organization-types.delete` | CAP-CRM-ENT-018 |
  | `crm.organization-types.bulk` | FND-CRM-ENT-013; CAP-CRM-ENT-018 evidence |
  | `crm.affiliation-types.read` | CAP-CRM-ENT-009, CAP-CRM-ENT-017 |
  | `crm.affiliation-types.create` | CAP-CRM-ENT-017 |
  | `crm.affiliation-types.update` | CAP-CRM-ENT-017 |
  | `crm.affiliation-types.delete` | CAP-CRM-ENT-017 |
  | `crm.affiliation-types.bulk` | FND-CRM-ENT-013; CAP-CRM-ENT-017 evidence |
  | `crm.affiliation-types.set-default` | CAP-CRM-ENT-017 |
  | `crm.address-types.read` | CAP-CRM-ENT-005, CAP-CRM-ENT-018 |
  | `crm.address-types.create` | CAP-CRM-ENT-018 |
  | `crm.address-types.update` | CAP-CRM-ENT-018 |
  | `crm.address-types.delete` | CAP-CRM-ENT-018 |
  | `crm.address-types.bulk` | FND-CRM-ENT-013; CAP-CRM-ENT-018 evidence |
  | `crm.phone-number-types.read` | CAP-CRM-ENT-005, CAP-CRM-ENT-018 |
  | `crm.phone-number-types.create` | CAP-CRM-ENT-018 |
  | `crm.phone-number-types.update` | CAP-CRM-ENT-018 |
  | `crm.phone-number-types.delete` | CAP-CRM-ENT-018 |
  | `crm.phone-number-types.bulk` | FND-CRM-ENT-013; CAP-CRM-ENT-018 evidence |

  ## Changes by artifact

  The ACT-CRM-001 through ACT-CRM-005 allocation creates the product-area actor catalogue. FEAT-CRM-ENT-01 through FEAT-CRM-ENT-07 partition all capabilities and journeys. CON-CRM-ENT-001 through CON-CRM-ENT-002 identify product nouns, owners and sourced relationships, including external metadata and communication owners. MOD-CRM-ENT and PRODUCT-AREAS receive the corrected console scope; the charter’s index follows the final titles, intent values and evidence states. ID_REGISTRY preserves all original identifiers and reserves the additional concept, rule, scenario and finding identifiers before use.

  Every CAP, ATS and JNY receives final OpenAI wording in a separate artifact rewrite commit following verification. Purposes, narratives, rule statements, scenario text and acceptance instructions retain their verified facts and citations. FINDINGS and the charter receive separate final-language commits. The registry titles follow the final artifact titles.

  | Artifact | Material verification change |
  |---|---|
  | `CAP-CRM-ENT-001` and `ATS-CRM-ENT-001` | BR05 limits only the six enforced name fields; BR12 requires duplicate-override authority and a reason. ATS12 binds the actual refusal/override browser assertion; FND023 records the broader-name policy gap. |
  | `CAP-CRM-ENT-002` and `ATS-CRM-ENT-002` | BR08 states the real status schema. BR11 becomes unknown pending organization-specific duplicate proof; ATS11 is added and FND029 records the gap. |
  | `CAP-CRM-ENT-003` and `ATS-CRM-ENT-003` | BR02 includes nickname through computed-name search. BR05 narrows picker coverage to the tested list. BR14 is a proposed display requirement, and BR15 describes the observed Quick Search indexing path only. |
  | `CAP-CRM-ENT-004` and `ATS-CRM-ENT-004` | BR04 names replacement exceptions; BR06 distinguishes ignored derived organization values from refusals. BR12 becomes a documented session-recovery obligation with FND022 instead of a misleading refresh binding. |
  | `CAP-CRM-ENT-005` and `ATS-CRM-ENT-005` | Sources and rule evidence are examined; acceptance levels follow API or console dependence. No outcome or ownership change is required. |
  | `CAP-CRM-ENT-006` and `ATS-CRM-ENT-006` | Background enforcement uses service, not job. BR13 is limited to the approved shared-address warning and remains proposed without implemented enforcement; FND010 retains the proof gap. |
  | `CAP-CRM-ENT-007` and `ATS-CRM-ENT-007` | BR06 describes the scoped communication preference contract without claiming downstream sender behavior. |
  | `CAP-CRM-ENT-008` and `ATS-CRM-ENT-008` | Stored custom values remain distinct from Platform definitions; proof levels reflect service and database evidence. |
  | `CAP-CRM-ENT-009` and `ATS-CRM-ENT-009` | BR12 cites the console departure helper and ends the old affiliation before the new start, bounded by its own start. ATS12 remains proposed without a binding that proves the whole departure interaction. |
  | `CAP-CRM-ENT-010` and `ATS-CRM-ENT-010` | Background enforcement is recorded as service; disabled scheduling remains FND007 rather than an unconditional running-schedule claim. |
  | `CAP-CRM-ENT-011` and `ATS-CRM-ENT-011` | BR02 accounts for role closure when an affiliation ends. BR11 cites M2-D12 as documented intent with FND028 for missing proof. The primary/nonprimary discrepancy is unknown and points to FND008; import behavior stays proposed. |
  | `CAP-CRM-ENT-012` and `ATS-CRM-ENT-012` | BR09 resolves the actual document heading. BR10 uses the organization-update key rather than an administrator label. BR13 removes the false notification-role prerequisite and records numeric-bound limitations. BR15–17 and ATS14–16 cover template merging, compensation and post-delete archival; FND024,025,027 preserve remaining risks. |
  | `CAP-CRM-ENT-013` and `ATS-CRM-ENT-013` | Archive and restore rules are checked against retained identity and version evidence; acceptance levels follow the tested surface. |
  | `CAP-CRM-ENT-014` and `ATS-CRM-ENT-014` | Owner-deletion behavior stays conditional on its switch. Background processing is service enforcement; FND006 records the default-off limitation. |
  | `CAP-CRM-ENT-015` and `ATS-CRM-ENT-015` | BR01 distinguishes dedicated lock actions from permitted ordinary delete-lock values. BR04 preserves unchanged lock round-tripping; sources establish protected-record behavior. |
  | `CAP-CRM-ENT-016` and `ATS-CRM-ENT-016` | History and merged-record references remain distinct; proof levels reflect backend and console evidence. |
  | `CAP-CRM-ENT-017` and `ATS-CRM-ENT-017` | BR09 narrows confirmed descriptive intent. BR11 gains actual inactive-column browser evidence and ATS10; saved-query execution remains FND012. Unused bulk keys move out of claimed API permissions and remain catalog evidence. |
  | `CAP-CRM-ENT-018` and `ATS-CRM-ENT-018` | BR07 names preservation exceptions in type replacement. Unused bulk keys move out of claimed API permissions; destructive omission remains an open product contract. |
  | `CAP-CRM-ENT-019` and `ATS-CRM-ENT-019` | The example requests effective definitions through the API rather than claiming a browser editor interaction from an API test. Platform-owned form and layout concepts are linked. |

  | Journey | Material verification change |
  |---|---|
  | `JNY-CRM-ENT-001` | Binds actual browser evidence; distinguishes inspected cards from hidden communication preferences; evidence is partially observed. |
  | `JNY-CRM-ENT-002` | Removes automatic-role creation from a fixture that does not configure it; corrects departure dates. |
  | `JNY-CRM-ENT-003` | Keeps archival separate from deletion and preserves historical attribution. |
  | `JNY-CRM-ENT-004` | Replaces unsupported inference with the observed affiliation selector; records API fallback limits through FND026. |
  | `JNY-CRM-ENT-005` | Separates current membership, dated affiliation rows and primary search labels. |

  All five journey intent values are proposed because the draft does not provide a scoped product record confirming each complete end-to-end narrative. Capability-level confirmation applies only to its cited milestone outcome; OQ-CRM-ENT-003 explains why observed details still need separate decisions.

  ### Changed evidence and contract fields

  This ledger records nonwording field changes against the supplied starting commit. Feature, actor and concept references are accounted for above. New rows keep their newly allocated identifiers.

  | Artifact | Field | Before | After |
  |---|---|---|---|
  | `CAP-CRM-ENT-001` | `purpose` | "Staff record a person once, with a name the system can sort and search, a server-owned number and an optional type, so every other part of Rhythm can refer to them." | "Staff establish an identifiable record for a person and keep the information needed for later CRM work." |
  | `CAP-CRM-ENT-001` | `outcomes` | ["A new contact exists with its computed names, number and id, and every value entered landed exactly once","A refused create writes nothing and names every problem","A retried create never makes a second person"] | ["A new contact exists with its computed names, number and id, and every value entered was saved exactly once.","A rejected create writes nothing and names every problem.","A retried create never makes a second person."] |
  | `CAP-CRM-ENT-001` | `postconditions` | ["The contact answers a read with the values it was created with, and its number is never reused"] | ["After completion, the contact can be retrieved with the values it was created with, and its number is never reused."] |
  | `CAP-CRM-ENT-001` | `rules.BR-CAP-CRM-ENT-001-01.examples.positive` | "Last name \"Hopper\" alone is saved and sorted as \"Hopper\"." | "Accepted example: last name \"Hopper\" alone is saved and sorted as \"Hopper\"." |
  | `CAP-CRM-ENT-001` | `rules.BR-CAP-CRM-ENT-001-01.examples.negative` | "First name of spaces and no last name is refused 400 naming first_name." | "Rejected example: first name of spaces and no last name is rejected 400 naming first_name." |
  | `CAP-CRM-ENT-001` | `rules.BR-CAP-CRM-ENT-001-02.examples.positive` | "Dr./Grace/Brewster/Amazing/Hopper/Jr/PhD gives \"Grace B. \"Amazing\" Hopper Jr, PhD\"." | "Accepted example: dr./Grace/Brewster/Amazing/Hopper/Jr/PhD gives \"Grace B. \"Amazing\" Hopper Jr, PhD\"." |
  | `CAP-CRM-ENT-001` | `rules.BR-CAP-CRM-ENT-001-02.examples.negative` | "A last name only gives the sort name \"Solo\", never \"Solo,\"." | "Rejected example: a last name only gives the sort name \"Solo\", never \"Solo,\"." |
  | `CAP-CRM-ENT-001` | `rules.BR-CAP-CRM-ENT-001-04.examples.positive` | "Salutation \"mr\" is stored as prefix \"Mr.\" with no salutation." | "Accepted example: salutation \"mr\" is stored as prefix \"Mr.\" with no salutation." |
  | `CAP-CRM-ENT-001` | `rules.BR-CAP-CRM-ENT-001-04.examples.negative` | "Salutation \"Dear colleague\" is kept as typed." | "Rejected example: salutation \"Dear colleague\" is preserved as typed." |
  | `CAP-CRM-ENT-001` | `rules.BR-CAP-CRM-ENT-001-05.examples.positive` | "A first name of exactly 200 characters is accepted." | "Accepted example: a first name of exactly 200 characters is accepted." |
  | `CAP-CRM-ENT-001` | `rules.BR-CAP-CRM-ENT-001-05.examples.negative` | "Notes of 10,001 characters are refused naming notes." | "Rejected example: notes of 10,001 characters are rejected naming notes." |
  | `CAP-CRM-ENT-001` | `rules.BR-CAP-CRM-ENT-001-06.examples.positive` | "A create naming no id answers a UUIDv7 id." | "Accepted example: a create naming no id returns a UUIDv7 id." |
  | `CAP-CRM-ENT-001` | `rules.BR-CAP-CRM-ENT-001-06.examples.negative` | "A create naming an id the tenant already uses is refused 400." | "Rejected example: a create naming an id the tenant already uses is rejected 400." |
  | `CAP-CRM-ENT-001` | `rules.BR-CAP-CRM-ENT-001-07.examples.positive` | "Two creates in a row answer consecutive numbers." | "Accepted example: two creates in a row answer consecutive numbers." |
  | `CAP-CRM-ENT-001` | `rules.BR-CAP-CRM-ENT-001-07.examples.negative` | "A body naming number 5 answers the tenant's next number." | "Rejected example: a body naming number 5 returns the tenant’s next number." |
  | `CAP-CRM-ENT-001` | `rules.BR-CAP-CRM-ENT-001-09.examples.positive` | "A contact with no type is saved and listed as \"No type\"." | "Accepted example: a contact with no type is saved and listed as \"No type\"." |
  | `CAP-CRM-ENT-001` | `rules.BR-CAP-CRM-ENT-001-09.examples.negative` | "A type id the tenant lacks is refused 409." | "Rejected example: a type id the tenant lacks is rejected 409." |
  | `CAP-CRM-ENT-001` | `rules.BR-CAP-CRM-ENT-001-10.examples.positive` | "Status \"deceased\" is saved." | "Accepted example: status \"deceased\" is saved." |
  | `CAP-CRM-ENT-001` | `rules.BR-CAP-CRM-ENT-001-10.examples.negative` | "Status \"archived\" is refused 400." | "Rejected example: status \"archived\" is rejected 400." |
  | `CAP-CRM-ENT-001` | `rules.BR-CAP-CRM-ENT-001-11.examples.positive` | "A names B as spouse; B reads A as spouse with its version bumped once." | "Accepted example: a names B as spouse; B retrieves A as spouse with its version advanced once." |
  | `CAP-CRM-ENT-001` | `rules.BR-CAP-CRM-ENT-001-11.examples.negative` | "A spouse of another tenant is refused 409." | "Rejected example: a spouse of another tenant is rejected 409." |
  | `CAP-CRM-ENT-001` | `rules.BR-CAP-CRM-ENT-001-12.provenance` | "observed" | "test" |
  | `CAP-CRM-ENT-001` | `rules.BR-CAP-CRM-ENT-001-12.source` | "services-crm:modules/entities/services/contacts/contact-create.ts:createRequestedContact" | "react-console:acceptance/crm/playwright/journeys/contacts/CRM-ACC-0042.spec.ts#CRM-ACC-0042" |
  | `CAP-CRM-ENT-002` | `implementation_evidence` | "observed" | "partially-observed" |
  | `CAP-CRM-ENT-002` | `purpose` | "Staff record the organizations people belong to (companies, chapters, schools), each with a type, a number and an optional parent, so the tenant can model its federation and its members' employers." | "Staff establish an organization record and position it within the tenant’s organizational structure." |
  | `CAP-CRM-ENT-002` | `outcomes` | ["An organization exists with its number, id, type and parent, and its ancestry is answered on every read","A loop in the hierarchy can never be saved","A refused create writes nothing and reports every problem at once"] | ["An organization exists with its number, id, type and parent, and its ancestry is returned on every read.","A loop in the hierarchy can never be saved.","A rejected create writes nothing and reports every problem at once."] |
  | `CAP-CRM-ENT-002` | `rules.BR-CAP-CRM-ENT-002-01.examples.positive` | "A name of exactly 200 characters is accepted." | "Accepted example: a name of exactly 200 characters is accepted." |
  | `CAP-CRM-ENT-002` | `rules.BR-CAP-CRM-ENT-002-01.examples.negative` | "A name of spaces is refused 400 naming name." | "Rejected example: a name of spaces is rejected 400 naming name." |
  | `CAP-CRM-ENT-002` | `rules.BR-CAP-CRM-ENT-002-06.examples.positive` | "A under B under a top: saved." | "Accepted example: a under B under a top: saved." |
  | `CAP-CRM-ENT-002` | `rules.BR-CAP-CRM-ENT-002-06.examples.negative` | "The top moved under its grandchild: 400 naming the parent field." | "Rejected example: the top moved under its grandchild: 400 naming the parent field." |
  | `CAP-CRM-ENT-002` | `rules.BR-CAP-CRM-ENT-002-08.enforced_at` | ["api","database","service"] | ["api","database"] |
  | `CAP-CRM-ENT-002` | `rules.BR-CAP-CRM-ENT-002-11.must_prove` | false | true |
  | `CAP-CRM-ENT-002` | `rules.BR-CAP-CRM-ENT-002-11.provenance` | "observed" | "unknown" |
  | `CAP-CRM-ENT-002` | `rules.BR-CAP-CRM-ENT-002-11.source` | "services-crm:modules/entities/aws/api/organizations.routes.ts:createOrganization" | "FND-CRM-ENT-029" |
  | `CAP-CRM-ENT-003` | `product_intent` | "confirmed" | "proposed" |
  | `CAP-CRM-ENT-003` | `purpose` | "Staff and integrations find the people and organizations of their tenant and read each one whole, and never anyone else's." | "Staff and integrations locate records and read the information their work requires." |
  | `CAP-CRM-ENT-003` | `outcomes` | ["A list walks the tenant's records a page at a time with a stable cursor","The people beneath an organization are the same set wherever they are listed","A record answers every stored detail, and another tenant's record is never reachable"] | ["A list walks the tenant’s records a page at a time with a stable cursor.","The people beneath an organization are the same set wherever they are listed.","A record returns every stored detail, and another tenant’s record is never reachable."] |
  | `CAP-CRM-ENT-003` | `rules.BR-CAP-CRM-ENT-003-01.examples.positive` | "limit=2 over five contacts walks three pages, the last without a cursor." | "Accepted example: limit=2 over five contacts walks three pages, the last without a cursor." |
  | `CAP-CRM-ENT-003` | `rules.BR-CAP-CRM-ENT-003-01.examples.negative` | "limit=101 is refused 400." | "Rejected example: limit=101 is rejected 400." |
  | `CAP-CRM-ENT-003` | `rules.BR-CAP-CRM-ENT-003-02.provenance` | "test" | "observed" |
  | `CAP-CRM-ENT-003` | `rules.BR-CAP-CRM-ENT-003-02.source` | "services-crm:modules/entities/tests/integration/services/persistence/contacts.queries.integration.spec.js#matches \"Lovelace, Ada\" too: the name is searched in both of the orders a contact is written in" | "services-crm:modules/entities/services/persistence/contacts.ts:listContactFields" |
  | `CAP-CRM-ENT-003` | `rules.BR-CAP-CRM-ENT-003-02.examples.positive` | "\"smith, j\" finds \"Smith, John\"." | "Accepted example: \"smith, j\" finds \"Smith, John\"." |
  | `CAP-CRM-ENT-003` | `rules.BR-CAP-CRM-ENT-003-02.examples.negative` | "A search of 101 characters is refused." | "Rejected example: a search of 101 characters is rejected." |
  | `CAP-CRM-ENT-003` | `rules.BR-CAP-CRM-ENT-003-05.enforced_at` | ["api","service","console"] | ["api","service"] |
  | `CAP-CRM-ENT-003` | `rules.BR-CAP-CRM-ENT-003-14.enforced_at` | ["console"] | [] |
  | `CAP-CRM-ENT-003` | `rules.BR-CAP-CRM-ENT-003-15.provenance` | "documented" | "observed" |
  | `CAP-CRM-ENT-003` | `rules.BR-CAP-CRM-ENT-003-15.source` | "services-crm:docs/milestones/CRM-M1-contacts-and-organizations.plan.md#7. Deliverables" | "services-crm:modules/entities/services/quick-search/quick-search-indexer.ts:quickSearchIndexerOf" |
  | `CAP-CRM-ENT-004` | `product_intent` | "confirmed" | "proposed" |
  | `CAP-CRM-ENT-004` | `purpose` | "Staff and integrations correct contacts and organizations knowing that a save changes only what they meant, never silently overwrites a colleague, and either lands whole or not at all." | "Staff correct records while retaining changes another person or the system has already made." |
  | `CAP-CRM-ENT-004` | `outcomes` | ["A stale save is refused and says who changed the record","A save that changes nothing leaves no trace","A refused save leaves every row as it was"] | ["A stale save is rejected and says who changed the record.","A save that changes nothing leaves no trace.","A rejected save leaves every row as it was."] |
  | `CAP-CRM-ENT-004` | `rules.BR-CAP-CRM-ENT-004-01.examples.positive` | "A patch led by test /sys_version at the current version is applied and bumps it once." | "Accepted example: a patch led by test /sys_version at the current version is applied and advances it once." |
  | `CAP-CRM-ENT-004` | `rules.BR-CAP-CRM-ENT-004-01.examples.negative` | "Two patches at the same version: the second is refused 409 and the first writer's value is kept." | "Rejected example: two patches at the same version: the second is rejected 409 and the first writer's value is preserved." |
  | `CAP-CRM-ENT-004` | `rules.BR-CAP-CRM-ENT-004-04.origin` | "services-crm:docs/milestones/CRM-M2-affiliations-roles-compliance.md#D-09" | "none" |
  | `CAP-CRM-ENT-004` | `rules.BR-CAP-CRM-ENT-004-04.examples.positive` | "A replacement without job_title clears it." | "Accepted example: a replacement without job_title clears it." |
  | `CAP-CRM-ENT-004` | `rules.BR-CAP-CRM-ENT-004-04.examples.negative` | "A replacement without addresses removes every address." | "Rejected example: a replacement without addresses removes every address." |
  | `CAP-CRM-ENT-004` | `rules.BR-CAP-CRM-ENT-004-12.enforced_at` | ["console"] | [] |
  | `CAP-CRM-ENT-004` | `rules.BR-CAP-CRM-ENT-004-12.provenance` | "test" | "documented" |
  | `CAP-CRM-ENT-004` | `rules.BR-CAP-CRM-ENT-004-12.source` | "react-console:acceptance/crm/playwright/journeys/contacts/CRM-ACC-0013.spec.ts#CRM-ACC-0013" | "services-crm:docs/milestones/CRM-M1-contacts-and-organizations.plan.md#A14" |
  | `CAP-CRM-ENT-005` | `purpose` | "Staff keep how to reach a person or an organization, typed by the tenant's own address and phone types, so mail, calls and e-mail go to the right place and one e-mail identifies one active person." | "Staff maintain the contact points used to reach people and organizations." |
  | `CAP-CRM-ENT-005` | `outcomes` | ["Each contact has at most three e-mails with one primary that no other active contact holds","Each contact and organization has at most one address and one phone number per tenant type, with one preferred","A seasonal address is a recurring season and decides the mailing address while in season"] | ["Each contact has at most three e-mails with one primary that no other active contact holds.","Each contact and organization has at most one address and one phone number per tenant type, with one preferred.","A seasonal address is a recurring season and decides the mailing address while in season."] |
  | `CAP-CRM-ENT-005` | `rules.BR-CAP-CRM-ENT-005-01.examples.positive` | "\"Ada@Example.com \" is stored as \"ada@example.com\" at position 1." | "Accepted example: \"Ada@Example.com \" is stored as \"ada@example.com\" at position 1." |
  | `CAP-CRM-ENT-005` | `rules.BR-CAP-CRM-ENT-005-01.examples.negative` | "A fourth address is refused." | "Rejected example: a fourth address is rejected." |
  | `CAP-CRM-ENT-005` | `rules.BR-CAP-CRM-ENT-005-02.examples.positive` | "Another contact may take the primary address of a deceased contact." | "Accepted example: another contact may take the primary address of a deceased contact." |
  | `CAP-CRM-ENT-005` | `rules.BR-CAP-CRM-ENT-005-02.examples.negative` | "A second active contact with \"ADA@example.com\" as primary is refused 409." | "Rejected example: a second active contact with \"ADA@example.com\" as primary is rejected 409." |
  | `CAP-CRM-ENT-005` | `rules.BR-CAP-CRM-ENT-005-04.examples.positive` | "\"202-555-0143\" is stored as \"(202) 555-0143\"." | "Accepted example: \"202-555-0143\" is stored as \"(202) 555-0143\"." |
  | `CAP-CRM-ENT-005` | `rules.BR-CAP-CRM-ENT-005-04.examples.negative` | "\"+44 20 7946 0958\" is stored as typed." | "Rejected example: \"+44 20 7946 0958\" is stored as typed." |
  | `CAP-CRM-ENT-006` | `product_intent` | "confirmed" | "proposed" |
  | `CAP-CRM-ENT-006` | `purpose` | "A person's work address and phone can come from the organization they work for and follow it when it moves, and when the organization removes the record the person keeps the last value, marked for verification." | "Staff share organization details with affiliated people and handle links whose sources disappear." |
  | `CAP-CRM-ENT-006` | `outcomes` | ["A linked row always shows the organization's current value while the tie is in effect, without rewriting the contact","No contact silently loses a value or keeps an unmarked stale one","A coordinator chooses which of a tie's default links are made"] | ["A linked row always displays the organization's current value while the affiliation is in effect, without rewriting the contact.","No contact silently loses a value or preserves an unmarked stale one.","A staff member chooses which of a affiliation's default links are made."] |
  | `CAP-CRM-ENT-006` | `rules.BR-CAP-CRM-ENT-006-12.enforced_at` | ["service","job"] | ["service"] |
  | `CAP-CRM-ENT-006` | `rules.BR-CAP-CRM-ENT-006-13.enforced_at` | ["console","api"] | [] |
  | `CAP-CRM-ENT-007` | `purpose` | "Staff record a person's communication restrictions (do not mail, do not call, e-mail opt-out) and per-type subscription preferences, so the people who contact members can see and, later, the senders can honour them." | "Staff record a person’s communication restrictions and subscription choices." |
  | `CAP-CRM-ENT-007` | `outcomes` | ["Each contact carries its three restrictions and at most one preference per communication type","The restrictions are visible on the Contact 360 header"] | ["Each contact carries its three restrictions and at most one preference per communication type.","The restrictions are visible on the Contact 360 header."] |
  | `CAP-CRM-ENT-008` | `purpose` | "A tenant stores the facts it defines itself (member since, dues, chapter code) on contacts and organizations, typed and validated by its own field definitions." | "Staff store the tenant’s additional information alongside contact and organization records." |
  | `CAP-CRM-ENT-008` | `outcomes` | ["Every custom value is stored in the type its field defines, or the save is refused at that key","A write changes only the keys it names"] | ["Every custom value is stored in the type its field defines, or the save is rejected at that key.","A write changes only the keys it names."] |
  | `CAP-CRM-ENT-009` | `purpose` | "Staff record a person's ties to organizations (employer, school, chapter) with dates and job titles, one of them the person's primary organization, and the organization lists its people the same way." | "Staff keep a person’s organizational memberships, employment and primary organization understandable over time." |
  | `CAP-CRM-ENT-009` | `outcomes` | ["A person's ties are history, not overwrites: ending a tie keeps it, changing employer never leaves two primaries","The organization's people list and the person's affiliations agree","A save that leaves out the affiliations never erases them"] | ["A person’s affiliations are history, not overwrites: ending a affiliation preserves it, changing employer never leaves two primaries.","The organization's people list and the person’s affiliations agree.","A save that leaves out the affiliations never erases them."] |
  | `CAP-CRM-ENT-009` | `rules.BR-CAP-CRM-ENT-009-12.provenance` | "test" | "observed" |
  | `CAP-CRM-ENT-009` | `rules.BR-CAP-CRM-ENT-009-12.source` | "react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0201.spec.ts#CRM-ACC-0201" | "react-console:lib/affiliations/section.ts:affiliationBeingLeft" |
  | `CAP-CRM-ENT-010` | `purpose` | "Whether a tie is upcoming, current or past is decided by the workspace's own calendar, the same in every screen and service, and a start or end that arrives by date alone takes effect without anyone saving." | "Rhythm follows the workspace calendar when relationships start or stop taking effect." |
  | `CAP-CRM-ENT-010` | `outcomes` | ["Upcoming, Current and Past never overlap, and counts, rows and the service agree","A job starting next month becomes current, with its roles and compliance, on its start day"] | ["Upcoming, Current and Past never overlap, and counts, rows and the service agree.","A job starting next month becomes current, with its roles and compliance, on its start day."] |
  | `CAP-CRM-ENT-010` | `rules.BR-CAP-CRM-ENT-010-04.enforced_at` | ["job","service"] | ["service"] |
  | `CAP-CRM-ENT-010` | `rules.BR-CAP-CRM-ENT-010-05.enforced_at` | ["job","service"] | ["service"] |
  | `CAP-CRM-ENT-010` | `rules.BR-CAP-CRM-ENT-010-06.enforced_at` | ["job","service"] | ["service"] |
  | `CAP-CRM-ENT-010` | `rules.BR-CAP-CRM-ENT-010-08.enforced_at` | ["job"] | ["service"] |
  | `CAP-CRM-ENT-011` | `product_intent` | "confirmed" | "proposed" |
  | `CAP-CRM-ENT-011` | `purpose` | "Staff record the roles a person holds at an organization (Billing Contact, Treasurer, President), each a dated period on one tie, and the tenant's automatic roles are given when someone joins, so organizations always know who to contact for what." | "Staff assign organizational responsibilities and configure automatic assignment where appropriate." |
  | `CAP-CRM-ENT-011` | `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"] | ["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."] |
  | `CAP-CRM-ENT-011` | `rules.BR-CAP-CRM-ENT-011-07.enforced_at` | ["service","job"] | ["service"] |
  | `CAP-CRM-ENT-011` | `rules.BR-CAP-CRM-ENT-011-08.enforced_at` | ["service","job"] | ["service"] |
  | `CAP-CRM-ENT-011` | `rules.BR-CAP-CRM-ENT-011-09.enforced_at` | ["service","job"] | ["service"] |
  | `CAP-CRM-ENT-011` | `rules.BR-CAP-CRM-ENT-011-10.enforced_at` | ["service","job"] | ["service"] |
  | `CAP-CRM-ENT-011` | `rules.BR-CAP-CRM-ENT-011-11.provenance` | "inferred" | "documented" |
  | `CAP-CRM-ENT-011` | `rules.BR-CAP-CRM-ENT-011-11.source` | "services-crm:modules/entities/services/contacts/role-assignment/contact-role-assignment.ts:automaticRolesDecidedFor" | "services-crm:docs/milestones/CRM-M2-affiliations-roles-compliance.md#M2-D12" |
  | `CAP-CRM-ENT-011` | `rules.BR-CAP-CRM-ENT-011-14.enforced_at` | ["job"] | [] |
  | `CAP-CRM-ENT-011` | `edge_cases.SC-CAP-CRM-ENT-011-03.provenance` | "inferred" | "unknown" |
  | `CAP-CRM-ENT-011` | `edge_cases.SC-CAP-CRM-ENT-011-03.source` | "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" | "FND-CRM-ENT-008" |
  | `CAP-CRM-ENT-012` | `purpose` | "An organization type can require roles (every chapter needs a Treasurer, at most two Voting Delegates); each organization shows whether it meets them, and its contacts are e-mailed once when it falls short." | "Staff assess an organization’s required role holders and prepare communication about missing responsibilities." |
  | `CAP-CRM-ENT-012` | `outcomes` | ["Each organization held to rules carries a status and the violations that explain it","A notice goes out exactly once per fall into non-compliance","An administrator can preview the notice and re-apply changed rules to the whole tenant"] | ["Each organization retained to rules carries a status and the violations that explain it.","A notice moves out exactly once per fall into non-compliance.","An administrator can preview the notice and re-apply changed rules to the complete tenant."] |
  | `CAP-CRM-ENT-012` | `rules.BR-CAP-CRM-ENT-012-04.enforced_at` | ["job","service"] | ["service"] |
  | `CAP-CRM-ENT-012` | `rules.BR-CAP-CRM-ENT-012-09.source` | "services-crm:docs/entities-api.md#compliance_notification_template: the e-mail the type sends" | "services-crm:docs/entities-api.md#`compliance_notification_template`: the e-mail the type sends" |
  | `CAP-CRM-ENT-012` | `rules.BR-CAP-CRM-ENT-012-10.enforced_at` | ["api","service","job"] | ["api","service"] |
  | `CAP-CRM-ENT-012` | `rules.BR-CAP-CRM-ENT-012-13.provenance` | "test" | "observed" |
  | `CAP-CRM-ENT-012` | `rules.BR-CAP-CRM-ENT-012-13.source` | "services-crm:modules/entities/tests/e2e/organization-types.e2e.spec.js#answers 409 for a rule of a role the tenant does not have, and saves nothing" | "services-crm:modules/entities/services/persistence/organization-types.ts:organizationTypeProblems" |
  | `CAP-CRM-ENT-012` | `rules.BR-CAP-CRM-ENT-012-15` | "not allocated" | "added" |
  | `CAP-CRM-ENT-012` | `rules.BR-CAP-CRM-ENT-012-16` | "not allocated" | "added" |
  | `CAP-CRM-ENT-012` | `rules.BR-CAP-CRM-ENT-012-17` | "not allocated" | "added" |
  | `CAP-CRM-ENT-013` | `purpose` | "An administrator takes a person or an organization out of active use without deleting it: it leaves lists and pickers, keeps its history and every reference to it, and can be brought back unchanged." | "Administrators retain records that should leave ordinary use and restore them when needed." |
  | `CAP-CRM-ENT-013` | `outcomes` | ["An archived record is out of every default list and picker and cannot be edited","Every affiliation that names an archived organization keeps it, badged archived","Unarchive returns the record as it was"] | ["An archived record is out of every default list and picker and cannot be edited.","Every affiliation that names an archived organization preserves it, badged archived.","Unarchive returns the record as it was."] |
  | `CAP-CRM-ENT-014` | `purpose` | "An administrator removes a record that should never have existed, taking everything it owns with it, while records that others depend on are protected from deletion and its history survives." | "Administrators remove a contact or organization when its deletion dependencies permit it." |
  | `CAP-CRM-ENT-014` | `outcomes` | ["A deleted contact's collections, affiliations and roles go with it and its history remains readable","An organization others depend on cannot be deleted","A refused delete removes nothing"] | ["A deleted contact's collections, affiliations and roles move with it and its history remains readable.","An organization others depend on cannot be deleted.","A rejected delete removes nothing."] |
  | `CAP-CRM-ENT-014` | `rules.BR-CAP-CRM-ENT-014-06.enforced_at` | ["service","job"] | ["service"] |
  | `CAP-CRM-ENT-015` | `purpose` | "An administrator can freeze a contact, an organization or a contact role against deletion or against every change, release it again through an audited action, and Rhythm's own protected records cannot be released by anyone." | "Administrators control customer locks while Rhythm preserves the separate protections of system records." |
  | `CAP-CRM-ENT-015` | `outcomes` | ["A lock is set and released only by an authorised, audited action","A locked record or element refuses what its lock names","A protected system record cannot be unlocked or deleted"] | ["A lock is set and released only by an authorised, audited action.","A locked record or element rejects what its lock names.","A protected system record cannot be unlocked or deleted."] |
  | `CAP-CRM-ENT-015` | `rules.BR-CAP-CRM-ENT-015-01.provenance` | "test" | "observed" |
  | `CAP-CRM-ENT-015` | `rules.BR-CAP-CRM-ENT-015-01.source` | "services-crm:modules/entities/tests/unit/api/record-lock-api-mapper.spec.js#publishes all six at tier admin, so administrators hold them and ordinary users do not" | "services-crm:modules/entities/aws/api/record-locks.routes.ts:defineRecordLockRoutes" |
  | `CAP-CRM-ENT-016` | `purpose` | "Staff see the whole story of a person or an organization: every committed change, who made it, through what, and the values before and after, even after the record is deleted." | "Readers trace changes to contacts and organizations, including records that have been deleted." |
  | `CAP-CRM-ENT-016` | `outcomes` | ["Every committed save leaves exactly one revision, and a save that changes nothing leaves none","A reader can filter the timeline and open any revision section by section","History cannot be forged or rewritten by the application"] | ["Every committed save leaves exactly one revision, and a save that changes nothing leaves none.","A reader can filter the timeline and open any revision section by section.","History cannot be forged or rewritten by the application."] |
  | `CAP-CRM-ENT-017` | `product_intent` | "confirmed" | "proposed" |
  | `CAP-CRM-ENT-017` | `purpose` | "An administrator maintains the kinds of tie a person can have with an organization (Employer, School, Chapter) with their default links, the workspace's default kind, and the catalogue of contact roles with their automatic behaviour and order." | "Administrators define the relationship categories and responsibilities used by the tenant." |
  | `CAP-CRM-ENT-017` | `outcomes` | ["Every affiliation and role names a kind or role the tenant maintains","A kind or role in use cannot be deleted","The workspace default kind is chosen only by an administrator"] | ["Every affiliation and role names a type or role the tenant maintains.","A type or role in use cannot be deleted.","The workspace default type is chosen only by an administrator."] |
  | `CAP-CRM-ENT-017` | `permissions` | [{"key":"crm.contact-roles.read","where_checked":"api","scope":"tenant"},{"key":"crm.contact-roles.create","where_checked":"api","scope":"tenant"},{"key":"crm.contact-roles.update","where_checked":"api","scope":"tenant"},{"key":"crm.contact-roles.delete","where_checked":"api","scope":"tenant"},{"key":"crm.contact-roles.bulk","where_checked":"api","scope":"tenant"},{"key":"crm.affiliation-types.read","where_checked":"api","scope":"tenant"},{"key":"crm.affiliation-types.create","where_checked":"api","scope":"tenant"},{"key":"crm.affiliation-types.update","where_checked":"api","scope":"tenant"},{"key":"crm.affiliation-types.delete","where_checked":"api","scope":"tenant"},{"key":"crm.affiliation-types.bulk","where_checked":"api","scope":"tenant"},{"key":"crm.affiliation-types.set-default","where_checked":"api","scope":"tenant"}] | [{"key":"crm.contact-roles.read","where_checked":"api","scope":"tenant"},{"key":"crm.contact-roles.create","where_checked":"api","scope":"tenant"},{"key":"crm.contact-roles.update","where_checked":"api","scope":"tenant"},{"key":"crm.contact-roles.delete","where_checked":"api","scope":"tenant"},{"key":"crm.affiliation-types.read","where_checked":"api","scope":"tenant"},{"key":"crm.affiliation-types.create","where_checked":"api","scope":"tenant"},{"key":"crm.affiliation-types.update","where_checked":"api","scope":"tenant"},{"key":"crm.affiliation-types.delete","where_checked":"api","scope":"tenant"},{"key":"crm.affiliation-types.set-default","where_checked":"api","scope":"tenant"}] |
  | `CAP-CRM-ENT-017` | `rules.BR-CAP-CRM-ENT-017-09.enforced_at` | ["api","console"] | ["console"] |
  | `CAP-CRM-ENT-017` | `rules.BR-CAP-CRM-ENT-017-11.enforced_at` | ["service"] | [] |
  | `CAP-CRM-ENT-017` | `rules.BR-CAP-CRM-ENT-017-11.provenance` | "unknown" | "test" |
  | `CAP-CRM-ENT-017` | `rules.BR-CAP-CRM-ENT-017-11.source` | "FND-CRM-ENT-012" | "react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0199.spec.ts#CRM-ACC-0199" |
  | `CAP-CRM-ENT-018` | `purpose` | "An administrator maintains the tenant's own classifications of people, organizations, addresses and phone numbers, and their order, so records are typed in the tenant's words and forms and pickers list them the tenant's way." | "Administrators maintain the categories used to classify records and their contact details." |
  | `CAP-CRM-ENT-018` | `outcomes` | ["Every type a record names is the tenant's own","A type in use cannot be deleted","The tenant decides the order pickers and defaults follow"] | ["Every type a record names is the tenant’s own.","A type in use cannot be deleted.","The tenant decides the order pickers and defaults follow."] |
  | `CAP-CRM-ENT-018` | `permissions` | [{"key":"crm.contact-types.read","where_checked":"api","scope":"tenant"},{"key":"crm.contact-types.create","where_checked":"api","scope":"tenant"},{"key":"crm.contact-types.update","where_checked":"api","scope":"tenant"},{"key":"crm.contact-types.delete","where_checked":"api","scope":"tenant"},{"key":"crm.contact-types.bulk","where_checked":"api","scope":"tenant"},{"key":"crm.organization-types.read","where_checked":"api","scope":"tenant"},{"key":"crm.organization-types.create","where_checked":"api","scope":"tenant"},{"key":"crm.organization-types.update","where_checked":"api","scope":"tenant"},{"key":"crm.organization-types.delete","where_checked":"api","scope":"tenant"},{"key":"crm.organization-types.bulk","where_checked":"api","scope":"tenant"},{"key":"crm.address-types.read","where_checked":"api","scope":"tenant"},{"key":"crm.address-types.create","where_checked":"api","scope":"tenant"},{"key":"crm.address-types.update","where_checked":"api","scope":"tenant"},{"key":"crm.address-types.delete","where_checked":"api","scope":"tenant"},{"key":"crm.address-types.bulk","where_checked":"api","scope":"tenant"},{"key":"crm.phone-number-types.read","where_checked":"api","scope":"tenant"},{"key":"crm.phone-number-types.create","where_checked":"api","scope":"tenant"},{"key":"crm.phone-number-types.update","where_checked":"api","scope":"tenant"},{"key":"crm.phone-number-types.delete","where_checked":"api","scope":"tenant"},{"key":"crm.phone-number-types.bulk","where_checked":"api","scope":"tenant"}] | [{"key":"crm.contact-types.read","where_checked":"api","scope":"tenant"},{"key":"crm.contact-types.create","where_checked":"api","scope":"tenant"},{"key":"crm.contact-types.update","where_checked":"api","scope":"tenant"},{"key":"crm.contact-types.delete","where_checked":"api","scope":"tenant"},{"key":"crm.organization-types.read","where_checked":"api","scope":"tenant"},{"key":"crm.organization-types.create","where_checked":"api","scope":"tenant"},{"key":"crm.organization-types.update","where_checked":"api","scope":"tenant"},{"key":"crm.organization-types.delete","where_checked":"api","scope":"tenant"},{"key":"crm.address-types.read","where_checked":"api","scope":"tenant"},{"key":"crm.address-types.create","where_checked":"api","scope":"tenant"},{"key":"crm.address-types.update","where_checked":"api","scope":"tenant"},{"key":"crm.address-types.delete","where_checked":"api","scope":"tenant"},{"key":"crm.phone-number-types.read","where_checked":"api","scope":"tenant"},{"key":"crm.phone-number-types.create","where_checked":"api","scope":"tenant"},{"key":"crm.phone-number-types.update","where_checked":"api","scope":"tenant"},{"key":"crm.phone-number-types.delete","where_checked":"api","scope":"tenant"}] |
  | `CAP-CRM-ENT-019` | `purpose` | "An administrator chooses the tenant's default page layouts and forms for contacts and organizations, and per type where it differs, so every console and portal screen shows and creates records the tenant's way." | "Staff obtain the applicable CRM forms and layouts, and administrators configure the defaults." |
  | `CAP-CRM-ENT-019` | `outcomes` | ["Each screen asks which definition is in force and gets one answer","Each section of the settings is changed only by its own administrator"] | ["Each screen asks which definition is in force and gets one answer.","Each section of the settings is changed only by its own administrator."] |
  | `ATS-CRM-ENT-001` | `scenarios.ATS-CRM-ENT-001-04.level` | "unit" | "browser" |
  | `ATS-CRM-ENT-001` | `scenarios.ATS-CRM-ENT-001-05.level` | "api" | "browser" |
  | `ATS-CRM-ENT-001` | `scenarios.ATS-CRM-ENT-001-07.level` | "unit" | "api" |
  | `ATS-CRM-ENT-001` | `scenarios.ATS-CRM-ENT-001-08.level` | "unit" | "api" |
  | `ATS-CRM-ENT-001` | `scenarios.ATS-CRM-ENT-001-10.level` | "unit" | "api" |
  | `ATS-CRM-ENT-001` | `scenarios.ATS-CRM-ENT-001-11.level` | "unit" | "api" |
  | `ATS-CRM-ENT-002` | `scenarios.ATS-CRM-ENT-002-03.level` | "unit" | "api" |
  | `ATS-CRM-ENT-002` | `scenarios.ATS-CRM-ENT-002-06.level` | "unit" | "browser" |
  | `ATS-CRM-ENT-002` | `scenarios.ATS-CRM-ENT-002-07.level` | "unit" | "api" |
  | `ATS-CRM-ENT-002` | `scenarios.ATS-CRM-ENT-002-09.level` | "unit" | "api" |
  | `ATS-CRM-ENT-002` | `scenarios.ATS-CRM-ENT-002-10.level` | "unit" | "api" |
  | `ATS-CRM-ENT-002` | `scenarios.ATS-CRM-ENT-002-11` | "not allocated" | "added" |
  | `ATS-CRM-ENT-003` | `scenarios.ATS-CRM-ENT-003-02.level` | "unit" | "api" |
  | `ATS-CRM-ENT-003` | `scenarios.ATS-CRM-ENT-003-03.level` | "unit" | "api" |
  | `ATS-CRM-ENT-003` | `scenarios.ATS-CRM-ENT-003-04.level` | "unit" | "browser" |
  | `ATS-CRM-ENT-003` | `scenarios.ATS-CRM-ENT-003-06.level` | "api" | "browser" |
  | `ATS-CRM-ENT-004` | `scenarios.ATS-CRM-ENT-004-02.level` | "unit" | "browser" |
  | `ATS-CRM-ENT-004` | `scenarios.ATS-CRM-ENT-004-04.level` | "unit" | "browser" |
  | `ATS-CRM-ENT-004` | `scenarios.ATS-CRM-ENT-004-06.level` | "api" | "browser" |
  | `ATS-CRM-ENT-004` | `scenarios.ATS-CRM-ENT-004-07.level` | "unit" | "api" |
  | `ATS-CRM-ENT-004` | `scenarios.ATS-CRM-ENT-004-08.level` | "unit" | "api" |
  | `ATS-CRM-ENT-004` | `scenarios.ATS-CRM-ENT-004-09.level` | "unit" | "browser" |
  | `ATS-CRM-ENT-004` | `scenarios.ATS-CRM-ENT-004-10.level` | "api" | "browser" |
  | `ATS-CRM-ENT-005` | `scenarios.ATS-CRM-ENT-005-01.level` | "unit" | "browser" |
  | `ATS-CRM-ENT-005` | `scenarios.ATS-CRM-ENT-005-02.level` | "unit" | "browser" |
  | `ATS-CRM-ENT-005` | `scenarios.ATS-CRM-ENT-005-03.level` | "unit" | "api" |
  | `ATS-CRM-ENT-005` | `scenarios.ATS-CRM-ENT-005-04.level` | "unit" | "api" |
  | `ATS-CRM-ENT-005` | `scenarios.ATS-CRM-ENT-005-05.level` | "unit" | "api" |
  | `ATS-CRM-ENT-005` | `scenarios.ATS-CRM-ENT-005-08.level` | "unit" | "browser" |
  | `ATS-CRM-ENT-006` | `scenarios.ATS-CRM-ENT-006-01.level` | "unit" | "api" |
  | `ATS-CRM-ENT-006` | `scenarios.ATS-CRM-ENT-006-02.level` | "unit" | "api" |
  | `ATS-CRM-ENT-006` | `scenarios.ATS-CRM-ENT-006-03.level` | "unit" | "browser" |
  | `ATS-CRM-ENT-006` | `scenarios.ATS-CRM-ENT-006-04.level` | "unit" | "browser" |
  | `ATS-CRM-ENT-006` | `scenarios.ATS-CRM-ENT-006-05.level` | "api" | "browser" |
  | `ATS-CRM-ENT-006` | `scenarios.ATS-CRM-ENT-006-08.level` | "unit" | "browser" |
  | `ATS-CRM-ENT-006` | `scenarios.ATS-CRM-ENT-006-09.level` | "unit" | "browser" |
  | `ATS-CRM-ENT-006` | `scenarios.ATS-CRM-ENT-006-10.level` | "unit" | "browser" |
  | `ATS-CRM-ENT-006` | `scenarios.ATS-CRM-ENT-006-11.level` | "unit" | "browser" |
  | `ATS-CRM-ENT-007` | `scenarios.ATS-CRM-ENT-007-01.level` | "unit" | "api" |
  | `ATS-CRM-ENT-007` | `scenarios.ATS-CRM-ENT-007-02.level` | "unit" | "api" |
  | `ATS-CRM-ENT-007` | `scenarios.ATS-CRM-ENT-007-03.level` | "unit" | "api" |
  | `ATS-CRM-ENT-008` | `scenarios.ATS-CRM-ENT-008-04.level` | "api" | "browser" |
  | `ATS-CRM-ENT-009` | `scenarios.ATS-CRM-ENT-009-03.level` | "api" | "browser" |
  | `ATS-CRM-ENT-009` | `scenarios.ATS-CRM-ENT-009-04.level` | "unit" | "api" |
  | `ATS-CRM-ENT-009` | `scenarios.ATS-CRM-ENT-009-05.level` | "unit" | "browser" |
  | `ATS-CRM-ENT-009` | `scenarios.ATS-CRM-ENT-009-06.level` | "unit" | "browser" |
  | `ATS-CRM-ENT-009` | `scenarios.ATS-CRM-ENT-009-08.level` | "unit" | "browser" |
  | `ATS-CRM-ENT-009` | `scenarios.ATS-CRM-ENT-009-12.bound_to` | ["react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0201.spec.ts#CRM-ACC-0201"] | [] |
  | `ATS-CRM-ENT-009` | `scenarios.ATS-CRM-ENT-009-12.provenance` | "test" | "proposed" |
  | `ATS-CRM-ENT-009` | `scenarios.ATS-CRM-ENT-009-12.source` | "react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0201.spec.ts#CRM-ACC-0201" | "react-console:lib/affiliations/section.ts:affiliationBeingLeft" |
  | `ATS-CRM-ENT-009` | `scenarios.ATS-CRM-ENT-009-13.level` | "unit" | "browser" |
  | `ATS-CRM-ENT-009` | `scenarios.ATS-CRM-ENT-009-15.level` | "api" | "browser" |
  | `ATS-CRM-ENT-010` | `scenarios.ATS-CRM-ENT-010-01.level` | "unit" | "api" |
  | `ATS-CRM-ENT-010` | `scenarios.ATS-CRM-ENT-010-04.level` | "unit" | "browser" |
  | `ATS-CRM-ENT-010` | `scenarios.ATS-CRM-ENT-010-05.level` | "unit" | "api" |
  | `ATS-CRM-ENT-011` | `scenarios.ATS-CRM-ENT-011-02.level` | "unit" | "browser" |
  | `ATS-CRM-ENT-011` | `scenarios.ATS-CRM-ENT-011-04.level` | "unit" | "browser" |
  | `ATS-CRM-ENT-011` | `scenarios.ATS-CRM-ENT-011-05.level` | "unit" | "browser" |
  | `ATS-CRM-ENT-011` | `scenarios.ATS-CRM-ENT-011-06.level` | "unit" | "api" |
  | `ATS-CRM-ENT-011` | `scenarios.ATS-CRM-ENT-011-07.level` | "unit" | "api" |
  | `ATS-CRM-ENT-011` | `scenarios.ATS-CRM-ENT-011-08.level` | "unit" | "browser" |
  | `ATS-CRM-ENT-011` | `scenarios.ATS-CRM-ENT-011-09.level` | "unit" | "api" |
  | `ATS-CRM-ENT-011` | `scenarios.ATS-CRM-ENT-011-10.level` | "unit" | "api" |
  | `ATS-CRM-ENT-011` | `scenarios.ATS-CRM-ENT-011-11.level` | "unit" | "api" |
  | `ATS-CRM-ENT-012` | `scenarios.ATS-CRM-ENT-012-01.level` | "unit" | "api" |
  | `ATS-CRM-ENT-012` | `scenarios.ATS-CRM-ENT-012-02.level` | "api" | "browser" |
  | `ATS-CRM-ENT-012` | `scenarios.ATS-CRM-ENT-012-03.level` | "unit" | "api" |
  | `ATS-CRM-ENT-012` | `scenarios.ATS-CRM-ENT-012-04.level` | "unit" | "api" |
  | `ATS-CRM-ENT-012` | `scenarios.ATS-CRM-ENT-012-05.level` | "unit" | "api" |
  | `ATS-CRM-ENT-012` | `scenarios.ATS-CRM-ENT-012-07.level` | "unit" | "api" |
  | `ATS-CRM-ENT-012` | `scenarios.ATS-CRM-ENT-012-08.level` | "unit" | "api" |
  | `ATS-CRM-ENT-012` | `scenarios.ATS-CRM-ENT-012-10.level` | "unit" | "api" |
  | `ATS-CRM-ENT-012` | `scenarios.ATS-CRM-ENT-012-14` | "not allocated" | "added" |
  | `ATS-CRM-ENT-012` | `scenarios.ATS-CRM-ENT-012-15` | "not allocated" | "added" |
  | `ATS-CRM-ENT-012` | `scenarios.ATS-CRM-ENT-012-16` | "not allocated" | "added" |
  | `ATS-CRM-ENT-013` | `scenarios.ATS-CRM-ENT-013-03.level` | "unit" | "api" |
  | `ATS-CRM-ENT-013` | `scenarios.ATS-CRM-ENT-013-04.level` | "unit" | "api" |
  | `ATS-CRM-ENT-013` | `scenarios.ATS-CRM-ENT-013-08.level` | "unit" | "browser" |
  | `ATS-CRM-ENT-013` | `scenarios.ATS-CRM-ENT-013-09.level` | "unit" | "api" |
  | `ATS-CRM-ENT-014` | `scenarios.ATS-CRM-ENT-014-03.level` | "unit" | "api" |
  | `ATS-CRM-ENT-014` | `scenarios.ATS-CRM-ENT-014-04.level` | "unit" | "browser" |
  | `ATS-CRM-ENT-014` | `scenarios.ATS-CRM-ENT-014-05.level` | "api" | "browser" |
  | `ATS-CRM-ENT-014` | `scenarios.ATS-CRM-ENT-014-06.level` | "unit" | "api" |
  | `ATS-CRM-ENT-015` | `scenarios.ATS-CRM-ENT-015-01.level` | "unit" | "browser" |
  | `ATS-CRM-ENT-015` | `scenarios.ATS-CRM-ENT-015-02.level` | "unit" | "api" |
  | `ATS-CRM-ENT-015` | `scenarios.ATS-CRM-ENT-015-03.level` | "unit" | "api" |
  | `ATS-CRM-ENT-015` | `scenarios.ATS-CRM-ENT-015-05.level` | "unit" | "browser" |
  | `ATS-CRM-ENT-015` | `scenarios.ATS-CRM-ENT-015-08.level` | "unit" | "api" |
  | `ATS-CRM-ENT-016` | `scenarios.ATS-CRM-ENT-016-01.level` | "unit" | "api" |
  | `ATS-CRM-ENT-016` | `scenarios.ATS-CRM-ENT-016-04.level` | "unit" | "api" |
  | `ATS-CRM-ENT-017` | `scenarios.ATS-CRM-ENT-017-03.level` | "unit" | "browser" |
  | `ATS-CRM-ENT-017` | `scenarios.ATS-CRM-ENT-017-07.level` | "api" | "browser" |
  | `ATS-CRM-ENT-017` | `scenarios.ATS-CRM-ENT-017-10` | "not allocated" | "added" |
  | `ATS-CRM-ENT-019` | `scenarios.ATS-CRM-ENT-019-04.level` | "unit" | "api" |
  | `JNY-CRM-ENT-001` | `product_intent` | "confirmed" | "proposed" |
  | `JNY-CRM-ENT-001` | `implementation_evidence` | "observed" | "partially-observed" |
  | `JNY-CRM-ENT-001` | `alternates` | [{"from_step":1,"condition":"The tenant has a single active contact type","path":"The chooser preselects it","outcome":"The form opens directly","provenance":"test","source":"react-console:acceptance/crm/playwright/journeys/contacts/CRM-ACC-0033.spec.ts#CRM-ACC-0033"}] | [{"from_step":1,"condition":"Only one active contact type exists.","path":"That type is already selected.","outcome":"Staff proceed directly to its form.","provenance":"test","source":"react-console:acceptance/crm/playwright/journeys/contacts/CRM-ACC-0033.spec.ts#CRM-ACC-0033"}] |
  | `JNY-CRM-ENT-001` | `failures` | [{"from_step":2,"condition":"A tenant duplicate rule set to block matches the primary e-mail","path":"The create is refused as a possible duplicate with no way to confirm in the console","outcome":"No contact is written","provenance":"test","source":"react-console:acceptance/crm/playwright/journeys/contacts/CRM-ACC-0042.spec.ts#CRM-ACC-0042"},{"from_step":5,"condition":"A colleague saved the contact first","path":"The save is refused and the conflict notice offers Reload","outcome":"Nothing of the colleague's is lost","provenance":"test","source":"react-console:acceptance/crm/playwright/journeys/contacts/CRM-ACC-0009.spec.ts#CRM-ACC-0009"}] | [{"from_step":2,"condition":"The entered primary e-mail matches a blocking duplicate rule.","path":"Creation returns a possible-duplicate refusal, with no confirmation control in the tested console path.","outcome":"The attempted contact is not created.","provenance":"test","source":"react-console:acceptance/crm/playwright/journeys/contacts/CRM-ACC-0042.spec.ts#CRM-ACC-0042"},{"from_step":5,"condition":"Another staff member saves before this editor does.","path":"The save opens a conflict notice offering Reload.","outcome":"The earlier changes remain intact.","provenance":"test","source":"react-console:acceptance/crm/playwright/journeys/contacts/CRM-ACC-0009.spec.ts#CRM-ACC-0009"}] |
  | `JNY-CRM-ENT-002` | `product_intent` | "confirmed" | "proposed" |
  | `JNY-CRM-ENT-002` | `alternates` | [{"from_step":5,"condition":"The coordinator uses Make Primary on an existing Harbor tie instead","path":"No question is asked; Harbor becomes primary","outcome":"Bayview stays current and no longer primary","provenance":"test","source":"react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0175.spec.ts#CRM-ACC-0175"},{"from_step":5,"condition":"The coordinator answers \"No, they stayed\"","path":"Both ties stay current","outcome":"Harbor primary, Bayview current","provenance":"test","source":"react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0201.spec.ts#CRM-ACC-0201"}] | [{"from_step":5,"condition":"Staff select Make Primary on an existing Harbor affiliation.","path":"Harbor becomes primary without a departure question.","outcome":"Bayview remains current with its primary flag cleared.","provenance":"test","source":"react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0175.spec.ts#CRM-ACC-0175"},{"from_step":5,"condition":"Staff answer that the person stayed at Bayview.","path":"Both affiliations remain open.","outcome":"Harbor is primary and Bayview remains current.","provenance":"test","source":"react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0201.spec.ts#CRM-ACC-0201"}] |
  | `JNY-CRM-ENT-002` | `failures` | [{"from_step":1,"condition":"The organization's type restricts roles and a role outside the list is ticked","path":"The save is refused naming the allowed roles","outcome":"Nothing is saved","provenance":"test","source":"react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0188.spec.ts#CRM-ACC-0188"},{"from_step":5,"condition":"A colleague saved the member's affiliations first","path":"The save is refused as changed by someone else","outcome":"The coordinator re-reads and redoes the change","provenance":"test","source":"react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0193.spec.ts#CRM-ACC-0193"}] | [{"from_step":1,"condition":"A selected role is outside the organization type’s allowed list.","path":"The save identifies the permitted roles and rejects the change.","outcome":"No affiliation changes are committed.","provenance":"test","source":"react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0188.spec.ts#CRM-ACC-0188"},{"from_step":5,"condition":"Another editor saves the affiliations first.","path":"The pending save reports a record-change conflict.","outcome":"Staff reload and reapply their intended change.","provenance":"test","source":"react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0193.spec.ts#CRM-ACC-0193"}] |
  | `JNY-CRM-ENT-003` | `product_intent` | "confirmed" | "proposed" |
  | `JNY-CRM-ENT-004` | `product_intent` | "confirmed" | "proposed" |
  | `JNY-CRM-ENT-004` | `alternates` | [{"from_step":1,"condition":"The administrator maintains the contact roles catalogue instead","path":"Creates, describes, reorders and deactivates a role","outcome":"The role is offered in role pickers in its order until deactivated","provenance":"test","source":"react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0197.spec.ts#CRM-ACC-0197"},{"from_step":6,"condition":"A contact type is deactivated while a coordinator is choosing it","path":"The create lands with the now-inactive type","outcome":"The chooser hides it on the next visit","provenance":"test","source":"react-console:acceptance/crm/playwright/journeys/contacts/CRM-ACC-0065.spec.ts#CRM-ACC-0065"}] | [{"from_step":1,"condition":"The administrator works on the contact-role catalogue instead.","path":"Create, describe, reorder and deactivate a role.","outcome":"Its ordered choice is available until deactivated.","provenance":"test","source":"react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0197.spec.ts#CRM-ACC-0197"},{"from_step":6,"condition":"A selected contact type is deactivated before creation completes.","path":"The contact still saves with that type.","outcome":"The next chooser visit excludes the inactive choice.","provenance":"test","source":"react-console:acceptance/crm/playwright/journeys/contacts/CRM-ACC-0065.spec.ts#CRM-ACC-0065"}] |
  | `JNY-CRM-ENT-004` | `failures` | [{"from_step":2,"condition":"A standard user tries to change the default","path":"Refused for want of the set-default key","outcome":"The default is unchanged","provenance":"test","source":"services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#refuses a caller who may only read affiliation types the change of the default (403)"},{"from_step":1,"condition":"Two default links feed the same destination","path":"The save is refused naming the field","outcome":"No type is written","provenance":"test","source":"react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0200.spec.ts#CRM-ACC-0200"}] | [{"from_step":2,"condition":"A standard user attempts to change the default affiliation type.","path":"The request lacks set-default authority and is rejected.","outcome":"The prior default remains selected.","provenance":"test","source":"services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#refuses a caller who may only read affiliation types the change of the default (403)"},{"from_step":1,"condition":"Two mappings target the same destination type.","path":"Validation identifies the duplicate destination and rejects saving.","outcome":"No new affiliation type is created.","provenance":"test","source":"react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0200.spec.ts#CRM-ACC-0200"}] |
  | `JNY-CRM-ENT-005` | `product_intent` | "confirmed" | "proposed" |
  | `JNY-CRM-ENT-005` | `alternates` | [{"from_step":4,"condition":"The coordinator asks for a past date","path":"The tab answers the ties in effect on that day","outcome":"Former members on that day are listed","provenance":"test","source":"react-console:acceptance/crm/playwright/journeys/organizations/CRM-ACC-0143.spec.ts#CRM-ACC-0143"}] | [{"from_step":4,"condition":"Staff choose a historical As Of date.","path":"The tab retrieves affiliations effective on that date.","outcome":"The historical members appear.","provenance":"test","source":"react-console:acceptance/crm/playwright/journeys/organizations/CRM-ACC-0143.spec.ts#CRM-ACC-0143"}] |
  | `JNY-CRM-ENT-005` | `failures` | [{"from_step":2,"condition":"A caller who may read organizations but not contacts opens the Contacts tab","path":"The people list is refused","outcome":"No people are shown","provenance":"test","source":"services-crm:modules/entities/tests/e2e/contact-affiliations.e2e.spec.js#answers 403 permission_missing to a caller who may read organizations but not contacts"}] | [{"from_step":2,"condition":"The caller has organization read permission but lacks contact read permission.","path":"The people-list request is rejected.","outcome":"The tab receives no contact listing.","provenance":"test","source":"services-crm:modules/entities/tests/e2e/contact-affiliations.e2e.spec.js#answers 403 permission_missing to a caller who may read organizations but not contacts"}] |

  ## Conformance blocker

  FND-CRM-ENT-030 remains open: the report requested by the job is rejected by the unmodified checker, and the same job prohibits checker changes. The required zero-error acceptance command cannot pass until the authorized owner applies the proposed report-validation change or changes the report requirement. The content work is committed for review; the job’s done condition is not met.

  ## Findings and disagreements

  FND-CRM-ENT-001 and OQ-CRM-ENT-004 record the original registry problem and its correction. FND-CRM-ENT-003 preserves seed divergences corrected by the current capability rules. FND-CRM-ENT-015 is a reconciled inventory discrepancy; it does not represent an uncovered route. The remaining findings stay open pending a product decision, implementation correction or stronger proof.

  | Finding | Remaining issue |
  |---|---|
  | `FND-CRM-ENT-001` | The original console registry names absent paths and omits editor, affiliation, configuration and browser-proof sources. This examination corrects the registry scope. The earlier scope cannot support reliable change detection. |
  | `FND-CRM-ENT-002` | The seed journeys report automation as not started for 165 of 167 entries, although browser specifications exist for their journey identifiers. Bindings use the specifications rather than the seed automation flags. |
  | `FND-CRM-ENT-003` | The seed inventory reflects an earlier service revision. Current milestone decisions change omitted-affiliation handling, dated relationships, contact-point sharing, computed fields, spouse links, patch versions, lock actions, seasonal addresses and organization history. Capability sources identify the current contract instead of adopting the seed statements unchanged. |
  | `FND-CRM-ENT-004` | The recorded complete-payload replacement contract differs from the implemented replacement behavior. Replacement clears omitted editable scalar values and owned collections, subject to the explicit affiliation and custom-value exceptions. OQ-CRM-ENT-001 asks Andrew to resolve the contract. |
  | `FND-CRM-ENT-005` | The milestone wording conflates contact types with organizations-only address and phone types. The service rejects organizations-only contact-point types on a contact. Contact types have no applicability flag. |
  | `FND-CRM-ENT-006` | Endpoint deletion supports Platform owner-deletion policy behind a switch that defaults to off. Without activation, deletion does not apply that policy to associated custom records. |
  | `FND-CRM-ENT-007` | Scheduled affiliation-date reconciliation defaults to disabled. Saves and requested reconciliation runs update date-sensitive compliance and contact-point links; the automatic-role step runs independently. The milestone’s scheduled behavior requires deployment activation. |
  | `FND-CRM-ENT-008` | Primary selection during a save and scheduled start-day reconciliation assign automatic roles differently. The save excludes a nonprimary affiliation, while reconciliation can assign roles to a due nonprimary affiliation. Product intent for this difference remains unresolved. |
  | `FND-CRM-ENT-009` | The older affiliation design describes role restrictions as picker filtering. The later milestone decision and persistence validation enforce the restriction when saving. |
  | `FND-CRM-ENT-010` | The approved warning before removing a shared organization address has no bound proof. The scoped service does not return the affected-person count, and the planned organization editor remains outside this milestone. |
  | `FND-CRM-ENT-011` | Contact-role deletion checks holders and compliance rules. The notification-role array does not supply a reference constraint, so a role used only for notification can be deleted despite the plan’s protection requirement. |
  | `FND-CRM-ENT-012` | The browser specification asserts that deactivation retains the affiliation-type dataset column and adds an inactive label. Execution of a query saved before deactivation remains unproved by that binding and belongs to Platform. |
  | `FND-CRM-ENT-013` | The catalogue publishes six configuration bulk permissions without corresponding route requirements. Their publication is evidence of declared keys, not evidence of supported bulk operations. |
  | `FND-CRM-ENT-014` | Classification records can carry locks without dedicated lock-release routes. A full lock on those types therefore has no supported API unlock action. |
  | `FND-CRM-ENT-015` | The pinned routes contain 53 distinct literal operation identifiers and 91 identifiers after factory expansion. The E2E directory contains 25 specification files and one helper. These totals differ from the brief’s stated denominators. |
  | `FND-CRM-ENT-016` | Classification routes are declared with Entities but execute through the configuration-types function. The planned module boundary needs an ownership decision before design. |
  | `FND-CRM-ENT-017` | The catalogue comment says CRM application access is not evaluated. The E2E specification asserts dispatcher refusal when application-access enforcement is enabled. |
  | `FND-CRM-ENT-018` | Unknown communication-type identifiers remain stored as submitted. The persistence source explicitly records the missing validation as debt. |
  | `FND-CRM-ENT-019` | Code comments name D-20 and D-32, but the scoped CRM milestone records do not contain those decisions. The affected rules retain code evidence without treating those comments as confirmed product records. |
  | `FND-CRM-ENT-020` | The scoped decisions E-01 and E-05 provide a defect identifier and option letter without the option’s meaning. They cannot establish a rule from the records available here. |
  | `FND-CRM-ENT-021` | Contact metadata marks civic-district values read-only, while the write schema derives fields from the table. No scoped test establishes whether writes are refused. This is a schema-based inference and needs direct API proof. |
  | `FND-CRM-ENT-022` | The cited refresh journey expects discarded unsaved work rather than restored-session recovery. The editor preserves a restored draft’s base version, but a dedicated browser scenario must prove the session-refresh contract. |
  | `FND-CRM-ENT-023` | The service caps six name components at 200 characters. Credentials, salutation and maiden name lack the same service limit. The broad milestone wording needs a decision about those fields. |
  | `FND-CRM-ENT-024` | Compliance-template failure compensation restores organization-type content through another update. The version advances, and a concurrent edit can prevent compensation. The refusal message’s claim that nothing changed is too broad. |
  | `FND-CRM-ENT-025` | Organization-type deletion commits before compliance-template archival. A later archival failure is logged without restoring the deleted type, leaving a possible template with no live owner. |
  | `FND-CRM-ENT-026` | Some browser specifications use API fallbacks or soft assertions while recording screen defects. A binding proves the existence of its assertions; it does not prove the screen path succeeds or that the test passed at these commits. |
  | `FND-CRM-ENT-027` | Compliance count bounds lack whole-number, nonnegative and ordering checks. Cleaning drops a minimum-only rule when its minimum is zero. These constraints are implementation observations awaiting product policy. |
  | `FND-CRM-ENT-028` | M2-D12 confirms automatic roles on a returning affiliation, but the acceptance scenario has no existing binding. The rule now cites the decision instead of an unsupported inference. |
  | `FND-CRM-ENT-029` | Organization creation delegates duplicate blocking to Data Quality. The published override contract requires its sensitive permission and a reason. No organization-specific bound scenario in scope proves the complete refusal and audit behavior. |

  OQ-CRM-ENT-001 asks Andrew to settle replacement semantics. OQ-CRM-ENT-002 asks for classification ownership. OQ-CRM-ENT-003 asks how to represent intent at rule level; no schema or convention is changed to answer it. OQ-CRM-ENT-004’s original correction request is resolved, with future scope completeness still subject to the next delta pass.

  ## Validation

  - `npm ci`: passes. `npm run check`: fails with one error, because the required report has no recognized artifact kind. All planning artifacts satisfy the checker; FND-CRM-ENT-030 records the blocker.
  - `npm test`: passes all four corpus checker tests.
  - Final pinned-reference audit: 1,380 structured references across 201 distinct source files, zero missing paths or anchors.
  - Source repository HEADs match the two pinned commits. No source repository changes, deployment, push or forbidden-path edits occur. The separately requested CRM actor file is the sole explicitly authorized exception to the general documentation-directory boundary.

  An unapplied 11-line patch at `reports/REPORT-VALIDATION.patch` recognizes dated examination reports and validates their requested metadata. A temporary checker copy with that patch reports zero errors against the complete corpus. The repository checker remains unchanged because tool-edit authorization is pending.

  The validation commands are executed before the report commit. Product-service and browser tests are examined as sources; their runtime status is not asserted here.
---

# CRM → Entities Examination

## Verdict for Andrew

The independent examination describes the scoped product at its pinned revisions. Its remaining concerns include replacement semantics, deployment switches, proof that exercises service fallbacks instead of the intended screen, and behavior owned by neighboring modules. Recorded findings separate these concerns from established behavior.

## Scope and Method

The examination checks source references, product decisions and existing automated-test bindings. It does not execute the CRM or console product suites. Observed code does not become product approval. The original technical catalog and examination notes remain in structured evidence.

## Planning Structure

The current planning layer groups four broad concepts across seven features, nineteen capabilities and five journeys. Superseded concepts retain their identities for traceability. Detailed facets replace the earlier table-by-table concept list.

## Validation

The original examination's run details remain in frontmatter. Current corpus validation is performed by the authoring job that changes these artifacts.
