The Fees That Priced People Out — Python Bug Hunt
Modelled on Wells Fargo, 2018: the bank disclosed that a calculation error in the tool it used to decide whether mortgage customers qualified for a loan…
- Language: Python
- Layer: Backend
- Difficulty: Medium
- Concepts: Money, Validation
- Modelled on: Wells Fargo · 2018
- Visible tests: a file with no fees and ample income qualifies; attorney fees do not push an affordable file over the ceiling
- Reward: 50 XP for a complete fix
Briefing
Modelled on Wells Fargo, 2018: the bank disclosed that a calculation error in the tool it used to decide whether mortgage customers qualified for a loan modification had included attorneys' fees incorrectly. Hundreds of customers who should have qualified were denied or not offered a modification, and many of them later lost their homes to foreclosure.
This reconstruction re-amortises a delinquent loan and checks the new payment against an affordability ceiling. The fees end up in the wrong place in that calculation.
Fix evaluate so the eligibility decision follows the policy below.
Bug report
BUG-MOD-FEES · Priority: Critical · Reported by: mortgage operations audit
evaluate(app) — all amounts in integer cents. app has principal, arrears, attorney_fees, monthly_income. Returns, in this shape: { "eligible", "balance", "payment", "fees_due" }
- balance: the modified (capitalised) balance = principal + arrears. Attorney fees are NOT capitalised into the re-amortised loan; they are reported separately as fees_due (= attorney_fees).
- payment: policy.monthly_payment(balance, policy.RATE_BPS, policy.TERM_MONTHS)
- eligible: payment <= policy.max_payment(monthly_income) (a payment exactly at the ceiling qualifies)
Observed: applicants whose payment fits the ceiling are denied as soon as their file carries any attorney fees.
Logs
[underwriting] app=M-20417 balance=21900000 payment=66318 ceiling=65100 -> DENIED
[underwriting] app=M-20417 manual review: payment without fees would be 65100The code as shipped
src/mortgage/underwriting.py (editable)
policy = bug_require("./policy.py")
def evaluate(app):
balance = app["principal"] + app["arrears"] + app["attorney_fees"]
payment = policy.monthly_payment(balance, policy.RATE_BPS, policy.TERM_MONTHS)
return {
"eligible": payment <= policy.max_payment(app["monthly_income"]),
"balance": balance,
"payment": payment,
"fees_due": app["attorney_fees"],
}
Read-only context: src/mortgage/policy.py.
Open the hunt to edit the files, run the visible tests and submit against the hidden ones. More Python bug hunts.