---
id: STATE-PFM-SEC-003
title: Workspace retirement request
object: DOM-PFM-SEC-002
product_area: platform
module: security
revision: 1
status: draft
design_intent: proposed
implementation_evidence: observed
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
states:
- name: scheduled
  meaning: The request is waiting for eligibility and required notices; hold or cancellation is still possible.
  provenance: observed
  source: services-platform:modules/tenants/services/deletion/deletion-holds.ts
- name: held
  meaning: A human hold or loss of requester authority pauses progress without immediately changing eligibility.
  provenance: observed
  source: services-platform:modules/tenants/services/deletion/deletion-holds.ts; begin-destruction.ts
- name: cancelled
  meaning: Cancellation closed the request and returned lifecycle to active, with business status still disabled.
  provenance: observed
  source: services-platform:modules/tenants/services/deletion/deletion-holds.ts
- name: executing
  meaning: The named purge job has authority to remove data after the destructive boundary.
  provenance: observed
  source: services-platform:modules/tenants/services/deletion/begin-destruction.ts
- name: failed
  meaning: The purge failed. Lifecycle remains deleting and recovery proceeds through a forward retry.
  provenance: observed
  source: services-platform:modules/tenants/services/deletion/tenant-purge-failure.ts
- name: completed
  meaning: Database finalization removed the workspace and retained deletion counts. External notices or ledger
    writing can still be outstanding.
  provenance: observed
  source: services-platform:modules/tenants/services/deletion/tenant-purge-workflow.ts (finalize)
transitions:
- from: scheduled
  to: held
  trigger: Staff place a hold, or the destructive boundary detects lost requester authority.
  guard: A human hold requires deletion-hold authority; the system can hold its scheduled request when authority
    is lost.
  side_effects:
  - Queue a hold notice
  who: Rhythm staff, or Platform System (schedule job)
  provenance: observed
  source: services-platform:modules/tenants/services/deletion/deletion-holds.ts; begin-destruction.ts
- from: held
  to: scheduled
  trigger: Staff release a hold.
  guard: The request is held and the caller has deletion-hold authority.
  side_effects:
  - Extend eligibility to the later of its prior date and three days from release
  - Schedule a fresh one-day reminder
  who: Rhythm staff
  provenance: observed
  source: services-platform:modules/tenants/services/deletion/deletion-holds.ts
- from: scheduled
  to: cancelled
  trigger: Staff cancel a scheduled request.
  guard: Cancellation must win the request/workspace locks before execution.
  side_effects:
  - Return lifecycle to active without enabling business status
  - Queue cancellation notice; the watcher settles on its next inspection
  who: Rhythm staff (platform.tenants.deletion-cancel)
  provenance: observed
  source: services-platform:modules/tenants/services/deletion/deletion-holds.ts
- from: held
  to: cancelled
  trigger: Staff cancel a held request.
  guard: The request has not entered execution.
  side_effects:
  - Return lifecycle to active while retaining disabled status
  who: Rhythm staff (platform.tenants.deletion-cancel)
  provenance: observed
  source: services-platform:modules/tenants/services/deletion/deletion-holds.ts
- from: scheduled
  to: executing
  trigger: The watcher executes the destructive boundary.
  guard: The named schedule job rechecks eligibility, notices, hold, workspace protections and requester authority.
  side_effects:
  - Set workspace lifecycle to deleting
  - Create the purge job in the same transaction
  who: Platform System (schedule job)
  provenance: observed
  source: services-platform:modules/tenants/services/deletion/begin-destruction.ts
- from: executing
  to: failed
  trigger: The purge failure handler or reconciler applies the failure consequence.
  guard: The executing request still names the failing job.
  side_effects:
  - Queue an operator-safe failure notice
  - Keep lifecycle deleting
  who: Platform System (purge job, job reconciler)
  provenance: observed
  source: services-platform:modules/tenants/services/deletion/tenant-purge-failure.ts
- from: failed
  to: executing
  trigger: An operator requests a purge retry.
  guard: The request is failed and the caller has deletion-request authority.
  side_effects:
  - Create and name the retry job with completed steps copied
  - The recovery path does not add a security-history event
  who: Rhythm staff
  provenance: observed
  source: services-platform:modules/tenants/services/deletion/operator-recovery.ts:retryTenantPurge
