---
id: ATS-PFM-TNL-003
scope: CAP-PFM-TNL-003
product_area: platform
module: tenant-lifecycle
revision: 2
status: proposed
approved_by: null
approved_at: null
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
scenarios:
  - id: ATS-PFM-TNL-003-01
    title: Snapshots distinguish authorized and absent reads
    level: api
    proves:
      - BR-CAP-PFM-TNL-003-01
    preconditions: Fixtures include a requested workspace and one without a provisioning job.
    steps: 'Read as staff and customer administrator, then inspect the no-job fixture.'
    expected: >-
      Staff obtain named steps; customer authority is refused and the no-job
      read returns not found.
    negative: true
    data_needs: >-
      Use the workspace, caller and collaborator fixtures declared by the bound
      tests.
    bound_to:
      - >-
        services-platform:modules/tenants/tests/e2e/tenant-provisioning.e2e.spec.js#shows
        every step completed, and names each one for the person reading it
      - >-
        services-platform:modules/tenants/tests/e2e/tenant-provisioning.e2e.spec.js#may
        not watch the provisioning of their own tenant
      - >-
        services-platform:modules/tenants/tests/e2e/tenant-provisioning.e2e.spec.js#answers
        404 for a tenant that was never provisioned by a request
    provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenant-provisioning.e2e.spec.js#shows
      every step completed, and names each one for the person reading it
  - id: ATS-PFM-TNL-003-02
    title: Failed construction retains partial resources
    level: api
    proves:
      - BR-CAP-PFM-TNL-003-02
    preconditions: A participant refuses its construction step.
    steps: Run the job and inspect its workspace and snapshot.
    expected: >-
      The workspace remains provisioning failed with the recorded refusal
      summary.
    negative: false
    data_needs: >-
      Use the workspace, caller and collaborator fixtures declared by the bound
      tests.
    bound_to:
      - >-
        services-platform:modules/tenants/tests/e2e/tenant-provisioning.e2e.spec.js#leaves
        the tenant saying its provisioning failed, which is what makes it
        retryable
      - >-
        services-platform:modules/tenants/tests/e2e/tenant-provisioning.e2e.spec.js#says
        so in the snapshot too, with the failure summary the task refused with
    provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenant-provisioning.e2e.spec.js#leaves
      the tenant saying its provisioning failed, which is what makes it
      retryable
  - id: ATS-PFM-TNL-003-03
    title: Recovery is limited to failed builds
    level: api
    proves:
      - BR-CAP-PFM-TNL-003-03
    preconditions: One build failed and another succeeded.
    steps: Request retry for each workspace.
    expected: >-
      The failed build gets a new attempt and can open; the successful build
      rejects retry.
    negative: true
    data_needs: >-
      Use the workspace, caller and collaborator fixtures declared by the bound
      tests.
    bound_to:
      - >-
        services-platform:modules/tenants/tests/e2e/tenant-provisioning.e2e.spec.js#answers
        200 and a new job to the retry
      - >-
        services-platform:modules/tenants/tests/e2e/tenant-provisioning.e2e.spec.js#leaves
        the tenant usable after the retry
      - >-
        services-platform:modules/tenants/tests/e2e/tenant-provisioning.e2e.spec.js#refuses
        to provision a tenant again whose provisioning did not fail
      - >-
        services-platform:modules/tenants/tests/e2e/tenant-provisioning.e2e.spec.js#may
        not provision their own tenant again
    provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenant-provisioning.e2e.spec.js#answers
      200 and a new job to the retry
  - id: ATS-PFM-TNL-003-04
    title: Outcome handling avoids normal replay
    level: api
    proves:
      - BR-CAP-PFM-TNL-003-04
    preconditions: Success and failure fixtures include requester notices.
    steps: Repeat closing tasks and failure reconciliation.
    expected: The delivered fixture notice is retained without another send.
    negative: false
    data_needs: >-
      Use the workspace, caller and collaborator fixtures declared by the bound
      tests.
    bound_to:
      - >-
        services-platform:modules/tenants/tests/integration/services/provisioning/provisioning-notices.integration.spec.js#sends
        the requester one message
      - >-
        services-platform:modules/tenants/tests/integration/services/provisioning/provisioning-notices.integration.spec.js#sends
        nothing a second time when the activate task runs again
      - >-
        services-platform:modules/tenants/tests/integration/services/provisioning/provisioning-notices.integration.spec.js#repeats
        the failure summary the job recorded, so the requester reads why
      - >-
        services-platform:modules/tenants/tests/integration/services/provisioning/provisioning-notices.integration.spec.js#sends
        nothing more when the reconciler applies the same consequence afterwards
    provenance: test
    source: >-
      services-platform:modules/tenants/tests/integration/services/provisioning/provisioning-notices.integration.spec.js#sends
      the requester one message
  - id: ATS-PFM-TNL-003-05
    title: Alerts accompany requester mail
    level: api
    proves:
      - BR-CAP-PFM-TNL-003-06
    preconditions: A successful build has an operations-channel fixture.
    steps: Inspect the alert and captured requester message.
    expected: Both channels identify the workspace and job outcome.
    negative: false
    data_needs: >-
      Use the workspace, caller and collaborator fixtures declared by the bound
      tests.
    bound_to:
      - >-
        services-platform:modules/tenants/tests/e2e/tenant-provisioning-alerts.e2e.spec.js#posts
        “Tenant ready” to the operations channel, with the message ts as the
        delivery’s provider reference
      - >-
        services-platform:modules/tenants/tests/e2e/tenant-provisioning-alerts.e2e.spec.js#tells
        the requester by e-mail as well: the alert is beside the notice, not
        instead of it
    provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenant-provisioning-alerts.e2e.spec.js#posts
      “Tenant ready” to the operations channel, with the message ts as the
      delivery’s provider reference
  - id: ATS-PFM-TNL-003-06
    title: Stranded repair is repeatable
    level: api
    proves:
      - BR-CAP-PFM-TNL-003-07
    preconditions: One workspace has a settled unstarted job and another a running job.
    steps: Run repair twice.
    expected: >-
      Only the stranded workspace becomes failed; its notice is handled once and
      the running workspace remains intact.
    negative: false
    data_needs: >-
      Use the workspace, caller and collaborator fixtures declared by the bound
      tests.
    bound_to:
      - >-
        services-platform:modules/tenants/tests/integration/services/provisioning/repair-stranded-provisioning.integration.spec.js#moves
        the stranded tenant to provisioning_failed, which makes it retryable and
        deletable again
      - >-
        services-platform:modules/tenants/tests/integration/services/provisioning/repair-stranded-provisioning.integration.spec.js#tells
        the staff member who asked for the tenant once, with the job’s own
        summary
      - >-
        services-platform:modules/tenants/tests/integration/services/provisioning/repair-stranded-provisioning.integration.spec.js#leaves
        a tenant whose provisioning is still running provisioning
      - >-
        services-platform:modules/tenants/tests/integration/services/provisioning/repair-stranded-provisioning.integration.spec.js#changes
        nothing about the repaired tenant on a second pass
      - >-
        services-platform:modules/tenants/tests/integration/lifecycle/reconciled-job-failure.integration.spec.js#moves
        the tenant to provisioning_failed, which is what makes it retryable and
        deletable again
    provenance: test
    source: >-
      services-platform:modules/tenants/tests/integration/services/provisioning/repair-stranded-provisioning.integration.spec.js#moves
      the stranded tenant to provisioning_failed, which makes it retryable and
      deletable again
  - id: ATS-PFM-TNL-003-07
    title: Ready mail links the requester to progress
    level: api
    proves:
      - AS-JNY-PFM-TNL-001-03
    preconditions: The successful provisioning journey captures requester mail.
    steps: Inspect the captured message and repeat outcome handling.
    expected: A single handled ready message includes the job link.
    negative: false
    data_needs: >-
      Use the workspace, caller and collaborator fixtures declared by the bound
      tests.
    bound_to:
      - >-
        services-platform:modules/tenants/tests/integration/services/provisioning/provisioning-notices.integration.spec.js#sends
        the requester one message
      - >-
        services-platform:modules/tenants/tests/integration/services/provisioning/provisioning-notices.integration.spec.js#links
        to the job’s own page in Rhythm HQ, so the requester can read the steps
    provenance: test
    source: >-
      services-platform:modules/tenants/tests/integration/services/provisioning/provisioning-notices.integration.spec.js#sends
      the requester one message
  - id: ATS-PFM-TNL-003-08
    title: Failure explanation supports staff recovery
    level: api
    proves:
      - AS-JNY-PFM-TNL-002-01
    preconditions: The recovery journey has a refused build.
    steps: Inspect its retained workspace and job snapshot.
    expected: >-
      The failed workspace and explanation remain available without removal of
      completed construction.
    negative: false
    data_needs: >-
      Use the workspace, caller and collaborator fixtures declared by the bound
      tests.
    bound_to:
      - >-
        services-platform:modules/tenants/tests/e2e/tenant-provisioning.e2e.spec.js#leaves
        the tenant saying its provisioning failed, which is what makes it
        retryable
      - >-
        services-platform:modules/tenants/tests/e2e/tenant-provisioning.e2e.spec.js#says
        so in the snapshot too, with the failure summary the task refused with
    provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenant-provisioning.e2e.spec.js#leaves
      the tenant saying its provisioning failed, which is what makes it
      retryable
  - id: ATS-PFM-TNL-003-09
    title: Recovery opens without duplicate construction
    level: api
    proves:
      - AS-JNY-PFM-TNL-002-02
    preconditions: The recovery journey retains completed steps from its failed attempt.
    steps: Run retry through activation.
    expected: >-
      The workspace opens and already completed participant work is not
      repeated.
    negative: false
    data_needs: >-
      Use the workspace, caller and collaborator fixtures declared by the bound
      tests.
    bound_to:
      - >-
        services-platform:modules/tenants/tests/integration/services/provisioning/provision-tenant.integration.spec.js#does
        the missing work and not the finished work when it is provisioned again
      - >-
        services-platform:modules/tenants/tests/e2e/tenant-provisioning.e2e.spec.js#leaves
        the tenant usable after the retry
    provenance: test
    source: >-
      services-platform:modules/tenants/tests/integration/services/provisioning/provision-tenant.integration.spec.js#does
      the missing work and not the finished work when it is provisioned again
