---
id: SVC-PFM-MTD-associations
title: Associations Service Module
product_area: platform
module: metadata
repository: services-platform
source_module: modules/associations
revision: 1
status: draft
design_intent: confirmed
origin: Custom objects architecture D-04, D-09, D-12 (approved 2026-10-18); PLAT-M6 plan approved 2026-10-21 with
  D1 to D5 and A1 to A3 (services-platform:docs/milestones/PLAT-M6-custom-record-relationships.md, In Progress);
  CRM-M1 owner delete (PLAT-M5 decisions table); the data job routes follow the data job engine plan under PLAT-M7,
  which is proposed; R2-ARCH-002 v2.0 (Andrew, 2026-10-22) for the publication column
implementation_evidence: observed
inference: []
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
owns:
- DOM-PFM-MTD-006
does_not_own:
- CRM owns contact-to-organization affiliation behavior.
- Endpoint records stay with their native or custom record owners.
- The Data Job Engine owns job state, batches and crosswalk identities behind these routes.
- The Custom Objects pipeline dispatches and consumes connection messages.
operations:
- operation_id: getAssociationsHealth
  intent: Return the Associations build identity and health response.
  access: public
  permission: 'none: the shared health route (generated by the health-route factory as get<Module>Health)'
  realises: []
  published_to_submissions: 'not published: Operational health checks have no intake binding.'
- operation_id: listAssociationTypes
  intent: Return local connection definitions, optionally filtered by endpoint and activity.
  access: console
  permission: platform.association-types.read
  realises:
  - CAP-PFM-MTD-017
  published_to_submissions: 'not published: This read has no Submissions binding.'
- operation_id: createAssociationType
  intent: Define endpoint categories, directional names, occupancy shape, dating and deletion policy.
  access: console
  permission: platform.association-types.create
  realises:
  - CAP-PFM-MTD-017
  - CAP-PFM-MTD-009
  published_to_submissions: 'not published: This staff maintenance operation has no Submissions binding.'
- operation_id: getAssociationType
  intent: Return the selected relationship definition in its current activity state.
  access: console
  permission: platform.association-types.read
  realises:
  - CAP-PFM-MTD-017
  published_to_submissions: 'not published: This read has no Submissions binding.'
- operation_id: updateAssociationType
  intent: Replace mutable connection policy and labels at the loaded version while retaining fixed shape.
  access: console
  permission: platform.association-types.update
  realises:
  - CAP-PFM-MTD-017
  published_to_submissions: 'not published: This staff maintenance operation has no Submissions binding.'
- operation_id: deleteAssociationType
  intent: Remove an unreferenced type or deactivate a used one, protecting every selected object-owner type.
  access: console
  permission: platform.association-types.delete
  realises:
  - CAP-PFM-MTD-017
  published_to_submissions: 'not published: This staff maintenance operation has no Submissions binding.'
- operation_id: listRecordAssociations
  intent: Return directional connections and opposite-record names, excluding ended history unless requested.
  access: console
  permission: platform.associations.read
  realises:
  - CAP-PFM-MTD-018
  published_to_submissions: 'not published: This read has no Submissions binding.'
- operation_id: createAssociation
  intent: Create a valid connection under an active type and its occupancy safeguards.
  access: console
  permission: platform.associations.create
  realises:
  - CAP-PFM-MTD-018
  - CAP-PFM-MTD-015
  published_to_submissions: 'not published: This staff maintenance operation has no Submissions binding.'
- operation_id: updateAssociation
  intent: Save complete mutable connection dates and annotations at the loaded version.
  access: console
  permission: platform.associations.update
  realises:
  - CAP-PFM-MTD-018
  published_to_submissions: 'not published: This staff maintenance operation has no Submissions binding.'
- operation_id: deleteAssociation
  intent: Remove an undated or already end-dated connection; an open dated connection receives today’s end instead.
  access: console
  permission: platform.associations.delete
  realises:
  - CAP-PFM-MTD-018
  - CAP-PFM-MTD-015
  published_to_submissions: 'not published: This staff maintenance operation has no Submissions binding.'
- operation_id: endAssociation
  intent: Set a valid inclusive ending for a dated, currently in-force link at its version.
  access: console
  permission: platform.associations.update
  realises:
  - CAP-PFM-MTD-018
  - CAP-PFM-MTD-015
  published_to_submissions: 'not published: This staff maintenance operation has no Submissions binding.'
- operation_id: submitAssociationDataJob
  intent: Store a link-load job and resolve repeated submission identities to the existing job.
  access: console
  permission: platform.associations.create, with platform.associations.update and the keys of the workspace's other
    queued batches evaluated
  realises:
  - CAP-PFM-MTD-016
  published_to_submissions: 'not published: Staff data-job controls have no Submissions binding.'
