---
id: ATS-CRM-ACT-001
scope: CAP-CRM-ACT-001
product_area: crm
module: activities-tasks
revision: 2
status: proposed
approved_by: null
approved_at: null
source_sha:
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
scenarios:
  - id: ATS-CRM-ACT-001-01
    title: Reject invalid activity link sets
    level: api
    proves:
      - BR-CAP-CRM-ACT-001-01
    preconditions: Workspace contact and organization fixtures are available.
    steps: 'Submit empty, ambiguous, repeated and 201-entry link sets.'
    expected: Each request identifies invalid links and leaves no activity.
    negative: true
    data_needs: Each run creates and isolates the records it needs.
    bound_to:
      - >-
        services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#refuses
        an activity linked to nothing
      - >-
        services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#refuses
        a link that names both a contact and an organization
      - >-
        services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#refuses
        a record linked twice
      - >-
        services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#refuses
        more than 200 links
      - >-
        services-crm:modules/activities/tests/integration/db/activities.table.integration.spec.js#refuses
        a link to a contact and an organization at once
    provenance: test
    source: >-
      services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#refuses
      an activity linked to nothing
  - id: ATS-CRM-ACT-001-02
    title: Default a primary link and reject competing primaries
    level: api
    proves:
      - BR-CAP-CRM-ACT-001-02
    preconditions: Two workspace contacts can be linked.
    steps: 'Save with neither primary, then with both marked primary.'
    expected: >-
      The first link becomes primary in the valid save; the conflicting save
      fails.
    negative: true
    data_needs: Each run creates and isolates the records it needs.
    bound_to:
      - >-
        services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#makes
        the first link the primary one when none says it is
      - >-
        services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#refuses
        two primary links
      - >-
        services-crm:modules/activities/tests/integration/db/activities.table.integration.spec.js#refuses
        a second primary link of one activity
    provenance: test
    source: >-
      services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#makes
      the first link the primary one when none says it is
  - id: ATS-CRM-ACT-001-03
    title: Select a different primary record in the form
    level: browser
    proves:
      - BR-CAP-CRM-ACT-001-02
    preconditions: A contact has an organization available for linking.
    steps: Log an activity and make the organization chip primary.
    expected: The stored primary link names the organization.
    negative: false
    data_needs: Each run creates and isolates the records it needs.
    bound_to:
      - >-
        react-console:lib/activities/links.test.ts#makes a chosen contact or
        organization the one primary link
      - >-
        react-console:acceptance/crm/playwright/journeys/cross-application/CRM-ACC-0691.spec.ts#CRM-ACC-0691
    provenance: test
    source: >-
      react-console:lib/activities/links.test.ts#makes a chosen contact or
      organization the one primary link
  - id: ATS-CRM-ACT-001-04
    title: Reject unavailable types for new interactions
    level: api
    proves:
      - BR-CAP-CRM-ACT-001-03
    preconditions: An activity type is inactive.
    steps: Create an activity with that type.
    expected: The service identifies the unavailable type and refuses creation.
    negative: true
    data_needs: Each run creates and isolates the records it needs.
    bound_to:
      - >-
        services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#refuses
        an inactive type for a new activity
      - >-
        services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#refuses
        a type the tenant does not have
    provenance: test
    source: >-
      services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#refuses
      an inactive type for a new activity
  - id: ATS-CRM-ACT-001-05
    title: Apply field modes without forbidding hidden attendee links
    level: unit
    proves:
      - BR-CAP-CRM-ACT-001-04
      - BR-CAP-CRM-ACT-001-16
    preconditions: Types cover hidden and required modes.
    steps: >-
      Evaluate hidden values, absent required values, a scheduled call and
      contacts with attendees hidden.
    expected: >-
      Invalid details fail; the scheduled call needs no completed-result fields
      and hidden attendee links remain valid.
    negative: true
    data_needs: Each run creates and isolates the records it needs.
    bound_to:
      - >-
        services-crm:modules/activities/tests/unit/services/activities/field-modes.spec.js#refuses
        a hidden direction that is present
      - >-
        services-crm:modules/activities/tests/unit/services/activities/field-modes.spec.js#refuses
        a required outcome that a completed activity lacks
      - >-
        services-crm:modules/activities/tests/unit/services/activities/field-modes.spec.js#asks
        a scheduled activity for no required outcome or duration, those being
        what came of it
      - >-
        services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#refuses
        a hidden field: a note with a direction
      - >-
        services-crm:modules/activities/tests/e2e/activities.e2e.spec.js#refuses
        a hidden field the type does not take: 400 naming it
      - >-
        services-crm:modules/activities/tests/unit/services/activities/field-modes.spec.js#refuses
        nothing about the links when attendees are hidden
    provenance: test
    source: >-
      services-crm:modules/activities/tests/unit/services/activities/field-modes.spec.js#refuses
      a hidden direction that is present
  - id: ATS-CRM-ACT-001-06
    title: Require an additional contact attendee
    level: api
    proves:
      - BR-CAP-CRM-ACT-001-05
    preconditions: The chosen type requires attendees.
    steps: Log an activity with only a primary contact.
    expected: The request identifies the missing attendee links.
    negative: true
    data_needs: Each run creates and isolates the records it needs.
    bound_to:
      - >-
        services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#asks
        for an attendee besides the primary record when the type requires
        attendees
    provenance: test
    source: >-
      services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#asks
      for an attendee besides the primary record when the type requires
      attendees
  - id: ATS-CRM-ACT-001-07
    title: Validate outcomes against type and active selection
    level: api
    proves:
      - BR-CAP-CRM-ACT-001-06
    preconditions: Two types and a deactivated outcome exist.
    steps: >-
      Try a foreign outcome and an inactive outcome, then retain a prior
      inactive selection.
    expected: New invalid selections fail while an existing inactive outcome can remain.
    negative: true
    data_needs: Each run creates and isolates the records it needs.
    bound_to:
      - >-
        services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#refuses
        an outcome of another type
      - >-
        services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#refuses
        a deactivated outcome for a new activity
      - >-
        services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#keeps
        a deactivated outcome on an activity that already has it
      - >-
        services-crm:modules/activities/tests/integration/db/activities.table.integration.spec.js#refuses
        an outcome of another type, by the three-column key
    provenance: test
    source: >-
      services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#refuses
      an outcome of another type
  - id: ATS-CRM-ACT-001-08
    title: Report time and numeric boundary failures
    level: api
    proves:
      - BR-CAP-CRM-ACT-001-07
    preconditions: A valid active type is available.
    steps: >-
      Send an earlier end, durations outside zero to 1,440 and a 501-character
      subject.
    expected: Each refusal names the relevant field.
    negative: true
    data_needs: Each run creates and isolates the records it needs.
    bound_to:
      - >-
        services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#refuses
        an end before the start
      - >-
        services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#refuses
        a duration below 0 minutes, naming the field
      - >-
        services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#refuses
        a duration above 1440 minutes, naming the field
      - >-
        services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#refuses
        a subject of more than 500 characters, naming the field
    provenance: test
    source: >-
      services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#refuses
      an end before the start
  - id: ATS-CRM-ACT-001-09
    title: Clean note content and reject excessive retained text
    level: unit
    proves:
      - BR-CAP-CRM-ACT-001-08
    preconditions: The sanitizer and a valid activity fixture are available.
    steps: >-
      Supply unsafe markup, empty markup and more than 100,000 retained
      characters.
    expected: >-
      Unsafe content disappears, empty content becomes empty, and excessive
      content fails by field.
    negative: true
    data_needs: Each run creates and isolates the records it needs.
    bound_to:
      - >-
        services-crm:modules/activities/tests/unit/services/activities/activity-body.spec.js#drops
        a script and its content
      - >-
        services-crm:modules/activities/tests/unit/services/activities/activity-body.spec.js#drops
        an event handler and an inline style
      - >-
        services-crm:modules/activities/tests/unit/services/activities/activity-body.spec.js#drops
        a javascript: link but keeps its text
      - >-
        services-crm:modules/activities/tests/unit/services/activities/activity-body.spec.js#answers
        null for a body of nothing but markup and whitespace
      - >-
        services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#refuses
        a body over 100000 characters once sanitised, naming body, and writes
        nothing
      - >-
        services-crm:modules/activities/tests/e2e/activities.e2e.spec.js#refuses
        a body over 100000 characters once sanitised: 400 naming body
    provenance: test
    source: >-
      services-crm:modules/activities/tests/unit/services/activities/activity-body.spec.js#drops
      a script and its content
  - id: ATS-CRM-ACT-001-10
    title: Apply defaults for person and machine callers
    level: api
    proves:
      - BR-CAP-CRM-ACT-001-09
    preconditions: A type declares a default duration.
    steps: Create with only required details as a user and as a job.
    expected: >-
      Type and clock defaults apply; the job-created activity has no default
      user owner.
    negative: false
    data_needs: Each run creates and isolates the records it needs.
    bound_to:
      - >-
        services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#defaults
        the status, the time and the owner from the type, the clock and the
        caller
      - >-
        services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#defaults
        a type’s duration on a create that states none
      - >-
        services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#gives
        the activity no owner when the caller is not a user
    provenance: test
    source: >-
      services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#defaults
      the status, the time and the owner from the type, the clock and the caller
  - id: ATS-CRM-ACT-001-11
    title: Recover one activity from repeated creation
    level: api
    proves:
      - BR-CAP-CRM-ACT-001-11
    preconditions: A client selects a valid time-ordered activity identifier.
    steps: >-
      Repeat identical creates, race them, and submit different content under
      the same identifier.
    expected: >-
      Identical deliveries retain one activity and follow-up; differing content
      conflicts.
    negative: true
    data_needs: Each run creates and isolates the records it needs.
    bound_to:
      - >-
        services-crm:modules/activities/tests/integration/services/persistence/activities.create-retries.integration.spec.js#makes
        one activity
      - >-
        services-crm:modules/activities/tests/integration/services/persistence/activities.create-retries.integration.spec.js#answers
        the retry with the activity the first attempt made, as a read answers it
      - >-
        services-crm:modules/activities/tests/integration/services/persistence/activities.create-retries.integration.spec.js#refuses
        it as a conflict (409), naming the id
      - >-
        react-console:acceptance/crm/playwright/journeys/cross-application/CRM-ACC-0729.spec.ts#CRM-ACC-0729
    provenance: test
    source: >-
      services-crm:modules/activities/tests/integration/services/persistence/activities.create-retries.integration.spec.js#makes
      one activity
  - id: ATS-CRM-ACT-001-12
    title: Retain import attribution and unique external references
    level: api
    proves:
      - BR-CAP-CRM-ACT-001-12
    preconditions: An import origin and external reference are supplied.
    steps: >-
      Create an imported activity, repeat its external reference and edit the
      original.
    expected: Origin persists and duplicate external references fail.
    negative: true
    data_needs: Each run creates and isolates the records it needs.
    bound_to:
      - >-
        services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#records
        sys_origin and sys_external_id from the source it is given
      - >-
        services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#keeps
        the origin it was created with
      - >-
        services-crm:modules/activities/tests/integration/db/activities.table.integration.spec.js#refuses
        a second activity of the tenant under the same external id
    provenance: test
    source: >-
      services-crm:modules/activities/tests/integration/services/persistence/activities.integration.spec.js#records
      sys_origin and sys_external_id from the source it is given
  - id: ATS-CRM-ACT-001-13
    title: Reject activity custom field values
    level: api
    proves:
      - BR-CAP-CRM-ACT-001-13
    preconditions: An active type permits a valid activity.
    steps: Include custom field values in the save.
    expected: The API rejects the unsupported custom-field property.
    negative: true
    data_needs: Each run creates and isolates the records it needs.
    bound_to:
      - >-
        services-crm:modules/activities/tests/e2e/activities.e2e.spec.js#refuses
        a custom field value, an activity having no custom fields (R2-ARCH-001):
        400 naming custom_fields
      - >-
        services-crm:modules/activities/tests/e2e/activities.e2e.spec.js#answers
        an activity with no custom_fields property
    provenance: test
    source: >-
      services-crm:modules/activities/tests/e2e/activities.e2e.spec.js#refuses a
      custom field value, an activity having no custom fields (R2-ARCH-001): 400
      naming custom_fields
