---
id: ATS-PFM-INT-007
scope: CAP-PFM-INT-007
product_area: platform
module: integrations
revision: 3
status: proposed
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  macroservice-libraries: 54536a441935c6e09fdb7f96f0bec71c52ba4e03
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
scenarios:
  - id: ATS-PFM-INT-007-01
    title: Replacement maintains one current scope choice
    level: api
    proves:
      - BR-CAP-PFM-INT-007-01
    preconditions: A business-unit binding selects A at its first revision.
    steps: Replace it with B and race two creates at an unbound scope.
    expected: >-
      A becomes superseded, B advances the revision and the race leaves one active winner with a conflict
      for the other.
    negative: false
    data_needs: 'Fixtures establishing the stated accounts, declarations and history in an isolated workspace.'
    bound_to:
      - TST-PFM-INT-554
      - TST-PFM-INT-488
    provenance: test
    source: >-
      services-platform:modules/integrations/tests/integration/services/persistence/integration-bindings.integration.spec.js#leaves
      one active binding at the scope
    category: concurrency
    binding_evidence:
      - >-
        services-platform:modules/integrations/tests/integration/services/persistence/integration-bindings.integration.spec.js#leaves
        one active binding at the scope
      - >-
        services-platform:modules/integrations/tests/integration/services/persistence/integration-bindings.integration.spec.js#supersedes
        the binding it replaces
      - >-
        services-platform:modules/integrations/tests/integration/services/persistence/integration-bindings.integration.spec.js#keeps
        the first, and refuses the second as a conflict
      - >-
        services-platform:modules/integrations/tests/e2e/integration-bindings.e2e.spec.js#answers the new
        binding at revision 2
    binding_scope: >-
      contributions: the cited tests support their own asserted outcomes. Additional setup, branches
      and combined sequences remain proposed unless the cited assertions exercise them.
  - id: ATS-PFM-INT-007-02
    title: Ineligible targets do not replace a valid choice
    level: api
    proves:
      - BR-CAP-PFM-INT-007-02
    preconditions: 'Prepare paused, foreign-workspace and unsupported connections alongside a usable one.'
    steps: Attempt bindings with each invalid condition and then the usable target.
    expected: Every rejection identifies its field and preserves the earlier binding; the valid choice succeeds.
    negative: true
    data_needs: 'Fixtures establishing the stated accounts, declarations and history in an isolated workspace.'
    bound_to:
      - TST-PFM-INT-554
      - TST-PFM-INT-488
    provenance: test
    source: >-
      services-platform:modules/integrations/tests/integration/services/persistence/integration-bindings.integration.spec.js#refuses
      a required feature the connection has not verified
    category: validation
    binding_evidence:
      - >-
        services-platform:modules/integrations/tests/integration/services/persistence/integration-bindings.integration.spec.js#refuses
        a required feature the connection has not verified
      - >-
        services-platform:modules/integrations/tests/integration/services/persistence/integration-bindings.integration.spec.js#refuses
        a scope kind the capability’s policy does not allow
      - >-
        services-platform:modules/integrations/tests/integration/services/persistence/integration-bindings.integration.spec.js#refuses
        a resource bound by an application that does not own it
      - >-
        services-platform:modules/integrations/tests/integration/services/persistence/integration-bindings.integration.spec.js#refuses
        a connection that is not active or degraded
      - >-
        services-platform:modules/integrations/tests/integration/services/persistence/integration-bindings.integration.spec.js#refuses
        a capability the connection’s pinned version does not implement
      - >-
        services-platform:modules/integrations/tests/integration/services/persistence/integration-bindings.integration.spec.js#leaves
        the current binding of a scope as it was when its replacement is refused
      - >-
        services-platform:modules/integrations/tests/e2e/integration-bindings.e2e.spec.js#answers 403 for
        a resource of another application
    binding_scope: >-
      contributions: the cited tests support their own asserted outcomes. Additional setup, branches
      and combined sequences remain proposed unless the cited assertions exercise them.
  - id: ATS-PFM-INT-007-03
    title: Default fallback depends on sensitivity
    level: unit
    proves:
      - BR-CAP-PFM-INT-007-03
    preconditions: Prepare a payment contract and an event contract.
    steps: Create bindings without specifying ineligibility policy.
    expected: Payments default to refusal and events default to broader-scope fallback.
    negative: false
    data_needs: 'Fixtures establishing the stated accounts, declarations and history in an isolated workspace.'
    bound_to:
      - TST-PFM-INT-571
      - TST-PFM-INT-554
    provenance: test
    source: >-
      services-platform:modules/integrations/tests/unit/services/binding-migration-rules.spec.ts#gives a
      sensitive capability the refusing default
    category: rule
    binding_evidence:
      - >-
        services-platform:modules/integrations/tests/unit/services/binding-migration-rules.spec.ts#gives
        a sensitive capability the refusing default
      - >-
        services-platform:modules/integrations/tests/integration/services/persistence/integration-bindings.integration.spec.js#answers
        the binding active at revision 1, with the capability’s default policy and its features sorted
        once
    binding_scope: >-
      contributions: the cited tests support their own asserted outcomes. Additional setup, branches
      and combined sequences remain proposed unless the cited assertions exercise them.
  - id: ATS-PFM-INT-007-04
    title: Removal exposes the next configured scope
    level: api
    proves:
      - BR-CAP-PFM-INT-007-04
    preconditions: A record and its business unit each have a binding.
    steps: 'Remove the record choice, Explain and inspect history.'
    expected: The business-unit connection resolves the next call and the old record choice remains traceable.
    negative: false
    data_needs: 'Fixtures establishing the stated accounts, declarations and history in an isolated workspace.'
    bound_to:
      - TST-PFM-INT-488
      - TST-PFM-INT-554
    provenance: test
    source: >-
      services-platform:modules/integrations/tests/e2e/integration-bindings.e2e.spec.js#supersedes it,
      and the scope resolves without it
    category: interaction
    binding_evidence:
      - >-
        services-platform:modules/integrations/tests/e2e/integration-bindings.e2e.spec.js#supersedes it,
        and the scope resolves without it
      - >-
        services-platform:modules/integrations/tests/integration/services/persistence/integration-bindings.integration.spec.js#keeps
        the removed binding readable, superseded at revision 2
      - >-
        services-platform:modules/integrations/tests/integration/services/persistence/integration-bindings.integration.spec.js#refuses
        to remove it again
    binding_scope: >-
      contributions: the cited tests support their own asserted outcomes. Additional setup, branches
      and combined sequences remain proposed unless the cited assertions exercise them.
  - id: ATS-PFM-INT-007-05
    title: Binding revisions cannot be rewritten
    level: api
    proves:
      - BR-CAP-PFM-INT-007-05
    preconditions: 'A scope has been created, replaced and unbound.'
    steps: Read its revisions and attempt direct revision update and deletion.
    expected: >-
      Newest-first snapshots retain reason, actor and time, and attempts to rewrite or delete history are
      refused.
    negative: false
    data_needs: 'Fixtures establishing the stated accounts, declarations and history in an isolated workspace.'
    bound_to:
      - TST-PFM-INT-495
      - TST-PFM-INT-488
      - TST-PFM-INT-554
    provenance: test
    source: >-
      services-platform:modules/integrations/tests/integration/db/integration-binding-revisions.table.integration.spec.js#refuses
      an UPDATE of a revision by the application role, so a history cannot be rewritten
    category: invariant
    binding_evidence:
      - >-
        services-platform:modules/integrations/tests/integration/db/integration-binding-revisions.table.integration.spec.js#refuses
        an UPDATE of a revision by the application role, so a history cannot be rewritten
      - >-
        services-platform:modules/integrations/tests/e2e/integration-bindings.e2e.spec.js#answers every
        revision of the scope newest first, each with its reason, author, time and snapshot
      - >-
        services-platform:modules/integrations/tests/integration/db/integration-binding-revisions.table.integration.spec.js#refuses
        a DELETE of a revision by the application role, so a history cannot be erased
      - >-
        services-platform:modules/integrations/tests/integration/services/persistence/integration-bindings.integration.spec.js#keeps
        the newest revisions up to the maximum and drops the oldest
    binding_scope: >-
      contributions: the cited tests support their own asserted outcomes. Additional setup, branches
      and combined sequences remain proposed unless the cited assertions exercise them.
  - id: ATS-PFM-INT-007-06
    title: Connection changes invalidate only affected choices
    level: api
    proves:
      - BR-CAP-PFM-INT-007-06
    preconditions: 'A connection has two choices, including one requiring a feature.'
    steps: 'Suspend, resume, remove that feature and update to a release without the major.'
    expected: >-
      Pause invalidates, resume restores, feature loss identifies its affected choice and unsupported
      major leaves the applicable binding invalid.
    negative: false
    data_needs: 'Fixtures establishing the stated accounts, declarations and history in an isolated workspace.'
    bound_to:
      - TST-PFM-INT-513
      - TST-PFM-INT-570
    provenance: test
    source: >-
      services-platform:modules/integrations/tests/integration/services/bindings/invalidation.integration.spec.js#invalidates
      its active bindings with connection_suspended, at the next revision
    category: transition
    binding_evidence:
      - >-
        services-platform:modules/integrations/tests/integration/services/bindings/invalidation.integration.spec.js#invalidates
        its active bindings with connection_suspended, at the next revision
      - >-
        services-platform:modules/integrations/tests/integration/services/bindings/invalidation.integration.spec.js#restores
        them when it is resumed
      - >-
        services-platform:modules/integrations/tests/integration/services/bindings/invalidation.integration.spec.js#invalidates
        the binding that requires it with feature_lost
      - >-
        services-platform:modules/integrations/tests/integration/services/bindings/invalidation.integration.spec.js#invalidates
        the dropped major’s binding with major_unsupported
      - >-
        services-platform:modules/integrations/tests/unit/services/binding-invalidation-rule.spec.ts#names
        the connection first when several causes hold
    binding_scope: >-
      contributions: the cited tests support their own asserted outcomes. Additional setup, branches
      and combined sequences remain proposed unless the cited assertions exercise them.
  - id: ATS-PFM-INT-007-07
    title: Invalidation notices respect transaction outcomes
    level: api
    proves:
      - BR-CAP-PFM-INT-007-07
    preconditions: Two active bindings select one connection.
    steps: 'Suspend, resume and attempt another suspension in a rolled-back change.'
    expected: One committed-loss e-mail names both choices; restoration and rollback send no notice.
    negative: false
    data_needs: 'Fixtures establishing the stated accounts, declarations and history in an isolated workspace.'
    bound_to:
      - TST-PFM-INT-513
    provenance: test
    source: >-
      services-platform:modules/integrations/tests/integration/services/bindings/invalidation.integration.spec.js#tells
      the administrators once, after the commit, naming both bindings and why
    category: failure
    binding_evidence:
      - >-
        services-platform:modules/integrations/tests/integration/services/bindings/invalidation.integration.spec.js#tells
        the administrators once, after the commit, naming both bindings and why
      - >-
        services-platform:modules/integrations/tests/integration/services/bindings/invalidation.integration.spec.js#sends
        no notice for the restoration
      - >-
        services-platform:modules/integrations/tests/integration/services/bindings/invalidation.integration.spec.js#sends
        no notice
    binding_scope: >-
      contributions: the cited tests support their own asserted outcomes. Additional setup, branches
      and combined sequences remain proposed unless the cited assertions exercise them.
  - id: ATS-PFM-INT-007-08
    title: Retirement moves valid choices and reports failed moves
    level: browser
    proves:
      - BR-CAP-PFM-INT-007-08
      - AS-JNY-PFM-INT-002-02
    preconditions: Main account has two bindings and a proposed replacement lacks a feature one needs.
    steps: >-
      Request disconnect, inspect the move offer, confirm the move and retry disconnect when dependencies
      are removed.
    expected: >-
      The offer appears after refusal, the eligible choice moves while the failed one reports its reason,
      and disconnection succeeds only once none remain.
    negative: false
    data_needs: 'Fixtures establishing the stated accounts, declarations and history in an isolated workspace.'
    bound_to:
      - TST-PFM-INT-511
      - TST-PFM-INT-106
    provenance: test
    source: >-
      services-platform:modules/integrations/tests/integration/services/bindings/binding-move.integration.spec.js#replaces
      every active binding of the source with one choosing the target, at the same scope, policy and note
    category: interaction
    binding_evidence:
      - >-
        services-platform:modules/integrations/tests/integration/services/bindings/binding-move.integration.spec.js#replaces
        every active binding of the source with one choosing the target, at the same scope, policy and
        note
      - >-
        services-platform:modules/integrations/tests/integration/services/bindings/binding-move.integration.spec.js#refuses
        a binding whose required feature the target has not verified, leaving it on the source, and moves
        the rest
      - >-
        services-platform:modules/integrations/tests/integration/services/bindings/binding-move.integration.spec.js#writes
        nothing on a dry run, answering what would move
      - >-
        services-platform:modules/integrations/tests/integration/services/bindings/binding-move.integration.spec.js#leaves
        the source with no active binding, so its disconnection is no longer refused
      - >-
        react-console:acceptance/integrations/playwright/journeys/bindings/INT-ACC-0262.spec.ts#INT-ACC-0262
    binding_scope: >-
      contributions: the cited tests support their own asserted outcomes. Additional setup, branches
      and combined sequences remain proposed unless the cited assertions exercise them.
  - id: ATS-PFM-INT-007-09
    title: Contract migration is repeatable and supports preview
    level: api
    proves:
      - BR-CAP-PFM-INT-007-09
    preconditions: Prepare current major-one choices and an eligible scripted major two.
    steps: 'Preview migration, apply it and repeat the request.'
    expected: >-
      Preview writes nothing, valid targets become first revisions and repetition identifies
      already-created copies.
    negative: false
    data_needs: 'Fixtures establishing the stated accounts, declarations and history in an isolated workspace.'
    bound_to:
      - TST-PFM-INT-510
    provenance: test
    source: >-
      services-platform:modules/integrations/tests/integration/services/bindings/binding-migration.integration.spec.js#refuses
      each ineligible binding with its reason and leaves the already migrated one alone
    category: edge
    binding_evidence:
      - >-
        services-platform:modules/integrations/tests/integration/services/bindings/binding-migration.integration.spec.js#refuses
        each ineligible binding with its reason and leaves the already migrated one alone
      - >-
        services-platform:modules/integrations/tests/integration/services/bindings/binding-migration.integration.spec.js#writes
        nothing
      - >-
        services-platform:modules/integrations/tests/integration/services/bindings/binding-migration.integration.spec.js#leaves
        the sources of a run without it current, so callers of the old major still resolve
      - >-
        services-platform:modules/integrations/tests/integration/services/bindings/binding-migration.integration.spec.js#answers
        the bindings it migrated already_bound and migrates nothing
    binding_scope: >-
      contributions: the cited tests support their own asserted outcomes. Additional setup, branches
      and combined sequences remain proposed unless the cited assertions exercise them.
  - id: ATS-PFM-INT-007-10
    title: Readers inspect bindings without editing
    level: api
    proves:
      - BR-CAP-PFM-INT-007-10
    preconditions: Prepare an integration reader and manager.
    steps: 'List bindings, read revisions and attempt to create a choice as each.'
    expected: Both can inspect the records and only the manager can change them.
    negative: true
    data_needs: 'Fixtures establishing the stated accounts, declarations and history in an isolated workspace.'
    bound_to:
      - TST-PFM-INT-488
    provenance: test
    source: >-
      services-platform:modules/integrations/tests/e2e/integration-bindings.e2e.spec.js#is refused a
      reader of integrations (403)
    category: permission
    binding_evidence:
      - >-
        services-platform:modules/integrations/tests/e2e/integration-bindings.e2e.spec.js#is refused a
        reader of integrations (403)
      - >-
        services-platform:modules/integrations/tests/e2e/integration-bindings.e2e.spec.js#is read by a
        reader of integrations
    binding_scope: >-
      contributions: the cited tests support their own asserted outcomes. Additional setup, branches
      and combined sequences remain proposed unless the cited assertions exercise them.
  - id: ATS-PFM-INT-007-11
    level: api
    negative: true
    data_needs: Run-owned records and principals in an isolated workspace.
    bound_to: []
    provenance: proposed
    title: Exercise the complete capability binding lifecycle
    category: transition
    proves:
      - BR-CAP-PFM-INT-007-01
      - BR-CAP-PFM-INT-007-04
      - BR-CAP-PFM-INT-007-06
    preconditions: >-
      Prepare one independent record in each starting state, including absent-record cases where the
      model defines creation.
    steps: >-
      Run each listed transition once with its guard satisfied, then repeat it with the guard denied.
      Inspect the resulting record and listed side effects after commit.
    expected: >-
      Each positive case reaches its listed destination and records its defined side effects. Each denied
      case preserves the starting record and creates no transition side effects.
    source: >-
      rhythm-v2-docs:specs/platform/integrations/design/state-models/STATE-PFM-INT-006-capability-binding-lifecycle.md#transitions
    state_model: STATE-PFM-INT-006
    transition_cases:
      - from: absent
        to: active
        trigger: Create an account selection
        guard: 'Contract, scope, feature and usable-account checks all pass'
        side_effects:
          - Create the first revision and commit both audit entries.
        provenance: proposed
        source: >-
          services-platform:modules/integrations/tests/integration/services/persistence/integration-bindings.integration.spec.js#refuses
          a required feature the connection has not verified
      - from: active
        to: superseded
        trigger: Replace or remove the current selection
        guard: The writer holds the scope’s current binding lock
        side_effects:
          - Make a replacement at the next revision or expose broader resolution
          - Append history and both audits.
        provenance: proposed
        source: >-
          services-platform:modules/integrations/tests/e2e/integration-bindings.e2e.spec.js#supersedes
          it, and the scope resolves without it
      - from: invalid
        to: superseded
        trigger: Replace or remove an unusable selection
        guard: The writer holds the current invalid binding lock
        side_effects:
          - Apply the same replacement or removal history rules.
        provenance: proposed
        source: >-
          services-platform:modules/integrations/tests/integration/services/persistence/integration-bindings.integration.spec.js#leaves
          one active binding at the scope
      - from: active
        to: invalid
        trigger: Lose account eligibility
        guard: 'Account usability, installation status, supported major or required feature fails'
        side_effects:
          - Advance the revision with the failure reason
          - Request one administrator notice after commit.
        provenance: proposed
        source: >-
          services-platform:modules/integrations/tests/integration/services/bindings/invalidation.integration.spec.js#invalidates
          its active bindings with connection_suspended, at the next revision
      - from: invalid
        to: active
        trigger: Regain account eligibility
        guard: The recorded eligibility cause no longer applies
        side_effects:
          - Advance a restoration revision and audit it without mail.
        provenance: proposed
        source: >-
          services-platform:modules/integrations/tests/integration/services/bindings/invalidation.integration.spec.js#invalidates
          its active bindings with connection_suspended, at the next revision
    proof_boundary: >-
      The parameterized cases prove the listed lifecycle outcomes. Separate assertions are needed for
      independent object invariants, numeric limits and simultaneous requests.
  - id: ATS-PFM-INT-007-12
    level: api
    negative: false
    data_needs: Run-owned records and principals in an isolated workspace.
    bound_to: []
    provenance: proposed
    title: Removing a narrow choice reveals a broader one
    category: interaction
    proves:
      - BR-CAP-PFM-INT-007-04
      - BR-CAP-PFM-INT-008-01
    exercises:
      - CAP-PFM-INT-007
      - CAP-PFM-INT-008
    preconditions: Record and business-unit bindings select different usable accounts.
    steps: 'Resolve for the record, remove its binding and resolve again.'
    expected: >-
      Selection changes to the business-unit account while the removed choice remains in revision
      history.
    source:
      - >-
        services-platform:modules/integrations/tests/e2e/integration-bindings.e2e.spec.js#supersedes it,
        and the scope resolves without it
      - >-
        services-platform:modules/integrations/tests/unit/services/binding-resolution.spec.ts#asks every
        scope the policy allows and the context names, most specific first
    workflows: []
  - id: ATS-PFM-INT-007-13
    level: api
    negative: false
    data_needs: Run-owned records and principals in an isolated workspace.
    bound_to: []
    provenance: proposed
    title: An invalid selection cannot send a payment
    category: interaction
    proves:
      - BR-CAP-PFM-INT-007-06
      - BR-CAP-PFM-INT-009-07
    exercises:
      - CAP-PFM-INT-007
      - CAP-PFM-INT-009
    preconditions: A sensitive capability selects an active account.
    steps: 'Suspend the account, inspect binding invalidation and invoke through the saved scope.'
    expected: The request refuses before provider contact and uses no broader processor.
    source:
      - >-
        services-platform:modules/integrations/tests/integration/services/bindings/invalidation.integration.spec.js#invalidates
        its active bindings with connection_suspended, at the next revision
      - >-
        services-platform:modules/integrations/tests/integration/services/executions/invoke-capability.integration.spec.js#refuses
        with 503 provider_unavailable while the circuit is open, and releases the key
    workflows: []
  - id: ATS-PFM-INT-007-14
    level: api
    negative: false
    data_needs: Run-owned records and principals in an isolated workspace.
    bound_to: []
    provenance: proposed
    title: Moving selections makes account retirement possible
    category: interaction
    proves:
      - BR-CAP-PFM-INT-004-07
      - BR-CAP-PFM-INT-007-08
    exercises:
      - CAP-PFM-INT-007
      - CAP-PFM-INT-004
    preconditions: An old account has two bindings and a replacement lacks one required feature.
    steps: >-
      Move selections, inspect per-binding results, remove the remaining dependency and disconnect the
      old account.
    expected: >-
      The eligible binding moves, the failed move retains its source, and closure succeeds only after
      every dependency is removed.
    source:
      - >-
        services-platform:modules/integrations/tests/e2e/disconnect-and-uninstall.e2e.spec.js#answers a
        disconnection of a bound connection 409, code connection_has_bindings, naming each binding
      - >-
        services-platform:modules/integrations/tests/integration/services/bindings/binding-move.integration.spec.js#replaces
        every active binding of the source with one choosing the target, at the same scope, policy and
        note
    workflows:
      - WF-PFM-INT-007
