---
id: ATS-PFM-ELG-009
scope: CAP-PFM-ELG-009
product_area: platform
module: eligibility
revision: 3
status: proposed
approved_by: null
approved_at: null
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
scenarios:
  - id: ATS-PFM-ELG-009-01
    title: Select consequential history
    level: unit
    proves:
      - BR-CAP-PFM-ELG-009-01
    preconditions: Display and transactional bindings exist in a workspace.
    steps: 'Evaluate 21 display questions including uncertainty, one transaction and one dry run.'
    expected: >-
      Transactional and uncertain answers are retained, ordinary displays are sampled and the dry
      run is omitted.
    negative: false
    data_needs: No fixtures beyond the described setup.
    bound_to:
      - >-
        services-platform:modules/eligibility/tests/unit/compile-and-evaluate.spec.js#records every
        transactional and authorization decision
      - TST-PFM-ELG-472
      - >-
        services-platform:modules/eligibility/tests/unit/compile-and-evaluate.spec.js#records every
        indeterminate display decision
      - >-
        services-platform:modules/eligibility/tests/unit/compile-and-evaluate.spec.js#records the
        first display decision of a tenant and then one in every rate
      - >-
        services-platform:modules/eligibility/tests/integration/services/evaluate/hosted-evaluate.integration.spec.js#never
        records a dry run
      - TST-PFM-ELG-430
      - >-
        react-console:acceptance/eligibility/playwright/journeys/evaluation/ELIG-ACC-0290.spec.ts#ELIG-ACC-0290
      - TST-PFM-ELG-146
    provenance: test
    source: >-
      services-platform:modules/eligibility/tests/unit/compile-and-evaluate.spec.js#records every
      transactional and authorization decision
    category: rule
    limitations:
      - FND-PFM-ELG-052
    action_evidence:
      provenance: test
      source: >-
        services-platform:modules/eligibility/tests/unit/compile-and-evaluate.spec.js#records every
        transactional and authorization decision
    assertion_evidence:
      provenance: test
      source: >-
        services-platform:modules/eligibility/tests/unit/compile-and-evaluate.spec.js#records every
        transactional and authorization decision
    binding_scope: >-
      The cited tests contribute their reachable assertions; the binding does not establish
      execution or every step of this scenario.
    binding_limitations:
      - FND-PFM-ELG-074
  - id: ATS-PFM-ELG-009-02
    title: Prevent historical mutation
    level: api
    proves:
      - BR-CAP-PFM-ELG-009-02
      - INV-DOM-PFM-ELG-003-01
    preconditions: A decision is retained.
    steps: Attempt application update and deletion.
    expected: Both fail and preserve the record.
    negative: true
    data_needs: No fixtures beyond the described setup.
    bound_to:
      - >-
        services-platform:modules/eligibility/tests/integration/db/eligibility-decisions.table.integration.spec.js#grants
        the application role SELECT and INSERT and nothing else, and no other role anything
      - TST-PFM-ELG-420
      - >-
        services-platform:modules/eligibility/tests/integration/db/eligibility-decisions.table.integration.spec.js#refuses
        an update from the application role
      - >-
        services-platform:modules/eligibility/tests/integration/db/eligibility-decisions.table.integration.spec.js#refuses
        a delete from the application role
      - >-
        services-platform:modules/eligibility/tests/integration/db/eligibility-decisions.table.integration.spec.js#refuses
        more than fifty reasons, by the reasons check
    provenance: test
    source: >-
      services-platform:modules/eligibility/tests/integration/db/eligibility-decisions.table.integration.spec.js#grants
      the application role SELECT and INSERT and nothing else, and no other role anything
    category: invariant
    action_evidence:
      provenance: test
      source: >-
        services-platform:modules/eligibility/tests/integration/db/eligibility-decisions.table.integration.spec.js#grants
        the application role SELECT and INSERT and nothing else, and no other role anything
    assertion_evidence:
      provenance: test
      source: >-
        services-platform:modules/eligibility/tests/integration/db/eligibility-decisions.table.integration.spec.js#grants
        the application role SELECT and INSERT and nothing else, and no other role anything
    binding_scope: >-
      The cited tests contribute their reachable assertions; the binding does not establish
      execution or every step of this scenario.
    binding_limitations:
      - FND-PFM-ELG-074
  - id: ATS-PFM-ELG-009-03
    title: Maintain the retention window
    level: api
    proves:
      - BR-CAP-PFM-ELG-009-03
    preconditions: Monthly partitions span October of the earlier year through December of the current year.
    steps: Run maintenance early in the current December.
    expected: 'The older October drops, November remains and two future months are prepared.'
    negative: false
    data_needs: No fixtures beyond the described setup.
    bound_to:
      - >-
        services-platform:modules/eligibility/tests/integration/db/eligibility-decisions.table.integration.spec.js#is
        in the partition registry by its date column, two months ahead and thirteen retained
      - TST-PFM-ELG-420
      - >-
        services-platform:modules/eligibility/tests/integration/db/eligibility-decisions.table.integration.spec.js#detaches
        and drops October 2025, fourteen months old
      - >-
        services-platform:modules/eligibility/tests/integration/db/eligibility-decisions.table.integration.spec.js#keeps
        November 2025, the oldest of the thirteen retained months
      - >-
        react-console:acceptance/eligibility/playwright/journeys/observability/ELIG-ACC-0669.spec.ts#ELIG-ACC-0669
      - TST-PFM-ELG-256
    provenance: test
    source: >-
      services-platform:modules/eligibility/tests/integration/db/eligibility-decisions.table.integration.spec.js#is
      in the partition registry by its date column, two months ahead and thirteen retained
    category: transition
    action_evidence:
      provenance: test
      source: >-
        services-platform:modules/eligibility/tests/integration/db/eligibility-decisions.table.integration.spec.js#is
        in the partition registry by its date column, two months ahead and thirteen retained
    assertion_evidence:
      provenance: test
      source: >-
        services-platform:modules/eligibility/tests/integration/db/eligibility-decisions.table.integration.spec.js#is
        in the partition registry by its date column, two months ahead and thirteen retained
    binding_scope: >-
      The cited tests contribute their reachable assertions; the binding does not establish
      execution or every step of this scenario.
    binding_limitations:
      - FND-PFM-ELG-074
  - id: ATS-PFM-ELG-009-04
    title: Validate decision-list requests
    level: api
    proves:
      - BR-CAP-PFM-ELG-009-05
    preconditions: A member has many retained decisions.
    steps: >-
      Omit subject and rule, request 101 entries, name an absent use and query a rule with no
      results.
    expected: >-
      Invalid filters and size fail, the absent binding returns not found and the empty rule returns
      an empty page.
    negative: true
    data_needs: No fixtures beyond the described setup.
    bound_to:
      - >-
        services-platform:modules/eligibility/tests/e2e/eligibility-evaluate.e2e.spec.js#refuses a
        list that names neither a subject nor a definition, 400
      - TST-PFM-ELG-412
      - >-
        services-platform:modules/eligibility/tests/e2e/eligibility-evaluate.e2e.spec.js#refuses a
        page of more than 100 decisions, 400
      - >-
        services-platform:modules/eligibility/tests/e2e/eligibility-governance-repairs.e2e.spec.js#answers
        404 for an unknown binding with a definition_key, not an empty page
      - TST-PFM-ELG-413
      - >-
        services-platform:modules/eligibility/tests/e2e/eligibility-governance-repairs.e2e.spec.js#still
        answers an empty page for a definition with no decisions (negative control)
      - >-
        react-console:acceptance/eligibility/playwright/journeys/evaluation/ELIG-ACC-0292.spec.ts#ELIG-ACC-0292
      - TST-PFM-ELG-148
    provenance: test
    source: >-
      services-platform:modules/eligibility/tests/e2e/eligibility-evaluate.e2e.spec.js#refuses a
      list that names neither a subject nor a definition, 400
    category: validation
    action_evidence:
      provenance: test
      source: >-
        services-platform:modules/eligibility/tests/e2e/eligibility-evaluate.e2e.spec.js#refuses a
        list that names neither a subject nor a definition, 400
    assertion_evidence:
      provenance: test
      source: >-
        services-platform:modules/eligibility/tests/e2e/eligibility-evaluate.e2e.spec.js#refuses a
        list that names neither a subject nor a definition, 400
    binding_scope: >-
      The cited tests contribute their reachable assertions; the binding does not establish
      execution or every step of this scenario.
    binding_limitations:
      - FND-PFM-ELG-074
  - id: ATS-PFM-ELG-009-05
    title: Conceal other-workspace history
    level: api
    proves:
      - BR-CAP-PFM-ELG-009-06
      - INV-DOM-PFM-ELG-003-03
    preconditions: A separate chapter owns a decision.
    steps: Open it from the current workspace.
    expected: The lookup returns not found.
    negative: true
    data_needs: No fixtures beyond the described setup.
    bound_to:
      - >-
        services-platform:modules/eligibility/tests/e2e/eligibility-evaluate.e2e.spec.js#answers 404
        for a decision the tenant does not have
      - TST-PFM-ELG-412
      - >-
        services-platform:modules/eligibility/tests/integration/db/eligibility-decisions.table.integration.spec.js#answers
        another tenant’s decision to a statement that names no tenant, which is why every read of
        the service names one
      - TST-PFM-ELG-420
      - >-
        react-console:acceptance/eligibility/playwright/journeys/evaluation/ELIG-ACC-0293.spec.ts#ELIG-ACC-0293
      - TST-PFM-ELG-149
    provenance: test
    source: >-
      services-platform:modules/eligibility/tests/e2e/eligibility-evaluate.e2e.spec.js#answers 404
      for a decision the tenant does not have
    category: boundary
    action_evidence:
      provenance: test
      source: >-
        services-platform:modules/eligibility/tests/e2e/eligibility-evaluate.e2e.spec.js#answers 404
        for a decision the tenant does not have
    assertion_evidence:
      provenance: test
      source: >-
        services-platform:modules/eligibility/tests/e2e/eligibility-evaluate.e2e.spec.js#answers 404
        for a decision the tenant does not have
    binding_scope: >-
      The cited tests contribute their reachable assertions; the binding does not establish
      execution or every step of this scenario.
    binding_limitations:
      - FND-PFM-ELG-074
  - id: ATS-PFM-ELG-009-06
    title: Restrict workspace decision purge
    level: api
    proves:
      - BR-CAP-PFM-ELG-009-08
    preconditions: One workspace is deleting and another remains live.
    steps: Purge both using the restricted function.
    expected: >-
      The deleting workspace loses decisions first, while the live workspace is rejected with its
      history intact.
    negative: false
    data_needs: No fixtures beyond the described setup.
    bound_to:
      - >-
        services-platform:modules/eligibility/tests/integration/services/maintenance/tenant-participant.integration.spec.js#removes
        the decisions first, through the definer function, one batch a call
      - TST-PFM-ELG-437
      - >-
        services-platform:modules/eligibility/tests/integration/services/maintenance/tenant-participant.integration.spec.js#is
        refused by the database, so the purger is never a delete-by-tenant tool
      - >-
        services-platform:modules/eligibility/tests/integration/services/maintenance/tenant-participant.integration.spec.js#leaves
        every decision standing
    provenance: test
    source: >-
      services-platform:modules/eligibility/tests/integration/services/maintenance/tenant-participant.integration.spec.js#removes
      the decisions first, through the definer function, one batch a call
    category: permission
    action_evidence:
      provenance: test
      source: >-
        services-platform:modules/eligibility/tests/integration/services/maintenance/tenant-participant.integration.spec.js#removes
        the decisions first, through the definer function, one batch a call
    assertion_evidence:
      provenance: test
      source: >-
        services-platform:modules/eligibility/tests/integration/services/maintenance/tenant-participant.integration.spec.js#removes
        the decisions first, through the definer function, one batch a call
    binding_scope: >-
      The cited tests contribute their reachable assertions; the binding does not establish
      execution or every step of this scenario.
    binding_limitations:
      - FND-PFM-ELG-074
  - id: ATS-PFM-ELG-009-07
    title: Place decision identities in their evaluation month
    level: api
    proves:
      - BR-CAP-PFM-ELG-009-04
      - INV-DOM-PFM-ELG-003-02
    preconditions: A decision is evaluated on each side of a calendar-month boundary.
    steps: Create the decision identity and persist both decisions.
    expected: >-
      Identities use their evaluation instants and each decision reaches its corresponding month
      partition.
    negative: false
    data_needs: Existing evidence fixtures provide the described setup.
    bound_to:
      - >-
        services-platform:modules/eligibility/tests/integration/services/persistence/decisions.integration.spec.js#answers
        the decision with a UUIDv7 minted at the evaluation’s instant
      - TST-PFM-ELG-448
      - >-
        services-platform:modules/eligibility/tests/integration/services/persistence/decisions.integration.spec.js#records
        the month of the evaluation as the partition key
      - >-
        services-platform:modules/eligibility/tests/integration/services/persistence/decisions.integration.spec.js#routes
        the last second of October into October’s partition
      - >-
        services-platform:modules/eligibility/tests/integration/services/persistence/decisions.integration.spec.js#routes
        the first second of November into November’s partition
    provenance: test
    source: >-
      services-platform:modules/eligibility/tests/integration/services/persistence/decisions.integration.spec.js#answers
      the decision with a UUIDv7 minted at the evaluation’s instant
    category: invariant
    action_evidence:
      provenance: test
      source: >-
        services-platform:modules/eligibility/tests/integration/services/persistence/decisions.integration.spec.js#answers
        the decision with a UUIDv7 minted at the evaluation’s instant
    assertion_evidence:
      provenance: test
      source: >-
        services-platform:modules/eligibility/tests/integration/services/persistence/decisions.integration.spec.js#answers
        the decision with a UUIDv7 minted at the evaluation’s instant
    binding_scope: >-
      The cited tests contribute their reachable assertions; the binding does not establish
      execution or every step of this scenario.
    binding_limitations:
      - FND-PFM-ELG-074
  - id: ATS-PFM-ELG-009-08
    title: Find retained history from a rule
    category: interaction
    level: api
    proves:
      - BR-CAP-PFM-ELG-002-01
      - BR-CAP-PFM-ELG-009-06
    exercises:
      - CAP-PFM-ELG-009
      - CAP-PFM-ELG-002
    preconditions: A rule has retained bound decisions and read authority is available.
    steps: >-
      Open the rule, request its newest decision page and inspect one decision; repeat in another
      workspace.
    expected: >-
      The rule reader sees the matching decision details locally and receives no history through the
      other workspace.
    negative: false
    data_needs: Run-owned records and a controlled clock where timing changes the result.
    bound_to: []
    provenance: proposed
    source: >-
      services-platform:modules/eligibility/tests/e2e/eligibility-definitions.e2e.spec.js#refuses a
      caller without platform.eligibility.read, 403;
      services-platform:modules/eligibility/tests/e2e/eligibility-evaluate.e2e.spec.js#answers 404
      for a decision the tenant does not have
    action_evidence:
      provenance: proposed
      source: >-
        services-platform:modules/eligibility/tests/e2e/eligibility-definitions.e2e.spec.js#refuses
        a caller without platform.eligibility.read, 403;
        services-platform:modules/eligibility/tests/e2e/eligibility-evaluate.e2e.spec.js#answers 404
        for a decision the tenant does not have
    assertion_evidence:
      provenance: proposed
      source: >-
        services-platform:modules/eligibility/tests/e2e/eligibility-definitions.e2e.spec.js#refuses
        a caller without platform.eligibility.read, 403;
        services-platform:modules/eligibility/tests/e2e/eligibility-evaluate.e2e.spec.js#answers 404
        for a decision the tenant does not have
    binding_scope: This sequence is proposed and has no executable proof binding.
  - id: ATS-PFM-ELG-009-09
    title: Record a consequential uncertain answer
    category: interaction
    level: api
    proves:
      - BR-CAP-PFM-ELG-008-02
      - BR-CAP-PFM-ELG-009-07
    exercises:
      - CAP-PFM-ELG-009
      - CAP-PFM-ELG-008
    preconditions: A bound authorization request has a missing workspace subject.
    steps: >-
      Evaluate under closed policy and inspect the returned decision and history before completing
      the caller operation.
    expected: >-
      The returned decision can be read immediately with its uncertain state, denial outcome and
      subject reason.
    negative: false
    data_needs: Run-owned records and a controlled clock where timing changes the result.
    bound_to: []
    provenance: proposed
    source: >-
      services-platform:modules/eligibility/tests/integration/services/evaluate/hosted-evaluate.integration.spec.js#answers
      a contact no row of the tenant has indeterminate, subject_not_found, ineligible under the
      closed policy;
      services-platform:modules/eligibility/tests/integration/services/evaluate/hosted-evaluate.integration.spec.js#records
      a display decision after answering it, at a sample rate of one
    action_evidence:
      provenance: proposed
      source: >-
        services-platform:modules/eligibility/tests/integration/services/evaluate/hosted-evaluate.integration.spec.js#answers
        a contact no row of the tenant has indeterminate, subject_not_found, ineligible under the
        closed policy;
        services-platform:modules/eligibility/tests/integration/services/evaluate/hosted-evaluate.integration.spec.js#records
        a display decision after answering it, at a sample rate of one
    assertion_evidence:
      provenance: proposed
      source: >-
        services-platform:modules/eligibility/tests/integration/services/evaluate/hosted-evaluate.integration.spec.js#answers
        a contact no row of the tenant has indeterminate, subject_not_found, ineligible under the
        closed policy;
        services-platform:modules/eligibility/tests/integration/services/evaluate/hosted-evaluate.integration.spec.js#records
        a display decision after answering it, at a sample rate of one
    binding_scope: This sequence is proposed and has no executable proof binding.
  - id: ATS-PFM-ELG-009-10
    title: Observe a failed history write
    category: interaction
    level: api
    proves:
      - BR-CAP-PFM-ELG-009-07
      - BR-CAP-PFM-ELG-012-05
    exercises:
      - CAP-PFM-ELG-009
      - CAP-PFM-ELG-012
    preconditions: A bound authorization evaluation can be forced to fail its decision insertion.
    steps: 'Inject the insertion failure, evaluate and inspect diagnostic output and history.'
    expected: >-
      The authorization request does not report a successful retained decision; diagnostics omit
      subject facts.
    negative: true
    data_needs: Run-owned records and a controlled clock where timing changes the result.
    bound_to: []
    provenance: proposed
    source: >-
      services-platform:modules/eligibility/tests/integration/services/evaluate/hosted-evaluate.integration.spec.js#records
      a display decision after answering it, at a sample rate of one;
      services-platform:modules/eligibility/tests/integration/services/evaluate/hosted-evaluate.integration.spec.js#logs
      one eligibility.evaluate event per evaluation with the plan and the state
    action_evidence:
      provenance: proposed
      source: >-
        services-platform:modules/eligibility/tests/integration/services/evaluate/hosted-evaluate.integration.spec.js#records
        a display decision after answering it, at a sample rate of one;
        services-platform:modules/eligibility/tests/integration/services/evaluate/hosted-evaluate.integration.spec.js#logs
        one eligibility.evaluate event per evaluation with the plan and the state
    assertion_evidence:
      provenance: proposed
      source: >-
        services-platform:modules/eligibility/tests/integration/services/evaluate/hosted-evaluate.integration.spec.js#records
        a display decision after answering it, at a sample rate of one;
        services-platform:modules/eligibility/tests/integration/services/evaluate/hosted-evaluate.integration.spec.js#logs
        one eligibility.evaluate event per evaluation with the plan and the state
    binding_scope: This sequence is proposed and has no executable proof binding.
  - title: Distinguish consequential and sampled insertion failure
    category: failure
    level: api
    proves:
      - BR-CAP-PFM-ELG-009-07
      - INV-DOM-PFM-ELG-003-04
    preconditions: An authorization request and a sample-eligible display request share a valid use.
    steps: >-
      Fail each history insertion separately, evaluate and inspect the caller response, transaction
      and diagnostic output.
    expected: >-
      Authorization does not complete with a retained decision; display can complete before its
      failed deferred insertion, whose diagnostic contains no fact payload.
    negative: true
    data_needs: 'Run-owned fixtures, separate caller contexts and a controlled clock where required.'
    bound_to: []
    provenance: proposed
    source: 'services-platform:modules/eligibility/services/evaluate/decision-recording.ts:recordDecisions'
    id: ATS-PFM-ELG-009-11
    limitations:
      - FND-PFM-ELG-052
    action_evidence:
      provenance: proposed
      source: >-
        services-platform:modules/eligibility/services/evaluate/decision-recording.ts:recordDecisions
    assertion_evidence:
      provenance: proposed
      source: >-
        services-platform:modules/eligibility/services/evaluate/decision-recording.ts:recordDecisions
    binding_scope: This sequence is proposed and has no executable proof binding.
