---
id: ATS-PFM-OPS-015
scope: CAP-PFM-OPS-015
product_area: platform
module: operations
revision: 2
status: proposed
approved_by: null
approved_at: null
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  macroservice-libraries: 54536a441935c6e09fdb7f96f0bec71c52ba4e03
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
scenarios:
  - id: ATS-PFM-OPS-015-01
    title: Retain a failed preparation and allow another attempt
    level: api
    proves:
      - BR-CAP-PFM-OPS-015-01
    preconditions: A declared participant first fails and later succeeds.
    steps: 'Prepare the application with a refusing participant, then request another preparation attempt.'
    expected: >-
      The failure explanation names the participant and repeated refusal remains recorded as failed
      preparation; successful recovery still requires its own complete executable proof.
    negative: false
    data_needs: Controlled records and caller contexts matching this scenario’s preconditions.
    bound_to: []
    provenance: proposed
    source: >-
      services-platform:modules/licensing/tests/integration/services/enablement/provision-tenant-application.integration.spec.js#says
      which participant could not run, in the reason an operator reads
    evidence_candidates:
      - >-
        services-platform:modules/licensing/tests/integration/services/enablement/provision-tenant-application.integration.spec.js#says
        which participant could not run, in the reason an operator reads
    category: transition
  - id: ATS-PFM-OPS-015-02
    title: Refuse invalid operational transitions
    level: api
    proves:
      - BR-CAP-PFM-OPS-015-02
    preconditions: 'Applications are enabled, suspended, failed and absent.'
    steps: 'Attempt retry, suspend and resume against each state.'
    expected: Only valid starting states permit the requested transitions.
    negative: true
    data_needs: Controlled records and caller contexts matching this scenario’s preconditions.
    bound_to:
      - TST-PFM-OPS-087
    provenance: test
    source: >-
      services-platform:modules/licensing/tests/integration/services/enablement/provision-tenant-application.integration.spec.js#refuses
      every move for an application the tenant has never been provisioned for
    evidence_candidates:
      - >-
        services-platform:modules/licensing/tests/integration/services/enablement/provision-tenant-application.integration.spec.js#refuses
        every move for an application the tenant has never been provisioned for
    category: validation
    binding_evidence:
      - >-
        services-platform:modules/licensing/tests/integration/services/enablement/provision-tenant-application.integration.spec.js#refuses
        every move for an application the tenant has never been provisioned for
  - id: ATS-PFM-OPS-015-03
    title: Reject unexplained suspension
    level: api
    proves:
      - BR-CAP-PFM-OPS-015-03
      - INV-DOM-PFM-OPS-004-02
    preconditions: An application is enabled.
    steps: Suspend without an explanation.
    expected: Validation refuses the request.
    negative: true
    data_needs: Controlled records and caller contexts matching this scenario’s preconditions.
    bound_to:
      - TST-PFM-OPS-081
    provenance: test
    source: >-
      services-platform:modules/licensing/tests/e2e/licensing.e2e.spec.js#refuses a suspension with no
      reason, with 400
    evidence_candidates:
      - >-
        services-platform:modules/licensing/tests/e2e/licensing.e2e.spec.js#refuses a suspension with no
        reason, with 400
    category: validation
    binding_evidence:
      - >-
        services-platform:modules/licensing/tests/e2e/licensing.e2e.spec.js#refuses a suspension with no
        reason, with 400
  - id: ATS-PFM-OPS-015-04
    title: Preserve data and original activation time
    level: api
    proves:
      - BR-CAP-PFM-OPS-015-04
    preconditions: An enabled application has data and a first-enabled timestamp.
    steps: Suspend and resume it.
    expected: Data remains and the original activation timestamp is retained.
    negative: false
    data_needs: Controlled records and caller contexts matching this scenario’s preconditions.
    bound_to: []
    provenance: proposed
    source: >-
      specs/platform/operations/planning/capabilities/CAP-PFM-OPS-015-bring-an-application-into-service-for-a-workspace-and-keep-it.md#rules
    evidence_candidates:
      - >-
        services-platform:modules/licensing/tests/integration/services/persistence/tenant-applications.integration.spec.js#keeps
        the instant it was first enabled through a suspension and a resumption
    category: invariant
  - id: ATS-PFM-OPS-015-05
    title: Separate state writes from later audit and invalidation
    level: api
    proves:
      - BR-CAP-PFM-OPS-015-05
    preconditions: 'Staff actions include valid transitions, repeated setup failure and a refusal.'
    steps: Execute the actions and inject later failures.
    expected: >-
      Committed state survives later failure, completed actions request invalidation and rejected
      transitions do not.
    negative: false
    data_needs: Controlled records and caller contexts matching this scenario’s preconditions.
    bound_to: []
    provenance: proposed
    source: >-
      services-platform:modules/licensing/tests/integration/services/enablement/provision-tenant-application.integration.spec.js#asks
      for a flush when provisioning is retried, even for a retry that failed again
    evidence_candidates:
      - >-
        services-platform:modules/licensing/tests/integration/services/enablement/provision-tenant-application.integration.spec.js#asks
        for a flush when provisioning is retried, even for a retry that failed again
    category: failure
  - id: ATS-PFM-OPS-015-06
    title: Backfill missing core states without resetting decisions
    level: api
    proves:
      - BR-CAP-PFM-OPS-015-06
      - INV-DOM-PFM-OPS-004-06
    preconditions: New and existing workspaces include missing and suspended core application rows.
    steps: Activate provisioning and run release backfill.
    expected: Missing states are enabled and suspended rows remain unchanged.
    negative: false
    data_needs: Controlled records and caller contexts matching this scenario’s preconditions.
    bound_to:
      - TST-PFM-OPS-104
    provenance: test
    source: >-
      services-platform:modules/licensing/tests/integration/services/persistence/tenant-applications.integration.spec.js#leaves
      a suspended row suspended, so a redeploy never undoes an operational decision
    evidence_candidates:
      - >-
        services-platform:modules/licensing/tests/integration/services/persistence/tenant-applications.integration.spec.js#leaves
        a suspended row suspended, so a redeploy never undoes an operational decision
    category: edge
    binding_evidence:
      - >-
        services-platform:modules/licensing/tests/integration/services/persistence/tenant-applications.integration.spec.js#leaves
        a suspended row suspended, so a redeploy never undoes an operational decision
  - id: ATS-PFM-OPS-015-07
    title: Refuse operational changes to readers
    level: api
    proves:
      - BR-CAP-PFM-OPS-015-07
    preconditions: A staff reader lacks licensing-management authority.
    steps: Request suspension.
    expected: The route refuses without an invalidation request.
    negative: true
    data_needs: Controlled records and caller contexts matching this scenario’s preconditions.
    bound_to:
      - TST-PFM-OPS-081
    provenance: test
    source: >-
      services-platform:modules/licensing/tests/e2e/licensing.e2e.spec.js#refuses a staff member who may
      only read, with 403
    evidence_candidates:
      - >-
        services-platform:modules/licensing/tests/e2e/licensing.e2e.spec.js#refuses a staff member who
        may only read, with 403
    category: permission
    binding_evidence:
      - >-
        services-platform:modules/licensing/tests/e2e/licensing.e2e.spec.js#refuses a staff member who
        may only read, with 403
  - id: ATS-PFM-OPS-015-08
    title: Remove workspace-owned licensing resources
    level: api
    proves:
      - BR-CAP-PFM-OPS-015-09
    preconditions: A retiring workspace has override and application-state rows.
    steps: Run the licensing participant purge.
    expected: Its declared licensing resources are removed.
    negative: false
    data_needs: Controlled records and caller contexts matching this scenario’s preconditions.
    bound_to: []
    provenance: proposed
    source: 'services-platform:modules/licensing/services/maintenance/tenant-participant.ts:licensingParticipant'
    evidence_candidates:
      - >-
        services-platform:modules/licensing/tests/integration/db/licence-overrides.table.integration.spec.js#leaves
        a tenant with no overrides at all once its rows are deleted with it
    category: transition
  - id: ATS-PFM-OPS-015-09
    title: Keep a commercial grant when preparation fails
    category: interaction
    level: api
    proves:
      - BR-CAP-PFM-OPS-011-05
      - BR-CAP-PFM-OPS-015-01
    exercises:
      - CAP-PFM-OPS-015
      - CAP-PFM-OPS-011
    preconditions: The application has no operational record and a participant refuses initialization.
    steps: Create a grant and inspect the commercial decision and preparation result.
    expected: The grant remains recorded while the application presents its failed readiness.
    negative: false
    data_needs: Isolated workspace records and caller contexts for both sides of the interaction.
    bound_to: []
    provenance: proposed
    source: >-
      services-platform:modules/licensing/tests/integration/services/enablement/provision-tenant-application.integration.spec.js#leaves
      the operational row exactly as it was, because the licence does not decide the state;
      services-platform:modules/licensing/tests/integration/services/enablement/provision-tenant-application.integration.spec.js#says
      which participant could not run, in the reason an operator reads; CAP-PFM-OPS-011; WF-PFM-OPS-009;
      WF-PFM-OPS-010; WF-PFM-OPS-011; WF-PFM-OPS-012; WF-PFM-OPS-016
  - id: ATS-PFM-OPS-015-10
    title: Separate licensing from operational resumption
    category: interaction
    level: api
    proves:
      - BR-CAP-PFM-OPS-014-01
      - BR-CAP-PFM-OPS-015-02
    exercises:
      - CAP-PFM-OPS-015
      - CAP-PFM-OPS-014
    preconditions: 'A licensed application is enabled, then suspended by staff.'
    steps: 'Resolve it before suspension, during suspension and after resumption.'
    expected: The commercial standing remains traceable while availability follows the operational change.
    negative: false
    data_needs: Isolated workspace records and caller contexts for both sides of the interaction.
    bound_to: []
    provenance: proposed
    source: >-
      services-platform:modules/licensing/tests/unit/availability/application-availability.spec.ts#answers
      the available ones, and only those, from the same resolution;
      services-platform:modules/licensing/tests/integration/services/enablement/provision-tenant-application.integration.spec.js#refuses
      every move for an application the tenant has never been provisioned for; CAP-PFM-OPS-014;
      WF-PFM-OPS-009; WF-PFM-OPS-010; WF-PFM-OPS-011; WF-PFM-OPS-012; WF-PFM-OPS-016
  - id: ATS-PFM-OPS-015-11
    title: Retain lifecycle failure evidence
    category: interaction
    level: api
    proves:
      - BR-CAP-PFM-OPS-015-01
    exercises:
      - CAP-PFM-OPS-015
      - CAP-PFM-SEC-003
    preconditions: A workspace lifecycle run reaches an interrupted execution outcome.
    steps: Reconcile it and inspect the lifecycle record alongside the job record.
    expected: Both records identify the failed work without silently reopening its final history.
    negative: false
    data_needs: Isolated workspace records and caller contexts for both sides of the interaction.
    bound_to: []
    provenance: proposed
    source: >-
      services-platform:modules/licensing/tests/integration/services/enablement/provision-tenant-application.integration.spec.js#says
      which participant could not run, in the reason an operator reads; CAP-PFM-SEC-003; WF-PFM-OPS-009;
      WF-PFM-OPS-010; WF-PFM-OPS-011; WF-PFM-OPS-012; WF-PFM-OPS-016
  - id: ATS-PFM-OPS-015-12
    title: Preserve retirement scope
    category: interaction
    level: api
    proves:
      - BR-CAP-PFM-OPS-015-09
    exercises:
      - CAP-PFM-OPS-015
      - CAP-PFM-SEC-004
    preconditions: A workspace is deleting and its deletion jobs must remain inspectable.
    steps: Purge operational resources and inspect the retained deletion runs.
    expected: Retirement removes owned resources while its retained work still explains the deletion.
    negative: false
    data_needs: Isolated workspace records and caller contexts for both sides of the interaction.
    bound_to: []
    provenance: proposed
    source: >-
      services-platform:modules/licensing/services/maintenance/tenant-participant.ts:licensingParticipant;
      CAP-PFM-SEC-004; WF-PFM-OPS-009; WF-PFM-OPS-010; WF-PFM-OPS-011; WF-PFM-OPS-012; WF-PFM-OPS-016
  - id: ATS-PFM-OPS-015-13
    title: Resolve competing first-row writers
    category: concurrency
    level: api
    proves:
      - BR-CAP-PFM-OPS-015-08
      - INV-DOM-PFM-OPS-004-01
    preconditions: An isolated workspace has no operational row for the application.
    steps: Run two provisioning-state writes concurrently.
    expected: Both writes finish and one operational row remains with its version advanced twice.
    negative: false
    data_needs: Run-owned records and controlled clocks or dependency responses named in the preconditions.
    bound_to:
      - TST-PFM-OPS-104
    provenance: test
    source: >-
      services-platform:modules/licensing/tests/integration/services/persistence/tenant-applications.integration.spec.js#lets
      both finish with one row, never a unique violation (a new workspace provisioning beside a
      development seed)
  - id: ATS-PFM-OPS-015-14
    title: Retain state reasons through valid operational moves
    category: transition
    level: api
    proves:
      - BR-CAP-PFM-OPS-015-01
      - BR-CAP-PFM-OPS-015-02
      - BR-CAP-PFM-OPS-015-03
    preconditions: An application can be prepared without participants and then deliberately suspended.
    steps: 'Prepare it, suspend it with a reason, then resume it.'
    expected: The service records each result and the resumed row clears the suspension explanation.
    negative: false
    data_needs: Run-owned records and controlled clocks or dependency responses named in the preconditions.
    bound_to:
      - TST-PFM-OPS-087
    provenance: test
    source: >-
      services-platform:modules/licensing/tests/integration/services/enablement/provision-tenant-application.integration.spec.js#the
      staff moves between operational states
    models:
      - STATE-PFM-OPS-006
    transitions:
      - 1
      - 3
      - 6
      - 7
  - id: ATS-PFM-OPS-015-15
    title: Remove readiness and exceptions while retaining purge evidence
    category: interaction
    level: api
    proves:
      - BR-CAP-PFM-OPS-015-09
    exercises:
      - CAP-PFM-OPS-001
      - CAP-PFM-OPS-010
      - CAP-PFM-OPS-012
      - CAP-PFM-OPS-015
    workflows:
      - WF-PFM-OPS-009
    preconditions: A deleting workspace has both staff exception rows and operational application states.
    steps: >-
      Run licensing resource removal alongside jobs and activity purge, then inspect the declared
      remaining inventory.
    expected: >-
      The removed workspace has no licensing-owned operational resources while retained deletion history
      remains inspectable.
    negative: false
    data_needs: >-
      Isolated workspace and run-owned lifecycle records, with a second linked workspace where shared
      company evidence is checked.
    bound_to: []
    provenance: proposed
    source: >-
      services-platform:modules/jobs/services/persistence/tenant-purges.ts:JOB_PURGE_RESOURCES;
      services-platform:modules/audit/tests/integration/services/persistence/audit-events.integration.spec.js#is
      refused by the database, so the purger is never a delete-by-tenant tool;
      services-platform:modules/licensing/services/maintenance/tenant-participant.ts:licensingParticipant
