---
id: CAP-PFM-OPS-014
title: Resolve a workspace’s application availability
feature: FEAT-PFM-OPS-04
product_area: platform
module: operations
revision: 1
status: draft
product_intent: confirmed
implementation_evidence: observed
supersedes: []
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
intent_sources:
  - >-
    services-platform:docs/proposals/application-access-and-entitlements.md#Status (built and accepted,
    2026-10-15)
  - 'services-platform:docs/proposals/application-access-and-entitlements.md#10.1 (D3, D10, D11)'
  - 'services-platform:docs/licensing.md#2. What this does NOT do (Andrew, 2026-10-13: "enforce everywhere")'
purpose: Combine licensing and operational readiness into a consistent application-access decision.
outcomes:
  - Application lists and authorization have a shared commercial and operational basis.
  - Always-available exceptions and ordinary readiness checks remain explicit.
concepts:
  - CON-PFM-OPS-004
  - CON-PFM-OPS-003
actors:
  - ACT-PFM-006
surfaces:
  - api
preconditions: []
postconditions:
  - Availability is resolved for the execution’s day and instant without storing a separate verdict.
permissions: []
rules:
  - id: BR-CAP-PFM-OPS-014-01
    proved_by: [ATS-PFM-OPS-012-15, ATS-PFM-OPS-014-01, ATS-PFM-OPS-014-09, ATS-PFM-OPS-014-10, ATS-PFM-OPS-014-14, ATS-PFM-OPS-015-10, TST-PFM-OPS-110]
    statement: >-
      Workspace availability includes always-available applications and licensed applications whose
      operational state is enabled.
    kind: calculation
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/licensing/tests/unit/availability/application-availability.spec.ts#answers the
      available ones, and only those, from the same resolution
    origin: 'services-platform:docs/proposals/application-access-and-entitlements.md#3.2'
  - id: BR-CAP-PFM-OPS-014-02
    proved_by: [ATS-PFM-OPS-011-13, ATS-PFM-OPS-014-02, ATS-PFM-OPS-014-08, TST-PFM-OPS-110]
    statement: >-
      Licence source resolution checks withhold, always-available status, current contract, grace contract,
      grant and expired contract in that order, regardless of decision recency.
    kind: calculation
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: observed
    source: 'services-platform:modules/licensing/services/availability/application-availability.ts:licenceStateOf'
    origin: none
  - id: BR-CAP-PFM-OPS-014-03
    proved_by: [ATS-PFM-OPS-014-03, ATS-PFM-OPS-014-13, TST-PFM-OPS-110]
    statement: >-
      Contract terms include their last calendar day, remain licensed throughout grace and become expired
      afterwards, while future terms provide no current licence.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/licensing/tests/unit/availability/application-availability.spec.ts#answers
      expired the day after the grace ends, which is when a licence really runs out
    origin: 'services-platform:docs/proposals/application-access-and-entitlements.md#D3'
  - id: BR-CAP-PFM-OPS-014-04
    proved_by: [ATS-PFM-OPS-014-04, TST-PFM-OPS-110]
    statement: >-
      A current term outranks grace or expired terms, and a grant can supply access after all contract
      coverage and grace have ended.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/licensing/tests/unit/availability/application-availability.spec.ts#falls back
      to a grant override once the contract has expired, which is a goodwill extension
    origin: none
  - id: BR-CAP-PFM-OPS-014-05
    proved_by: [ATS-PFM-OPS-014-05, ATS-PFM-OPS-014-15, TST-PFM-OPS-110]
    statement: >-
      Platform and Contacts & Organizations bypass operational readiness but remain subject to explicit
      withholds, while Rhythm HQ is available by rule outside workspace application records.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/licensing/tests/unit/availability/application-availability.spec.ts#lets a
      withhold beat always_available, which is the only way to take one of those away
    origin: >-
      services-platform:docs/proposals/application-access-and-entitlements.md#10.1 Decided by Andrew on
      2026-10-11 (D10, D11, 2026-10-12)
  - id: BR-CAP-PFM-OPS-014-06
    proved_by: [ATS-PFM-OPS-014-06, TST-PFM-OPS-110]
    statement: >-
      An unavailable application reports one commercial or operational refusal reason, covering absent
      licence, withhold, expiry, missing setup, setup in progress, failed setup or suspension.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/licensing/tests/unit/availability/application-availability.spec.ts#gives each
      unavailable one the reason its own half of the rule refused by
    origin: none
  - id: BR-CAP-PFM-OPS-014-07
    proved_by: []
    statement: >-
      A workspace without a HubSpot company resolves licensing solely from overrides and always-available
      status.
    kind: calculation
    enforced_at:
      - service
    must_prove: false
    provenance: test
    source: >-
      services-platform:modules/licensing/tests/unit/availability/application-availability.spec.ts#answers the
      same for a tenant with no licence windows as for one whose windows were not asked for
    origin: none
  - id: BR-CAP-PFM-OPS-014-08
    proved_by: [ATS-PFM-OPS-014-11, ATS-PFM-OPS-014-12]
    statement: >-
      The availability decision supplies authorization and application-list inputs in every environment, so
      unlicensed application requests are refused before the handler executes.
    kind: policy
    enforced_at:
      - service
    must_prove: false
    provenance: documented
    source: 'services-platform:docs/licensing.md#9. How a licence reaches the permission check'
    origin: 'services-platform:docs/licensing.md#2. What this does NOT do (Andrew, 2026-10-13)'
  - id: BR-CAP-PFM-OPS-014-09
    proved_by: [ATS-PFM-OPS-014-07, TST-PFM-OPS-112]
    statement: >-
      The catalog retains the retired commercial application key while product mappings grant Accounting &
      Billing under its replacement key.
    kind: lifecycle
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/licensing/tests/unit/catalog/product-grants.spec.ts#grant `accounting` and
      never the retired `collect`, which is the rename of 2026-10-13
    origin: >-
      services-platform:docs/licensing.md#1. The rule (Andrew, 2026-10-13: accounting is the key, collect
      retired)
  - id: BR-CAP-PFM-OPS-014-10
    proved_by: []
    statement: >-
      Websites and Marketing have no mapped commercial product grants, so their production licensing currently
      depends on explicit overrides.
    kind: policy
    enforced_at:
      - service
    must_prove: false
    provenance: documented
    source: 'services-platform:docs/licensing.md#1. The rule'
    origin: 'services-platform:docs/licensing.md#1. The rule (Andrew, 2026-10-20: Marketing key, no product yet)'
