---
id: ATS-PFM-MTD-006
scope: CAP-PFM-MTD-006
product_area: platform
module: metadata
revision: 2
status: proposed
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
scenarios:
  - id: ATS-PFM-MTD-006-01
    title: Replacement removes omitted rule kinds
    level: api
    proves:
      - BR-CAP-PFM-MTD-006-01
    preconditions: A property has several rules.
    steps:
      - do: Save a smaller set and inspect rules and storage.
        provenance: test
        source: >-
          services-platform:modules/metadata/tests/integration/services/persistence/custom-fields.rules.integration.spec.js#removes
          the kinds a replacement leaves out
    expected: 'Omitted kinds are gone, kinds are unique and default staff exposure needs no row.'
    negative: false
    data_needs: A property has several rules.
    bound_to:
      - >-
        services-platform:modules/metadata/tests/integration/services/persistence/custom-fields.rules.integration.spec.js#removes
        the kinds a replacement leaves out
      - >-
        services-platform:modules/metadata/tests/integration/services/persistence/custom-fields.rules.integration.spec.js#stores
        one row per kind, and exposure staff as none
      - >-
        services-platform:modules/metadata/tests/integration/db/custom-field-rules.table.integration.spec.js#refuses
        a second rule of the same kind on the field, by the primary key
      - TST-PFM-MTD-120
      - TST-PFM-MTD-109
    provenance: test
    source: >-
      services-platform:modules/metadata/tests/integration/services/persistence/custom-fields.rules.integration.spec.js#removes
      the kinds a replacement leaves out
    category: rule
    assertions:
      - expect: 'Omitted kinds are gone, kinds are unique and default staff exposure needs no row.'
        provenance: test
        source: >-
          services-platform:modules/metadata/tests/integration/services/persistence/custom-fields.rules.integration.spec.js#removes
          the kinds a replacement leaves out
  - id: ATS-PFM-MTD-006-02
    title: Conditions use valid fields and bounded storage
    level: api
    proves:
      - BR-CAP-PFM-MTD-006-02
      - INV-DOM-PFM-MTD-002-06
    preconditions: Rule replacement is available.
    steps:
      - do: Submit unknown and self references and conditions at and beyond the stored size limit.
        provenance: test
        source: >-
          services-platform:modules/metadata/tests/integration/services/persistence/custom-fields.rules.integration.spec.js#refuses
          a condition naming a field the object does not have, and leaves the rules unchanged
    expected: 'Unknown, self and oversized conditions fail without changing rules; the boundary size succeeds.'
    negative: true
    data_needs: Rule replacement is available.
    bound_to:
      - >-
        services-platform:modules/metadata/tests/integration/services/persistence/custom-fields.rules.integration.spec.js#refuses
        a condition naming a field the object does not have, and leaves the rules unchanged
      - >-
        services-platform:modules/metadata/tests/unit/custom-object-properties.spec.ts#refuses a field
        required because of itself
      - >-
        services-platform:modules/metadata/tests/integration/services/persistence/custom-fields.rules.integration.spec.js#accepts
        a condition exactly at the stored size limit
      - >-
        services-platform:modules/metadata/tests/integration/services/persistence/custom-fields.rules.integration.spec.js#refuses
        a condition one byte over the stored size limit as invalid rules, and leaves the rules unchanged
      - TST-PFM-MTD-120
      - TST-PFM-MTD-129
    provenance: test
    source: >-
      services-platform:modules/metadata/tests/integration/services/persistence/custom-fields.rules.integration.spec.js#refuses
      a condition naming a field the object does not have, and leaves the rules unchanged
    category: boundary
    assertions:
      - expect: 'Unknown, self and oversized conditions fail without changing rules; the boundary size succeeds.'
        provenance: test
        source: >-
          services-platform:modules/metadata/tests/integration/services/persistence/custom-fields.rules.integration.spec.js#refuses
          a condition naming a field the object does not have, and leaves the rules unchanged
  - id: ATS-PFM-MTD-006-03
    title: Uniqueness checks existing data before enabling
    level: api
    proves:
      - BR-CAP-PFM-MTD-006-03
      - INV-DOM-PFM-MTD-002-07
    preconditions: Some boats share a property value while another property is unique.
    steps:
      - do: Enable uniqueness for each and repeat with no checker registered.
        provenance: test
        source: >-
          services-platform:modules/custom-objects/tests/integration/services/persistence/custom-object-records.integration.spec.js#refuses
          a unique rule on a property two records already share, with the count
    expected: >-
      Duplicates report their count, unique data enables enforcement and an unavailable checker refuses the
      rule.
    negative: true
    data_needs: Some boats share a property value while another property is unique.
    bound_to:
      - >-
        services-platform:modules/custom-objects/tests/integration/services/persistence/custom-object-records.integration.spec.js#refuses
        a unique rule on a property two records already share, with the count
      - >-
        services-platform:modules/custom-objects/tests/integration/services/persistence/custom-object-records.integration.spec.js#stores
        a unique rule once the values are unique, and enforces it from then on
      - >-
        services-platform:modules/metadata/tests/integration/services/persistence/custom-fields.rules.integration.spec.js#refuses
        a unique rule while nothing can check the object’s values for uniqueness
      - TST-PFM-MTD-065
      - TST-PFM-MTD-120
    provenance: test
    source: >-
      services-platform:modules/custom-objects/tests/integration/services/persistence/custom-object-records.integration.spec.js#refuses
      a unique rule on a property two records already share, with the count
    category: interaction
    assertions:
      - expect: >-
          Duplicates report their count, unique data enables enforcement and an unavailable checker refuses
          the rule.
        provenance: test
        source: >-
          services-platform:modules/custom-objects/tests/integration/services/persistence/custom-object-records.integration.spec.js#refuses
          a unique rule on a property two records already share, with the count
  - id: ATS-PFM-MTD-006-04
    title: Defaults agree with the property type
    level: unit
    proves:
      - BR-CAP-PFM-MTD-006-04
    preconditions: A field definition is available.
    steps:
      - do: Validate compatible and incompatible literal defaults.
        provenance: test
        source: >-
          services-platform:modules/metadata/tests/unit/custom-object-properties.spec.ts#refuses a default the
          field cannot hold
    expected: The compatible value is accepted and the other fails.
    negative: true
    data_needs: A field definition is available.
    bound_to:
      - >-
        services-platform:modules/metadata/tests/unit/custom-object-properties.spec.ts#accepts a public
        exposure and a literal default the field can hold
      - >-
        services-platform:modules/metadata/tests/unit/custom-object-properties.spec.ts#refuses a default the
        field cannot hold
      - TST-PFM-MTD-129
    provenance: test
    source: >-
      services-platform:modules/metadata/tests/unit/custom-object-properties.spec.ts#refuses a default the
      field cannot hold
    category: validation
    assertions:
      - expect: The compatible value is accepted and the other fails.
        provenance: test
        source: >-
          services-platform:modules/metadata/tests/unit/custom-object-properties.spec.ts#refuses a default the
          field cannot hold
  - id: ATS-PFM-MTD-006-05
    title: Exposure admits only supported audiences
    level: unit
    proves:
      - BR-CAP-PFM-MTD-006-05
    preconditions: A property definition is available.
    steps:
      - do: Validate public exposure and an unsupported exposure value.
        provenance: test
        source: >-
          services-platform:modules/metadata/tests/unit/custom-object-properties.spec.ts#refuses an exposure
          off the ladder before the description is read
    expected: The supported value succeeds and the other is rejected.
    negative: true
    data_needs: A property definition is available.
    bound_to:
      - >-
        services-platform:modules/metadata/tests/unit/custom-object-properties.spec.ts#refuses an exposure off
        the ladder before the description is read
      - >-
        services-platform:modules/metadata/tests/integration/db/custom-field-rules.table.integration.spec.js#refuses
        an exposure rule without its value, by the shape check
      - TST-PFM-MTD-129
      - TST-PFM-MTD-109
    provenance: test
    source: >-
      services-platform:modules/metadata/tests/unit/custom-object-properties.spec.ts#refuses an exposure off
      the ladder before the description is read
    category: permission
    assertions:
      - expect: The supported value succeeds and the other is rejected.
        provenance: test
        source: >-
          services-platform:modules/metadata/tests/unit/custom-object-properties.spec.ts#refuses an exposure
          off the ladder before the description is read
  - id: ATS-PFM-MTD-006-06
    title: Dependencies protect custom-object properties
    level: browser
    proves:
      - BR-CAP-PFM-MTD-006-06
      - INV-DOM-PFM-MTD-002-08
    preconditions: One property condition names another property.
    steps:
      - do: Archive the named property before and after changing the dependent condition.
        provenance: test
        source: >-
          services-platform:modules/metadata/tests/integration/services/persistence/custom-fields.rules.integration.spec.js#refuses
          the archive naming each dependent property and rule, and leaves the field and the rules unchanged
    expected: The dependency refusal preserves both field and rules; after correction the archival succeeds.
    negative: true
    data_needs: One property condition names another property.
    bound_to:
      - >-
        services-platform:modules/metadata/tests/integration/services/persistence/custom-fields.rules.integration.spec.js#refuses
        the archive naming each dependent property and rule, and leaves the field and the rules unchanged
      - >-
        services-platform:modules/metadata/tests/integration/services/persistence/custom-fields.rules.integration.spec.js#archives
        it once the rules are emptied
      - >-
        react-console:acceptance/custom-objects/playwright/journeys/PLAT-M5-S09.spec.ts#PLAT-M5-S09: archiving
        a property another rule depends on is refused, naming the rule
      - TST-PFM-MTD-120
      - TST-PFM-MTD-009
    provenance: test
    source: >-
      services-platform:modules/metadata/tests/integration/services/persistence/custom-fields.rules.integration.spec.js#refuses
      the archive naming each dependent property and rule, and leaves the field and the rules unchanged
    category: interaction
    assertions:
      - expect: The dependency refusal preserves both field and rules; after correction the archival succeeds.
        provenance: test
        source: >-
          services-platform:modules/metadata/tests/integration/services/persistence/custom-fields.rules.integration.spec.js#refuses
          the archive naming each dependent property and rule, and leaves the field and the rules unchanged
  - id: ATS-PFM-MTD-006-07
    title: Archival removes the field’s own rules
    level: api
    proves:
      - BR-CAP-PFM-MTD-006-07
    preconditions: A field has a rule set.
    steps:
      - do: 'Archive it, read its rules and try replacing them.'
        provenance: test
        source: >-
          services-platform:modules/metadata/tests/integration/services/persistence/custom-fields.rules.integration.spec.js#removes
          a field’s rules when the field is archived
    expected: Its own rules disappear and replacement is refused until restoration.
    negative: true
    data_needs: A field has a rule set.
    bound_to:
      - >-
        services-platform:modules/metadata/tests/integration/services/persistence/custom-fields.rules.integration.spec.js#removes
        a field’s rules when the field is archived
      - >-
        services-platform:modules/metadata/tests/integration/services/persistence/custom-fields.rules.integration.spec.js#refuses
        the rules of an archived field
      - TST-PFM-MTD-120
    provenance: test
    source: >-
      services-platform:modules/metadata/tests/integration/services/persistence/custom-fields.rules.integration.spec.js#removes
      a field’s rules when the field is archived
    category: transition
    assertions:
      - expect: Its own rules disappear and replacement is refused until restoration.
        provenance: test
        source: >-
          services-platform:modules/metadata/tests/integration/services/persistence/custom-fields.rules.integration.spec.js#removes
          a field’s rules when the field is archived
  - id: ATS-PFM-MTD-006-08
    title: Rule writes invalidate query descriptions
    level: api
    proves:
      - BR-CAP-PFM-MTD-006-08
      - INV-DOM-PFM-MTD-002-09
    preconditions: The workspace has a query description stamp.
    steps:
      - do: Write a field rule.
        provenance: test
        source: >-
          services-platform:modules/metadata/tests/integration/db/custom-field-rules.table.integration.spec.js#moves
          the tenant’s query description stamp when a rule is written
    expected: The stamp advances in the transaction.
    negative: false
    data_needs: The workspace has a query description stamp.
    bound_to:
      - >-
        services-platform:modules/metadata/tests/integration/db/custom-field-rules.table.integration.spec.js#moves
        the tenant’s query description stamp when a rule is written
      - TST-PFM-MTD-109
    provenance: test
    source: >-
      services-platform:modules/metadata/tests/integration/db/custom-field-rules.table.integration.spec.js#moves
      the tenant’s query description stamp when a rule is written
    category: invariant
    assertions:
      - expect: The stamp advances in the transaction.
        provenance: test
        source: >-
          services-platform:modules/metadata/tests/integration/db/custom-field-rules.table.integration.spec.js#moves
          the tenant’s query description stamp when a rule is written
  - id: ATS-PFM-MTD-006-09
    title: Native fields lack the custom-object dependency safeguard
    level: api
    proves:
      - BR-CAP-PFM-MTD-006-09
    preconditions: A contact field is referenced by another condition.
    steps:
      - do: Archive the referenced field.
        provenance: test
        source: >-
          services-platform:modules/metadata/tests/integration/services/persistence/custom-fields.rules.integration.spec.js#does
          not apply to a native object: a contacts field its rule depends on is archived
    expected: Archival succeeds despite that dependency.
    negative: false
    data_needs: A contact field is referenced by another condition.
    bound_to:
      - >-
        services-platform:modules/metadata/tests/integration/services/persistence/custom-fields.rules.integration.spec.js#does
        not apply to a native object: a contacts field its rule depends on is archived
      - TST-PFM-MTD-120
    provenance: test
    source: >-
      services-platform:modules/metadata/tests/integration/services/persistence/custom-fields.rules.integration.spec.js#does
      not apply to a native object: a contacts field its rule depends on is archived
    category: edge
    assertions:
      - expect: Archival succeeds despite that dependency.
        provenance: test
        source: >-
          services-platform:modules/metadata/tests/integration/services/persistence/custom-fields.rules.integration.spec.js#does
          not apply to a native object: a contacts field its rule depends on is archived
  - id: ATS-PFM-MTD-006-10
    title: Uniqueness and exposure affect different record outcomes
    category: interaction
    level: api
    exercises:
      - CAP-PFM-MTD-006
      - CAP-PFM-MTD-011
      - CAP-PFM-MTD-012
    proves:
      - BR-CAP-PFM-MTD-006-03
      - BR-CAP-PFM-MTD-006-05
      - BR-CAP-PFM-MTD-012-07
      - BR-CAP-PFM-MTD-011-06
    preconditions: An active object has a unique property and staff and public audience projections.
    steps:
      - do: >-
          Enable uniqueness and public exposure, create a record, attempt a normalized duplicate and project
          the surviving record for both audiences.
        provenance: proposed
        source: &ref_0
          - >-
            services-platform:modules/custom-objects/tests/integration/services/persistence/custom-object-records.integration.spec.js#refuses
            a unique rule on a property two records already share, with the count
          - >-
            services-platform:modules/metadata/tests/unit/custom-object-properties.spec.ts#refuses an exposure
            off the ladder before the description is read
          - >-
            services-platform:modules/custom-objects/tests/integration/services/persistence/custom-object-records.integration.spec.js#refuses
            a hull number another boat holds, naming the property and the boat
          - >-
            services-platform:modules/custom-objects/tests/unit/exposure.spec.ts#shows a portal member the
            portal and public properties
    expected: Check the duplicate refusal separately from the audience projection.
    negative: false
    data_needs: An active object has a unique property and staff and public audience projections.
    bound_to: []
    provenance: proposed
    source: *ref_0
    assertions:
      - expect: Check the duplicate refusal separately from the audience projection.
        provenance: proposed
        source: *ref_0
  - id: ATS-PFM-MTD-006-11
    title: A failed rule save leaves the earlier field definition
    proves:
      - BR-CAP-PFM-MTD-006-02
      - BR-CAP-PFM-MTD-005-03
    preconditions: The administrator creates a new property through the console.
    steps:
      - do: >-
          Allow definition creation, submit an invalid condition in the later rule request and reopen the
          property.
        provenance: proposed
        source: >-
          specs/platform/metadata/design/workflows/WF-PFM-MTD-003-save-a-field-definition-and-its-rules.md:hops
    expected: >-
      The new definition remains stored and the invalid rule set is absent; the person can correct and retry
      it.
    source: 'specs/platform/metadata/design/workflows/WF-PFM-MTD-003-save-a-field-definition-and-its-rules.md:hops'
    category: failure
    level: browser
    negative: true
    data_needs: The administrator creates a new property through the console.
    bound_to: []
    provenance: proposed
    assertions:
      - expect: >-
          The new definition remains stored and the invalid rule set is absent; the person can correct and
          retry it.
        provenance: proposed
        source: >-
          specs/platform/metadata/design/workflows/WF-PFM-MTD-003-save-a-field-definition-and-its-rules.md:hops
