---
id: ATS-CRM-ENT-017
scope: CAP-CRM-ENT-017
product_area: crm
module: entities
revision: 1
status: proposed
source_sha:
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
scenarios:
  - id: ATS-CRM-ENT-017-01
    title: Names required and trimmed
    level: api
    proves:
      - BR-CAP-CRM-ENT-017-01
    preconditions: No additional setup is required.
    steps: >-
      Create a role and a type with an empty name, a name of spaces, a padded
      name.
    expected: 400 naming the field and no record changes; trimmed.
    negative: true
    data_needs: No additional fixtures.
    bound_to:
      - TST-CRM-ENT-786
    provenance: test
    source: >-
      services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#answers
      400 naming the field for a create whose name is nothing but spaces
    category: validation
    action_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#answers
        400 naming the field for a create whose name is nothing but spaces
    assertion_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#answers
        400 naming the field for a create whose name is nothing but spaces
    test_anchors:
      - >-
        services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#answers
        400 naming the field for a create whose name is the empty string
      - >-
        services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#answers
        400 naming the field for a create whose name is nothing but spaces
      - >-
        services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#writes
        no role at all for a create it refused: the id reads back 404
      - >-
        services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#takes
        a name with spaces around it and stores it trimmed
      - >-
        services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#answers
        400 naming the field for a create whose name is nothing but spaces
    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-017-02
    title: Ids follow the grammar and never repeat
    level: api
    proves:
      - BR-CAP-CRM-ENT-017-02
    preconditions: No additional setup is required.
    steps: >-
      Create without an id; with a space; with 63 and 64 characters; with the
      reserved prefix; with a used id; change the id.
    expected: Derived; 400; accepted then 400; 400; 400; 400.
    negative: true
    data_needs: No additional fixtures.
    bound_to:
      - TST-CRM-ENT-786
    provenance: test
    source: >-
      services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#answers
      400 for an id that is not a configuration id, saying what an id may hold
    category: boundary
    action_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#answers
        400 for an id that is not a configuration id, saying what an id may hold
    assertion_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#answers
        400 for an id that is not a configuration id, saying what an id may hold
    test_anchors:
      - >-
        services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#derives
        the id from the name when the create names none
      - >-
        services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#answers
        400 for an id with a space
      - >-
        services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#creates
        a role with a 63-character id and a 255-character name (CRM-ACC-0173)
      - >-
        services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#answers
        400 naming the id for a 64-character id, never a 500 without a message
        (CRM-ACC-0173)
      - >-
        services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#answers
        400 for a reserved id
      - >-
        services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#answers
        400 for an id the tenant already uses
      - >-
        services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#then,
        when the id is wrong, refuses the change (400)
    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-017-03
    title: Roles in use cannot be deleted
    level: browser
    proves:
      - BR-CAP-CRM-ENT-017-03
      - INV-DOM-CRM-ENT-003-14
    preconditions: >-
      Prepare a role retained on an ended affiliation; a role named by a
      compliance rule; an unused role.
    steps: Delete each.
    expected: 409 with the holders' count; 409 naming the types; deleted.
    negative: true
    data_needs: No additional fixtures.
    bound_to:
      - TST-CRM-ENT-787
      - TST-CRM-ENT-786
      - TST-CRM-ENT-776
    provenance: test
    source: >-
      services-crm:modules/entities/tests/integration/services/persistence/contact-roles.integration.spec.js#refuses
      it with the legacy words, naming the organization types whose rules depend
      on it
    category: interaction
    action_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/integration/services/persistence/contact-roles.integration.spec.js#refuses
        it with the legacy words, naming the organization types whose rules
        depend on it
    assertion_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/integration/services/persistence/contact-roles.integration.spec.js#refuses
        it with the legacy words, naming the organization types whose rules
        depend on it
    test_anchors:
      - >-
        services-crm:modules/entities/tests/integration/services/persistence/contact-roles.integration.spec.js#refuses
        it with the legacy words and the number of holders
      - >-
        services-crm:modules/entities/tests/integration/services/persistence/contact-roles.integration.spec.js#refuses
        it with the legacy words, naming the organization types whose rules
        depend on it
      - >-
        services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#deletes
        a role no contact holds
      - >-
        services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#answers
        409 for a role a contact holds, with the legacy words
      - >-
        react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0198.spec.ts#CRM-ACC-0198
    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-017-04
    title: Deletes are administrators'
    level: browser
    proves:
      - BR-CAP-CRM-ENT-017-04
    preconditions: Prepare a standard user and read-only staff.
    steps: 'Create, edit, reorder and delete a role and a type.'
    expected: >-
      The standard user creates, edits and reorders but cannot delete either;
      read-only staff only read.
    negative: true
    data_needs: Use personas by tier.
    bound_to:
      - TST-CRM-ENT-776
    provenance: test
    source: >-
      react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0196.spec.ts#CRM-ACC-0196
    category: permission
    action_evidence:
      provenance: test
      source: >-
        react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0196.spec.ts#CRM-ACC-0196
    assertion_evidence:
      provenance: test
      source: >-
        react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0196.spec.ts#CRM-ACC-0196
    test_anchors:
      - >-
        react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0196.spec.ts#CRM-ACC-0196
    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-017-05
    title: Types in use or default cannot be deleted
    level: api
    proves:
      - BR-CAP-CRM-ENT-017-05
      - INV-DOM-CRM-ENT-003-13
    preconditions: Prepare a type a contact's affiliation uses; the default type.
    steps: Delete each; delete after the contact has gone.
    expected: 409; 409; deleted.
    negative: true
    data_needs: No additional fixtures.
    bound_to:
      - TST-CRM-ENT-786
    provenance: test
    source: >-
      services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#refuses
      the delete (409) while an affiliation of a contact is of that type
    category: interaction
    action_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#refuses
        the delete (409) while an affiliation of a contact is of that type
    assertion_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#refuses
        the delete (409) while an affiliation of a contact is of that type
    test_anchors:
      - >-
        services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#refuses
        the delete (409) while an affiliation of a contact is of that type
      - >-
        services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#leaves
        the type in place after the refusal
      - >-
        services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#accepts
        the delete once the contact affiliated under it has gone
      - >-
        services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#refuses
        the delete of the type that is the default (409)
    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-017-06
    title: the workspace default type
    level: api
    proves:
      - BR-CAP-CRM-ENT-017-06
    preconditions: Prepare a workspace that chose none.
    steps: >-
      Read the default; set a workspace type; set one it lacks; change it with
      only the read key.
    expected: Other; saved and read back; 400 naming the field; 403.
    negative: true
    data_needs: No additional fixtures.
    bound_to:
      - TST-CRM-ENT-786
    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)
    category: permission
    action_evidence:
      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)
    assertion_evidence:
      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)
    test_anchors:
      - >-
        services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#answers
        other as the default of a tenant that chose none
      - >-
        services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#saves
        a type of the tenant as the default and answers it
      - >-
        services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#refuses
        a default the tenant does not have (400), naming the field
      - >-
        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)
      - >-
        services-crm:modules/entities/tests/e2e/page-layouts.e2e.spec.js#is not
        answered the default affiliation type, which the affiliation types keys
        govern
    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-017-07
    title: Default links are validated and preserved by an omitting replacement
    level: browser
    proves:
      - BR-CAP-CRM-ENT-017-07
    preconditions: No additional setup is required.
    steps: >-
      Save mappings of a bad type, an unknown type, one destination twice, 21
      mappings; replace without the list; replace with null.
    expected: 400 naming the field each; preserved; cleared.
    negative: true
    data_needs: No additional fixtures.
    bound_to:
      - TST-CRM-ENT-786
      - TST-CRM-ENT-787
      - TST-CRM-ENT-776
    provenance: test
    source: >-
      services-crm:modules/entities/tests/integration/services/persistence/affiliation-types.integration.spec.js#keeps
      the mappings, as an omitted collection means unchanged
    category: boundary
    action_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/integration/services/persistence/affiliation-types.integration.spec.js#keeps
        the mappings, as an omitted collection means unchanged
    assertion_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/integration/services/persistence/affiliation-types.integration.spec.js#keeps
        the mappings, as an omitted collection means unchanged
    test_anchors:
      - >-
        services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#answers
        400 naming the field for a kind that is neither address nor phone
      - >-
        services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#answers
        400 naming the field for a type id the tenant does not have
      - >-
        services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#answers
        400 naming the field for a second mapping of one kind to one destination
      - >-
        services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#answers
        400 naming the field for more than 20 mappings
      - >-
        services-crm:modules/entities/tests/integration/services/persistence/affiliation-types.integration.spec.js#keeps
        the mappings, as an omitted collection means unchanged
      - >-
        services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#clears
        the mappings for a replacement that sends null, as a later read shows
      - >-
        react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0200.spec.ts#CRM-ACC-0200
    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-017-08
    title: Role reorder is all or nothing and ignores locks
    level: api
    proves:
      - BR-CAP-CRM-ENT-017-08
    preconditions: 'Prepare a workspace’s roles, one locked.'
    steps: >-
      Reorder all; leave one out; name one the workspace lacks; as a read-only
      caller.
    expected: >-
      Numbered 1..n, the locked one moved; 400; 400; 403; the order unmodified
      after each refusal.
    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/contact-roles.e2e.spec.js#answers
      400 for a reorder that leaves a role of the tenant out, naming it
    category: failure
    action_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#answers
        400 for a reorder that leaves a role of the tenant out, naming it
    assertion_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#answers
        400 for a reorder that leaves a role of the tenant out, naming it
    test_anchors:
      - >-
        services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#answers
        200 with every role of the tenant, in the order the body listed them,
        numbered 1..n
      - >-
        services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#answers
        400 for a reorder that leaves a role of the tenant out, naming it
      - >-
        services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#answers
        400 for a reorder that names a role the tenant does not have
      - >-
        services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#answers
        403 to a caller who may only read contact roles
      - >-
        services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#leaves
        the order as the successful reorder left it after every refusal
      - >-
        services-crm:modules/entities/tests/integration/services/persistence/contact-types.integration.spec.js#numbers
        a placeless type locked against updates that the first reorder leaves
        where its name stands
    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-017-09
    title: 'the journey: configure a type of affiliation and use it'
    level: browser
    proves:
      - AS-JNY-CRM-ENT-004-01
      - AS-JNY-CRM-ENT-004-02
      - AS-JNY-CRM-ENT-004-03
    preconditions: Prepare an administrator and a staff member.
    steps: Run JNY-CRM-ENT-004.
    expected: >-
      The Organization field uses the default type; delete rejected while used
      or default; deactivation leaves affiliations unmodified.
    negative: false
    data_needs: No additional fixtures.
    bound_to:
      - TST-CRM-ENT-776
    provenance: test
    source: >-
      react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0199.spec.ts#CRM-ACC-0199
    category: interaction
    action_evidence:
      provenance: test
      source: >-
        react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0199.spec.ts#CRM-ACC-0199
    assertion_evidence:
      provenance: test
      source: >-
        react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0199.spec.ts#CRM-ACC-0199
    test_anchors:
      - >-
        react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0199.spec.ts#CRM-ACC-0199
    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-017-10
    title: Inactive affiliation columns remain available
    level: browser
    proves:
      - BR-CAP-CRM-ENT-017-11
    preconditions: Prepare an active affiliation type with a query column.
    steps: Deactivate the type and read the dataset description again.
    expected: The column is still available and its label includes "(inactive)".
    negative: false
    data_needs: Use a type with an existing affiliation.
    bound_to:
      - TST-CRM-ENT-776
    provenance: test
    source: >-
      react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0199.spec.ts#CRM-ACC-0199
    category: rule
    action_evidence:
      provenance: test
      source: >-
        react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0199.spec.ts#CRM-ACC-0199
    assertion_evidence:
      provenance: test
      source: >-
        react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0199.spec.ts#CRM-ACC-0199
    test_anchors:
      - >-
        react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0199.spec.ts#CRM-ACC-0199
    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-017-11
    title: A portal reader pages the role catalogue
    category: edge
    level: api
    proves:
      - BR-CAP-CRM-ENT-017-10
    preconditions: >-
      A workspace portal caller has the documented catalogue read access and
      multiple roles are present.
    steps: Read the first role page and follow its continuation cursor.
    expected: >-
      The caller receives the workspace’s role names in the declared order
      without repeats.
    negative: false
    data_needs: Run-owned records and configuration in an isolated workspace.
    bound_to:
      - TST-CRM-ENT-786
    provenance: test
    source: >-
      services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#answers
      a portal user of the tenant
    test_anchors:
      - >-
        services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#answers
        a portal user of the tenant
    action_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#answers
        a portal user of the tenant
    assertion_evidence:
      provenance: test
      source: >-
        services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#answers
        a portal user of the tenant
    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-017-12
    title: A default mapping supplies a newly effective tie
    category: interaction
    level: api
    proves:
      - BR-CAP-CRM-ENT-006-11
      - BR-CAP-CRM-ENT-017-07
    preconditions: >-
      An affiliation type maps an organization address purpose to an empty
      person address purpose.
    steps: >-
      Add a current affiliation of that type with the mapping selected and read
      the saved person.
    expected: >-
      The new link uses the configured source and destination while preexisting
      personal values remain.
    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-information-sources.integration.spec.js#links
      nothing when the choice is an empty list;
      services-crm:modules/entities/tests/integration/services/persistence/affiliation-types.integration.spec.js#keeps
      the mappings, as an omitted collection means unchanged
    exercises:
      - CAP-CRM-ENT-006
      - CAP-CRM-ENT-017
    workflows: []
    test_anchors: []
    action_evidence:
      provenance: proposed
      source: >-
        services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#links
        nothing when the choice is an empty list;
        services-crm:modules/entities/tests/integration/services/persistence/affiliation-types.integration.spec.js#keeps
        the mappings, as an omitted collection means unchanged
    assertion_evidence:
      provenance: proposed
      source: >-
        services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#links
        nothing when the choice is an empty list;
        services-crm:modules/entities/tests/integration/services/persistence/affiliation-types.integration.spec.js#keeps
        the mappings, as an omitted collection means unchanged
    binding_scope: 'unbound: the detailed scenario still needs executable proof.'
  - id: ATS-CRM-ENT-017-13
    title: The configured default supplies the Organization command
    category: interaction
    level: api
    proves:
      - BR-CAP-CRM-ENT-009-11
      - BR-CAP-CRM-ENT-017-06
    preconditions: An administrator selects a nondefault affiliation type for the workspace.
    steps: >-
      Set a person’s primary organization using the Organization command and
      inspect the created tie.
    expected: The saved relationship uses the selected workspace default type.
    negative: false
    data_needs: Run-owned records and configuration in an isolated workspace.
    bound_to: []
    provenance: proposed
    source: >-
      services-crm:modules/entities/tests/unit/services/persistence/contact-affiliations.spec.js#ends
      the previous primary the day before the effective date by default, and its
      open roles with it;
      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)
    exercises:
      - CAP-CRM-ENT-009
      - CAP-CRM-ENT-017
    workflows: []
    test_anchors: []
    action_evidence:
      provenance: proposed
      source: >-
        services-crm:modules/entities/tests/unit/services/persistence/contact-affiliations.spec.js#ends
        the previous primary the day before the effective date by default, and
        its open roles with it;
        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)
    assertion_evidence:
      provenance: proposed
      source: >-
        services-crm:modules/entities/tests/unit/services/persistence/contact-affiliations.spec.js#ends
        the previous primary the day before the effective date by default, and
        its open roles with it;
        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)
    binding_scope: 'unbound: the detailed scenario still needs executable proof.'
  - id: ATS-CRM-ENT-017-14
    title: Automatic assignment creates a catalogue dependency
    category: interaction
    level: api
    proves:
      - BR-CAP-CRM-ENT-011-06
      - BR-CAP-CRM-ENT-017-03
    preconditions: An active catalogue role is automatic and has no holder yet.
    steps: Join an eligible person as primary; try deleting the assigned role.
    expected: >-
      The new affiliation holds the role and deletion is refused while that role
      period remains.
    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/contacts/role-assignment/contact-role-assignment.integration.spec.js#gives
      the organization's first contact the automatic and first-contact roles,
      besides the roles it states;
      services-crm:modules/entities/tests/integration/services/persistence/contact-roles.integration.spec.js#refuses
      it with the legacy words, naming the organization types whose rules depend
      on it
    exercises:
      - CAP-CRM-ENT-011
      - CAP-CRM-ENT-017
    workflows: []
    test_anchors: []
    action_evidence:
      provenance: proposed
      source: >-
        services-crm:modules/entities/tests/integration/services/contacts/role-assignment/contact-role-assignment.integration.spec.js#gives
        the organization's first contact the automatic and first-contact roles,
        besides the roles it states;
        services-crm:modules/entities/tests/integration/services/persistence/contact-roles.integration.spec.js#refuses
        it with the legacy words, naming the organization types whose rules
        depend on it
    assertion_evidence:
      provenance: proposed
      source: >-
        services-crm:modules/entities/tests/integration/services/contacts/role-assignment/contact-role-assignment.integration.spec.js#gives
        the organization's first contact the automatic and first-contact roles,
        besides the roles it states;
        services-crm:modules/entities/tests/integration/services/persistence/contact-roles.integration.spec.js#refuses
        it with the legacy words, naming the organization types whose rules
        depend on it
    binding_scope: 'unbound: the detailed scenario still needs executable proof.'
  - id: ATS-CRM-ENT-017-15
    title: A policy reference protects its role catalogue entry
    category: interaction
    level: api
    proves:
      - BR-CAP-CRM-ENT-012-13
      - BR-CAP-CRM-ENT-017-03
    preconditions: A role is referenced by an organization classification’s compliance rule.
    steps: Try deleting that role before and after removing the rule reference.
    expected: >-
      The referenced role cannot be deleted; after the reference is removed and
      no holders remain, deletion succeeds.
    negative: false
    data_needs: Run-owned records and configuration in an isolated workspace.
    bound_to: []
    provenance: proposed
    source: >-
      services-crm:modules/entities/services/persistence/organization-types.ts:organizationTypeProblems;
      services-crm:modules/entities/tests/integration/services/persistence/contact-roles.integration.spec.js#refuses
      it with the legacy words, naming the organization types whose rules depend
      on it
    exercises:
      - CAP-CRM-ENT-012
      - CAP-CRM-ENT-017
    workflows: []
    test_anchors: []
    action_evidence:
      provenance: proposed
      source: >-
        services-crm:modules/entities/services/persistence/organization-types.ts:organizationTypeProblems;
        services-crm:modules/entities/tests/integration/services/persistence/contact-roles.integration.spec.js#refuses
        it with the legacy words, naming the organization types whose rules
        depend on it
    assertion_evidence:
      provenance: proposed
      source: >-
        services-crm:modules/entities/services/persistence/organization-types.ts:organizationTypeProblems;
        services-crm:modules/entities/tests/integration/services/persistence/contact-roles.integration.spec.js#refuses
        it with the legacy words, naming the organization types whose rules
        depend on it
    binding_scope: 'unbound: the detailed scenario still needs executable proof.'
  - id: ATS-CRM-ENT-017-16
    title: Legacy role writes differ from dedicated lock actions
    category: interaction
    level: api
    proves:
      - BR-CAP-CRM-ENT-015-04
      - BR-CAP-CRM-ENT-017-04
    preconditions: >-
      A role is available for ordinary editing and dedicated lock
      administration.
    steps: >-
      Set a delete lock through the ordinary role write; compare its audit with
      a later dedicated lock action.
    expected: >-
      The ordinary role write retains the documented delete-lock exception; the
      dedicated action records its own reason and audit.
    negative: false
    data_needs: Run-owned records and configuration in an isolated workspace.
    bound_to: []
    provenance: proposed
    source: >-
      services-crm:modules/entities/tests/e2e/contacts.e2e.spec.js#answers 403
      naming sys_locked for a replacement that sets a lock (E-14);
      react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0196.spec.ts#CRM-ACC-0196
    exercises:
      - CAP-CRM-ENT-015
      - CAP-CRM-ENT-017
    workflows: []
    test_anchors: []
    action_evidence:
      provenance: proposed
      source: >-
        services-crm:modules/entities/tests/e2e/contacts.e2e.spec.js#answers 403
        naming sys_locked for a replacement that sets a lock (E-14);
        react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0196.spec.ts#CRM-ACC-0196
    assertion_evidence:
      provenance: proposed
      source: >-
        services-crm:modules/entities/tests/e2e/contacts.e2e.spec.js#answers 403
        naming sys_locked for a replacement that sets a lock (E-14);
        react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0196.spec.ts#CRM-ACC-0196
    binding_scope: 'unbound: the detailed scenario still needs executable proof.'
  - id: ATS-CRM-ENT-017-17
    title: Default mappings retain their contact-point purposes
    category: interaction
    level: api
    proves:
      - BR-CAP-CRM-ENT-017-07
      - BR-CAP-CRM-ENT-018-03
    preconditions: >-
      An affiliation type references address and phone purposes in its default
      mappings.
    steps: >-
      Attempt deletion of a referenced purpose; remove the mapping and retry
      when no record holds the purpose.
    expected: >-
      The reference blocks the first delete; the unused purpose is deletable
      after the mapping is removed.
    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/affiliation-types.integration.spec.js#keeps
      the mappings, as an omitted collection means unchanged;
      services-crm:modules/entities/tests/e2e/address-types.e2e.spec.js#says
      which records keep the type when it refuses the delete
    exercises:
      - CAP-CRM-ENT-017
      - CAP-CRM-ENT-018
    workflows: []
    test_anchors: []
    action_evidence:
      provenance: proposed
      source: >-
        services-crm:modules/entities/tests/integration/services/persistence/affiliation-types.integration.spec.js#keeps
        the mappings, as an omitted collection means unchanged;
        services-crm:modules/entities/tests/e2e/address-types.e2e.spec.js#says
        which records keep the type when it refuses the delete
    assertion_evidence:
      provenance: proposed
      source: >-
        services-crm:modules/entities/tests/integration/services/persistence/affiliation-types.integration.spec.js#keeps
        the mappings, as an omitted collection means unchanged;
        services-crm:modules/entities/tests/e2e/address-types.e2e.spec.js#says
        which records keep the type when it refuses the delete
    binding_scope: 'unbound: the detailed scenario still needs executable proof.'
  - id: ATS-CRM-ENT-017-18
    title: Settings do not expose the affiliation default through layout-only access
    category: interaction
    level: api
    proves:
      - BR-CAP-CRM-ENT-017-06
      - BR-CAP-CRM-ENT-019-01
    preconditions: A caller may read contact layouts but cannot read affiliation types.
    steps: 'Read settings with that access, then with affiliation-type read added.'
    expected: >-
      The layout-only response omits the default affiliation type; the
      additional catalogue authority exposes it.
    negative: false
    data_needs: Run-owned records and configuration in an isolated workspace.
    bound_to: []
    provenance: proposed
    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); services-crm:modules/entities/tests/e2e/page-layouts.e2e.spec.js#is
      not answered the section it may not read: it is ABSENT, not null, so
      "forbidden" and "unset" never look alike
    exercises:
      - CAP-CRM-ENT-017
      - CAP-CRM-ENT-019
    workflows: []
    test_anchors: []
    action_evidence:
      provenance: proposed
      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);
        services-crm:modules/entities/tests/e2e/page-layouts.e2e.spec.js#is not
        answered the section it may not read: it is ABSENT, not null, so
        "forbidden" and "unset" never look alike
    assertion_evidence:
      provenance: proposed
      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);
        services-crm:modules/entities/tests/e2e/page-layouts.e2e.spec.js#is not
        answered the section it may not read: it is ABSENT, not null, so
        "forbidden" and "unset" never look alike
    binding_scope: 'unbound: the detailed scenario still needs executable proof.'
  - id: ATS-CRM-ENT-017-19
    title: Exercise every declared authority independently
    category: permission
    level: api
    proves:
      - BR-CAP-CRM-ENT-017-04
      - BR-CAP-CRM-ENT-017-06
      - BR-CAP-CRM-ENT-017-10
    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/affiliation-types.routes.ts;
      services-crm:modules/entities/aws/api/contact-roles.routes.ts
    permission_keys:
      - crm.contact-roles.read
      - crm.contact-roles.create
      - crm.contact-roles.update
      - crm.contact-roles.delete
      - crm.affiliation-types.read
      - crm.affiliation-types.create
      - crm.affiliation-types.update
      - crm.affiliation-types.delete
      - crm.affiliation-types.set-default
    test_anchors: []
    action_evidence:
      provenance: proposed
      source: >-
        services-crm:aws/crm.service.ts:ApplicationPermissions;
        services-crm:modules/entities/aws/api/affiliation-types.routes.ts;
        services-crm:modules/entities/aws/api/contact-roles.routes.ts
    assertion_evidence:
      provenance: proposed
      source: >-
        services-crm:aws/crm.service.ts:ApplicationPermissions;
        services-crm:modules/entities/aws/api/affiliation-types.routes.ts;
        services-crm:modules/entities/aws/api/contact-roles.routes.ts
    binding_scope: 'unbound: the detailed scenario still needs executable proof.'
