---
id: ATS-PFM-TNL-018
scope: CAP-PFM-TNL-018
product_area: platform
module: tenant-lifecycle
revision: 3
status: proposed
approved_by: null
approved_at: null
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
  services-commerce: c8b66a98e2490617aec38ba5c8165dd9bd0a8f9b
  services-committees: 36129c24daeaadcdb339218c38cdeaff9861359d
  services-membership: 5994c270e8a37a30f848e99ba5b5ee6b87c08893
  services-submissions: 64236c19be89579ef5897aad7de3925ed3ce03bf
  services-websites: 5fc6823c69d5e6f208c21dba8c0eb3132f8bdc4c
  services-marketing: d071a159fe9782bb71ff246d5c67d5bbfe07fbfa
  rhythm-v2-docs: d318a948692343e2f0a7ecc2e11c50db179a8c95
scenarios:
  - id: ATS-PFM-TNL-018-01
    title: Completion retains numeric evidence
    level: api
    proves:
      - BR-CAP-PFM-TNL-018-01
    preconditions: The purge fixture has completed.
    steps: Read its deletion request.
    expected: Removal totals and zero-result verification remain available.
    negative: false
    data_needs: >-
      Use the run-owned records and caller contexts created by the cited tests; use their provider and clock
      seams only where declared.
    bound_to:
      - >-
        services-platform:modules/tenants/tests/integration/services/deletion/tenant-purge.integration.spec.js#records
        on the request what was removed, and the counts it verified
      - TST-PFM-TNL-067
    provenance: test
    source: >-
      services-platform:modules/tenants/tests/integration/services/deletion/tenant-purge.integration.spec.js#records
      on the request what was removed, and the counts it verified
    category: rule
    action_evidence:
      provenance: test
      source: >-
        services-platform:modules/tenants/tests/integration/services/deletion/tenant-purge.integration.spec.js#records
        on the request what was removed, and the counts it verified
    assertion_evidence:
      provenance: test
      source: >-
        services-platform:modules/tenants/tests/integration/services/deletion/tenant-purge.integration.spec.js#records
        on the request what was removed, and the counts it verified
    binding_note: >-
      All cited checks for this scenario occur in the registered file. The link establishes inspected
      executable source rather than a passing run.
  - id: ATS-PFM-TNL-018-02
    title: Request identity survives workspace removal
    level: api
    proves:
      - BR-CAP-PFM-TNL-018-02
    preconditions: Deletion removed the workspace record.
    steps: Read the retained request.
    expected: 'Its copied identity, actors and dates remain readable.'
    negative: false
    data_needs: >-
      Use the run-owned records and caller contexts created by the cited tests; use their provider and clock
      seams only where declared.
    bound_to:
      - >-
        services-platform:modules/tenants/tests/integration/services/deletion/request-deletion.integration.spec.js#copies
        the tenant name and customer, so the record still reads after the tenant is gone
      - >-
        services-platform:modules/tenants/tests/integration/services/deletion/tenant-purge.integration.spec.js#keeps
        the deletion’s own job rows, which are the record of what was done
    provenance: test
    source: >-
      services-platform:modules/tenants/tests/integration/services/deletion/request-deletion.integration.spec.js#copies
      the tenant name and customer, so the record still reads after the tenant is gone
    category: invariant
    action_evidence:
      provenance: test
      source: >-
        services-platform:modules/tenants/tests/integration/services/deletion/request-deletion.integration.spec.js#copies
        the tenant name and customer, so the record still reads after the tenant is gone
    assertion_evidence:
      provenance: test
      source: >-
        services-platform:modules/tenants/tests/integration/services/deletion/request-deletion.integration.spec.js#copies
        the tenant name and customer, so the record still reads after the tenant is gone
    binding_note: >-
      The original test-title references contribute separate assertions from several files. No suite receives
      an implements link for the complete combined scenario; a full executable mapping remains
      FND-PFM-TNL-084.
    binding_gap: FND-PFM-TNL-084
  - id: ATS-PFM-TNL-018-03
    title: External ledger retains completed deletion
    level: api
    proves:
      - BR-CAP-PFM-TNL-018-03
    preconditions: The purge fixture completed its outside-database work.
    steps: Read the workspace’s ledger entry.
    expected: The completed dates and count evidence appear in its retained entry.
    negative: false
    data_needs: >-
      Use the run-owned records and caller contexts created by the cited tests; use their provider and clock
      seams only where declared.
    bound_to:
      - >-
        services-platform:modules/tenants/tests/integration/services/deletion/tenant-purge.integration.spec.js#writes
        the permanent deletion record outside the database, keyed by the tenant
      - >-
        services-platform:modules/tenants/tests/unit/services/deletion/deletion-ledger.spec.js#answers no
        entry for a tenant the ledger does not hold
    provenance: test
    source: >-
      services-platform:modules/tenants/tests/integration/services/deletion/tenant-purge.integration.spec.js#writes
      the permanent deletion record outside the database, keyed by the tenant
    category: invariant
    action_evidence:
      provenance: test
      source: >-
        services-platform:modules/tenants/tests/integration/services/deletion/tenant-purge.integration.spec.js#writes
        the permanent deletion record outside the database, keyed by the tenant
    assertion_evidence:
      provenance: test
      source: >-
        services-platform:modules/tenants/tests/integration/services/deletion/tenant-purge.integration.spec.js#writes
        the permanent deletion record outside the database, keyed by the tenant
    binding_note: >-
      The original test-title references contribute separate assertions from several files. No suite receives
      an implements link for the complete combined scenario; a full executable mapping remains
      FND-PFM-TNL-084.
    binding_gap: FND-PFM-TNL-084
  - id: ATS-PFM-TNL-018-04
    title: Retired identity cannot be provisioned again
    level: api
    proves:
      - BR-CAP-PFM-TNL-018-04
    preconditions: A completed deletion ledger entry exists.
    steps: Request creation under the same identifier.
    expected: The refusal identifies retirement and its deletion request.
    negative: true
    data_needs: >-
      Use the run-owned records and caller contexts created by the cited tests; use their provider and clock
      seams only where declared.
    bound_to:
      - >-
        services-platform:modules/tenants/tests/integration/services/deletion/tenant-purge-recovery.integration.spec.js#refuses
        to create a tenant again under the id of one that was deleted
      - TST-PFM-TNL-066
    provenance: test
    source: >-
      services-platform:modules/tenants/tests/integration/services/deletion/tenant-purge-recovery.integration.spec.js#refuses
      to create a tenant again under the id of one that was deleted
    category: validation
    action_evidence:
      provenance: test
      source: >-
        services-platform:modules/tenants/tests/integration/services/deletion/tenant-purge-recovery.integration.spec.js#refuses
        to create a tenant again under the id of one that was deleted
    assertion_evidence:
      provenance: test
      source: >-
        services-platform:modules/tenants/tests/integration/services/deletion/tenant-purge-recovery.integration.spec.js#refuses
        to create a tenant again under the id of one that was deleted
    binding_note: >-
      All cited checks for this scenario occur in the registered file. The link establishes inspected
      executable source rather than a passing run.
  - id: ATS-PFM-TNL-018-05
    title: Legacy immediate delete changes nothing
    level: api
    proves:
      - BR-CAP-PFM-TNL-018-08
    preconditions: Fixtures include present and absent workspaces.
    steps: Invoke immediate deletion for both.
    expected: The same refusal directs callers to requests and preserves the present workspace.
    negative: true
    data_needs: >-
      Use the run-owned records and caller contexts created by the cited tests; use their provider and clock
      seams only where declared.
    bound_to:
      - >-
        services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers the gone status the error
        contract can express
      - >-
        services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#points the caller at the deletion
        request route
      - >-
        services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#leaves the tenant exactly as it was,
        which is the point of refusing
      - >-
        services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers the same to a tenant that does
        not exist, because nothing is read before the refusal
      - TST-PFM-TNL-057
    provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers the gone status the error
      contract can express
    category: edge
    action_evidence:
      provenance: test
      source: >-
        services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers the gone status the error
        contract can express
    assertion_evidence:
      provenance: test
      source: >-
        services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers the gone status the error
        contract can express
    binding_note: >-
      All cited checks for this scenario occur in the registered file. The link establishes inspected
      executable source rather than a passing run.
  - id: ATS-PFM-TNL-018-06
    title: Deletion journey retains evidence and retirement
    level: api
    proves:
      - AS-JNY-PFM-TNL-004-04
    preconditions: The deletion journey completed its fixture.
    steps: Read retained counts and attempt identifier reuse.
    expected: Numeric history remains and creation refuses the retired identifier.
    negative: false
    data_needs: >-
      Use the run-owned records and caller contexts created by the cited tests; use their provider and clock
      seams only where declared.
    bound_to:
      - >-
        services-platform:modules/tenants/tests/integration/services/deletion/tenant-purge.integration.spec.js#records
        on the request what was removed, and the counts it verified
      - >-
        services-platform:modules/tenants/tests/integration/services/deletion/tenant-purge-recovery.integration.spec.js#refuses
        to create a tenant again under the id of one that was deleted
    provenance: test
    source: >-
      services-platform:modules/tenants/tests/integration/services/deletion/tenant-purge.integration.spec.js#records
      on the request what was removed, and the counts it verified
    category: interaction
    action_evidence:
      provenance: test
      source: >-
        services-platform:modules/tenants/tests/integration/services/deletion/tenant-purge.integration.spec.js#records
        on the request what was removed, and the counts it verified
    assertion_evidence:
      provenance: test
      source: >-
        services-platform:modules/tenants/tests/integration/services/deletion/tenant-purge.integration.spec.js#records
        on the request what was removed, and the counts it verified
    binding_note: >-
      The original test-title references contribute separate assertions from several files. No suite receives
      an implements link for the complete combined scenario; a full executable mapping remains
      FND-PFM-TNL-084.
    binding_gap: FND-PFM-TNL-084
  - id: ATS-PFM-TNL-018-07
    title: Restore reapplication has an access window
    category: interaction
    level: api
    proves:
      - BR-CAP-PFM-TNL-018-07
    interacts_with:
      - CAP-PFM-TNL-005
      - CAP-PFM-TNL-001
      - CAP-PFM-TNL-017
    preconditions: A backup restores an active workspace whose completed deletion exists only in the external ledger.
    steps: >-
      Check ordinary access before reapplication, run reapplication in dry-run and apply modes, and check
      lifecycle and access again.
    expected: >-
      The product should refuse ordinary access before reapplication as well as after apply; dry-run should
      leave records unchanged and apply should record disabled deleting standing. The current gate admits a
      restored active fixture before apply, so the initial assertion is an unresolved defect.
    negative: true
    data_needs: >-
      Create a separate run-owned workspace for each decision branch and an unaffected comparison workspace.
      Use a controlled clock, paused task or injected fault at the boundary named in the scenario.
    bound_to: []
    provenance: proposed
    source: >-
      rhythm-v2-docs:specs/platform/tenant-lifecycle/planning/capabilities/CAP-PFM-TNL-018-keep-a-lasting-record-of-a-deleted-workspace-and-stop-it.md;
      rhythm-v2-docs:specs/platform/tenant-lifecycle/planning/capabilities/CAP-PFM-TNL-005-keep-people-and-background-work-out-of-a-workspace-that-is.md;
      rhythm-v2-docs:specs/platform/tenant-lifecycle/planning/capabilities/CAP-PFM-TNL-001-ask-for-a-new-workspace-and-have-every-application-build-it.md;
      rhythm-v2-docs:specs/platform/tenant-lifecycle/planning/capabilities/CAP-PFM-TNL-017-remove-everything-a-workspace-owned-and-prove-it-is-gone.md
    action_evidence:
      provenance: proposed
      source: >-
        rhythm-v2-docs:specs/platform/tenant-lifecycle/planning/capabilities/CAP-PFM-TNL-018-keep-a-lasting-record-of-a-deleted-workspace-and-stop-it.md;
        rhythm-v2-docs:specs/platform/tenant-lifecycle/planning/capabilities/CAP-PFM-TNL-005-keep-people-and-background-work-out-of-a-workspace-that-is.md;
        rhythm-v2-docs:specs/platform/tenant-lifecycle/planning/capabilities/CAP-PFM-TNL-001-ask-for-a-new-workspace-and-have-every-application-build-it.md;
        rhythm-v2-docs:specs/platform/tenant-lifecycle/planning/capabilities/CAP-PFM-TNL-017-remove-everything-a-workspace-owned-and-prove-it-is-gone.md
    assertion_evidence:
      provenance: proposed
      source: >-
        rhythm-v2-docs:specs/platform/tenant-lifecycle/planning/capabilities/CAP-PFM-TNL-018-keep-a-lasting-record-of-a-deleted-workspace-and-stop-it.md;
        rhythm-v2-docs:specs/platform/tenant-lifecycle/planning/capabilities/CAP-PFM-TNL-005-keep-people-and-background-work-out-of-a-workspace-that-is.md;
        rhythm-v2-docs:specs/platform/tenant-lifecycle/planning/capabilities/CAP-PFM-TNL-001-ask-for-a-new-workspace-and-have-every-application-build-it.md;
        rhythm-v2-docs:specs/platform/tenant-lifecycle/planning/capabilities/CAP-PFM-TNL-017-remove-everything-a-workspace-owned-and-prove-it-is-gone.md
    current_observation:
      provenance: observed
      source: >-
        services-platform:modules/tenants/services/access/tenant-availability.ts;
        services-platform:modules/tenants/services/deletion/reapply-deletions.ts
      finding: FND-PFM-TNL-004
