---
id: CAP-MBR-MEM-005
title: Determine membership standing and refresh list status
feature: FEAT-MBR-MEM-01
product_area: membership
module: memberships
revision: 1
status: draft
product_intent: confirmed
implementation_evidence: partially-observed
supersedes:
  - 'inventory:CAP-MBR-MEM-008'
  - 'inventory:CAP-MBR-MEM-009'
  - 'inventory:CAP-MBR-MEM-010'
  - 'inventory:CAP-MBR-MEM-011'
  - 'inventory:CAP-MBR-CFG-015'
source_sha:
  services-membership: 5994c270e8a37a30f848e99ba5b5ee6b87c08893
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
intent_sources:
  - 'services-membership:README.md#2026-10-18 — Final acceptance'
  - 'services-membership:docs/migrations/membership-core/README.md#The sweep: schedule and catch-up'
purpose: >-
  Authorized readers inspect standing for a business date and distinguish term-derived answers from the cached
  status used by lists.
outcomes:
  - Record standing remains available when scheduled cache refresh is delayed.
  - Lists expose both cached and current-status filtering.
  - Joining history and continuity episodes describe the member’s tenure.
concepts:
  - CON-MBR-MEM-001
  - CON-MBR-MEM-002
actors:
  - ACT-MBR-007
  - ACT-MBR-008
  - ACT-MBR-006
  - ACT-MBR-012
surfaces:
  - console
  - api
  - job
permissions:
  - key: membership.members.read
    where_checked: api
    scope: record
  - key: membership.operations.run
    where_checked: api
    scope: tenant
