---
id: ATS-CRM-DQ-006
scope: CAP-CRM-DQ-006
product_area: crm
module: data-quality
revision: 1
status: proposed
source_sha:
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
scenarios:
  - id: ATS-CRM-DQ-006-01
    title: Registration suggestions use the medium floor and ranking
    level: api
    proves:
      - BR-CAP-CRM-DQ-006-01
      - BR-CAP-CRM-DQ-006-04
    preconditions: 'Prepare neighboring scores of 70, 50, 50, 50 and 38.'
    steps: Call candidate selection.
    expected: >-
      Three contacts appear, shared e-mail first and tied scores by number, with
      staff-equivalent scores.
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - TST-CRM-DQ-180
    provenance: test
    source: >-
      services-crm:modules/duplicates/tests/integration/db/portal-sign-up-contacts.integration.spec.js#answers
      the three best contacts above the floor, the e-mail match first and a tie
      in contact-number order, with what Platform masks
    category: boundary
    execution_sources:
      - >-
        services-crm:modules/duplicates/tests/integration/db/portal-sign-up-contacts.integration.spec.js#answers
        the three best contacts above the floor, the e-mail match first and a
        tie in contact-number order, with what Platform masks
      - >-
        services-crm:modules/duplicates/tests/integration/db/portal-sign-up-contacts.integration.spec.js#leaves
        out a fourth contact at the floor, because a member is shown three
      - >-
        services-crm:modules/duplicates/tests/integration/db/portal-sign-up-contacts.integration.spec.js#scores
        every contact of the neighbourhood with the score and the reasons the
        TypeScript scorer gives it
  - id: ATS-CRM-DQ-006-02
    title: Unavailable registration identities are excluded
    level: api
    proves:
      - BR-CAP-CRM-DQ-006-02
    preconditions: 'Prepare linked, deleted and other-workspace matching contacts.'
    steps: Request candidates.
    expected: None of those contacts is offered.
    negative: true
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - TST-CRM-DQ-180
    provenance: test
    source: >-
      services-crm:modules/duplicates/tests/integration/db/portal-sign-up-contacts.integration.spec.js#never
      offers a contact a portal user of the tenant already links
    category: edge
    execution_sources:
      - >-
        services-crm:modules/duplicates/tests/integration/db/portal-sign-up-contacts.integration.spec.js#never
        offers a contact a portal user of the tenant already links
      - >-
        services-crm:modules/duplicates/tests/integration/db/portal-sign-up-contacts.integration.spec.js#never
        offers a contact that has been deleted, its keys gone with it
      - >-
        services-crm:modules/duplicates/tests/integration/db/portal-sign-up-contacts.integration.spec.js#offers
        only the asking tenant's contacts, the same sign-up in the other tenant
        finding that tenant's own
  - id: ATS-CRM-DQ-006-03
    title: Declining a suggestion preserves a review pair
    level: api
    proves:
      - BR-CAP-CRM-DQ-006-05
      - BR-CAP-CRM-DQ-006-06
      - BR-CAP-CRM-DQ-006-07
    preconditions: Registration rejects an existing candidate.
    steps: Create the portal contact naming that candidate and detect the new record.
    expected: >-
      The contact has portal attribution and an open declined-match pair at 35
      that remains grouped after detection.
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - TST-CRM-DQ-180
    provenance: test
    source: >-
      services-crm:modules/duplicates/tests/integration/db/portal-sign-up-contacts.integration.spec.js#writes
      the contact with a UUIDv7 id, the next number, the names trimmed and
      computed and the stamps of portal-sign-up
    category: transition
    execution_sources:
      - >-
        services-crm:modules/duplicates/tests/integration/db/portal-sign-up-contacts.integration.spec.js#writes
        the contact with a UUIDv7 id, the next number, the names trimmed and
        computed and the stamps of portal-sign-up
      - >-
        services-crm:modules/duplicates/tests/integration/db/portal-sign-up-contacts.integration.spec.js#records
        the declined pair, open, with origin portal_sign_up and the score and
        reasons the scorer gives it
      - >-
        services-crm:modules/duplicates/tests/integration/db/portal-sign-up-contacts.integration.spec.js#keeps
        the declined pair through detection pass over the new contact, which
        groups it
  - id: ATS-CRM-DQ-006-04
    title: Repeated registration reuses its recent contact
    level: api
    proves:
      - BR-CAP-CRM-DQ-006-08
    preconditions: A registration has just created a contact.
    steps: Repeat the submission within one minute.
    expected: The function returns that contact and performs no further creation.
    negative: false
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - TST-CRM-DQ-180
    provenance: test
    source: >-
      services-crm:modules/duplicates/tests/integration/db/portal-sign-up-contacts.integration.spec.js#answers
      the same contact for the same sign-up retried within a minute, and writes
      nothing more
    category: invariant
    execution_sources:
      - >-
        services-crm:modules/duplicates/tests/integration/db/portal-sign-up-contacts.integration.spec.js#answers
        the same contact for the same sign-up retried within a minute, and
        writes nothing more
  - id: ATS-CRM-DQ-006-05
    title: Registration honors contact validation
    level: api
    proves:
      - BR-CAP-CRM-DQ-006-09
    preconditions: An active contact reserves the intended primary e-mail.
    steps: 'Try creation with that address, then try creation without either name.'
    expected: Both requests are rejected.
    negative: true
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - TST-CRM-DQ-180
    provenance: test
    source: >-
      services-crm:modules/duplicates/tests/integration/db/portal-sign-up-contacts.integration.spec.js#refuses
      an address that is already the primary address of a contact it did not
      just create
    category: validation
    execution_sources:
      - >-
        services-crm:modules/duplicates/tests/integration/db/portal-sign-up-contacts.integration.spec.js#refuses
        an address that is already the primary address of a contact it did not
        just create
      - >-
        services-crm:modules/duplicates/tests/integration/db/portal-sign-up-contacts.integration.spec.js#refuses
        a sign-up with neither a first nor a last name
  - id: ATS-CRM-DQ-006-06
    title: Portal functions restrict their callers and workspace
    level: api
    proves:
      - BR-CAP-CRM-DQ-006-10
    preconditions: Use the CRM application role and a session outside the target workspace.
    steps: Attempt the registration functions.
    expected: The calls are denied.
    negative: true
    data_needs: The existing scenario setup supplies the required records.
    bound_to:
      - TST-CRM-DQ-180
    provenance: test
    source: >-
      services-crm:modules/duplicates/tests/integration/db/portal-sign-up-contacts.integration.spec.js#refuses
      CRM's own application role, which is not granted it
    category: permission
    execution_sources:
      - >-
        services-crm:modules/duplicates/tests/integration/db/portal-sign-up-contacts.integration.spec.js#refuses
        CRM's own application role, which is not granted it
      - >-
        services-crm:modules/duplicates/tests/integration/db/portal-sign-up-contacts.integration.spec.js#refuses
        a session already acting in another tenant
  - id: ATS-CRM-DQ-006-07
    title: A name alone produces no registration suggestion
    category: rule
    level: api
    proves:
      - BR-CAP-CRM-DQ-006-03
    preconditions: >-
      An unlinked contact matching the supplied names but sharing neither e-mail
      nor phone.
    steps: >-
      Select registration candidates, then repeat with a shared phone and
      sufficient scoring evidence.
    expected: >-
      The name-only input returns no candidate; the shared-phone case can return
      the eligible contact.
    negative: true
    data_needs: Run-owned records and caller permissions that distinguish the two cases.
    source: >-
      services-crm:modules/duplicates/tests/integration/db/portal-sign-up-contacts.integration.spec.js#offers
      nothing for a sign-up that shares no e-mail address and no number with any
      contact
    design_sources:
      - CAP-CRM-DQ-006
    bound_to: []
    provenance: proposed
    execution_sources: []
  - id: ATS-CRM-DQ-006-08
    title: Declined registration reaches the staff queue
    category: interaction
    level: api
    proves:
      - BR-CAP-CRM-DQ-006-01
      - BR-CAP-CRM-DQ-006-04
      - BR-CAP-CRM-DQ-006-02
      - BR-CAP-CRM-DQ-006-05
      - BR-CAP-CRM-DQ-006-06
      - BR-CAP-CRM-DQ-006-07
      - BR-CAP-CRM-DQ-006-08
      - BR-CAP-CRM-DQ-006-09
      - BR-CAP-CRM-DQ-006-10
      - BR-CAP-CRM-DQ-006-03
    exercises:
      - CAP-CRM-DQ-006
      - CAP-CRM-DQ-007
    workflow_sources:
      - WF-CRM-DQ-008
    preconditions: >-
      Run-owned contact and organization records, the relevant staff permissions
      and the related state described by the sequence.
    steps: >-
      Decline an eligible offered contact, create the registration contact,
      deliver its detection change and open the resulting review group.
    expected: >-
      The registration pair retains its origin and the staff queue presents the
      same contact evidence.
    negative: false
    data_needs: >-
      An isolated workspace with related records and fixed timestamps; owned
      participant failure injection where requested.
    source: CAP-CRM-DQ-006; CAP-CRM-DQ-007; WF-CRM-DQ-008
    note: >-
      This cumulative seam scenario remains proposed until one executable
      sequence establishes all of its outcomes.
    bound_to: []
    provenance: proposed
    workflow_coverage_note: >-
      The workflows identify the handoffs under review. Separate assertions
      leave recovery and failure ordering unproved; the capability coverage
      finding records that limit.
    execution_sources: []