evidence:
  - >-
    services-platform:modules/tenants/tests/integration/services/deletion/tenant-purge.integration.spec.js#records
    on the request what was removed, and the counts it verified
  - >-
    services-platform:modules/tenants/tests/integration/services/deletion/request-deletion.integration.spec.js#copies
    the tenant name and customer, so the record still reads after the tenant is gone
  - >-
    services-platform:modules/tenants/tests/integration/services/deletion/tenant-purge.integration.spec.js#writes
    the permanent deletion record outside the database, keyed by the tenant
  - >-
    services-platform:modules/tenants/tests/integration/services/deletion/tenant-purge-recovery.integration.spec.js#refuses
    to create a tenant again under the id of one that was deleted
  - >-
    services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers the gone status the error contract
    can express
  - >-
    rhythm-v2-docs:specs/platform/tenant-lifecycle/planning/capabilities/CAP-PFM-TNL-018-keep-a-lasting-record-of-a-deleted-workspace-and-stop-it.md;
    rhythm-v2-docs:specs/platform/tenant-lifecycle/planning/capabilities/CAP-PFM-TNL-005-keep-people-and-background-work-out-of-a-workspace-that-is.md;
    rhythm-v2-docs:specs/platform/tenant-lifecycle/planning/capabilities/CAP-PFM-TNL-001-ask-for-a-new-workspace-and-have-every-application-build-it.md;
    rhythm-v2-docs:specs/platform/tenant-lifecycle/planning/capabilities/CAP-PFM-TNL-017-remove-everything-a-workspace-owned-and-prove-it-is-gone.md
