---
id: ATS-CRM-REG-001
scope: CAP-CRM-REG-001
product_area: crm
module: regions
revision: 3
status: proposed
approved_by: null
approved_at: null
source_sha:
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
scenarios:
  - id: ATS-CRM-REG-001-01
    title: Identifier validation preserves the legacy grammar
    level: api
    proves:
      - BR-CAP-CRM-REG-001-01
    preconditions: Regional creation is authorized.
    steps: Submit an identifier with a space and another combining permitted punctuation.
    expected: The invalid identifier receives a field-specific refusal; the valid identifier is accepted.
    negative: true
    data_needs: An invalid spaced identifier and valid identifiers covering the accepted grammar.
    bound_to:
      - TST-CRM-REG-047
      - TST-CRM-REG-049
    provenance: test
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#answers 400 for an id with a space,
      naming the characters an id may hold
    category: validation
    test_assertions:
      - >-
        services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#answers 400 for an id with a space,
        naming the characters an id may hold
      - >-
        services-crm:modules/regions/tests/integration/db/regions.table.integration.spec.js#refuses an id
        outside the legacy grammar (a space)
      - >-
        services-crm:modules/regions/tests/integration/db/regions.table.integration.spec.js#accepts the
        characters of the legacy grammar (word characters, | and -)
  - id: ATS-CRM-REG-001-02
    title: Blank names prevent creation
    level: api
    proves:
      - BR-CAP-CRM-REG-001-02
    preconditions: The caller can create regions.
    steps: Submit creation without a name and with a name containing only spaces.
    expected: Both requests fail name validation and persist nothing.
    negative: true
    data_needs: The authorized workspace requires no additional records.
    bound_to:
      - TST-CRM-REG-047
      - TST-CRM-REG-049
    provenance: test
    source: 'services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#answers 400 for a body with no name'
    category: validation
    test_assertions:
      - 'services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#answers 400 for a body with no name'
      - >-
        services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#answers 400 naming the field for a
        name of nothing but spaces
      - >-
        services-crm:modules/regions/tests/integration/db/regions.table.integration.spec.js#refuses a
        blank name
  - id: ATS-CRM-REG-001-03
    title: Generated and duplicate identifiers have distinct outcomes
    level: api
    proves:
      - BR-CAP-CRM-REG-001-03
      - BR-CAP-CRM-REG-001-04
    preconditions: A named region already exists.
    steps: 'Create without an identifier, then attempt another creation using the existing identifier.'
    expected: >-
      The first receives a generated identifier and defaults active; the duplicate is rejected without
      modifying the original.
    negative: true
    data_needs: A previously saved regional definition.
    bound_to:
      - TST-CRM-REG-054
    provenance: test
    source: >-
      services-crm:modules/regions/tests/integration/services/persistence/regions.integration.spec.js#generates
      an id when the client names none
    category: edge
    test_assertions:
      - >-
        services-crm:modules/regions/tests/integration/services/persistence/regions.integration.spec.js#generates
        an id when the client names none
      - >-
        services-crm:modules/regions/tests/integration/services/persistence/regions.integration.spec.js#refuses
        an id the tenant already uses
      - >-
        services-crm:modules/regions/tests/integration/services/persistence/regions.integration.spec.js#creates
        a region active by default
  - id: ATS-CRM-REG-001-04
    title: Replacement requires a current version
    level: api
    proves:
      - BR-CAP-CRM-REG-001-05
    preconditions: The saved region has version two.
    steps: 'Replace using version one, omit the version, then use version two.'
    expected: 'The requests respectively conflict, fail validation and save at version three.'
    negative: true
    data_needs: A regional definition with an intervening edit.
    bound_to: []
    provenance: proposed
    source: FND-CRM-REG-022
    category: concurrency
  - id: ATS-CRM-REG-001-05
    title: Replacement removes omitted fields
    level: api
    proves:
      - BR-CAP-CRM-REG-001-06
    preconditions: The region has a description and external identifier.
    steps: Replace the region with its required name and current version while omitting those fields.
    expected: The omitted values clear and the version increases.
    negative: false
    data_needs: A region carrying explanatory text.
    bound_to:
      - TST-CRM-REG-055
    provenance: test
    source: >-
      services-crm:modules/regions/tests/integration/services/persistence/regions.queries.integration.spec.js#the
      record a replace left › answers the whole record as the replace left it: the fields it did not
      state cleared, the version bumped
    category: rule
    test_assertions:
      - >-
        services-crm:modules/regions/tests/integration/services/persistence/regions.queries.integration.spec.js#the
        record a replace left › answers the whole record as the replace left it: the fields it did not
        state cleared, the version bumped
  - id: ATS-CRM-REG-001-06
    title: Pagination preserves identifier order
    level: api
    proves:
      - BR-CAP-CRM-REG-001-07
    preconditions: Region identifiers include different letter cases.
    steps: Read small pages and continue from each returned position.
    expected: 'All records appear once in byte order, and the final page has no continuation.'
    negative: false
    data_needs: Five catalogue entries whose identifiers mix letter case.
    bound_to:
      - TST-CRM-REG-054
      - TST-CRM-REG-055
    provenance: test
    source: >-
      services-crm:modules/regions/tests/integration/services/persistence/regions.integration.spec.js#lists
      the tenant's regions in id order by bytes, a page at a time
    category: boundary
    test_assertions:
      - >-
        services-crm:modules/regions/tests/integration/services/persistence/regions.integration.spec.js#lists
        the tenant's regions in id order by bytes, a page at a time
      - >-
        services-crm:modules/regions/tests/integration/services/persistence/regions.queries.integration.spec.js#listRegions
        › answers the next page beginning where the first one ended
  - id: ATS-CRM-REG-001-07
    title: Reads are workspace-specific
    level: api
    proves:
      - BR-CAP-CRM-REG-001-08
    preconditions: A caller can access two workspaces.
    steps: Read and list one workspace’s region through the other workspace.
    expected: The single read returns not found and the list excludes the foreign region.
    negative: true
    data_needs: Two distinct customer workspaces.
    bound_to:
      - TST-CRM-REG-047
      - TST-CRM-REG-054
    provenance: test
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#the regions › answers 404 for this
      tenant's region read in another tenant, to a context that covers both
    category: boundary
    test_assertions:
      - >-
        services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#the regions › answers 404 for this
        tenant's region read in another tenant, to a context that covers both
      - >-
        services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#the regions › answers none of this
        tenant's regions to another tenant's list
      - >-
        services-crm:modules/regions/tests/integration/services/persistence/regions.integration.spec.js#never
        reads another tenant's region
  - id: ATS-CRM-REG-001-08
    title: An ambiguous create response does not duplicate the region
    level: unit
    proves:
      - BR-CAP-CRM-REG-001-10
    preconditions: The drawer already chose the creation identifier.
    steps: Lose the first response and retry creation.
    expected: Lookup recovers the original region and no duplicate is created.
    negative: false
    data_needs: A request double that loses the initial response.
    bound_to:
      - TST-CRM-REG-046
    provenance: test
    source: >-
      react-console:lib/configuration/regions.test.ts#the regions api writes (D-05, D-35, D-43) › creates
      a region under the id the drawer chose and finds it when the answer was lost
    category: failure
    test_assertions:
      - >-
        react-console:lib/configuration/regions.test.ts#the regions api writes (D-05, D-35, D-43) ›
        creates a region under the id the drawer chose and finds it when the answer was lost
  - id: ATS-CRM-REG-001-09
    title: Unchanged replacement still advances the version
    level: api
    proves:
      - BR-CAP-CRM-REG-001-12
    preconditions: The region stands at version two.
    steps: Replace it with the same fields and version.
    expected: The fields remain but the saved version becomes three.
    negative: false
    data_needs: A single regional definition.
    bound_to: []
    provenance: proposed
    source: 'services-crm:modules/regions/services/persistence/regions.ts:updateRegionRow'
    category: transition
  - id: ATS-CRM-REG-001-10
    title: A shared catalogue survives import and retirement
    category: interaction
    level: api
    proves:
      - BR-CAP-CRM-REG-001-08
      - BR-CAP-CRM-REG-002-06
      - BR-CAP-CRM-REG-013-05
      - BR-CAP-CRM-REG-014-03
      - BR-CAP-CRM-REG-015-02
    preconditions: >-
      An authorized importer has a file defining one region and an administrator can maintain the
      catalogue.
    steps: >-
      Apply the file, read and rename its region, retire it, then export the saved catalogue; repeat the
      write requests as a reader.
    expected: >-
      The same regional identity appears through maintenance and export, retirement retains it, and the
      reader cannot change it.
    negative: false
    data_needs: >-
      An authorized importer has a file defining one region and an administrator can maintain the
      catalogue.
    bound_to: []
    provenance: proposed
    source: WF-CRM-REG-005
    exercises:
      - CAP-CRM-REG-001
      - CAP-CRM-REG-002
      - CAP-CRM-REG-013
      - CAP-CRM-REG-014
      - CAP-CRM-REG-015
  - id: ATS-CRM-REG-001-11
    title: Regional identity remains local across competing references
    category: invariant
    level: api
    proves:
      - INV-DOM-CRM-REG-001-01
      - INV-DOM-CRM-REG-001-03
      - INV-DOM-CRM-REG-001-04
    preconditions: Two workspaces each have a region with the same identifier.
    steps: 'Create local references, attempt a foreign-only reference and remove each referenced definition.'
    expected: Local references resolve to their own definition and foreign or dangling references do not commit.
    negative: true
    data_needs: Two workspaces each have a region with the same identifier.
    bound_to: []
    provenance: proposed
    source: DOM-CRM-REG-001