evidence:
  - >-
    Pinned capability rules, object invariants, state transitions and workflows are reviewed for testing
    obligations.
  - >-
    Executable bindings refer only to existing suites; no module executable suite runs during this
    documentation job.
coverage:
  rule: 'gap: FND-PFM-OPS-067'
  transition: covered
  validation: covered
  permission: covered
  edge: covered
  failure: covered
  boundary: 'gap: FND-PFM-OPS-067'
  concurrency: 'gap: FND-PFM-OPS-067'
  invariant: covered
  interaction: covered
coverage_notes:
  rule: No distinct general rule case is categorized here.
  boundary: Exact limits and cross-scope boundaries need dedicated proof.
  concurrency: >-
    The first-row collision scenario proves row uniqueness; it does not serialize participant work or
    prevent stale transition checks from overwriting a newer decision.
related_capabilities:
  - CAP-PFM-OPS-011
  - CAP-PFM-OPS-014
  - CAP-PFM-SEC-003
  - CAP-PFM-SEC-004
workflow_interactions:
  - WF-PFM-OPS-009
  - WF-PFM-OPS-010
  - WF-PFM-OPS-011
  - WF-PFM-OPS-012
  - WF-PFM-OPS-016
coverage_obligations:
  finding: FND-PFM-OPS-067
  uncovered_must_prove:
    - BR-CAP-PFM-OPS-015-10
  object_invariants_requiring_explicit_trace:
    - INV-DOM-PFM-OPS-004-03
    - INV-DOM-PFM-OPS-004-04
    - INV-DOM-PFM-OPS-004-05
    - INV-DOM-PFM-OPS-004-07
    - INV-DOM-PFM-OPS-004-08
  related_scenarios:
    - capabilities:
        - CAP-PFM-OPS-015
        - CAP-PFM-OPS-011
      scenario: ATS-PFM-OPS-015-09
    - capabilities:
        - CAP-PFM-OPS-015
        - CAP-PFM-OPS-014
      scenario: ATS-PFM-OPS-015-10
    - capabilities:
        - CAP-PFM-OPS-015
        - CAP-PFM-SEC-003
      scenario: ATS-PFM-OPS-015-11
    - capabilities:
        - CAP-PFM-OPS-015
        - CAP-PFM-SEC-004
      scenario: ATS-PFM-OPS-015-12
  unbound_scenarios:
    - ATS-PFM-OPS-015-01
    - ATS-PFM-OPS-015-04
    - ATS-PFM-OPS-015-05
    - ATS-PFM-OPS-015-08
    - ATS-PFM-OPS-015-09
    - ATS-PFM-OPS-015-10
    - ATS-PFM-OPS-015-11
    - ATS-PFM-OPS-015-12
    - ATS-PFM-OPS-015-15
  transition_review:
    - model: STATE-PFM-OPS-006
      transition: 2
      from: never provisioned
      to: enabled
      provenance: unknown
      source: FND-PFM-OPS-067
      note: >-
        Existing cases may exercise this move, but exhaustive transition-to-scenario trace is not
        established.
    - model: STATE-PFM-OPS-006
      transition: 4
      from: provisioning
      to: provisioning failed
      provenance: unknown
      source: FND-PFM-OPS-067
      note: >-
        Existing cases may exercise this move, but exhaustive transition-to-scenario trace is not
        established.
    - model: STATE-PFM-OPS-006
      transition: 5
      from: provisioning failed
      to: provisioning
      provenance: unknown
      source: FND-PFM-OPS-067
      note: >-
        Existing cases may exercise this move, but exhaustive transition-to-scenario trace is not
        established.
  permission_review:
    - key: hq.licensing.manage
      where_checked: api
      provenance: unknown
      source: FND-PFM-OPS-067
      note: >-
        Scenario-level audience checks do not establish every grant combination at each enforcement
        surface.
  gap_detail: >-
    Participant-free and repeated preparation, exact state-reason limits and stale service checks during
    competing moves need complete proof; insertion safety does not serialize the transition.
