---
id: TST-CRM-REG-047
title: Local regional API lifecycle
kind: api-lifecycle
product_area: crm
module: regions
revision: 1
status: draft
source_sha:
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
repository: services-crm
files:
  - modules/regions/tests/e2e/regions.e2e.spec.js
implements:
  - ATS-CRM-REG-001-01
  - ATS-CRM-REG-001-02
  - ATS-CRM-REG-001-07
  - ATS-CRM-REG-002-01
  - ATS-CRM-REG-002-02
  - ATS-CRM-REG-003-01
  - ATS-CRM-REG-003-02
  - ATS-CRM-REG-004-02
  - ATS-CRM-REG-004-03
  - ATS-CRM-REG-004-04
  - ATS-CRM-REG-004-07
  - ATS-CRM-REG-005-01
  - ATS-CRM-REG-005-03
  - ATS-CRM-REG-005-04
  - ATS-CRM-REG-005-06
  - ATS-CRM-REG-005-07
  - ATS-CRM-REG-007-01
  - ATS-CRM-REG-007-02
  - ATS-CRM-REG-007-03
  - ATS-CRM-REG-007-04
  - ATS-CRM-REG-007-05
  - ATS-CRM-REG-008-01
  - ATS-CRM-REG-011-03
  - ATS-CRM-REG-011-05
  - ATS-CRM-REG-012-01
  - ATS-CRM-REG-012-06
  - ATS-CRM-REG-013-03
  - ATS-CRM-REG-013-06
environment: local
implementation_state: implemented
latest_result: not-run
latest_run_at: null
latest_run_ref: null
conformance: not-verified
estimated_minutes: 2
isolation: Suite-owned workspace and records in the prepared test database.
evidence:
  - 'services-crm:modules/regions/tests/e2e/regions.e2e.spec.js'
assertions:
  - scenario: ATS-CRM-REG-001-01
    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
  - scenario: ATS-CRM-REG-001-02
    source: 'services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#answers 400 for a body with no name'
  - scenario: ATS-CRM-REG-001-02
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#answers 400 naming the field for a name
      of nothing but spaces
  - scenario: ATS-CRM-REG-001-07
    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
  - scenario: ATS-CRM-REG-001-07
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#the regions › answers none of this
      tenant's regions to another tenant's list
  - scenario: ATS-CRM-REG-002-01
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#answers 409 to a delete of a region in
      use
  - scenario: ATS-CRM-REG-002-02
    source: 'services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#deletes a region nothing uses'
  - scenario: ATS-CRM-REG-002-02
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#leaves nothing to read after the delete:
      a later GET answers 404
  - scenario: ATS-CRM-REG-003-01
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#answers assignment off and no rules
      before the tenant saves any
  - scenario: ATS-CRM-REG-003-02
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#switches assignment on with an empty
      rule list, and reads back on with no rules
  - scenario: ATS-CRM-REG-004-02
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#answers 400 for a postal code rule with
      no ranges
  - scenario: ATS-CRM-REG-004-03
    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
  - scenario: ATS-CRM-REG-004-04
    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
  - scenario: ATS-CRM-REG-004-04
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#answers the created rule with its
      ranges, its country upper-cased and its note
  - scenario: ATS-CRM-REG-004-07
    source: >-
      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
  - scenario: ATS-CRM-REG-004-07
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#reads the replaced rules and their
      ranges back exactly as the save answered them
  - scenario: ATS-CRM-REG-005-01
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#appends a created rule at the end of the
      order
  - scenario: ATS-CRM-REG-005-01
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#lists both rules in the order they are
      tried
  - scenario: ATS-CRM-REG-005-03
    source: 'services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#deletes a rule'
  - scenario: ATS-CRM-REG-005-03
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#closes the gap the delete left, so the
      rule that remains is at the first position
  - scenario: ATS-CRM-REG-005-04
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#answers 400 for an order that does not
      name every rule of the tenant
  - scenario: ATS-CRM-REG-005-04
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#puts the rules in the order the body
      names, renumbering the positions
  - scenario: ATS-CRM-REG-005-06
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#the last enabled rule while assignment
      is on › disables it, leaving the tenant assignment on with nothing to match
  - scenario: ATS-CRM-REG-005-06
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#the last enabled rule while assignment
      is on › deletes it
  - scenario: ATS-CRM-REG-005-06
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#the last enabled rule while assignment
      is on › leaves assignment on, so the console’s switch stays usable with no rule
  - scenario: ATS-CRM-REG-005-07
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#the rules, one at a time › answers none
      of this tenant's rules to another tenant's list
  - scenario: ATS-CRM-REG-005-07
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#answers 404 for a rule the tenant does
      not have
  - scenario: ATS-CRM-REG-007-01
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#the preview › answers the region the
      address would be given and the rule that decides it
  - scenario: ATS-CRM-REG-007-01
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#the preview › says why, so the console
      can show it
  - scenario: ATS-CRM-REG-007-02
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#the preview › writes nothing: the tenant
      still has the rules it had
  - scenario: ATS-CRM-REG-007-03
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#the preview › answers 403 to a context
      carrying no regions permission at all
  - scenario: ATS-CRM-REG-007-04
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#the preview › answers 400 for a body
      with no address
  - scenario: ATS-CRM-REG-007-05
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#the preview › answers no region and no
      rule for an address no rule covers
  - scenario: ATS-CRM-REG-008-01
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#answers a contact posted through the
      contacts route with no region: the assignment is a reaction to the save
  - scenario: ATS-CRM-REG-008-01
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#gives that contact its region once the
      change event has been delivered
  - scenario: ATS-CRM-REG-011-03
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#answers the recalculation, completed
      within the request
  - scenario: ATS-CRM-REG-011-05
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#moves the contact to its region under
      the new rules
  - scenario: ATS-CRM-REG-012-01
    source: 'services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#lists the recalculation'
  - scenario: ATS-CRM-REG-012-01
    source: 'services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#reads the recalculation'
  - scenario: ATS-CRM-REG-012-06
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#answers 404 for a recalculation the
      tenant does not have
  - scenario: ATS-CRM-REG-013-03
    source: 'services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#answers 401 to an anonymous call'
  - scenario: ATS-CRM-REG-013-03
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#the regions › answers 403 when the
      signed context does not cover the path's tenant
  - scenario: ATS-CRM-REG-013-06
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#the rules, one at a time › answers 200
      to a list for a context carrying only the read permission
  - scenario: ATS-CRM-REG-013-06
    source: >-
      services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#the rules, one at a time › answers 403
      to a create for that same read-only context