- from: executing
  to: completed
  trigger: Purge finalizes after all inventories report zero.
  guard: The deleting workspace and request still authorize this job.
  side_effects:
  - Remove workspace, resource and seed records
  - Retain counts, then attempt the external ledger write
  - Permanently retire the identifier
  who: Platform System (purge job)
  provenance: observed
  source: services-platform:modules/tenants/services/deletion/tenant-purge-workflow.ts (finalize)
invalid:
- from: executing
  to: cancelled
  why: Cancellation cannot promise preservation after the destructive boundary, so it is rejected.
  provenance: observed
  source: 'services-platform at ad3f6a65: modules/tenants/db/tenant-deletion-requests.table.ts, tenant-deletion-notices.table.ts;
    services/deletion/*; docs/tenants/tenant-lifecycle-plan.md §5.'
- from: failed
  to: scheduled
  why: Partial destruction cannot return to a pre-destruction waiting state.
  provenance: observed
  source: 'services-platform at ad3f6a65: modules/tenants/db/tenant-deletion-requests.table.ts, tenant-deletion-notices.table.ts;
    services/deletion/*; docs/tenants/tenant-lifecycle-plan.md §5.'
- from: cancelled
  to: scheduled
  why: A later retirement after cancellation needs a new request and its own eligibility calculation.
  provenance: observed
  source: 'services-platform at ad3f6a65: modules/tenants/db/tenant-deletion-requests.table.ts, tenant-deletion-notices.table.ts;
    services/deletion/*; docs/tenants/tenant-lifecycle-plan.md §5.'
- from: completed
  to: executing
  why: Completed requests are not reopened. Task replay may finish external work; a restored workspace follows
    the ledger-reapplication path.
  provenance: observed
  source: 'services-platform at ad3f6a65: modules/tenants/db/tenant-deletion-requests.table.ts, tenant-deletion-notices.table.ts;
    services/deletion/*; docs/tenants/tenant-lifecycle-plan.md §5.'
concurrency: Request and workspace locks serialize holds, releases, cancellation and the destructive boundary.
  Unique indexes admit one open request. Recovery replaces the named schedule or purge job, causing stale tasks
  to settle or refuse. A completed request can coexist with an unfinished external ledger write; the failure
  consequence does not turn that completed request into failed.
invariants:
- INV-DOM-PFM-SEC-002-08
- INV-DOM-PFM-SEC-002-09
- INV-DOM-PFM-SEC-002-10
evidence:
- 'services-platform at ad3f6a65: modules/tenants/db/tenant-deletion-requests.table.ts, tenant-deletion-notices.table.ts;
  services/deletion/*; docs/tenants/tenant-lifecycle-plan.md §5.'
examined_at: '2026-10-23'
examiner: codex
---

# Workspace retirement request

## The Lifecycle

```mermaid
stateDiagram-v2
    state "Scheduled" as scheduled
    state "Held" as held
    state "Cancelled" as cancelled
    state "Executing" as executing
    state "Failed" as failed
    state "Completed" as completed
    scheduled --> held
    held --> scheduled
    scheduled --> cancelled
    held --> cancelled
    scheduled --> executing
    executing --> failed
    failed --> executing
    executing --> completed
```

The diagram summarizes the observed transition rows; declared edges without an observed writer remain outside the operational graph.

## Transitions Explained

The request is retained independently of the workspace it removes. Its structured transitions identify the cancellable period, destructive boundary, forward-retry state and database completion.

Completion of the request is earlier than guaranteed completion of external ledger work. Task replay can finish that work, but request-specific purge retry accepts failed requests only. Operator recovery for retry exhaustion remains a finding.

## What Cannot Happen

Cancellation cannot promise preservation after the destructive boundary, so it is rejected.

Partial destruction cannot return to a pre-destruction waiting state.

A later retirement after cancellation needs a new request and its own eligibility calculation.

Completed requests are not reopened. Task replay may finish external work; a restored workspace follows the ledger-reapplication path.

## Concurrency and Timing

Request and workspace locks serialize holds, releases, cancellation and the destructive boundary. Unique indexes admit one open request. Recovery replaces the named schedule or purge job, causing stale tasks to settle or refuse. A completed request can coexist with an unfinished external ledger write; the failure consequence does not turn that completed request into failed.