evidence:
  - >-
    services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#answers
    400 naming the field for a create whose name is nothing but spaces
  - >-
    services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#answers
    400 naming the field for a create whose name is the empty string
  - >-
    services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#answers
    400 naming the field for a create whose name is nothing but spaces
  - >-
    services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#writes no
    role at all for a create it refused: the id reads back 404
  - >-
    services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#takes a
    name with spaces around it and stores it trimmed
  - >-
    services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#answers
    400 for an id that is not a configuration id, saying what an id may hold
  - >-
    services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#derives
    the id from the name when the create names none
  - >-
    services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#answers
    400 for an id with a space
  - >-
    services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#creates a
    role with a 63-character id and a 255-character name (CRM-ACC-0173)
  - >-
    services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#answers
    400 naming the id for a 64-character id, never a 500 without a message
    (CRM-ACC-0173)
  - >-
    services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#answers
    400 for a reserved id
  - >-
    services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#answers
    400 for an id the tenant already uses
  - >-
    services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#then,
    when the id is wrong, refuses the change (400)
  - >-
    services-crm:modules/entities/tests/integration/services/persistence/contact-roles.integration.spec.js#refuses
    it with the legacy words, naming the organization types whose rules depend
    on it
  - >-
    services-crm:modules/entities/tests/integration/services/persistence/contact-roles.integration.spec.js#refuses
    it with the legacy words and the number of holders
  - >-
    services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#deletes a
    role no contact holds
  - >-
    services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#answers
    409 for a role a contact holds, with the legacy words
  - >-
    react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0198.spec.ts#CRM-ACC-0198
  - >-
    react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0196.spec.ts#CRM-ACC-0196
  - >-
    services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#refuses
    the delete (409) while an affiliation of a contact is of that type
  - >-
    services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#leaves
    the type in place after the refusal
  - >-
    services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#accepts
    the delete once the contact affiliated under it has gone
  - >-
    services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#refuses
    the delete of the type that is the default (409)
  - >-
    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)
  - >-
    services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#answers
    other as the default of a tenant that chose none
  - >-
    services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#saves
    a type of the tenant as the default and answers it
  - >-
    services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#refuses
    a default the tenant does not have (400), naming the field
  - >-
    services-crm:modules/entities/tests/e2e/page-layouts.e2e.spec.js#is not
    answered the default affiliation type, which the affiliation types keys
    govern
  - >-
    services-crm:modules/entities/tests/integration/services/persistence/affiliation-types.integration.spec.js#keeps
    the mappings, as an omitted collection means unchanged
  - >-
    services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#answers
    400 naming the field for a kind that is neither address nor phone
  - >-
    services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#answers
    400 naming the field for a type id the tenant does not have
  - >-
    services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#answers
    400 naming the field for a second mapping of one kind to one destination
  - >-
    services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#answers
    400 naming the field for more than 20 mappings
  - >-
    services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#clears
    the mappings for a replacement that sends null, as a later read shows
  - >-
    react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0200.spec.ts#CRM-ACC-0200
  - >-
    services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#answers
    400 for a reorder that leaves a role of the tenant out, naming it
  - >-
    services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#answers
    200 with every role of the tenant, in the order the body listed them,
    numbered 1..n
  - >-
    services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#answers
    400 for a reorder that names a role the tenant does not have
  - >-
    services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#answers
    403 to a caller who may only read contact roles
  - >-
    services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#leaves the
    order as the successful reorder left it after every refusal
  - >-
    services-crm:modules/entities/tests/integration/services/persistence/contact-types.integration.spec.js#numbers
    a placeless type locked against updates that the first reorder leaves where
    its name stands
  - >-
    react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0199.spec.ts#CRM-ACC-0199
  - >-
    services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#answers a
    portal user of the tenant
  - >-
    services-crm:modules/entities/tests/integration/services/persistence/contact-information-sources.integration.spec.js#links
    nothing when the choice is an empty list;
    services-crm:modules/entities/tests/integration/services/persistence/affiliation-types.integration.spec.js#keeps
    the mappings, as an omitted collection means unchanged
  - >-
    services-crm:modules/entities/tests/unit/services/persistence/contact-affiliations.spec.js#ends
    the previous primary the day before the effective date by default, and its
    open roles with it;
    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)
  - >-
    services-crm:modules/entities/tests/integration/services/contacts/role-assignment/contact-role-assignment.integration.spec.js#gives
    the organization's first contact the automatic and first-contact roles,
    besides the roles it states;
    services-crm:modules/entities/tests/integration/services/persistence/contact-roles.integration.spec.js#refuses
    it with the legacy words, naming the organization types whose rules depend
    on it
  - >-
    services-crm:modules/entities/services/persistence/organization-types.ts:organizationTypeProblems;
    services-crm:modules/entities/tests/integration/services/persistence/contact-roles.integration.spec.js#refuses
    it with the legacy words, naming the organization types whose rules depend
    on it
  - >-
    services-crm:modules/entities/tests/e2e/contacts.e2e.spec.js#answers 403
    naming sys_locked for a replacement that sets a lock (E-14);
    react-console:acceptance/crm/playwright/journeys/affiliations/CRM-ACC-0196.spec.ts#CRM-ACC-0196
  - >-
    services-crm:modules/entities/tests/integration/services/persistence/affiliation-types.integration.spec.js#keeps
    the mappings, as an omitted collection means unchanged;
    services-crm:modules/entities/tests/e2e/address-types.e2e.spec.js#says which
    records keep the type when it refuses the delete
  - >-
    services-crm:modules/entities/tests/e2e/affiliation-types.e2e.spec.js#refuses
    a caller who may only read affiliation types the change of the default
    (403); services-crm:modules/entities/tests/e2e/page-layouts.e2e.spec.js#is
    not answered the section it may not read: it is ABSENT, not null, so
    "forbidden" and "unset" never look alike
  - >-
    services-crm:aws/crm.service.ts:ApplicationPermissions;
    services-crm:modules/entities/aws/api/affiliation-types.routes.ts;
    services-crm:modules/entities/aws/api/contact-roles.routes.ts
