---
id: ATS-PFM-CSH-010
scope: CAP-PFM-CSH-010
product_area: platform
module: console-shell
revision: 3
status: proposed
approved_by: null
approved_at: null
source_sha:
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  rhythm-v2-docs: 25e253cb434aac6603ee294e3ca197ab6c4bfd0b
scenarios:
  - id: ATS-PFM-CSH-010-01
    title: The new page waits for its requested workspace
    level: browser
    proves:
      - BR-CAP-PFM-CSH-010-01
    preconditions: A person can enter two workspaces and holds the first context.
    steps: Open work in the second while delaying its context response.
    expected: >-
      The destination waits; the first workspace body is not rendered as the
      second workspace’s content.
    negative: false
    data_needs: >-
      An isolated browser context with the stated identity, workspace and
      response fixtures.
    bound_to: []
    provenance: proposed
    source: 'react-console:components/console/tenant-id-gate.tsx:TenantIdGate'
    category: invariant
    test_sources: []
    action_evidence:
      provenance: proposed
      source: 'react-console:components/console/tenant-id-gate.tsx:TenantIdGate'
    assertion_evidence:
      provenance: proposed
      source: 'react-console:components/console/tenant-id-gate.tsx:TenantIdGate'
  - id: ATS-PFM-CSH-010-02
    title: An absent workspace identity yields not found
    level: browser
    proves:
      - BR-CAP-PFM-CSH-010-02
      - AS-JNY-PFM-CSH-003-03
    preconditions: The requested workspace identity is not registered.
    steps: Open that identity’s destination in the mock and development fixtures.
    expected: The workspace gate presents its not-found outcome.
    negative: true
    data_needs: >-
      An isolated browser context with the stated identity, workspace and
      response fixtures.
    bound_to:
      - TST-PFM-CSH-014
      - TST-PFM-CSH-009
    provenance: test
    source: >-
      react-console:e2e/mock/url-architecture.mock.spec.ts#an id no tenant has
      shows not found
    category: validation
    test_sources:
      - >-
        react-console:e2e/mock/url-architecture.mock.spec.ts#an id no tenant has
        shows not found
      - >-
        react-console:e2e/dev/url-architecture.dev.spec.ts#an id no tenant has
        shows not found
    action_evidence:
      provenance: test
      source: >-
        react-console:e2e/mock/url-architecture.mock.spec.ts#an id no tenant has
        shows not found
    assertion_evidence:
      provenance: test
      source: >-
        react-console:e2e/mock/url-architecture.mock.spec.ts#an id no tenant has
        shows not found
  - id: ATS-PFM-CSH-010-03
    title: Refusal selects only a reachable return destination
    level: unit
    proves:
      - BR-CAP-PFM-CSH-010-03
      - BR-CAP-PFM-CSH-010-04
      - AS-JNY-PFM-CSH-004-02
    preconditions: >-
      Fixtures cover a held workspace, another reachable workspace and no valid
      alternative.
    steps: Evaluate customer denial and its return-workspace choices.
    expected: >-
      The held workspace wins when usable, otherwise a reachable alternative
      wins, and no invalid return is offered.
    negative: true
    data_needs: Independent fixture inputs for the variants listed in this case.
    bound_to:
      - TST-PFM-CSH-003
    provenance: test
    source: >-
      react-console:components/console/__tests__/tenant-id-gate.test.tsx#leaves
      anyone else on the access-denied page
    category: permission
    test_sources:
      - >-
        react-console:components/console/__tests__/tenant-id-gate.test.tsx#leaves
        anyone else on the access-denied page
      - >-
        react-console:components/console/__tests__/tenant-id-gate.test.tsx#leads
        to the tenant the person is still in
      - >-
        react-console:components/console/__tests__/tenant-id-gate.test.tsx#leads
        to another tenant they can reach when they are in none, never the
        refused one
      - >-
        react-console:components/console/__tests__/tenant-id-gate.test.tsx#is
        not offered when they can reach no other tenant
    action_evidence:
      provenance: test
      source: >-
        react-console:components/console/__tests__/tenant-id-gate.test.tsx#leaves
        anyone else on the access-denied page
    assertion_evidence:
      provenance: test
      source: >-
        react-console:components/console/__tests__/tenant-id-gate.test.tsx#leaves
        anyone else on the access-denied page
  - id: ATS-PFM-CSH-010-04
    title: Disabled workspace entry remains an availability refusal
    level: unit
    proves:
      - BR-CAP-PFM-CSH-010-05
    preconditions: Staff and customer fixtures request a disabled workspace.
    steps: Evaluate the unavailable panel and each return choice.
    expected: >-
      The explanation names unavailability; staff can return to HQ and customers
      can return to another reachable workspace.
    negative: true
    data_needs: Independent fixture inputs for the variants listed in this case.
    bound_to:
      - TST-PFM-CSH-003
    provenance: test
    source: >-
      react-console:components/console/__tests__/tenant-id-gate.test.tsx#says
      the workspace is unavailable, never no access, with the way back for staff
    category: validation
    test_sources:
      - >-
        react-console:components/console/__tests__/tenant-id-gate.test.tsx#says
        the workspace is unavailable, never no access, with the way back for
        staff
      - >-
        react-console:components/console/__tests__/tenant-id-gate.test.tsx#leads
        a non-staff person to another workspace, never the unavailable one
    action_evidence:
      provenance: test
      source: >-
        react-console:components/console/__tests__/tenant-id-gate.test.tsx#says
        the workspace is unavailable, never no access, with the way back for
        staff
    assertion_evidence:
      provenance: test
      source: >-
        react-console:components/console/__tests__/tenant-id-gate.test.tsx#says
        the workspace is unavailable, never no access, with the way back for
        staff
  - id: ATS-PFM-CSH-010-05
    title: Direct startup reuses its named-workspace answer
    level: browser
    proves:
      - BR-CAP-PFM-CSH-010-09
    preconditions: The browser starts signed in at a direct workspace destination.
    steps: 'Capture the initial context request, gate entry and reload.'
    expected: >-
      The request names the destination workspace; content waits and the gate
      reuses the matching boot answer rather than requesting it again.
    negative: false
    data_needs: >-
      An isolated browser context with the stated identity, workspace and
      response fixtures.
    bound_to: []
    provenance: proposed
    source: 'react-console:lib/security-context/provider.tsx:openTenantId'
    category: rule
    test_sources: []
    action_evidence:
      provenance: proposed
      source: 'react-console:lib/security-context/provider.tsx:openTenantId'
    assertion_evidence:
      provenance: proposed
      source: 'react-console:lib/security-context/provider.tsx:openTenantId'
  - id: ATS-PFM-CSH-010-06
    title: A strict read refuses the wrong workspace answer
    category: invariant
    level: unit
    proves:
      - BR-CAP-PFM-CSH-010-01
      - INV-DOM-PFM-CSH-003-02
    preconditions: The requested workspace differs from the returned context.
    steps: Return a successful context response naming the default workspace instead.
    expected: >-
      The strict reader rejects the answer and emits a warning rather than
      confirming entry.
    negative: true
    data_needs: Independent in-memory fixtures for each listed input.
    bound_to:
      - TST-PFM-CSH-034
    provenance: test
    source: >-
      react-console:lib/security-context/tenant-id.test.ts#refuses a 200 about
      another tenant than the one asked for, warning in the console
    test_sources:
      - >-
        react-console:lib/security-context/tenant-id.test.ts#refuses a 200 about
        another tenant than the one asked for, warning in the console
    action_evidence:
      provenance: test
      source: >-
        react-console:lib/security-context/tenant-id.test.ts#refuses a 200 about
        another tenant than the one asked for, warning in the console
    assertion_evidence:
      provenance: test
      source: >-
        react-console:lib/security-context/tenant-id.test.ts#refuses a 200 about
        another tenant than the one asked for, warning in the console
  - id: ATS-PFM-CSH-010-07
    title: Unexpected entry failure remains a failure
    category: failure
    level: browser
    proves:
      - BR-CAP-PFM-CSH-010-08
    preconditions: The requested workspace read raises an unclassified error.
    steps: Open its destination and await the failed answer.
    expected: >-
      The gate displays the failure message without granting entry or
      substituting another working page.
    negative: true
    data_needs: >-
      A fresh browser context, isolated account fixtures and controlled
      responses for the listed transitions.
    bound_to: []
    provenance: proposed
    source: >-
      rhythm-v2-docs:specs/platform/console-shell/planning/capabilities/CAP-PFM-CSH-010-enter-the-workspace-an-address-names-or-learn-why-not.md
    test_sources: []
    action_evidence:
      provenance: proposed
      source: >-
        rhythm-v2-docs:specs/platform/console-shell/planning/capabilities/CAP-PFM-CSH-010-enter-the-workspace-an-address-names-or-learn-why-not.md
    assertion_evidence:
      provenance: proposed
      source: >-
        rhythm-v2-docs:specs/platform/console-shell/planning/capabilities/CAP-PFM-CSH-010-enter-the-workspace-an-address-names-or-learn-why-not.md
  - id: ATS-PFM-CSH-010-08
    title: Encoded workspace identity is compared without case
    category: validation
    level: browser
    proves:
      - BR-CAP-PFM-CSH-010-10
    preconditions: The URL encodes characters in a mixed-case reachable workspace identity.
    steps: Open the address against a lowercased matching context.
    expected: >-
      Entry decodes and lowercases the address identity before comparing it; no
      false mismatch remains.
    negative: false
    data_needs: >-
      A fresh browser context, isolated account fixtures and controlled
      responses for the listed transitions.
    bound_to: []
    provenance: proposed
    source: >-
      rhythm-v2-docs:specs/platform/console-shell/planning/capabilities/CAP-PFM-CSH-010-enter-the-workspace-an-address-names-or-learn-why-not.md
    test_sources: []
    action_evidence:
      provenance: proposed
      source: >-
        rhythm-v2-docs:specs/platform/console-shell/planning/capabilities/CAP-PFM-CSH-010-enter-the-workspace-an-address-names-or-learn-why-not.md
    assertion_evidence:
      provenance: proposed
      source: >-
        rhythm-v2-docs:specs/platform/console-shell/planning/capabilities/CAP-PFM-CSH-010-enter-the-workspace-an-address-names-or-learn-why-not.md
  - id: ATS-PFM-CSH-010-09
    title: Switch entry withholds the old record from the new workspace
    category: interaction
    level: browser
    proves:
      - BR-CAP-PFM-CSH-010-01
      - BR-CAP-PFM-CSH-011-07
    preconditions: A contact is open and the sandbox context read is delayed.
    steps: 'Select the sandbox, then complete entry.'
    expected: >-
      The pending destination shows no old contact body; successful entry clears
      SWR answers and mounts fresh workspace stores before the new list renders.
    negative: false
    data_needs: >-
      A fresh browser context, isolated account fixtures and controlled
      responses for the listed transitions.
    bound_to: []
    provenance: proposed
    source: >-
      rhythm-v2-docs:specs/platform/console-shell/planning/capabilities/CAP-PFM-CSH-010-enter-the-workspace-an-address-names-or-learn-why-not.md
    test_sources: []
    action_evidence:
      provenance: proposed
      source: >-
        rhythm-v2-docs:specs/platform/console-shell/planning/capabilities/CAP-PFM-CSH-010-enter-the-workspace-an-address-names-or-learn-why-not.md
    assertion_evidence:
      provenance: proposed
      source: >-
        rhythm-v2-docs:specs/platform/console-shell/planning/capabilities/CAP-PFM-CSH-010-enter-the-workspace-an-address-names-or-learn-why-not.md
