Skip to content

Decision Rules — Policy ↔ Engine Cross-Reference

Kaptl → TurnKey Lender configuration brief. Prepared 15 July 2026.

This document cross-references Kaptl's contractual credit policy (Decision Tree / Approval Logic attached to the signed Order Form, 30 June 2026 — see the Offer & Contract Summary) against the decision rules actually evaluating on the Kaptl UAT tenant (kaptl-uat.turnkey-lender.com).

Evidence base. On 15 July 2026 all 19 loans present on UAT were read via the Public API (GET /Management/Loans/{loanId}) and their RiskScoreResults.MatchedDecisionRules unioned: the engine currently evaluates 26 distinct rules. Rule identifiers below are quoted exactly as the API returns them (including the RegistraionDistance spelling).

Per the support terms, new or modified credit rules within existing scope carry 48-business-hour delivery to UAT — the request lists at the end of this page are scoped to that.


1. Policy ↔ engine mapping

Tier 1 — Fraud & lists checks (policy: reject on hit)

# Policy item Engine rule(s) on UAT Status
1.1 Multiple applications in a short period Missing — no velocity rule observed
1.2 Fake ID / photo of ID / copy of ID / stolen identity Handled in origination (ID + liveness), not the decision engine — confirm
1.3 Cross-application matching (email + phone) MainPhoneUniqueness, EqualPhones, SsnUniqueness, DriverIdUniqueness Configured — email uniqueness not evidenced, confirm
1.4 Internal blacklist BlackListCheck Configured
1.5 External blacklists Missing — no external-list rule observed
1.6 Sanctioned persons OpenSanctionsDatabaseNameDoB, OpenSanctionsDatabaseNationalId Configured

Tier 2 — Hard rules (policy: fail → reject)

# Policy item Engine rule(s) on UAT Status
2.1 Age 20+ SuspiciousAge Mismatch — the engine rule flags high age (a 90-year-old refers on UAT); the policy requires a minimum age of 20. Both bounds needed.
2.2 Bulgarian citizenship Residence Configured — confirm it checks citizenship, not only residency
2.3 Valid ID (photo / copy) + liveness test Origination flow, not the decision engine — confirm
2.4 Credit history: 0 current DPD; MaxDPD < 15 in last 12 months; no write-off / legal / other bad status per AnaCredit (ex-CCR) PastDueActiveLoans, PastDueClosedLoans, DelinquencyAmountCheckActiveAndClosedLoans, DelinquencyAmountCheckPastDueLoans, ChargeOffCheck Partial — rules exist but thresholds and the AnaCredit/BNB data source must be confirmed (AnaCredit integration is in the contracted scope)
2.5 Up to 5 active loans (max 1 from an NBFI) LoansNumber Partial — active-loan count exists; the NBFI sub-limit is not evidenced
2.6 At least 1 successfully closed loan (repeat borrowers) Missing
2.7 Minimum €1,200 official net monthly income NetIncome Threshold mismatch — UAT refers below €100; policy requires €1,200
2.8 More than 6 months with current employer Missing — expected via the NSSI Bulgaria check (contracted scope)
2.9 More than 12 months total employment in last 24 months Missing — expected via NSSI
2.10 Permanent or long-term fixed employment contract Unemployed Partial — Unemployed catches no employment; contract-type check not evidenced
2.11 Self-employed / civil contract → approval only after additional verification Missing — needs a refer-not-reject branch on income type

Tier 3 — Soft rules (policy: fail → review)

# Policy item Engine rule(s) on UAT Status
3.1 Debt-to-income < 50% PTI Configured — confirm the threshold is 50%
3.2 Free cash flow ≥ €400 / month after existing obligations (per register) Missing
3.3 Located outside Bulgaria → flagged RegistraionDistance, IpAddressLookupRule Configured — both currently refer with "Address details are not provided in the application form", so they fire on missing data rather than geography (see §2, item D)
3.4 Data mismatch → flagged Missing — no cross-field consistency rule observed

Engine rules with no policy counterpart

Evaluating on UAT but not part of the signed decision tree — confirm whether they should stay active, and at what verdict:

CreditBureauScore (refers below 660) · CreditBureauInquiries (refers above 15 in 6 months) · BankruptcyCheck (refers above 0) · SuspiciousPhoneNumber (currently refers because the suspicious-phones list is empty — see §2, item C) · ResidedAtAddressOwner / ResidedAtAddressTenant.


2. Observed configuration issues on UAT

  • A. NetIncome threshold. Live referral comment: "Net monthly income is less than 100". Policy minimum is €1,200. Please raise the threshold.
  • B. SuspiciousAge direction. Live comment: "Borrower's age is suspicious: 90" — a maximum-age check. The policy's hard rule is a minimum age of 20. Please add/confirm the lower bound (and confirm the intended upper bound, if any).
  • C. SuspiciousPhoneNumber fires on empty list. Live comment: "The rule can not be checked correctly because Suspicious phones' list is empty." Every application refers until the list is seeded or the rule is set to pass on an empty list.
  • D. Geolocation rules fire on missing data. RegistraionDistance and IpAddressLookupRule both refer with "Address details are not provided in the application form" — as does DriverIdUniqueness for the licence field. Please confirm whether missing-data referrals are intended ahead of the application-form field mapping, or whether these should pass until the field exists.
  • E. Verdict severity. All rule failures observed on UAT produce Refer (manual review). The policy's Tier 1 and Tier 2 items are reject rules. Please align verdicts per tier: fraud/lists and hard rules → Reject, soft rules → Refer.

3. Requested changes (48-business-hour scope)

  1. Set NetIncome threshold to €1,200 (item A).
  2. Add a minimum-age (20) bound; confirm SuspiciousAge upper bound (item B).
  3. Seed or disable the suspicious-phones list so SuspiciousPhoneNumber stops referring every application (item C).
  4. Align verdicts per tier — hard/fraud rules Reject, soft rules Refer (item E).
  5. Confirm PTI threshold = 50% and LoansNumber limit = 5 active.
  6. Confirm whether the credit-bureau rules (CreditBureauScore, CreditBureauInquiries, BankruptcyCheck) should remain active, and their place in the decision tree.

4. Requested confirmations / new scope

  1. Velocity rule for multiple applications in a short period (1.1).
  2. External blacklists rule and its data source (1.5).
  3. Email uniqueness in cross-application matching (1.3).
  4. AnaCredit/BNB-backed credit-history thresholds: 0 current DPD, MaxDPD < 15 in 12 months, bad-status exclusions (2.4) — contracted integration.
  5. NBFI sub-limit (max 1 of the 5 active loans) (2.5).
  6. Repeat-borrower rule — at least 1 successfully closed loan (2.6).
  7. Employment tenure rules via NSSI — > 6 months current employer,

    12 of last 24 months total (2.8, 2.9) — contracted integration.

  8. Contract-type / self-employed branch — permanent contract passes, self-employed refers for additional verification (2.10, 2.11).
  9. Free-cash-flow rule — ≥ €400/month after obligations (3.2).
  10. Data-mismatch flag (3.4).
  11. Confirm ID + liveness and fake/stolen-ID detection are enforced in the origination flow, since they are not decision-engine rules (1.2, 2.3).

Method note: engine evidence is read-only Public API output from the UAT tenant; no tenant configuration was changed in producing this document. The same cross-reference is mirrored in the Kaptl LOS prototype under Settings → Decision rules.