evidence:
  - 'services-platform at ad3f6a6582843008ed0f5a17b131878d15829af1: the rules specs named in each scenario.'
  - 'react-console at baf6dae382d6f41dce976c7f848667ccc37e076f: Playwright PLAT-M5-S09.'
  - >-
    Codex testing back-fill: pinned capability, domain object, state model and workflow obligations reviewed;
    existing bound test files and exact case titles checked.
coverage:
  rule: covered
  transition: covered
  validation: covered
  permission: covered
  edge: covered
  failure: covered
  boundary: covered
  concurrency: 'gap: FND-PFM-MTD-068'
  invariant: covered
  interaction: covered
coverage_obligations:
  - rule: BR-CAP-PFM-MTD-006-01
    scenarios:
      - ATS-PFM-MTD-006-01
    finding: null
    provenance: documented
    source: >-
      specs/platform/metadata/planning/capabilities/CAP-PFM-MTD-006-make-a-field-required-shown-unique-defaulted-or-exposed-by.md
  - rule: BR-CAP-PFM-MTD-006-02
    scenarios:
      - ATS-PFM-MTD-006-02
      - ATS-PFM-MTD-006-11
    finding: null
    provenance: documented
    source: >-
      specs/platform/metadata/planning/capabilities/CAP-PFM-MTD-006-make-a-field-required-shown-unique-defaulted-or-exposed-by.md
  - rule: BR-CAP-PFM-MTD-006-03
    scenarios:
      - ATS-PFM-MTD-006-03
      - ATS-PFM-MTD-006-10
    finding: null
    provenance: documented
    source: >-
      specs/platform/metadata/planning/capabilities/CAP-PFM-MTD-006-make-a-field-required-shown-unique-defaulted-or-exposed-by.md
  - rule: BR-CAP-PFM-MTD-006-04
    scenarios:
      - ATS-PFM-MTD-006-04
    finding: null
    provenance: documented
    source: >-
      specs/platform/metadata/planning/capabilities/CAP-PFM-MTD-006-make-a-field-required-shown-unique-defaulted-or-exposed-by.md
  - rule: BR-CAP-PFM-MTD-006-05
    scenarios:
      - ATS-PFM-MTD-006-05
      - ATS-PFM-MTD-006-10
    finding: null
    provenance: documented
    source: >-
      specs/platform/metadata/planning/capabilities/CAP-PFM-MTD-006-make-a-field-required-shown-unique-defaulted-or-exposed-by.md
  - rule: BR-CAP-PFM-MTD-006-06
    scenarios:
      - ATS-PFM-MTD-006-06
    finding: null
    provenance: documented
    source: >-
      specs/platform/metadata/planning/capabilities/CAP-PFM-MTD-006-make-a-field-required-shown-unique-defaulted-or-exposed-by.md
  - rule: BR-CAP-PFM-MTD-006-07
    scenarios:
      - ATS-PFM-MTD-006-07
    finding: null
    provenance: documented
    source: >-
      specs/platform/metadata/planning/capabilities/CAP-PFM-MTD-006-make-a-field-required-shown-unique-defaulted-or-exposed-by.md
  - rule: BR-CAP-PFM-MTD-006-08
    scenarios:
      - ATS-PFM-MTD-006-08
    finding: null
    provenance: documented
    source: >-
      specs/platform/metadata/planning/capabilities/CAP-PFM-MTD-006-make-a-field-required-shown-unique-defaulted-or-exposed-by.md
  - rule: BR-CAP-PFM-MTD-006-09
    scenarios:
      - ATS-PFM-MTD-006-09
    finding: null
    provenance: documented
    source: >-
      specs/platform/metadata/planning/capabilities/CAP-PFM-MTD-006-make-a-field-required-shown-unique-defaulted-or-exposed-by.md