evidence:
  - repository: services-crm
    source_sha: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
    paths:
      - >-
        modules/duplicates/tests/integration/db/portal-sign-up-contacts.integration.spec.js
    note: >-
      Bindings identify authored proof; empty bindings remain proposed and
      findings record known limitations.
coverage:
  rule: covered
  transition: covered
  validation: covered
  permission: covered
  edge: covered
  failure: 'gap: FND-CRM-DQ-057'
  boundary: covered
  concurrency: 'gap: FND-CRM-DQ-057'
  invariant: covered
  interaction: covered
coverage_notes:
  failure: >-
    No complete scenario currently isolates this category; the finding lists the
    remaining proof obligation.
  concurrency: >-
    No complete scenario currently isolates this category; the finding lists the
    remaining proof obligation.
permission_coverage: []
proof_matrix:
  - rule: BR-CAP-CRM-DQ-006-01
    scenarios:
      - ATS-CRM-DQ-006-01
      - ATS-CRM-DQ-006-08
  - rule: BR-CAP-CRM-DQ-006-02
    scenarios:
      - ATS-CRM-DQ-006-02
      - ATS-CRM-DQ-006-08
  - rule: BR-CAP-CRM-DQ-006-03
    scenarios:
      - ATS-CRM-DQ-006-07
      - ATS-CRM-DQ-006-08
  - rule: BR-CAP-CRM-DQ-006-04
    scenarios:
      - ATS-CRM-DQ-006-01
      - ATS-CRM-DQ-006-08
  - rule: BR-CAP-CRM-DQ-006-05
    scenarios:
      - ATS-CRM-DQ-006-03
      - ATS-CRM-DQ-006-08
  - rule: BR-CAP-CRM-DQ-006-06
    scenarios:
      - ATS-CRM-DQ-006-03
      - ATS-CRM-DQ-006-08
  - rule: BR-CAP-CRM-DQ-006-07
    scenarios:
      - ATS-CRM-DQ-006-03
      - ATS-CRM-DQ-006-08
  - rule: BR-CAP-CRM-DQ-006-08
    scenarios:
      - ATS-CRM-DQ-006-04
      - ATS-CRM-DQ-006-08
  - rule: BR-CAP-CRM-DQ-006-09
    scenarios:
      - ATS-CRM-DQ-006-05
      - ATS-CRM-DQ-006-08
  - rule: BR-CAP-CRM-DQ-006-10
    scenarios:
      - ATS-CRM-DQ-006-06
      - ATS-CRM-DQ-006-08
