Skip to content

CAP-PFM-MTD-018Maintain Dated Links Between Records

Markdown

CAP-PFM-MTD-018

Maintain Dated Links Between Records

Markdown
  • DocumentDraft
  • Product intentConfirmed
  • ImplementationObserved

KindCapabilityProduct areaPlatformModuleMetadata and Organization-defined RecordsRevision1

Read atservices-platform ad3f6a65react-console baf6dae3

The Formal Contract

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

Outcomes
Record keepers need to express current and past connections without losing their dates.Both endpoint cards expose permitted actions and the option to inspect ended links.
Surfaces
consoleapi
Preconditions
The type is active and both endpoints belong to the workspace.
Intent sources
services-platform:docs/milestones/plans/PLAT-M6-plan.md#3. How it works for the user; 5. D2 (Andrew, 2026-10-21: in force until it ends)services-platform:docs/milestones/plans/PLAT-M6-plan.md#9. Acceptance scenarios PLAT-M6-S03 to S07, S10, S12services-platform:docs/proposals/custom-objects/09-decisions.md#D-04, D-12, D-16

Controls

23 controls apply, from the corpus control catalogue.

TC-AZ-001 TC-AZ-002 TC-AZ-003 TC-AZ-004 TC-DAT-001 TC-DAT-002 TC-DAT-003 TC-DAT-004 TC-LOG-002 TC-LOG-003 TC-LOG-004 TC-LOG-005 TC-PI-001 TC-PI-003 TC-PI-005 TC-PRV-001 TC-PRV-002 TC-TEN-001 TC-TEN-002 TC-TEN-003 TC-VEN-001 TC-VEN-002 TC-VEN-003

Permissions

KeyChecked atScope
platform.associations.readapitenant
platform.associations.createapitenant
platform.associations.updateapitenant
platform.associations.deleteapitenant

Business Rules

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

IdRuleKindEnforced atProvenance
01must prove
Confirmed
Creating a link requires an active workspace type and two existing compatible endpoints, rejects self-links and fills an omitted endpoint from the record route.
validationservicetest
02must prove
Confirmed
A link remains in force through its inclusive end date in the workspace calendar, or indefinitely when no end date exists.
origin: services-platform:docs/milestones/plans/PLAT-M6-plan.md#5. D2 (Andrew, 2026-10-21: "In force until it ends")
calculationservice, databasetest
03must prove
Confirmed
Overlapping date spans cannot occupy a duplicate pair, a cardinality-limited endpoint or the primary place of a record and type; unbounded ends and inclusive dates determine conflicts while adjacent spans are allowed.
validationservice, databasetest
services-platform:modules/associations/tests/integration/services/persistence/associations.in-force.integration.spec.js#refuses a second link of a one-place type that starts today, naming the link whose end date has not passed
04must prove
Confirmed
Concurrent writers cannot both occupy a conflicting relationship place, and the losing write receives a conflict refusal.
invariantservice, databasetest
services-platform:modules/associations/tests/integration/services/persistence/associations.in-force.integration.spec.js#refuses one of two writers of overlapping links of one pair, as a refusal and not a database error
05must prove
Confirmed
Only dated types accept calendar dates, an end cannot precede its start and only primary-enabled types accept primary links.
validationservice, databasetest
06must prove
Confirmed
Type and endpoint identities remain fixed, while versioned replacements can change dates, primary designation, position and notes bounded to four thousand characters.
invariantservicetest
services-platform:modules/associations/tests/e2e/associations.e2e.spec.js#answers 400 to a replacement that names another record
07must prove
Confirmed
Ending a dated link uses a supplied day or the workspace today and refuses already-ended, invalid or conflicting spans; ending an undated link is refused in favour of removal.
lifecycleservicetest
08must prove
Confirmed
Removing a dated link without an end date ends it today, removing a dated link with an end date deletes it as a correction, and undated links are deleted.
lifecycleservicetest
services-platform:modules/associations/tests/integration/services/persistence/associations.in-force.integration.spec.js#removes a link that has an end date when it is deleted, correcting history, and ends one with none
09must prove
Confirmed
Creation permits one thousand links per record and type on each side, counting current and ended links together, while merge can exceed that limit.
validationservicetest
services-platform:modules/associations/tests/integration/services/persistence/associations.integration.spec.js#refuses an association past the per-record limit of the type, writing nothing
10must prove
Confirmed
Link lists use the current endpoint label and opposite record name, default to in-force links, offer ended history when requested and isolate workspaces.
policyservicetest
services-platform:modules/associations/tests/e2e/associations.e2e.spec.js#lists it on the organization’s path in the reverse direction, naming the contact
11must prove
Confirmed
Relationship cards on custom, contact and organization pages expose permitted link actions and ended history, allowing standard users to maintain links while readers receive no actions.
permissionconsole, apitest
react-console:acceptance/custom-objects/playwright/journeys/PLAT-M6-S12.spec.ts#PLAT-M6-S12: a standard user links, ends and removes but has no Relationship Types screen, and a read-only colleague sees no actions
12
Confirmed
General relationships leave contact-to-organization affiliations under the separate CRM model.
policyservicedocumented
13must prove
Confirmed
Update locks refuse edits and ending, any lock refuses removal, and deactivation does not prevent maintenance of existing unlocked links.
policyserviceobserved

Scenarios

IdGivenWhenThenProvenance
01Tom charter on Osprey ends on the last day of November.In October, request Maria charter from today and then from the first day of December.The overlapping request identifies Tom dates and is refused, while the adjacent charter succeeds.documented
services-platform:docs/associations.md#1a. In force (PLAT-M6 D2)

Edge Cases

IdGivenWhenThenProvenance
02A member has two sponsor links.Designate the second sponsor primary in the console.Primary designation transfers to the second sponsor.test
react-console:acceptance/custom-objects/playwright/journeys/PLAT-M6-S07.spec.ts#PLAT-M6-S07: marking a second sponsor primary moves the primary flag

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.