Skip to content

ATS-PFM-SEC-002Maintain workspace information and operating status: Capability Test Specification

Markdown

ATS-PFM-SEC-002

Maintain workspace information and operating status: Capability Test Specification

Markdown
  • DocumentProposed

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

Read atservices-platform ad3f6a65react-console baf6dae3

Coverage

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

Test Scenarios

24 scenarios proving CAP-PFM-SEC-002; 13 bound to an existing test.

01 Workspace reach across customer boundariesboundaryapinegativetest
Proves
BR-CAP-PFM-SEC-002-01
Preconditions
Prepare two customers with a workspace each.
Steps
Read and list workspaces using one customer’s administrator.
Expected
The list contains only reachable workspaces; another customer’s default returns 404.
Data
Use the records described in the setup.
Bound to
services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#lists no tenant of another customer, which is what the reach reduction means
services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers 404 for another customer's default tenant, so the route cannot be walked
Source
services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#lists no tenant of another customer, which is what the reach reduction means
02 The HQ authority for status changespermissionapinegativetest
Proves
BR-CAP-PFM-SEC-002-02
Preconditions
Prepare an implementation workspace.
Steps
Attempt console patch and replacement status changes, then an HQ staff patch.
Expected
Console changes fail with HQ guidance and leave status intact; the staff patch succeeds.
Data
Use the records described in the setup.
Bound to
services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses a customer administrator the same change on the console route, naming where it is made
services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers 200 and the live status to the HQ patch
Source
services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses a customer administrator the same change on the console route, naming where it is made
03 Lifecycle ownership on ordinary writesinvariantapinegativetest
Proves
BR-CAP-PFM-SEC-002-03 INV-DOM-PFM-SEC-002-03 INV-DOM-PFM-SEC-002-04
Preconditions
Prepare an active workspace.
Steps
Send lifecycle values in a patch and replacement, then attempt a status prohibited by lifecycle constraints.
Expected
Client lifecycle values have no effect; the prohibited status fails without changing the record.
Data
Use the records described in the setup.
Bound to
services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#leaves the lifecycle state where the server put it after such a patch
services-platform:modules/tenants/tests/integration/services/persistence/tenants.integration.spec.js#refuses a status change the lifecycle forbids, by the rule the database holds
Source
services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#leaves the lifecycle state where the server put it after such a patch
04 Accepted time-zone formsvalidationapinegativetest
Proves
BR-CAP-PFM-SEC-002-04 INV-DOM-PFM-SEC-002-05
Preconditions
Prepare a workspace to create and edit.
Steps
Try an abbreviation, offset, Etc location and wrong case; also omit the zone.
Expected
Invalid forms return 400 without storage changes; omission uses Eastern time.
Data
Use the records described in the setup.
Bound to
services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses a time zone given as an abbreviation as 400
services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses a time zone given as a fixed offset as 400
services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses an IANA zone spelled in another case as 400
services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#leaves the stored zone as the last accepted one
Source
services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses a time zone given as an abbreviation as 400
05 Stable acronym suffixingruleapitest
Proves
BR-CAP-PFM-SEC-002-05
Preconditions
Prepare a workspace with an acronym.
Steps
Create it and save its name twice.
Expected
The saved name contains one acronym suffix after both updates.
Data
Use the records described in the setup.
Bound to
Source
services-platform:modules/tenants/tests/integration/services/persistence/tenants.integration.spec.js#suffixes it in the row, not only in the answer
06 Sandbox parent constraintsinvariantunitnegativetest
Proves
BR-CAP-PFM-SEC-002-06 INV-DOM-PFM-SEC-002-02
Preconditions
Prepare a customer-type workspace and sandbox.
Steps
Try absent, wrong-type and cross-customer parents, nested sandboxes and a customer change on the parent.
Expected
Invalid relationships fail at the database; a same-customer pair succeeds.
Data
Use the records described in the setup.
Bound to
services-platform:modules/tenants/tests/integration/db/tenants.table.integration.spec.js#refuses a sandbox that names no parent by tenants_sandbox_parent_check
services-platform:modules/tenants/tests/integration/db/tenants.table.integration.spec.js#refuses a sandbox of a sandbox, so a sandbox is never a parent
services-platform:modules/tenants/tests/integration/db/tenants.table.integration.spec.js#refuses moving a tenant that has sandboxes to another customer, which would split the pair
services-platform:modules/tenants/tests/integration/db/tenants.table.integration.spec.js#accepts a sandbox of a customer tenant of its own customer, the negative control
Source
services-platform:modules/tenants/tests/integration/db/tenants.table.integration.spec.js#refuses a sandbox that names no parent by tenants_sandbox_parent_check
07 The dedicated commercial-account actionpermissionapinegativetest
Proves
BR-CAP-PFM-SEC-002-07 INV-DOM-PFM-SEC-002-06
Preconditions
Prepare a commercially linked workspace.
Steps
Attempt ordinary link edits and replacement omission; perform and repeat a versioned staff move, then clear the link.
Expected
Ordinary changes return 400; the move succeeds once and then returns 409; a customer administrator receives 403; moving requests licence synchronization, while clearing requests none.
Data
Use the records described in the setup.
Bound to
services-platform:modules/tenants/tests/e2e/tenant-hubspot-link.e2e.spec.js#refuses a patch that moves the link as 400, even for Rhythm staff in their own editor
services-platform:modules/tenants/tests/e2e/tenant-hubspot-link.e2e.spec.js#refuses a replacement that simply drops the field, because omitting it would clear the link
services-platform:modules/tenants/tests/e2e/tenant-hubspot-link.e2e.spec.js#refuses a second move at the version already written as 409
services-platform:modules/tenants/tests/e2e/tenant-hubspot-link.e2e.spec.js#refuses an administrator of the customer as 403, because this is a system route
services-platform:modules/tenants/tests/e2e/tenant-hubspot-link.e2e.spec.js#asks for the company it moved the tenant to to be read from HubSpot
services-platform:modules/tenants/tests/e2e/tenant-hubspot-link.e2e.spec.js#asks for nothing when the link is cleared, because there is no company to read
Source
services-platform:modules/tenants/tests/e2e/tenant-hubspot-link.e2e.spec.js#refuses a patch that moves the link as 400, even for Rhythm staff in their own editor
08 Version and lock refusals; add a valid clearing proofconcurrencyapinegativeproposed
Proves
BR-CAP-PFM-SEC-002-08
Preconditions
Read a workspace at version n with a populated optional field.
Steps
Replace at n omitting that field, repeat at n, and replace an update-locked record; read back the current field spelling.
Expected
Stale and locked replacements fail. The proposed clearing check must assert the current stored field is absent or cleared, rather than inspect an obsolete property name.
Data
Use the records described in the setup.
Source
FND-PFM-SEC-035
09 Workspace availability by route and callerboundaryapinegativetest
Proves
BR-CAP-PFM-SEC-002-09 INV-DOM-PFM-SEC-002-07
Preconditions
Prepare disabled, provisioning, loading and deleting workspaces.
Steps
Request ordinary routes as customer users and staff, HQ routes as staff, and an initial-import route during loading.
Expected
Ordinary blocked requests return 403 with the generic refusal; HQ staff pass subject to read-only deletion, and loading permits the authorized import route.
Data
Use the records described in the setup.
Bound to
services-platform:modules/tenants/tests/e2e/tenant-availability-gate.e2e.spec.js#is refused 403 in a tenant whose customer has been cut off
services-platform:modules/tenants/tests/e2e/tenant-availability-gate.e2e.spec.js#is refused 403 in a tenant that is still being provisioned
services-platform:modules/tenants/tests/e2e/tenant-availability-gate.e2e.spec.js#is refused 403 in a tenant whose initial data import is open
services-platform:modules/tenants/tests/e2e/tenant-availability-gate.e2e.spec.js#is refused the same way in a tenant being deleted, so the exemption is not a console route’s to grant
services-platform:modules/tenants/tests/e2e/tenant-availability-gate.e2e.spec.js#may not write to a tenant being deleted, which the same caller being served above is the premise for
services-platform:modules/tenants/tests/unit/services/access/tenant-availability.spec.js#answers the rule for every combination of lifecycle state, status and caller
Source
services-platform:modules/tenants/tests/e2e/tenant-availability-gate.e2e.spec.js#is refused 403 in a tenant whose customer has been cut off
10 Direct deletion gives recovery guidancetransitionapinegativetest
Proves
BR-CAP-PFM-SEC-002-11
Preconditions
Prepare an existing workspace.
Steps
Call its direct delete operation.
Expected
The operation returns 405, points to deletion requests and leaves the workspace unchanged.
Data
Use the records described in the setup.
Bound to
services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers the gone status the error contract can express
services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#points the caller at the deletion request route
services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#leaves the tenant exactly as it was, which is the point of refusing
Source
services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers the gone status the error contract can express
11 HQ workspace search, filtering and paginationboundaryapinegativetest
Proves
BR-CAP-PFM-SEC-002-12
Preconditions
Prepare workspaces for several customers.
Steps
Search an identifier in different case, filter by type, follow a cursor and call as a customer administrator.
Expected
Search and filtering select the expected records, the cursor continues the list and the administrator receives 403.
Data
Use the records described in the setup.
Bound to
services-platform:modules/tenants/tests/e2e/hq-tenants.e2e.spec.js#finds a tenant by its id, the association's domain, whatever its case
services-platform:modules/tenants/tests/e2e/hq-tenants.e2e.spec.js#answers only the tenants of the type asked for
services-platform:modules/tenants/tests/e2e/hq-tenants.e2e.spec.js#answers a cursor that resumes the list where the page stopped
services-platform:modules/tenants/tests/e2e/hq-tenants.e2e.spec.js#refuses an administrator of a customer, holding every key at that customer, as 403
Source
services-platform:modules/tenants/tests/e2e/hq-tenants.e2e.spec.js#finds a tenant by its id, the association's domain, whatever its case
12 Private staff shortcuts and list limitsedgeapinegativetest
Proves
BR-CAP-PFM-SEC-002-13
Preconditions
Prepare two staff identities.
Steps
Pin twenty-one workspaces, open eleven and compare the two identities’ lists.
Expected
The extra pin fails; only ten recent entries remain, pins are preserved and lists do not disclose each other’s entries.
Data
Use the records described in the setup.
Bound to
services-platform:modules/tenants/tests/e2e/hq-tenant-shortcuts.e2e.spec.js#never answers the administrator the tenant the other person pinned
services-platform:modules/tenants/tests/e2e/hq-tenant-shortcuts.e2e.spec.js#refuses an administrator of a customer reading the home page as 403, because these are system routes
Source
services-platform:modules/tenants/tests/integration/services/persistence/staff-tenant-shortcuts.integration.spec.js#refuses the pin that would be one too many, naming the maximum
13 Dedicated and shared sender informationruleapitest
Proves
BR-CAP-PFM-SEC-002-14
Preconditions
Prepare one dedicated sender and one shared-sender workspace.
Steps
Read sender information as staff and as the customer administrator.
Expected
Staff receive DNS and verification details or a null shared-sender result; the administrator receives 403.
Data
Use the records described in the setup.
Bound to
services-platform:modules/tenants/tests/e2e/tenant-email-sender.e2e.spec.js#answers the DNS records the customer must publish, so a support person can read them out
services-platform:modules/tenants/tests/e2e/tenant-email-sender.e2e.spec.js#answers null rather than a record, which is how it says the shared sender
services-platform:modules/tenants/tests/e2e/tenant-email-sender.e2e.spec.js#refuses an administrator of the tenant’s own customer as 403, because this is a system route
Source
services-platform:modules/tenants/tests/e2e/tenant-email-sender.e2e.spec.js#answers the DNS records the customer must publish, so a support person can read them out
14 The HQ edit sheet and disable confirmationpermissionbrowsertest
Proves
AS-JNY-PFM-SEC-001-03
Preconditions
Prepare an HQ staff session and an existing workspace.
Steps
Edit the workspace name, save it, then attempt disabled status through the confirmation dialog.
Expected
The sheet omits an identifier editor, reflects the saved name and asks for confirmation before disabling; this mock test does not establish go-live behavior.
Data
Use the records described in the setup.
Bound to
react-console:e2e/mock/hq-ops.mock.spec.ts#the edit sheet saves, has no identifier to change, and confirms before disabling the tenant
Source
react-console:e2e/mock/hq-ops.mock.spec.ts#the edit sheet saves, has no identifier to change, and confirms before disabling the tenant
15 Workspace business status: implementation to livetransitionapiproposed
Proves
BR-CAP-PFM-SEC-002-02
Preconditions
Prepare a run-owned workspace business status in implementation state with the authority and inputs required by the cited transition.
Steps
[ { "do": "Save live status with the current version as authorized staff.", "expect": "After the stated action, observe the workspace business status in live state. This case does not require an additional history event unless the transition explicitly defines one.", "provenance": "proposed", "source": [ "services-platform:modules/tenants/tests/integration/services/persistence/tenants.integration.spec.js#lets a sandbox tenant go live, the data-import check being recorded as debt", "services-platform at ad3f6a65: modules/tenants/db/tenants.table.ts; aws/api/tenants.routes.ts, tenant-api-mapper.ts; services/access/tenant-availability.ts." ] } ]
Expected
After the stated action, observe the workspace business status in live 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/tenants/tests/integration/services/persistence/tenants.integration.spec.js#lets a sandbox tenant go live, the data-import check being recorded as debt,services-platform at ad3f6a65: modules/tenants/db/tenants.table.ts; aws/api/tenants.routes.ts, tenant-api-mapper.ts; services/access/tenant-availability.ts.
16 Workspace business status: live to disabledtransitionapiproposed
Proves
BR-CAP-PFM-SEC-002-02
Preconditions
Prepare a run-owned workspace business status in live state with the authority and inputs required by the cited transition.
Steps
[ { "do": "Disable the live workspace using the dedicated staff edit.", "expect": "After the stated action, observe the workspace business status in disabled state. This case does not require an additional history event unless the transition explicitly defines one.", "provenance": "proposed", "source": [ "services-platform:modules/tenants/aws/api/tenants.routes.ts:patchHqTenant (requireStatusAuthority)", "services-platform at ad3f6a65: modules/tenants/db/tenants.table.ts; aws/api/tenants.routes.ts, tenant-api-mapper.ts; services/access/tenant-availability.ts." ] } ]
Expected
After the stated action, observe the workspace business status in disabled 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/tenants/aws/api/tenants.routes.ts:patchHqTenant (requireStatusAuthority),services-platform at ad3f6a65: modules/tenants/db/tenants.table.ts; aws/api/tenants.routes.ts, tenant-api-mapper.ts; services/access/tenant-availability.ts.
17 Workspace business status: implementation to disabledtransitionapiproposed
Proves
BR-CAP-PFM-SEC-002-02
Preconditions
Prepare a run-owned workspace business status in implementation state with the authority and inputs required by the cited transition.
Steps
[ { "do": "Disable the implementation workspace while no load is open.", "expect": "After the stated action, observe the workspace business status in disabled state. This case does not require an additional history event unless the transition explicitly defines one.", "provenance": "proposed", "source": [ "services-platform:modules/tenants/aws/api/tenants.routes.ts:patchHqTenant (requireStatusAuthority)", "services-platform at ad3f6a65: modules/tenants/db/tenants.table.ts; aws/api/tenants.routes.ts, tenant-api-mapper.ts; services/access/tenant-availability.ts." ] } ]
Expected
After the stated action, observe the workspace business status in disabled 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/tenants/aws/api/tenants.routes.ts:patchHqTenant (requireStatusAuthority),services-platform at ad3f6a65: modules/tenants/db/tenants.table.ts; aws/api/tenants.routes.ts, tenant-api-mapper.ts; services/access/tenant-availability.ts.
18 Workspace business status: disabled to livetransitionapiproposed
Proves
BR-CAP-PFM-SEC-002-02
Preconditions
Prepare a run-owned workspace business status in disabled state with the authority and inputs required by the cited transition.
Steps
[ { "do": "Save live status on the disabled workspace when no retirement is open.", "expect": "After the stated action, observe the workspace business status in live state. This case does not require an additional history event unless the transition explicitly defines one.", "provenance": "proposed", "source": [ "services-platform:modules/tenants/db/tenants.table.ts:tenants (tenants_deletion_pending_status_check)", "services-platform at ad3f6a65: modules/tenants/db/tenants.table.ts; aws/api/tenants.routes.ts, tenant-api-mapper.ts; services/access/tenant-availability.ts." ] } ]
Expected
After the stated action, observe the workspace business status in live 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/tenants/db/tenants.table.ts:tenants (tenants_deletion_pending_status_check),services-platform at ad3f6a65: modules/tenants/db/tenants.table.ts; aws/api/tenants.routes.ts, tenant-api-mapper.ts; services/access/tenant-availability.ts.
19 Workspace business status: disabled to implementationtransitionapiproposed
Proves
BR-CAP-PFM-SEC-002-02
Preconditions
Prepare a run-owned workspace business status in disabled state with the authority and inputs required by the cited transition.
Steps
[ { "do": "Save implementation status on the disabled workspace when no retirement is open.", "expect": "After the stated action, observe the workspace business status in implementation state. This case does not require an additional history event unless the transition explicitly defines one.", "provenance": "proposed", "source": [ "services-platform:modules/tenants/db/tenants.table.ts:tenants (tenants_deletion_pending_status_check)", "services-platform at ad3f6a65: modules/tenants/db/tenants.table.ts; aws/api/tenants.routes.ts, tenant-api-mapper.ts; services/access/tenant-availability.ts." ] } ]
Expected
After the stated action, observe the workspace business status in implementation 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/tenants/db/tenants.table.ts:tenants (tenants_deletion_pending_status_check),services-platform at ad3f6a65: modules/tenants/db/tenants.table.ts; aws/api/tenants.routes.ts, tenant-api-mapper.ts; services/access/tenant-availability.ts.
20 Workspace business status: live to implementationtransitionapiproposed
Proves
BR-CAP-PFM-SEC-002-02
Preconditions
Prepare a run-owned workspace business status in live state with the authority and inputs required by the cited transition.
Steps
[ { "do": "Save implementation status on the live workspace as authorized staff.", "expect": "After the stated action, observe the workspace business status in implementation state. This case does not require an additional history event unless the transition explicitly defines one.", "provenance": "proposed", "source": [ "services-platform:modules/tenants/db/tenants.table.ts:TENANT_STATUSES", "services-platform at ad3f6a65: modules/tenants/db/tenants.table.ts; aws/api/tenants.routes.ts, tenant-api-mapper.ts; services/access/tenant-availability.ts." ] } ]
Expected
After the stated action, observe the workspace business status in implementation 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/tenants/db/tenants.table.ts:TENANT_STATUSES,services-platform at ad3f6a65: modules/tenants/db/tenants.table.ts; aws/api/tenants.routes.ts, tenant-api-mapper.ts; services/access/tenant-availability.ts.
21 Maintain workspace information and operating status with establish and administer a customerinteractionapinegativeproposed
Proves
BR-CAP-PFM-SEC-001-11 BR-CAP-PFM-SEC-002-01
Preconditions
A customer has one active workspace.
Steps
Try deleting the customer, then read the workspace and customer.
Expected
Deletion is refused and both records retain their identities.
Data
An isolated customer with two workspaces, ordinary and staff identities, and records owned by this run.
Source
services-platform:modules/customers/tests/e2e/customers.e2e.spec.js#refuses a customer that still has tenants as 409,services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#lists no tenant of another customer, which is what the reach reduction means
22 Maintain workspace information and operating status with prepare a workspace for customer useinteractionapinegativeproposed
Proves
BR-CAP-PFM-SEC-002-09 BR-CAP-PFM-SEC-003-13
Preconditions
An active implementation workspace has an ordinary caller and an import operator.
Steps
Open an initial load, try ordinary work, then activate with a separate authorized staff identity.
Expected
Ordinary work is refused during loading and resumes after activation; implementation status remains unchanged.
Data
An isolated customer with two workspaces, ordinary and staff identities, and records owned by this run.
Source
services-platform:modules/tenants/services/access/tenant-availability.ts:tenantAvailabilityOf,services-platform:modules/tenants/tests/e2e/hq-tenant-loading.e2e.spec.js#refuses a live tenant, an initial import going only into an implementation tenant
23 Maintain workspace information and operating status with manage a workspace retirement requestinteractionapinegativeproposed
Proves
BR-CAP-PFM-SEC-002-03 BR-CAP-PFM-SEC-004-07
Preconditions
A disabled active workspace is eligible for retirement.
Steps
Request retirement, try enabling the workspace, cancel before destruction, and read both axes.
Expected
The enabling attempt fails; cancellation restores active lifecycle while business status remains disabled.
Data
An isolated customer with two workspaces, ordinary and staff identities, and records owned by this run.
Source
services-platform:modules/tenants/tests/integration/services/persistence/tenants.integration.spec.js#ignores a lifecycle state a write input carries, rather than letting a client set the system axis,services-platform:modules/tenants/tests/integration/services/deletion/deletion-holds.integration.spec.js#leaves the tenant disabled: calling off a deletion restores nobody access
24 Maintain workspace information and operating status with enforce access at request boundariesinteractionapinegativeproposed
Proves
BR-CAP-PFM-SEC-002-09 BR-CAP-PFM-SEC-015-06
Preconditions
An ordinary caller has valid authority over an active workspace.
Steps
Disable the workspace and issue a new protected request after the availability cache expires.
Expected
The new request is refused even though the role assignment remains present.
Data
An isolated customer with two workspaces, ordinary and staff identities, and records owned by this run.
Source
services-platform:modules/tenants/services/access/tenant-availability.ts:tenantAvailabilityOf,services-platform:modules/security/tests/unit/authorizer/authorize.spec.ts#returns a Deny for the whole route when no grant could apply anywhere

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.