---
id: ATS-ACC-PRD-001
scope: CAP-ACC-PRD-001
product_area: accounting
module: products
revision: 3
status: proposed
approved_by: null
approved_at: null
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
scenarios:
  - id: ATS-ACC-PRD-001-01
    title: Release control protects product kinds
    level: unit
    proves:
      - BR-CAP-ACC-PRD-001-01
    preconditions: The seeded kind register exists.
    steps: 'Attempt insertion, update and deletion as the application role.'
    expected: Every attempted mutation fails and seeded kinds remain intact.
    negative: true
    data_needs: The seeded kind register exists.
    bound_to:
      - >-
        services-accounting:modules/products/tests/integration/db/products.table.integration.spec.js#refuses
        the application role an INSERT
      - >-
        services-accounting:modules/products/tests/integration/db/products.table.integration.spec.js#refuses
        the application role an UPDATE
      - >-
        services-accounting:modules/products/tests/integration/db/products.table.integration.spec.js#refuses
        the application role a DELETE
      - TST-ACC-PRD-031
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/db/products.table.integration.spec.js#refuses the
      application role an INSERT
    category: invariant
    binding_scope:
      - suite: TST-ACC-PRD-031
        assertions:
          - >-
            services-accounting:modules/products/tests/integration/db/products.table.integration.spec.js#refuses
            the application role an INSERT
          - >-
            services-accounting:modules/products/tests/integration/db/products.table.integration.spec.js#refuses
            the application role an UPDATE
          - >-
            services-accounting:modules/products/tests/integration/db/products.table.integration.spec.js#refuses
            the application role a DELETE
        provenance: test
        source: >-
          services-accounting:modules/products/tests/integration/db/products.table.integration.spec.js#refuses
          the application role an INSERT;
          services-accounting:modules/products/tests/integration/db/products.table.integration.spec.js#refuses
          the application role an UPDATE;
          services-accounting:modules/products/tests/integration/db/products.table.integration.spec.js#refuses
          the application role a DELETE
  - id: ATS-ACC-PRD-001-02
    title: The shared register retains ordering and ownership
    level: api
    proves:
      - BR-CAP-ACC-PRD-001-02
      - BR-CAP-ACC-PRD-001-03
    preconditions: A caller can read the global register.
    steps: Read it from ordinary workspace and no-workspace contexts.
    expected: >-
      Accounting’s three kinds lead the domain kinds; owners and extensions are present and inactive kinds
      remain identified.
    negative: false
    data_needs: A caller can read the global register.
    bound_to:
      - >-
        services-accounting:modules/products/tests/e2e/products.e2e.spec.js#answers the three Accounting types
        first, in display order, with their labels and legacy types
      - >-
        services-accounting:modules/products/tests/e2e/products.e2e.spec.js#answers the domains’ types after
        them, each with its owning service and extension table, the Events ones inactive
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/product-types.queries.integration.spec.js#answers
        the same types to a transaction with no tenant, the registry being global
      - TST-ACC-PRD-030
      - TST-ACC-PRD-038
    provenance: test
    source: >-
      services-accounting:modules/products/tests/e2e/products.e2e.spec.js#answers the three Accounting types
      first, in display order, with their labels and legacy types
    category: rule
    binding_scope:
      - suite: TST-ACC-PRD-030
        assertions:
          - >-
            services-accounting:modules/products/tests/e2e/products.e2e.spec.js#answers the three Accounting
            types first, in display order, with their labels and legacy types
          - >-
            services-accounting:modules/products/tests/e2e/products.e2e.spec.js#answers the domains’ types
            after them, each with its owning service and extension table, the Events ones inactive
        provenance: test
        source: >-
          services-accounting:modules/products/tests/e2e/products.e2e.spec.js#answers the three Accounting
          types first, in display order, with their labels and legacy types;
          services-accounting:modules/products/tests/e2e/products.e2e.spec.js#answers the domains’ types after
          them, each with its owning service and extension table, the Events ones inactive;
          services-accounting:modules/products/tests/integration/services/persistence/product-types.queries.integration.spec.js#answers
          the same types to a transaction with no tenant, the registry being global
      - suite: TST-ACC-PRD-038
        assertions:
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/product-types.queries.integration.spec.js#answers
            the same types to a transaction with no tenant, the registry being global
        provenance: test
        source: >-
          services-accounting:modules/products/tests/e2e/products.e2e.spec.js#answers the three Accounting
          types first, in display order, with their labels and legacy types;
          services-accounting:modules/products/tests/e2e/products.e2e.spec.js#answers the domains’ types after
          them, each with its owning service and extension table, the Events ones inactive;
          services-accounting:modules/products/tests/integration/services/persistence/product-types.queries.integration.spec.js#answers
          the same types to a transaction with no tenant, the registry being global
  - id: ATS-ACC-PRD-001-03
    title: Authorized callers can read product kinds
    level: api
    proves:
      - BR-CAP-ACC-PRD-001-06
    preconditions: A caller has product read authority.
    steps: Request the product-kind register.
    expected: The register read succeeds.
    negative: true
    data_needs: One caller has read authority and another lacks Accounting access.
    bound_to:
      - >-
        services-accounting:modules/products/tests/e2e/products-security.e2e.spec.js#reads the product type
        registry
      - TST-ACC-PRD-028
    provenance: test
    source: >-
      services-accounting:modules/products/tests/e2e/products-security.e2e.spec.js#reads the product type
      registry
    category: permission
    binding_scope:
      - suite: TST-ACC-PRD-028
        assertions:
          - >-
            services-accounting:modules/products/tests/e2e/products-security.e2e.spec.js#reads the product
            type registry
        provenance: test
        source: >-
          services-accounting:modules/products/tests/e2e/products-security.e2e.spec.js#reads the product type
          registry
  - id: ATS-ACC-PRD-001-04
    title: Accounting tabs exclude domain kinds
    level: browser
    proves:
      - BR-CAP-ACC-PRD-001-07
    preconditions: The register contains active Membership and Commerce kinds.
    steps: Visit Accounting Products.
    expected: 'Only Accounting, Donation and Legacy product tabs appear.'
    negative: false
    data_needs: The register contains active Membership and Commerce kinds.
    bound_to:
      - 'react-console:e2e/mock/accounting-products-list.mock.spec.ts#shows each type on its own tab'
      - TST-ACC-PRD-021
    provenance: test
    source: 'react-console:e2e/mock/accounting-products-list.mock.spec.ts#shows each type on its own tab'
    category: rule
    binding_scope:
      - suite: TST-ACC-PRD-021
        assertions:
          - 'react-console:e2e/mock/accounting-products-list.mock.spec.ts#shows each type on its own tab'
        provenance: test
        source: 'react-console:e2e/mock/accounting-products-list.mock.spec.ts#shows each type on its own tab'
  - id: ATS-ACC-PRD-001-05
    title: Register size reaches its response ceiling
    category: boundary
    level: api
    proves:
      - BR-CAP-ACC-PRD-001-05
    preconditions: 'An isolated register contains exactly two hundred kinds, then one additional kind.'
    steps: 'Read the register at each size, restoring its seed after the check.'
    expected: >-
      The first read returns the complete ordered register and count; the second fails without returning a
      truncated register.
    negative: true
    data_needs: 'An isolated register contains exactly two hundred kinds, then one additional kind.'
    bound_to: []
    provenance: proposed
    source: 'services-accounting:modules/products/services/persistence/product-types.ts:listProductTypes'
    binding_scope: []
  - id: ATS-ACC-PRD-001-06
    title: Kind selection governs creation and domain ownership
    category: interaction
    level: api
    proves:
      - BR-CAP-ACC-PRD-001-03
      - BR-CAP-ACC-PRD-002-04
      - BR-CAP-ACC-PRD-007-01
    preconditions: The register contains active Accounting and Membership kinds and an inactive Events kind.
    steps: >-
      Read the kinds, create suitable products through their owning callers, and try the inactive and
      cross-owner choices.
    expected: Successful records match the selected kind; inactive and cross-owner choices leave no new product.
    negative: true
    data_needs: The register contains active Accounting and Membership kinds and an inactive Events kind.
    bound_to: []
    provenance: proposed
    source: >-
      services-accounting:modules/products/tests/e2e/products.e2e.spec.js#answers the domains’ types after
      them, each with its owning service and extension table, the Events ones inactive;
      services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#refuses a type
      registered inactive (an Events type), 400 with its sentence;
      services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#refuses
      Commerce creating a membership package, naming the owner, the type and the caller
    exercises:
      - CAP-ACC-PRD-001
      - CAP-ACC-PRD-002
      - CAP-ACC-PRD-007
    binding_scope: []