evidence:
  - >-
    services-platform: docs/eligibility.md; docs/milestones/PLAT-M11-eligibility-rules.md,
    PLAT-M12-eligibility-who-qualifies.md, PLAT-M13-eligibility-roles-and-permissions.md,
    plans/PLAT-M11-plan.md; docs/proposals/eligibility/17-decision-register.md;
    modules/eligibility/aws/api/evaluate.routes.ts (decisions),
    services/evaluate/decision-recording.ts, decision-history.ts, services/persistence/decisions.ts,
    services/maintenance/workspace-participant.ts, db/eligibility-decisions.table.ts,
    db/partitioned-tables.ts; docs/debt/eligibility-display-decision-outbox.md; rule-level source
    and test references
  - >-
    react-console: acceptance/eligibility/journeys/evaluation/ELIG-ACC-0290, 0292, 0293;
    observability/ELIG-ACC-0668, 0669.
related_coverage:
  - capability: CAP-PFM-ELG-002
    scenario: ATS-PFM-ELG-009-08
  - capability: CAP-PFM-ELG-008
    scenario: ATS-PFM-ELG-009-09
  - capability: CAP-PFM-ELG-012
    scenario: ATS-PFM-ELG-009-10
coverage:
  rule: covered
  transition: covered
  validation: covered
  permission: 'gap: FND-PFM-ELG-061'
  edge: 'gap: FND-PFM-ELG-061'
  failure: 'gap: FND-PFM-ELG-061'
  boundary: covered
  concurrency: 'gap: FND-PFM-ELG-061'
  invariant: 'gap: FND-PFM-ELG-061'
  interaction: covered