evidence:
  - >-
    Inspected source:
    services-platform:modules/tenants/tests/e2e/tenant-provisioning.e2e.spec.js#shows
    every step completed, and names each one for the person reading it
  - >-
    Inspected source:
    services-platform:modules/tenants/tests/e2e/tenant-provisioning.e2e.spec.js#may
    not watch the provisioning of their own tenant
  - >-
    Inspected source:
    services-platform:modules/tenants/tests/e2e/tenant-provisioning.e2e.spec.js#answers
    404 for a tenant that was never provisioned by a request
  - >-
    Inspected source:
    services-platform:modules/tenants/tests/e2e/tenant-provisioning.e2e.spec.js#leaves
    the tenant saying its provisioning failed, which is what makes it retryable
  - >-
    Inspected source:
    services-platform:modules/tenants/tests/e2e/tenant-provisioning.e2e.spec.js#says
    so in the snapshot too, with the failure summary the task refused with
  - >-
    Inspected source:
    services-platform:modules/tenants/tests/e2e/tenant-provisioning.e2e.spec.js#answers
    200 and a new job to the retry
  - >-
    Inspected source:
    services-platform:modules/tenants/tests/e2e/tenant-provisioning.e2e.spec.js#leaves
    the tenant usable after the retry
  - >-
    Inspected source:
    services-platform:modules/tenants/tests/e2e/tenant-provisioning.e2e.spec.js#refuses
    to provision a tenant again whose provisioning did not fail
  - >-
    Inspected source:
    services-platform:modules/tenants/tests/e2e/tenant-provisioning.e2e.spec.js#may
    not provision their own tenant again
  - >-
    Inspected source:
    services-platform:modules/tenants/tests/integration/services/provisioning/provisioning-notices.integration.spec.js#sends
    the requester one message
  - >-
    Inspected source:
    services-platform:modules/tenants/tests/integration/services/provisioning/provisioning-notices.integration.spec.js#sends
    nothing a second time when the activate task runs again
  - >-
    Inspected source:
    services-platform:modules/tenants/tests/integration/services/provisioning/provisioning-notices.integration.spec.js#repeats
    the failure summary the job recorded, so the requester reads why
  - >-
    Inspected source:
    services-platform:modules/tenants/tests/integration/services/provisioning/provisioning-notices.integration.spec.js#sends
    nothing more when the reconciler applies the same consequence afterwards
  - >-
    Inspected source:
    services-platform:modules/tenants/tests/e2e/tenant-provisioning-alerts.e2e.spec.js#posts
    “Tenant ready” to the operations channel, with the message ts as the
    delivery’s provider reference
  - >-
    Inspected source:
    services-platform:modules/tenants/tests/e2e/tenant-provisioning-alerts.e2e.spec.js#tells
    the requester by e-mail as well: the alert is beside the notice, not instead
    of it
  - >-
    Inspected source:
    services-platform:modules/tenants/tests/integration/services/provisioning/repair-stranded-provisioning.integration.spec.js#moves
    the stranded tenant to provisioning_failed, which makes it retryable and
    deletable again
  - >-
    Inspected source:
    services-platform:modules/tenants/tests/integration/services/provisioning/repair-stranded-provisioning.integration.spec.js#tells
    the staff member who asked for the tenant once, with the job’s own summary
  - >-
    Inspected source:
    services-platform:modules/tenants/tests/integration/services/provisioning/repair-stranded-provisioning.integration.spec.js#leaves
    a tenant whose provisioning is still running provisioning
  - >-
    Inspected source:
    services-platform:modules/tenants/tests/integration/services/provisioning/repair-stranded-provisioning.integration.spec.js#changes
    nothing about the repaired tenant on a second pass
  - >-
    Inspected source:
    services-platform:modules/tenants/tests/integration/lifecycle/reconciled-job-failure.integration.spec.js#moves
    the tenant to provisioning_failed, which is what makes it retryable and
    deletable again
  - >-
    Inspected source:
    services-platform:modules/tenants/tests/integration/services/provisioning/provisioning-notices.integration.spec.js#links
    to the job’s own page in Rhythm HQ, so the requester can read the steps
  - >-
    Inspected source:
    services-platform:modules/tenants/tests/integration/services/provisioning/provision-tenant.integration.spec.js#does
    the missing work and not the finished work when it is provisioned again
---

# Understand and recover a workspace build: Acceptance Test Set

## Coverage

| Rule | Proved by |
|---|---|
| `BR-CAP-PFM-TNL-003-01` | `ATS-PFM-TNL-003-01` |
| `BR-CAP-PFM-TNL-003-02` | `ATS-PFM-TNL-003-02` |
| `BR-CAP-PFM-TNL-003-03` | `ATS-PFM-TNL-003-03` |
| `BR-CAP-PFM-TNL-003-04` | `ATS-PFM-TNL-003-04` |
| `BR-CAP-PFM-TNL-003-06` | `ATS-PFM-TNL-003-05` |
| `BR-CAP-PFM-TNL-003-07` | `ATS-PFM-TNL-003-06` |
