---
id: CAP-PFM-SEC-007
title: Understand available workspace access
feature: FEAT-PFM-SEC-02
product_area: platform
module: security
revision: 1
status: draft
product_intent: confirmed
implementation_evidence: observed
supersedes: []
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
intent_sources:
  - >-
    services-platform:docs/security/console-authentication.md#Acceptance checkpoints (2026-10-10 Final
    acceptance)
  - >-
    services-platform:docs/security/security-administration.md#14 Acceptance checkpoints (2026-10-11
    Final acceptance)
  - >-
    services-platform:docs/security/security-administration.md#Naming the people a record mentions
    (approved by Andrew 2026-10-14)
  - >-
    services-platform:docs/security/application-access.md#The application access step, enforced
    everywhere
purpose: >-
  The signed-in person receives a workspace-specific explanation of the applications and actions the
  console can offer.
outcomes:
  - Console navigation reflects the person’s evaluated workspace access.
  - HQ authority appears separately from customer workspace permissions.
  - Record screens can resolve permitted people to names and pictures.
concepts:
  - CON-PFM-SEC-003
  - CON-PFM-SEC-002
actors:
  - ACT-PFM-002
  - ACT-PFM-003
  - ACT-PFM-004
  - ACT-PFM-005
surfaces:
  - console
  - portal
  - api
preconditions: []
postconditions: []
permissions:
  - key: platform.security-self.read
    where_checked: api
    scope: record
  - key: platform.application.access
    where_checked: console
    scope: tenant
