Skip to content

CAP-CRM-REG-004Build the geographic assignment policy

Markdown

CAP-CRM-REG-004

Build the geographic assignment policy

Markdown
  • DocumentDraft
  • Product intentProposed
  • ImplementationObserved

KindCapabilityProduct areaCRMModuleRegionsRevision2

Read atservices-crm a8d1364freact-console baf6dae3

The Formal Contract

The narrative above explains; the sections below are authoritative — the rules, scenarios and tests this document binds.

Outcomes
Rules connect geographic criteria to workspace regions.The complete policy can be saved in a single ordered replacement.Staff see validation issues before submitting changes.
Surfaces
consoleapi
Intent sources
services-crm:docs/migrations/crm-regions/README.md#2026-10-12 — Final acceptance (second pass), decision 2026-10-12: a country sent on a rule that is not a postal code rule is dropped silentlyservices-crm:docs/migrations/crm-regions/README.md#2026-10-15 — Final acceptance (console follow-ups) (Andrew approved 2026-10-15: two tabs, Test an Address dialog, drawers, a read-only Assignment Rules tab with its own editor screen and the banner)services-crm:docs/milestones/CRM-M3-crm-configuration.md#D-35services-crm:docs/migrations/crm-regions/README.md#2026-10-11 second pass (Andrew, 2026-10-11: rules are managed one at a time; an organization has a preferred address)

Controls

17 controls apply, from the corpus control catalogue.

TC-AZ-001 TC-AZ-002 TC-AZ-003 TC-AZ-004 TC-AZ-006 TC-DAT-001 TC-DAT-003 TC-LOG-001 TC-LOG-002 TC-LOG-003 TC-LOG-004 TC-LOG-005 TC-PI-001 TC-PI-003 TC-TEN-001 TC-TEN-002 TC-TEN-003

Permissions

KeyChecked atScope
crm.regions.updateapitenant
crm.regions.readapitenant

Business Rules

14 rules, 10 to be proved before approval. A rule's product intent is derived from its origin: 0 confirmed by a product decision, the rest inheriting this capability's proposed.

IdRuleKindEnforced atProvenance
01must prove
Proposed
An assignment rule uses postal code ranges, states, countries or a rest-of-the-world fallback.
no proof recorded yet
validationapi, databasetest
02must prove
Proposed
Postal rules require one to one thousand nonblank endpoint pairs, state and country rules require one to one thousand entries, and fallback rules carry no criteria list.
no proof recorded yet
validationapi, service, databaseobserved
03must prove
Proposed
Saving retains only the criteria associated with the rule kind and silently discards a country restriction on other than postal rules.
origin: services-crm:docs/migrations/crm-regions/README.md#2026-10-12 — Final acceptance (second pass), decision 2026-10-12: a country sent on a rule that is not a postal code rule is dropped silently
no proof recorded yet
policyservicetest
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
04must prove
Proposed
A postal rule’s optional country restriction accepts a two-letter ISO country code, stores it in capitals and rejects invalid codes.
no proof recorded yet
validationservice, databasetest
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
05
Proposed
Country-rule entries are trimmed and saved in capitals.
policyservicetest
services-crm:modules/regions/tests/integration/services/persistence/region-assignment-settings.integration.spec.js#a countries rule given its codes in lower case › stores the codes of a settings save trimmed and upper-cased
06must prove
Proposed
Every rule targets a region in its own workspace, and a nonexistent target causes a refusal identifying the region.
no proof recorded yet
validationservice, databasetest
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
07
Proposed
Rules can be disabled without deletion and carry an explanatory note of at most one thousand characters that does not affect matching.
origin: services-crm:docs/migrations/crm-regions/README.md#2026-10-11 second pass (Andrew, 2026-10-11: rules are managed one at a time; an organization has a preferred address)
policyapi, serviceobserved
08must prove
Proposed
The policy accepts at most one thousand rules and rejects creation or replacement that exceeds that limit.
no proof recorded yet
validationapi, serviceobserved
09must prove
Proposed
Settings replacement with a rules list atomically replaces the complete ordered policy; omitting that list preserves the current rules.
no proof recorded yet
policyservicetest
10must prove
Proposed
Saved rules have distinct identifiers and consecutive positions beginning at one, with no shared position.
no proof recorded yet
invariantservice, databasetest
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
11
Proposed
The console saves the staged settings and full ordered policy against the editor’s initial version, omitting identifiers for rules the service has not yet created.
policyconsoletest
react-console:components/regions/__tests__/assignment-draft.test.ts#what Save sends › is the settings at the version the editor opened with and every rule in its staged order
12must prove
Proposed
The editor flags absent or missing target regions, incomplete criteria and missing address choices before saving, but suppresses these checks while assignment is disabled.
no proof recorded yet
validationconsoletest
react-console:components/regions/__tests__/assignment-draft.test.ts#the issues a save would be refused for › names a rule without a region, and points at the rule
13
Proposed
The console warns about covered rules, inactive targets and missing or repeated fallback rules without treating those warnings as save refusals.
policyconsoletest
react-console:lib/configuration/regions-analysis.test.ts#a rule an earlier rule already covers › flags a postal range inside an earlier range for the same country
14must prove
Proposed
Whole-list replacement recreates retained rule identifiers at version one, allowing an older single-rule edit also based on version one to pass its version check.
no proof recorded yet
lifecycleserviceobserved
services-crm:modules/regions/services/persistence/region-assignment-settings.ts:saveRegionAssignmentSettings, insertRule, updateRegionAssignmentRule

Scenarios

IdGivenWhenThenProvenance
01Coverage distinguishes Boston, nearby states, Canada and all remaining addresses.An administrator saves postal, state, country and fallback rules in that sequence.Reads return four identified rules with consecutive positions and their appropriate criteria.test
02A state rule has no state entries.The administrator submits the policy.Validation identifies the missing entries and retains the previous policy.test

Edge Cases

IdGivenWhenThenProvenance
03A country entry is written in lower case.The client saves that rule.The stored entry is returned in capitals.test
services-crm:modules/regions/tests/integration/services/persistence/region-assignment-settings.integration.spec.js#a countries rule given its codes in lower case › stores the codes of a rule created on its own upper-cased

The Markdown files under specs/ in rhythmsoftware/rhythm-v2-docs are the canonical source of truth. This reader is a generated, read-only projection of them.