Execution-time checks
Re-evaluate volatile controls at send, dial, submit, or post time so immediate and queued work cannot act on stale permission.
Execution answers “may this exact action run now?” The current owning operation asks that question internally. Scheduled voice work also has a dispatch gate and a dispatch-bound dial-authorization check because facts can change while it waits.
What can change
In the seconds or days between planning and execution:
- the customer revokes consent or asks you to stop;
- a bankruptcy, representation, dispute, fraud, or vulnerability signal arrives;
- another worker uses the remaining contact capacity;
- a payment posts, returns, or moves in flight;
- a loan, schedule, restriction, instrument, or case version changes;
- the customer’s local time crosses a configured boundary;
- a product or rule version reaches its effective time;
- an approver rejects or the approval expires.
An earlier allowed result cannot authorize around any of those changes.
The preview and execution pattern (roadmap)
Interaction example
curl -X POST "$BASE/v1/servicing/calls/outbound" \
-H "Authorization: Bearer $TOKEN" \
-H "LendEasy-Tenant: demo-lender" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: hbr-call-attempt-2027-05-01-1" \
-d '{
"caseId": 1001,
"customerRef": "412",
"loanRef": "7204",
"contactPointRef": "cp_MAYA_MOBILE_1",
"reasonCode": "COLLECTIONS_FOLLOW_UP"
}'
The dial API does not accept or trust a caller-provided allowed flag. It creates the interaction evidence first, resolves the latest contact facts, makes the execution decision, and only then invokes the telephony gateway — the response is always 201 with the persisted attempt, whose status is DIALING, BLOCKED, or FAILED with the compliance decisionId. A future-dated contact is booked as a scheduled callback on the case, and its start-call command runs this same gate again at dial time; there is deliberately no scheduled email or SMS send to drift stale.
Atomicity boundary
To avoid a check-then-act race, the executor binds:
- normalized action payload hash;
- customer, loan, case, instrument, schedule, and restriction versions used;
- policy bundle and rule versions;
- decision ID and expiry;
- idempotency key and attempt number;
- provider request or authoritative action reference.
If a bound version changes before commit, execution fails with a conflict or new decision—not a stale side effect.
Blocked attempts are evidence
A blocked attempt is not a sent interaction and should not count as provider delivery. It still records the intended action, pre-check, current blocking fact, rules, time, actor, and safe next step. This proves the control prevented execution.
Population actions
A mass action fans out into individually governed actions. Each customer receives a fresh evaluation at their execution time. One customer can be allowed, one blocked, one missing facts, and one already resolved; the aggregate result preserves every branch.