---
id: STATE-PFM-INT-006
title: Capability binding lifecycle
object: DOM-PFM-INT-003
product_area: platform
module: integrations
revision: 1
status: draft
design_intent: confirmed
implementation_evidence: observed
origin: 'docs/milestones/INTG-M2-calls-through-the-gateway.md#Decisions M2-D4, M2-D9 (Andrew)'
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
states:
  - name: absent
    meaning: The capability major and scope have no current account choice.
  - name: active
    meaning: The current routing choice can be considered by resolution.
  - name: invalid
    meaning: The current choice has an eligibility failure with a saved reason.
  - name: superseded
    meaning: A replacement or removal retired this row from resolution while keeping history.
transitions:
  - 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.
    who: Integration administrator
    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
  - 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.
    who: 'Integration administrator, bindings move or migration'
    provenance: test
    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.
    who: Integration administrator
    provenance: test
    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.
    who: Binding hooks inside the causing transaction
    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
  - 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.
    who: Binding hooks inside the causing transaction
    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
invalid:
  - from: superseded
    to: active
    why: History rows cannot become current again; a new row continues the scope revision.
  - from: absent
    to: invalid
    why: Initial put validation refuses an ineligible account choice.
concurrency: >-
  The write path serializes current choices and protects applicable uniqueness. Reassessment shares the
  dependency-change transaction, and rollback discards notices. A current invalid binding still blocks
  disconnection, so the removed draft edge cannot occur through ordinary closure.
invariants:
  - INV-DOM-PFM-INT-003-01
  - INV-DOM-PFM-INT-003-02
evidence:
  - >-
    services-platform at ad3f6a65: modules/integrations/db/integration-bindings.table.ts;
    services/bindings/binding-operations.ts, invalidation.ts, binding-notices.ts; docs/integrations/README.md
    (Bindings; Invalidation and restoration)
---

# Capability binding lifecycle

## The Lifecycle

```mermaid
stateDiagram-v2
  state "absent" as s0
  state "active" as s1
  state "invalid" as s2
  state "superseded" as s3
  s0 --> s1: Create an account selection
  s1 --> s3: Replace or remove the current selection
  s2 --> s3: Replace or remove an unusable selection
  s1 --> s2: Lose account eligibility
  s2 --> s1: Regain account eligibility
```

## Transitions Explained

A new eligible choice becomes current. Replacement or removal retires the old row while advancing scope history. Dependency changes can make the current row invalid and later restore it, without removing the administrator’s selection.

## What Cannot Happen

History rows cannot become current again; a new row continues the scope revision. Initial put validation refuses an ineligible account choice.

## Concurrency and Timing

The write path serializes current choices and protects applicable uniqueness. Reassessment shares the dependency-change transaction, and rollback discards notices. A current invalid binding still blocks disconnection, so the removed draft edge cannot occur through ordinary closure.
