---
id: ATS-ACC-PRD-018
scope: CAP-ACC-PRD-018
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-018-01
    title: Tax resolution honors assignment priority
    level: api
    proves:
      - BR-CAP-ACC-PRD-018-01
      - INV-DOM-ACC-PRD-004-11
    preconditions: Packages differ in setup classes and a kind default can be configured.
    steps: Read packages before and after assigning the default.
    expected: 'Own assignments win, defaults fill missing assignments and absent choices return no class.'
    negative: false
    data_needs: Packages differ in setup classes and a kind default can be configured.
    bound_to:
      - >-
        services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#lets the product’s own
        accounting setup class win over the type default
      - >-
        services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#sets a default for
        membership packages, after which a package without a setup class is taxed under it
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#resolves
        each product’s class with its source, inside a transaction
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#sets
        a type’s default, answers it on every product of the type without a setup class, and keeps the setup’s
        class where there is one
      - TST-ACC-PRD-029
      - TST-ACC-PRD-042
    provenance: test
    source: >-
      services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#lets the product’s own
      accounting setup class win over the type default
    category: interaction
    binding_scope:
      - suite: TST-ACC-PRD-029
        assertions:
          - >-
            services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#lets the product’s
            own accounting setup class win over the type default
          - >-
            services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#sets a default for
            membership packages, after which a package without a setup class is taxed under it
        provenance: test
        source: >-
          services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#lets the product’s
          own accounting setup class win over the type default;
          services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#sets a default for
          membership packages, after which a package without a setup class is taxed under it;
          services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#resolves
          each product’s class with its source, inside a transaction;
          services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#sets
          a type’s default, answers it on every product of the type without a setup class, and keeps the
          setup’s class where there is one
      - suite: TST-ACC-PRD-042
        assertions:
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#resolves
            each product’s class with its source, inside a transaction
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#sets
            a type’s default, answers it on every product of the type without a setup class, and keeps the
            setup’s class where there is one
        provenance: test
        source: >-
          services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#lets the product’s
          own accounting setup class win over the type default;
          services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#sets a default for
          membership packages, after which a package without a setup class is taxed under it;
          services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#resolves
          each product’s class with its source, inside a transaction;
          services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#sets
          a type’s default, answers it on every product of the type without a setup class, and keeps the
          setup’s class where there is one
    exercises:
      - CAP-ACC-PRD-018
      - CAP-ACC-PRD-015
      - CAP-ACC-PRD-003
  - id: ATS-ACC-PRD-018-02
    title: Defaults reject unavailable new assignments
    level: unit
    proves:
      - BR-CAP-ACC-PRD-018-02
      - BR-CAP-ACC-PRD-018-03
    preconditions: Tax fixtures include inactive and later-retired classes.
    steps: 'Try missing kinds, missing classes and new inactive choices, then resave a held retired class.'
    expected: Invalid new choices fail and the retained class remains.
    negative: true
    data_needs: Tax fixtures include inactive and later-retired classes.
    bound_to:
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#refuses
        an unknown type, an unknown class and an inactive class newly chosen, and keeps an inactive class once
        held
      - >-
        services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#refuses an unknown
        type and an unknown class, 400 with their sentences
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#lists
        the tenant’s defaults and reads one
      - TST-ACC-PRD-042
      - TST-ACC-PRD-029
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#refuses
      an unknown type, an unknown class and an inactive class newly chosen, and keeps an inactive class once
      held
    category: validation
    binding_scope:
      - suite: TST-ACC-PRD-042
        assertions:
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#refuses
            an unknown type, an unknown class and an inactive class newly chosen, and keeps an inactive class
            once held
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#lists
            the tenant’s defaults and reads one
        provenance: test
        source: >-
          services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#refuses
          an unknown type, an unknown class and an inactive class newly chosen, and keeps an inactive class
          once held; services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#refuses
          an unknown type and an unknown class, 400 with their sentences;
          services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#lists
          the tenant’s defaults and reads one
      - suite: TST-ACC-PRD-029
        assertions:
          - >-
            services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#refuses an unknown
            type and an unknown class, 400 with their sentences
        provenance: test
        source: >-
          services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#refuses
          an unknown type, an unknown class and an inactive class newly chosen, and keeps an inactive class
          once held; services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#refuses
          an unknown type and an unknown class, 400 with their sentences;
          services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#lists
          the tenant’s defaults and reads one
  - id: ATS-ACC-PRD-018-03
    title: Tax defaults use their own versions
    level: api
    proves:
      - BR-CAP-ACC-PRD-018-04
    preconditions: The kind initially has no default.
    steps: 'Create one, replace at its read version and try obsolete or omitted replacement versions.'
    expected: Creation and current replacement succeed while invalid versions fail.
    negative: true
    data_needs: The kind initially has no default.
    bound_to:
      - >-
        services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#replaces the default
        at the version read, lists it, and refuses a stale version 409
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#replaces
        a default at the version read, and refuses a stale one or one without its version
      - TST-ACC-PRD-029
      - TST-ACC-PRD-042
    provenance: test
    source: >-
      services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#replaces the default at
      the version read, lists it, and refuses a stale version 409
    category: concurrency
    binding_scope:
      - suite: TST-ACC-PRD-029
        assertions:
          - >-
            services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#replaces the
            default at the version read, lists it, and refuses a stale version 409
        provenance: test
        source: >-
          services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#replaces the default
          at the version read, lists it, and refuses a stale version 409;
          services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#replaces
          a default at the version read, and refuses a stale one or one without its version
      - suite: TST-ACC-PRD-042
        assertions:
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#replaces
            a default at the version read, and refuses a stale one or one without its version
        provenance: test
        source: >-
          services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#replaces the default
          at the version read, lists it, and refuses a stale version 409;
          services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#replaces
          a default at the version read, and refuses a stale one or one without its version
  - id: ATS-ACC-PRD-018-04
    title: Default removal changes fallback resolution
    level: api
    proves:
      - BR-CAP-ACC-PRD-018-05
    preconditions: Packages use a kind default without own assignments.
    steps: Remove the default and repeat removal.
    expected: Those packages resolve no class and repeat removal returns not found.
    negative: true
    data_needs: Packages use a kind default without own assignments.
    bound_to:
      - >-
        services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#removes the default,
        200 then 404, after which a package without a setup class is taxed under none
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#removes
        a default, after which its products fall back to none; a second delete is 404
      - TST-ACC-PRD-029
      - TST-ACC-PRD-042
    provenance: test
    source: >-
      services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#removes the default, 200
      then 404, after which a package without a setup class is taxed under none
    category: transition
    binding_scope:
      - suite: TST-ACC-PRD-029
        assertions:
          - >-
            services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#removes the
            default, 200 then 404, after which a package without a setup class is taxed under none
        provenance: test
        source: >-
          services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#removes the default,
          200 then 404, after which a package without a setup class is taxed under none;
          services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#removes
          a default, after which its products fall back to none; a second delete is 404
      - suite: TST-ACC-PRD-042
        assertions:
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#removes
            a default, after which its products fall back to none; a second delete is 404
        provenance: test
        source: >-
          services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#removes the default,
          200 then 404, after which a package without a setup class is taxed under none;
          services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#removes
          a default, after which its products fall back to none; a second delete is 404
  - id: ATS-ACC-PRD-018-05
    title: Default references protect tax classes
    level: api
    proves:
      - BR-CAP-ACC-PRD-018-06
    preconditions: Only a kind default refers to a class.
    steps: 'Delete the class, remove the default and try class deletion again.'
    expected: The first deletion fails and the final deletion succeeds.
    negative: true
    data_needs: Only a kind default refers to a class.
    bound_to:
      - >-
        services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#refuses deleting a tax
        class only a default names, 409 with the sentence, and allows it once the default is gone
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#refuses
        deleting a tax class a default names, as one a setup names
      - TST-ACC-PRD-029
      - TST-ACC-PRD-042
    provenance: test
    source: >-
      services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#refuses deleting a tax
      class only a default names, 409 with the sentence, and allows it once the default is gone
    category: invariant
    binding_scope:
      - suite: TST-ACC-PRD-029
        assertions:
          - >-
            services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#refuses deleting a
            tax class only a default names, 409 with the sentence, and allows it once the default is gone
        provenance: test
        source: >-
          services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#refuses deleting a
          tax class only a default names, 409 with the sentence, and allows it once the default is gone;
          services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#refuses
          deleting a tax class a default names, as one a setup names
      - suite: TST-ACC-PRD-042
        assertions:
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#refuses
            deleting a tax class a default names, as one a setup names
        provenance: test
        source: >-
          services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#refuses deleting a
          tax class only a default names, 409 with the sentence, and allows it once the default is gone;
          services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#refuses
          deleting a tax class a default names, as one a setup names
  - id: ATS-ACC-PRD-018-06
    title: Combined locks protect tax defaults
    level: unit
    proves:
      - BR-CAP-ACC-PRD-018-07
    preconditions: A default has an update-and-delete lock.
    steps: Attempt replacement and removal.
    expected: Both operations fail.
    negative: true
    data_needs: A default has an update-and-delete lock.
    bound_to:
      - >-
        services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#refuses
        replacing or deleting a locked default
      - TST-ACC-PRD-042
    provenance: test
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#refuses
      replacing or deleting a locked default
    category: permission
    binding_scope:
      - suite: TST-ACC-PRD-042
        assertions:
          - >-
            services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#refuses
            replacing or deleting a locked default
        provenance: test
        source: >-
          services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#refuses
          replacing or deleting a locked default
  - id: ATS-ACC-PRD-018-07
    title: Product authority does not grant tax authority
    level: api
    proves:
      - BR-CAP-ACC-PRD-018-08
    preconditions: A product manager has no tax-class permissions.
    steps: Request a default read and replacement.
    expected: Both requests are denied.
    negative: true
    data_needs: A product manager has no tax-class permissions.
    bound_to:
      - >-
        services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#refuses a caller with
        product rights alone (tax configuration needs the tax-classes keys)
      - TST-ACC-PRD-029
    provenance: test
    source: >-
      services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#refuses a caller with
      product rights alone (tax configuration needs the tax-classes keys)
    category: permission
    binding_scope:
      - suite: TST-ACC-PRD-029
        assertions:
          - >-
            services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#refuses a caller
            with product rights alone (tax configuration needs the tax-classes keys)
        provenance: test
        source: >-
          services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#refuses a caller
          with product rights alone (tax configuration needs the tax-classes keys)
  - id: ATS-ACC-PRD-018-08
    title: Deletion-only default protection permits replacement
    category: edge
    level: api
    proves:
      - BR-CAP-ACC-PRD-018-07
    preconditions: A kind default has deletion-only protection and a current version.
    steps: 'Replace its class at that version, then request removal.'
    expected: The class replacement succeeds; deletion remains refused.
    negative: true
    data_needs: A kind default has deletion-only protection and a current version.
    bound_to: []
    provenance: proposed
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#refuses
      replacing or deleting a locked default
    binding_scope: []
  - id: ATS-ACC-PRD-018-09
    title: Default changes alter product resolution without changing product versions
    category: interaction
    level: api
    proves:
      - BR-CAP-ACC-PRD-018-01
      - BR-CAP-ACC-PRD-018-05
      - BR-CAP-ACC-PRD-003-03
    preconditions: Two products of the same kind differ in whether their setup names a class.
    steps: 'Change the kind default, read both products, remove the default and repeat the reads.'
    expected: Only fallback resolution changes; explicit setup classification and product versions remain unchanged.
    negative: true
    data_needs: Two products of the same kind differ in whether their setup names a class.
    bound_to: []
    provenance: proposed
    source: >-
      services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#lets the product’s own
      accounting setup class win over the type default;
      services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#removes the default, 200
      then 404, after which a package without a setup class is taxed under none;
      services-accounting:modules/products/tests/integration/services/persistence/products.queries.integration.spec.js#maps
      a product whole: every column, its prices, its components and its accounting summary
    exercises:
      - CAP-ACC-PRD-018
      - CAP-ACC-PRD-003
    binding_scope: []
