---
id: ATS-MBR-MEM-003
scope: CAP-MBR-MEM-003
product_area: membership
module: memberships
revision: 2
status: proposed
approved_by: null
approved_at: null
source_sha:
  services-membership: 5994c270e8a37a30f848e99ba5b5ee6b87c08893
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
scenarios:
  - id: ATS-MBR-MEM-003-01
    title: Reject stale changes and closure of a cancelled term
    level: api
    proves:
      - BR-CAP-MBR-MEM-003-01
    preconditions: >-
      A term has been read by two staff callers, and another term has already
      been cancelled.
    steps:
      - do: >-
          Correct using the first caller, retry a correction at the older
          version, and attempt to terminate the cancelled term.
        expect: >-
          The stale write identifies the current version; the cancelled term
          cannot be terminated.
        provenance: proposed
        source: >-
          services-membership:modules/memberships/services/operations/staff-operations.ts:lockTerm,
          correctTerm, terminateTerm
    expected: >-
      The stale write identifies the current version; the cancelled term cannot
      be terminated.
    negative: true
    data_needs: >-
      Principal term records, applicable status reasons and the dependent
      records required by this scenario.
    bound_to: []
    provenance: proposed
    source: >-
      services-membership:modules/memberships/services/operations/staff-operations.ts:lockTerm,
      correctTerm, terminateTerm
    category: concurrency
  - id: ATS-MBR-MEM-003-02
    title: Reproduce term knowledge from before a correction
    level: api
    proves:
      - BR-CAP-MBR-MEM-003-02
    preconditions: >-
      A dated term has a recorded history and an identifiable moment before its
      amendment.
    steps:
      - do: >-
          Amend the start with a reason, inspect versions, and read using
          knowledge before and after the write.
        expect: >-
          History retains the original start and actor; the earlier-known and
          later-known reads return their respective starts.
        provenance: test
        source:
          - >-
            services-membership:modules/memberships/tests/integration/services/staff-operations.integration.spec.ts#keeps
            the old truth of a correction in the versions, recorded with the
            actor
          - >-
            services-membership:modules/memberships/tests/integration/db/membership-functions.integration.spec.ts#answers
            the corrected start with a known_at after the correction
          - >-
            services-membership:modules/memberships/tests/integration/db/membership-functions.integration.spec.ts#keeps
            answering what was known before the correction with a known_at
            before it
    expected: >-
      History retains the original start and actor; the earlier-known and
      later-known reads return their respective starts.
    negative: false
    data_needs: >-
      Principal term records, applicable status reasons and the dependent
      records required by this scenario.
    bound_to:
      - TST-MBR-MEM-028
      - TST-MBR-MEM-020
    provenance: test
    source: >-
      services-membership:modules/memberships/tests/integration/services/staff-operations.integration.spec.ts#keeps
      the old truth of a correction in the versions, recorded with the actor
    category: invariant
    binding_evidence:
      - suite: TST-MBR-MEM-028
        source: >-
          services-membership:modules/memberships/tests/integration/services/staff-operations.integration.spec.ts#keeps
          the old truth of a correction in the versions, recorded with the actor
      - suite: TST-MBR-MEM-020
        source: >-
          services-membership:modules/memberships/tests/integration/db/membership-functions.integration.spec.ts#answers
          the corrected start with a known_at after the correction
      - suite: TST-MBR-MEM-020
        source: >-
          services-membership:modules/memberships/tests/integration/db/membership-functions.integration.spec.ts#keeps
          answering what was known before the correction with a known_at before
          it
  - id: ATS-MBR-MEM-003-03
    title: Constrain affiliations after dates and package change
    level: api
    proves:
      - BR-CAP-MBR-MEM-003-04
    preconditions: >-
      A term holds chapter affiliations and an alternative package permits fewer
      chapters.
    steps:
      - do: >-
          Move the term’s start later, then attempt to select the more
          restrictive package.
        expect: >-
          Affiliations starting before the amended start move forward; the
          excessive chapter count prevents the package change.
        provenance: test
        source:
          - >-
            services-membership:modules/memberships/tests/integration/services/affiliations.integration.spec.ts#moves
            a term’s affiliations with a corrected start
          - >-
            services-membership:tests/acceptance/memberships/MBR-ACC-0198.acceptance.ts#MBR-ACC-0198:
            A member's chapters stay inside her term when it is shortened or
            ended, a package that allows fewer chapters cannot replace hers, and
            her chapter's officer sees her only while her chain reaches the
            chapter
    expected: >-
      Affiliations starting before the amended start move forward; the excessive
      chapter count prevents the package change.
    negative: false
    data_needs: >-
      Principal term records, applicable status reasons and the dependent
      records required by this scenario.
    bound_to:
      - TST-MBR-MEM-024
      - TST-MBR-MEM-214
    provenance: test
    source: >-
      services-membership:modules/memberships/tests/integration/services/affiliations.integration.spec.ts#moves
      a term’s affiliations with a corrected start
    category: validation
    binding_evidence:
      - suite: TST-MBR-MEM-024
        source: >-
          services-membership:modules/memberships/tests/integration/services/affiliations.integration.spec.ts#moves
          a term’s affiliations with a corrected start
      - suite: TST-MBR-MEM-214
        source: >-
          services-membership:tests/acceptance/memberships/MBR-ACC-0198.acceptance.ts#MBR-ACC-0198:
          A member's chapters stay inside her term when it is shortened or
          ended, a package that allows fewer chapters cannot replace hers, and
          her chapter's officer sees her only while her chain reaches the
          chapter
  - id: ATS-MBR-MEM-003-04
    title: Distinguish early closure from recording a later drop
    level: api
    proves:
      - BR-CAP-MBR-MEM-003-06
    preconditions: One term is effective and another has already expired.
    steps:
      - do: >-
          Terminate the effective term from a chosen date and record the expired
          member’s drop later.
        expect: >-
          The effective period contracts to the preceding day; the expired
          period retains its end and records the later drop date.
        provenance: test
        source:
          - >-
            services-membership:modules/memberships/tests/integration/services/staff-operations.integration.spec.ts#terminates
            a term from the effective date, with the reason, and the status
            follows
          - >-
            services-membership:tests/e2e/s04-lapse-and-rejoin.e2e.spec.ts#drops
            the expired term with its reason and leaves its dates as they were
    expected: >-
      The effective period contracts to the preceding day; the expired period
      retains its end and records the later drop date.
    negative: false
    data_needs: >-
      Principal term records, applicable status reasons and the dependent
      records required by this scenario.
    bound_to:
      - TST-MBR-MEM-028
      - TST-MBR-MEM-247
    provenance: test
    source: >-
      services-membership:modules/memberships/tests/integration/services/staff-operations.integration.spec.ts#terminates
      a term from the effective date, with the reason, and the status follows
    category: transition
    binding_evidence:
      - suite: TST-MBR-MEM-028
        source: >-
          services-membership:modules/memberships/tests/integration/services/staff-operations.integration.spec.ts#terminates
          a term from the effective date, with the reason, and the status
          follows
      - suite: TST-MBR-MEM-247
        source: >-
          services-membership:tests/e2e/s04-lapse-and-rejoin.e2e.spec.ts#drops
          the expired term with its reason and leaves its dates as they were
  - id: ATS-MBR-MEM-003-05
    title: Cancel future coverage and reuse its dates
    level: api
    proves:
      - BR-CAP-MBR-MEM-003-07
    preconditions: A future committed term has not yet begun.
    steps:
      - do: >-
          Close it before its start, inspect standing, and add replacement
          coverage for the same dates.
        expect: >-
          The original period is cancelled; standing falls back and replacement
          coverage is accepted.
        provenance: test
        source:
          - >-
            services-membership:modules/events/tests/integration/business-events.integration.spec.ts#states
            membership.term.cancelled, not terminated, for a term that had not
            started
          - >-
            services-membership:tests/acceptance/memberships/MBR-ACC-0164.acceptance.ts#MBR-ACC-0164:
            A prepaid future term is cancelled before it starts, the membership
            falls back to none, the dates become free again, and a cancelled
            term cannot be closed twice
    expected: >-
      The original period is cancelled; standing falls back and replacement
      coverage is accepted.
    negative: false
    data_needs: >-
      Principal term records, applicable status reasons and the dependent
      records required by this scenario.
    bound_to:
      - TST-MBR-MEM-014
      - TST-MBR-MEM-183
    provenance: test
    source: >-
      services-membership:modules/events/tests/integration/business-events.integration.spec.ts#states
      membership.term.cancelled, not terminated, for a term that had not started
    category: transition
    binding_evidence:
      - suite: TST-MBR-MEM-014
        source: >-
          services-membership:modules/events/tests/integration/business-events.integration.spec.ts#states
          membership.term.cancelled, not terminated, for a term that had not
          started
      - suite: TST-MBR-MEM-183
        source: >-
          services-membership:tests/acceptance/memberships/MBR-ACC-0164.acceptance.ts#MBR-ACC-0164:
          A prepaid future term is cancelled before it starts, the membership
          falls back to none, the dates become free again, and a cancelled term
          cannot be closed twice
  - id: ATS-MBR-MEM-003-06
    title: Limit chapter coverage through an ended term
    level: api
    proves:
      - BR-CAP-MBR-MEM-003-08
    preconditions: A member has a term with a chapter affiliation.
    steps:
      - do: Terminate the term and inspect both its last day and the chapter row.
        expect: >-
          The term has the shortened end; the affiliation end is either empty or
          equal to that end, with coverage limited by the term.
        provenance: test
        source:
          - >-
            services-membership:tests/acceptance/memberships/MBR-ACC-0198.acceptance.ts#MBR-ACC-0198:
            A member's chapters stay inside her term when it is shortened or
            ended, a package that allows fewer chapters cannot replace hers, and
            her chapter's officer sees her only while her chain reaches the
            chapter
    expected: >-
      The term has the shortened end; the affiliation end is either empty or
      equal to that end, with coverage limited by the term.
    negative: false
    data_needs: >-
      Principal term records, applicable status reasons and the dependent
      records required by this scenario.
    bound_to:
      - TST-MBR-MEM-214
    provenance: test
    source: >-
      services-membership:tests/acceptance/memberships/MBR-ACC-0198.acceptance.ts#MBR-ACC-0198:
      A member's chapters stay inside her term when it is shortened or ended, a
      package that allows fewer chapters cannot replace hers, and her chapter's
      officer sees her only while her chain reaches the chapter
    category: boundary
    binding_evidence:
      - suite: TST-MBR-MEM-214
        source: >-
          services-membership:tests/acceptance/memberships/MBR-ACC-0198.acceptance.ts#MBR-ACC-0198:
          A member's chapters stay inside her term when it is shortened or
          ended, a package that allows fewer chapters cannot replace hers, and
          her chapter's officer sees her only while her chain reaches the
          chapter
  - id: ATS-MBR-MEM-003-07
    title: Adjust granted mirrors when their source contracts
    level: api
    proves:
      - BR-CAP-MBR-MEM-003-09
    preconditions: A package-granted term mirrors a source period.
    steps:
      - do: >-
          Shorten, extend, terminate and cancel source periods, inspecting the
          corresponding granted periods.
        expect: >-
          A mirror shortens, remains at its shortened end after extension, or
          closes with the source as appropriate.
        provenance: test
        source:
          - >-
            services-membership:tests/acceptance/memberships/MBR-ACC-0182.acceptance.ts#MBR-ACC-0182:
            Granted terms follow their source down but never up: shortened with
            a correction, terminated or cancelled with it, while the granted
            membership is not suspended with the primary
    expected: >-
      A mirror shortens, remains at its shortened end after extension, or closes
      with the source as appropriate.
    negative: false
    data_needs: >-
      Principal term records, applicable status reasons and the dependent
      records required by this scenario.
    bound_to:
      - TST-MBR-MEM-201
    provenance: test
    source: >-
      services-membership:tests/acceptance/memberships/MBR-ACC-0182.acceptance.ts#MBR-ACC-0182:
      Granted terms follow their source down but never up: shortened with a
      correction, terminated or cancelled with it, while the granted membership
      is not suspended with the primary
    category: interaction
    binding_evidence:
      - suite: TST-MBR-MEM-201
        source: >-
          services-membership:tests/acceptance/memberships/MBR-ACC-0182.acceptance.ts#MBR-ACC-0182:
          Granted terms follow their source down but never up: shortened with a
          correction, terminated or cancelled with it, while the granted
          membership is not suspended with the primary
  - id: ATS-MBR-MEM-003-08
    title: Contract linked periods when staff correct the source
    category: interaction
    level: api
    proves:
      - BR-CAP-MBR-MEM-003-09
      - BR-CAP-MBR-MEM-006-07
    interacts_with:
      - CAP-MBR-MEM-006
    workflows:
      - WF-MBR-MEM-003
      - WF-MBR-MEM-004
    relies_on:
      - ATS-MBR-MEM-003-07
      - ATS-MBR-MEM-006-07
    preconditions: An organizational holding and a granting holding have dependent periods.
    steps:
      - do: 'Shorten each source period, then read its linked periods.'
        expect: >-
          Dependent periods retain their source links and reflect the permitted
          contracted coverage.
        provenance: proposed
        source: &ref_0
          - >-
            services-membership:tests/acceptance/memberships/MBR-ACC-0182.acceptance.ts#MBR-ACC-0182:
            Granted terms follow their source down but never up: shortened with
            a correction, terminated or cancelled with it, while the granted
            membership is not suspended with the primary
          - >-
            services-membership:modules/memberships/tests/integration/services/organization-children.integration.spec.ts#re-mirrors
            the children when the parent’s end is corrected: a child never
            outlasts the parent
    expected: >-
      Dependent periods retain their source links and reflect the permitted
      contracted coverage.
    negative: false
    data_needs: >-
      An isolated workspace with the specified membership, package, chapter and
      partner-port fixtures.
    bound_to: []
    provenance: proposed
    source: *ref_0
  - id: ATS-MBR-MEM-003-09
    title: Keep chapters valid after a period correction
    category: interaction
    level: api
    proves:
      - BR-CAP-MBR-MEM-003-04
      - BR-CAP-MBR-MEM-007-03
    interacts_with:
      - CAP-MBR-MEM-007
    workflows: []
    relies_on:
      - ATS-MBR-MEM-003-03
      - ATS-MBR-MEM-007-03
    preconditions: A current period has two chapter connections.
    steps:
      - do: >-
          Move the first day later, then attempt a package change that permits
          only one chapter.
        expect: >-
          The saved connections start inside the amended period; the invalid
          package change leaves the saved correction intact.
        provenance: proposed
        source: &ref_1
          - >-
            services-membership:modules/memberships/tests/integration/services/affiliations.integration.spec.ts#moves
            a term’s affiliations with a corrected start
          - >-
            services-membership:modules/memberships/tests/unit/unit-rules.spec.ts#refuses
            fewer affiliations of a type than its minimum from the day the
            operation takes effect
    expected: >-
      The saved connections start inside the amended period; the invalid package
      change leaves the saved correction intact.
    negative: false
    data_needs: >-
      An isolated workspace with the specified membership, package, chapter and
      partner-port fixtures.
    bound_to: []
    provenance: proposed
    source: *ref_1
  - id: ATS-MBR-MEM-003-10
    title: Make a planned billing action stale after correction
    category: interaction
    level: api
    proves:
      - BR-CAP-MBR-MEM-003-06
      - BR-CAP-MBR-MEM-013-07
    interacts_with:
      - CAP-MBR-MEM-013
    workflows:
      - WF-MBR-MEM-004
      - WF-MBR-MEM-018
    relies_on:
      - ATS-MBR-MEM-003-04
      - ATS-MBR-MEM-013-07
    preconditions: A renewal action is planned from a current term.
    steps:
      - do: 'Correct the term, then execute the planned action.'
        expect: >-
          The action is stale and creates no renewal order for the corrected
          version.
        provenance: proposed
        source: &ref_2
          - >-
            services-membership:modules/memberships/tests/integration/services/staff-operations.integration.spec.ts#terminates
            a term from the effective date, with the reason, and the status
            follows
          - >-
            services-membership:modules/billing/tests/integration/billing-runs.integration.spec.ts#refuses
            as stale an action whose term changed after planning
    expected: >-
      The action is stale and creates no renewal order for the corrected
      version.
    negative: true
    data_needs: >-
      An isolated workspace with the specified membership, package, chapter and
      partner-port fixtures.
    bound_to: []
    provenance: proposed
    source: *ref_2
  - id: ATS-MBR-MEM-003-11
    title: Resolve expiry attention through staff closure
    category: interaction
    level: api
    proves:
      - BR-CAP-MBR-MEM-003-06
      - BR-CAP-MBR-MEM-014-07
    interacts_with:
      - CAP-MBR-MEM-014
    workflows:
      - WF-MBR-MEM-004
    relies_on:
      - ATS-MBR-MEM-003-04
      - ATS-MBR-MEM-014-07
    preconditions: Publication is enabled and a started period has an expiry item.
    steps:
      - do: >-
          Terminate the period and inspect its last day and attention outcome
          after commit.
        expect: The period is closed and its existing item is resolved as terminated.
        provenance: proposed
        source: &ref_3
          - >-
            services-membership:modules/memberships/tests/integration/services/staff-operations.integration.spec.ts#terminates
            a term from the effective date, with the reason, and the status
            follows
          - >-
            services-membership:modules/memberships/tests/integration/services/expiring-memberships.integration.spec.ts#resolves
            the item renewed in the staff renewal’s transaction
    expected: The period is closed and its existing item is resolved as terminated.
    negative: false
    data_needs: >-
      An isolated workspace with the specified membership, package, chapter and
      partner-port fixtures.
    bound_to: []
    provenance: proposed
    source: *ref_3
  - id: ATS-MBR-MEM-003-12
    title: Preserve the pre-correction answer for earlier knowledge
    category: interaction
    level: api
    proves:
      - BR-CAP-MBR-MEM-003-02
      - BR-CAP-MBR-MEM-018-08
    interacts_with:
      - CAP-MBR-MEM-018
    workflows:
      - WF-MBR-MEM-003
    relies_on:
      - ATS-MBR-MEM-003-02
      - ATS-MBR-MEM-018-08
    preconditions: A committed term has recorded history.
    steps:
      - do: >-
          Correct its start, then read the same date with recording instants
          before and after the correction.
        expect: >-
          The earlier-known answer retains the first start; the later-known
          answer reflects the correction.
        provenance: proposed
        source: &ref_4
          - >-
            services-membership:modules/memberships/tests/integration/services/staff-operations.integration.spec.ts#keeps
            the old truth of a correction in the versions, recorded with the
            actor
          - >-
            services-membership:modules/history/tests/integration/membership-as-of.integration.spec.ts#answers
            the term as it was known before the correction, with a known_at
            before it
    expected: >-
      The earlier-known answer retains the first start; the later-known answer
      reflects the correction.
    negative: false
    data_needs: >-
      An isolated workspace with the specified membership, package, chapter and
      partner-port fixtures.
    bound_to: []
    provenance: proposed
    source: *ref_4
  - id: ATS-MBR-MEM-003-13
    title: Publish the last covered day of staff termination
    category: interaction
    level: api
    proves:
      - BR-CAP-MBR-MEM-003-06
      - BR-CAP-MBR-MEM-020-03
    interacts_with:
      - CAP-MBR-MEM-020
    workflows:
      - WF-MBR-MEM-004
    relies_on:
      - ATS-MBR-MEM-003-04
      - ATS-MBR-MEM-020-03
    preconditions: A person holds a started period.
    steps:
      - do: >-
          Terminate it from a selected day and inspect the committed termination
          event; repeat the operation in a transaction that rolls back.
        expect: >-
          The committed event identifies the shortened last day; the rolled-back
          attempt publishes no event.
        provenance: proposed
        source: &ref_5
          - >-
            services-membership:modules/memberships/tests/integration/services/staff-operations.integration.spec.ts#terminates
            a term from the effective date, with the reason, and the status
            follows
          - >-
            services-membership:modules/events/tests/integration/business-events.integration.spec.ts#states
            one membership.term.terminated for a staff termination, with the
            person’s contact_id and the last day of rights
    expected: >-
      The committed event identifies the shortened last day; the rolled-back
      attempt publishes no event.
    negative: false
    data_needs: >-
      An isolated workspace with the specified membership, package, chapter and
      partner-port fixtures.
    bound_to: []
    provenance: proposed
    source: *ref_5
  - id: ATS-MBR-MEM-003-14
    title: Keep correction and termination behind separate staff grants
    category: permission
    level: api
    proves:
      - BR-CAP-MBR-MEM-003-01
    permissions:
      - membership.terms.correct
      - membership.terms.terminate
    preconditions: >-
      A current term and a future term have known versions; staff and a
      read-only colleague share their identifiers.
    steps:
      - do: >-
          Correct the current term as staff and the colleague; attempt
          future-term closure as the colleague before closing it as staff.
        expect: >-
          The colleague’s requests are refused; the saved correction retains its
          version and dates, and only staff closes the future term.
        provenance: test
        source: >-
          services-membership:tests/acceptance/memberships/MBR-ACC-0172.acceptance.ts
    expected: >-
      The colleague’s requests are refused; the saved correction retains its
      version and dates, and only staff closes the future term.
    negative: true
    data_needs: >-
      Suite-owned workspaces, annual membership fixtures, signed staff and
      restricted contexts.
    bound_to:
      - TST-MBR-MEM-191
    binding_evidence:
      - suite: TST-MBR-MEM-191
        source: >-
          services-membership:tests/acceptance/memberships/MBR-ACC-0172.acceptance.ts
    provenance: test
    source: >-
      services-membership:tests/acceptance/memberships/MBR-ACC-0172.acceptance.ts