evidence:
  - >-
    react-console at baf6dae: components/console/tenant-id-gate.tsx,
    components/console/__tests__/tenant-id-gate.test.tsx,
    lib/security-context/{tenant-id,left-tenant,boot}.ts,
    docs/url-architecture.md §2.2, §6, §11,
    e2e/mock/url-architecture.mock.spec.ts,
    e2e/dev/{url-architecture,initialisation}.dev.spec.ts.
  - >-
    services-platform at ad3f6a6: modules/security/aws/api/access.routes.ts
    (getMySecurityContext with tenant_id and preferred_tenant_id,
    getMySecurityContextInTenant; MOD-PFM-SEC).
  - >-
    rhythm-v2-docs at 25e253cb434aac6603ee294e3ca197ab6c4bfd0b: capability,
    related capabilities, domain objects, client lifecycles, workflows and prior
    OpenAI examinations; continuation coverage limitations are recorded in
    FND-PFM-CSH-060.
coverage:
  rule: covered
  transition: 'gap: FND-PFM-CSH-060'
  validation: covered
  permission: 'gap: FND-PFM-CSH-060'
  edge: 'gap: FND-PFM-CSH-060'
  failure: covered
  boundary: 'gap: FND-PFM-CSH-060'
  concurrency: 'gap: FND-PFM-CSH-060'
  invariant: 'gap: FND-PFM-CSH-060'
  interaction: 'gap: FND-PFM-CSH-060'
