---
id: ATS-CRM-REG-004
scope: CAP-CRM-REG-004
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-004-01
    title: Unknown rule kinds are invalid
    level: api
    proves:
      - BR-CAP-CRM-REG-004-01
    preconditions: A settings record exists.
    steps: Attempt to store an unsupported rule kind.
    expected: The rule-kind constraint rejects it.
    negative: true
    data_needs: No extra fixture records are required.
    bound_to:
      - TST-CRM-REG-048
    provenance: test
    source: >-
      services-crm:modules/regions/tests/integration/db/region-assignment-settings.table.integration.spec.js#rule
      constraints › refuses a rule type outside the legacy list
    category: validation
    test_assertions:
      - >-
        services-crm:modules/regions/tests/integration/db/region-assignment-settings.table.integration.spec.js#rule
        constraints › refuses a rule type outside the legacy list
  - id: ATS-CRM-REG-004-02
    title: Criteria lists require valid bounded content
    level: api
    proves:
      - BR-CAP-CRM-REG-004-02
    preconditions: The workspace contains a target region.
    steps: >-
      Submit missing postal ranges, empty states or countries, too many states and a range with a blank
      endpoint.
    expected: Each invalid list is refused and no replacement policy is committed.
    negative: true
    data_needs: Criteria lists constructed at the required boundary sizes.
    bound_to:
      - TST-CRM-REG-047
      - TST-CRM-REG-050
      - TST-CRM-REG-048
    provenance: test
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#answers 400 for a postal code rule with
      no ranges
    category: boundary
    test_assertions:
      - >-
        services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#answers 400 for a postal code rule
        with no ranges
      - >-
        services-crm:modules/regions/tests/integration/services/persistence/region-assignment-settings.integration.spec.js#the
        capability › refuses a state rule with no states
      - >-
        services-crm:modules/regions/tests/integration/db/region-assignment-settings.table.integration.spec.js#rule
        constraints › refuses a state rule with more than 1000 states
      - >-
        services-crm:modules/regions/tests/integration/db/region-assignment-settings.table.integration.spec.js#rule
        constraints › refuses a country rule with no countries
      - >-
        services-crm:modules/regions/tests/integration/db/region-assignment-settings.table.integration.spec.js#postal
        code range constraints › refuses a blank start or end
      - >-
        services-crm:modules/regions/tests/integration/db/region-assignment-settings.table.integration.spec.js#postal
        code range constraints › refuses a range position beyond 1000
  - id: ATS-CRM-REG-004-03
    title: Rule normalization removes unrelated criteria
    level: api
    proves:
      - BR-CAP-CRM-REG-004-03
    preconditions: A target region exists.
    steps: Create a state rule also carrying a country restriction and postal ranges.
    expected: Only the state criteria remain on the saved rule.
    negative: false
    data_needs: A single regional definition.
    bound_to:
      - TST-CRM-REG-047
      - TST-CRM-REG-048
    provenance: test
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#drops a country given on a rule that is
      not a postal code rule, as it drops the other types’ lists
    category: rule
    test_assertions:
      - >-
        services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#drops a country given on a rule that
        is not a postal code rule, as it drops the other types’ lists
      - >-
        services-crm:modules/regions/tests/integration/db/region-assignment-settings.table.integration.spec.js#rule
        constraints › refuses states on a rule that is not a state rule
  - id: ATS-CRM-REG-004-04
    title: Postal restrictions use valid country codes
    level: api
    proves:
      - BR-CAP-CRM-REG-004-04
    preconditions: A target region exists.
    steps: Create postal rules with a lowercase two-letter code and an invalid three-letter code.
    expected: The valid code is stored in capitals and the invalid code is refused.
    negative: true
    data_needs: A single regional definition.
    bound_to:
      - TST-CRM-REG-047
      - TST-CRM-REG-048
    provenance: test
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#answers 400 for a country that is not an
      ISO 3166-1 alpha-2 code
    category: validation
    test_assertions:
      - >-
        services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#answers 400 for a country that is not
        an ISO 3166-1 alpha-2 code
      - >-
        services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#answers the created rule with its
        ranges, its country upper-cased and its note
      - >-
        services-crm:modules/regions/tests/integration/db/region-assignment-settings.table.integration.spec.js#rule
        constraints › refuses a country that is not two upper-case letters, because it is an ISO 3166-1
        alpha-2 code
  - id: ATS-CRM-REG-004-05
    title: Foreign and absent rule targets are rejected
    level: api
    proves:
      - BR-CAP-CRM-REG-004-06
    preconditions: Two workspaces contain separate regions.
    steps: Save rules targeting a nonexistent region and the other workspace’s region.
    expected: Both requests identify the missing local target and preserve the saved policy.
    negative: true
    data_needs: Two distinct customer workspaces.
    bound_to:
      - TST-CRM-REG-050
      - TST-CRM-REG-058
      - TST-CRM-REG-048
    provenance: test
    source: >-
      services-crm:modules/regions/tests/integration/services/persistence/region-assignment-settings.integration.spec.js#the
      capability › refuses a rule naming a region the tenant does not have, naming it
    category: boundary
    test_assertions:
      - >-
        services-crm:modules/regions/tests/integration/services/persistence/region-assignment-settings.integration.spec.js#the
        capability › refuses a rule naming a region the tenant does not have, naming it
      - >-
        services-crm:modules/regions/tests/integration/services/region-assignment/region-assignment.integration.spec.js#refusals
        › refuses settings whose rule names a region the tenant does not have
      - >-
        services-crm:modules/regions/tests/integration/db/region-assignment-settings.table.integration.spec.js#rule
        constraints › refuses a rule naming a region of another tenant
  - id: ATS-CRM-REG-004-06
    title: The policy cannot exceed its rule limit
    level: api
    proves:
      - BR-CAP-CRM-REG-004-08
    preconditions: The workspace already holds one thousand rules.
    steps: Add one rule and submit a whole list containing one thousand and one rules.
    expected: Both requests are rejected while the existing policy remains intact.
    negative: true
    data_needs: A policy populated to its one-thousand-entry limit.
    bound_to: []
    provenance: proposed
    source: >-
      services-crm:modules/regions/aws/api/regions.schemas.ts:regionAssignmentSettingsSchema;
      services-crm:modules/regions/services/persistence/region-assignment-settings.ts:createRegionAssignmentRule
    category: boundary
  - id: ATS-CRM-REG-004-07
    title: Omitted rules preserve the list
    level: api
    proves:
      - BR-CAP-CRM-REG-004-09
    preconditions: The settings hold three rules.
    steps: 'Replace with two different rules, then save settings without a rules property.'
    expected: The first replacement establishes the new ordered pair and the second retains it.
    negative: false
    data_needs: A three-entry assignment policy.
    bound_to:
      - TST-CRM-REG-050
      - TST-CRM-REG-047
    provenance: test
    source: >-
      services-crm:modules/regions/tests/integration/services/persistence/region-assignment-settings.integration.spec.js#the
      capability › replaces the rules whole on the next save
    category: rule
    test_assertions:
      - >-
        services-crm:modules/regions/tests/integration/services/persistence/region-assignment-settings.integration.spec.js#the
        capability › replaces the rules whole on the next save
      - >-
        services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#leaves the rules alone when the body
        carries none, so switching the settings on keeps them
      - >-
        services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#reads the replaced rules and their
        ranges back exactly as the save answered them
  - id: ATS-CRM-REG-004-08
    title: Rule identity and position remain valid
    level: api
    proves:
      - BR-CAP-CRM-REG-004-10
    preconditions: A target region exists.
    steps: 'Save three rules, then attempt duplicate positions and a zero position directly.'
    expected: The saved rules have identifiers and positions one through three; invalid positions are rejected.
    negative: true
    data_needs: A single regional definition.
    bound_to:
      - TST-CRM-REG-050
      - TST-CRM-REG-048
    provenance: test
    source: >-
      services-crm:modules/regions/tests/integration/services/persistence/region-assignment-settings.integration.spec.js#the
      capability › gives every rule it saved an id of its own, because a rule is a record a console can
      now manage one at a time
    category: invariant
    test_assertions:
      - >-
        services-crm:modules/regions/tests/integration/services/persistence/region-assignment-settings.integration.spec.js#the
        capability › gives every rule it saved an id of its own, because a rule is a record a console can
        now manage one at a time
      - >-
        services-crm:modules/regions/tests/integration/db/region-assignment-settings.table.integration.spec.js#rule
        constraints › refuses two rules at one position
      - >-
        services-crm:modules/regions/tests/integration/db/region-assignment-settings.table.integration.spec.js#rule
        constraints › refuses a position below 1
  - id: ATS-CRM-REG-004-09
    title: Whole-policy replacement changes individual reads and preview
    category: interaction
    level: api
    proves:
      - BR-CAP-CRM-REG-004-09
      - BR-CAP-CRM-REG-005-03
      - BR-CAP-CRM-REG-006-01
      - BR-CAP-CRM-REG-007-01
    preconditions: A policy has two distinguishable overlapping rules and saved assignment choices.
    steps: >-
      Save both rules in the opposite order, read each through individual-rule operations and preview an
      overlapping address.
    expected: Individual reads reflect the saved order and preview identifies the first matching geographic rule.
    negative: false
    data_needs: A policy has two distinguishable overlapping rules and saved assignment choices.
    bound_to: []
    provenance: proposed
    source: ADR-CRM-REG-006
    exercises:
      - CAP-CRM-REG-003
      - CAP-CRM-REG-004
      - CAP-CRM-REG-005
      - CAP-CRM-REG-006
      - CAP-CRM-REG-007
  - id: ATS-CRM-REG-004-10
    title: Whole-list save admits an old version-one individual edit
    category: concurrency
    level: api
    proves:
      - BR-CAP-CRM-REG-004-14
    preconditions: A saved rule is read at its initial version and a full-policy draft retains its identifier.
    steps: >-
      Change that rule through whole-list replacement, then send the earlier individual replacement at
      version one.
    expected: >-
      The recreated rule starts at version one and the older individual edit passes its version check,
      exposing the documented concurrency weakness.
    negative: true
    data_needs: A saved rule is read at its initial version and a full-policy draft retains its identifier.
    bound_to: []
    provenance: proposed
    source: >-
      services-crm:modules/regions/services/persistence/region-assignment-settings.ts:saveRegionAssignmentSettings,
      insertRule, updateRegionAssignmentRule
  - id: ATS-CRM-REG-004-11
    title: Enabled draft issues prevent submission at the relevant controls
    category: validation
    level: api
    proves:
      - BR-CAP-CRM-REG-004-12
    preconditions: >-
      A policy editor stages an enabled rule with no target and incomplete criteria plus a typed source
      with no address type.
    steps: >-
      Attempt Save and reveal each reported issue, then disable automatic assignment and review draft
      issues.
    expected: >-
      The enabled draft identifies the affected controls and does not submit; disabling suppresses those
      editor checks without promising backend acceptance.
    negative: false
    data_needs: >-
      A policy editor stages an enabled rule with no target and incomplete criteria plus a typed source
      with no address type.
    bound_to: []
    provenance: proposed
    source: 'react-console:components/regions/__tests__/assignment-draft.test.ts'
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/integration/db/region-assignment-settings.table.integration.spec.js
  - 'services-crm:modules/regions/tests/e2e/regions.e2e.spec.js'
  - >-
    services-crm:modules/regions/tests/integration/services/persistence/region-assignment-settings.integration.spec.js
  - >-
    services-crm:modules/regions/tests/integration/services/region-assignment/region-assignment.integration.spec.js
  - 'services-crm:modules/regions/aws/api/regions.schemas.ts'
  - 'services-crm:modules/regions/services/persistence/region-assignment-settings.ts'