interaction_coverage:
  related:
    - CAP-CRM-DQ-007
  workflow_sources:
    - WF-CRM-DQ-008
  scenarios:
    - ATS-CRM-DQ-006-08
---

# Reuse a contact during portal registration: Capability Test Specification

## Coverage

The rule matrix names the authored checks. A covered category means that a scenario exists; it does not report a passing execution. The coverage notes and findings identify missing checks, while execution sources retain the exact assertions inspected.

| Required Rule | Scenarios |
|---|---|
| `BR-CAP-CRM-DQ-006-01` | `ATS-CRM-DQ-006-01`, `ATS-CRM-DQ-006-08` |
| `BR-CAP-CRM-DQ-006-02` | `ATS-CRM-DQ-006-02`, `ATS-CRM-DQ-006-08` |
| `BR-CAP-CRM-DQ-006-03` | `ATS-CRM-DQ-006-07`, `ATS-CRM-DQ-006-08` |
| `BR-CAP-CRM-DQ-006-04` | `ATS-CRM-DQ-006-01`, `ATS-CRM-DQ-006-08` |
| `BR-CAP-CRM-DQ-006-05` | `ATS-CRM-DQ-006-03`, `ATS-CRM-DQ-006-08` |
| `BR-CAP-CRM-DQ-006-06` | `ATS-CRM-DQ-006-03`, `ATS-CRM-DQ-006-08` |
| `BR-CAP-CRM-DQ-006-07` | `ATS-CRM-DQ-006-03`, `ATS-CRM-DQ-006-08` |
| `BR-CAP-CRM-DQ-006-08` | `ATS-CRM-DQ-006-04`, `ATS-CRM-DQ-006-08` |
| `BR-CAP-CRM-DQ-006-09` | `ATS-CRM-DQ-006-05`, `ATS-CRM-DQ-006-08` |
| `BR-CAP-CRM-DQ-006-10` | `ATS-CRM-DQ-006-06`, `ATS-CRM-DQ-006-08` |

## Interactions With Related Capabilities

Decline an eligible offered contact, create the registration contact, deliver its detection change and open the resulting review group.

These sequences test the handoffs named in the interaction coverage record. A proposed sequence remains unbound until an executable run checks its combined outcome; component assertions alone leave that obligation open.
