---
id: ATS-CRM-ENT-012
scope: CAP-CRM-ENT-012
product_area: crm
module: entities
revision: 1
status: proposed
source_sha:
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
scenarios:
  - id: ATS-CRM-ENT-012-01
    title: Only types with rules compute compliance
    level: api
    proves:
      - BR-CAP-CRM-ENT-012-01
      - INV-DOM-CRM-ENT-002-07
    preconditions: Prepare types with and without rules.
    steps: >-
      Create organizations of each and none; recalculate one whose type lost its
      rules.
    expected: Status only for the first; cleared for the last.
    negative: true
    data_needs: No additional fixtures.
    bound_to:
      - TST-CRM-ENT-787
    provenance: test
    source: >-
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
      a type that holds it to no rule, or with no type: no status and no
      violations
    category: edge
    action_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
        a type that holds it to no rule, or with no type: no status and no
        violations
    assertion_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
        a type that holds it to no rule, or with no type: no status and no
        violations
    test_anchors:
      - >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
        a type that holds it to no rule, or with no type: no status and no
        violations
      - >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-change-events.integration.spec.js#an
        organization no type holds that still carries a status, so the
        recalculation clears it
    binding_scope: >-
      contributions: the cited executable assertions collectively support only
      the observations they contain; additional matrix and journey checks remain
      proposed.
  - id: ATS-CRM-ENT-012-02
    title: a new organization violates every minimum
    level: browser
    proves:
      - BR-CAP-CRM-ENT-012-02
    preconditions: Prepare a type requiring one Billing Contact; one with only a maximum.
    steps: Create an organization of each.
    expected: Not in compliance with too few 0; in compliance.
    negative: false
    data_needs: No additional fixtures.
    bound_to:
      - TST-CRM-ENT-786
      - TST-CRM-ENT-775
    provenance: test
    source: >-
      services-crm:modules/entities/tests/e2e/organization-compliance.e2e.spec.js#answer
      the computed status and violations of an organization created with a
      compliance type
    category: transition
    action_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/e2e/organization-compliance.e2e.spec.js#answer
        the computed status and violations of an organization created with a
        compliance type
    assertion_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/e2e/organization-compliance.e2e.spec.js#answer
        the computed status and violations of an organization created with a
        compliance type
    test_anchors:
      - >-
        services-crm:modules/entities/tests/e2e/organization-compliance.e2e.spec.js#answer
        the computed status and violations of an organization created with a
        compliance type
      - >-
        react-console:acceptance/crm/playwright/journeys/organizations/CRM-ACC-0121.spec.ts#CRM-ACC-0121
    binding_scope: >-
      contributions: the cited executable assertions collectively support only
      the observations they contain; additional matrix and journey checks remain
      proposed.
  - id: ATS-CRM-ENT-012-03
    title: 'Counting roles in effect, too few and too many'
    level: api
    proves:
      - BR-CAP-CRM-ENT-012-03
    preconditions: Prepare rules with minimum and maximum.
    steps: >-
      Give the role on a non-primary current affiliation; end the affiliation;
      end the role; exceed the maximum.
    expected: In; out; out; too many.
    negative: false
    data_needs: No additional fixtures.
    bound_to:
      - TST-CRM-ENT-787
    provenance: test
    source: >-
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#brings
      an organization into compliance for a role held on a current affiliation
      that is not primary
    category: interaction
    action_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#brings
        an organization into compliance for a role held on a current affiliation
        that is not primary
    assertion_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#brings
        an organization into compliance for a role held on a current affiliation
        that is not primary
    test_anchors:
      - >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#brings
        an organization into compliance for a role held on a current affiliation
        that is not primary
      - >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#takes
        an organization out of compliance when the affiliation holding its role
        ends
      - >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#takes
        an organization out of compliance when the role ends on an affiliation
        that goes on
      - >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#reports
        too many holders of a role with a maximum
      - >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-reads.integration.spec.js#counts
        a role held on a current affiliation that is not the contact’s primary
        one
    binding_scope: >-
      contributions: the cited executable assertions collectively support only
      the observations they contain; additional matrix and journey checks remain
      proposed.
  - id: ATS-CRM-ENT-012-04
    title: Which contact changes recalculate which organizations
    level: api
    proves:
      - BR-CAP-CRM-ENT-012-04
    preconditions: Prepare contacts tied to organizations retained to rules.
    steps: >-
      Save without affiliation changes; with the escape-hatch notes; add, end
      and remove affiliations and roles; delete a contact tied to two.
    expected: Nothing; nothing; the organization named; both.
    negative: false
    data_needs: No additional fixtures.
    bound_to:
      - TST-CRM-ENT-787
    provenance: test
    source: >-
      services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-change-events.integration.spec.js#a
      contact saved with the notes DISABLE_CONTACT_ROLE_COMPLIANCE_CHECK:
      nothing (its delete still records)
    category: interaction
    action_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-change-events.integration.spec.js#a
        contact saved with the notes DISABLE_CONTACT_ROLE_COMPLIANCE_CHECK:
        nothing (its delete still records)
    assertion_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-change-events.integration.spec.js#a
        contact saved with the notes DISABLE_CONTACT_ROLE_COMPLIANCE_CHECK:
        nothing (its delete still records)
    test_anchors:
      - >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-change-events.integration.spec.js#a
        save that changes neither the affiliations nor the roles: nothing
      - >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-change-events.integration.spec.js#a
        contact saved with the notes DISABLE_CONTACT_ROLE_COMPLIANCE_CHECK:
        nothing (its delete still records)
      - >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-change-events.integration.spec.js#an
        affiliation added that is not primary: its organization
      - >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-change-events.integration.spec.js#a
        role ended on an affiliation that goes on: its organization
      - >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-change-events.integration.spec.js#a
        contact affiliated with two organizations deleted: both
    binding_scope: >-
      contributions: the cited executable assertions collectively support only
      the observations they contain; additional matrix and journey checks remain
      proposed.
  - id: ATS-CRM-ENT-012-05
    title: 'Writes only on change, serialised'
    level: api
    proves:
      - BR-CAP-CRM-ENT-012-05
    preconditions: Prepare an organization out of compliance.
    steps: Deliver the same event twice; run two recalculations at once.
    expected: 'No second write; one writes, the other finds nothing.'
    negative: false
    data_needs: No additional fixtures.
    bound_to:
      - TST-CRM-ENT-787
    provenance: test
    source: >-
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#writes
      nothing for a duplicate delivery, or a second run on an unchanged
      organization
    category: concurrency
    action_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#writes
        nothing for a duplicate delivery, or a second run on an unchanged
        organization
    assertion_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#writes
        nothing for a duplicate delivery, or a second run on an unchanged
        organization
    test_anchors:
      - >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#writes
        nothing for a duplicate delivery, or a second run on an unchanged
        organization
      - >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#serializes
        two runs at once on one organization: one writes, the other finds
        nothing to change
    binding_scope: >-
      contributions: the cited executable assertions collectively support only
      the observations they contain; additional matrix and journey checks remain
      proposed.
  - id: ATS-CRM-ENT-012-06
    title: Rule and type changes wait for a reprocess; sent status ignored
    level: browser
    proves:
      - BR-CAP-CRM-ENT-012-06
      - INV-DOM-CRM-ENT-002-06
    preconditions: Prepare an organization of a type whose minimum is raised.
    steps: >-
      Save the type; read the organization; PUT the organization with another
      status; reprocess.
    expected: Status unmodified until the reprocess; the PUT's status ignored.
    negative: false
    data_needs: No additional fixtures.
    bound_to:
      - TST-CRM-ENT-786
      - TST-CRM-ENT-775
    provenance: test
    source: >-
      react-console:acceptance/crm/playwright/journeys/organizations/CRM-ACC-0124.spec.ts#CRM-ACC-0124
    category: rule
    action_evidence:
      provenance: test
      source: >-
        react-console:acceptance/crm/playwright/journeys/organizations/CRM-ACC-0124.spec.ts#CRM-ACC-0124
    assertion_evidence:
      provenance: test
      source: >-
        react-console:acceptance/crm/playwright/journeys/organizations/CRM-ACC-0124.spec.ts#CRM-ACC-0124
    test_anchors:
      - >-
        services-crm:modules/entities/tests/e2e/organization-compliance.e2e.spec.js#keep
        them against a PUT that sends others back
      - >-
        react-console:acceptance/crm/playwright/journeys/organizations/CRM-ACC-0124.spec.ts#CRM-ACC-0124
    binding_scope: >-
      contributions: the cited executable assertions collectively support only
      the observations they contain; additional matrix and journey checks remain
      proposed.
  - id: ATS-CRM-ENT-012-07
    title: 'One notice per fall, in the transaction'
    level: api
    proves:
      - BR-CAP-CRM-ENT-012-07
      - INV-DOM-CRM-ENT-002-08
    preconditions: Prepare a notifying type.
    steps: >-
      Take the organization out of compliance; recalculate unmodified; add a
      violation while out; roll back a recalculation.
    expected: One request; none; none; none.
    negative: false
    data_needs: No additional fixtures.
    bound_to:
      - TST-CRM-ENT-787
    provenance: test
    source: >-
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#is
      not submitted again while the organization stays out of compliance, nor
      for a type that does not notify
    category: invariant
    action_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#is
        not submitted again while the organization stays out of compliance, nor
        for a type that does not notify
    assertion_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#is
        not submitted again while the organization stays out of compliance, nor
        for a type that does not notify
    test_anchors:
      - >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#is
        submitted by the recalculation that takes an organization out of
        compliance, one request to the contacts to notify
      - >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#submits
        nothing when the organization is recalculated again, unchanged: the
        transition already happened
      - >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#is
        not submitted again while the organization stays out of compliance, nor
        for a type that does not notify
    binding_scope: >-
      contributions: the cited executable assertions collectively support only
      the observations they contain; additional matrix and journey checks remain
      proposed.
  - id: ATS-CRM-ENT-012-08
    title: 'Recipients: notification-role holders with a primary e-mail'
    level: api
    proves:
      - BR-CAP-CRM-ENT-012-08
    preconditions: 'Prepare contacts with a primary address, only a secondary, none.'
    steps: Compose the recipients.
    expected: 'Only the one with a primary address, in contact id order.'
    negative: false
    data_needs: No additional fixtures.
    bound_to:
      - TST-CRM-ENT-787
    provenance: test
    source: >-
      services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-reads.integration.spec.js#leaves
      out the contact whose addresses sit past the primary slot, no secondary
      address standing in
    category: rule
    action_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-reads.integration.spec.js#leaves
        out the contact whose addresses sit past the primary slot, no secondary
        address standing in
    assertion_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-reads.integration.spec.js#leaves
        out the contact whose addresses sit past the primary slot, no secondary
        address standing in
    test_anchors:
      - >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-reads.integration.spec.js#answers
        one recipient for the contact with a primary address: the whole record
        as the API reads it, and that address
      - >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-reads.integration.spec.js#leaves
        out the contact with no e-mail address at all, there being nowhere to
        send it
      - >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-reads.integration.spec.js#leaves
        out the contact whose addresses sit past the primary slot, no secondary
        address standing in
    binding_scope: >-
      contributions: the cited executable assertions collectively support only
      the observations they contain; additional matrix and journey checks remain
      proposed.
  - id: ATS-CRM-ENT-012-09
    title: 'No template, nobody e-mailed'
    level: browser
    proves:
      - BR-CAP-CRM-ENT-012-09
    preconditions: Prepare a notifying type that owns no template.
    steps: Take an organization of it out of compliance.
    expected: The notice is blocked for configuration and no mail moves out.
    negative: true
    data_needs: No additional fixtures.
    bound_to:
      - TST-CRM-ENT-775
      - TST-CRM-ENT-787
    provenance: test
    source: >-
      react-console:acceptance/crm/playwright/journeys/organizations/CRM-ACC-0123.spec.ts#CRM-ACC-0123
    category: failure
    action_evidence:
      provenance: test
      source: >-
        react-console:acceptance/crm/playwright/journeys/organizations/CRM-ACC-0123.spec.ts#CRM-ACC-0123
    assertion_evidence:
      provenance: test
      source: >-
        react-console:acceptance/crm/playwright/journeys/organizations/CRM-ACC-0123.spec.ts#CRM-ACC-0123
    test_anchors:
      - >-
        react-console:acceptance/crm/playwright/journeys/organizations/CRM-ACC-0123.spec.ts#CRM-ACC-0123
      - >-
        services-crm:modules/entities/tests/integration/services/templates/compliance-notification-template.integration.spec.js#answers
        null for a type that owns none
    binding_scope: >-
      contributions: the cited executable assertions collectively support only
      the observations they contain; additional matrix and journey checks remain
      proposed.
  - id: ATS-CRM-ENT-012-10
    title: 'Reprocess: one run per workspace, batches, failures'
    level: api
    proves:
      - BR-CAP-CRM-ENT-012-10
      - INV-DOM-CRM-ENT-002-09
    preconditions: Prepare a workspace with organizations.
    steps: >-
      Start a run; start another; run the batches; fail a batch then its last
      delivery.
    expected: >-
      The legacy message and one run; rejected second; completed; failed only on
      the last receive with a redacted reason.
    negative: true
    data_needs: No additional fixtures.
    bound_to:
      - TST-CRM-ENT-787
      - TST-CRM-ENT-786
    provenance: test
    source: >-
      services-crm:modules/entities/tests/integration/services/persistence/compliance-reprocesses.integration.spec.js#refuses
      a second running run for the tenant
    category: transition
    action_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/integration/services/persistence/compliance-reprocesses.integration.spec.js#refuses
        a second running run for the tenant
    assertion_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/integration/services/persistence/compliance-reprocesses.integration.spec.js#refuses
        a second running run for the tenant
    test_anchors:
      - >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-reprocess.integration.spec.js#answers
        the legacy message, naming every organization of the tenant
      - >-
        services-crm:modules/entities/tests/integration/services/persistence/compliance-reprocesses.integration.spec.js#refuses
        a second running run for the tenant
      - >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-reprocess.integration.spec.js#answers
        the run completed once the following batches reach the end, every
        organization counted
      - >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-reprocess-errors.integration.spec.js#fails
        the run on that last receive, because nothing will deliver its event
        again
      - >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-reprocess-errors.integration.spec.js#records
        no value of the batch that failed: not the organization, the tenant, the
        statement or its parameters
      - >-
        services-crm:modules/entities/tests/e2e/organization-compliance.e2e.spec.js#answers
        403 to a caller who may only read organizations
    binding_scope: >-
      contributions: the cited executable assertions collectively support only
      the observations they contain; additional matrix and journey checks remain
      proposed.
  - id: ATS-CRM-ENT-012-11
    title: 'Preview: keys, linked contact, sample data, problems as returns'
    level: api
    proves:
      - BR-CAP-CRM-ENT-012-11
    preconditions: Prepare an organization and contacts tied and not tied to it.
    steps: >-
      Preview as an administrator with and without the read keys; for a contact
      not tied; with a broken template; for a compliant organization.
    expected: >-
      403 without either read key; 400; 200 with problems; sample violations
      named.
    negative: true
    data_needs: No additional fixtures.
    bound_to:
      - TST-CRM-ENT-786
      - TST-CRM-ENT-787
    provenance: test
    source: >-
      services-crm:modules/entities/tests/e2e/email-previews.e2e.spec.js#answers
      403 to a caller who may administer types but may not read the records the
      answer contains
    category: permission
    action_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/e2e/email-previews.e2e.spec.js#answers
        403 to a caller who may administer types but may not read the records
        the answer contains
    assertion_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/e2e/email-previews.e2e.spec.js#answers
        403 to a caller who may administer types but may not read the records
        the answer contains
    test_anchors:
      - >-
        services-crm:modules/entities/tests/e2e/email-previews.e2e.spec.js#admits
        a caller holding the administration key and both read keys
      - >-
        services-crm:modules/entities/tests/e2e/email-previews.e2e.spec.js#answers
        403 to a caller who may administer types but may not read the records
        the answer contains
      - >-
        services-crm:modules/entities/tests/e2e/email-previews.e2e.spec.js#answers
        400 for a contact that is not linked to the organization
      - >-
        services-crm:modules/entities/tests/e2e/email-previews.e2e.spec.js#answers
        200 with the problem, because a template’s problems are an answer and
        not a refusal
      - >-
        services-crm:modules/entities/tests/integration/services/email-previews/email-preview.integration.spec.js#refuses
        a contact whose only affiliation to the organization has ended
      - >-
        services-crm:modules/entities/tests/integration/services/email-previews/email-preview.integration.spec.js#is
        previewed with the purpose contract’s example violations, and says so in
        sample_data
    binding_scope: >-
      contributions: the cited executable assertions collectively support only
      the observations they contain; additional matrix and journey checks remain
      proposed.
  - id: ATS-CRM-ENT-012-12
    title: Test send
    level: api
    proves:
      - BR-CAP-CRM-ENT-012-12
    preconditions: Prepare a template and an organization.
    steps: >-
      Send a typed draft to an address; send with both a named and a typed
      template; without a subject; for an unknown contact.
    expected: Sent with its message id; 400; 400; 404.
    negative: true
    data_needs: Use platform test send in dev.
    bound_to:
      - TST-CRM-ENT-786
    provenance: test
    source: >-
      services-crm:modules/entities/tests/e2e/organization-compliance.e2e.spec.js#answers
      400 for a template both named and typed in, or neither
    category: rule
    action_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/e2e/organization-compliance.e2e.spec.js#answers
        400 for a template both named and typed in, or neither
    assertion_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/e2e/organization-compliance.e2e.spec.js#answers
        400 for a template both named and typed in, or neither
    test_anchors:
      - >-
        services-crm:modules/entities/tests/e2e/organization-compliance.e2e.spec.js#answers
        200 with Platform's answer to the one test send: sent, with its message
        id
      - >-
        services-crm:modules/entities/tests/e2e/organization-compliance.e2e.spec.js#answers
        400 for a template both named and typed in, or neither
      - >-
        services-crm:modules/entities/tests/e2e/organization-compliance.e2e.spec.js#answers
        400 for a typed-in template without a subject, naming the field
      - >-
        services-crm:modules/entities/tests/e2e/organization-compliance.e2e.spec.js#answers
        404 for a contact the tenant does not have
    binding_scope: >-
      contributions: the cited executable assertions collectively support only
      the observations they contain; additional matrix and journey checks remain
      proposed.
  - id: ATS-CRM-ENT-012-13
    title: Type rules are cleaned and validated
    level: api
    proves:
      - BR-CAP-CRM-ENT-012-13
      - INV-DOM-CRM-ENT-002-11
    preconditions: No additional setup is required.
    steps: >-
      Save a type with a rule with neither bound, a rule of an unknown role, a
      notify switch without its list.
    expected: The rule dropped; 409 and nothing saved; 400 naming the field.
    negative: true
    data_needs: No additional fixtures.
    bound_to:
      - TST-CRM-ENT-786
    provenance: test
    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
    category: validation
    action_evidence:
      provenance: test
      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
    assertion_evidence:
      provenance: test
      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
    test_anchors:
      - >-
        services-crm:modules/entities/tests/e2e/organization-types.e2e.spec.js#runs
        the legacy cleaning on save: rules with neither bound dropped
      - >-
        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/tests/e2e/organization-types.e2e.spec.js#answers
        400 when a switch is on and its list is missing, naming the field
    binding_scope: >-
      contributions: the cited executable assertions collectively support only
      the observations they contain; additional matrix and journey checks remain
      proposed.
  - id: ATS-CRM-ENT-012-14
    title: Compliance template partial change
    level: api
    proves:
      - BR-CAP-CRM-ENT-012-15
    preconditions: Prepare an organization type and a controllable Platform template service.
    steps: >-
      Change only one template property, omit the template on another save, then
      clear it.
    expected: >-
      Unmentioned template properties remain, omission leaves the template
      unmodified, and clearing removes the active template.
    negative: false
    data_needs: Use a type with a published compliance template.
    bound_to:
      - TST-CRM-ENT-787
    provenance: test
    source: >-
      services-crm:modules/entities/services/templates/compliance-notification-template.ts:effectiveTemplateChange
    category: rule
    action_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/services/templates/compliance-notification-template.ts:effectiveTemplateChange
    assertion_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/services/templates/compliance-notification-template.ts:effectiveTemplateChange
    test_anchors:
      - >-
        services-crm:modules/entities/tests/integration/services/templates/compliance-notification-template.integration.spec.js#merges
        a partial template onto the saved one, keeping the fields the save did
        not mention
      - >-
        services-crm:modules/entities/tests/integration/services/templates/compliance-notification-template.integration.spec.js#leaves
        the template untouched when the property is omitted, and asks Platform
        for nothing
      - >-
        services-crm:modules/entities/tests/integration/services/templates/compliance-notification-template.integration.spec.js#clears
        the template when the property is null, and the type then owns none
    binding_scope: >-
      contributions: the cited executable assertions collectively support only
      the observations they contain; additional matrix and journey checks remain
      proposed.
  - id: ATS-CRM-ENT-012-15
    title: Compliance template failure compensation
    level: api
    proves:
      - BR-CAP-CRM-ENT-012-16
    preconditions: Prepare an organization type and a controllable Platform template service.
    steps: >-
      Submit invalid template content, then simulate an unavailable template
      service during a valid create and update.
    expected: >-
      Invalid content causes no type change; a failed create leaves no type, and
      a failed update restores content but advances the type version.
    negative: true
    data_needs: Use a type with a published compliance template.
    bound_to: []
    provenance: proposed
    source: >-
      services-crm:modules/entities/services/persistence/organization-types.ts:updateOrganizationType
    category: failure
    action_evidence:
      provenance: proposed
      source: >-
        services-crm:modules/entities/services/persistence/organization-types.ts:updateOrganizationType
    assertion_evidence:
      provenance: proposed
      source: >-
        services-crm:modules/entities/services/persistence/organization-types.ts:updateOrganizationType
    test_anchors: []
    binding_scope: 'unbound: the detailed scenario still needs executable proof.'
  - id: ATS-CRM-ENT-012-16
    title: Compliance template cleanup after deletion
    level: api
    proves:
      - BR-CAP-CRM-ENT-012-17
    preconditions: Prepare an organization type and a controllable Platform template service.
    steps: >-
      Delete a type with a template, once with Platform available and once while
      template archival fails.
    expected: >-
      The successful cleanup archives the template; failed cleanup logs the type
      id and leaves the type deleted.
    negative: true
    data_needs: Use a type with a published compliance template.
    bound_to:
      - TST-CRM-ENT-787
    provenance: test
    source: >-
      services-crm:modules/entities/tests/integration/services/templates/compliance-notification-template.integration.spec.js#keeps
      the delete and logs the type id when Platform cannot clear it: the type is
      gone either way
    category: transition
    action_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/integration/services/templates/compliance-notification-template.integration.spec.js#keeps
        the delete and logs the type id when Platform cannot clear it: the type
        is gone either way
    assertion_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/integration/services/templates/compliance-notification-template.integration.spec.js#keeps
        the delete and logs the type id when Platform cannot clear it: the type
        is gone either way
    test_anchors:
      - >-
        services-crm:modules/entities/tests/integration/services/templates/compliance-notification-template.integration.spec.js#clears
        the template the deleted type owned, so no template is left owned by a
        type that is gone
      - >-
        services-crm:modules/entities/tests/integration/services/templates/compliance-notification-template.integration.spec.js#keeps
        the delete and logs the type id when Platform cannot clear it: the type
        is gone either way
    binding_scope: >-
      contributions: the cited executable assertions collectively support only
      the observations they contain; additional matrix and journey checks remain
      proposed.
  - id: ATS-CRM-ENT-012-17
    title: Distinguish empty notice-role selection from all affiliates
    category: edge
    level: api
    proves:
      - BR-CAP-CRM-ENT-012-08
    preconditions: >-
      A notifying type has an explicitly empty notification-role selection and
      the organization has an eligible affiliate with a primary email.
    steps: >-
      Enter noncompliance and inspect composed recipients and communication
      submissions.
    expected: >-
      The pinned implementation composes no recipients and submits no notice;
      the planning rule’s all-affiliate fallback remains contradicted.
    negative: true
    data_needs: Run-owned records and configuration in an isolated workspace.
    bound_to: []
    provenance: proposed
    source: >-
      services-crm:modules/entities/services/organizations/compliance/contact-role-compliance.ts:contactsToNotify;
      FND-CRM-ENT-043
    intent_mismatch: FND-CRM-ENT-043
    test_anchors: []
    action_evidence:
      provenance: proposed
      source: >-
        services-crm:modules/entities/services/organizations/compliance/contact-role-compliance.ts:contactsToNotify;
        FND-CRM-ENT-043
    assertion_evidence:
      provenance: proposed
      source: >-
        services-crm:modules/entities/services/organizations/compliance/contact-role-compliance.ts:contactsToNotify;
        FND-CRM-ENT-043
    binding_scope: 'unbound: the detailed scenario still needs executable proof.'
  - id: ATS-CRM-ENT-012-18
    title: A terminal failed reprocess cannot resume through redelivery
    category: invariant
    level: api
    proves:
      - BR-CAP-CRM-ENT-012-10
    preconditions: A compliance reprocess is terminally failed after exhausting retries.
    steps: 'Redeliver its message, then request a fresh run.'
    expected: >-
      The failed run stays terminal; recovery begins with a distinct run rather
      than resuming the old one.
    negative: false
    data_needs: Run-owned records and configuration in an isolated workspace.
    bound_to: []
    provenance: proposed
    source: >-
      services-crm:modules/entities/services/organizations/compliance/compliance-reprocess.ts:runComplianceReprocess;
      rhythm-v2-docs:specs/crm/entities/design/state-models/STATE-CRM-ENT-004-compliance-reprocess-run.md:invalid
    intent_mismatch: FND-CRM-ENT-047
    test_anchors: []
    action_evidence:
      provenance: proposed
      source: >-
        services-crm:modules/entities/services/organizations/compliance/compliance-reprocess.ts:runComplianceReprocess;
        rhythm-v2-docs:specs/crm/entities/design/state-models/STATE-CRM-ENT-004-compliance-reprocess-run.md:invalid
    assertion_evidence:
      provenance: proposed
      source: >-
        services-crm:modules/entities/services/organizations/compliance/compliance-reprocess.ts:runComplianceReprocess;
        rhythm-v2-docs:specs/crm/entities/design/state-models/STATE-CRM-ENT-004-compliance-reprocess-run.md:invalid
    binding_scope: 'unbound: the detailed scenario still needs executable proof.'
  - id: ATS-CRM-ENT-012-19
    title: Establish a body under role policy
    category: interaction
    level: api
    proves:
      - BR-CAP-CRM-ENT-002-04
      - BR-CAP-CRM-ENT-012-02
    preconditions: An organization classification requires one holder of a selected role.
    steps: >-
      Create an organization using that classification and read its initial
      compliance.
    expected: >-
      The new organization has the initial zero-holder violation and creation
      submits no notice.
    negative: false
    data_needs: Run-owned records and configuration in an isolated workspace.
    bound_to: []
    provenance: proposed
    source: >-
      services-crm:modules/entities/tests/e2e/organization-types.e2e.spec.js#refuses
      an organization of a type the tenant does not have (409), and the delete
      of a type an organization has (409);
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
      a type that holds it to rules: not in compliance, every rule with a
      minimum violated (it has no contact yet)
    exercises:
      - CAP-CRM-ENT-002
      - CAP-CRM-ENT-012
    workflows:
      - WF-CRM-ENT-003
    test_anchors: []
    action_evidence:
      provenance: proposed
      source: >-
        services-crm:modules/entities/tests/e2e/organization-types.e2e.spec.js#refuses
        an organization of a type the tenant does not have (409), and the delete
        of a type an organization has (409);
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
        a type that holds it to rules: not in compliance, every rule with a
        minimum violated (it has no contact yet)
    assertion_evidence:
      provenance: proposed
      source: >-
        services-crm:modules/entities/tests/e2e/organization-types.e2e.spec.js#refuses
        an organization of a type the tenant does not have (409), and the delete
        of a type an organization has (409);
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
        a type that holds it to rules: not in compliance, every rule with a
        minimum violated (it has no contact yet)
    binding_scope: 'unbound: the detailed scenario still needs executable proof.'
  - id: ATS-CRM-ENT-012-20
    title: A role change reaches organization coverage after commit
    category: interaction
    level: api
    proves:
      - BR-CAP-CRM-ENT-009-02
      - BR-CAP-CRM-ENT-012-04
    preconditions: >-
      A current affiliation belongs to an organization with a minimum-role
      policy.
    steps: >-
      Add the missing role through the person save; process its committed
      compliance reaction and read the organization.
    expected: >-
      The person retains the role and the organization’s recalculated coverage
      reflects that effective holder.
    negative: false
    data_needs: Run-owned records and configuration in an isolated workspace.
    bound_to: []
    provenance: proposed
    source: >-
      react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0202.spec.ts#CRM-ACC-0202;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-change-events.integration.spec.js#a
      contact saved with the notes DISABLE_CONTACT_ROLE_COMPLIANCE_CHECK:
      nothing (its delete still records)
    exercises:
      - CAP-CRM-ENT-009
      - CAP-CRM-ENT-012
    workflows: []
    test_anchors: []
    action_evidence:
      provenance: proposed
      source: >-
        react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0202.spec.ts#CRM-ACC-0202;
        services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-change-events.integration.spec.js#a
        contact saved with the notes DISABLE_CONTACT_ROLE_COMPLIANCE_CHECK:
        nothing (its delete still records)
    assertion_evidence:
      provenance: proposed
      source: >-
        react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0202.spec.ts#CRM-ACC-0202;
        services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-change-events.integration.spec.js#a
        contact saved with the notes DISABLE_CONTACT_ROLE_COMPLIANCE_CHECK:
        nothing (its delete still records)
    binding_scope: 'unbound: the detailed scenario still needs executable proof.'
  - id: ATS-CRM-ENT-012-21
    title: An expired role changes organizational coverage
    category: interaction
    level: api
    proves:
      - BR-CAP-CRM-ENT-010-05
      - BR-CAP-CRM-ENT-012-03
    preconditions: An organization meets its minimum through a role ending today.
    steps: >-
      Read coverage on the inclusive end day; reconcile the next local day and
      reread coverage.
    expected: >-
      Coverage remains satisfied through the last day and becomes deficient
      after the ended role no longer counts.
    negative: false
    data_needs: Run-owned records and configuration in an isolated workspace.
    bound_to: []
    provenance: proposed
    source: >-
      services-crm:modules/entities/tests/integration/services/affiliations/affiliation-date-reconciliation.integration.spec.js#takes
      the organization out of compliance the next morning, with no save of the
      contact;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#brings
      an organization into compliance for a role held on a current affiliation
      that is not primary
    exercises:
      - CAP-CRM-ENT-010
      - CAP-CRM-ENT-012
    workflows:
      - WF-CRM-ENT-006
    test_anchors: []
    action_evidence:
      provenance: proposed
      source: >-
        services-crm:modules/entities/tests/integration/services/affiliations/affiliation-date-reconciliation.integration.spec.js#takes
        the organization out of compliance the next morning, with no save of the
        contact;
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#brings
        an organization into compliance for a role held on a current affiliation
        that is not primary
    assertion_evidence:
      provenance: proposed
      source: >-
        services-crm:modules/entities/tests/integration/services/affiliations/affiliation-date-reconciliation.integration.spec.js#takes
        the organization out of compliance the next morning, with no save of the
        contact;
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#brings
        an organization into compliance for a role held on a current affiliation
        that is not primary
    binding_scope: 'unbound: the detailed scenario still needs executable proof.'
  - id: ATS-CRM-ENT-012-22
    title: Allowed responsibility satisfies organizational policy
    category: interaction
    level: api
    proves:
      - BR-CAP-CRM-ENT-011-05
      - BR-CAP-CRM-ENT-012-03
    preconditions: A governed organization allows a required role on a current affiliation.
    steps: Assign that role through the person and recalculate the organization.
    expected: >-
      The allowed assignment persists and its effective holder satisfies the
      configured minimum.
    negative: false
    data_needs: Run-owned records and configuration in an isolated workspace.
    bound_to: []
    provenance: proposed
    source: >-
      services-crm:modules/entities/tests/integration/services/persistence/contact-affiliations.integration.spec.js#refuses
      a role outside the list added to an existing affiliation;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#brings
      an organization into compliance for a role held on a current affiliation
      that is not primary
    exercises:
      - CAP-CRM-ENT-011
      - CAP-CRM-ENT-012
    workflows:
      - WF-CRM-ENT-004
      - WF-CRM-ENT-006
    test_anchors: []
    action_evidence:
      provenance: proposed
      source: >-
        services-crm:modules/entities/tests/integration/services/persistence/contact-affiliations.integration.spec.js#refuses
        a role outside the list added to an existing affiliation;
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#brings
        an organization into compliance for a role held on a current affiliation
        that is not primary
    assertion_evidence:
      provenance: proposed
      source: >-
        services-crm:modules/entities/tests/integration/services/persistence/contact-affiliations.integration.spec.js#refuses
        a role outside the list added to an existing affiliation;
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#brings
        an organization into compliance for a role held on a current affiliation
        that is not primary
    binding_scope: 'unbound: the detailed scenario still needs executable proof.'
  - id: ATS-CRM-ENT-012-23
    title: Policy editing takes effect when reprocessing reaches the body
    category: interaction
    level: api
    proves:
      - BR-CAP-CRM-ENT-012-06
      - BR-CAP-CRM-ENT-018-07
    preconditions: >-
      An existing organization is compliant under its classification’s old
      policy.
    steps: >-
      Increase the minimum in the classification; read the body, request
      reprocessing and read it after settlement.
    expected: >-
      The first read retains stored coverage; settled reprocessing records the
      new deficient coverage.
    negative: false
    data_needs: Run-owned records and configuration in an isolated workspace.
    bound_to: []
    provenance: proposed
    source: >-
      services-crm:modules/entities/tests/e2e/organization-compliance.e2e.spec.js#keep
      them against a PUT that sends others back;
      services-crm:modules/entities/tests/e2e/contact-types.e2e.spec.js#then,
      when the version is off, refuses the change (409)
    exercises:
      - CAP-CRM-ENT-012
      - CAP-CRM-ENT-018
    workflows:
      - WF-CRM-ENT-008
    test_anchors: []
    action_evidence:
      provenance: proposed
      source: >-
        services-crm:modules/entities/tests/e2e/organization-compliance.e2e.spec.js#keep
        them against a PUT that sends others back;
        services-crm:modules/entities/tests/e2e/contact-types.e2e.spec.js#then,
        when the version is off, refuses the change (409)
    assertion_evidence:
      provenance: proposed
      source: >-
        services-crm:modules/entities/tests/e2e/organization-compliance.e2e.spec.js#keep
        them against a PUT that sends others back;
        services-crm:modules/entities/tests/e2e/contact-types.e2e.spec.js#then,
        when the version is off, refuses the change (409)
    binding_scope: 'unbound: the detailed scenario still needs executable proof.'
  - id: ATS-CRM-ENT-012-24
    title: Recalculate through every policy state
    category: transition
    level: api
    proves:
      - BR-CAP-CRM-ENT-012-01
      - BR-CAP-CRM-ENT-012-03
      - BR-CAP-CRM-ENT-012-05
      - BR-CAP-CRM-ENT-012-06
      - BR-CAP-CRM-ENT-012-07
    preconditions: >-
      Two initially ungoverned organizations have controlled role-holder
      fixtures.
    steps: >-
      Enable a minimum policy; recalculate one with a holder and one without.
      Remove and restore the holder; change the deficiency while still
      deficient; disable policy on a satisfied and a deficient organization and
      recalculate both.
    expected: >-
      The reads distinguish newly satisfied, newly deficient, changing
      deficiency and cleared policy state. Unchanged recalculation contributes
      no additional version and notice submissions follow the transition
      contract.
    negative: false
    data_needs: Run-owned records and configuration in an isolated workspace.
    bound_to: []
    provenance: proposed
    source: >-
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
      a type that holds it to rules: not in compliance, every rule with a
      minimum violated (it has no contact yet);
      services-crm:modules/entities/services/organizations/compliance/organization-compliance.ts:recalculateOrganizationCompliance;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#is
      not submitted again while the organization stays out of compliance, nor
      for a type that does not notify;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#brings
      an organization into compliance for a role held on a current affiliation
      that is not primary;
      services-crm:modules/entities/services/organizations/compliance/organization-compliance.ts:recalculateOrganizationCompliance;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
      a type that holds it to no rule, or with no type: no status and no
      violations;
      services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
      a type that holds it to no rule, or with no type: no status and no
      violations
    test_anchors: []
    action_evidence:
      provenance: proposed
      source: >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
        a type that holds it to rules: not in compliance, every rule with a
        minimum violated (it has no contact yet);
        services-crm:modules/entities/services/organizations/compliance/organization-compliance.ts:recalculateOrganizationCompliance;
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#is
        not submitted again while the organization stays out of compliance, nor
        for a type that does not notify;
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#brings
        an organization into compliance for a role held on a current affiliation
        that is not primary;
        services-crm:modules/entities/services/organizations/compliance/organization-compliance.ts:recalculateOrganizationCompliance;
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
        a type that holds it to no rule, or with no type: no status and no
        violations;
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
        a type that holds it to no rule, or with no type: no status and no
        violations
    assertion_evidence:
      provenance: proposed
      source: >-
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
        a type that holds it to rules: not in compliance, every rule with a
        minimum violated (it has no contact yet);
        services-crm:modules/entities/services/organizations/compliance/organization-compliance.ts:recalculateOrganizationCompliance;
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#is
        not submitted again while the organization stays out of compliance, nor
        for a type that does not notify;
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#brings
        an organization into compliance for a role held on a current affiliation
        that is not primary;
        services-crm:modules/entities/services/organizations/compliance/organization-compliance.ts:recalculateOrganizationCompliance;
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
        a type that holds it to no rule, or with no type: no status and no
        violations;
        services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
        a type that holds it to no rule, or with no type: no status and no
        violations
    binding_scope: 'unbound: the detailed scenario still needs executable proof.'
  - id: ATS-CRM-ENT-012-25
    title: Exercise every declared authority independently
    category: permission
    level: api
    proves:
      - BR-CAP-CRM-ENT-012-11
    preconditions: >-
      An eligible record and configuration fixture exist for each operation; the
      caller can reach only the run’s workspace.
    steps: >-
      For each declared permission, execute its matching operation with that
      permission, then without it while retaining the other required grants.
      Read affected records after every refused mutation.
    expected: >-
      The authorized case reaches the operation; the missing-grant case is
      refused and preserves saved data. Record access alone does not authorize
      the other declared actions.
    negative: true
    data_needs: Run-owned records and configuration in an isolated workspace.
    bound_to: []
    provenance: proposed
    source: >-
      services-crm:aws/crm.service.ts:ApplicationPermissions;
      services-crm:modules/entities/aws/api/entities.routes.ts
    permission_keys:
      - crm.organizations.update
      - crm.organization-types.update
      - crm.organizations.read
      - crm.contacts.read
    test_anchors: []
    action_evidence:
      provenance: proposed
      source: >-
        services-crm:aws/crm.service.ts:ApplicationPermissions;
        services-crm:modules/entities/aws/api/entities.routes.ts
    assertion_evidence:
      provenance: proposed
      source: >-
        services-crm:aws/crm.service.ts:ApplicationPermissions;
        services-crm:modules/entities/aws/api/entities.routes.ts
    binding_scope: 'unbound: the detailed scenario still needs executable proof.'