scenarios:
  - id: SC-CAP-PFM-OPS-014-01
    given: An enabled application’s contract ended four days earlier.
    when: Availability is resolved for the workspace day.
    then: The application remains in grace; a date beyond grace produces expiry.
    provenance: inferred
    source: >-
      services-platform:modules/licensing/tests/unit/availability/application-availability.spec.ts#answers
      in_grace the day after the window ends, which is still available (D3)
    note: >-
      This illustrative example combines behavior established by the cited test and the capability’s
      implementation evidence; it is not an independently bound end-to-end proof.
  - id: SC-CAP-PFM-OPS-014-02
    given: An always-available application has failed preparation.
    when: Availability is resolved.
    then: The failure state remains reported without making the application unavailable.
    provenance: inferred
    source: >-
      services-platform:modules/licensing/tests/unit/availability/application-availability.spec.ts#is
      available while its own provisioning is still failed, and reports that state all the same
    note: >-
      This illustrative example combines behavior established by the cited test and the capability’s
      implementation evidence; it is not an independently bound end-to-end proof.
edge_cases: []
constraints:
  - The pure availability resolver and the authorization query are separate implementations that must agree.
depends_on: []
related:
  - CAP-PFM-OPS-011
  - CAP-PFM-OPS-012
  - CAP-PFM-OPS-015
  - CAP-PFM-SEC-007
  - CAP-PFM-SEC-015
journeys:
  - JNY-PFM-OPS-004
  - JNY-PFM-OPS-005
open_questions: []
evidence:
  - >-
    services-platform at ad3f6a6: modules/licensing/services/availability/application-availability.ts,
    services/persistence/tenant-applications.ts (applicationAvailabilityOf, availableApplicationsOf),
    catalog/applications.ts, application-keys.ts, db/applications.table.ts; application-availability unit
    suite, tenant-applications queries and availability integration suites, applications table and persistence
    suites; docs/licensing.md §1, §2, §9.
  - 'services-platform at ad3f6a6, tables named by this capability: applications.table.ts.'
  - >-
    Examination: proposed acceptance matrices retain candidate test references; incomplete proof is recorded
    by FND-PFM-OPS-028.
controls: [TC-AVL-001, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-DAT-001, TC-DAT-003, TC-DAT-004, TC-LOG-001, TC-LOG-004, TC-LOG-005, TC-MON-001, TC-PI-001, TC-PI-003, 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]
exercised_by: [FAS-PFM-OPS-04-01, FAS-PFM-OPS-04-02, FAS-PFM-OPS-04-03, FAS-PFM-OPS-04-04, FAS-PFM-OPS-04-05]
suites: [TST-PFM-OPS-110, TST-PFM-OPS-112]
---

# Resolve a workspace’s application availability

## Purpose

Combine licensing and operational readiness into a consistent application-access decision.

## How It Works

The resolver gathers registered applications, the workspace’s overrides, company licence windows and operational records. It evaluates them for the execution’s current day and instant. An explicit withhold wins even for an otherwise always-available application. Current or grace contract coverage explains the licence before a grant is used as a fallback. Licensed applications then need an enabled operational state. Always-available applications preserve their reported operational state but bypass that readiness requirement. Unavailable results carry one explanatory reason. Authorization and application lists consume the availability decision, while personal application permission remains a separate concern.

## Relationships

Licence decisions feed availability alongside operational state; security applies the resulting access decision and the console explains it.