evidence:
  - 'react-console:components/accounting-config/products/use-products.ts'
  - 'services-accounting:modules/products/aws/api/products.routes.ts'
  - 'services-accounting:modules/products/db/product-types.table.ts'
  - 'services-accounting:modules/products/tests/e2e/products-security.e2e.spec.js'
  - 'services-accounting:modules/products/tests/e2e/products.e2e.spec.js'
  - 'services-accounting:modules/products/tests/integration/db/products.table.integration.spec.js'
  - >-
    services-accounting:modules/products/tests/integration/services/persistence/product-types.queries.integration.spec.js
coverage:
  rule: covered
  transition: not-applicable
  validation: 'gap: FND-ACC-PRD-071'
  permission: covered
  edge: 'gap: FND-ACC-PRD-071'
  failure: 'gap: FND-ACC-PRD-071'
  boundary: covered
  concurrency: not-applicable
  invariant: covered
  interaction: covered
coverage_notes:
  transition:
    reason: The product-kind register is release-managed; callers have no record lifecycle.
    provenance: documented
    source: >-
      services-accounting:modules/products/tests/integration/db/products.table.integration.spec.js#refuses the
      application role an INSERT
  validation:
    reason: No dedicated scenario isolates this category for the capability.
    provenance: unknown
    source: FND-ACC-PRD-071
  edge:
    reason: No dedicated scenario isolates this category for the capability.
    provenance: unknown
    source: FND-ACC-PRD-071
  failure:
    reason: No dedicated scenario isolates this category for the capability.
    provenance: unknown
    source: FND-ACC-PRD-071
  concurrency:
    reason: Application callers only read the immutable release-managed register.
    provenance: documented
    source: >-
      services-accounting:modules/products/tests/integration/db/products.table.integration.spec.js#refuses the
      application role an INSERT
  remaining_obligations:
    reason: >-
      The maximum-size scenario is unbound, and denial of register read access lacks a dedicated existing
      assertion. Workflow edges not named by a scenario remain in this finding rather than gaining a binding
      from shared workflow membership.
    provenance: unknown
    source: FND-ACC-PRD-071
  meaning:
    reason: >-
      Covered means a specification scenario exists in this category. Executable coverage and run results
      remain independent.
    provenance: documented
    source: 'rhythm-v2-docs:specs/CONVENTIONS.md#9.10 Capability Test Specification (`ATS`, under `design/tests/`)'
