---
id: WF-PFM-MTD-008
title: Apply relationship rules when CRM deletes a contact or organization
trigger: "Platform exposes transactional endpoint cleanup for CRM\u2019s deletion contract."
product_area: platform
module: metadata
revision: 1
status: draft
design_intent: confirmed
origin: 'CRM-M1 owner delete, relayed 2026-10-19 (services-platform:docs/milestones/PLAT-M5-custom-records.md#Decisions:
  Platform provides a SQL function callable in CRM''s delete transaction); PLAT-M5 B5; PLAT-M6 assumption A2'
implementation_evidence: observed
inference: []
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
implements:
- CAP-PFM-MTD-019
- CAP-PFM-MTD-015
moves:
- STATE-PFM-MTD-010
- STATE-PFM-MTD-005
crosses:
- SVC-PFM-MTD-associations
- SVC-PFM-MTD-custom-objects
idempotency: The database function neither begins nor commits the owner transaction. Repetition after links are
  removed has no remaining effects; cascade records and links remain locked until the owner commits or rolls back.
concurrency: The database function neither begins nor commits the owner transaction. Repetition after links are
  removed has no remaining effects; cascade records and links remain locked until the owner commits or rolls back.
hops:
- n: 1
  actor_or_service: CRM contact or organization deletion
  action: "The endpoint owner\u2019s deletion contract calls Platform\u2019s database function in its own attributed\
    \ workspace transaction."
  anchor: services-platform:docs/associations.md#The contract for another service (CRM's contact and organization
    deletes); CRM's own call site is not in this job's repositories
  seam: sync
  on_failure: The owner must map the function refusal and roll back its failed transaction.
  left_inconsistent: Platform changes cannot commit independently of that transaction.
  observer: The initiating person or service and its operation logs.
  provenance: documented
  source: services-platform:docs/associations.md#The contract for another service (CRM's contact and organization
    deletes)
- n: 2
  actor_or_service: Endpoint deletion function (Platform, definer rights)
  action: The SQL entry point checks the session workspace and walks deletion policies, allowing custom-record cascades
    no deeper than ten.
  anchor: services-platform:db/migrations/20261020023906_apply_endpoint_deletion.sql:platform.apply_endpoint_deletion
  seam: sync
  on_failure: Raise the policy, lock or depth refusal for the owner to handle.
  left_inconsistent: The owner transaction remains failed until rolled back.
  observer: The initiating person or service and its operation logs.
  provenance: test
  source: 'services-platform:tests/acceptance/custom-objects/deployed/associations/CO-ACC-0256.spec.js#step 3: Fulmar
    answers 404 and its associations are gone'
- n: 3
  actor_or_service: Endpoint deletion function
  action: Each cascaded deletion releases stored values and uniqueness claims, detaches assets, and captures audit,
    history and events in the caller transaction.
  anchor: services-platform:db/migrations/20261020023906_apply_endpoint_deletion.sql:platform.apply_endpoint_deletion
  seam: sync
  on_failure: Abort the transaction if any cascade work fails.
  left_inconsistent: The preceding committed state survives once the owner rolls back.
  observer: The initiating person or service and its operation logs.
  provenance: test
  source: services-platform:modules/associations/tests/integration/db/apply-endpoint-deletion.integration.spec.js#leaves
    the same audit rows, events, revisions and no rec
- n: 4
  actor_or_service: CRM contact or organization deletion
  action: "The owner commits its deletion with Platform\u2019s deferred captured revisions."
  anchor: services-platform:docs/record-history.md
  seam: sync
  on_failure: Reject commit when history attribution is absent.
  left_inconsistent: Neither deletion nor Platform effects commit on history failure.
  observer: The initiating person or service and its operation logs.
  provenance: documented
  source: services-platform:docs/associations.md#The contract for another service (CRM's contact and organization
    deletes)
- n: 5
  actor_or_service: Business events dispatcher
  action: The event dispatcher later claims the committed facts from its schedule.
  anchor: services-platform:modules/custom-objects/services/dispatch/business-events.ts:dispatchPlatformBusinessEvents
  seam: schedule
  on_failure: Retry waiting outbox work on later successful runs.
  left_inconsistent: Delivery may lag, and detached files remain without Platform cleanup.
  observer: Scheduled execution logs and configured alarms.
  provenance: inferred
  source: services-platform:docs/business-events.md#2. One event per committed change
  note: The caller commits through SQL without the API nudge; scheduled dispatch therefore supplies the documented
    delivery path.
branches: []
waits: []
evidence:
- "services-platform at ad3f6a65: docs/associations.md \xA76; modules/associations/services/persistence/associations.ts;\
  \ modules/associations/tests/integration/db/apply-endpoint-deletion.integration.spec.js; tests/acceptance/custom-objects/deployed/associations/CO-ACC-0256.spec.js"
- services-platform:db/migrations/20261020023906_apply_endpoint_deletion.sql; db/migrations/20261021162402_associations_in_force_until_end_date.sql
  (current deletion-rule date predicate)
controls: [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-002, TC-LOG-003, TC-LOG-004, TC-LOG-005, TC-MON-001, TC-MON-002, 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]
---

# Apply relationship rules when CRM deletes a contact or organization

## What It Does

Platform exposes transactional endpoint cleanup for CRM’s deletion contract. The function applies restrictions and cascades without committing independently of the record owner.

## The Flow

```mermaid
sequenceDiagram
  participant CRM as CRM deletion (one transaction)
  participant Fn as Platform endpoint deletion function
  participant Rec as Custom record store tables
  CRM->>Fn: apply endpoint deletion (workspace, record type, record)
  Fn->>Fn: check workspace, read links for update
  alt restrict link in force
    Fn-->>CRM: refusal code with message
    CRM->>CRM: roll back
  else
    Fn->>Rec: delete cascaded custom records, values, files, audit, events
    Fn-->>CRM: removed count, cascaded records
    CRM->>CRM: commit (history captured)
  end
```

## When Something Fails

The owner must map the function refusal and roll back its failed transaction. Platform changes cannot commit independently of that transaction. Raise the policy, lock or depth refusal for the owner to handle. The owner transaction remains failed until rolled back. Abort the transaction if any cascade work fails. The preceding committed state survives once the owner rolls back. Reject commit when history attribution is absent. Neither deletion nor Platform effects commit on history failure. Retry waiting outbox work on later successful runs. Delivery may lag, and detached files remain without Platform cleanup.

## Open Design Questions

The record owner’s call sites are outside the supplied repositories; this is the verified Platform contract and documented caller obligation.