coverage_notes:
  rule:
    provenance: proposed
    source: >-
      ATS-PFM-CSH-010-01; ATS-PFM-CSH-010-02; ATS-PFM-CSH-010-03;
      ATS-PFM-CSH-010-04; ATS-PFM-CSH-010-05; ATS-PFM-CSH-010-06;
      ATS-PFM-CSH-010-07; ATS-PFM-CSH-010-08; ATS-PFM-CSH-010-09
    reason: >-
      Every mandatory rule has a proving scenario, including shared interaction
      cases; bindings identify execution separately.
  transition:
    provenance: unknown
    source: FND-PFM-CSH-060
    reason: >-
      The associated lifecycle has additional transitions beyond the specified
      cases.
  validation:
    provenance: proposed
    source: ATS-PFM-CSH-010-02; ATS-PFM-CSH-010-04; ATS-PFM-CSH-010-08
    reason: >-
      The listed scenarios specify this category; their bindings separately
      identify existing executable evidence.
  permission:
    provenance: unknown
    source: FND-PFM-CSH-060
    reason: >-
      The named permission keys still need a complete allowed, denied and scope
      matrix across their enforcement boundaries.
  edge:
    provenance: unknown
    source: FND-PFM-CSH-060
    reason: >-
      No dedicated scenario establishes this category; applicability and the
      required fixtures need review.
  failure:
    provenance: proposed
    source: ATS-PFM-CSH-010-07
    reason: >-
      The listed scenarios specify this category; their bindings separately
      identify existing executable evidence.
  boundary:
    provenance: unknown
    source: FND-PFM-CSH-060
    reason: >-
      No dedicated scenario establishes this category; applicability and the
      required fixtures need review.
  concurrency:
    provenance: unknown
    source: FND-PFM-CSH-060
    reason: >-
      No complete scenario matrix covers repeated events, overlapping reads or
      superseded answers for this capability.
  invariant:
    provenance: unknown
    source: FND-PFM-CSH-060
    reason: Associated object invariants remain without explicit proving scenarios.
  interaction:
    provenance: unknown
    source: FND-PFM-CSH-060
    reason: >-
      Related-capability combinations remain unspecified beyond the interactions
      listed.