evidence:
  - 'react-console:components/configuration/tax/product-type-tax-classes-panel.tsx'
  - 'services-accounting:modules/products/db/product-type-tax-classes.table.ts'
  - 'services-accounting:modules/products/services/persistence/product-type-tax-classes.ts'
  - 'services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js'
  - >-
    services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js
coverage:
  rule: 'gap: FND-ACC-PRD-067'
  transition: covered
  validation: covered
  permission: covered
  edge: covered
  failure: 'gap: FND-ACC-PRD-067'
  boundary: 'gap: FND-ACC-PRD-067'
  concurrency: covered
  invariant: covered
  interaction: covered
coverage_notes:
  rule:
    reason: No dedicated scenario isolates this category for the capability.
    provenance: unknown
    source: FND-ACC-PRD-067
  failure:
    reason: No dedicated scenario isolates this category for the capability.
    provenance: unknown
    source: FND-ACC-PRD-067
  boundary:
    reason: No dedicated scenario isolates this category for the capability.
    provenance: unknown
    source: FND-ACC-PRD-067
  remaining_obligations:
    reason: >-
      Delete-only protection, every tax permission, inactive-kind defaults and concurrent first assignments
      need execution; tax ownership transfer is a separate product decision. 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-067
  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-067
related_capabilities:
  - CAP-ACC-PRD-003
