---
id: TST-PFM-SEC-230
title: Workspaces request checks
kind: api-lifecycle
product_area: platform
module: security
revision: 2
status: draft
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
repository: services-platform
files:
  - modules/tenants/tests/e2e/tenants.e2e.spec.js
implements:
  - ATS-PFM-SEC-002-01
  - ATS-PFM-SEC-002-02
  - ATS-PFM-SEC-002-03
  - ATS-PFM-SEC-002-04
  - ATS-PFM-SEC-002-10
  - ATS-PFM-SEC-003-02
  - ATS-PFM-SEC-007-06
environment: local
implementation_state: implemented
latest_result: not-run
latest_run_at: null
latest_run_ref: null
conformance: not-verified
estimated_minutes: 5
isolation: Use the prepared test database and suite-owned fixture rows; retain shared seed records.
assertion_evidence:
  - provenance: test
    source: 'services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#tenants API (end to end)'
  - provenance: test
    source: 'services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#the public health route'
  - provenance: test
    source: 'services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers 200 without a context'
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#names the service and says it
      is well
  - provenance: test
    source: 'services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#createTenant'
  - provenance: test
    source: 'services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers 200 for a valid body'
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#suffixes the acronym to the
      name it answers
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers the tenant under its
      customer with the status and zone it was given
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers the time zone under
      its snake_case property, time_zone, and never under a camelCase spelling
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#carries none of the fields the
      tenant no longer has
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#stamps version 1 with the
      signed caller as creator, in the answer to the submission itself
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers the provisioning job
      that is making the tenant usable
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers a tenant that is not
      usable yet, because the provisioning has only just been asked for
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#reads the created tenant back
      through the API
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses a status outside the
      closed list as 400
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses a name that is nothing
      but whitespace as 400 naming name
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses a customer that does
      not exist as 409
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#names the missing customer in
      the 409
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses the camelCase spelling
      timeZone as an unknown property (400): the field is time_zone
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses a time zone given as
      an abbreviation as 400
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses a time zone given as a
      fixed offset as 400
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses an Etc time zone as
      400
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses an IANA zone spelled
      in another case as 400
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses a place no time zone
      database knows as 400
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses an anonymous call as
      401
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses a context signed by
      another key as 401
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#createTenant without a time
      zone
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers 200 for a body that
      names no time zone
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers the system default,
      Eastern
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#reads the default zone back
      through the API, so it was stored and not merely answered
  - provenance: test
    source: 'services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#getTenant'
  - provenance: test
    source: 'services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#reads the tenant'
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#projects the record to the
      requested fields
  - provenance: test
    source: 'services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers 404 for an unknown id'
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#names the contract prefix in
      the 404
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses an anonymous call as
      401
  - provenance: test
    source: 'services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#listTenants'
  - provenance: test
    source: 'services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers 200'
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#lists the caller's own
      customer's tenants, the one this suite created among them
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#lists no tenant of another
      customer, which is what the reach reduction means
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#reduces the list to the
      tenants the caller may reach
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses an anonymous call as
      401
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses a context signed by
      another key as 401
  - provenance: test
    source: 'services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#listByCustomerId'
  - provenance: test
    source: 'services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#lists the customer''s tenants'
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#does not list another
      customer's tenant
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#reduces the list to the
      tenants the caller may reach
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses an anonymous call as
      401
  - provenance: test
    source: 'services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#listTenantsByParentId'
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers the parent's children
      as items with their count
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers no children for a
      tenant that has none
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses an anonymous call as
      401
  - provenance: test
    source: 'services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#getDefaultTenantForCustomer'
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers the customer's default
      tenant
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers 404 for another
      customer's default tenant, so the route cannot be walked
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers 200 and null when the
      caller may reach none of the customer’s tenants
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses an anonymous call as
      401
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#patchTenant: changing the time
      zone
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers 200 to a change to
      another IANA zone
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers the tenant in its new
      zone
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses a zone that is not an
      IANA location as 400
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#leaves the stored zone as the
      last accepted one
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#leaves the version where the
      accepted change left it
  - provenance: test
    source: 'services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#the two axes a tenant has'
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers the lifecycle state of
      a tenant created ready to use
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers when the tenant became
      active
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses a status the closed
      list no longer has as 400
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#leaves the tenant in sandbox
      after that refusal
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#accepts a replacement that
      echoes the lifecycle state back, as every round trip does
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers 200 to a patch aimed
      at the lifecycle state, because the property is simply dropped
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#leaves the lifecycle state
      where the server put it after such a patch
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#leaves the activation instant
      where the server put it, whatever a client sends
  - provenance: test
    source: 'services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#going live, then disabled'
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers 200 and the live
      status to the HQ patch
  - provenance: test
    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
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers the disabled status to
      the patch that follows
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#leaves the lifecycle state
      alone, because the status axis never moves it
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#persists the last status
      reached
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses a replacement at a
      stale version as 409
  - provenance: test
    source: 'services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#updateTenant'
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers 200 for a replacement
      at the version read
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers the replaced name with
      the version bumped
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#persists the replacement, read
      back through the API
  - provenance: test
    source: 'services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses an unknown id as 404'
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses moving a tenant to a
      customer that does not exist as 409
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses an anonymous call as
      401
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#leaves the record unchanged
      after the refusals above
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#deleteTenant, which no longer
      deletes anything
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#read the tenant before the
      call
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers the gone status the
      error contract can express
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#points the caller at the
      deletion request route
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#says the deletion waits, is
      notified and can be cancelled, so nobody reads this as a refusal to delete
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#leaves the tenant exactly as
      it was, which is the point of refusing
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers the same to a tenant
      that does not exist, because nothing is read before the refusal
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers the same for a seeded
      tenant with children
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#leaves that seeded tenant
      readable
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses an anonymous call as
      401
  - provenance: test
    source: 'services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#the tenant id'
  - provenance: test
    source: 'services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#stores the id a create names'
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#stores an id normalized,
      trimmed and lowercase
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#reads FAA.Org as faa.org, and
      so answers it taken by the well-known tenant: 409 tenant_id_taken
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses a create that names no
      id as 400 tenant_id_required, naming id
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses a UUID-shaped id as
      400 tenant_id_invalid, nothing generating ids any more
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses an id with two dots
      together as 400 tenant_id_invalid
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses a reserved id as 400
      tenant_id_reserved
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses an id another tenant
      has as 409 tenant_id_taken
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses a create that sends
      domain as 400, naming the unknown property
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers no domain on the HQ
      read, the id being the tenant’s one identifier
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#a migrated association’s round
      trip
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#creates rubber.org under its
      own new customer rubber.org
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#creates the sandbox
      sandbox.rubber.org under it
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers the security context
      of sandbox.rubber.org for ?tenant_id=sandbox.rubber.org
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#lists both tenants in that
      context, each by its readable id
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers 404 tenant_not_found
      for ?tenant_id=nobody.org
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#carries sandbox.rubber.org as
      the path tenant of a tenant route through the front door
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#refuses that path tenant to a
      context whose tenants omit it, the control for the front door
  - provenance: test
    source: 'services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#routing'
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers 404 for a path no
      route declares
  - provenance: test
    source: >-
      services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js#answers 405 for a method a
      declared path does not take
