Dealer Finance: auditable stock loans for vehicle dealers
A loan engine with approval at both the dealer and the bank, fees computed to the Kenya Finance Act, and security you can prove with tests.
The problem
Dealers need short-term capital to order vehicles before they've sold them. The bank needs to know each loan went to the manufacturer and nowhere else.
The existing process was manual and slow. The bank needed structured credit facilities, approval at two levels, automatic overdue handling and a clean audit trail for every lending decision.
Architecture
Nine services behind Spring Cloud Gateway with central token validation; services trust each other via signed API keys. A shared audit library runs in every service and publishes to the database or Kafka.
What I built
- 01Three-step approval without over-lendingA dealer maker requests, a dealer checker approves, and the bank's credit team gives final approval. Available credit counts every loan still in the pipeline, so concurrent requests can't over-commit a facility.
- 02Tax-compliant fees and overdue handlingFees matched to the repayment tenure, with interest, excise duty, VAT and remittance charges. A daily scheduler applies grace periods, a one-time penalty and daily past-due interest, capped at the principal as the law requires.
- 03Fine-grained authorizationKeycloak UMA permissions with data scopes for borrower, buyer and lender views. An ownership guard on every query prevents users reading each other's data (IDOR) and blocks privilege escalation, and caller-supplied filters are silently replaced by the caller's scope.
- 04An audit library every service sharesOne annotation audits an action. Every event carries correlation and trace IDs, personal data is stripped from failure messages, every allowed or denied permission check is recorded, and audit writes commit even if the business transaction rolls back.
- 05Security proven by testsTests assert that a denied permission returns 403 and the underlying service is never called, that scopes override user input, and that no combination of token claims grants extra access. Refresh tokens are stored hashed and compared in constant time.
- 06Automated deliveryA seven-stage Jenkins pipeline builds only the services that changed, versions and pushes images, and deploys with Ansible to on-premises servers. Secrets never enter the repository.
Outcome
Delivered production-ready to the bank; currently pre-deployment.
Bulk repayment via Excel upload, two-phase bank statement reconciliation, and notifications by email, SMS and push.