workflows: []
rule_coverage:
  - rule: BR-CAP-ACC-PRD-018-01
    scenarios:
      - ATS-ACC-PRD-018-01
      - ATS-ACC-PRD-018-09
  - rule: BR-CAP-ACC-PRD-018-02
    scenarios:
      - ATS-ACC-PRD-018-02
  - rule: BR-CAP-ACC-PRD-018-03
    scenarios:
      - ATS-ACC-PRD-018-02
  - rule: BR-CAP-ACC-PRD-018-04
    scenarios:
      - ATS-ACC-PRD-018-03
  - rule: BR-CAP-ACC-PRD-018-05
    scenarios:
      - ATS-ACC-PRD-018-04
      - ATS-ACC-PRD-018-09
  - rule: BR-CAP-ACC-PRD-018-06
    scenarios:
      - ATS-ACC-PRD-018-05
  - rule: BR-CAP-ACC-PRD-018-07
    scenarios:
      - ATS-ACC-PRD-018-06
      - ATS-ACC-PRD-018-08
  - rule: BR-CAP-ACC-PRD-018-08
    scenarios:
      - ATS-ACC-PRD-018-07
interaction_coverage:
  - scenario: ATS-ACC-PRD-018-01
    exercises:
      - CAP-ACC-PRD-018
      - CAP-ACC-PRD-015
      - CAP-ACC-PRD-003
    provenance: test
    source: >-
      services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#lets the product’s own
      accounting setup class win over the type default
  - scenario: ATS-ACC-PRD-018-09
    exercises:
      - CAP-ACC-PRD-018
      - CAP-ACC-PRD-003
    provenance: proposed
    source: >-
      services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#lets the product’s own
      accounting setup class win over the type default;
      services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#removes the default, 200
      then 404, after which a package without a setup class is taxed under none;
      services-accounting:modules/products/tests/integration/services/persistence/products.queries.integration.spec.js#maps
      a product whole: every column, its prices, its components and its accounting summary