coverage:
  rule: covered
  transition: 'gap: FND-CRM-ENT-065'
  validation: covered
  permission: covered
  edge: covered
  failure: covered
  boundary: covered
  concurrency: 'gap: FND-CRM-ENT-065'
  invariant: 'gap: FND-CRM-ENT-065'
  interaction: covered
previous_approval:
  revision: 1
  approved_by: Andrew
  approved_at: '2026-10-22T00:00:00.000Z'
coverage_notes:
  transition:
    reason: >-
      No detailed transition scenario currently specifies this aspect; the
      coverage finding records the required follow-through.
    provenance: unknown
    source: FND-CRM-ENT-065
  concurrency:
    reason: >-
      No detailed concurrency scenario currently specifies this aspect; the
      coverage finding records the required follow-through.
    provenance: unknown
    source: FND-CRM-ENT-065
  invariant:
    reason: >-
      No detailed invariant scenario currently specifies this aspect; the
      coverage finding records the required follow-through.
    provenance: unknown
    source: FND-CRM-ENT-065
coverage_findings:
  - FND-CRM-ENT-065
  - FND-CRM-ENT-075
permission_coverage:
  - key: crm.contact-roles.read
    where_checked: api
    scenario: ATS-CRM-ENT-017-19
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/planning/capabilities/CAP-CRM-ENT-017-maintain-the-kinds-of-tie-and-the-catalogue-of-roles-people.md
  - key: crm.contact-roles.create
    where_checked: api
    scenario: ATS-CRM-ENT-017-19
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/planning/capabilities/CAP-CRM-ENT-017-maintain-the-kinds-of-tie-and-the-catalogue-of-roles-people.md
  - key: crm.contact-roles.update
    where_checked: api
    scenario: ATS-CRM-ENT-017-19
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/planning/capabilities/CAP-CRM-ENT-017-maintain-the-kinds-of-tie-and-the-catalogue-of-roles-people.md
  - key: crm.contact-roles.delete
    where_checked: api
    scenario: ATS-CRM-ENT-017-19
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/planning/capabilities/CAP-CRM-ENT-017-maintain-the-kinds-of-tie-and-the-catalogue-of-roles-people.md
  - key: crm.affiliation-types.read
    where_checked: api
    scenario: ATS-CRM-ENT-017-19
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/planning/capabilities/CAP-CRM-ENT-017-maintain-the-kinds-of-tie-and-the-catalogue-of-roles-people.md
  - key: crm.affiliation-types.create
    where_checked: api
    scenario: ATS-CRM-ENT-017-19
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/planning/capabilities/CAP-CRM-ENT-017-maintain-the-kinds-of-tie-and-the-catalogue-of-roles-people.md
  - key: crm.affiliation-types.update
    where_checked: api
    scenario: ATS-CRM-ENT-017-19
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/planning/capabilities/CAP-CRM-ENT-017-maintain-the-kinds-of-tie-and-the-catalogue-of-roles-people.md
  - key: crm.affiliation-types.delete
    where_checked: api
    scenario: ATS-CRM-ENT-017-19
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/planning/capabilities/CAP-CRM-ENT-017-maintain-the-kinds-of-tie-and-the-catalogue-of-roles-people.md
  - key: crm.affiliation-types.set-default
    where_checked: api
    scenario: ATS-CRM-ENT-017-19
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/planning/capabilities/CAP-CRM-ENT-017-maintain-the-kinds-of-tie-and-the-catalogue-of-roles-people.md
related_coverage:
  - capability: CAP-CRM-ENT-006
    scenarios:
      - ATS-CRM-ENT-017-12
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/planning/capabilities/CAP-CRM-ENT-017-maintain-the-kinds-of-tie-and-the-catalogue-of-roles-people.md:related
  - capability: CAP-CRM-ENT-009
    scenarios:
      - ATS-CRM-ENT-017-13
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/planning/capabilities/CAP-CRM-ENT-017-maintain-the-kinds-of-tie-and-the-catalogue-of-roles-people.md:related
  - capability: CAP-CRM-ENT-011
    scenarios:
      - ATS-CRM-ENT-017-14
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/planning/capabilities/CAP-CRM-ENT-017-maintain-the-kinds-of-tie-and-the-catalogue-of-roles-people.md:related
  - capability: CAP-CRM-ENT-012
    scenarios:
      - ATS-CRM-ENT-017-15
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/planning/capabilities/CAP-CRM-ENT-017-maintain-the-kinds-of-tie-and-the-catalogue-of-roles-people.md:related
  - capability: CAP-CRM-ENT-015
    scenarios:
      - ATS-CRM-ENT-017-16
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/planning/capabilities/CAP-CRM-ENT-017-maintain-the-kinds-of-tie-and-the-catalogue-of-roles-people.md:related
  - capability: CAP-CRM-ENT-018
    scenarios:
      - ATS-CRM-ENT-017-17
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/planning/capabilities/CAP-CRM-ENT-017-maintain-the-kinds-of-tie-and-the-catalogue-of-roles-people.md:related
  - capability: CAP-CRM-ENT-019
    scenarios:
      - ATS-CRM-ENT-017-18
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/crm/entities/planning/capabilities/CAP-CRM-ENT-017-maintain-the-kinds-of-tie-and-the-catalogue-of-roles-people.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
---