evidence:
  - >-
    Each binding identifies an existing source test at the pinned revision; unbound scenarios remain
    proposed proof obligations.
coverage:
  rule: covered
  transition: covered
  validation: covered
  permission: covered
  edge: covered
  failure: covered
  boundary: 'gap: FND-PFM-INT-064'
  concurrency: covered
  invariant: covered
  interaction: covered
coverage_notes:
  covered: A designed scenario exists; executable coverage and a passing run require separate evidence.
  gaps: >-
    The finding records categories without a designed scenario and remaining permission and rule audit
    obligations.
---
# Assign provider connections to business needs: Capability Test Specification

## Coverage

| Rule | Proved By |
|---|---|
| `BR-CAP-PFM-INT-007-01` | `ATS-PFM-INT-007-01`, `ATS-PFM-INT-007-11` |
| `BR-CAP-PFM-INT-007-02` | `ATS-PFM-INT-007-02` |
| `BR-CAP-PFM-INT-007-03` | `ATS-PFM-INT-007-03` |
| `BR-CAP-PFM-INT-007-04` | `ATS-PFM-INT-007-04`, `ATS-PFM-INT-007-11`, `ATS-PFM-INT-007-12` |
| `BR-CAP-PFM-INT-007-05` | `ATS-PFM-INT-007-05` |
| `BR-CAP-PFM-INT-007-06` | `ATS-PFM-INT-007-06`, `ATS-PFM-INT-007-11`, `ATS-PFM-INT-007-13` |
| `BR-CAP-PFM-INT-007-07` | `ATS-PFM-INT-007-07` |
| `BR-CAP-PFM-INT-007-08` | `ATS-PFM-INT-007-08`, `ATS-PFM-INT-007-14` |
| `BR-CAP-PFM-INT-007-09` | `ATS-PFM-INT-007-09` |
| `BR-CAP-PFM-INT-007-10` | `ATS-PFM-INT-007-10` |
| `BR-CAP-PFM-INT-007-11` | `FND-PFM-INT-064` |

## Interactions With Related Capabilities

Binding changes select the account used by later calls and influence whether an account can be retired. The interaction cases compare preview with invocation and follow migration, invalidation and removal through account lifecycle checks.

The structured scenarios name the capabilities and rules involved. A bound test contributes only the outcomes it asserts; proposed transition matrices and composed interactions still require executable proof.