binding_scope: >-
  Exact assertion anchors identify the contribution of this file. Scenario-level bindings may compose
  several files; registration does not assert that every file alone executes every scenario step.
---

# Local regional API lifecycle

## Verification Boundary

The suite invokes the local API harness and reads persisted results in the test database. It verifies regional route handling without a deployed gateway.

## What This Suite Proves

The linked source assertions contribute checks for identifier validation preserves the legacy grammar; blank names prevent creation; reads are workspace-specific; references block removal; unused regions can be removed permanently; unsaved configuration returns defaults; assignment can start with empty coverage; criteria lists require valid bounded content; rule normalization removes unrelated criteria; postal restrictions use valid country codes; omitted rules preserve the list; insertion supports append and earlier placement; deletion closes the position gap; reorder requires the complete distinct set; enabled assignment tolerates removal of its final rule; rule reads cannot cross workspaces; preview explains the winning rule; preview leaves policy unchanged; preview is read-authorized work; an address is required for preview; preview explains lack of coverage; placement is a reaction to committed creation; request processing and continuation share the run; recalculation applies changed coverage; history and individual reads expose progress; run reads cannot cross workspaces; authentication and workspace access are required; read permits listing but cannot create rules. A scenario spanning several files relies on those assertions together; this file supplies only its named checks.

## What It Does Not Prove

The register establishes neither a current passing run nor verified conformance. Unbound scenarios, broader feature chains and the delegated infrastructure beyond this execution boundary remain unproved.

## Real Dependencies and Test Doubles

PostgreSQL and the regional persistence under assertion are real. The suite supplies test execution contexts and fixtures; a local API harness replaces deployed transport where applicable.

## Must Not Be Doubled

Regional matching, regional persistence and the stored values under assertion must remain real. A substitute answer for these dependencies cannot qualify the linked regional outcomes.
