---
id: TST-PFM-MTD-067
title: custom objects
kind: integration
product_area: platform
module: metadata
revision: 1
status: draft
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
repository: services-platform
files:
  - modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js
implements:
  - ATS-PFM-MTD-009-01
  - ATS-PFM-MTD-009-02
  - ATS-PFM-MTD-009-03
  - ATS-PFM-MTD-009-04
  - ATS-PFM-MTD-009-05
  - ATS-PFM-MTD-009-06
  - ATS-PFM-MTD-009-07
  - ATS-PFM-MTD-009-08
  - ATS-PFM-MTD-009-09
  - ATS-PFM-MTD-010-01
  - ATS-PFM-MTD-010-02
  - ATS-PFM-MTD-010-05
environment: local
implementation_state: implemented
latest_result: not-run
latest_run_at: null
latest_run_ref: null
conformance: not-verified
estimated_minutes: 5
isolation: >-
  Prepared integration database and the suite fixture records; fixture teardown restores or removes its own
  rows.
evidence:
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#creates
    a draft at version 1 whose object id is objects. and the plural key
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#records
    the create in the security trail, with the fields it stated by name
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
    a plural key that is not a snake_case word, and writes nothing
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
    a key that is not a configuration id
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
    an object id the tenant already has, naming the plural key
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
    a key the tenant already has
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
    the published rule on an object that is not publishable
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#accepts
    the published rule on a publishable object
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
    a portal rules document of the wrong shape, naming where
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
    an owner type that does not end at the object
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
    navigation that names a property it does not have
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
    the fifty-first object of a tenant, which holds fifty
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#replaces
    the changeable fields at the version read and bumps the version
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#records
    the replacement with the fields it changed
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
    a replacement at another version, and leaves the row unchanged
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
    a replacement of an object the tenant does not have
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
    a replacement of an archived object
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
    turning publication off while nothing can check the object’s published records
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#turns
    publication off once the record store says no record is published
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
    turning publication off while the record store says a record is published
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#turns
    publication on at any time, with nothing to check
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
    an active object’s display property that is not one of its properties
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#names
    an owner type that ends at the object and gives a record one owner
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
    an owner type that gives a record many owners
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
    an owner_organization rule naming a contact role the tenant does not have, naming the role
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#accepts
    an owner_organization rule naming a contact role the tenant has
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
    an owner_organization rule naming another tenant’s contact role
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
    an eligible rule naming a binding the tenant does not have, whether or not the id is a UUID
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#accepts
    an eligible rule naming a binding the tenant has
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
    portal rules naming an association type that does not relate to the object
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
    activating a draft that names no display property, and leaves it a draft
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
    activating a draft whose display property it does not have
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
    activating a draft whose display property is an image
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#activates
    a draft whose display property is a text property, recording it
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
    activating an object that is already active
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
    an activation at another version
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#archives
    an active object and records it
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
    archiving an object that is already archived
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#restores
    an archived object as a draft, keeping its object id
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
    restoring an object that is not archived
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#keeps
    an archived object’s object id, so a create cannot take it
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#creates
    an object placed in a platform application, with its group
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#creates
    an object placed in a custom app of the tenant
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#creates
    an object with neither a placement nor an owner
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
    an app that is neither an application nor a custom app, naming it, and writes nothing
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#places
    objects in orders, meetings and eligibility, console apps the licensing keys do not carry
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
    a custom app of another tenant as unknown
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
    a new placement in an archived custom app, and writes nothing
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
    a placement with a property it does not know
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
    a group blank once trimmed
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#moves
    an object to another app by a replacement, and names placement in the trail
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#clears
    the placement by a replacement that leaves it out
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
    a replacement that moves an object into an archived custom app, the row unchanged
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#activates
    an object that has neither a placement nor an owner association type (B4: no activation rule for either)
  - >-
    services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#lets
    an archived object keep its placement in an app archived after it (B3: only draft and active objects hold
    an archive back)
fixture_imports:
  - drizzle-orm
  - '@rhythmsoftware/macroservice-testing/refusals'
  - '@rhythmsoftware/macroservice-errors/errors'
  - ../../../../../eligibility/tests/integration/support
  - ../../../../../eligibility/services/persistence/definitions
  - ../../../../../eligibility/services/persistence/bindings
  - ../../../../services/persistence/custom-apps
  - ../../../../../security/db/security-audit-events.table
  - ../../../../db/custom-objects.table
  - ../../../../services/persistence/custom-objects
  - ../../support