evidence:
  - >-
    services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
    a type that holds it to no rule, or with no type: no status and no
    violations
  - >-
    services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-change-events.integration.spec.js#an
    organization no type holds that still carries a status, so the recalculation
    clears it
  - >-
    services-crm:modules/entities/tests/e2e/organization-compliance.e2e.spec.js#answer
    the computed status and violations of an organization created with a
    compliance type
  - >-
    react-console:acceptance/crm/playwright/journeys/organizations/CRM-ACC-0121.spec.ts#CRM-ACC-0121
  - >-
    services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#brings
    an organization into compliance for a role held on a current affiliation
    that is not primary
  - >-
    services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#takes
    an organization out of compliance when the affiliation holding its role ends
  - >-
    services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#takes
    an organization out of compliance when the role ends on an affiliation that
    goes on
  - >-
    services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#reports
    too many holders of a role with a maximum
  - >-
    services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-reads.integration.spec.js#counts
    a role held on a current affiliation that is not the contact’s primary one
  - >-
    services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-change-events.integration.spec.js#a
    contact saved with the notes DISABLE_CONTACT_ROLE_COMPLIANCE_CHECK: nothing
    (its delete still records)
  - >-
    services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-change-events.integration.spec.js#a
    save that changes neither the affiliations nor the roles: nothing
  - >-
    services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-change-events.integration.spec.js#an
    affiliation added that is not primary: its organization
  - >-
    services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-change-events.integration.spec.js#a
    role ended on an affiliation that goes on: its organization
  - >-
    services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-change-events.integration.spec.js#a
    contact affiliated with two organizations deleted: both
  - >-
    services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#writes
    nothing for a duplicate delivery, or a second run on an unchanged
    organization
  - >-
    services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#serializes
    two runs at once on one organization: one writes, the other finds nothing to
    change
  - >-
    react-console:acceptance/crm/playwright/journeys/organizations/CRM-ACC-0124.spec.ts#CRM-ACC-0124
  - >-
    services-crm:modules/entities/tests/e2e/organization-compliance.e2e.spec.js#keep
    them against a PUT that sends others back
  - >-
    services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#is
    not submitted again while the organization stays out of compliance, nor for
    a type that does not notify
  - >-
    services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#is
    submitted by the recalculation that takes an organization out of compliance,
    one request to the contacts to notify
  - >-
    services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#submits
    nothing when the organization is recalculated again, unchanged: the
    transition already happened
  - >-
    services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-reads.integration.spec.js#leaves
    out the contact whose addresses sit past the primary slot, no secondary
    address standing in
  - >-
    services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-reads.integration.spec.js#answers
    one recipient for the contact with a primary address: the whole record as
    the API reads it, and that address
  - >-
    services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-reads.integration.spec.js#leaves
    out the contact with no e-mail address at all, there being nowhere to send
    it
  - >-
    react-console:acceptance/crm/playwright/journeys/organizations/CRM-ACC-0123.spec.ts#CRM-ACC-0123
  - >-
    services-crm:modules/entities/tests/integration/services/templates/compliance-notification-template.integration.spec.js#answers
    null for a type that owns none
  - >-
    services-crm:modules/entities/tests/integration/services/persistence/compliance-reprocesses.integration.spec.js#refuses
    a second running run for the tenant
  - >-
    services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-reprocess.integration.spec.js#answers
    the legacy message, naming every organization of the tenant
  - >-
    services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-reprocess.integration.spec.js#answers
    the run completed once the following batches reach the end, every
    organization counted
  - >-
    services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-reprocess-errors.integration.spec.js#fails
    the run on that last receive, because nothing will deliver its event again
  - >-
    services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-reprocess-errors.integration.spec.js#records
    no value of the batch that failed: not the organization, the tenant, the
    statement or its parameters
  - >-
    services-crm:modules/entities/tests/e2e/organization-compliance.e2e.spec.js#answers
    403 to a caller who may only read organizations
  - >-
    services-crm:modules/entities/tests/e2e/email-previews.e2e.spec.js#answers
    403 to a caller who may administer types but may not read the records the
    answer contains
  - >-
    services-crm:modules/entities/tests/e2e/email-previews.e2e.spec.js#admits a
    caller holding the administration key and both read keys
  - >-
    services-crm:modules/entities/tests/e2e/email-previews.e2e.spec.js#answers
    400 for a contact that is not linked to the organization
  - >-
    services-crm:modules/entities/tests/e2e/email-previews.e2e.spec.js#answers
    200 with the problem, because a template’s problems are an answer and not a
    refusal
  - >-
    services-crm:modules/entities/tests/integration/services/email-previews/email-preview.integration.spec.js#refuses
    a contact whose only affiliation to the organization has ended
  - >-
    services-crm:modules/entities/tests/integration/services/email-previews/email-preview.integration.spec.js#is
    previewed with the purpose contract’s example violations, and says so in
    sample_data
  - >-
    services-crm:modules/entities/tests/e2e/organization-compliance.e2e.spec.js#answers
    400 for a template both named and typed in, or neither
  - >-
    services-crm:modules/entities/tests/e2e/organization-compliance.e2e.spec.js#answers
    200 with Platform's answer to the one test send: sent, with its message id
  - >-
    services-crm:modules/entities/tests/e2e/organization-compliance.e2e.spec.js#answers
    400 for a typed-in template without a subject, naming the field
  - >-
    services-crm:modules/entities/tests/e2e/organization-compliance.e2e.spec.js#answers
    404 for a contact the tenant does not have
  - >-
    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/tests/e2e/organization-types.e2e.spec.js#runs
    the legacy cleaning on save: rules with neither bound dropped
  - >-
    services-crm:modules/entities/tests/e2e/organization-types.e2e.spec.js#answers
    400 when a switch is on and its list is missing, naming the field
  - >-
    services-crm:modules/entities/services/templates/compliance-notification-template.ts:effectiveTemplateChange
  - >-
    services-crm:modules/entities/tests/integration/services/templates/compliance-notification-template.integration.spec.js#merges
    a partial template onto the saved one, keeping the fields the save did not
    mention
  - >-
    services-crm:modules/entities/tests/integration/services/templates/compliance-notification-template.integration.spec.js#leaves
    the template untouched when the property is omitted, and asks Platform for
    nothing
  - >-
    services-crm:modules/entities/tests/integration/services/templates/compliance-notification-template.integration.spec.js#clears
    the template when the property is null, and the type then owns none
  - >-
    services-crm:modules/entities/services/persistence/organization-types.ts:updateOrganizationType
  - >-
    services-crm:modules/entities/tests/integration/services/templates/compliance-notification-template.integration.spec.js#keeps
    the delete and logs the type id when Platform cannot clear it: the type is
    gone either way
  - >-
    services-crm:modules/entities/tests/integration/services/templates/compliance-notification-template.integration.spec.js#clears
    the template the deleted type owned, so no template is left owned by a type
    that is gone
  - >-
    services-crm:modules/entities/queries/compliance.query.ts:complianceNoticeContactIds;
    FND-CRM-ENT-043
  - >-
    Failed runs are also skipped on redrive. Recovery requires requesting
    another run.;
    services-crm:modules/entities/services/organizations/compliance/compliance-reprocess.ts:runComplianceReprocess
  - >-
    services-crm:modules/entities/tests/e2e/organization-types.e2e.spec.js#refuses
    an organization of a type the tenant does not have (409), and the delete of
    a type an organization has (409);
    services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
    a type that holds it to rules: not in compliance, every rule with a minimum
    violated (it has no contact yet)
  - >-
    react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0202.spec.ts#CRM-ACC-0202;
    services-crm:modules/entities/tests/integration/services/organizations/compliance/compliance-change-events.integration.spec.js#a
    contact saved with the notes DISABLE_CONTACT_ROLE_COMPLIANCE_CHECK: nothing
    (its delete still records)
  - >-
    services-crm:modules/entities/tests/integration/services/affiliations/affiliation-date-reconciliation.integration.spec.js#takes
    the organization out of compliance the next morning, with no save of the
    contact;
    services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#brings
    an organization into compliance for a role held on a current affiliation
    that is not primary
  - >-
    services-crm:modules/entities/tests/integration/services/persistence/contact-affiliations.integration.spec.js#refuses
    a role outside the list added to an existing affiliation;
    services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#brings
    an organization into compliance for a role held on a current affiliation
    that is not primary
  - >-
    services-crm:modules/entities/tests/e2e/organization-compliance.e2e.spec.js#keep
    them against a PUT that sends others back;
    services-crm:modules/entities/tests/e2e/contact-types.e2e.spec.js#then, when
    the version is off, refuses the change (409)
  - >-
    services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
    a type that holds it to rules: not in compliance, every rule with a minimum
    violated (it has no contact yet);
    services-crm:modules/entities/services/organizations/compliance/organization-compliance.ts:recalculateOrganizationCompliance;
    services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#is
    not submitted again while the organization stays out of compliance, nor for
    a type that does not notify;
    services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#brings
    an organization into compliance for a role held on a current affiliation
    that is not primary;
    services-crm:modules/entities/services/organizations/compliance/organization-compliance.ts:recalculateOrganizationCompliance;
    services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
    a type that holds it to no rule, or with no type: no status and no
    violations;
    services-crm:modules/entities/tests/integration/services/organizations/compliance/organization-compliance.integration.spec.js#with
    a type that holds it to no rule, or with no type: no status and no
    violations
  - >-
    services-crm:aws/crm.service.ts:ApplicationPermissions;
    services-crm:modules/entities/aws/api/entities.routes.ts
