Skip to content

CAP-CRM-ENT-008Keep customer-defined information with records

Markdown

CAP-CRM-ENT-008

Keep customer-defined information with records

Markdown
  • DocumentApproved
  • Product intentConfirmed
  • ImplementationObserved

KindCapabilityProduct areaCRMModuleEntitiesRevision1Approved byAndrewApproved at2026-10-22

Read atservices-crm 7ea48a41react-console da630758

The Formal Contract

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

Outcomes
Every custom value is stored in the type its field defines, or the save is rejected at that key.A write changes only the keys it names.
Surfaces
consoleapi
Intent sources
services-crm:docs/milestones/CRM-M1-contacts-and-organizations.md#D-04services-crm:docs/milestones/CRM-M1-contacts-and-organizations.plan.md#2. Scopeservices-crm:docs/milestones/CRM-M2-affiliations-roles-compliance.plan.md#A12

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-002 TC-DAT-003 TC-LOG-004 TC-LOG-005 TC-PI-001 TC-PI-003 TC-PRV-001 TC-PRV-002 TC-TEN-001 TC-TEN-002 TC-TEN-003

Repositories Read

RepositoryPaths
undefined:modules/entities/
undefined:docs/milestones/CRM-M1-contacts-and-organizations.md
undefined:modules/entities/tests/e2e/contact-roles.e2e.spec.js
undefined:modules/entities/tests/e2e/contacts-custom-fields.e2e.spec.js
undefined:app/(console)/console/[tenantId]/crm/contacts/
undefined:acceptance/crm/playwright/journeys/contacts/CRM-ACC-0027.spec.ts
undefined:acceptance/crm/playwright/journeys/contacts/CRM-ACC-0063.spec.ts

Where It Lives

Permissions

KeyChecked atScope
crm.contacts.updateapitenant
crm.organizations.updateapitenant
crm.contacts.readapitenant
crm.organizations.readapitenant

Business Rules

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

IdRuleKindEnforced atProvenance
01must prove
Confirmed
Custom field writes merge only named keys, preserve omitted or empty maps, set supplied values and clear null or blank values, but reject nulling or removing the entire map.
policyapi, servicetest
services-crm:modules/entities/tests/e2e/contacts-custom-fields.e2e.spec.js#sets the key it sends, clears the key sent null and the selection sent empty, and leaves the others
02must prove
Confirmed
Writable custom field keys must identify active definitions for the tenant and record kind; unknown, foreign, mismatched or archived definitions are rejected at the key’s path.
validationservicetest
03must prove
Confirmed
Custom values are converted to their declared types or rejected, including exact integer and decimal conversion, explicit true/false interpretation, text lengths, live list options, offset-qualified date-times and tenant-owned references.
validationservicetest
04must prove
Confirmed
API-required custom fields need values on creation and cannot be cleared, while an older record lacking a newly required value can still be saved.
validationservicetest
services-crm:modules/entities/tests/e2e/contacts-custom-fields.e2e.spec.js#saves a replace of a contact created before the field was required, leaving the field out
05
Confirmed
Reads return readable custom values in one map using their JSON forms and null for empty values; top-level custom field properties are neither returned nor accepted on writes.
policyapi, servicetest
services-crm:modules/entities/tests/e2e/contacts-custom-fields.e2e.spec.js#puts no custom field at the top level of the record
06must prove
Confirmed
Contact roles, affiliation types and affiliations do not support custom values and reject custom_fields as an unknown property.
validationapitest
services-crm:modules/entities/tests/e2e/contact-roles.e2e.spec.js#refuses a create that carries custom_fields, as an unknown property
07
Confirmed
Rich-text custom values use a sanitized basic editor and safe rendering in forms, Explorer and record views.
policyconsoledocumented

Scenarios

IdGivenWhenThenProvenance
01A tenant with member_since__c (date) and dues__c (amount, 2 places).A staff member sets both from the Custom Fields tab and the API retrieves them.Dues retrieves "12.50" and member_since the date entered.test

Edge Cases

IdGivenWhenThenProvenance
02A custom field archived while it holds values.Records are read and written.Its values vanish from retrieves, writes to it are rejected, and restoring the field brings them back.test

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.