test_doubles: []
limitations: []
unmatched_specification: null
binding_assertions:
  - scenario: ATS-PFM-MTD-009-01
    provenance: test
    source:
      - >-
        services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
        a plural key that is not a snake_case word, and writes nothing
      - >-
        services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
        an object id the tenant already has, naming the plural key
      - >-
        services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#keeps
        an archived object’s object id, so a create cannot take it
    note: >-
      These references identify the assertions this suite contributes; bindings to additional suites remain
      part of the scenario’s proof.
  - scenario: ATS-PFM-MTD-009-02
    provenance: test
    source:
      - >-
        services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
        the fifty-first object of a tenant, which holds fifty
    note: >-
      These references identify the assertions this suite contributes; bindings to additional suites remain
      part of the scenario’s proof.
  - scenario: ATS-PFM-MTD-009-03
    provenance: test
    source:
      - >-
        services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
        a replacement of an archived object
    note: >-
      These references identify the assertions this suite contributes; bindings to additional suites remain
      part of the scenario’s proof.
  - scenario: ATS-PFM-MTD-009-04
    provenance: test
    source:
      - >-
        services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
        activating a draft that names no display property, and leaves it a draft
      - >-
        services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
        activating a draft whose display property is an image
      - >-
        services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
        activating an object that is already active
    note: >-
      These references identify the assertions this suite contributes; bindings to additional suites remain
      part of the scenario’s proof.
  - scenario: ATS-PFM-MTD-009-05
    provenance: test
    source:
      - >-
        services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
        an owner type that gives a record many owners
    note: >-
      These references identify the assertions this suite contributes; bindings to additional suites remain
      part of the scenario’s proof.
  - scenario: ATS-PFM-MTD-009-06
    provenance: test
    source:
      - >-
        services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
        turning publication off while the record store says a record is published
      - >-
        services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#turns
        publication off once the record store says no record is published
      - >-
        services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#turns
        publication on at any time, with nothing to check
    note: >-
      These references identify the assertions this suite contributes; bindings to additional suites remain
      part of the scenario’s proof.
  - scenario: ATS-PFM-MTD-009-07
    provenance: test
    source:
      - >-
        services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
        an owner_organization rule naming a contact role the tenant does not have, naming the role
      - >-
        services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
        an owner_organization rule naming another tenant’s contact role
      - >-
        services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
        an eligible rule naming a binding the tenant does not have, whether or not the id is a UUID
      - >-
        services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
        portal rules naming an association type that does not relate to the object
    note: >-
      These references identify the assertions this suite contributes; bindings to additional suites remain
      part of the scenario’s proof.
  - scenario: ATS-PFM-MTD-009-08
    provenance: test
    source:
      - >-
        services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#restores
        an archived object as a draft, keeping its object id
    note: >-
      These references identify the assertions this suite contributes; bindings to additional suites remain
      part of the scenario’s proof.
  - scenario: ATS-PFM-MTD-009-09
    provenance: test
    source:
      - >-
        services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#records
        the create in the security trail, with the fields it stated by name
      - >-
        services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#records
        the replacement with the fields it changed
      - >-
        services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#archives
        an active object and records it
    note: >-
      These references identify the assertions this suite contributes; bindings to additional suites remain
      part of the scenario’s proof.
  - scenario: ATS-PFM-MTD-010-01
    provenance: test
    source:
      - >-
        services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#places
        objects in orders, meetings and eligibility, console apps the licensing keys do not carry
      - >-
        services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
        an app that is neither an application nor a custom app, naming it, and writes nothing
      - >-
        services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
        a custom app of another tenant as unknown
      - >-
        services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
        a group blank once trimmed
    note: >-
      These references identify the assertions this suite contributes; bindings to additional suites remain
      part of the scenario’s proof.
  - scenario: ATS-PFM-MTD-010-02
    provenance: test
    source:
      - >-
        services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#activates
        an object that has neither a placement nor an owner association type (B4: no activation rule for
        either)
    note: >-
      These references identify the assertions this suite contributes; bindings to additional suites remain
      part of the scenario’s proof.
  - scenario: ATS-PFM-MTD-010-05
    provenance: test
    source:
      - >-
        services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
        a new placement in an archived custom app, and writes nothing
      - >-
        services-platform:modules/custom-objects/tests/integration/services/persistence/custom-objects.integration.spec.js#refuses
        a replacement that moves an object into an archived custom app, the row unchanged
    note: >-
      These references identify the assertions this suite contributes; bindings to additional suites remain
      part of the scenario’s proof.
---

# Custom objects

## Verification Boundary

This integration suite checks custom objects and records within the local test harness. The registered file and pinned revision define its boundary.

## What This Suite Proves

The bindings identify the detailed or feature scenarios whose outcomes have assertions in this suite. Original case references remain attached to the detailed scenarios so a reviewer can inspect the exact assertion. Assertions are evidence of implemented checks; no execution result is claimed.

## What It Does Not Prove

The register does not establish a current passing run or full specification conformance. Behavior outside the suite’s fixtures and assertions remains unverified.

## Real Dependencies and Test Doubles

The fixture uses PostgreSQL and the imported persistence or API code. The fixture imports identify the setup seams; this register makes no broader claim that dependencies are undoubled.

## Must Not Be Doubled

The operation under examination and its asserted stored outcomes must remain real within the declared harness. A fixture cannot replace the write, refusal or transactional effect that the bound scenario checks.
