---
id: WF-PFM-OPS-012
title: Suspend or resume a workspace application
product_area: platform
module: operations
revision: 1
status: draft
design_intent: confirmed
implementation_evidence: observed
inference: []
origin: >-
  services-platform:docs/proposals/application-access-and-entitlements.md#7.3 (built and accepted by Andrew
  2026-10-15)
trigger: Authorized staff suspend an enabled application with a reason or resume a suspended application.
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
implements:
  - CAP-PFM-OPS-015
  - CAP-PFM-OPS-013
moves:
  - STATE-PFM-OPS-006
crosses:
  - SVC-PFM-OPS-licensing
idempotency: >-
  A sequential repeat fails its starting-state check and requests no refresh. Concurrent requests can pass the
  same earlier check before either writes.
concurrency: >-
  Each write locks the row, but the service’s starting-state check is earlier. Stale checks can replace a
  newer operational decision; opposite actions do not both pass against one unchanged starting state.
hops:
  - 'n': 1
    actor_or_service: Licensing service
    action: >-
      Require the operational row and checked starting state, then write reasoned suspension or enabled
      resumption while retaining first enablement.
    anchor: >-
      services-platform:modules/licensing/services/enablement/provision-tenant-application.ts:suspendTenantApplication
    seam: sync
    on_failure: Refuse absent records or incompatible checked states before writing.
    left_inconsistent: No operational change results from the refused check.
    observer: Response is the observation surface.
    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
  - 'n': 2
    actor_or_service: Licensing service
    action: Request cache refresh after the operational write commits.
    anchor: >-
      services-platform:modules/security/services/authorizer-flush/submit-flush-job.ts:submitAuthorizerFlushJob
    seam: state_machine
    on_failure: Contain submission failure and leave expiry as fallback.
    left_inconsistent: Signed cached authority may briefly lag the state.
    observer: Refresh job’s record is the observation surface.
    provenance: observed
    source: >-
      services-platform:modules/security/services/authorizer-flush/submit-flush-job.ts:submitAuthorizerFlushJob
  - 'n': 3
    actor_or_service: Licensing API
    action: Attempt the security-history entry using the move’s widening direction.
    anchor: 'services-platform:modules/licensing/aws/api/licensing.routes.ts:suspendTenantApplication'
    seam: sync
    on_failure: Report history failure without undoing the state or already requested refresh.
    left_inconsistent: The operational move can remain unaudited.
    observer: Request’s error is the observation surface.
    provenance: observed
    source: 'services-platform:modules/licensing/aws/api/licensing.routes.ts:suspendTenantApplication'
branches: []
waits:
  - what: Access refresh
    how_long: 'until the refresh job runs, or the cache lifetime'
evidence:
  - >-
    services-platform at ad3f6a6: modules/licensing/aws/api/licensing.routes.ts (suspendTenantApplication,
    resumeTenantApplication), services/enablement/provision-tenant-application.ts,
    services/enablement/grant-licence-override.ts:recordTenantApplicationEvent.
  - 'react-console at baf6dae: components/console/hq/tenant-licensing-card.tsx.'
  - >-
    codex examination 2026-10-23: checked the pinned source anchors, planning references and enforcement
    boundaries; unresolved limits are recorded in module findings.
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-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-PI-001, TC-PI-002, TC-PI-003, TC-PI-004, TC-PI-005, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-VEN-001, TC-VEN-002, TC-VEN-003]
---

# Suspend or resume a workspace application

## What It Does

Suspension stops access without deleting prepared data or configuration. Resumption restores the operational enabled state and retains first enablement. Both staff actions request refresh before their route attempts security-history insertion.

## The Flow

```mermaid
flowchart TD
  H0["Require the operational row and checked starting state, then write reasoned suspension or enabled resumption while retaining first enablement."]
  H1["Request cache refresh after the operational write commits."]
  H0 --> H1
  H2["Attempt the security-history entry using the move’s widening direction."]
  H1 --> H2
```

## When Something Fails

The wrong checked state produces refusal. A later history error returns an error after the operational change and refresh request. This order differs from override handling, where a history failure prevents refresh. Neither path compensates the committed decision.

## Open Design Questions

Concurrent stale state checks remain a documented defect rather than an end-to-end serialization guarantee.
