---
id: WF-PFM-SEC-001
title: Provision a workspace
trigger: HQ submits workspace provisioning, or development bootstrap requests provisioning for an existing
  record.
product_area: platform
module: security
revision: 1
status: draft
design_intent: confirmed
origin: services-platform:docs/tenants/tenant-lifecycle-plan.md#4 (provisioning job, participants, readiness,
  failure); docs/jobs.md (durable job standard)
implementation_evidence: observed
inference: []
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
implements:
- CAP-PFM-SEC-003
- CAP-PFM-SEC-001
moves:
- STATE-PFM-SEC-001
crosses:
- SVC-PFM-SEC-tenants
- SVC-PFM-SEC-customers
- SVC-PFM-SEC-security
idempotency: The wizard retains a submission identity across repeats, returning the existing workspace and
  job. A competing submission cannot take an occupied identifier. Retry carries completed steps forward; participants
  use their seed ledgers to converge. Notification claims avoid repeating a claim, but a failed send after
  claiming can leave a recipient uninformed.
concurrency: Submission commits customer creation when requested, the workspace and its job together. Participant
  execution follows dependency order. Initialization accepts active or failed-provisioning workspaces, while
  retirement excludes a still-running provisioning state.
hops:
- n: 1
  actor_or_service: HQ provisioning wizard and route
  action: Validate staff provisioning authority and all requested workspace, customer, sender and first-administrator
    fields.
  anchor: services-platform:modules/tenants/aws/api/tenants.routes.ts:tenantsRoutes (createTenant)
  seam: sync
  on_failure: Reject before persistence with the relevant validation error.
  left_inconsistent: No submitted record has committed.
  observer: The wizard or API caller receives the validation result.
  provenance: observed
  source: services-platform:modules/tenants/services/provisioning/submit-tenant-provisioning.ts:submitTenantProvisioning
- n: 2
  actor_or_service: Workspaces service (one transaction)
  action: Create the requested customer, provisioning workspace, sender setting and static-plan job in one
    transaction.
  anchor: services-platform:modules/tenants/services/provisioning/submit-tenant-provisioning.ts:submitTenantProvisioning
  seam: sync
  on_failure: Roll back the submission; report an occupied identifier.
  left_inconsistent: No partial submission survives rollback.
  observer: The submitting caller receives the refusal.
  provenance: observed
  source: services-platform:modules/tenants/services/provisioning/submit-tenant-provisioning.ts (One transaction)
- n: 3
  actor_or_service: Job engine
  action: Start execution after the submission commits.
  anchor: '@rhythmsoftware/macroservice-jobs engine startJobOrLeaveToReconciler'
  seam: state_machine
  on_failure: Leave the durable pending job for reconciliation; do not undo the successful request.
  left_inconsistent: The workspace can remain provisioning behind an unstarted job.
  observer: HQ details and job monitoring expose the pending work.
  provenance: documented
  source: services-platform:docs/jobs.md#2. Adding a job (step 8)
- n: 4
  actor_or_service: Provisioning job (publish step)
  action: Compare live participant manifests with the static job plan.
  anchor: services-platform:modules/tenants/services/provisioning/provision-tenant-workflow.ts (PublishStepDefinition)
  seam: state_machine
  on_failure: Fail the job on a plan difference and apply its failure consequence.
  left_inconsistent: No participant provisioning has started.
  observer: Job events identify the plan mismatch.
  provenance: observed
  source: services-platform:modules/tenants/services/provisioning/provision-tenant-workflow.ts (header)
- n: 5
  actor_or_service: Each participant, in dependency order
  action: Invoke participants in dependency order, locally for Platform and through lifecycle functions for
    other services.
  anchor: services-platform:modules/tenants/services/provisioning/provision-tenant-operations.ts:provisionParticipant
  seam: state_machine
  on_failure: Use task retries, then fail and settle the provisioning consequence.
  left_inconsistent: Completed participants remain prepared while ordinary workspace use is blocked.
  observer: The failed participant step and error appear in job monitoring.
  provenance: observed
  source: services-platform:modules/tenants/services/lifecycle/participants.ts (participant table)
- n: 6
  actor_or_service: Provisioning job (verify-readiness)
  action: Verify readiness for every enabled participant.
  anchor: services-platform:modules/tenants/services/provisioning/provision-tenant-operations.ts:verifyParticipant
  seam: state_machine
  on_failure: Fail with the missing participant readiness information.
  left_inconsistent: Prepared work remains in place without ordinary availability.
  observer: The job records the readiness failure.
  provenance: observed
  source: services-platform:modules/tenants/services/provisioning/provision-tenant-workflow.ts (verify-readiness)
