---
id: STATE-PFM-MTD-005
title: Custom record retention lifecycle
object: DOM-PFM-MTD-005
product_area: platform
module: metadata
revision: 1
status: draft
design_intent: confirmed
origin: 'Custom objects architecture D-19 (Andrew, 2026-10-18: the delete key archives and restores) and PLAT-M5
  D3, B1, B5 (services-platform:docs/milestones/PLAT-M5-custom-records.md#Decisions); PLAT-M6 D2 (in force until
  it ends, plan approved 2026-10-21)'
implementation_evidence: observed
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
states:
- name: absent
  meaning: There is no stored record.
- name: live
  meaning: The record is included in ordinary lists and supports permitted writes under an active object.
- name: archived
  meaning: Content and links remain stored, but ordinary lists exclude the record and only restoration or permitted
    deletion is available.
- name: deleted
  meaning: Record data and reservations have been removed; revisions survive, and file lifecycle entries record
    detachment.
transitions:
- from: absent
  to: live
  trigger: A person or load creates a custom record.
  guard: The object is active, property values meet current rules and changed files have prepared references.
  side_effects:
  - Allocate number and name, store values and reservations, attach files and commit audit, revision and created
    event.
  who: Record Keeper (platform.custom-records.create) or a data job
  provenance: test
  source: services-platform:modules/custom-objects/tests/integration/services/persistence/custom-object-records.integration.spec.js#defaults
    a date to the tenant’s today,
- from: live
  to: live
  trigger: A person or load changes stored properties.
  guard: The object is active, the version matches, update locks permit the write and resulting values satisfy rules.
  side_effects:
  - Recompose the name and reservations, detach replaced files, audit the write and capture changed business values
    and event content.
  who: Record Keeper (platform.custom-records.update) or a data job
  provenance: test
  source: services-platform:modules/custom-objects/tests/integration/services/persistence/custom-object-records.integration.spec.js#clears
    every property a replacement le
- from: live
  to: archived
  trigger: An administrator archives the record.
  guard: The object is active, the version matches, no lock applies and the record is not already archived.
  side_effects:
  - Stamp archival with its audit, revision and archived event.
  who: Records Administrator (platform.custom-records.delete)
  provenance: test
  source: services-platform:modules/custom-objects/tests/integration/services/persistence/custom-object-records.integration.spec.js#archives
    a record with everything kept
- from: archived
  to: live
  trigger: An administrator restores the record.
  guard: The object is active, the record is archived and the version matches.
  side_effects:
  - Clear archival with its audit, revision and restored event.
  who: Records Administrator (platform.custom-records.delete)
  provenance: observed
  source: services-platform:modules/custom-objects/services/persistence/custom-object-records.ts:restoreRecord
- from: live
  to: deleted
  trigger: A direct deletion or owner cascade removes a live record.
  guard: Direct deletion needs an active object and current version; all paths check delete locks, in-force restrictions
    and depth ten. Registered deletion checks apply on the direct store path.
  side_effects:
  - Apply link policy, recursively delete custom dependants, detach files and commit audit, revisions and dependant-first
    deleted events.
  who: Records Administrator (platform.custom-records.delete), or CRM's deletion of an endpoint
  provenance: test
  source: services-platform:modules/custom-objects/tests/integration/services/persistence/custom-object-records.integration.spec.js#writes
    every dependant’s event before
- from: archived
  to: deleted
  trigger: A direct deletion or owner cascade removes an archived record.
  guard: Apply the same deletion checks; the record’s archive stamp alone does not prevent removal.
  side_effects:
  - Remove data and reservations, apply link policy, detach files and capture deletion facts in the transaction.
  who: Records Administrator (platform.custom-records.delete), or CRM's deletion of an endpoint
  provenance: observed
  source: services-platform:modules/custom-objects/services/persistence/custom-object-records.ts:deleteRecord
invalid:
- from: deleted
  to: live
  why: Deletion has no reversal. Archived records reject editing or repeated archival until restoration.
- from: archived
  to: archived
  why: Deletion has no reversal. Archived records reject editing or repeated archival until restoration.
- from: deleted
  to: archived
  why: Deletion has no reversal. Archived records reject editing or repeated archival until restoration.
concurrency: Record changes lock the row and use its read version while holding the parent shared. Cascades lock
  reached records within the deleting transaction, so concurrent edits resolve before deletion or observe removal
  afterwards.
invariants:
- INV-DOM-PFM-MTD-005-01
- INV-DOM-PFM-MTD-005-07
- INV-DOM-PFM-MTD-005-08
evidence:
- 'services-platform at ad3f6a65: modules/custom-objects/services/persistence/custom-object-records.ts (createRecord,
  updateRecord, replaceRecord, archiveRecord, restoreRecord, deleteRecord, deleteWithRules); docs/custom-objects.md
  §13 to §16'
---

# Custom record retention lifecycle

## The Lifecycle

```mermaid
stateDiagram-v2
  [*] --> absent
  absent --> live: create
  live --> live: patch or replace
  live --> archived: archive
  archived --> live: restore
  live --> deleted: delete or cascade
  archived --> deleted: delete or cascade
  deleted --> [*]
```

## Transitions Explained

Archival retains record content for restoration, whereas deletion removes it permanently under relationship policy. Deletion cascades and their supporting facts commit together or roll back together.

## What Cannot Happen

Deletion has no reversal. Archived records reject editing or repeated archival until restoration.

## Concurrency and Timing

Record changes lock the row and use its read version while holding the parent shared. Cascades lock reached records within the deleting transaction, so concurrent edits resolve before deletion or observe removal afterwards.