rules:
  - id: BR-CAP-MBR-MEM-005-01
    proved_by: [ATS-MBR-MEM-005-01, ATS-MBR-MEM-005-10, ATS-MBR-MEM-005-11, ATS-MBR-MEM-015-10, ATS-MBR-MEM-019-12, TST-MBR-MEM-020, TST-MBR-MEM-247]
    statement: >-
      Date-based standing gives precedence to suspension, current coverage, grace, lapse, future coverage,
      pending coverage and no coverage, with grace taken from the type when specified and otherwise the
      program.
    kind: calculation
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-membership:modules/memberships/tests/integration/db/membership-functions.integration.spec.ts#answers
      Sam grace, lapsed, then active across the lapse and rejoin (scenario 4)
    origin: none
  - id: BR-CAP-MBR-MEM-005-02
    proved_by: [ATS-MBR-MEM-005-02, TST-MBR-MEM-198]
    statement: Current coverage under a type without benefits returns active without benefits.
    kind: calculation
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-membership:tests/acceptance/memberships/MBR-ACC-0179.acceptance.ts#MBR-ACC-0179: Every status
      the engine can answer, from the terms and the type's or program's grace: none, pending, future, active,
      active without benefits, grace, lapsed and suspended, with the same answer from the SQL twins
    origin: none
  - id: BR-CAP-MBR-MEM-005-03
    proved_by: [ATS-MBR-MEM-005-03, TST-MBR-MEM-029, TST-MBR-MEM-197]
    statement: >-
      Record and date-specific reads derive standing from terms, while the record view also exposes the cached
      status and its calculation date.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: observed
    source: >-
      services-membership:modules/memberships/services/reads/membership-views.ts:membershipView,
      membershipAsOf
    origin: none
  - id: BR-CAP-MBR-MEM-005-04
    proved_by: [ATS-MBR-MEM-005-04, TST-MBR-MEM-029]
    statement: >-
      Term writes refresh derived membership caches within their transaction, and a normal nightly sweep
      selects start, expiry and grace-end boundaries for the workspace’s business date.
    kind: calculation
    enforced_at:
      - service
    must_prove: true
    provenance: observed
    source: >-
      services-membership:modules/memberships/services/operations/term-writes.ts:finishMembershipWrite;
      modules/memberships/services/sweep/status-sweep.ts:sweepTenant
    origin: none
  - id: BR-CAP-MBR-MEM-005-05
    proved_by: [ATS-MBR-MEM-005-05, ATS-MBR-MEM-005-12, ATS-MBR-MEM-020-10, TST-MBR-MEM-029]
    statement: >-
      Expiry and lapse detections retain their actual boundary dates and are recorded at most once per term
      and detection kind, including when discovered late.
    kind: lifecycle
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: test
    source: >-
      services-membership:modules/memberships/tests/integration/services/status-sweep.integration.spec.ts#records
      lapsed_detected effective the day after grace ended, even when found late
    origin: none
  - id: BR-CAP-MBR-MEM-005-06
    proved_by: [ATS-MBR-MEM-005-06, TST-MBR-MEM-029]
    statement: >-
      A sweep after a missing prior run or a run older than yesterday refreshes every membership in the
      workspace.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-membership:modules/memberships/tests/integration/services/status-sweep.integration.spec.ts#catches
      up after a missed night, recomputing every membership
    origin: none
  - id: BR-CAP-MBR-MEM-005-07
    proved_by: [ATS-MBR-MEM-005-07, TST-MBR-MEM-029, TST-MBR-MEM-196]
    statement: >-
      An authorized administrator can request today’s sweep, and repeating a sweep for the same day does not
      duplicate detections.
    kind: permission
    enforced_at:
      - api
      - service
    must_prove: true
    provenance: test
    source: >-
      services-membership:modules/memberships/tests/integration/services/status-sweep.integration.spec.ts#records
      nothing twice when the same night is swept again
    origin: none
  - id: BR-CAP-MBR-MEM-005-08
    proved_by: []
    statement: The schedule consumer is configured to pause a schedule after five consecutive failures.
    kind: policy
    enforced_at:
      - service
    must_prove: false
    provenance: observed
    source: >-
      services-membership:modules/memberships/aws/lambda/SCHEDULE_CONSUMER.ts:STATUS_SWEEP_AUTO_PAUSE_AFTER_FAILURES
    origin: none
  - id: BR-CAP-MBR-MEM-005-09
    proved_by: [ATS-MBR-MEM-005-08, TST-MBR-MEM-020, TST-MBR-MEM-247]
    statement: >-
      When the original join date is empty, cache recomputation derives it from the first effective term;
      continuity starts another episode when an intervening gap exceeds the program allowance.
    kind: calculation
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: observed
    source: 'services-membership:modules/memberships/services/membership-caches.ts:recomputeMembershipCache'
    origin: none
  - id: BR-CAP-MBR-MEM-005-10
    proved_by: [ATS-MBR-MEM-005-09, ATS-MBR-MEM-017-06, TST-MBR-MEM-024, TST-MBR-MEM-197, TST-MBR-MEM-204]
    statement: >-
      Lists filter by owner, program, cached status or today’s derived status and by dated unit membership,
      optionally including descendants, without duplicating a membership across matching units.
    kind: policy
    enforced_at:
      - api
      - service
    must_prove: true
    provenance: observed
    source: >-
      services-membership:modules/memberships/services/reads/membership-views.ts:membershipFiltersOf;
      modules/memberships/services/persistence/memberships.ts:listMembershipRows
    origin: none
  - id: BR-CAP-MBR-MEM-005-11
    proved_by: []
    statement: >-
      The product should honor the program’s grace-benefits setting, which defaults to enabled, when deciding
      rights during grace.
    kind: policy
    enforced_at:
      - service
      - database
    must_prove: true
    provenance: unknown
    source: FND-MBR-MEM-013
    origin: 'D-07 (services-membership:docs/migrations/membership-core/README.md#Tables and migrations)'