invariant_gaps: []
transition_coverage: []
permission_coverage:
  - key: platform.eligibility.read
    finding: FND-PFM-ELG-061
    reason: A capability-level authority scenario does not prove every operation protected by this key.
coverage_notes:
  meaning: >-
    Covered means a detailed scenario exists; it does not mean the scenario ran or every executable
    assertion conforms.
  gaps: >-
    History-write ordering needs injected authorization and sampled display failures and a SQL-only
    control. Exact paging sizes, purge failure and concurrent retention reads need proof.
---

# Retain the eligibility decisions that matter: Capability Test Specification

## Coverage

The scenarios check observable outcomes against the cited contracts. The coverage map retains partial proof and unresolved design boundaries as findings.

| Required Rule | Scenarios |
|---|---|
| `BR-CAP-PFM-ELG-009-01` | `ATS-PFM-ELG-009-01` |
| `BR-CAP-PFM-ELG-009-02` | `ATS-PFM-ELG-009-02` |
| `BR-CAP-PFM-ELG-009-03` | `ATS-PFM-ELG-009-03` |
| `BR-CAP-PFM-ELG-009-04` | `ATS-PFM-ELG-009-07` |
| `BR-CAP-PFM-ELG-009-05` | `ATS-PFM-ELG-009-04` |
| `BR-CAP-PFM-ELG-009-06` | `ATS-PFM-ELG-009-05`, `ATS-PFM-ELG-009-08` |
| `BR-CAP-PFM-ELG-009-07` | `ATS-PFM-ELG-009-09`, `ATS-PFM-ELG-009-10`, `ATS-PFM-ELG-009-11` |
| `BR-CAP-PFM-ELG-009-08` | `ATS-PFM-ELG-009-06` |

## Interactions With Related Capabilities

Find retained history from a rule. Open the rule, request its newest decision page and inspect one decision; repeat in another workspace.

Record a consequential uncertain answer. Evaluate under closed policy and inspect the returned decision and history before completing the caller operation.

Observe a failed history write. Inject the insertion failure, evaluate and inspect diagnostic output and history.