coverage:
  rule: 'gap: FND-PFM-TNL-083'
  transition: 'gap: FND-PFM-TNL-083'
  validation: covered
  permission: 'gap: FND-PFM-TNL-083'
  edge: covered
  failure: 'gap: FND-PFM-TNL-083'
  boundary: 'gap: FND-PFM-TNL-083'
  concurrency: 'gap: FND-PFM-TNL-083'
  invariant: covered
  interaction: covered
coverage_notes:
  transition: >-
    The listed scenarios sample lifecycle changes. Complete transition, guard and side-effect proof is still
    owed for the state models named in the coverage finding.
  interaction: >-
    The added interaction is proposed. Related capabilities not included in that scenario remain named in the
    coverage finding.
transition_obligations:
  - state_model: STATE-PFM-TNL-001
    transition_n: 1
    coverage: 'gap: FND-PFM-TNL-083'
    provenance: observed
    source: 'services-platform:modules/tenants/services/persistence/tenants.ts:activateProvisionedTenant'
  - state_model: STATE-PFM-TNL-001
    transition_n: 2
    coverage: 'gap: FND-PFM-TNL-083'
    provenance: observed
    source: >-
      services-platform:modules/tenants/services/provisioning/provision-tenant-failure.ts:applyTenantProvisioningFailure
  - state_model: STATE-PFM-TNL-001
    transition_n: 3
    coverage: 'gap: FND-PFM-TNL-083'
    provenance: observed
    source: >-
      services-platform:modules/tenants/services/provisioning/submit-tenant-provisioning.ts:retryTenantProvisioning
  - state_model: STATE-PFM-TNL-001
    transition_n: 4
    coverage: 'gap: FND-PFM-TNL-083'
    provenance: observed
    source: 'services-platform:modules/tenants/services/deletion/request-deletion.ts:requestTenantDeletion'
  - state_model: STATE-PFM-TNL-001
    transition_n: 5
    coverage: 'gap: FND-PFM-TNL-083'
    provenance: observed
    source: 'services-platform:modules/tenants/services/persistence/tenants.ts:enterTenantLoading'
  - state_model: STATE-PFM-TNL-001
    transition_n: 6
    coverage: 'gap: FND-PFM-TNL-083'
    provenance: observed
    source: 'services-platform:modules/tenants/services/deletion/request-deletion.ts:requestTenantDeletion'
  - state_model: STATE-PFM-TNL-001
    transition_n: 7
    coverage: 'gap: FND-PFM-TNL-083'
    provenance: observed
    source: 'services-platform:modules/tenants/services/persistence/tenants.ts:activateLoadedTenant'
  - state_model: STATE-PFM-TNL-001
    transition_n: 8
    coverage: 'gap: FND-PFM-TNL-083'
    provenance: observed
    source: 'services-platform:modules/tenants/services/lifecycle/lifecycle-transitions.ts:SUCCESSORS'
  - state_model: STATE-PFM-TNL-001
    transition_n: 9
    coverage: 'gap: FND-PFM-TNL-083'
    provenance: observed
    source: 'services-platform:modules/tenants/services/deletion/deletion-holds.ts:cancelTenantDeletion'
  - state_model: STATE-PFM-TNL-001
    transition_n: 10
    coverage: 'gap: FND-PFM-TNL-083'
    provenance: observed
    source: 'services-platform:modules/tenants/services/deletion/begin-destruction.ts:beginTenantDestruction'
  - state_model: STATE-PFM-TNL-001
    transition_n: 11
    coverage: 'gap: FND-PFM-TNL-083'
    provenance: observed
    source: 'services-platform:modules/tenants/services/persistence/tenants.ts:forceTenantDeletingAfterRestore'
  - state_model: STATE-PFM-TNL-004
    transition_n: 1
    coverage: 'gap: FND-PFM-TNL-083'
    provenance: observed
    source: 'services-platform:modules/tenants/services/deletion/deletion-holds.ts:holdTenantDeletion'
  - state_model: STATE-PFM-TNL-004
    transition_n: 2
    coverage: 'gap: FND-PFM-TNL-083'
    provenance: observed
    source: 'services-platform:modules/tenants/services/deletion/begin-destruction.ts:beginTenantDestruction'
  - state_model: STATE-PFM-TNL-004
    transition_n: 3
    coverage: 'gap: FND-PFM-TNL-083'
    provenance: observed
    source: 'services-platform:modules/tenants/services/deletion/deletion-holds.ts:releaseTenantDeletion'
  - state_model: STATE-PFM-TNL-004
    transition_n: 4
    coverage: 'gap: FND-PFM-TNL-083'
    provenance: observed
    source: 'services-platform:modules/tenants/services/deletion/deletion-holds.ts:cancelTenantDeletion'
  - state_model: STATE-PFM-TNL-004
    transition_n: 5
    coverage: 'gap: FND-PFM-TNL-083'
    provenance: observed
    source: 'services-platform:modules/tenants/services/deletion/deletion-holds.ts:cancelTenantDeletion'
  - state_model: STATE-PFM-TNL-004
    transition_n: 6
    coverage: 'gap: FND-PFM-TNL-083'
    provenance: observed
    source: 'services-platform:modules/tenants/services/deletion/begin-destruction.ts:beginTenantDestruction'
  - state_model: STATE-PFM-TNL-004
    transition_n: 7
    coverage: 'gap: FND-PFM-TNL-083'
    provenance: observed
    source: 'services-platform:modules/tenants/services/deletion/tenant-purge-operations.ts:tenantPurgeOperations'
  - state_model: STATE-PFM-TNL-004
    transition_n: 8
    coverage: 'gap: FND-PFM-TNL-083'
    provenance: observed
    source: 'services-platform:modules/tenants/services/deletion/tenant-purge-failure.ts:applyTenantPurgeFailure'
  - state_model: STATE-PFM-TNL-004
    transition_n: 9
    coverage: 'gap: FND-PFM-TNL-083'
    provenance: observed
    source: 'services-platform:modules/tenants/services/deletion/operator-recovery.ts:retryTenantPurge'
