---
id: DOM-PFM-SEC-001
title: Customer
realises: CON-PFM-SEC-001
product_area: platform
module: security
revision: 1
status: draft
design_intent: proposed
implementation_evidence: observed
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
owned_by: SVC-PFM-SEC-customers
readable_by:
- SVC-PFM-SEC-tenants
- SVC-PFM-SEC-security
custom_fields: none
identity: The creator chooses a permanent customer identifier. Normalization trims and lowercases it. Its length
  is one to sixty-four characters; letters, digits, dots, hyphens and underscores are permitted, with alphanumeric
  ends and no adjacent dots. Reserved names and generated-identifier shapes are rejected. Migrated customers
  use the normalized earlier identifier.
attributes:
- name: identifier
  kind: text
  required: true
  computed: false
  notes: A permanent name chosen when the customer is created, using the workspace identifier grammar.
- name: name
  kind: text
  required: false
  computed: false
  notes: The organization name shown to staff.
- name: e-mail address
  kind: text
  required: false
  computed: false
  notes: An optional contact address; persistence lowercases it and converts a blank to absence.
- name: customer type
  kind: enum
  required: true
  computed: false
  notes: Classification as customer, trial, demo or training.
- name: commercial company reference
  kind: reference
  required: false
  computed: false
  notes: The commercial company used to locate licensing contracts; provisioning inherits it when no workspace
    reference is supplied.
- name: accounting customer reference
  kind: reference
  required: false
  computed: false
  notes: The customer record used by QuickBooks Online for billing.
- name: workspace count
  kind: computed
  required: true
  computed: true
  notes: HQ computes this from the current workspace rows when reading customers.
- name: record facts
  kind: collection
  required: true
  computed: true
  notes: 'Shared record metadata: version, creation and modification actors and times, and update/delete locks.'
relationships:
- to: DOM-PFM-SEC-002
  cardinality: one customer to zero or more workspaces
  ownership: Workspaces store their customer reference, and that reference prevents customer deletion while
    any workspace remains.
  cross_service: false
- to: DOM-PFM-SEC-003
  cardinality: one customer to zero or more console memberships and custom access definitions
  ownership: Memberships and custom definitions store the customer reference. Staff memberships belong to Rhythm’s
    customer; standing-access reconciliation supplies eligible administrators with grants into other customers.
  cross_service: false
invariants:
- id: INV-DOM-PFM-SEC-001-01
  statement: Customer identifiers are normalized, unique and permanent; reserved names and generated-identifier
    shapes are refused.
  enforced_at:
  - api
  - service
  - database
  provenance: observed
  source: services-platform:modules/customers/services/persistence/customers.ts:requireCustomerId
- id: INV-DOM-PFM-SEC-001-02
  statement: 'A customer must use one of the four declared classifications: customer, trial, demo or training.'
  enforced_at:
  - api
  - database
  provenance: observed
  source: services-platform:modules/customers/db/customers.table.ts:customers (customers_type_check)
- id: INV-DOM-PFM-SEC-001-03
  statement: Persistence rejects invalid contact addresses and stores valid addresses in lowercase; absence
    is allowed.
  enforced_at:
  - service
  - database
  provenance: observed
  source: services-platform:modules/customers/services/persistence/customers.ts:customerRowInput
- id: INV-DOM-PFM-SEC-001-04
  statement: A remaining workspace reference prevents the database from deleting its customer.
  enforced_at:
  - database
  provenance: test
  source: services-platform:modules/customers/tests/integration/db/customers.table.integration.spec.js#refuses
    deleting a customer that tenants still reference by tenants_customer_fk
- id: INV-DOM-PFM-SEC-001-05
  statement: Customer persistence refuses updates under an update lock and deletion under a delete lock.
  enforced_at:
  - service
  provenance: observed
  source: services-platform:modules/customers/services/persistence/customers.ts:updateCustomer, deleteCustomer
- id: INV-DOM-PFM-SEC-001-06
  statement: Version-checked customer writes reject stale versions without applying the requested fields.
  enforced_at:
  - service
  provenance: observed
  source: services-platform:modules/customers/services/persistence/customers.ts:updateCustomer (versionedRowPredicate)
- id: INV-DOM-PFM-SEC-001-07
  statement: Reconciliation creates standing grants for eligible Rhythm Administrators outside Rhythm’s customer
    and retains manual revocations; deleting a customer removes its standing grants in the same transaction.
  enforced_at:
  - service
  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;
    modules/security/services/staff-access/ensure-standing-access.ts:ensureStandingAccess
physical:
- platform.customers
evidence:
- 'services-platform at ad3f6a65: modules/customers/db/customers.table.ts; services/persistence/customers.ts;
  aws/api/customers.routes.ts, customer-api-mapper.ts, customers.schemas.ts; modules/tenants/db/record-slug.ts;
  modules/security/services/staff-access/ensure-standing-access.ts; docs/standards/custom-field-capability.md
  §2; docs/standards/record-write-contracts/compliance-by-service.md.'
examined_at: '2026-10-23'
examiner: codex
---

# Customer

## What It Models

The customer represents the organization that Rhythm licenses and bills. Its record holds the organization’s identity and classification, contact address, and commercial and accounting references. The Customers service owns these fields; the workspace count is calculated for HQ reads.

## Identity and Attributes

The creator chooses a permanent customer identifier. Normalization trims and lowercases it. Its length is one to sixty-four characters; letters, digits, dots, hyphens and underscores are permitted, with alphanumeric ends and no adjacent dots. Reserved names and generated-identifier shapes are rejected. Migrated customers use the normalized earlier identifier.

The attribute rows distinguish stored fields, computed answers and supporting records.

## Relationships

Workspaces store their customer reference, and that reference prevents customer deletion while any workspace remains. Memberships and custom definitions store the customer reference. Staff memberships belong to Rhythm’s customer; standing-access reconciliation supplies eligible administrators with grants into other customers.

## Invariants

The structured invariant rows identify each protection, its enforcement layer and its evidence. Read their qualifications with the statement rather than treating a service check as a database constraint.

## How It Is Stored and Shared

Workspaces, console memberships and custom access definitions refer to the customer while retaining their own service ownership. Workspace provisioning can create the first customer in its transaction and inherit its commercial reference. Licensing uses that reference to locate contracts. Customer access is restricted to the caller’s reachable organization, with inaccessible records returned as absent.

## Open Design Questions

The structured invariants define identity, validation, locking and deletion. Custom fields are disabled by the product classification and the absence of an enabling registration. Customer deletion also removes standing staff grants. The ordinary creation path reconciles those grants; the HQ creation path omits that call, leaving a recorded defect.

The planning safeguards for deletion are stronger than the implementation: membership and definition checks, typed-name confirmation, a reason and security history remain outstanding. Commercial-reference authority and replacement/patch version handling also need resolution before implementation preparation.