design_obligations:
  - artifact: STATE-PFM-CSH-002
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/platform/console-shell/design/state-models/STATE-PFM-CSH-002-workspace-entry-from-an-address.md
    transitions:
      - ordinal: 1
        from: resolving
        to: entered
        provenance: test
        source: >-
          react-console:e2e/mock/url-architecture.mock.spec.ts#a record deep
          link survives a reload
        disposition: 'gap: FND-PFM-CSH-060'
      - ordinal: 2
        from: resolving
        to: waiting-after-leave
        provenance: observed
        source: >-
          react-console:components/console/tenant-id-gate.tsx:TenantIdGate
          (wasJustLeft, JUST_LEFT_RETRY_MS)
        disposition: 'gap: FND-PFM-CSH-060'
      - ordinal: 3
        from: waiting-after-leave
        to: resolving
        provenance: observed
        source: 'react-console:components/console/tenant-id-gate.tsx:TenantIdGate'
        disposition: 'gap: FND-PFM-CSH-060'
      - ordinal: 4
        from: resolving
        to: not-found
        provenance: test
        source: >-
          react-console:e2e/mock/url-architecture.mock.spec.ts#an id no tenant
          has shows not found
        disposition: 'gap: FND-PFM-CSH-060'
      - ordinal: 5
        from: resolving
        to: denied
        provenance: test
        source: >-
          react-console:components/console/__tests__/tenant-id-gate.test.tsx#leaves
          anyone else on the access-denied page
        disposition: 'gap: FND-PFM-CSH-060'
      - ordinal: 6
        from: denied
        to: sent-to-hq
        provenance: observed
        source: >-
          react-console:components/console/tenant-id-gate.tsx:deniedDestination,
          TenantIdGate
        disposition: 'gap: FND-PFM-CSH-060'
      - ordinal: 7
        from: resolving
        to: unavailable
        provenance: test
        source: >-
          react-console:components/console/__tests__/tenant-id-gate.test.tsx#says
          the workspace is unavailable, never no access, with the way back for
          staff
        disposition: 'gap: FND-PFM-CSH-060'
      - ordinal: 8
        from: resolving
        to: failed
        provenance: observed
        source: >-
          react-console:lib/security-context/tenant-id.ts:TenantIdUnconfirmedError;
          components/console/tenant-id-gate.tsx
        disposition: 'gap: FND-PFM-CSH-060'
      - ordinal: 9
        from: not-found
        to: resolving
        provenance: observed
        source: 'react-console:components/console/tenant-id-gate.tsx:rememberedRefusal'
        disposition: 'gap: FND-PFM-CSH-060'
      - ordinal: 10
        from: denied
        to: resolving
        provenance: observed
        source: 'react-console:components/console/tenant-id-gate.tsx:rememberedRefusal'
        disposition: 'gap: FND-PFM-CSH-060'
    note: >-
      The finding carries exhaustive transition execution coverage; overlapping
      scenario examples do not close the remaining lifecycle matrix.
