---
id: SAT-CRM-ENT-004
screen: SCR-CRM-ENT-004
product_area: crm
module: entities
revision: 1
status: proposed
source_sha:
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
coverage:
  fields: covered
  actions: covered
  states: covered
  navigation: covered
  permissions: covered
  refusals: covered
  components: covered
  rules: covered
  accessibility: 'gap: FND-CRM-ENT-087'
scenarios:
  - id: SAT-CRM-ENT-004-01
    title: reviewed changes save against the original version without altering untouched values
    category: action
    level: browser
    proves: [AC-SCR-CRM-ENT-004-01, BR-CAP-CRM-ENT-004-01, BR-CAP-CRM-ENT-004-11]
    preconditions: The coordinator can update an existing contact with a job title and one postal address.
    steps: Open Edit Contact and alter only Job Title. Inspect the one entry in Review Changes, then confirm Save Changes.
    expected: The one patch includes the title change and original version. Contact 360 opens with the updated title and a success toast; the saved address retains its prior value.
    negative: false
    data_needs: An acceptance-workspace contact with the required initial values.
    bound_to: []
    provenance: proposed
    source: 'react-console:acceptance/crm/playwright/journeys/contacts (ATS-CRM-ENT-004-11 as implemented by the contact records acceptance suite)'
  - id: SAT-CRM-ENT-004-02
    title: a stale save leaves recovery to the person through Reload or Keep Editing
    category: state
    level: browser
    proves: [AC-SCR-CRM-ENT-004-02, BR-CAP-CRM-ENT-004-01]
    preconditions: The editor holds a contact version that a second session subsequently changes.
    steps: Edit a field and submit the reviewed changes against the earlier version.
    expected: The save returns a conflict in the action bar. Keep Editing retains the draft and dismisses the alert; Reload reads the latest record and reports the discarded draft.
    negative: true
    data_needs: A contact that can be changed through a second session or an API request.
    bound_to: []
    provenance: proposed
    source: 'react-console:acceptance/crm/playwright/journeys/contacts (ATS-CRM-ENT-004-10 and -11 as implemented by the contact records acceptance suite)'
  - id: SAT-CRM-ENT-004-03
    title: field issues support correction before a valid save can proceed
    category: state
    level: browser
    proves: [AC-SCR-CRM-ENT-004-03, AC-SCR-CRM-ENT-004-06, BR-CAP-CRM-ENT-001-04]
    preconditions: An existing contact is loaded in Edit Contact.
    steps: Remove the first and last names, inspect the issue list and follow the name issue. Supply a last name, then inspect Review Changes.
    expected: The field and summary identify the name issue, and following it focuses the field. The design criterion requires Save to stay unavailable until correction, although the built button currently permits an attempt that focuses validation. Review Changes shows the name normalization for submission.
    negative: true
    data_needs: An existing contact available to the run.
    bound_to: []
    provenance: proposed
    source: 'react-console:acceptance/crm/playwright/journeys/contacts (ATS-CRM-ENT-001-04 and -02 as implemented by the contact records acceptance suite)'
  - id: SAT-CRM-ENT-004-04
    title: Cancel and supported link navigation confirm abandonment of a dirty draft
    category: navigation
    level: browser
    proves: [AC-SCR-CRM-ENT-004-04]
    preconditions: An existing contact is loaded in Edit Contact.
    steps: Cancel an unchanged edit. Reopen it, alter a field and Cancel again; keep editing in the confirmation. Follow a sidebar link and confirm Discard Changes.
    expected: An unchanged Cancel opens Contact 360 immediately. A dirty Cancel opens the confirmation; Keep Editing stays in the form. The same dialog holds the sidebar navigation until Discard Changes continues it.
    negative: false
    data_needs: An existing contact available to the run.
    bound_to: []
    provenance: proposed
    source: 'react-console:components/contact-editor/unsaved-changes.tsx'
  - id: SAT-CRM-ENT-004-05
    title: missing update authority prevents editor entry and a service write
    category: permission
    level: browser
    proves: [AC-SCR-CRM-ENT-004-05]
    preconditions: A contact exists and the signed-in person can read contacts but cannot update them.
    steps: Follow a direct Edit Contact address and attempt a contact patch using the same person's token.
    expected: The page presents an access refusal. The service refuses the unauthorized patch and preserves the saved contact.
    negative: true
    data_needs: An acceptance-workspace identity granted contact read access alone.
    bound_to: []
    provenance: proposed
    source: 'react-console:app/(console)/console/[tenantId]/crm/contacts/[id]/edit/page.tsx; services-crm:modules/entities/aws/api/contacts.routes.ts'
  - id: SAT-CRM-ENT-004-06
    title: the address collection checks the design requirement to release a link before removal
    category: component
    level: browser
    proves: [AC-SCR-CRM-ENT-004-07, BR-CAP-CRM-ENT-006-03, BR-CAP-CRM-ENT-006-04]
    preconditions: A contact affiliation supplies a work address from an organization's headquarters address.
    steps: Inspect the linked work card on Overview and attempt Remove. Make an independent copy using its source actions, then remove the copied row.
    expected: The design expects the source marker and a disabled Remove with an explanation, followed by an editable independent copy that can be removed. The current row source controls leave Remove enabled, so this proposed check exposes the recorded discrepancy.
    negative: true
    data_needs: A contact affiliation and an organization headquarters address that supplies the link.
    bound_to: []
    provenance: proposed
    source: 'react-console:components/contact-editor/collections/address-list-editor.tsx; e2e/mock/affiliations.mock.spec.ts'
  - id: SAT-CRM-ENT-004-07
    title: changing the primary relationship asks whether the previous one ends
    category: action
    level: browser
    proves: [AC-SCR-CRM-ENT-004-08, BR-CAP-CRM-ENT-009-09]
    preconditions: An existing contact has a current primary organization relationship.
    steps: Add a relationship to another organization on Affiliations, choose it as primary and answer the question about leaving the previous organization.
    expected: The leaving question appears before applying the choice. Yes ends the prior relationship today and moves the primary marker; No retains both current relationships with the new one primary.
    negative: false
    data_needs: A contact with a primary relationship and another organization available for selection.
    bound_to: []
    provenance: proposed
    source: 'react-console:components/contact-editor/contact-editor.tsx; components/affiliations/affiliation-editor.tsx'
  - id: SAT-CRM-ENT-004-08
    title: loading a contact shows the form while a missing contact shows recovery navigation
    category: state
    level: browser
    proves: [AC-SCR-CRM-ENT-004-05]
    preconditions: The run has an existing contact and a distinct address identifying no contact.
    steps: Visit Edit Contact for the existing record, then visit the address for the missing record.
    expected: The loaded record presents its identity, form tabs and action bar with No unsaved changes. The missing record presents Contact Not Found and Back to Contacts.
    negative: true
    data_needs: An existing contact available to the run.
    bound_to: []
    provenance: proposed
    source: 'react-console:components/contact-editor/contact-editor.tsx'
