---
id: WF-PFM-ELG-005
title: Check eligibility inside a consumer transaction
trigger: >-
  A consumer checks qualification while preparing a database transaction, using
  either the recorded transaction evaluator or the stored SQL-only check.
product_area: platform
module: eligibility
revision: 1
status: draft
design_intent: confirmed
origin: >-
  Eligibility Engine architecture D-17 (transactional checks through an
  owner-published SQL function over the SQL-only plan, provider facts fetched
  just before and passed in) and D-15 (committed orders record the version
  used), approved 2026-10-17 (PLAT-M11 "Decisions")
implementation_evidence: partially-observed
inference: []
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
implements:
  - CAP-PFM-ELG-008
  - CAP-PFM-ELG-009
moves: []
crosses:
  - SVC-PFM-ELG-eligibility
idempotency: >-
  The recorded evaluator inserts each decision within the business transaction;
  rollback removes it. The SQL-only function inserts no decision.
concurrency: >-
  Reporting reads share the caller transaction. Provider preparation precedes
  the evaluator callback but may still occur inside an already-open caller
  transaction.
hops:
  - 'n': 1
    actor_or_service: In-transaction evaluator
    action: >-
      Prepare the binding, release and plan, and fetch required provider facts
      before the evaluator transaction callback.
    anchor: >-
      services-platform:modules/eligibility/services/evaluate/in-transaction.ts:evaluateInTransaction
    seam: sync
    on_failure: 'Missing uses, suspension or no effective release raises to the consumer.'
    left_inconsistent: No caller business commit has occurred.
    observer: The consumer handles the preparation error.
    provenance: observed
    source: >-
      services-platform:modules/eligibility/services/evaluate/in-transaction.ts:evaluateInTransaction
  - 'n': 2
    actor_or_service: In-transaction evaluator (caller's transaction)
    action: >-
      Read subjects and predicates through rolled-back savepoints, fold results,
      apply policy and insert the decision transactionally.
    anchor: >-
      services-platform:modules/eligibility/services/persistence/savepoints.ts:inRolledBackSavepoint
    seam: sync
    on_failure: >-
      Failed reads can yield uncertainty; a cold dataset description can disrupt
      the read path.
    left_inconsistent: Only the caller transaction determines the business outcome.
    observer: Read-failure metrics and consumer errors expose problems.
    provenance: observed
    source: 'services-platform:docs/debt/eligibility-check-cold-model.md'
  - 'n': 3
    actor_or_service: Transactional database function
    action: >-
      Alternatively execute a stored SQL-only plan with bound workspace,
      subjects and day under the caller’s row policy, returning state, reasons
      and trace without history insertion.
    anchor: >-
      services-platform:db/migrations/20261018010635_eligibility_check.sql:platform.eligibility_check
    seam: sync
    on_failure: >-
      Missing use, release or plan and unsupported constructs raise; the plan
      must have been stored through Platform first.
    left_inconsistent: The failing SQL statement supplies no qualification result.
    observer: The consumer receives the database refusal.
    provenance: observed
    source: >-
      services-platform:docs/eligibility.md#9.7 In a transaction, and the SQL
      function
branches:
  - >-
    The internal in-process evaluator also exists and does not record history,
    but its consumer package is unpublished.
waits: []
evidence:
  - >-
    services-platform at ad3f6a6: services/evaluate/in-transaction.ts,
    in-process.ts; services/persistence/savepoints.ts;
    db/migrations/20261018010635_eligibility_check.sql,
    20261019161958_eligibility_check_subject_existence.sql; docs/eligibility.md
    §9.6, §9.7; docs/debt/eligibility-check-cold-model.md.
controls: [TC-AVL-004, TC-AVL-005, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-CRY-001, TC-CRY-002, TC-CRY-003, TC-CRY-004, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-DAT-004, TC-IAM-001, TC-IAM-002, TC-IAM-004, TC-IAM-005, TC-LOG-002, TC-LOG-003, TC-LOG-004, TC-LOG-005, TC-MON-001, TC-PI-001, TC-PI-002, TC-PI-003, TC-PI-004, TC-PI-005, TC-PRV-001, TC-PRV-002, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-VEN-001, TC-VEN-002, TC-VEN-003]
---
# Check eligibility inside a consumer transaction

## What It Does

A consumer checks qualification while preparing a database transaction, using either the recorded transaction evaluator or the stored SQL-only check.

## The Flow

```mermaid
flowchart TD
  Choice[Consumer check] --> Recorded[Recorded transaction evaluator]
  Choice --> SQL[SQL-only database check]
  Recorded --> History[Decision inserted with caller transaction]
  SQL --> Answer[Answer returned without history]
```

Prepare the binding, release and plan, and fetch required provider facts before the evaluator transaction callback. Read subjects and predicates through rolled-back savepoints, fold results, apply policy and insert the decision transactionally. Alternatively execute a stored SQL-only plan with bound workspace, subjects and day under the caller’s row policy, returning state, reasons and trace without history insertion.

## When Something Fails

Missing uses, suspension or no effective release raises to the consumer. No caller business commit has occurred. Failed reads can yield uncertainty; a cold dataset description can disrupt the read path. Only the caller transaction determines the business outcome. Missing use, release or plan and unsupported constructs raise; the plan must have been stored through Platform first. The failing SQL statement supplies no qualification result.

## Open Design Questions

The internal in-process evaluator also exists and does not record history, but its consumer package is unpublished.