coverage_findings:
  - FND-ACC-PRD-071
related_capabilities:
  - CAP-ACC-PRD-002
  - CAP-ACC-PRD-007
workflows: []
rule_coverage:
  - rule: BR-CAP-ACC-PRD-001-01
    scenarios:
      - ATS-ACC-PRD-001-01
  - rule: BR-CAP-ACC-PRD-001-02
    scenarios:
      - ATS-ACC-PRD-001-02
  - rule: BR-CAP-ACC-PRD-001-03
    scenarios:
      - ATS-ACC-PRD-001-02
      - ATS-ACC-PRD-001-06
  - rule: BR-CAP-ACC-PRD-001-05
    scenarios:
      - ATS-ACC-PRD-001-05
  - rule: BR-CAP-ACC-PRD-001-06
    scenarios:
      - ATS-ACC-PRD-001-03
  - rule: BR-CAP-ACC-PRD-001-07
    scenarios:
      - ATS-ACC-PRD-001-04
interaction_coverage:
  - scenario: ATS-ACC-PRD-001-06
    exercises:
      - CAP-ACC-PRD-001
      - CAP-ACC-PRD-002
      - CAP-ACC-PRD-007
    provenance: proposed
    source: >-
      services-accounting:modules/products/tests/e2e/products.e2e.spec.js#answers the domains’ types after
      them, each with its owning service and extension table, the Events ones inactive;
      services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#refuses a type
      registered inactive (an Events type), 400 with its sentence;
      services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#refuses
      Commerce creating a membership package, naming the owner, the type and the caller
permission_coverage:
  - key: accounting.products.read
    where_checked: api
    scope: tenant
    scenarios:
      - ATS-ACC-PRD-001-03
    finding: null
    provenance: proposed
    source: >-
      services-accounting:modules/products/tests/e2e/products-security.e2e.spec.js#reads the product type
      registry
---

# Understand the available product kinds: Capability Test Specification

## Coverage

The frontmatter lists a proof scenario or finding for every required rule and records each applicable category. Scenario coverage describes what to check; bindings identify the assertions that already exist, and execution results remain unverified. The maximum-size scenario is unbound, and denial of register read access lacks a dedicated existing assertion. Workflow edges not named by a scenario remain in this finding rather than gaining a binding from shared workflow membership.

## Interactions With Related Capabilities

Kind selection governs creation and domain ownership. The register contains active Accounting and Membership kinds and an inactive Events kind. Read the kinds, create suitable products through their owning callers, and try the inactive and cross-owner choices. Successful records match the selected kind; inactive and cross-owner choices leave no new product.