- operation_id: listAssociationDataJobs
  intent: Return newest-first link jobs within creator or granted updater visibility.
  access: console
  permission: platform.associations.create, with platform.associations.update and the keys of the workspace's other
    queued batches evaluated
  realises:
  - CAP-PFM-MTD-016
  published_to_submissions: 'not published: This read has no Submissions binding.'
- operation_id: getAssociationDataJob
  intent: Return the job’s state, counters and validated impact contract.
  access: console
  permission: platform.associations.create, with platform.associations.update and the keys of the workspace's other
    queued batches evaluated
  realises:
  - CAP-PFM-MTD-016
  published_to_submissions: 'not published: This read has no Submissions binding.'
- operation_id: listAssociationDataJobResults
  intent: Return ordered per-line outcomes for the selected job.
  access: console
  permission: platform.associations.create, with platform.associations.update and the keys of the workspace's other
    queued batches evaluated
  realises:
  - CAP-PFM-MTD-016
  published_to_submissions: 'not published: This read has no Submissions binding.'
- operation_id: listAssociationDataJobRejections
  intent: Return rejected line identities and safe reasons without their input values.
  access: console
  permission: platform.associations.create, with platform.associations.update and the keys of the workspace's other
    queued batches evaluated
  realises:
  - CAP-PFM-MTD-016
  published_to_submissions: 'not published: This read has no Submissions binding.'
- operation_id: applyAssociationDataJob
  intent: Start applying a validated job when its impact digest matches.
  access: console
  permission: platform.associations.create, with platform.associations.update and the keys of the workspace's other
    queued batches evaluated
  realises:
  - CAP-PFM-MTD-016
  published_to_submissions: 'not published: Staff data-job controls have no Submissions binding.'
- operation_id: pauseAssociationDataJob
  intent: Stop new job batches after any running work completes.
  access: console
  permission: platform.associations.create, with platform.associations.update and the keys of the workspace's other
    queued batches evaluated
  realises:
  - CAP-PFM-MTD-016
  published_to_submissions: 'not published: Staff data-job controls have no Submissions binding.'
- operation_id: resumeAssociationDataJob
  intent: Continue remaining batches of a paused job.
  access: console
  permission: platform.associations.create, with platform.associations.update and the keys of the workspace's other
    queued batches evaluated
  realises:
  - CAP-PFM-MTD-016
  published_to_submissions: 'not published: Staff data-job controls have no Submissions binding.'
- operation_id: cancelAssociationDataJob
  intent: Stop remaining work and retain the outcomes already committed.
  access: console
  permission: platform.associations.create, with platform.associations.update and the keys of the workspace's other
    queued batches evaluated
  realises:
  - CAP-PFM-MTD-016
  published_to_submissions: 'not published: Staff data-job controls have no Submissions binding.'
- operation_id: retryAssociationDataJob
  intent: Reoffer eligible batches that exhausted transient attempts.
  access: console
  permission: platform.associations.create, with platform.associations.update and the keys of the workspace's other
    queued batches evaluated
  realises:
  - CAP-PFM-MTD-016
  published_to_submissions: 'not published: Staff data-job controls have no Submissions binding.'
- operation_id: platform.apply_endpoint_deletion
  intent: Apply endpoint policy and custom cascades inside the deleting owner’s transaction.
  access: internal
  permission: 'none: database function executable only by the CRM and Platform application roles'
  realises:
  - CAP-PFM-MTD-019
  published_to_submissions: 'not published: Internal service collaboration has no Submissions entry point.'
- operation_id: platform.merge_plan_contacts
  intent: Describe connection moves, collision endings and custom-reference changes for the owner’s merge plan.
  access: internal
  permission: 'none: database function run in CRM''s merge transaction as CRM''s application role'
  realises:
  - CAP-PFM-MTD-019
  published_to_submissions: 'not published: Internal service collaboration has no Submissions entry point.'
- operation_id: platform.merge_plan_organizations
  intent: Describe connection moves, collision endings and custom-reference changes for the owner’s merge plan.
  access: internal
  permission: 'none: database function run in CRM''s merge transaction as CRM''s application role'
  realises:
  - CAP-PFM-MTD-019
  published_to_submissions: 'not published: Internal service collaboration has no Submissions entry point.'
- operation_id: platform.merge_apply_contacts
  intent: Redirect duplicate endpoints and references, resolving connection collisions inside the owner’s merge
    transaction.
  access: internal
  permission: 'none: database function run in CRM''s merge transaction as CRM''s application role'
  realises:
  - CAP-PFM-MTD-019
  published_to_submissions: 'not published: Internal service collaboration has no Submissions entry point.'