rules:
  - id: BR-CAP-PFM-SEC-007-01
    proved_by: [ATS-PFM-SEC-007-01, TST-PFM-SEC-065]
    statement: >-
      Security-context and access-document reads identify the authenticated active caller, refuse
      inactive or unknown memberships, never return another person’s document and send no-store response
      guidance.
    kind: permission
    enforced_at:
      - api
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/security/tests/e2e/security-context.e2e.spec.js#answers the user the
      signed context names and no other, so one person can never read another’s document
    origin: >-
      services-platform:docs/security/console-authentication.md#Acceptance checkpoints (2026-10-10 Final
      acceptance)
  - id: BR-CAP-PFM-SEC-007-02
    proved_by: [ATS-PFM-SEC-007-02, TST-PFM-SEC-015, TST-PFM-SEC-065, TST-PFM-SEC-182]
    statement: >-
      Context refuses callers without an in-force assignment, including pending or future-only grants,
      using the no-access code that displays the console’s No Access page rather than another sign-in
      redirect.
    kind: policy
    enforced_at:
      - service
      - console
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/security/tests/integration/services/security-context/get-security-context.integration.spec.js#is
      refused their own document rather than answered an empty one
    origin: >-
      services-platform:docs/security/security-administration.md#14 Acceptance checkpoints (2026-10-11
      Final acceptance)
  - id: BR-CAP-PFM-SEC-007-03
    proved_by: [ATS-PFM-SEC-007-03, ATS-PFM-SEC-015-13, TST-PFM-SEC-065, TST-PFM-SEC-182]
    statement: >-
      Workspace permissions expand current catalog keys through effective grants with deny precedence,
      exclude staff-only and platform-scope authority, and list record grants without treating them as
      workspace-wide permission.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/security/tests/integration/services/security-context/get-security-context.integration.spec.js#takes
      the denied key out of the allowed keys, though another grant allows it
    origin: >-
      services-platform:docs/security/console-authentication.md#Acceptance checkpoints (2026-10-10 Final
      acceptance)
  - id: BR-CAP-PFM-SEC-007-04
    proved_by: [ATS-PFM-SEC-007-04, ATS-PFM-SEC-007-16, ATS-PFM-SEC-017-18, TST-PFM-SEC-182]
    statement: >-
      Staff context includes a separate HQ permission collection, which can be empty when staff grants
      have expired; non-staff context contains no HQ collection.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/security/tests/integration/services/security-context/get-security-context.integration.spec.js#expands
      the wildcard to every concrete key of the catalog in Rhythm HQ, the staff-only one included
    origin: 'services-platform:docs/hq/rhythm-hq-plan.md#D1'
  - id: BR-CAP-PFM-SEC-007-05
    proved_by: [ATS-PFM-SEC-007-05, TST-PFM-SEC-182]
    statement: >-
      Context presents operational workspaces reached by the caller’s customer grants and, for staff,
      live customer-access grants, excluding unavailable workspaces from ordinary customer choices.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/security/tests/integration/services/security-context/get-security-context.integration.spec.js#offers
      the customer’s own person only the tenants they can work in
    origin: >-
      services-platform:docs/security/console-authentication.md#Acceptance checkpoints (2026-10-10 Final
      acceptance)
  - id: BR-CAP-PFM-SEC-007-06
    proved_by: [ATS-PFM-SEC-007-06, TST-PFM-SEC-065, TST-PFM-SEC-230]
    statement: >-
      A strict workspace selection returns that workspace’s context or an access-denied/not-found
      response; an unavailable remembered preference instead falls back, and strict and preferred
      parameters cannot be combined.
    kind: validation
    enforced_at:
      - api
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/security/tests/e2e/security-context.e2e.spec.js#refuses the same tenant
      named strictly by tenant_id, the console URL never falling back
    origin: 'services-platform:docs/tenants/tenant-identity.md#The rules (Andrew, 2026-10-17)'
  - id: BR-CAP-PFM-SEC-007-07
    proved_by: [ATS-PFM-SEC-007-07, TST-PFM-SEC-020, TST-PFM-SEC-047, TST-PFM-SEC-065]
    statement: >-
      An application requires workspace licensing and the caller’s application-access permission;
      Platform and HQ are exempt from those application gates.
    kind: calculation
    enforced_at:
      - service
      - console
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/security/tests/e2e/security-context.e2e.spec.js#answers the application
      that follows from those keys
    origin: >-
      services-platform:docs/security/application-access.md#The application access step, enforced
      everywhere
  - id: BR-CAP-PFM-SEC-007-08
    proved_by: [ATS-PFM-SEC-006-12, ATS-PFM-SEC-007-08, ATS-PFM-SEC-007-14, TST-PFM-SEC-006]
    statement: >-
      The console waits for context before rendering application work or requesting its data, offers
      retry after a non-authorization failure and can renew an expired token before retrying.
    kind: policy
    enforced_at:
      - console
    must_prove: true
    provenance: test
    source: >-
      react-console:e2e/controlled/security-context.controlled.spec.ts#will not open the console when the
      Platform cannot say what somebody may do, and opens it on the retry
    origin: >-
      services-platform:docs/security/console-authentication.md#Acceptance checkpoints (2026-10-10 Final
      acceptance)
  - id: BR-CAP-PFM-SEC-007-09
    proved_by: [ATS-PFM-SEC-007-09, TST-PFM-SEC-015, TST-PFM-SEC-030]
    statement: >-
      Console navigation and actions omit unavailable permissions, and protected page access fails even
      when the user enters the address directly.
    kind: permission
    enforced_at:
      - console
    must_prove: true
    provenance: test
    source: >-
      react-console:e2e/dev/permissions.dev.spec.ts#denies a page whose permission nobody holds, when its
      URL is typed
    origin: >-
      services-platform:docs/security/security-administration.md#14 Acceptance checkpoints (2026-10-11
      Final acceptance)
  - id: BR-CAP-PFM-SEC-007-10
    proved_by: [ATS-PFM-SEC-007-10, TST-PFM-SEC-046]
    statement: >-
      The access document presents active and pending assignments, including derivation details, excludes
      revoked assignments and does not derive access from pending assignments.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: observed
    source: 'services-platform:modules/security/services/access/access-document.ts:getAccessDocument'
    origin: >-
      services-platform:docs/security/security-administration.md#14 Acceptance checkpoints (2026-10-11
      Final acceptance)
  - id: BR-CAP-PFM-SEC-007-11
    proved_by: [ATS-PFM-SEC-007-11, TST-PFM-SEC-068]
    statement: >-
      Console name lookup accepts 1–100 requested identities and returns only identifiers, display names
      and pictures for the customer’s console users, relevant portal members and Rhythm staff; other
      identities are omitted and portal callers are refused.
    kind: policy
    enforced_at:
      - api
      - service
    must_prove: true
    provenance: test
    source: >-
      services-platform:modules/security/tests/e2e/user-names.e2e.spec.js#leaves out another customer's
      user and an id that names nobody, rather than nulling or refusing them
    origin: >-
      services-platform:docs/security/security-administration.md#Naming the people a record mentions
      (approved by Andrew 2026-10-14)
  - id: BR-CAP-PFM-SEC-007-12
    proved_by: [ATS-PFM-SEC-007-15]
    statement: >-
      When a remembered workspace is unavailable, the console explains its fallback to the default; a
      staff deep link without customer-access authority returns to HQ with guidance.
    kind: policy
    enforced_at:
      - console
    must_prove: false
    provenance: test
    source: >-
      react-console:e2e/controlled/tenant-unavailable.controlled.spec.ts#falls back to the default
      tenant, with a word of explanation, rather than refusing access
    origin: none
  - id: BR-CAP-PFM-SEC-007-13
    proved_by: [ATS-PFM-SEC-007-13, TST-PFM-SEC-182, TST-PFM-SEC-199]
    statement: >-
      A successful interactive context read records recent authentication at most once per minute without
      changing membership status or version; unattended jobs skip the stamp and stamp failure is logged
      without failing the context read.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: observed
    source: 'services-platform:modules/security/services/access/security-context.ts:noteAuthentication'
    origin: none