evidence:
  - >-
    services-crm: Examined the pinned regional implementation, its declared constraints and the
    supporting records.
  - 'react-console: Examined the pinned regional configuration surfaces and their available test evidence.'
  - 'services-crm:modules/regions/tests/e2e/regions.e2e.spec.js'
  - 'services-crm:modules/regions/tests/integration/db/regions.table.integration.spec.js'
  - 'services-crm:modules/regions/tests/integration/services/persistence/regions.integration.spec.js'
  - >-
    services-crm:modules/regions/tests/integration/services/persistence/regions.queries.integration.spec.js
  - 'react-console:lib/configuration/regions.test.ts'
  - 'services-crm:modules/regions/services/persistence/regions.ts'
coverage:
  rule: covered
  transition: covered
  validation: covered
  permission: 'gap: FND-CRM-REG-046'
  edge: covered
  failure: covered
  boundary: covered
  concurrency: covered
  invariant: covered
  interaction: covered
---

# Maintain the region catalogue: Capability Test Specification

## Coverage

Each row links a required rule to its authored proof. A covered category records a specification; executable and remaining variant gaps stay in the finding register.

| Rule | Proved By |
|---|---|
| `BR-CAP-CRM-REG-001-01` | `ATS-CRM-REG-001-01` |
| `BR-CAP-CRM-REG-001-02` | `ATS-CRM-REG-001-02` |
| `BR-CAP-CRM-REG-001-03` | `ATS-CRM-REG-001-03` |
| `BR-CAP-CRM-REG-001-05` | `ATS-CRM-REG-001-04` |
| `BR-CAP-CRM-REG-001-06` | `ATS-CRM-REG-001-05` |
| `BR-CAP-CRM-REG-001-07` | `ATS-CRM-REG-001-06` |
| `BR-CAP-CRM-REG-001-08` | `ATS-CRM-REG-001-07`, `ATS-CRM-REG-001-10` |
| `BR-CAP-CRM-REG-001-10` | `ATS-CRM-REG-001-08` |
| `BR-CAP-CRM-REG-001-12` | `ATS-CRM-REG-001-09` |

## Interactions With Related Capabilities

A shared catalogue survives import and retirement. The interaction scenario connects retire regions while preserving their references, restrict regional work to authorised users, import a catalogue of regions, share regions through record references and exports with this capability. Cross-workflow expectations are proposed where no executable binding is present.