state_coverage:
  - model: STATE-ACC-PRD-002
    from: unlocked
    to: delete-locked
    scenarios: []
    finding: FND-ACC-PRD-067
    provenance: unknown
    source: 'services-accounting:modules/products/aws/api/products-api-mapper.ts:toInput'
  - model: STATE-ACC-PRD-002
    from: unlocked
    to: update-and-delete-locked
    scenarios: []
    finding: FND-ACC-PRD-067
    provenance: unknown
    source: 'services-accounting:modules/products/aws/api/products-api-mapper.ts:toInput'
  - model: STATE-ACC-PRD-002
    from: delete-locked
    to: unlocked
    scenarios: []
    finding: FND-ACC-PRD-067
    provenance: unknown
    source: 'services-accounting:modules/products/services/rules/product-rules.ts:lockedReplaceProblem'
  - model: STATE-ACC-PRD-002
    from: delete-locked
    to: update-and-delete-locked
    scenarios: []
    finding: FND-ACC-PRD-067
    provenance: unknown
    source: 'services-accounting:modules/products/services/rules/product-rules.ts:lockedReplaceProblem'
  - model: STATE-ACC-PRD-002
    from: update-and-delete-locked
    to: unlocked
    scenarios: []
    finding: FND-ACC-PRD-067
    provenance: unknown
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.integration.spec.js#unlocks
      a locked product replaced with sys_locked null, then edits and deletes it
  - model: STATE-ACC-PRD-002
    from: update-and-delete-locked
    to: delete-locked
    scenarios: []
    finding: FND-ACC-PRD-067
    provenance: unknown
    source: 'services-accounting:modules/products/services/rules/product-rules.ts:lockedReplaceProblem'