coverage:
  rule: covered
  transition: covered
  validation: covered
  permission: covered
  edge: covered
  failure: covered
  boundary: 'gap: FND-CRM-ENT-060'
  concurrency: covered
  invariant: covered
  interaction: covered
previous_approval:
  revision: 1
  approved_by: Andrew
  approved_at: '2026-10-22T00:00:00.000Z'
transition_coverage:
  - state_model: STATE-CRM-ENT-003
    from: ungoverned
    to: not in compliance
    scenarios:
      - ATS-CRM-ENT-012-24
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/design/state-models/STATE-CRM-ENT-003-organization-role-compliance-status.md:transitions
  - state_model: STATE-CRM-ENT-003
    from: ungoverned
    to: in compliance
    scenarios:
      - ATS-CRM-ENT-012-24
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/design/state-models/STATE-CRM-ENT-003-organization-role-compliance-status.md:transitions
  - state_model: STATE-CRM-ENT-003
    from: in compliance
    to: not in compliance
    scenarios:
      - ATS-CRM-ENT-012-24
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/design/state-models/STATE-CRM-ENT-003-organization-role-compliance-status.md:transitions
  - state_model: STATE-CRM-ENT-003
    from: not in compliance
    to: in compliance
    scenarios:
      - ATS-CRM-ENT-012-24
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/design/state-models/STATE-CRM-ENT-003-organization-role-compliance-status.md:transitions
  - state_model: STATE-CRM-ENT-003
    from: not in compliance
    to: not in compliance
    scenarios:
      - ATS-CRM-ENT-012-24
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/design/state-models/STATE-CRM-ENT-003-organization-role-compliance-status.md:transitions
  - state_model: STATE-CRM-ENT-003
    from: in compliance
    to: ungoverned
    scenarios:
      - ATS-CRM-ENT-012-24
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/design/state-models/STATE-CRM-ENT-003-organization-role-compliance-status.md:transitions
  - state_model: STATE-CRM-ENT-003
    from: not in compliance
    to: ungoverned
    scenarios:
      - ATS-CRM-ENT-012-24
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/design/state-models/STATE-CRM-ENT-003-organization-role-compliance-status.md:transitions
  - state_model: STATE-CRM-ENT-004
    from: requested
    to: running
    scenarios:
      - ATS-CRM-ENT-012-10
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/design/state-models/STATE-CRM-ENT-004-compliance-reprocess-run.md:transitions
  - state_model: STATE-CRM-ENT-004
    from: running
    to: running
    scenarios:
      - ATS-CRM-ENT-012-10
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/design/state-models/STATE-CRM-ENT-004-compliance-reprocess-run.md:transitions
  - state_model: STATE-CRM-ENT-004
    from: running
    to: completed
    scenarios:
      - ATS-CRM-ENT-012-10
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/design/state-models/STATE-CRM-ENT-004-compliance-reprocess-run.md:transitions
  - state_model: STATE-CRM-ENT-004
    from: running
    to: failed
    scenarios:
      - ATS-CRM-ENT-012-10
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/design/state-models/STATE-CRM-ENT-004-compliance-reprocess-run.md:transitions
coverage_notes:
  boundary:
    reason: >-
      No detailed boundary scenario currently specifies this aspect; the
      coverage finding records the required follow-through.
    provenance: unknown
    source: FND-CRM-ENT-060