evidence:
  - >-
    Pinned service assertions and proposed proof cases are identified in the
    scenario sources and bindings.
  - >-
    Pinned console assertions and proposed proof cases are identified in the
    scenario sources and bindings.
---

# Log one interaction for all related people and organizations: Acceptance Test Set

## Coverage

Bound scenarios identify existing assertions; unbound scenarios remain proposed proof. Static inspection does not establish a passing execution.

| Rule | Proof Scenario Or Gap |
|---|---|
| `BR-CAP-CRM-ACT-001-01` | `ATS-CRM-ACT-001-01` |
| `BR-CAP-CRM-ACT-001-02` | `ATS-CRM-ACT-001-02`, `ATS-CRM-ACT-001-03` |
| `BR-CAP-CRM-ACT-001-03` | `ATS-CRM-ACT-001-04` |
| `BR-CAP-CRM-ACT-001-04` | `ATS-CRM-ACT-001-05` |
| `BR-CAP-CRM-ACT-001-05` | `ATS-CRM-ACT-001-06` |
| `BR-CAP-CRM-ACT-001-06` | `ATS-CRM-ACT-001-07` |
| `BR-CAP-CRM-ACT-001-07` | `ATS-CRM-ACT-001-08` |
| `BR-CAP-CRM-ACT-001-08` | `ATS-CRM-ACT-001-09` |
| `BR-CAP-CRM-ACT-001-09` | `ATS-CRM-ACT-001-10` |
| `BR-CAP-CRM-ACT-001-11` | `ATS-CRM-ACT-001-11` |
| `BR-CAP-CRM-ACT-001-12` | `ATS-CRM-ACT-001-12` |
| `BR-CAP-CRM-ACT-001-13` | `ATS-CRM-ACT-001-13` |
| `BR-CAP-CRM-ACT-001-15` | no scenario: `FND-CRM-ACT-028` |
| `BR-CAP-CRM-ACT-001-16` | `ATS-CRM-ACT-001-05` |

| `BR-CAP-CRM-ACT-001-17` | no scenario: `FND-CRM-ACT-033` |
