---
id: ATS-PFM-SEC-017
scope: CAP-PFM-SEC-017
product_area: platform
module: security
revision: 3
status: proposed
approved_by: null
approved_at: null
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
scenarios:
  - id: ATS-PFM-SEC-017-01
    title: Require the grant behind cross-customer assignments
    level: api
    proves:
      - BR-CAP-PFM-SEC-017-01
      - INV-DOM-PFM-SEC-003-17
    preconditions: 'Prepare a staff member, a non-staff member and active and revoked staff grants.'
    steps: >-
      Insert cross-customer assignments with no grant, with an active grant, with a revoked grant
      and for the non-staff member.
    expected: The database permits only the staff assignment named by an active grant.
    negative: true
    data_needs: Use the records described in the setup.
    bound_to:
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#refuses
        a staff member’s tenant-scoped assignment into another customer that no grant names
      - TST-PFM-SEC-190
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#admits
        the same assignment when an active grant names it
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#refuses
        it when the grant naming it has already been revoked
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#refuses
        the assignment of somebody who is not Rhythm staff into another customer, though an active
        grant names it
      - >-
        services-platform:modules/security/tests/e2e/approved-access.e2e.spec.js#refuses every
        console route to Rhythm’s own staff, whatever they hold at platform scope (rule S1)
      - TST-PFM-SEC-049
    provenance: test
    source: >-
      services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#refuses
      a staff member’s tenant-scoped assignment into another customer that no grant names
    category: invariant
    test_references:
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#refuses
        a staff member’s tenant-scoped assignment into another customer that no grant names
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#admits
        the same assignment when an active grant names it
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#refuses
        it when the grant naming it has already been revoked
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#refuses
        the assignment of somebody who is not Rhythm staff into another customer, though an active
        grant names it
      - >-
        services-platform:modules/security/tests/e2e/approved-access.e2e.spec.js#refuses every
        console route to Rhythm’s own staff, whatever they hold at platform scope (rule S1)
    action_evidence:
      provenance: test
      source: >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#refuses
        a staff member’s tenant-scoped assignment into another customer that no grant names
    assertion_evidence:
      provenance: test
      source: >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#refuses
        a staff member’s tenant-scoped assignment into another customer that no grant names
    binding_scope: >-
      The binding applies to the cited executable observations and their dependency boundary. Extra
      setup, operations or combinations in this scenario still require evidence before the whole
      scenario is qualified.
  - id: ATS-PFM-SEC-017-02
    title: Create a request without access
    level: api
    proves:
      - BR-CAP-PFM-SEC-017-02
    preconditions: Prepare a staff requester and workspace administrators.
    steps: >-
      Request thirty-one days, submit a valid request, repeat it and request while already holding
      access.
    expected: >-
      Reject excessive duration and duplicates; store the valid request without an assignment and
      notify administrators.
    negative: true
    data_needs: Use the records described in the setup.
    bound_to:
      - >-
        services-platform:modules/security/tests/e2e/approved-access.e2e.spec.js#refuses a request
        for more days than the maximum, 400
      - TST-PFM-SEC-049
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#materializes
        nothing, so asking grants no access at all
      - TST-PFM-SEC-186
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#e-mails
        the tenant’s administrators, and nobody else
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#refuses
        a second request for the same tenant, naming the one already open
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#refuses
        it 409 staff_access_grant_active, naming the tenant-level grant
    provenance: test
    source: >-
      services-platform:modules/security/tests/e2e/approved-access.e2e.spec.js#refuses a request for
      more days than the maximum, 400
    category: transition
    test_references:
      - >-
        services-platform:modules/security/tests/e2e/approved-access.e2e.spec.js#refuses a request
        for more days than the maximum, 400
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#materializes
        nothing, so asking grants no access at all
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#e-mails
        the tenant’s administrators, and nobody else
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#refuses
        a second request for the same tenant, naming the one already open
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#refuses
        it 409 staff_access_grant_active, naming the tenant-level grant
    action_evidence:
      provenance: test
      source: >-
        services-platform:modules/security/tests/e2e/approved-access.e2e.spec.js#refuses a request
        for more days than the maximum, 400
    assertion_evidence:
      provenance: test
      source: >-
        services-platform:modules/security/tests/e2e/approved-access.e2e.spec.js#refuses a request
        for more days than the maximum, 400
    binding_scope: >-
      The binding applies to the cited executable observations and their dependency boundary. Extra
      setup, operations or combinations in this scenario still require evidence before the whole
      scenario is qualified.
  - id: ATS-PFM-SEC-017-03
    title: Reserve access decisions for authorized administrators
    level: api
    proves:
      - BR-CAP-PFM-SEC-017-03
    preconditions: 'Prepare Power User, Read Only and Administrator callers.'
    steps: List and decide a waiting request with each caller.
    expected: >-
      Reject callers lacking the staff-access key without deciding the request; serve the
      Administrator.
    negative: true
    data_needs: Use the records described in the setup.
    bound_to:
      - >-
        services-platform:modules/security/tests/e2e/power-user-staff-access.e2e.spec.js#refuses the
        Power User every staff-access route, 403, for the missing key
      - TST-PFM-SEC-062
      - >-
        services-platform:modules/security/tests/e2e/power-user-staff-access.e2e.spec.js#leaves the
        request waiting after the Power User’s refused decisions
      - >-
        services-platform:modules/security/tests/e2e/built-in-administrator-staff-access.e2e.spec.js#refuses
        the built-in Read Only the list, 403, for the missing key
      - TST-PFM-SEC-050
      - >-
        services-platform:modules/security/tests/e2e/built-in-administrator-staff-access.e2e.spec.js#answers
        the built-in Administrator the list, 200
    provenance: test
    source: >-
      services-platform:modules/security/tests/e2e/power-user-staff-access.e2e.spec.js#refuses the
      Power User every staff-access route, 403, for the missing key
    category: permission
    test_references:
      - >-
        services-platform:modules/security/tests/e2e/power-user-staff-access.e2e.spec.js#refuses the
        Power User every staff-access route, 403, for the missing key
      - >-
        services-platform:modules/security/tests/e2e/power-user-staff-access.e2e.spec.js#leaves the
        request waiting after the Power User’s refused decisions
      - >-
        services-platform:modules/security/tests/e2e/built-in-administrator-staff-access.e2e.spec.js#refuses
        the built-in Read Only the list, 403, for the missing key
      - >-
        services-platform:modules/security/tests/e2e/built-in-administrator-staff-access.e2e.spec.js#answers
        the built-in Administrator the list, 200
    action_evidence:
      provenance: test
      source: >-
        services-platform:modules/security/tests/e2e/power-user-staff-access.e2e.spec.js#refuses the
        Power User every staff-access route, 403, for the missing key
    assertion_evidence:
      provenance: test
      source: >-
        services-platform:modules/security/tests/e2e/power-user-staff-access.e2e.spec.js#refuses the
        Power User every staff-access route, 403, for the missing key
    binding_scope: >-
      The binding applies to the cited executable observations and their dependency boundary. Extra
      setup, operations or combinations in this scenario still require evidence before the whole
      scenario is qualified.
  - id: ATS-PFM-SEC-017-04
    title: Cap approval at the requested duration
    level: api
    proves:
      - BR-CAP-PFM-SEC-017-04
      - INV-DOM-PFM-SEC-003-18
    preconditions: Prepare requests for two days.
    steps: 'Approve one for thirty days, decline another with a reason and withdraw a third as requester.'
    expected: 'Grant only two days, retain the decline reason and withdrawal actor, and notify the requester.'
    negative: false
    data_needs: Use the records described in the setup.
    bound_to:
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#gives
        the two days that were asked for, not the thirty the approver named
      - TST-PFM-SEC-186
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#refuses
        a duration outside the one-to-thirty-day range before it decides anything
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#stores
        a declined request with the reason the administrator gave and no assignment
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#records
        a withdrawal as the requester’s own decision, so it is not read as the customer refusing
    provenance: test
    source: >-
      services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#gives
      the two days that were asked for, not the thirty the approver named
    category: boundary
    test_references:
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#gives
        the two days that were asked for, not the thirty the approver named
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#refuses
        a duration outside the one-to-thirty-day range before it decides anything
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#stores
        a declined request with the reason the administrator gave and no assignment
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#records
        a withdrawal as the requester’s own decision, so it is not read as the customer refusing
    action_evidence:
      provenance: test
      source: >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#gives
        the two days that were asked for, not the thirty the approver named
    assertion_evidence:
      provenance: test
      source: >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#gives
        the two days that were asked for, not the thirty the approver named
    binding_scope: >-
      The binding applies to the cited executable observations and their dependency boundary. Extra
      setup, operations or combinations in this scenario still require evidence before the whole
      scenario is qualified.
  - id: ATS-PFM-SEC-017-05
    title: Grant access to an identified staff member
    level: api
    proves:
      - BR-CAP-PFM-SEC-017-05
    preconditions: 'Prepare an authorized customer administrator, staff address and unknown address.'
    steps: Grant workspace access to each address.
    expected: >-
      Activate and list the staff grant and send notices; reject the unknown address without a grant
      write.
    negative: false
    data_needs: Use the records described in the setup.
    bound_to:
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#writes
        an approved grant that is active and decided at once, by the administrator who gave it
      - TST-PFM-SEC-186
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#e-mails
        the staff member it was given to and the tenant’s administrators
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#refuses
        an address that belongs to nobody at Rhythm, and writes nothing
    provenance: test
    source: >-
      services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#writes
      an approved grant that is active and decided at once, by the administrator who gave it
    category: transition
    test_references:
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#writes
        an approved grant that is active and decided at once, by the administrator who gave it
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#e-mails
        the staff member it was given to and the tenant’s administrators
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#refuses
        an address that belongs to nobody at Rhythm, and writes nothing
    action_evidence:
      provenance: test
      source: >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#writes
        an approved grant that is active and decided at once, by the administrator who gave it
    assertion_evidence:
      provenance: test
      source: >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#writes
        an approved grant that is active and decided at once, by the administrator who gave it
    binding_scope: >-
      The binding applies to the cited executable observations and their dependency boundary. Extra
      setup, operations or combinations in this scenario still require evidence before the whole
      scenario is qualified.
  - id: ATS-PFM-SEC-017-06
    title: Revoke access without restoring standing grants
    level: api
    proves:
      - BR-CAP-PFM-SEC-017-06
      - INV-DOM-PFM-SEC-003-19
    preconditions: 'Prepare approved, emergency and standing grants.'
    steps: 'Revoke each, then reconcile standing access.'
    expected: >-
      Revoke each assignment and preserve the standing grant’s revoked state. Fresh evaluation loses
      the access.
    negative: true
    data_needs: Use the records described in the setup.
    bound_to:
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#revokes
        the assignment the grant materialized, so the access is gone at once
      - TST-PFM-SEC-186
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#revokes
        an emergency grant the customer never approved in the first place
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#revokes
        a standing grant, which a deploy would otherwise keep ensuring
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#leaves
        that standing grant revoked when standing access is ensured again
      - >-
        services-platform:modules/security/tests/e2e/approved-access.e2e.spec.js#takes the access
        away again when the administrator revokes it
      - TST-PFM-SEC-049
    provenance: test
    source: >-
      services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#revokes
      the assignment the grant materialized, so the access is gone at once
    category: transition
    test_references:
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#revokes
        the assignment the grant materialized, so the access is gone at once
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#revokes
        an emergency grant the customer never approved in the first place
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#revokes
        a standing grant, which a deploy would otherwise keep ensuring
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#leaves
        that standing grant revoked when standing access is ensured again
      - >-
        services-platform:modules/security/tests/e2e/approved-access.e2e.spec.js#takes the access
        away again when the administrator revokes it
    action_evidence:
      provenance: test
      source: >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#revokes
        the assignment the grant materialized, so the access is gone at once
    assertion_evidence:
      provenance: test
      source: >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#revokes
        the assignment the grant materialized, so the access is gone at once
    binding_scope: >-
      The binding applies to the cited executable observations and their dependency boundary. Extra
      setup, operations or combinations in this scenario still require evidence before the whole
      scenario is qualified.
  - id: ATS-PFM-SEC-017-07
    title: Validate emergency authority and request details
    level: api
    proves:
      - BR-CAP-PFM-SEC-017-07
      - INV-DOM-PFM-SEC-003-18
    preconditions: Prepare staff roles and a customer Administrator.
    steps: >-
      Try short reasons, missing tickets, invalid durations and staff-role choices; then open a
      valid request with Rhythm Administrator authority.
    expected: >-
      Reject invalid and unauthorized requests; activate valid emergency access and send its
      notices.
    negative: true
    data_needs: Use the records described in the setup.
    bound_to:
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#refuses
        a reason shorter than twenty characters
      - TST-PFM-SEC-190
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#refuses
        a missing ticket reference
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#refuses
        a duration past four hours, which is never extended
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#refuses
        a staff role, which is no role a tenant uses
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#refuses
        a Software Engineer, whose HQ reader keys and custom query table keys do not carry
        hq.emergency-access.use
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#e-mails
        the staff security list beside the tenant’s administrators, in the staff’s words
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#still
        opens the grant, and reports the notice as failed
    provenance: test
    source: >-
      services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#refuses
      a reason shorter than twenty characters
    category: validation
    test_references:
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#refuses
        a reason shorter than twenty characters
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#refuses
        a missing ticket reference
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#refuses
        a duration past four hours, which is never extended
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#refuses
        a staff role, which is no role a tenant uses
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#refuses
        a Software Engineer, whose HQ reader keys and custom query table keys do not carry
        hq.emergency-access.use
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#e-mails
        the staff security list beside the tenant’s administrators, in the staff’s words
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#still
        opens the grant, and reports the notice as failed
    action_evidence:
      provenance: test
      source: >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#refuses
        a reason shorter than twenty characters
    assertion_evidence:
      provenance: test
      source: >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#refuses
        a reason shorter than twenty characters
    binding_scope: >-
      The binding applies to the cited executable observations and their dependency boundary. Extra
      setup, operations or combinations in this scenario still require evidence before the whole
      scenario is qualified.
  - id: ATS-PFM-SEC-017-08
    title: Maintain role-derived standing grants
    level: api
    proves:
      - BR-CAP-PFM-SEC-017-08
      - INV-DOM-PFM-SEC-001-07
      - INV-DOM-PFM-SEC-003-19
    preconditions: 'Prepare administrators, Support and multiple customers.'
    steps: >-
      Add and remove the administrator role, suspend a holder, create a customer through the tested
      service and request emergency access where standing access exists.
    expected: >-
      Create the expected grants outside Rhythm’s customer, revoke them on lifecycle changes and
      submit flush requests. Reject redundant emergency access. The binding does not establish HQ
      customer-create reconciliation.
    negative: true
    data_needs: Use the records described in the setup.
    bound_to:
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/rhythm-administrator-standing-access.integration.spec.js#gives
        each Rhythm Administrator one active customer-level standing grant in every customer but
        Rhythm’s own
      - TST-PFM-SEC-191
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/rhythm-administrator-standing-access.integration.spec.js#ends
        every customer-level standing grant: revoked, by the system, for the role’s removal
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/rhythm-administrator-standing-access.integration.spec.js#ends
        every standing grant: revoked, by the system, for the suspension
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/rhythm-administrator-standing-access.integration.spec.js#gives
        every Rhythm Administrator its grant, the integration database’s own among them
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#refuses
        a request into a tenant of that customer 409 staff_access_grant_active, naming the
        customer-level grant
      - TST-PFM-SEC-186
    provenance: test
    source: >-
      services-platform:modules/security/tests/integration/services/staff-access/rhythm-administrator-standing-access.integration.spec.js#gives
      each Rhythm Administrator one active customer-level standing grant in every customer but
      Rhythm’s own
    category: transition
    test_references:
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/rhythm-administrator-standing-access.integration.spec.js#gives
        each Rhythm Administrator one active customer-level standing grant in every customer but
        Rhythm’s own
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/rhythm-administrator-standing-access.integration.spec.js#ends
        every customer-level standing grant: revoked, by the system, for the role’s removal
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/rhythm-administrator-standing-access.integration.spec.js#ends
        every standing grant: revoked, by the system, for the suspension
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/rhythm-administrator-standing-access.integration.spec.js#gives
        every Rhythm Administrator its grant, the integration database’s own among them
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#refuses
        a request into a tenant of that customer 409 staff_access_grant_active, naming the
        customer-level grant
    action_evidence:
      provenance: test
      source: >-
        services-platform:modules/security/tests/integration/services/staff-access/rhythm-administrator-standing-access.integration.spec.js#gives
        each Rhythm Administrator one active customer-level standing grant in every customer but
        Rhythm’s own
    assertion_evidence:
      provenance: test
      source: >-
        services-platform:modules/security/tests/integration/services/staff-access/rhythm-administrator-standing-access.integration.spec.js#gives
        each Rhythm Administrator one active customer-level standing grant in every customer but
        Rhythm’s own
    binding_scope: >-
      The binding applies to the cited executable observations and their dependency boundary. Extra
      setup, operations or combinations in this scenario still require evidence before the whole
      scenario is qualified.
  - id: ATS-PFM-SEC-017-09
    title: End only permitted grants from HQ
    level: api
    proves:
      - BR-CAP-PFM-SEC-017-09
    preconditions: Prepare the caller’s emergency and standing grants and another member’s grant.
    steps: Attempt to end each.
    expected: >-
      End the caller’s emergency grant and submit a flush request; preserve standing access and hide
      the other member’s grant as 404.
    negative: true
    data_needs: Use the records described in the setup.
    bound_to:
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#revokes
        the assignment, so the access ends with it
      - TST-PFM-SEC-190
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#submits
        an authorizer-cache flush naming the grant, so a cached answer does not outlive the access
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#refuses
        it 409 staff_access_grant_standing, naming the grant
      - >-
        services-platform:modules/security/tests/e2e/staff-access.e2e.spec.js#answers another staff
        member ending the grant 404
      - TST-PFM-SEC-066
      - >-
        services-platform:modules/security/tests/e2e/hq-staff-detail.e2e.spec.js#refuses ending
        another member’s standing grant 409 staff_access_grant_standing, naming the grant
      - TST-PFM-SEC-057
    provenance: test
    source: >-
      services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#revokes
      the assignment, so the access ends with it
    category: permission
    test_references:
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#revokes
        the assignment, so the access ends with it
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#submits
        an authorizer-cache flush naming the grant, so a cached answer does not outlive the access
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#refuses
        it 409 staff_access_grant_standing, naming the grant
      - >-
        services-platform:modules/security/tests/e2e/staff-access.e2e.spec.js#answers another staff
        member ending the grant 404
      - >-
        services-platform:modules/security/tests/e2e/hq-staff-detail.e2e.spec.js#refuses ending
        another member’s standing grant 409 staff_access_grant_standing, naming the grant
    action_evidence:
      provenance: test
      source: >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#revokes
        the assignment, so the access ends with it
    assertion_evidence:
      provenance: test
      source: >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#revokes
        the assignment, so the access ends with it
    binding_scope: >-
      The binding applies to the cited executable observations and their dependency boundary. Extra
      setup, operations or combinations in this scenario still require evidence before the whole
      scenario is qualified.
  - id: ATS-PFM-SEC-017-10
    title: Deny and record expired access
    level: api
    proves:
      - BR-CAP-PFM-SEC-017-10
    preconditions: Prepare an emergency grant past its validity limit.
    steps: 'Evaluate it, list grants and try to end it.'
    expected: 'Evaluation denies access, the read stores expiry, and a further end request is rejected.'
    negative: true
    data_needs: Use the records described in the setup.
    bound_to:
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#gives
        no access: the evaluator refuses the role’s keys in that tenant over the assignment
      - TST-PFM-SEC-190
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#is
        no longer among the caller’s active grants, and is stored as expired
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#cannot
        be ended, having ended already
    provenance: test
    source: >-
      services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#gives
      no access: the evaluator refuses the role’s keys in that tenant over the assignment
    category: boundary
    test_references:
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#gives
        no access: the evaluator refuses the role’s keys in that tenant over the assignment
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#is
        no longer among the caller’s active grants, and is stored as expired
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#cannot
        be ended, having ended already
    action_evidence:
      provenance: test
      source: >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#gives
        no access: the evaluator refuses the role’s keys in that tenant over the assignment
    assertion_evidence:
      provenance: test
      source: >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#gives
        no access: the evaluator refuses the role’s keys in that tenant over the assignment
    binding_scope: >-
      The binding applies to the cited executable observations and their dependency boundary. Extra
      setup, operations or combinations in this scenario still require evidence before the whole
      scenario is qualified.
  - id: ATS-PFM-SEC-017-11
    title: Isolate customer history and monthly reporting
    level: api
    proves:
      - BR-CAP-PFM-SEC-017-11
    preconditions: Prepare emergency grants across customers and adjacent months.
    steps: Read customer histories and the report for one month.
    expected: >-
      Histories contain only their own customer’s events; the report includes grants opened in the
      selected month with the referenced names.
    negative: true
    data_needs: Use the records described in the setup.
    bound_to:
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#shows
        the grant on the trail of the customer whose tenant it reaches
      - TST-PFM-SEC-190
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#never
        shows it on another customer’s trail
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#reports
        the grant opened in the month, with every name behind it
      - TST-PFM-SEC-186
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#leaves
        out the one opened in the next month, which that month’s report holds instead
      - >-
        services-platform:modules/security/tests/e2e/approved-access.e2e.spec.js#answers the monthly
        emergency report to staff, for the month asked
      - TST-PFM-SEC-049
    provenance: test
    source: >-
      services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#shows
      the grant on the trail of the customer whose tenant it reaches
    category: invariant
    test_references:
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#shows
        the grant on the trail of the customer whose tenant it reaches
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#never
        shows it on another customer’s trail
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#reports
        the grant opened in the month, with every name behind it
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#leaves
        out the one opened in the next month, which that month’s report holds instead
      - >-
        services-platform:modules/security/tests/e2e/approved-access.e2e.spec.js#answers the monthly
        emergency report to staff, for the month asked
    action_evidence:
      provenance: test
      source: >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#shows
        the grant on the trail of the customer whose tenant it reaches
    assertion_evidence:
      provenance: test
      source: >-
        services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#shows
        the grant on the trail of the customer whose tenant it reaches
    binding_scope: >-
      The binding applies to the cited executable observations and their dependency boundary. Extra
      setup, operations or combinations in this scenario still require evidence before the whole
      scenario is qualified.
  - id: ATS-PFM-SEC-017-12
    title: Apply customer security safeguards to staff
    level: api
    proves:
      - BR-CAP-PFM-SEC-017-14
    preconditions: Give staff a customer-level grant into a customer with one administrator.
    steps: >-
      Attempt to withdraw that administrator’s assignment or security policy, then operate in an
      ungranted customer.
    expected: Reject administrator lockout and refuse the ungranted customer operation.
    negative: true
    data_needs: Use the records described in the setup.
    bound_to:
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/staff-customer-administration.integration.spec.js#refuses
        staff withdrawing that administrator’s grant, as a lockout
      - TST-PFM-SEC-192
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/staff-customer-administration.integration.spec.js#refuses
        staff taking the Security Administrator policy off the role that makes them administrator,
        as a lockout
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/customer-named-security-routes.integration.spec.js#refuses
        the same route naming a customer the staff member holds no grant in
      - TST-PFM-SEC-187
    provenance: test
    source: >-
      services-platform:modules/security/tests/integration/services/staff-access/staff-customer-administration.integration.spec.js#refuses
      staff withdrawing that administrator’s grant, as a lockout
    category: permission
    test_references:
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/staff-customer-administration.integration.spec.js#refuses
        staff withdrawing that administrator’s grant, as a lockout
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/staff-customer-administration.integration.spec.js#refuses
        staff taking the Security Administrator policy off the role that makes them administrator,
        as a lockout
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/customer-named-security-routes.integration.spec.js#refuses
        the same route naming a customer the staff member holds no grant in
    action_evidence:
      provenance: test
      source: >-
        services-platform:modules/security/tests/integration/services/staff-access/staff-customer-administration.integration.spec.js#refuses
        staff withdrawing that administrator’s grant, as a lockout
    assertion_evidence:
      provenance: test
      source: >-
        services-platform:modules/security/tests/integration/services/staff-access/staff-customer-administration.integration.spec.js#refuses
        staff withdrawing that administrator’s grant, as a lockout
    binding_scope: >-
      The binding applies to the cited executable observations and their dependency boundary. Extra
      setup, operations or combinations in this scenario still require evidence before the whole
      scenario is qualified.
  - id: ATS-PFM-SEC-017-13
    title: Follow approved access through revocation
    level: browser
    proves:
      - AS-JNY-PFM-SEC-005-01
      - AS-JNY-PFM-SEC-005-02
      - AS-JNY-PFM-SEC-005-03
    preconditions: Prepare a staff requester and customer security administrator.
    steps: 'Request access, approve, enter the workspace and revoke.'
    expected: >-
      Fresh evaluation has no access before approval, permits it afterward and loses it after
      revocation; the mock console binding supplies banner evidence.
    negative: false
    data_needs: Use the records described in the setup.
    bound_to:
      - >-
        services-platform:modules/security/tests/e2e/approved-access.e2e.spec.js#grants the staff
        member nothing while the request is waiting
      - TST-PFM-SEC-049
      - >-
        services-platform:modules/security/tests/e2e/approved-access.e2e.spec.js#is what lets the
        staff member into the tenant, and only then
      - >-
        services-platform:modules/security/tests/e2e/approved-access.e2e.spec.js#takes the access
        away again when the administrator revokes it
      - >-
        react-console:e2e/mock/hq-lists.mock.spec.ts#without a grant asks for emergency access,
        validates it, then switches in with only the tenant's navigation
      - TST-PFM-SEC-022
    provenance: test
    source: >-
      services-platform:modules/security/tests/e2e/approved-access.e2e.spec.js#grants the staff
      member nothing while the request is waiting
    category: interaction
    test_references:
      - >-
        services-platform:modules/security/tests/e2e/approved-access.e2e.spec.js#grants the staff
        member nothing while the request is waiting
      - >-
        services-platform:modules/security/tests/e2e/approved-access.e2e.spec.js#is what lets the
        staff member into the tenant, and only then
      - >-
        services-platform:modules/security/tests/e2e/approved-access.e2e.spec.js#takes the access
        away again when the administrator revokes it
      - >-
        react-console:e2e/mock/hq-lists.mock.spec.ts#without a grant asks for emergency access,
        validates it, then switches in with only the tenant's navigation
    action_evidence:
      provenance: test
      source: >-
        services-platform:modules/security/tests/e2e/approved-access.e2e.spec.js#grants the staff
        member nothing while the request is waiting
    assertion_evidence:
      provenance: test
      source: >-
        services-platform:modules/security/tests/e2e/approved-access.e2e.spec.js#grants the staff
        member nothing while the request is waiting
    binding_scope: >-
      The binding applies to the cited executable observations and their dependency boundary. Extra
      setup, operations or combinations in this scenario still require evidence before the whole
      scenario is qualified.
  - id: ATS-PFM-SEC-017-14
    title: 'Staff access grant: requested to active'
    category: transition
    level: api
    proves:
      - BR-CAP-PFM-SEC-017-04
    state_model: STATE-PFM-SEC-007
    transition:
      from: requested
      to: active
      index: 0
    preconditions: >-
      Prepare a run-owned staff access grant in requested state with the authority and inputs
      required by the cited transition.
    steps:
      - do: Approve the request within its requested duration and inspect the matching assignment.
        expect: >-
          After the stated action, observe the staff access grant in active state. This case does
          not require an additional history event unless the transition explicitly defines one.
        provenance: proposed
        source:
          - 'services-platform:modules/security/services/staff-access/decide-tenant-access.ts'
          - >-
            services-platform at ad3f6a65: modules/security/db/staff-access-grants.table.ts;
            services/staff-access/*; docs/hq/rhythm-hq-plan.md §D2.
    expected: >-
      After the stated action, observe the staff access grant in active state. This case does not
      require an additional history event unless the transition explicitly defines one.
    negative: false
    data_needs: >-
      A disposable customer, workspace and named actor; a controllable clock where the transition
      depends on time.
    bound_to: []
    provenance: proposed
    source:
      - 'services-platform:modules/security/services/staff-access/decide-tenant-access.ts'
      - >-
        services-platform at ad3f6a65: modules/security/db/staff-access-grants.table.ts;
        services/staff-access/*; docs/hq/rhythm-hq-plan.md §D2.
    guard_cases: >-
      The caller can manage staff access; duration cannot exceed the requested duration or thirty
      days.
    side_effects_to_verify:
      - Create the scoped role assignment with matching validity
      - Record customer security history and send the decision notice after commit
    transition_assertion:
      state: active
      provenance: proposed
      source:
        - 'services-platform:modules/security/services/staff-access/decide-tenant-access.ts'
        - >-
          services-platform at ad3f6a65: modules/security/db/staff-access-grants.table.ts;
          services/staff-access/*; docs/hq/rhythm-hq-plan.md §D2.
    action_evidence:
      provenance: proposed
      source:
        - 'services-platform:modules/security/services/staff-access/decide-tenant-access.ts'
        - >-
          services-platform at ad3f6a65: modules/security/db/staff-access-grants.table.ts;
          services/staff-access/*; docs/hq/rhythm-hq-plan.md §D2.
    assertion_evidence:
      provenance: proposed
      source:
        - 'services-platform:modules/security/services/staff-access/decide-tenant-access.ts'
        - >-
          services-platform at ad3f6a65: modules/security/db/staff-access-grants.table.ts;
          services/staff-access/*; docs/hq/rhythm-hq-plan.md §D2.
    binding_scope: >-
      No executable assertion is bound. The scenario specifies proposed proof and does not establish
      implemented or passing behavior.
  - id: ATS-PFM-SEC-017-15
    title: 'Staff access grant: requested to declined'
    category: transition
    level: api
    proves:
      - BR-CAP-PFM-SEC-017-04
    state_model: STATE-PFM-SEC-007
    transition:
      from: requested
      to: declined
      index: 1
    preconditions: >-
      Prepare a run-owned staff access grant in requested state with the authority and inputs
      required by the cited transition.
    steps:
      - do: >-
          Decline one request as a customer administrator and withdraw another as its staff
          requester.
        expect: >-
          After the stated action, observe the staff access grant in declined state. This case does
          not require an additional history event unless the transition explicitly defines one.
        provenance: proposed
        source:
          - >-
            services-platform:modules/security/services/staff-access/request-tenant-access.ts:withdrawAccessRequest
          - >-
            services-platform at ad3f6a65: modules/security/db/staff-access-grants.table.ts;
            services/staff-access/*; docs/hq/rhythm-hq-plan.md §D2.
    expected: >-
      After the stated action, observe the staff access grant in declined state. This case does not
      require an additional history event unless the transition explicitly defines one.
    negative: false
    data_needs: >-
      A disposable customer, workspace and named actor; a controllable clock where the transition
      depends on time.
    bound_to: []
    provenance: proposed
    source:
      - >-
        services-platform:modules/security/services/staff-access/request-tenant-access.ts:withdrawAccessRequest
      - >-
        services-platform at ad3f6a65: modules/security/db/staff-access-grants.table.ts;
        services/staff-access/*; docs/hq/rhythm-hq-plan.md §D2.
    guard_cases: The request is still awaiting a decision.
    side_effects_to_verify:
      - Retain the reason and identify the withdrawing requester as decider
    transition_assertion:
      state: declined
      provenance: proposed
      source:
        - >-
          services-platform:modules/security/services/staff-access/request-tenant-access.ts:withdrawAccessRequest
        - >-
          services-platform at ad3f6a65: modules/security/db/staff-access-grants.table.ts;
          services/staff-access/*; docs/hq/rhythm-hq-plan.md §D2.
    action_evidence:
      provenance: proposed
      source:
        - >-
          services-platform:modules/security/services/staff-access/request-tenant-access.ts:withdrawAccessRequest
        - >-
          services-platform at ad3f6a65: modules/security/db/staff-access-grants.table.ts;
          services/staff-access/*; docs/hq/rhythm-hq-plan.md §D2.
    assertion_evidence:
      provenance: proposed
      source:
        - >-
          services-platform:modules/security/services/staff-access/request-tenant-access.ts:withdrawAccessRequest
        - >-
          services-platform at ad3f6a65: modules/security/db/staff-access-grants.table.ts;
          services/staff-access/*; docs/hq/rhythm-hq-plan.md §D2.
    binding_scope: >-
      No executable assertion is bound. The scenario specifies proposed proof and does not establish
      implemented or passing behavior.
  - id: ATS-PFM-SEC-017-16
    title: 'Staff access grant: active to expired'
    category: transition
    level: api
    proves:
      - BR-CAP-PFM-SEC-017-10
    state_model: STATE-PFM-SEC-007
    transition:
      from: active
      to: expired
      index: 2
    preconditions: >-
      Prepare a run-owned staff access grant in active state with the authority and inputs required
      by the cited transition.
    steps:
      - do: Advance to expiry and inspect both fresh access and the lazily settled grant.
        expect: >-
          After the stated action, observe the staff access grant in expired state. This case does
          not require an additional history event unless the transition explicitly defines one.
        provenance: proposed
        source:
          - >-
            services-platform:modules/security/services/persistence/staff-access-grants.ts:settleExpiredStaffAccessGrants
          - >-
            services-platform at ad3f6a65: modules/security/db/staff-access-grants.table.ts;
            services/staff-access/*; docs/hq/rhythm-hq-plan.md §D2.
    expected: >-
      After the stated action, observe the staff access grant in expired state. This case does not
      require an additional history event unless the transition explicitly defines one.
    negative: false
    data_needs: >-
      A disposable customer, workspace and named actor; a controllable clock where the transition
      depends on time.
    bound_to: []
    provenance: proposed
    source:
      - >-
        services-platform:modules/security/services/persistence/staff-access-grants.ts:settleExpiredStaffAccessGrants
      - >-
        services-platform at ad3f6a65: modules/security/db/staff-access-grants.table.ts;
        services/staff-access/*; docs/hq/rhythm-hq-plan.md §D2.
    guard_cases: Evaluation already excludes the expired assignment; a read settles the grant state.
    side_effects_to_verify: []
    transition_assertion:
      state: expired
      provenance: proposed
      source:
        - >-
          services-platform:modules/security/services/persistence/staff-access-grants.ts:settleExpiredStaffAccessGrants
        - >-
          services-platform at ad3f6a65: modules/security/db/staff-access-grants.table.ts;
          services/staff-access/*; docs/hq/rhythm-hq-plan.md §D2.
    action_evidence:
      provenance: proposed
      source:
        - >-
          services-platform:modules/security/services/persistence/staff-access-grants.ts:settleExpiredStaffAccessGrants
        - >-
          services-platform at ad3f6a65: modules/security/db/staff-access-grants.table.ts;
          services/staff-access/*; docs/hq/rhythm-hq-plan.md §D2.
    assertion_evidence:
      provenance: proposed
      source:
        - >-
          services-platform:modules/security/services/persistence/staff-access-grants.ts:settleExpiredStaffAccessGrants
        - >-
          services-platform at ad3f6a65: modules/security/db/staff-access-grants.table.ts;
          services/staff-access/*; docs/hq/rhythm-hq-plan.md §D2.
    binding_scope: >-
      No executable assertion is bound. The scenario specifies proposed proof and does not establish
      implemented or passing behavior.
  - id: ATS-PFM-SEC-017-17
    title: 'Staff access grant: active to revoked'
    category: transition
    level: api
    proves:
      - BR-CAP-PFM-SEC-017-06
    state_model: STATE-PFM-SEC-007
    transition:
      from: active
      to: revoked
      index: 3
    preconditions: >-
      Prepare a run-owned staff access grant in active state with the authority and inputs required
      by the cited transition.
    steps:
      - do: 'Revoke the active grant and inspect its assignment, history and flush submission.'
        expect: >-
          After the stated action, observe the staff access grant in revoked state. This case does
          not require an additional history event unless the transition explicitly defines one.
        provenance: proposed
        source:
          - 'services-platform:modules/security/services/staff-access/end-access-grant.ts'
          - >-
            services-platform at ad3f6a65: modules/security/db/staff-access-grants.table.ts;
            services/staff-access/*; docs/hq/rhythm-hq-plan.md §D2.
    expected: >-
      After the stated action, observe the staff access grant in revoked state. This case does not
      require an additional history event unless the transition explicitly defines one.
    negative: false
    data_needs: >-
      A disposable customer, workspace and named actor; a controllable clock where the transition
      depends on time.
    bound_to: []
    provenance: proposed
    source:
      - 'services-platform:modules/security/services/staff-access/end-access-grant.ts'
      - >-
        services-platform at ad3f6a65: modules/security/db/staff-access-grants.table.ts;
        services/staff-access/*; docs/hq/rhythm-hq-plan.md §D2.
    guard_cases: HQ end-access operations exclude standing grants; customer administration may revoke them.
    side_effects_to_verify:
      - Revoke the assignment and record security history atomically
      - Request a post-commit flush and send the revocation notice
    transition_assertion:
      state: revoked
      provenance: proposed
      source:
        - 'services-platform:modules/security/services/staff-access/end-access-grant.ts'
        - >-
          services-platform at ad3f6a65: modules/security/db/staff-access-grants.table.ts;
          services/staff-access/*; docs/hq/rhythm-hq-plan.md §D2.
    action_evidence:
      provenance: proposed
      source:
        - 'services-platform:modules/security/services/staff-access/end-access-grant.ts'
        - >-
          services-platform at ad3f6a65: modules/security/db/staff-access-grants.table.ts;
          services/staff-access/*; docs/hq/rhythm-hq-plan.md §D2.
    assertion_evidence:
      provenance: proposed
      source:
        - 'services-platform:modules/security/services/staff-access/end-access-grant.ts'
        - >-
          services-platform at ad3f6a65: modules/security/db/staff-access-grants.table.ts;
          services/staff-access/*; docs/hq/rhythm-hq-plan.md §D2.
    binding_scope: >-
      No executable assertion is bound. The scenario specifies proposed proof and does not establish
      implemented or passing behavior.
  - id: ATS-PFM-SEC-017-18
    title: Control staff access to customer workspaces with understand available workspace access
    category: interaction
    level: api
    proves:
      - BR-CAP-PFM-SEC-007-04
      - BR-CAP-PFM-SEC-017-06
    exercises:
      - CAP-PFM-SEC-017
      - CAP-PFM-SEC-007
    preconditions: A staff member has approved entry to one customer workspace.
    steps: >-
      Read HQ and workspace contexts, revoke the entry, and read again after cached authority
      expires.
    expected: HQ authority remains separate; the customer workspace is unavailable after revocation.
    negative: true
    data_needs: >-
      An isolated customer with two workspaces, ordinary and staff identities, and records owned by
      this run.
    bound_to: []
    provenance: proposed
    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
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#leaves
        that standing grant revoked when standing access is ensured again
    action_evidence:
      provenance: proposed
      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
        - >-
          services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#leaves
          that standing grant revoked when standing access is ensured again
    assertion_evidence:
      provenance: proposed
      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
        - >-
          services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#leaves
          that standing grant revoked when standing access is ensured again
    binding_scope: >-
      No executable assertion is bound. The scenario specifies proposed proof and does not establish
      implemented or passing behavior.
  - id: ATS-PFM-SEC-017-19
    title: Control staff access to customer workspaces with assign roles within a controlled scope
    category: interaction
    level: api
    proves:
      - BR-CAP-PFM-SEC-010-02
      - BR-CAP-PFM-SEC-017-14
    exercises:
      - CAP-PFM-SEC-017
      - CAP-PFM-SEC-010
    preconditions: A staff member has customer-level standing access but lacks a permission being delegated.
    steps: Attempt to grant that permission through customer security administration.
    expected: >-
      Standing entry does not bypass widening checks; the unavailable delegation is refused without
      an assignment.
    negative: true
    data_needs: >-
      An isolated customer with two workspaces, ordinary and staff identities, and records owned by
      this run.
    bound_to: []
    provenance: proposed
    source:
      - >-
        services-platform:modules/security/tests/unit/services/invitations/widening.spec.ts#refuses
        a scope the caller does not manage, and says which scope rather than which role
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/staff-customer-administration.integration.spec.js#refuses
        staff withdrawing that administrator’s grant, as a lockout
    action_evidence:
      provenance: proposed
      source:
        - >-
          services-platform:modules/security/tests/unit/services/invitations/widening.spec.ts#refuses
          a scope the caller does not manage, and says which scope rather than which role
        - >-
          services-platform:modules/security/tests/integration/services/staff-access/staff-customer-administration.integration.spec.js#refuses
          staff withdrawing that administrator’s grant, as a lockout
    assertion_evidence:
      provenance: proposed
      source:
        - >-
          services-platform:modules/security/tests/unit/services/invitations/widening.spec.ts#refuses
          a scope the caller does not manage, and says which scope rather than which role
        - >-
          services-platform:modules/security/tests/integration/services/staff-access/staff-customer-administration.integration.spec.js#refuses
          staff withdrawing that administrator’s grant, as a lockout
    binding_scope: >-
      No executable assertion is bound. The scenario specifies proposed proof and does not establish
      implemented or passing behavior.
  - id: ATS-PFM-SEC-017-20
    title: Control staff access to customer workspaces with administer rhythm staff memberships
    category: interaction
    level: api
    proves:
      - BR-CAP-PFM-SEC-016-05
      - BR-CAP-PFM-SEC-017-08
    exercises:
      - CAP-PFM-SEC-017
      - CAP-PFM-SEC-016
    preconditions: A Rhythm Administrator has standing access to a customer.
    steps: >-
      Suspend the staff membership and inspect customer entry and its standing assignments;
      reinstate through authorized staff administration.
    expected: >-
      Suspension ends usable customer entry; fresh access follows the retained or reconciled
      assignment state rather than staff status alone.
    negative: false
    data_needs: >-
      An isolated customer with two workspaces, ordinary and staff identities, and records owned by
      this run.
    bound_to: []
    provenance: proposed
    source:
      - 'services-platform:modules/security/aws/api/hq-staff.routes.ts:hqStaffRoutes'
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/rhythm-administrator-standing-access.integration.spec.js#gives
        each Rhythm Administrator one active customer-level standing grant in every customer but
        Rhythm’s own
    action_evidence:
      provenance: proposed
      source:
        - 'services-platform:modules/security/aws/api/hq-staff.routes.ts:hqStaffRoutes'
        - >-
          services-platform:modules/security/tests/integration/services/staff-access/rhythm-administrator-standing-access.integration.spec.js#gives
          each Rhythm Administrator one active customer-level standing grant in every customer but
          Rhythm’s own
    assertion_evidence:
      provenance: proposed
      source:
        - 'services-platform:modules/security/aws/api/hq-staff.routes.ts:hqStaffRoutes'
        - >-
          services-platform:modules/security/tests/integration/services/staff-access/rhythm-administrator-standing-access.integration.spec.js#gives
          each Rhythm Administrator one active customer-level standing grant in every customer but
          Rhythm’s own
    binding_scope: >-
      No executable assertion is bound. The scenario specifies proposed proof and does not establish
      implemented or passing behavior.
  - id: ATS-PFM-SEC-017-21
    title: Control staff access to customer workspaces with establish and administer a customer
    category: interaction
    level: api
    proves:
      - BR-CAP-PFM-SEC-001-12
      - BR-CAP-PFM-SEC-017-08
    exercises:
      - CAP-PFM-SEC-017
      - CAP-PFM-SEC-001
    preconditions: A customer without workspaces has a standing staff grant.
    steps: Delete the customer and inspect retained staff-access records.
    expected: >-
      The customer and its standing grant are removed together; no usable assignment reaches the
      removed customer.
    negative: false
    data_needs: >-
      An isolated customer with two workspaces, ordinary and staff identities, and records owned by
      this run.
    bound_to: []
    provenance: proposed
    source:
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/rhythm-administrator-standing-access.integration.spec.js#deletes
        the customer
      - >-
        services-platform:modules/security/tests/integration/services/staff-access/rhythm-administrator-standing-access.integration.spec.js#gives
        each Rhythm Administrator one active customer-level standing grant in every customer but
        Rhythm’s own
    action_evidence:
      provenance: proposed
      source:
        - >-
          services-platform:modules/security/tests/integration/services/staff-access/rhythm-administrator-standing-access.integration.spec.js#deletes
          the customer
        - >-
          services-platform:modules/security/tests/integration/services/staff-access/rhythm-administrator-standing-access.integration.spec.js#gives
          each Rhythm Administrator one active customer-level standing grant in every customer but
          Rhythm’s own
    assertion_evidence:
      provenance: proposed
      source:
        - >-
          services-platform:modules/security/tests/integration/services/staff-access/rhythm-administrator-standing-access.integration.spec.js#deletes
          the customer
        - >-
          services-platform:modules/security/tests/integration/services/staff-access/rhythm-administrator-standing-access.integration.spec.js#gives
          each Rhythm Administrator one active customer-level standing grant in every customer but
          Rhythm’s own
    binding_scope: >-
      No executable assertion is bound. The scenario specifies proposed proof and does not establish
      implemented or passing behavior.
evidence:
  - >-
    Pinned services-platform references for the structured rows:
    modules/security/tests/e2e/approved-access.e2e.spec.js;
    modules/security/tests/e2e/built-in-administrator-staff-access.e2e.spec.js;
    modules/security/tests/e2e/hq-staff-detail.e2e.spec.js;
    modules/security/tests/e2e/power-user-staff-access.e2e.spec.js;
    modules/security/tests/e2e/staff-access.e2e.spec.js;
    modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js;
    modules/security/tests/integration/services/staff-access/customer-named-security-routes.integration.spec.js;
    modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js;
    modules/security/tests/integration/services/staff-access/rhythm-administrator-standing-access.integration.spec.js;
    modules/security/tests/integration/services/staff-access/staff-customer-administration.integration.spec.js.
  - 'Pinned react-console references for the structured rows: e2e/mock/hq-lists.mock.spec.ts.'
  - >-
    Testing back-fill reviews the pinned suite assertions, related capabilities, domain invariants,
    state transitions and workflow failure boundaries. New unbound rows remain proposed.
coverage:
  rule: 'gap: FND-PFM-SEC-074'
  transition: covered
  validation: covered
  permission: covered
  edge: 'gap: FND-PFM-SEC-074'
  failure: 'gap: FND-PFM-SEC-074'
  boundary: covered
  concurrency: 'gap: FND-PFM-SEC-074'
  invariant: covered
  interaction: covered
coverage_notes:
  rule: No scenario isolates this category. The referenced finding retains the missing design proof.
  edge: No scenario isolates this category. The referenced finding retains the missing design proof.
  failure: No scenario isolates this category. The referenced finding retains the missing design proof.
  concurrency: No scenario isolates this category. The referenced finding retains the missing design proof.
invariant_proofs:
  - scenario: ATS-PFM-SEC-017-01
    proves:
      - INV-DOM-PFM-SEC-003-17
    provenance: test
    source: >-
      services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#refuses
      a staff member’s tenant-scoped assignment into another customer that no grant names
    proof_scope: >-
      Only the cited assertions support this invariant mapping; a source reference does not
      establish a passing execution.
  - scenario: ATS-PFM-SEC-017-04
    proves:
      - INV-DOM-PFM-SEC-003-18
    provenance: test
    source: >-
      services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#gives
      the two days that were asked for, not the thirty the approver named
    proof_scope: >-
      The cited check exercises one part of an invariant whose full guarantee remains unknown. It
      supplies no proof of concurrent exclusion or unrestricted history protection.
  - scenario: ATS-PFM-SEC-017-06
    proves:
      - INV-DOM-PFM-SEC-003-19
    provenance: test
    source: >-
      services-platform:modules/security/tests/integration/services/staff-access/approved-tenant-access.integration.spec.js#revokes
      the assignment the grant materialized, so the access is gone at once
    proof_scope: >-
      Only the cited assertions support this invariant mapping; a source reference does not
      establish a passing execution.
  - scenario: ATS-PFM-SEC-017-07
    proves:
      - INV-DOM-PFM-SEC-003-18
    provenance: test
    source: >-
      services-platform:modules/security/tests/integration/services/staff-access/open-emergency-access.integration.spec.js#refuses
      a reason shorter than twenty characters
    proof_scope: >-
      The cited check exercises one part of an invariant whose full guarantee remains unknown. It
      supplies no proof of concurrent exclusion or unrestricted history protection.
  - scenario: ATS-PFM-SEC-017-08
    proves:
      - INV-DOM-PFM-SEC-001-07
      - INV-DOM-PFM-SEC-003-19
    provenance: test
    source: >-
      services-platform:modules/security/tests/integration/services/staff-access/rhythm-administrator-standing-access.integration.spec.js#gives
      each Rhythm Administrator one active customer-level standing grant in every customer but
      Rhythm’s own
    proof_scope: >-
      Only the cited assertions support this invariant mapping; a source reference does not
      establish a passing execution.
permission_proof_review:
  - key: hq.tenant-access.request
    scenario_candidates:
      - ATS-PFM-SEC-017-03
      - ATS-PFM-SEC-017-12
      - ATS-PFM-SEC-017-19
    qualification: >-
      These are candidate scenarios for the authority boundary, not an exhaustive allowed/refused
      matrix for this key. The finding retains combinations not established by the executable
      assertions.
    gap: FND-PFM-SEC-074
    provenance: inferred
    source: >-
      specs/platform/security/planning/capabilities/CAP-PFM-SEC-017-let-rhythm-staff-into-a-customer-s-workspace-only-by-consent.md
  - key: hq.tenant-access.read
    scenario_candidates:
      - ATS-PFM-SEC-017-03
      - ATS-PFM-SEC-017-12
      - ATS-PFM-SEC-017-19
    qualification: >-
      These are candidate scenarios for the authority boundary, not an exhaustive allowed/refused
      matrix for this key. The finding retains combinations not established by the executable
      assertions.
    gap: FND-PFM-SEC-074
    provenance: inferred
    source: >-
      specs/platform/security/planning/capabilities/CAP-PFM-SEC-017-let-rhythm-staff-into-a-customer-s-workspace-only-by-consent.md
  - key: hq.emergency-access.use
    scenario_candidates:
      - ATS-PFM-SEC-017-03
      - ATS-PFM-SEC-017-12
      - ATS-PFM-SEC-017-19
    qualification: >-
      These are candidate scenarios for the authority boundary, not an exhaustive allowed/refused
      matrix for this key. The finding retains combinations not established by the executable
      assertions.
    gap: FND-PFM-SEC-074
    provenance: inferred
    source: >-
      specs/platform/security/planning/capabilities/CAP-PFM-SEC-017-let-rhythm-staff-into-a-customer-s-workspace-only-by-consent.md
  - key: hq.audit.read
    scenario_candidates:
      - ATS-PFM-SEC-017-03
      - ATS-PFM-SEC-017-12
      - ATS-PFM-SEC-017-19
    qualification: >-
      These are candidate scenarios for the authority boundary, not an exhaustive allowed/refused
      matrix for this key. The finding retains combinations not established by the executable
      assertions.
    gap: FND-PFM-SEC-074
    provenance: inferred
    source: >-
      specs/platform/security/planning/capabilities/CAP-PFM-SEC-017-let-rhythm-staff-into-a-customer-s-workspace-only-by-consent.md
  - key: hq.tenants.read
    scenario_candidates:
      - ATS-PFM-SEC-017-03
      - ATS-PFM-SEC-017-12
      - ATS-PFM-SEC-017-19
    qualification: >-
      These are candidate scenarios for the authority boundary, not an exhaustive allowed/refused
      matrix for this key. The finding retains combinations not established by the executable
      assertions.
    gap: FND-PFM-SEC-074
    provenance: inferred
    source: >-
      specs/platform/security/planning/capabilities/CAP-PFM-SEC-017-let-rhythm-staff-into-a-customer-s-workspace-only-by-consent.md
  - key: platform.staff-access.read
    scenario_candidates:
      - ATS-PFM-SEC-017-03
      - ATS-PFM-SEC-017-12
      - ATS-PFM-SEC-017-19
    qualification: >-
      These are candidate scenarios for the authority boundary, not an exhaustive allowed/refused
      matrix for this key. The finding retains combinations not established by the executable
      assertions.
    gap: FND-PFM-SEC-074
    provenance: inferred
    source: >-
      specs/platform/security/planning/capabilities/CAP-PFM-SEC-017-let-rhythm-staff-into-a-customer-s-workspace-only-by-consent.md
  - key: platform.staff-access.manage
    scenario_candidates:
      - ATS-PFM-SEC-017-03
      - ATS-PFM-SEC-017-12
      - ATS-PFM-SEC-017-19
    qualification: >-
      These are candidate scenarios for the authority boundary, not an exhaustive allowed/refused
      matrix for this key. The finding retains combinations not established by the executable
      assertions.
    gap: FND-PFM-SEC-074
    provenance: inferred
    source: >-
      specs/platform/security/planning/capabilities/CAP-PFM-SEC-017-let-rhythm-staff-into-a-customer-s-workspace-only-by-consent.md
examiner: codex
examined_at: '2026-10-23'
final_text: OpenAI
---
# Control staff access to customer workspaces: Capability Test Specification

## Coverage

| Required rule | Scenario or finding |
|---|---|
| `BR-CAP-PFM-SEC-017-01` | `ATS-PFM-SEC-017-01` |
| `BR-CAP-PFM-SEC-017-02` | `ATS-PFM-SEC-017-02` |
| `BR-CAP-PFM-SEC-017-03` | `ATS-PFM-SEC-017-03` |
| `BR-CAP-PFM-SEC-017-04` | `ATS-PFM-SEC-017-04`, `ATS-PFM-SEC-017-14`, `ATS-PFM-SEC-017-15` |
| `BR-CAP-PFM-SEC-017-05` | `ATS-PFM-SEC-017-05` |
| `BR-CAP-PFM-SEC-017-06` | `ATS-PFM-SEC-017-06`, `ATS-PFM-SEC-017-17`, `ATS-PFM-SEC-017-18` |
| `BR-CAP-PFM-SEC-017-07` | `ATS-PFM-SEC-017-07` |
| `BR-CAP-PFM-SEC-017-08` | `ATS-PFM-SEC-017-08`, `ATS-PFM-SEC-017-20`, `ATS-PFM-SEC-017-21` |
| `BR-CAP-PFM-SEC-017-09` | `ATS-PFM-SEC-017-09` |
| `BR-CAP-PFM-SEC-017-10` | `ATS-PFM-SEC-017-10`, `ATS-PFM-SEC-017-16` |
| `BR-CAP-PFM-SEC-017-11` | `ATS-PFM-SEC-017-11` |
| `BR-CAP-PFM-SEC-017-14` | `ATS-PFM-SEC-017-12`, `ATS-PFM-SEC-017-19` |

The category map records specified proof. A covered category can contain proposed scenarios; it does not mean the checks have run. The bindings identify individual executable contributions, while findings retain missing rules, permissions, transitions and assertions.

## Interactions With Related Capabilities

The interaction scenarios connect this capability to the related actions and workflow handoffs named in their proof references. Each case observes the outcome after the connected action changes records or available authority. A collection of separately bound checks does not establish an ordered feature journey.

Source revisions and assertion references are recorded in frontmatter. Steps and expected observations carry separate evidence annotations. Proposed checks remain distinct from executable test statements, and static review supplies no run result.