scenarios:
  - id: SC-CAP-MBR-MEM-005-01
    given: Sam’s term ends on 30 June 2026 and carries 60 days of grace.
    when: A delayed sweep catches up on 5 September 2026.
    then: The cache becomes lapsed and the lapse detection remains dated 30 August 2026.
    provenance: test
    source: >-
      services-membership:modules/memberships/tests/integration/services/status-sweep.integration.spec.ts#catches
      up after a missed night, recomputing every membership
  - id: SC-CAP-MBR-MEM-005-02
    given: The workspace has missed a nightly cache refresh.
    when: The next sweep runs after that interruption.
    then: Its catch-up mode examines every membership in the workspace.
    provenance: test
    source: >-
      services-membership:modules/memberships/tests/integration/services/status-sweep.integration.spec.ts#catches
      up after a missed night, recomputing every membership
edge_cases: []
constraints:
  - Membership list pages contain no more than 500 records.
depends_on: []
related:
  - CAP-MBR-MEM-015
  - CAP-MBR-MEM-019
journeys:
  - JNY-MBR-MEM-001
open_questions: []
evidence:
  - repository: services-membership
    source_sha: 5994c270e8a37a30f848e99ba5b5ee6b87c08893
    paths:
      - modules/memberships/services/reads/membership-views.ts
      - modules/memberships/services/membership-caches.ts
      - modules/memberships/services/sweep/status-sweep.ts
      - modules/memberships/services/sweep/status-sweep-schedule.ts
      - modules/terms/services/status.ts
      - modules/terms/services/sweep.ts
      - modules/memberships/db/status-sweeps.table.ts
      - modules/memberships/db/schedules.table.ts
      - modules/memberships/db/schedule-runs.table.ts
      - modules/memberships/db/membership-lifecycle-events.table.ts
      - modules/memberships/db/memberships-for-queries.view.ts
      - modules/memberships/db/membership-unit-views.view.ts
      - modules/memberships/tests/integration/services/status-sweep.integration.spec.ts
      - modules/memberships/tests/integration/db/membership-functions.integration.spec.ts
      - docs/migrations/membership-core/README.md
controls: [TC-AVL-002, TC-AVL-003, TC-AVL-004, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-AZ-005, TC-AZ-006, TC-CHG-001, TC-CHG-002, TC-CHG-003, TC-CHG-004, TC-CRY-001, TC-CRY-002, TC-CRY-003, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-DAT-007, TC-IAM-001, TC-IAM-002, TC-IAM-004, TC-IAM-005, TC-IAM-006, TC-LOG-002, TC-LOG-003, TC-LOG-004, TC-LOG-005, TC-MON-001, TC-MON-002, TC-MON-004, TC-PI-001, TC-PI-002, TC-PI-003, TC-PI-004, TC-PI-005, TC-PRV-001, TC-PRV-002, TC-SEC-001, TC-SEC-004, TC-TEN-001, TC-TEN-002, TC-TEN-003]
exercised_by: [FAS-MBR-MEM-01-01, FAS-MBR-MEM-01-03, FAS-MBR-MEM-01-05]
suites: [TST-MBR-MEM-020, TST-MBR-MEM-024, TST-MBR-MEM-029, TST-MBR-MEM-196, TST-MBR-MEM-197, TST-MBR-MEM-198, TST-MBR-MEM-204, TST-MBR-MEM-247]
---

# Determine membership standing and refresh list status

## Purpose

Staff and other applications need a dependable answer about membership on a chosen date. They also need to understand why a list based on stored status can differ from a current record view after a missed refresh.

## How It Works

Readers inspect a membership’s dated periods through the record or date-specific view. The view presents derived standing alongside joining and continuity information. Lists offer a separate choice between saved status and status calculated for today. A daily sweep maintains the saved values used by that listing workflow. Administrators can also request a sweep when investigating stale lists. A late run catches up rather than relying solely on that night’s boundaries. The sweep ledger and lifecycle detections make the refresh inspectable. The grace-benefits finding remains a product concern because the stored setting does not currently determine benefits.

## Relationships

- The shared term engine supplies standing, continuity and sweep calculations.
- Officer scope limits which membership records a reader can inspect.
- Membership reporting exposes related derived answers through query datasets.