evidence:
  - >-
    services-membership at 5994c270e8a37a30f848e99ba5b5ee6b87c08893: reviewed
    term correction and closure, affiliation trimming, granted mirror
    adjustments and the cited history, integration and acceptance assertions.
  - >-
    rhythm-v2-docs:specs/membership/memberships/design/: domain objects, state
    models and workflows reviewed for coverage.
coverage:
  rule: 'gap: FND-MBR-MEM-085'
  transition: 'gap: FND-MBR-MEM-085'
  validation: covered
  permission: covered
  edge: 'gap: FND-MBR-MEM-085'
  failure: 'gap: FND-MBR-MEM-085'
  boundary: covered
  concurrency: covered
  invariant: 'gap: FND-MBR-MEM-085'
  interaction: covered
coverage_notes:
  transition: >-
    The scenarios do not enumerate every applicable object transition; the
    finding preserves the remaining transition matrix.
  permission: >-
    The signed API acceptance case asserts allowed staff work and
    missing-permission refusals for every named key.
  invariant: >-
    Existing invariant examples do not cover every applicable domain-object
    constraint.
  interaction: >-
    Every related capability and each cross-capability workflow has an explicit
    composite scenario. Unbound composites remain proposed.
---

# Correct or close a term without losing earlier knowledge: Capability Test Specification