interactions:
  - with: CAP-PFM-MTD-011
    scenarios:
      - ATS-PFM-MTD-006-10
    finding: null
    provenance: proposed
    source: >-
      specs/platform/metadata/planning/capabilities/CAP-PFM-MTD-006-make-a-field-required-shown-unique-defaulted-or-exposed-by.md
  - with: CAP-PFM-MTD-012
    scenarios:
      - ATS-PFM-MTD-006-10
    finding: null
    provenance: proposed
    source: >-
      specs/platform/metadata/planning/capabilities/CAP-PFM-MTD-006-make-a-field-required-shown-unique-defaulted-or-exposed-by.md
---

# Configure Field Requirements and Exposure: Capability Test Specification

## Coverage

- Obligation 01: 1 scenario cite this obligation.
- Obligation 02: 2 scenarios cite this obligation.
- Obligation 03: 2 scenarios cite this obligation.
- Obligation 04: 1 scenario cite this obligation.
- Obligation 05: 2 scenarios cite this obligation.
- Obligation 06: 1 scenario cite this obligation.
- Obligation 07: 1 scenario cite this obligation.
- Obligation 08: 1 scenario cite this obligation.
- Obligation 09: 1 scenario cite this obligation.

Category coverage identifies the kind of proof present. Detailed transition, permission and invariant obligations and unbound proposals remain in the coverage finding until their individual cases are accounted for.

## Interactions With Related Capabilities

Exposure does not bypass uniqueness when records are written. The structured interaction rows identify the related capabilities exercised and any remaining gap. Cross-capability workflow seams remain subject to the detailed coverage audit.