coverage_findings:
  - FND-CRM-ENT-060
  - FND-CRM-ENT-075
permission_coverage:
  - key: crm.organizations.update
    where_checked: api
    scenario: ATS-CRM-ENT-012-25
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/planning/capabilities/CAP-CRM-ENT-012-hold-organizations-to-their-type-s-role-rules-and-tell-them.md
  - key: crm.organization-types.update
    where_checked: api
    scenario: ATS-CRM-ENT-012-25
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/planning/capabilities/CAP-CRM-ENT-012-hold-organizations-to-their-type-s-role-rules-and-tell-them.md
  - key: crm.organizations.read
    where_checked: service
    scenario: ATS-CRM-ENT-012-25
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/planning/capabilities/CAP-CRM-ENT-012-hold-organizations-to-their-type-s-role-rules-and-tell-them.md
  - key: crm.contacts.read
    where_checked: service
    scenario: ATS-CRM-ENT-012-25
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/planning/capabilities/CAP-CRM-ENT-012-hold-organizations-to-their-type-s-role-rules-and-tell-them.md
related_coverage:
  - capability: CAP-CRM-ENT-002
    scenarios:
      - ATS-CRM-ENT-012-19
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/planning/capabilities/CAP-CRM-ENT-012-hold-organizations-to-their-type-s-role-rules-and-tell-them.md:related
  - capability: CAP-CRM-ENT-009
    scenarios:
      - ATS-CRM-ENT-012-20
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/planning/capabilities/CAP-CRM-ENT-012-hold-organizations-to-their-type-s-role-rules-and-tell-them.md:related
  - capability: CAP-CRM-ENT-010
    scenarios:
      - ATS-CRM-ENT-012-21
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/planning/capabilities/CAP-CRM-ENT-012-hold-organizations-to-their-type-s-role-rules-and-tell-them.md:related
  - capability: CAP-CRM-ENT-011
    scenarios:
      - ATS-CRM-ENT-012-22
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/planning/capabilities/CAP-CRM-ENT-012-hold-organizations-to-their-type-s-role-rules-and-tell-them.md:related
  - capability: CAP-CRM-ENT-018
    scenarios:
      - ATS-CRM-ENT-012-23
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/planning/capabilities/CAP-CRM-ENT-012-hold-organizations-to-their-type-s-role-rules-and-tell-them.md:related
examination_evidence:
  provenance: documented
  source: 'rhythm-v2-docs:specs/crm/entities/reports/EXAMINATION-2026-10-23.md'
  heading_conflict: FND-CRM-ENT-075