interactions:
  - capability: CAP-PFM-CSH-011
    provenance: proposed
    source: ATS-PFM-CSH-010-09
  - capability: CAP-PFM-CSH-013
    provenance: unknown
    source: FND-PFM-CSH-060
  - capability: CAP-PFM-CSH-009
    provenance: unknown
    source: FND-PFM-CSH-060
workflow_obligations:
  - artifact: WF-PFM-CSH-001
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/platform/console-shell/design/workflows/WF-PFM-CSH-001-start-the-console-and-settle-the-working-context.md
    disposition: 'gap: FND-PFM-CSH-060'
    note: >-
      Review every hop, branch, failure and race with the cited capability
      scenarios; unexecuted combinations remain in the coverage finding.
  - artifact: WF-PFM-CSH-002
    provenance: documented
    source: >-
      rhythm-v2-docs:specs/platform/console-shell/design/workflows/WF-PFM-CSH-002-enter-the-workspace-an-address-names.md
    disposition: 'gap: FND-PFM-CSH-060'
    note: >-
      Review every hop, branch, failure and race with the cited capability
      scenarios; unexecuted combinations remain in the coverage finding.
---

# Enter the workspace named by a link: Capability Test Specification

## Coverage

The coverage map describes specified proof, not a passing run. Each mandatory rule below has a scenario or an explicit finding; a proposed scenario remains an execution obligation even when its expected outcome follows the pinned implementation.

| Mandatory Rule | Scenarios or Finding |
|---|---|
| `BR-CAP-PFM-CSH-010-01` | `ATS-PFM-CSH-010-01`, `ATS-PFM-CSH-010-06`, `ATS-PFM-CSH-010-09` |
| `BR-CAP-PFM-CSH-010-02` | `ATS-PFM-CSH-010-02` |
| `BR-CAP-PFM-CSH-010-03` | `ATS-PFM-CSH-010-03` |
| `BR-CAP-PFM-CSH-010-04` | `ATS-PFM-CSH-010-03` |
| `BR-CAP-PFM-CSH-010-05` | `ATS-PFM-CSH-010-04` |
| `BR-CAP-PFM-CSH-010-08` | `ATS-PFM-CSH-010-07` |
| `BR-CAP-PFM-CSH-010-09` | `ATS-PFM-CSH-010-05` |
| `BR-CAP-PFM-CSH-010-10` | `ATS-PFM-CSH-010-08` |

Entry needs every refusal, mismatched answers, encoded identifiers, unexpected failures, ten-second refusal-memory expiry and the six-second retry after leaving. Helper tests do not prove provider request reuse or mounting order.

## Interactions With Related Capabilities

The pending destination shows no old contact body; successful entry clears SWR answers and mounts fresh workspace stores before the new list renders.

The interaction rows cite the contracts they exercise. Related combinations without a complete case remain in the coverage finding, together with cross-capability workflows and permission boundaries. A helper assertion is bound only for its stated outcome; the full browser handoff remains proposed until a suite checks it.


Pinned source and exact test anchors are recorded in frontmatter. Test bindings record static assertion review and use the executable-suite register; no product test result is inferred from that review. The prior planning and design examinations supply context, while this continuation records the remaining proof obligations explicitly.