# Configure affiliation types and contact roles
## 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-017-01` | `ATS-CRM-ENT-017-01` |
| `BR-CAP-CRM-ENT-017-02` | `ATS-CRM-ENT-017-02` |
| `BR-CAP-CRM-ENT-017-03` | `ATS-CRM-ENT-017-03`, `ATS-CRM-ENT-017-14`, `ATS-CRM-ENT-017-15` |
| `BR-CAP-CRM-ENT-017-04` | `ATS-CRM-ENT-017-04`, `ATS-CRM-ENT-017-16`, `ATS-CRM-ENT-017-19` |
| `BR-CAP-CRM-ENT-017-05` | `ATS-CRM-ENT-017-05` |
| `BR-CAP-CRM-ENT-017-06` | `ATS-CRM-ENT-017-06`, `ATS-CRM-ENT-017-13`, `ATS-CRM-ENT-017-18`, `ATS-CRM-ENT-017-19` |
| `BR-CAP-CRM-ENT-017-07` | `ATS-CRM-ENT-017-07`, `ATS-CRM-ENT-017-12`, `ATS-CRM-ENT-017-17` |
| `BR-CAP-CRM-ENT-017-08` | `ATS-CRM-ENT-017-08` |
| `BR-CAP-CRM-ENT-017-11` | `ATS-CRM-ENT-017-10` |

## Interactions With Related Capabilities

The interaction scenarios exercise share organization contact points with affiliated people; maintain a person’s organizational relationships; maintain responsibilities on organizational relationships; review organization role compliance and prepare notices; control record locks and system protection; organize the workspace’s record classifications; resolve the forms and layouts used for CRM records. 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.