permission_obligations:
  - key: platform.tenants.deletion-read
    where_checked: api
    scenario_examples: []
    coverage: 'gap: FND-PFM-TNL-083'
    note: 'Examples do not establish the complete key-by-key grant, revoked-grant and staff-context matrix.'
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/platform/tenant-lifecycle/planning/capabilities/CAP-PFM-TNL-018-keep-a-lasting-record-of-a-deleted-workspace-and-stop-it.md
  - key: hq.tenants.update
    where_checked: api
    scenario_examples: []
    coverage: 'gap: FND-PFM-TNL-083'
    note: 'Examples do not establish the complete key-by-key grant, revoked-grant and staff-context matrix.'
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/platform/tenant-lifecycle/planning/capabilities/CAP-PFM-TNL-018-keep-a-lasting-record-of-a-deleted-workspace-and-stop-it.md
evidence_note: >-
  The test-specific convention lists an Evidence body section, but the corpus checker rejects it. Sources and
  verification limits remain in frontmatter so this artifact conforms without changing the checker.
---
# Retain deletion evidence and prevent identifier reuse: Capability Test Specification

## Coverage

The category map separates defined scenarios from missing proof. A covered category has a scenario; a binding records inspected test assertions and carries no execution result. State-model completeness and untested interactions remain explicit gaps.

| Rule | Proved by |
|---|---|
| `BR-CAP-PFM-TNL-018-01` | `ATS-PFM-TNL-018-01` |
| `BR-CAP-PFM-TNL-018-02` | `ATS-PFM-TNL-018-02` |
| `BR-CAP-PFM-TNL-018-03` | `ATS-PFM-TNL-018-03` |
| `BR-CAP-PFM-TNL-018-04` | `ATS-PFM-TNL-018-04` |
| `BR-CAP-PFM-TNL-018-06` | No scenario: `FND-PFM-TNL-083` |
| `BR-CAP-PFM-TNL-018-07` | `ATS-PFM-TNL-018-07` |
| `BR-CAP-PFM-TNL-018-08` | `ATS-PFM-TNL-018-05` |

## Interactions With Related Capabilities

Restore reapplication has an access window. The combined scenario sets up the stated boundary, changes the upstream condition and observes its effect on the dependent outcome. Its steps and assertions are proposed; component tests do not establish this combined execution.

| Related capability | Combined coverage |
|---|---|
| `CAP-PFM-TNL-001` | `ATS-PFM-TNL-018-07` (proposed) |
| `CAP-PFM-TNL-005` | `ATS-PFM-TNL-018-07` (proposed) |