---

# Review organization role compliance and prepare notices
## Coverage

The category map separates specified cases from recorded gaps. A proposed case describes proof to implement; a binding identifies the assertions supplied by an existing executable file. The permission and transition ledgers record the individual checks needed for the capability.

| Required rule | Scenario or finding |
|---|---|
| `BR-CAP-CRM-ENT-012-01` | `ATS-CRM-ENT-012-01`, `ATS-CRM-ENT-012-24` |
| `BR-CAP-CRM-ENT-012-02` | `ATS-CRM-ENT-012-02`, `ATS-CRM-ENT-012-19` |
| `BR-CAP-CRM-ENT-012-03` | `ATS-CRM-ENT-012-03`, `ATS-CRM-ENT-012-21`, `ATS-CRM-ENT-012-22`, `ATS-CRM-ENT-012-24` |
| `BR-CAP-CRM-ENT-012-04` | `ATS-CRM-ENT-012-04`, `ATS-CRM-ENT-012-20` |
| `BR-CAP-CRM-ENT-012-05` | `ATS-CRM-ENT-012-05`, `ATS-CRM-ENT-012-24` |
| `BR-CAP-CRM-ENT-012-06` | `ATS-CRM-ENT-012-06`, `ATS-CRM-ENT-012-23`, `ATS-CRM-ENT-012-24` |
| `BR-CAP-CRM-ENT-012-07` | `ATS-CRM-ENT-012-07`, `ATS-CRM-ENT-012-24` |
| `BR-CAP-CRM-ENT-012-08` | `ATS-CRM-ENT-012-08`, `ATS-CRM-ENT-012-17` |
| `BR-CAP-CRM-ENT-012-09` | `ATS-CRM-ENT-012-09` |
| `BR-CAP-CRM-ENT-012-10` | `ATS-CRM-ENT-012-10`, `ATS-CRM-ENT-012-18` |
| `BR-CAP-CRM-ENT-012-11` | `ATS-CRM-ENT-012-11`, `ATS-CRM-ENT-012-25` |
| `BR-CAP-CRM-ENT-012-12` | `ATS-CRM-ENT-012-12` |
| `BR-CAP-CRM-ENT-012-13` | `ATS-CRM-ENT-012-13` |
| `BR-CAP-CRM-ENT-012-15` | `ATS-CRM-ENT-012-14` |
| `BR-CAP-CRM-ENT-012-16` | `ATS-CRM-ENT-012-15` |
| `BR-CAP-CRM-ENT-012-17` | `ATS-CRM-ENT-012-16` |

## Interactions With Related Capabilities

The interaction scenarios exercise establish an organization and its hierarchy; maintain a person’s organizational relationships; keep dated relationships current; maintain responsibilities on organizational relationships; organize the workspace’s record classifications. They change one part of a prepared record and inspect the dependent outcome. Unbound interactions remain proposed rather than implying an existing end-to-end implementation.

## Source Evidence

The frontmatter pins the repositories and identifies the source anchors for each scenario. Bindings record inspected assertions, while unbound cases remain proposed. Source inspection supplies no execution result or product approval.