evidence:
  - 'react-console at baf6dae3: acceptance/crm/playwright/journeys/contacts/**; e2e/dev/contact-edit.dev.spec.ts; e2e/mock/affiliations.mock.spec.ts; components/contact-editor/**'
---

# Edit Contact: Screen Acceptance

## What the Suite Proves

These scenarios describe browser checks for a coordinator correcting a contact: review and submission, conflict recovery, validation, protected navigation, permission refusal, source-controlled addresses and primary relationships. Their proof references connect them to the screen criteria and capability rules. Source inspection finds overlapping assertions in the contact records suite, but does not establish full execution coverage of the three previously bound scenarios. All eight scenarios therefore remain proposed here.

## Coverage

The first scenario addresses the save criterion; the second addresses conflict recovery. The third covers validation and name handling together, including a disabled-Save expectation that differs from the built button. The fourth addresses Cancel and guarded navigation.

The fifth covers the update permission at editor entry and the API boundary, while the eighth adds loaded and missing-contact states. The sixth checks the Address Editor and linked-removal criterion, which the current implementation does not satisfy on its row source path. The seventh checks the primary-affiliation question. Accessibility has no scenario. The protected coverage map records scenario presence; it is not a report of passing runs or complete executable bindings.

## What It Does Not Prove

These proposed browser checks do not replace the capability test specifications' service-level proof, the Contact Records feature suite's complete business process, or the Address Editor's unit criteria. They do not establish accessibility conformance or deployment qualification. The contact journeys provide useful partial evidence, but their existing assertions alone cannot certify every step and expected result written in this screen specification.
