---
id: WF-PFM-TNL-004
title: Retry a failed build
trigger: Recover failed construction through a linked attempt with completed steps carried forward.
product_area: platform
module: tenant-lifecycle
revision: 1
status: draft
design_intent: confirmed
origin: services-platform:docs/tenants/tenant-lifecycle-plan.md#§4.1 Retry, §4.4 (approved 2026-10-09)
implementation_evidence: observed
inference: []
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
implements:
- CAP-PFM-TNL-003
- CAP-PFM-TNL-002
moves:
- STATE-PFM-TNL-001
- STATE-PFM-TNL-002
crosses:
- SVC-PFM-TNL-tenants
idempotency: A call made after the lifecycle move is refused; linked retries carry completed steps. Two callers
  can both pass the earlier unlocked read before one moves the workspace.
concurrency: Lifecycle return and retry creation are separate commits. A pre-read race is not prevented by the later
  successor assertion accepting the same state.
hops:
- n: 1
  actor_or_service: Platform API (retryTenantProvisioning)
  action: Check staff authority, failed-provisioning lifecycle and a prior attempt.
  anchor: services-platform:modules/tenants/aws/api/tenants.routes.ts:retryTenantProvisioning
  seam: sync
  on_failure: Refuse absent records or inadmissible standing.
  left_inconsistent: No retry is created.
  observer: Job progress and service logs.
  provenance: observed
  source: services-platform:modules/tenants/services/provisioning/submit-tenant-provisioning.ts:retryTenantProvisioning
- n: 2
  actor_or_service: Provisioning submission
  action: Commit the move back to provisioning and clear local availability.
  anchor: services-platform:modules/tenants/services/persistence/tenants.ts:setTenantLifecycleState
  seam: sync
  on_failure: Reject an illegal lifecycle move.
  left_inconsistent: The workspace move can commit without a new attempt.
  observer: Job progress and service logs.
  provenance: observed
  source: services-platform:modules/tenants/services/provisioning/submit-tenant-provisioning.ts:retryTenantProvisioning
- n: 3
  actor_or_service: Job engine
  action: Create a linked retry carrying the prior completed steps in a later commit.
  anchor: services-platform:modules/jobs (retryJob)
  seam: sync
  on_failure: Return the creation error.
  left_inconsistent: The workspace can remain provisioning until stranded-workspace repair.
  observer: Job progress and service logs.
  provenance: inferred
  source: services-platform:modules/tenants/services/provisioning/submit-tenant-provisioning.ts:retryTenantProvisioning
- n: 4
  actor_or_service: Job engine
  action: Start the new execution, which skips copied completed participant steps.
  anchor: services-platform:modules/jobs (startJobOrLeaveToReconciler)
  seam: state_machine
  on_failure: Leave start failure to shared reconciliation.
  left_inconsistent: A committed retry can have no execution until recovered.
  observer: Job progress and service logs.
  provenance: observed
  source: services-platform:modules/tenants/services/provisioning/provision-tenant-operations.ts:provisionParticipant
branches: []
waits: []
evidence:
- 'services-platform at ad3f6a65: modules/tenants/services/provisioning/{submit-tenant-provisioning, provision-tenant-operations}.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-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-VEN-001, TC-VEN-002, TC-VEN-003]
---

# Retry A Failed Build

## What It Does

Recover failed construction through a linked attempt with completed steps carried forward. A call made after the lifecycle move is refused; linked retries carry completed steps. Two callers can both pass the earlier unlocked read before one moves the workspace.

## The Flow

```mermaid
sequenceDiagram
  autonumber
  actor Staff as Rhythm staff
  participant API as Platform API
  participant DB as Platform database
  participant Jobs as Job engine
  Staff->>API: retry the build
  API->>DB: workspace is provisioning failed?
  API->>DB: workspace -> provisioning (commit 1)
  API->>Jobs: linked retry attempt, completed steps copied (commit 2)
  API->>Jobs: start execution after commit
  API-->>Staff: workspace and new job
```

## When Something Fails

Refuse absent records or inadmissible standing. No retry is created. Reject an illegal lifecycle move. The workspace move can commit without a new attempt. Return the creation error. The workspace can remain provisioning until stranded-workspace repair. Leave start failure to shared reconciliation. A committed retry can have no execution until recovered.

## Open Design Questions

The product should close the separate-commit window between lifecycle return and retry creation, and decide how concurrent retry submission is recovered.
