Skip to content

CAP-CRM-REG-005Maintain individual rules alongside the shared policy

Markdown

CAP-CRM-REG-005

Maintain individual rules alongside the shared 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
Successful writes retain consecutive rule positions.Version checks detect stale edits except where whole-list replacement resets individual versions.
Surfaces
api
Intent sources
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)services-crm:docs/migrations/crm-regions/README.md#2026-10-12 — Final acceptance (second pass), Since: 2026-10-14, Andrew: assignment may be on with no rulesservices-crm:docs/milestones/CRM-M1-contacts-and-organizations.md#D-05

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.readapitenant
crm.regions.updateapitenant

Business Rules

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

IdRuleKindEnforced atProvenance
01must prove
Proposed
Creating a rule appends it unless an earlier insertion position is requested, in which case following rules move down one position.
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)
no proof recorded yet
policyserviceobserved
02must prove
Confirmed
Rule replacement and patching require the version read and reject missing or stale versions.
no proof recorded yet
validationapi, servicetest
services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#the rules, one at a time › answers 409 for a replace from a stale read
03
Proposed
Replacement preserves the rule identifier and current position; changing order uses the separate reorder operation.
invariantserviceobserved
04must prove
Proposed
Deleting a rule preserves the remaining sequence and closes the gap with positions starting at one.
no proof recorded yet
invariantservicetest
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
05must prove
Proposed
Reordering requires every workspace rule exactly once and rejects omissions, duplicates and unknown identifiers with an explanation.
no proof recorded yet
validationservicetest
services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#answers 400 for an order that does not name every rule of the tenant
06must prove
Proposed
Each individual-rule write increments the settings version, causing a whole-list save based on the earlier version to conflict rather than discard that write.
no proof recorded yet
invariantservicetest
services-crm:modules/regions/tests/integration/services/persistence/region-assignment-settings.integration.spec.js#rules written one at a time, beside a settings save › a whole-list save read before a rule was created › is refused as stale, so the new rule is not dropped
07
Proposed
Individual-rule writes and settings replacements serialize on the workspace settings row so their rule updates cannot interleave.
invariantservice, databaseobserved
08
Proposed
Creating a workspace’s first rule also creates default settings with automatic assignment disabled.
policyserviceobserved
09must prove
Proposed
The final enabled rule can be disabled or removed while automatic assignment remains on, leaving no matching rule.
origin: services-crm:docs/migrations/crm-regions/README.md#2026-10-12 — Final acceptance (second pass), Since: 2026-10-14, Andrew: assignment may be on with no rules
no proof recorded yet
policyservicetest
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
10
Proposed
Authorized region readers receive rules in evaluation order, with the default list returning the bounded policy of up to one thousand rules.
policyapitest
services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#lists both rules in the order they are tried
11must prove
Proposed
Rule reads and writes are confined to their workspace, and an unknown rule returns not found.
no proof recorded yet
invariantapi, servicetest
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

Scenarios

IdGivenWhenThenProvenance
01The policy already contains three rules.An integration adds a rule without an insertion position.The new rule follows the existing three at position four.test
services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#appends a created rule at the end of the order
02A policy contains two rules.A client submits an order containing only one.The missing rule is identified and the order remains intact.test
services-crm:modules/regions/tests/e2e/regions.e2e.spec.js#answers 400 for an order that does not name every rule of the tenant

Edge Cases

IdGivenWhenThenProvenance
03An editor holds an earlier whole-list draft.An integration adds a rule before that draft is saved.The settings-version conflict preserves the integration’s addition.test
services-crm:modules/regions/tests/integration/services/persistence/region-assignment-settings.integration.spec.js#rules written one at a time, beside a settings save › a whole-list save read before a rule was created › leaves the rule created beside it in the list

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.