---
id: WF-PFM-TNL-011
title: Watch a deletion through its waiting period
trigger: Watch recorded notice times and eligibility without keeping a function running.
product_area: platform
module: tenant-lifecycle
revision: 1
status: draft
design_intent: confirmed
origin: services-platform:docs/tenants/tenant-lifecycle-plan.md#§5.4, §5.5, §5.7 (approved 2026-10-09)
implementation_evidence: observed
inference: []
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
implements:
- CAP-PFM-TNL-015
- CAP-PFM-TNL-016
moves:
- STATE-PFM-TNL-004
- STATE-PFM-TNL-005
crosses:
- SVC-PFM-TNL-tenants
idempotency: The watcher checks its current request reference on each task. Due-notice selection excludes recorded
  delivered or suppressed outcomes, but sends can repeat before persistence.
concurrency: Current watcher references limit superseded work. No exclusive notice-send claim prevents overlapping
  external delivery.
hops:
- n: 1
  actor_or_service: Watcher (notice step)
  action: Read the request and end when it no longer belongs to this watcher or is no longer scheduled or held.
  anchor: services-platform:modules/tenants/services/deletion/tenant-deletion-schedule-operations.ts:tenantDeletionScheduleOperations
  seam: state_machine
  on_failure: Retry read errors under notice-task policy.
  left_inconsistent: No request mutation is required.
  observer: Job progress and service logs.
  provenance: observed
  source: services-platform:modules/tenants/services/deletion/tenant-deletion-schedule-operations.ts
- n: 2
  actor_or_service: Notice sender
  action: Attempt due notices to staff recipients and record delivery outcomes.
  anchor: services-platform:modules/tenants/services/deletion/notices/send-notices.ts:sendDueTenantDeletionNotices
  seam: sync
  on_failure: Throw for per-notice failures while fast retries remain; recipient setup can fail earlier.
  left_inconsistent: Provider acceptance can precede the recorded outcome and cause duplicate delivery.
  observer: Job progress and service logs.
  provenance: observed
  source: services-platform:modules/tenants/services/deletion/notices/send-notices.ts
- n: 3
  actor_or_service: Watcher (notice step)
  action: Choose destruction checks once eligibility and sends permit it; otherwise calculate the next wake instant.
  anchor: services-platform:modules/tenants/services/deletion/tenant-deletion-schedule-operations.ts:nextScheduleWakeInstant
  seam: state_machine
  on_failure: Return a bounded wake result rather than blocking in the function.
  left_inconsistent: No destructive decision is made here.
  observer: Job progress and service logs.
  provenance: observed
  source: services-platform:modules/tenants/services/deletion/tenant-deletion-schedule-operations.ts:nextScheduleWakeInstant
- n: 4
  actor_or_service: Step Functions
  action: Wait in the state machine and revisit due work.
  anchor: services-platform:modules/tenants/aws/logic/tenant-deletion-schedule.step-function.ts
  seam: state_machine
  on_failure: Execution failure or the one-year timeout stops the watcher.
  left_inconsistent: The request can remain scheduled or held without a live watcher.
  observer: Job progress and service logs.
  provenance: observed
  source: services-platform:modules/tenants/services/deletion/tenant-deletion-schedule-workflow.ts
- n: 5
  actor_or_service: Watcher (begin destruction)
  action: Run irreversible-removal checks, wait six hours for recoverable conditions or conclude after handoff.
  anchor: services-platform:modules/tenants/services/deletion/tenant-deletion-schedule-operations.ts
  seam: state_machine
  on_failure: Unexpected task failure is recorded; job recovery needs schedule resume.
  left_inconsistent: The request retains its standing when the watcher stops.
  observer: Job progress and service logs.
  provenance: observed
  source: services-platform:modules/tenants/services/deletion/tenant-deletion-schedule-workflow.ts
branches:
- Held standing postpones destruction even after eligibility.
waits:
- The state machine sleeps until notice or eligibility times and revisits failed conditions after six hours, within
  a one-year execution.
evidence:
- 'services-platform at ad3f6a65: modules/tenants/services/deletion/{tenant-deletion-schedule-workflow, tenant-deletion-schedule-operations,
  notice-schedule}.ts; notices/*.ts; aws/logic/tenant-deletion-schedule.step-function.ts; aws/logic/tenant-deletion-notice.alarm.ts.'
controls: [TC-AVL-001, TC-AVL-004, TC-AVL-005, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-AZ-005, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-DAT-004, TC-IAM-001, TC-IAM-002, TC-IAM-003, TC-IAM-004, TC-IAM-005, TC-IAM-006, TC-LOG-001, TC-LOG-002, TC-LOG-003, 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-VEN-001, TC-VEN-002, TC-VEN-003]
---

# Watch A Deletion Through Its Waiting Period

## What It Does

Watch recorded notice times and eligibility without keeping a function running. The watcher checks its current request reference on each task. Due-notice selection excludes recorded delivered or suppressed outcomes, but sends can repeat before persistence.

## The Flow

```mermaid
sequenceDiagram
  autonumber
  participant SF as Watcher (Step Functions)
  participant Op as Watcher tasks
  participant DB as Platform database
  participant Mail as Staff list and requester
  loop until began or ended
    SF->>Op: send due notices
    Op->>DB: is the request still this watcher's?
    Op->>Mail: due notices
    Op->>DB: record delivered, suppressed or failed
    alt eligible and gating notices sent
      SF->>Op: begin destruction
    else
      SF->>SF: wait until the next notice, eligibility or six hours
    end
  end
  SF->>Op: conclude with the reason
```

## When Something Fails

Retry read errors under notice-task policy. No request mutation is required. Throw for per-notice failures while fast retries remain; recipient setup can fail earlier. Provider acceptance can precede the recorded outcome and cause duplicate delivery. Return a bounded wake result rather than blocking in the function. No destructive decision is made here. Execution failure or the one-year timeout stops the watcher. The request can remain scheduled or held without a live watcher. Unexpected task failure is recorded; job recovery needs schedule resume. The request retains its standing when the watcher stops.

## Open Design Questions

Recipient setup and notice-delivery failures have different persistence boundaries. The one-year execution limit requires operational recovery for longer waits.