## Coverage

| Rule | Scenario or Finding |
|---|---|
| `BR-CAP-MBR-MEM-003-01` | `ATS-MBR-MEM-003-01`, `ATS-MBR-MEM-003-14` |
| `BR-CAP-MBR-MEM-003-02` | `ATS-MBR-MEM-003-02`, `ATS-MBR-MEM-003-12` |
| `BR-CAP-MBR-MEM-003-03` | no scenario: `FND-MBR-MEM-010` |
| `BR-CAP-MBR-MEM-003-04` | `ATS-MBR-MEM-003-03`, `ATS-MBR-MEM-003-09` |
| `BR-CAP-MBR-MEM-003-05` | no scenario: `FND-MBR-MEM-011` |
| `BR-CAP-MBR-MEM-003-06` | `ATS-MBR-MEM-003-04`, `ATS-MBR-MEM-003-10`, `ATS-MBR-MEM-003-11`, `ATS-MBR-MEM-003-13` |
| `BR-CAP-MBR-MEM-003-07` | `ATS-MBR-MEM-003-05` |
| `BR-CAP-MBR-MEM-003-08` | `ATS-MBR-MEM-003-06` |
| `BR-CAP-MBR-MEM-003-09` | `ATS-MBR-MEM-003-07`, `ATS-MBR-MEM-003-08` |

## Interactions With Related Capabilities

The interaction cases test how a shared holding, period, chapter connection or recorded change affects related work. Each case names its related capabilities and workflows in frontmatter. A composite case remains proposed until executable assertions establish every part of its expected outcome.
