---
id: JNY-PFM-SEC-004
title: Compose and assign a customer role
feature: FEAT-PFM-SEC-04
product_area: platform
module: security
revision: 1
status: draft
product_intent: confirmed
implementation_evidence: observed
supersedes: []
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
actor: ACT-PFM-001
goal: 'Represent a customer job with policies and a role, assign it, and retire it safely.'
capabilities:
  - CAP-PFM-SEC-012
  - CAP-PFM-SEC-010
  - CAP-PFM-SEC-011
screens:
  - '/console/{tenantId}/security/policies/new'
  - '/console/{tenantId}/security/roles/new'
  - '/console/{tenantId}/security/roles/{roleRef}'
steps:
  - 'n': 1
    surface: '/console/{tenantId}/security/policies/new'
    action: Create a policy with explicit allow permissions and a deny pattern.
    capability: CAP-PFM-SEC-012
    expected: The editor rejects an allow wildcard and accepts the tested deny wildcard.
    provenance: test
    source: >-
      react-console:e2e/security/policies.spec.ts#refuses an allow rule that names a wildcard, and
      accepts it as a deny
  - 'n': 2
    surface: '/console/{tenantId}/security/roles/new'
    action: Compose a custom role from the selected policies.
    capability: CAP-PFM-SEC-012
    expected: The role appears in the searchable list with its custom classification.
    provenance: test
    source: 'react-console:e2e/security/roles.spec.ts#is on the Roles list, searchable, and marked custom'
  - 'n': 3
    surface: grantConsoleUserRole
    action: Assign the new role to a colleague.
    capability: CAP-PFM-SEC-010
    expected: The role’s Members tab includes that person.
    provenance: test
    source: 'react-console:e2e/security/roles.spec.ts#is given to a person, who then shows on its Members tab'
  - 'n': 4
    surface: '/console/{tenantId}/security/roles/{roleRef}'
    action: Edit the role and reload its page.
    capability: CAP-PFM-SEC-012
    expected: The test observes the saved role change after reload.
    provenance: test
    source: 'react-console:e2e/security/roles.spec.ts#is edited, and the change survives a reload'
  - 'n': 5
    surface: archiveSecurityRole
    action: Archive the role after its assignments have been withdrawn.
    capability: CAP-PFM-SEC-012
    expected: The archived role disappears from the active list.
    provenance: test
    source: >-
      react-console:e2e/security/roles.spec.ts#is archived once nobody holds it, and leaves the active
      list
alternates:
  - from_step: 1
    condition: An existing built-in policy provides a useful starting point.
    path: Duplicate it and edit the customer-owned copy.
    outcome: The copy is editable while the shared built-in remains read-only.
    provenance: test
    source: >-
      react-console:e2e/security/policies.spec.ts#shows a built-in policy read-only, and duplicates it
      into one that can be changed
failures:
  - from_step: 5
    condition: The role still has a holder.
    path: Reject archive and display links to the holders.
    outcome: The role remains available rather than being archived.
    provenance: test
    source: >-
      react-console:e2e/security/roles.spec.ts#refuses to archive a role somebody still holds, and names
      them
  - from_step: 4
    condition: Another editor has already saved a new version.
    path: Present the stale-save conflict and choose Reload.
    outcome: The mock editor replaces local values with the saved version.
    provenance: test
    source: >-
      react-console:e2e/mock/security-editor-bar.mock.spec.ts#a stale save is the bar's conflict, and
      Reload takes what was saved
rules_in_play:
  - BR-CAP-PFM-SEC-012-02
  - BR-CAP-PFM-SEC-012-03
  - BR-CAP-PFM-SEC-012-06
  - BR-CAP-PFM-SEC-012-09
  - BR-CAP-PFM-SEC-012-10
  - BR-CAP-PFM-SEC-012-12
  - BR-CAP-PFM-SEC-010-02
assertions:
  - id: AS-JNY-PFM-SEC-004-01
    statement: Policy creation requires at least one permission in the rule before saving.
    provenance: test
    source: >-
      react-console:e2e/security/policies.spec.ts#is created with a rule, and the rule has to name a
      permission
  - id: AS-JNY-PFM-SEC-004-02
    statement: The policy’s usage view links the role that uses it.
    provenance: test
    source: 'react-console:e2e/security/policies.spec.ts#is used by a role, and the policy says so'
  - id: AS-JNY-PFM-SEC-004-03
    statement: The role’s Members tab shows the person who receives its assignment.
    provenance: test
    source: 'react-console:e2e/security/roles.spec.ts#is given to a person, who then shows on its Members tab'
e2e_policy: required
e2e_reason: >-
  Policy editing, role composition and member assignment span separate screens. Real-service browser
  tests must establish their agreement, with API rules tested independently and mock conflict behavior
  identified separately.
evidence:
  - >-
    Pinned react-console references for the structured rows: e2e/mock/security-editor-bar.mock.spec.ts;
    e2e/security/policies.spec.ts; e2e/security/roles.spec.ts.
proved_by: []
---
# Compose and assign a customer role

## Story

A security administrator creates a policy for a customer job and composes a role from it and another suitable policy. They assign that role and verify the member list. Later they rename the role and confirm the saved value after reload. When the job is retired, they withdraw its assignments before archiving it.
