01must proveProposed | An activity links between one and 200 distinct workspace records, and each link identifies either a contact or an organization. ✓ A meeting involving two contacts and their organization saves as one activity.✗ A single link identifying a contact and an organization fails validation. no proof recorded yet | validation | api, service, database | test |
02must proveConfirmed | Only one link can be primary; if none is selected, Rhythm makes the first link primary. no proof recorded yet | policy | service, database | test |
03must proveProposed | Creating an activity requires an active activity type from the same workspace. no proof recorded yet | validation | service | test |
04must proveProposed | Field modes control hidden and required details, with required duration and outcome checked only on completion and hidden attendees still permitted as links. no proof recorded yet | validation | console, service | observed |
05must proveProposed | An activity type that requires attendees needs a linked contact other than the primary record. no proof recorded yet | validation | console, service | test |
06must proveProposed | A newly selected outcome must be active and belong to the selected activity type, with the type relationship also checked in storage. no proof recorded yet | validation | service, database | test |
07must proveProposed | The end cannot precede the start, duration must be between zero and 1,440 minutes, and the subject cannot exceed 500 characters; refusals identify the affected field. no proof recorded yet | validation | service, database | test |
08must proveProposed | Rhythm cleans formatted notes of scripts, styles, frames, event handlers and unsafe links, treats content reduced to nothing as empty, and limits the result to 100,000 characters. no proof recorded yet | calculation | service, database | test |
09must proveProposed | A new activity defaults to the current time, its type’s initial status and visible default duration, and the signed-in user as owner. no proof recorded yet | calculation | service | test |
10Confirmed | Ownership is optional and remains separate from creation and modification attribution. | policy | console, service | test |
11must proveConfirmed | Repeating an identical create under the same client-selected identifier returns the existing activity, while different content under that identifier causes a conflict. no proof recorded yet | invariant | service, database | test |
12must proveProposed | Rhythm supplies the activity’s origin, and an imported external reference must be unique within its workspace. no proof recorded yet | invariant | service, database | test |
13must proveProposed | Activity saves reject custom field values because activities do not support custom fields. origin: R2-ARCH-001 D1 (Andrew 2026-10-19), recorded at services-crm:docs/migrations/activities/README.md#9. Decisions no proof recorded yet | validation | api | test |
14Proposed | For a future-dated new activity, the console selects Scheduled unless the user already chose a status; editing preserves the saved status. | policy | console | test |
15must proveProposed | A field-mode refusal reports the detected field problems together, and a rejected transaction keeps neither its activity nor its follow-up. no proof recorded yet | invariant | service | observed |
16must proveProposed | Hiding the attendee control leaves additional contact links valid. no proof recorded yet | validation | service | test |
17must proveProposed | A user create replaces absent or empty ownership with the caller, while a subsequent edit can retain empty ownership. no proof recorded yet | calculation | service | observed |