---
id: TST-PFM-SEC-044
title: Customers database and service checks
kind: integration
product_area: platform
module: security
revision: 2
status: draft
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
repository: services-platform
files:
  - modules/customers/tests/integration/services/persistence/customers.integration.spec.js
implements:
  - ATS-PFM-SEC-001-02
  - ATS-PFM-SEC-001-04
  - ATS-PFM-SEC-001-06
  - ATS-PFM-SEC-001-08
environment: local
implementation_state: implemented
latest_result: not-run
latest_run_at: null
latest_run_ref: null
conformance: not-verified
estimated_minutes: 3
isolation: Use the prepared test database and suite-owned fixture rows; retain shared seed records.
assertion_evidence:
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#customers
      persistence: createCustomer
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#answers
      the customer with the fields it was given
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#stamps
      version 1 with the caller as creator and as last modifier
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#stamps
      the created and last-modified instants at the same moment
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#persists
      exactly the record it answered
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#accepts
      a body carrying the server-owned system properties and ignores their values
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#writes
      the two client-settable system columns the body names
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#refuses
      an id that already exists as 409 customer_id_taken, naming the property
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#reads
      a padded id in capitals as the id it normalizes to, and so finds it taken
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#refuses
      a create that names no id as customer_id_required, nothing generating one
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#refuses
      the shape of a generated UUID as customer_id_invalid
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#refuses
      a reserved id as customer_id_reserved
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#leaves
      the existing customer untouched when it refuses the duplicate id
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#customers
      persistence: the e-mail address
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#stores
      an address in its canonical form on create
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#stores
      an address in its canonical form on replace
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#stores
      a blank address as none
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#refuses
      an invalid address on create as ObjectInvalid naming the field
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#writes
      nothing when it refuses an invalid address on create
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#refuses
      an invalid address on replace as ObjectInvalid, leaving the customer unchanged
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#customers
      persistence: getCustomer
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#reads
      a seeded well-known customer with its own fields
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#answers
      a seeded instant as an ISO 8601 UTC timestamp
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#answers
      undefined for an unknown id
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#omits
      the properties the row does not have rather than returning nulls
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#customers
      persistence: listCustomers
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#lists
      the seeded well-known customers
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#returns
      the customers in id order
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#carries
      no custom-field values, which customers do not have
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#customers
      persistence: updateCustomer
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#replacing
      a customer at the version it was read at
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#answers
      the replaced fields
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#bumps
      the version and stamps the updater, keeping the original creator
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#persists
      exactly the record it answered
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#clears
      a property the replacement omits
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#clears
      from the row, not only from the answer, the property the replacement omits
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#refuses
      a stale version as StaleObject
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#leaves
      the row at the version it reached when it refuses a stale version
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#refuses
      an unknown id as RecordNotFound
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#refuses
      a record locked against updates as IllegalOperation
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#leaves
      a record locked against updates unchanged
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#updates
      a record locked against deletes alone, which the update guard does not refuse
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#customers
      persistence: deleteCustomer
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#answers
      the id of the customer it deleted
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#leaves
      no row behind
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#refuses
      an unknown id as RecordNotFound
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#refuses
      a record locked against deletes as IllegalOperation
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#refuses
      a record locked against updates and deletes as IllegalOperation
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#leaves
      a locked record in place
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#refuses
      a customer that still has tenants as a ForeignKeyViolation
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#leaves
      a customer that still has tenants in place
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#execution
      context: transactions and propagation (customers)
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#a
      transaction the caller aborts
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#runs
      the callback in a context that says it is in a transaction
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#makes
      the repository write visible to reads on the same transaction
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#lets
      the callback’s own error out
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#rolls
      the writes back together, leaving no customer behind
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#a
      transaction the callback completes
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#hands
      the open transaction to a nested withTransaction rather than opening another
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#answers
      the record the nested call produced
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#commits
      the writes when the callback returns
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#a
      transaction opened from a context with its own caller, clock and request
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#keeps
      the request, the caller and the clock of the context it derived from
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#reads
      the fixed clock as the transaction’s now
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#stamps
      the write with that caller and that instant
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#logs
      the transaction’s start and commit, and nothing between them
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#binds
      the request and the caller to the transaction’s log lines
  - provenance: test
    source: >-
      services-platform:modules/customers/tests/integration/services/persistence/customers.integration.spec.js#writes
      outside any transaction, with the test actor, through the plain context
dependency_evidence: >-
  The prepared PostgreSQL database supplies the persisted fixtures and constraints exercised here.
  The file declares no substituted collaborators.
evidence:
  - >-
    services-platform:modules/customers/tests/integration/services/persistence/customers.integration.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/customers/tests/integration/services/persistence/customers.integration.spec.js
  explicit_no_doubles: true
  identified_double_boundaries: []
---
# Customers database and service checks

## Verification Boundary

The file exercises database or service behavior through the local integration harness. The assertion references identify the source checks for customers.

## 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 prepared PostgreSQL database supplies the persisted fixtures and constraints exercised here. The file declares no substituted collaborators.

## Must Not Be Doubled

Keep the queried database, applicable constraints and transaction boundaries real. Provider substitutes cannot establish delivery, cloud execution or cross-service recovery.