workflow_scenarios:
  WF-PFM-OPS-009:
    - ATS-PFM-OPS-001-17
    - ATS-PFM-OPS-010-13
    - ATS-PFM-OPS-012-19
    - ATS-PFM-OPS-015-15
  WF-PFM-OPS-010:
    - ATS-PFM-OPS-011-12
    - ATS-PFM-OPS-011-05
  WF-PFM-OPS-011:
    - ATS-PFM-OPS-015-09
  WF-PFM-OPS-012:
    - ATS-PFM-OPS-013-09
    - ATS-PFM-OPS-015-10
  WF-PFM-OPS-016:
    - ATS-PFM-OPS-011-15
    - ATS-PFM-OPS-014-12
---

# Prepare and operate workspace applications: Capability Test Specification

## Coverage

The category map distinguishes authored scenarios from unresolved proof obligations. A bound scenario names an existing executable suite; its recorded result remains unrun.

| Rule | Proof status |
|---|---|
| `BR-CAP-PFM-OPS-015-01` | `ATS-PFM-OPS-015-01`, `ATS-PFM-OPS-015-09`, `ATS-PFM-OPS-015-11`, `ATS-PFM-OPS-015-14` |
| `BR-CAP-PFM-OPS-015-02` | `ATS-PFM-OPS-015-02`, `ATS-PFM-OPS-015-10`, `ATS-PFM-OPS-015-14` |
| `BR-CAP-PFM-OPS-015-03` | `ATS-PFM-OPS-015-03`, `ATS-PFM-OPS-015-14` |
| `BR-CAP-PFM-OPS-015-04` | `ATS-PFM-OPS-015-04` |
| `BR-CAP-PFM-OPS-015-05` | `ATS-PFM-OPS-015-05` |
| `BR-CAP-PFM-OPS-015-06` | `ATS-PFM-OPS-015-06` |
| `BR-CAP-PFM-OPS-015-07` | `ATS-PFM-OPS-015-07` |
| `BR-CAP-PFM-OPS-015-09` | `ATS-PFM-OPS-015-08`, `ATS-PFM-OPS-015-12` |
| `BR-CAP-PFM-OPS-015-10` | no scenario: `FND-PFM-OPS-067` |

## Interactions With Related Capabilities

Keep a commercial grant when preparation fails. The grant remains recorded while the application presents its failed readiness.

Separate licensing from operational resumption. The commercial standing remains traceable while availability follows the operational change.

Retain lifecycle failure evidence. Both records identify the failed work without silently reopening its final history.

Preserve retirement scope. Retirement removes owned resources while its retained work still explains the deletion.

Remove readiness and exceptions while retaining purge evidence. The removed workspace has no licensing-owned operational resources while retained deletion history remains inspectable.

## Evidence and Boundaries

Pinned assertion sources support the listed executable bindings. Proposed cases retain the proof required beyond those boundaries. Structured obligations name incomplete object, transition and permission trace; row-level concurrency proof does not establish complete workflow serialization.