- operation_id: platform.merge_apply_organizations
  intent: Redirect duplicate endpoints and references, resolving connection collisions inside the owner’s merge
    transaction.
  access: internal
  permission: 'none: database function run in CRM''s merge transaction as CRM''s application role'
  realises:
  - CAP-PFM-MTD-019
  published_to_submissions: 'not published: Internal service collaboration has no Submissions entry point.'
events:
- name: objects.association.created
  direction: produced
  when: Creation of the connection commits.
  payload_summary: Connection and type identities, both endpoint categories and records, primary marking and inclusive
    date boundaries.
- name: objects.association.ended
  direction: produced
  when: A dated connection receives an end through explicit ending, open-link removal or a replacement that newly
    sets its end day.
  payload_summary: Connection and type identities, both endpoint categories and records, primary marking and inclusive
    date boundaries.
- name: objects.association.deleted
  direction: produced
  when: Direct or policy-driven removal of the connection commits.
  payload_summary: Connection and type identities, both endpoint categories and records, primary marking and inclusive
    date boundaries.
jobs: []
integrations:
- system: CRM contact and organization deletion
  direction: inbound
  contract: The endpoint owner invokes Platform cleanup in its own attributed workspace transaction and maps defined
    refusal codes.
- system: CRM record merge
  direction: inbound
  contract: The owner invokes participant plan and apply functions under the merge contract within its transaction.
- system: Queries
  direction: outbound
  contract: Type mutations advance query description, and granted readers consume relationship definitions and connections.
consistency:
- rule: Ordinary connection writes cannot overlap a constrained place even during concurrent creation.
  kind: transactional
  compensation: The conflicting writer is refused rather than compensated.
- rule: Endpoint deletion and connection-policy effects share the deleting transaction.
  kind: transactional
  compensation: A policy refusal rolls back all owner and connection changes.
- rule: Endpoint redirection and reference changes share the owner’s merge transaction.
  kind: transactional
  compensation: Failed merge application restores the preceding committed state.
- rule: Supported connection events enter asynchronous delivery.
  kind: eventual
  compensation: Annotation-only updates and merge moves have no event to retry.
- rule: A load keeps each successfully committed batch.
  kind: transactional
  compensation: Cancellation and failure do not reverse preceding batches.
evidence:
- 'services-platform at ad3f6a65: modules/associations/aws/api/associations.routes.ts, association-data-jobs.routes.ts,
  associations.schemas.ts; services/persistence/**; services/maintenance/tenant-participant.ts; association-events.ts;
  rules.ts; db/**; lib/record-merge/platform-references.ts; aws/platform.service.ts (ASSOCIATION_TYPES_PERMISSIONS,
  ASSOCIATIONS_PERMISSIONS); docs/associations.md; docs/record-merge-participant.md; docs/data-jobs/platform-data-operations.md'
- '@rhythmsoftware/macroservice-http 0.19.0 dist/health-route.js (the generated health operation name)'
controls: [TC-AVL-001, TC-AVL-004, TC-AVL-005, 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-IAM-001, TC-IAM-002, TC-IAM-004, TC-IAM-005, TC-IAM-006, TC-LOG-001, TC-LOG-002, TC-LOG-003, TC-LOG-004, TC-LOG-005, TC-MON-001, TC-PI-001, TC-PI-002, TC-PI-003, TC-PI-004, TC-PI-005, TC-PRV-001, TC-PRV-002, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-TEN-004, TC-VEN-001, TC-VEN-002, TC-VEN-003]
---


# Associations Service Module

## What This Service Is For

Associations stores general connection definitions and dated links between supported records. It supplies endpoint deletion and merge functions for record owners to call within their own transactions.

## Boundary

Native endpoints remain with CRM and custom endpoints with Custom Objects. General connections do not replace affiliations; load routes delegate orchestration to the Data Job Engine and event delivery to the custom-object pipeline.

## Operations in Words

Definition operations maintain relationship vocabulary and policy. Link operations create and correct connections or stop them by ending or removal. Ten job routes control bulk link loading; database functions preserve transactional effects during owner deletion and merge.

## Events and Jobs

Created, ended and deleted connections produce three event kinds. Ordinary annotation updates and merge moves or endings produce none; delivery belongs to the shared dispatcher.

## Consistency Guarantees

Ordinary occupancy is checked under locks and backed by indexes. Endpoint removal and merge effects share the owner transaction. Load batches retain earlier commits, and asynchronous announcements have separate retry and failure outcomes.