coverage:
  rule: covered
  transition: 'gap: FND-CRM-REG-049'
  validation: covered
  permission: 'gap: FND-CRM-REG-049'
  edge: 'gap: FND-CRM-REG-049'
  failure: 'gap: FND-CRM-REG-049'
  boundary: covered
  concurrency: covered
  invariant: covered
  interaction: covered
---

# Build the geographic assignment policy: 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-004-01` | `ATS-CRM-REG-004-01` |
| `BR-CAP-CRM-REG-004-02` | `ATS-CRM-REG-004-02` |
| `BR-CAP-CRM-REG-004-03` | `ATS-CRM-REG-004-03` |
| `BR-CAP-CRM-REG-004-04` | `ATS-CRM-REG-004-04` |
| `BR-CAP-CRM-REG-004-06` | `ATS-CRM-REG-004-05` |
| `BR-CAP-CRM-REG-004-08` | `ATS-CRM-REG-004-06` |
| `BR-CAP-CRM-REG-004-09` | `ATS-CRM-REG-004-07`, `ATS-CRM-REG-004-09` |
| `BR-CAP-CRM-REG-004-10` | `ATS-CRM-REG-004-08` |
| `BR-CAP-CRM-REG-004-12` | `ATS-CRM-REG-004-11` |
| `BR-CAP-CRM-REG-004-14` | `ATS-CRM-REG-004-10` |

## Interactions With Related Capabilities

Whole-policy replacement changes individual reads and preview. The interaction scenario connects configure automatic placement and its address sources, maintain individual rules alongside the shared policy, determine an address’s geographic region, check an address against the saved policy with this capability. Cross-workflow expectations are proposed where no executable binding is present.
