Skip to content

ATS-PFM-SEC-012Model customer responsibilities with roles and policies: Capability Test Specification

Markdown

ATS-PFM-SEC-012

Model customer responsibilities with roles and policies: Capability Test Specification

Markdown
  • DocumentProposed

KindAcceptance test setProduct areaPlatformModuleSecurity, Customers and WorkspacesRevision3ExaminercodexExamined on2026-10-23

Read atservices-platform ad3f6a65react-console baf6dae3

Coverage

  • Rule gap: FND-PFM-SEC-069
  • Transition covered
  • Validation covered
  • Permission covered
  • Edge covered
  • Failure gap: FND-PFM-SEC-069
  • Boundary covered
  • Concurrency covered
  • Invariant covered
  • Interaction covered

Test Scenarios

18 scenarios proving CAP-PFM-SEC-012; 13 bound to an existing test.

01 Separate read and management permissionspermissionapinegativetest
Proves
BR-CAP-PFM-SEC-012-01
Preconditions
Prepare a caller holding only definition-read keys.
Steps
Read a role and attempt creation.
Expected
Reading succeeds while the write is refused.
Data
Use the records described in the setup.
Bound to
services-platform:modules/security/tests/e2e/definitions.e2e.spec.js#lets a caller holding only the read key read a role, and refuses the same caller the write
react-console:e2e/mock/security-view-edit.mock.spec.ts#somebody who may only read roles gets no Edit, and the edit page sends them to the view
Source
services-platform:modules/security/tests/e2e/definitions.e2e.spec.js#lets a caller holding only the read key read a role, and refuses the same caller the write
02 Built-in integrity and copy provenanceinvariantapinegativetest
Proves
BR-CAP-PFM-SEC-012-02
Preconditions
Prepare a built-in policy and role.
Steps
Edit and copy each, then attempt a direct built-in mutation.
Expected
Edits fail as read-only, copies retain source and version and database safeguards refuse the direct mutation.
Data
Use the records described in the setup.
Bound to
services-platform:modules/security/tests/e2e/definitions.e2e.spec.js#refuses a write against a built-in as read-only rather than as a record that is not there
services-platform:modules/security/tests/e2e/definitions.e2e.spec.js#copies a built-in into the customer, recording what it was copied from
services-platform:modules/security/tests/integration/db/security-definition-integrity.integration.spec.js#refuses an insert, an update and a delete of a built-in policy outside a reconciliation
react-console:e2e/security/policies.spec.ts#shows a built-in policy read-only, and duplicates it into one that can be changed
Source
services-platform:modules/security/tests/e2e/definitions.e2e.spec.js#refuses a write against a built-in as read-only rather than as a record that is not there
03 Catalog keys, patterns and nonempty selectionsvalidationapinegativetest
Proves
BR-CAP-PFM-SEC-012-03
Preconditions
Use the current permission catalog.
Steps
Try allow and deny patterns, an unknown key, duplicate selections and an empty permission list.
Expected
The tested matching deny pattern succeeds; allow patterns and malformed selections fail with rule-specific guidance.
Data
Use the records described in the setup.
Bound to
react-console:e2e/security/policies.spec.ts#refuses an allow rule that names a wildcard, and accepts it as a deny
services-platform:modules/security/tests/unit/services/persistence/rule-validation.spec.ts#names the key the catalog does not have, and the rule it is in
services-platform:modules/security/tests/unit/services/persistence/rule-validation.spec.ts#refuses an unknown key in a DENY too, because a deny nobody matches takes nothing away
services-platform:modules/security/tests/unit/services/persistence/rule-validation.spec.ts#refuses the same permission named twice, which is a mistake worth naming rather than absorbing
services-platform:modules/security/tests/unit/services/persistence/rule-validation.spec.ts#refuses a rule naming no permission, which would say nothing at all
Source
react-console:e2e/security/policies.spec.ts#refuses an allow rule that names a wildcard, and accepts it as a deny
04 Condition interpretationvalidationunitnegativetest
Proves
BR-CAP-PFM-SEC-012-04
Preconditions
Prepare a rule-validation request.
Steps
Validate a supported condition and an unsupported shape.
Expected
The supported form passes and the unsupported condition is refused.
Data
Use the records described in the setup.
Bound to
services-platform:modules/security/tests/unit/services/persistence/rule-validation.spec.ts#refuses a condition the evaluator could only read as UNKNOWN
Source
services-platform:modules/security/tests/unit/services/persistence/rule-validation.spec.ts#accepts a rule carrying a condition the evaluator can read
05 Policy ownership and lifecycle on attachmentsboundaryapinegativetest
Proves
BR-CAP-PFM-SEC-012-06 INV-DOM-PFM-SEC-003-14
Preconditions
Prepare policies from two customers and an archived policy.
Steps
Attach the foreign and archived policies, then try a custom policy on a built-in role.
Expected
The tested API and database paths reject every invalid attachment.
Data
Use the records described in the setup.
Bound to
services-platform:modules/security/tests/integration/services/definitions/manage-roles.integration.spec.js#refuses a reference to another customer's policy, and writes no role at all
services-platform:modules/security/tests/integration/db/security-definition-integrity.integration.spec.js#refuses another customer's policy, the one way authority could cross a wall through a definition
services-platform:modules/security/tests/integration/db/security-definition-integrity.integration.spec.js#refuses a customer's policy on a built-in role, which must mean the same thing for everybody
Source
services-platform:modules/security/tests/integration/services/definitions/manage-roles.integration.spec.js#refuses a reference to another customer's policy, and writes no role at all
06 Role requests cannot declare scopevalidationapinegativetest
Proves
BR-CAP-PFM-SEC-012-07
Preconditions
Prepare role creation and edit requests.
Steps
Include a scope field in both requests.
Expected
Both fail unknown-field validation.
Data
Use the records described in the setup.
Bound to
services-platform:modules/security/tests/integration/services/definitions/role-request-scope.integration.spec.js#refuses a create that states intended_scope as an unknown field, and writes no role
services-platform:modules/security/tests/integration/services/definitions/role-request-scope.integration.spec.js#refuses an edit that states intended_scope as an unknown field, and leaves the role as it was
Source
services-platform:modules/security/tests/integration/services/definitions/role-request-scope.integration.spec.js#refuses a create that states intended_scope as an unknown field, and writes no role
07 Grants-nothing presentationedgeapitest
Proves
BR-CAP-PFM-SEC-012-08
Preconditions
Prepare empty and deny-only role requests.
Steps
Save both, inspect record and list, then attach an active allowing policy to the empty role.
Expected
The initial definitions are labelled as granting nothing; the label clears when allowing authority is added.
Data
Use the records described in the setup.
Bound to
services-platform:modules/security/tests/e2e/definitions.e2e.spec.js#saves a role with neither policies nor rules, and answers that it grants nothing
services-platform:modules/security/tests/e2e/definitions.e2e.spec.js#answers a role whose only rule denies as granting nothing
services-platform:modules/security/tests/e2e/definitions.e2e.spec.js#stops answering grants-nothing once the draft is given a policy
Source
services-platform:modules/security/tests/e2e/definitions.e2e.spec.js#saves a role with neither policies nor rules, and answers that it grants nothing
08 Archive dependency refusalstransitionapinegativetest
Proves
BR-CAP-PFM-SEC-012-09 INV-DOM-PFM-SEC-003-15
Preconditions
Prepare an assigned role, referenced policy and unused definitions.
Steps
Archive each definition.
Expected
The in-use definitions fail with holder or role details; unused definitions archive successfully.
Data
Use the records described in the setup.
Bound to
services-platform:modules/security/tests/e2e/definitions.e2e.spec.js#refuses to archive a role somebody still holds, naming the holders in the details
services-platform:modules/security/tests/e2e/definitions.e2e.spec.js#refuses to archive a policy a role still uses, naming the roles in the details
services-platform:modules/security/tests/e2e/definitions.e2e.spec.js#archives a role nobody holds, through the same route a held one is refused by
react-console:e2e/security/roles.spec.ts#refuses to archive a role somebody still holds, and names them
Source
services-platform:modules/security/tests/e2e/definitions.e2e.spec.js#refuses to archive a role somebody still holds, naming the holders in the details
09 Widening and self-widening during editspermissionapinegativetest
Proves
BR-CAP-PFM-SEC-012-10
Preconditions
Prepare a held role and an editor lacking some affected keys.
Steps
Add a missing key, weaken a conditional deny, widen an editor-held role and rename a definition.
Expected
The tested widening attempts fail while the rename succeeds.
Data
Use the records described in the setup.
Bound to
services-platform:modules/security/tests/integration/services/definitions/manage-policies.integration.spec.js#refuses an edit that would add a key the editor is not allowed where the policy is already held
services-platform:modules/security/tests/integration/services/definitions/manage-policies.integration.spec.js#refuses an edit that weakens a conditional deny, for an editor who is not allowed the key it was holding back
services-platform:modules/security/tests/integration/services/definitions/manage-roles.integration.spec.js#refuses an edit that would widen a role the editor holds themselves, whoever else holds it
services-platform:modules/security/tests/integration/services/definitions/manage-policies.integration.spec.js#allows the same editor to rename a held policy, because a rename frees nothing
Source
services-platform:modules/security/tests/integration/services/definitions/manage-policies.integration.spec.js#refuses an edit that would add a key the editor is not allowed where the policy is already held
10 Last-administrator role protectioninvariantapinegativetest
Proves
BR-CAP-PFM-SEC-012-11 INV-DOM-PFM-SEC-003-12
Preconditions
Prepare the role supplying the only qualifying security administrator.
Steps
Detach its security-administrator policy.
Expected
The edit fails and preserves the policy attachment.
Data
Use the records described in the setup.
Bound to
services-platform:modules/security/tests/integration/services/definitions/manage-roles.integration.spec.js#refuses an edit that would leave the customer with no security administrator, and detaches nothing
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
Source
services-platform:modules/security/tests/integration/services/definitions/manage-roles.integration.spec.js#refuses an edit that would leave the customer with no security administrator, and detaches nothing
11 Stale definition editsconcurrencyapinegativetest
Proves
BR-CAP-PFM-SEC-012-12
Preconditions
Prepare a definition changed after its earlier read.
Steps
Save using the old version.
Expected
The edit fails and preserves the newer stored definition.
Data
Use the records described in the setup.
Bound to
services-platform:modules/security/tests/integration/services/definitions/manage-policies.integration.spec.js#refuses an edit made against a version the policy has moved past, leaving the row as it was
services-platform:modules/security/tests/integration/services/definitions/manage-roles.integration.spec.js#refuses an edit made against a version the role has moved past, leaving the row as it was
services-platform:modules/security/tests/e2e/definitions.e2e.spec.js#changes a policy at the version If-Match states, and refuses the same change twice
react-console:e2e/mock/security-editor-bar.mock.spec.ts#a stale save is the bar's conflict, and Reload takes what was saved
Source
services-platform:modules/security/tests/integration/services/definitions/manage-policies.integration.spec.js#refuses an edit made against a version the policy has moved past, leaving the row as it was
12 Staff-definition isolationboundaryapinegativetest
Proves
BR-CAP-PFM-SEC-012-14 INV-DOM-PFM-SEC-003-14
Preconditions
Sign in as a customer administrator.
Steps
List definitions, read a staff role and its members, and try copying or composing from it.
Expected
Lists omit staff-only definitions, reads return 404 and composition attempts fail.
Data
Use the records described in the setup.
Bound to
services-platform:modules/security/tests/e2e/definitions.e2e.spec.js#lists every role but the staff-only ones, the built-ins a customer assigns among them
services-platform:modules/security/tests/e2e/definitions.e2e.spec.js#answers 404 for a staff-only role and policy read by their keys, as for a role that is not there
services-platform:modules/security/tests/e2e/definitions.e2e.spec.js#answers 404 for the members of a staff-only role
services-platform:modules/security/tests/e2e/definitions.e2e.spec.js#refuses a role built from a staff-only policy, and copying a staff-only role or policy
Source
services-platform:modules/security/tests/e2e/definitions.e2e.spec.js#lists every role but the staff-only ones, the built-ins a customer assigns among them
13 Custom definition creation and dependenciesinteractionbrowsertest
Proves
AS-JNY-PFM-SEC-004-01 AS-JNY-PFM-SEC-004-02
Preconditions
Sign in as a security administrator.
Steps
Create a policy and role, find the role in its list and archive the policy after removing its use.
Expected
The rule requires a permission, the role is searchable and custom, and policy presentation identifies its dependent role before archive.
Data
Use the records described in the setup.
Bound to
react-console:e2e/security/policies.spec.ts#is created with a rule, and the rule has to name a permission
react-console:e2e/security/roles.spec.ts#is created from a name and a permission
react-console:e2e/security/roles.spec.ts#is on the Roles list, searchable, and marked custom
react-console:e2e/security/policies.spec.ts#is used by a role, and the policy says so
react-console:e2e/security/policies.spec.ts#is archived once no role references it
Source
react-console:e2e/security/policies.spec.ts#is created with a rule, and the rule has to name a permission
14 Custom and built-in access definition: active to archivedtransitionapiproposed
Proves
BR-CAP-PFM-SEC-012-09
Preconditions
Prepare a run-owned custom and built-in access definition in active state with the authority and inputs required by the cited transition.
Steps
[ { "do": "Archive an unreferenced custom definition with management permission and its current version.", "expect": "After the stated action, observe the custom and built-in access definition in archived state. This case does not require an additional history event unless the transition explicitly defines one.", "provenance": "proposed", "source": [ "services-platform:modules/security/services/definitions/manage-roles.ts:archiveCustomRole", "services-platform at ad3f6a65: modules/security/db/security-roles.table.ts, security-policies.table.ts; services/definitions/manage-roles.ts, manage-policies.ts, impact.ts; services/catalog/*." ] } ]
Expected
After the stated action, observe the custom and built-in access definition in archived state. This case does not require an additional history event unless the transition explicitly defines one.
Data
A disposable customer, workspace and named actor; a controllable clock where the transition depends on time.
Source
services-platform:modules/security/services/definitions/manage-roles.ts:archiveCustomRole,services-platform at ad3f6a65: modules/security/db/security-roles.table.ts, security-policies.table.ts; services/definitions/manage-roles.ts, manage-policies.ts, impact.ts; services/catalog/*.
15 Custom and built-in access definition: active to activetransitionapiproposed
Proves
BR-CAP-PFM-SEC-012-10
Preconditions
Prepare a run-owned custom and built-in access definition in active state with the authority and inputs required by the cited transition.
Steps
[ { "do": "Change the active custom definition, then independently change a built-in through release reconciliation.", "expect": "After the stated action, observe the custom and built-in access definition 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/definitions/manage-roles.ts:updateCustomRole", "services-platform at ad3f6a65: modules/security/db/security-roles.table.ts, security-policies.table.ts; services/definitions/manage-roles.ts, manage-policies.ts, impact.ts; services/catalog/*." ] } ]
Expected
After the stated action, observe the custom and built-in access definition in active state. This case does not require an additional history event unless the transition explicitly defines one.
Data
A disposable customer, workspace and named actor; a controllable clock where the transition depends on time.
Source
services-platform:modules/security/services/definitions/manage-roles.ts:updateCustomRole,services-platform at ad3f6a65: modules/security/db/security-roles.table.ts, security-policies.table.ts; services/definitions/manage-roles.ts, manage-policies.ts, impact.ts; services/catalog/*.
16 Model customer responsibilities with roles and policies with assign roles within a controlled scopeinteractionapinegativeproposed
Proves
BR-CAP-PFM-SEC-010-07 BR-CAP-PFM-SEC-012-09
Preconditions
A custom role is assigned to an active member.
Steps
Try archiving the role, withdraw its assignment, and archive again.
Expected
The held role cannot be archived; after withdrawal it can leave the active list while history remains.
Data
An isolated customer with two workspaces, ordinary and staff identities, and records owned by this run.
Source
services-platform:modules/security/tests/integration/services/membership/manage-assignments.integration.spec.js#revokes the grant, keeps the row, and audits what was withdrawn,services-platform:modules/security/tests/integration/services/definitions/manage-roles.integration.spec.js#refuses to archive a role somebody still holds, names them, and leaves it active
17 Model customer responsibilities with roles and policies with review security changes and refused attemptsinteractionapinegativeproposed
Proves
BR-CAP-PFM-SEC-011-02 BR-CAP-PFM-SEC-012-10
Preconditions
A role editor lacks authority for a requested widening change.
Steps
Attempt the edit and inspect the definition and refusal history.
Expected
The definition is unchanged and the classified refusal survives rollback.
Data
An isolated customer with two workspaces, ordinary and staff identities, and records owned by this run.
Source
services-platform:modules/security/services/audit/refused-attempts.ts:auditedAttempt,services-platform:modules/security/tests/integration/services/definitions/manage-roles.integration.spec.js#refuses an edit that would widen a role the editor holds themselves, whoever else holds it
18 Model customer responsibilities with roles and policies with derive member access from appointments and eligibilityinteractionapinegativeproposed
Proves
BR-CAP-PFM-SEC-012-04 BR-CAP-PFM-SEC-014-12
Preconditions
A customer role uses an eligibility condition binding in its own workspace.
Steps
Evaluate the condition, then try replacing it with another customer’s binding.
Expected
The owned condition participates in evaluation; the foreign replacement is refused without changing the definition.
Data
An isolated customer with two workspaces, ordinary and staff identities, and records owned by this run.
Source
services-platform:modules/security/services/persistence/rules.ts:parseConditions,services-platform:modules/security/tests/integration/services/definitions/eligibility-conditions.integration.spec.js#refuses a binding of another customer’s tenant, naming it, and stores no policy

The Markdown files under specs/ in rhythmsoftware/rhythm-v2-docs are the canonical source of truth. This reader is a generated, read-only projection of them.