permission_coverage:
  - key: accounting.tax-classes.read
    where_checked: api
    scope: tenant
    scenarios:
      - ATS-ACC-PRD-018-06
      - ATS-ACC-PRD-018-07
    finding: null
    provenance: proposed
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#refuses
      replacing or deleting a locked default;
      services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#refuses a caller with
      product rights alone (tax configuration needs the tax-classes keys)
  - key: accounting.tax-classes.update
    where_checked: api
    scope: tenant
    scenarios:
      - ATS-ACC-PRD-018-06
      - ATS-ACC-PRD-018-07
    finding: null
    provenance: proposed
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#refuses
      replacing or deleting a locked default;
      services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#refuses a caller with
      product rights alone (tax configuration needs the tax-classes keys)
  - key: accounting.tax-classes.delete
    where_checked: api
    scope: tenant
    scenarios:
      - ATS-ACC-PRD-018-06
      - ATS-ACC-PRD-018-07
    finding: null
    provenance: proposed
    source: >-
      services-accounting:modules/products/tests/integration/services/persistence/products.shared-base.integration.spec.js#refuses
      replacing or deleting a locked default;
      services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#refuses a caller with
      product rights alone (tax configuration needs the tax-classes keys)
invariant_coverage:
  - invariant: INV-DOM-ACC-PRD-004-11
    scenarios:
      - ATS-ACC-PRD-018-01
    finding: null
    provenance: test
    source: >-
      services-accounting:modules/products/tests/e2e/products-shared-base.e2e.spec.js#lets the product’s own
      accounting setup class win over the type default
  - invariant: INV-DOM-ACC-PRD-004-12
    scenarios:
      - ATS-ACC-PRD-018-02
    finding: FND-ACC-PRD-067
    provenance: proposed
    source: 'services-accounting:modules/products/db/product-type-tax-classes.table.ts:productTypeTaxClasses'
    note: >-
      The mapped scenario exercises the related behavior; the complete invariant statement still needs
      dedicated proof.
---

# Maintain the tax default for a product kind: 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. Delete-only protection, every tax permission, inactive-kind defaults and concurrent first assignments need execution; tax ownership transfer is a separate product decision. Workflow edges not named by a scenario remain in this finding rather than gaining a binding from shared workflow membership.

## Interactions With Related Capabilities

Default changes alter product resolution without changing product versions. Two products of the same kind differ in whether their setup names a class. Change the kind default, read both products, remove the default and repeat the reads. Only fallback resolution changes; explicit setup classification and product versions remain unchanged.
