Test Scenarios
23 scenarios proving CAP-CRM-ENT-004; 11 bound to an existing test.
01 Writes need the version read; stale writes are conflicts that name the changeconcurrencyapinegativetest
- Proves
BR-CAP-CRM-ENT-004-01 INV-DOM-CRM-ENT-033-01 - Preconditions
- Prepare a contact at version n.
- Steps
- PUT without sys_version; PATCH without a test; two patches at n; a PUT at n after a colleague saved.
- Expected
- 400 naming sys_version twice; the second patch 409 with the first value preserved; 409 record_changed naming the colleague.
- Data
- No additional fixtures.
- Bound to
- Source
- services-crm:modules/entities/tests/e2e/contacts.e2e.spec.js#answers 400 naming sys_version to a patch that tests no version
03 a patch changes what it names and null clearsruleapitest
- Proves
BR-CAP-CRM-ENT-004-03 - Preconditions
- Prepare a contact with a job title and two phones.
- Steps
- Patch replace one field, edit one element, add one, remove one, then remove a field.
- Expected
- Each change applied, others untouched, version advanced.
- Data
- No additional fixtures.
- Bound to
- Source
- services-crm:modules/entities/tests/e2e/contacts.e2e.spec.js#sets the field the patch replaced and bumps the version
05 Elements keep their ids; foreign or repeated ids are rejected; types can swapinvariantapinegativetest
- Proves
BR-CAP-CRM-ENT-004-05 - Preconditions
- Prepare a contact with home and work addresses.
- Steps
- Replace with home edited and work omitted; with an element id of another contact; with one id twice; swap two types.
- Expected
- Home preserved under its id at version 2, work removed; 400 naming the element; 400; swap accepted.
- Data
- Use two contacts.
- Bound to
- Source
- services-crm:modules/entities/tests/integration/services/persistence/contacts.integration.spec.js#moves the second address into the type the first left, and the preferred flag with it
09 Strings are trimmed and blanks are nothingrulebrowsertest
- Proves
BR-CAP-CRM-ENT-004-09 - Preconditions
- No additional setup is required.
- Steps
- Send a blank e-mail element, a padded name, an empty-string name.
- Expected
- Element dropped; name trimmed; required name rejected.
- Data
- No additional fixtures.
- Bound to
- Source
- services-crm:modules/entities/tests/unit/api/contact-api-mapper.spec.js#drops a blank e-mail element rather than refusing the null the string standard made of it
10 a system change is a conflict naming the systeminteractionbrowsernegativetest
- Proves
BR-CAP-CRM-ENT-004-10 - Preconditions
- Prepare a contact read by an editor; its spouse then deleted.
- Steps
- The editor saves at the version read.
- Expected
- 409 naming the system.
- Data
- No additional fixtures.
- Bound to
- Source
- services-crm:modules/entities/tests/e2e/contacts.e2e.spec.js#answers 409 naming the system, not a colleague, when the system cleared the spouse link while the contact was edited (M1-D6)
11 the editor patches only what changed and handles conflicts safelyconcurrencybrowsernegativetest
- Proves
BR-CAP-CRM-ENT-004-11 - Preconditions
- Prepare two staff members on one contact.
- Steps
- Edit several fields through Review Changes; then save after a colleague; press Keep Editing.
- Expected
- One patch of the changed keys, one version bump, one revision; the conflict notice; no silent version advance.
- Data
- Use two personas.
- Bound to
- Source
- react-console:acceptance/crm/playwright/journeys/contacts/CRM-ACC-0009.spec.ts#CRM-ACC-0009
13 A whole-record save must carry every replaceable propertyruleapinegativeproposed
- Proves
BR-CAP-CRM-ENT-004-13 - Preconditions
- A contact exists with a job title and two addresses; the caller holds crm.contacts.update.
- Steps
- Read the contact; send it back unchanged with PUT; then send a PUT that omits job_title; then send a PUT with job_title null.
- Expected
- The unchanged save succeeds without changing the version; the omitting save is refused with 400 naming job_title and writes nothing; the null save clears the job title and keeps both addresses.
- Data
- One contact with a job title and two typed addresses in a disposable workspace.
- Source
- OQ-CRM-ENT-001 decided 2026-10-22: A; services-crm:docs/entities-api.md#Not yet under the complete-payload rule
21 Change person standing and preserve an unavailable email reservationtransitionapinegativeproposed
- Proves
BR-CAP-CRM-ENT-001-10 BR-CAP-CRM-ENT-005-02 BR-CAP-CRM-ENT-004-01 - Preconditions
- A person is active with a primary email; another run-owned person can claim that email after its reservation is released.
- Steps
- Save the first person inactive, then deceased; let the other person claim its email and attempt reactivation. Release the competing reservation and reactivate, then mark duplicate.
- Expected
- The stored standing follows each accepted save. The conflicting reactivation preserves deceased status; reactivation succeeds after release and duplicate status remains supported.
- Data
- Run-owned records and configuration in an isolated workspace.
- Source
- services-crm:modules/entities/tests/integration/db/contact-email-addresses.table.integration.spec.js#refuses to make an inactive contact active while another contact holds its primary address
23 Exercise every declared authority independentlypermissionapinegativeproposed
- Proves
BR-CAP-CRM-ENT-003-07 BR-CAP-CRM-ENT-003-09 - Preconditions
- An eligible record and configuration fixture exist for each operation; the caller can reach only the run’s workspace.
- Steps
- For each declared permission, execute its matching operation with that permission, then without it while retaining the other required grants. Read affected records after every refused mutation.
- Expected
- The authorized case reaches the operation; the missing-grant case is refused and preserves saved data. Record access alone does not authorize the other declared actions.
- Data
- Run-owned records and configuration in an isolated workspace.
- Source
- services-crm:aws/crm.service.ts:ApplicationPermissions; services-crm:modules/entities/aws/api/entities.routes.ts