dependency_evidence: >-
  The local request harness exercises the route dispatcher and the prepared database. The file
  declares no substituted collaborators.
evidence:
  - 'services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js'
  - >-
    Static review at the recorded source revision; executable results remain not-run and conformance
    remains not-verified.
binding_note: >-
  Each binding names the scenario to which this file contributes assertions. A binding is not a
  recorded pass and does not extend the file’s dependency boundary.
examiner: codex
examined_at: '2026-10-23'
final_text: OpenAI
dependency_review:
  provenance: test
  source: 'services-platform:modules/tenants/tests/e2e/tenants.e2e.spec.js'
  explicit_no_doubles: true
  identified_double_boundaries: []
---
# Workspaces request checks

## Verification Boundary

The file exercises public request handling through the local service harness. The assertion references identify the source checks for workspaces.

## What This Suite Proves

The source assertions support the observations named in the bound scenarios. A scenario spanning multiple files must retain the other files’ contributions.

## What It Does Not Prove

This examination does not run the suite. Passing behavior, deployed conformance and the behavior of substituted dependencies require separate execution evidence.

## Real Dependencies and Test Doubles

The local request harness exercises the route dispatcher and the prepared database. The file declares no substituted collaborators.

## Must Not Be Doubled

Keep route dispatch, signed-context verification and the exercised service decisions real. A test key can supply signatures, but replacing the authorization decision cannot prove request enforcement.