- n: 7
  actor_or_service: Provisioning job (activate)
  action: Activate in the requested status, enable baseline applications, invalidate availability, reconcile
    standing access and attempt completion notices.
  anchor: services-platform:modules/tenants/services/provisioning/provision-tenant-operations.ts:activateOperation
  seam: state_machine
  on_failure: Retry activation work; repeated activation can update metadata. Best-effort standing access and
    notifications log their failures.
  left_inconsistent: Activation can remain committed even if later work causes job failure; a late consequence
    preserves active lifecycle.
  observer: Requester notices, HQ alerts and job state show the outcome.
  provenance: observed
  source: services-platform:modules/tenants/services/provisioning/provision-tenant-operations.ts:activateOperation
- n: 8
  actor_or_service: Failure consequence (failure task or job reconciler)
  action: Apply failed-provisioning lifecycle only while the workspace still awaits preparation, and attempt
    claimed failure notices.
  anchor: services-platform:modules/tenants/services/provisioning/provision-tenant-failure.ts:applyTenantProvisioningFailure
  seam: state_machine
  on_failure: Failure-task retries and reconciliation can reapply the consequence.
  left_inconsistent: Partial participant preparation remains for retry or retirement.
  observer: HQ shows failed lifecycle; notices and logs expose failure.
  provenance: observed
  source: services-platform:modules/tenants/services/provisioning/provision-tenant-failure.ts (header)
- n: 9
  actor_or_service: Stranded-provisioning repair (after every job-reconciler pass)
  action: Repair a bounded set of stranded workspaces after job reconciliation.
  anchor: services-platform:modules/tenants/services/provisioning/repair-stranded-provisioning.ts
  seam: schedule
  on_failure: Log an individual repair error and continue; a later pass can retry.
  left_inconsistent: Failed preparation can remain stranded until repair succeeds.
  observer: Reconciliation logs and HQ lifecycle show outstanding repair.
  provenance: observed
  source: services-platform:modules/tenants/services/provisioning/repair-stranded-provisioning.ts (header)
branches:
- A retry returns failed provisioning to provisioning and carries completed participant steps into a new job.
- Development bootstrap uses the same execution on an existing workspace without creating a first customer
  administrator.
- Later initialization applies participant defaults through its seed ledger without creating a provisioning
  job.
waits:
- Provisioning executions have a seven-day limit; task retry policies remain bounded.
evidence:
- 'services-platform at ad3f6a65: modules/tenants/services/provisioning/*; services/lifecycle/participants.ts,
  first-administrator.ts, remote-participants.ts; aws/logic/tenant-provisioning.step-function.ts; docs/jobs.md;
  docs/tenants/tenant-lifecycle-plan.md §4.'
- 'react-console at baf6dae: components/console/hq/provision-wizard.tsx (submission identity minted once per
  form).'
examined_at: '2026-10-23'
examiner: codex
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-AZ-006, TC-CHG-001, TC-CHG-002, TC-CHG-003, TC-CHG-004, TC-CHG-005, TC-CHG-006, TC-CHG-007, TC-CRY-001, TC-CRY-002, TC-CRY-003, TC-CRY-004, 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-004, TC-LOG-005, TC-MON-001, TC-MON-002, TC-MON-003, 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]
---

# Provision a workspace

## What It Does

Provisioning commits intent before invoking participant work. The hop rows identify validation, durable submission, participant execution, readiness, activation and failure settlement.

## The Flow

```mermaid
flowchart TD
    H1["Validate submission"]
    H2["Commit workspace and job"]
    H3["Start execution"]
    H4["Check participant plan"]
    H5["Prepare participants"]
    H6["Verify readiness"]
    H7["Activate workspace"]
    H8["Settle failure"]
    H9["Repair stranded work"]
    H1 --> H2
    H2 --> H3
    H3 --> H4
    H4 --> H5
    H5 --> H6
    H6 --> H7
    H4 -. failure .-> H8
    H5 -. failure .-> H8
    H6 -. failure .-> H8
    H7 -. later failure .-> H8
    H9 --> H8
```

The diagram separates the relevant success, alternative and failure paths. The numbered hop rows retain the detailed authority checks, delegated work and retry limits.

## When Something Fails

Failure retains completed preparation rather than compensating it away. A retry resumes from the copied completed steps. Notification claims and provider sends have different guarantees; successful activation does not prove every completion notice arrived.

The wizard retains a submission identity across repeats, returning the existing workspace and job. A competing submission cannot take an occupied identifier. Retry carries completed steps forward; participants use their seed ledgers to converge. Notification claims avoid repeating a claim, but a failed send after claiming can leave a recipient uninformed.

Submission commits customer creation when requested, the workspace and its job together. Participant execution follows dependency order. Initialization accepts active or failed-provisioning workspaces, while retirement excludes a still-running provisioning state.

## Open Design Questions

The recorded findings retain any stronger planning expectation, missing writer or unproved recovery path. Observed behavior does not approve those outstanding product choices.