scenarios:
  - id: SC-CAP-PFM-SEC-007-01
    given: An active member has no assigned access.
    when: The member signs in and loads context.
    then: The console presents No Access and a sign-out option without returning repeatedly to sign-in.
    provenance: test
    source: >-
      react-console:e2e/dev/permissions.dev.spec.ts#shows a person with no role the No Access screen, and
      does not loop back to the login screen
  - id: SC-CAP-PFM-SEC-007-02
    given: A workspace lacks an application licence.
    when: The member views navigation or follows that application’s deep link.
    then: Navigation omits the application and the deep link explains its unavailability.
    provenance: test
    source: >-
      react-console:e2e/mock/application-access.mock.spec.ts#a deep link into one of them says the
      application isn't available
edge_cases: []
constraints: []
depends_on:
  - CAP-PFM-SEC-015
related:
  - CAP-PFM-SEC-006
  - CAP-PFM-SEC-010
  - CAP-PFM-SEC-017
journeys:
  - JNY-PFM-SEC-002
open_questions: []
evidence:
  - >-
    Pinned services-platform references for the structured rows: docs/hq/rhythm-hq-plan.md;
    docs/security/application-access.md; docs/security/console-authentication.md;
    docs/security/security-administration.md; docs/tenants/tenant-identity.md;
    modules/security/services/access/access-document.ts;
    modules/security/services/access/security-context.ts;
    modules/security/tests/e2e/security-context.e2e.spec.js;
    modules/security/tests/e2e/user-names.e2e.spec.js;
    modules/security/tests/integration/services/security-context/get-security-context.integration.spec.js.
  - >-
    Pinned react-console references for the structured rows:
    e2e/controlled/security-context.controlled.spec.ts;
    e2e/controlled/tenant-unavailable.controlled.spec.ts; e2e/dev/permissions.dev.spec.ts;
    e2e/mock/application-access.mock.spec.ts.
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-CRY-001, TC-CRY-002, TC-CRY-003, TC-CRY-004, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-IAM-001, TC-IAM-002, TC-IAM-003, TC-IAM-004, TC-IAM-005, TC-LOG-001, TC-LOG-004, TC-LOG-005, TC-MON-001, TC-MON-003, TC-PI-001, TC-PI-002, TC-PI-003, TC-PI-004, TC-PI-005, TC-PRV-004, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-VEN-001, TC-VEN-002, TC-VEN-003]
exercised_by: [FAS-PFM-SEC-02-01, FAS-PFM-SEC-02-02, FAS-PFM-SEC-02-03, FAS-PFM-SEC-02-04]
suites: [TST-PFM-SEC-006, TST-PFM-SEC-015, TST-PFM-SEC-020, TST-PFM-SEC-030, TST-PFM-SEC-046, TST-PFM-SEC-047, TST-PFM-SEC-065, TST-PFM-SEC-068, TST-PFM-SEC-182, TST-PFM-SEC-199, TST-PFM-SEC-230]
---
# Understand available workspace access

## Purpose

People need to understand where they can work and which actions are available. The context gives the console an evaluated view of that access before it offers application work.

## How It Works

The console asks for context after sign-in and when selecting a workspace. A person can inspect the resulting workspace choices and available applications. A strict deep link remains tied to its named workspace rather than silently opening different work. A remembered choice can fall back with an explanation when it is no longer usable. The screen waits while context loads and supplies retry guidance when the service cannot answer. No Access gives a signed-in person a stable place to understand that an administrator still needs to grant access. Staff inspect HQ authority separately from customer work. The access document explains assignment state and derivation when a person needs more detail. Record displays use the limited name lookup to make creator and editor identities recognizable. Context reads also record recent authentication activity, a bookkeeping side effect with its own rule and tests.

## Relationships

- Sign-in supplies the established caller identity.
- The authorization evaluator determines permission results.
- Role assignment and staff-access grants supply the authority being explained.
