MortgageAmortization — monthly P&I from loan terms (WS6 support)
The one PITI component not stored on the loan. Standard fully-amortizing formula P·r·(1+r)^n/((1+r)^n−1); zero rate degrades to straight-line; non-positive prin...
ClosingReadinessEvaluator — loan-level clear-to-close gate
Rolls a loan's obligations up to the funding question the end-to-end gap analysis raised ("service the loan all the way to funding"): clear-to-close iff zero ad...
QualifyingRatioEngine — the reproducible dti keystone (WS6)
Composes the four cores (income, liabilities, PITI/DTI, reserves) into ONE QualifyingSnapshot: qualifying income, reconciled monthly debt, assembled PITIA, fron...
ReservesCalculator — eligible-asset haircuts → PITIA months (WS6)
Derives reserve months from actual assets with standard agency haircuts — liquid deposits 100%, brokerage 70%, vested retirement 60%, gift/borrowed excluded — d...
PitiDtiCalculator — PITI assembly + front/back DTI (WS6)
Pure ratio core completing the DTI trio with LiabilityReconciler + the income core: PITIA = P&I + taxes + HOI + HOA + MI + flood; front = PITIA / income; back =...
QualifyingIncomeCalculator — base + variable core (WS5)
Pure/deterministic income core: base salaried = conservative lowest-of available evidence (paystub / W-2 / VOE); variable = 2-yr average with a declining-income...
LiabilityReconciler — agency payment-inclusion rules (WS6 core)
Pure/stateless computer turning each liability into the monthly payment that counts against DTI, with a cited rationale: omitted/paid-off excluded, leases alway...
Explicit-period quantity spec for delta successors
RequirementQuantity gains an explicit periods list (+ deltaJson builder); when present it IS the required set, so a successor can be scoped to "just send August...
**************** as the single period-key source
Adds periodKeyFor(date) so the write-path (satisfier stamping) and the coverage evaluator key periods identically; evaluator now delegates to it. Pure/additive,...
Period-coverage primitives for period-aware document collection
The pure, additive foundation of period-aware collection (doc 06 §4) — the first slice of the bank-statement "collect only the months I don't have yet" fix. Zer...
Persist software branding fields via patchOrganization whitelist
Add WEB_CHAT_INTEGRATION_ID attribution columns to visitor/ticket/ai-session
WebChatIntegration entity + repo + DTO + default design config
Add ALLOW_MOBILE_ACCESS (167) general right for Mobile Copilot
New RoleRightType (serviceType=null → General group) gating the 'Setup Mobile Access' interaction-center tab. RoleRightsSyncService backfills it to all roles on...
Add publicDailyMessageCap to AiOrgSettings for anon web-chat quota
Add creating-key-hash attribution columns to PublicChatVisitor + SupportTicket
Add findOrganizationOwners for per-org public-chat system member
Device-token + push-registration entities, HMAC stream-token codec
hashed secret, rotation grace, sliding expiry), push_device_registrations (one push destination per device+org+kind), and StreamTokenCodec — short-lived HMAC to...
Multi-pass closed-loan training — pass counter + corpus upsert key
The closed-loan trainer now re-reads a loan on successive passes until its extraction reproduces the loan outcome, so: - LeadLosLink.closedLoanPasses drives a p...
Status-preserving progress write for the closed-loan trainer
run is RUNNING, without touching status. An operator pause (status → PAUSED) can no longer be clobbered by a full-row save from the pool thread — the guarded up...
Harden closed-loan trainer — run lock + per-loan idempotency
- ClosedLoanTrainingRun.claim(): atomic conditional UPDATE that takes ownership of a run only when it is not already RUNNING or its heartbeat is stale (prev...
Org-scoped loan roster query for the closed-loan trainer
**************** gives the trainer every LOS-linked loan for an org+provider, each carrying the externalLoanName it reads status + documents for.
Closed-loan auto-trainer foundation (MeridianLink ground truth)
Foundation for training document extraction against funded loans (the answer key): - ClosedLoanTrainingRun entity+repo — per-org run control + live counters - E...
Plain-language borrower messages for document rejections
RejectionReasonType was a bare enum (the borrower literally saw "ILLEGIBLE"). Each value now carries a borrowerMessage() remediation string + a messageFor() map...
Platform-wide QC review (cross-tenant labeling for the shared model)
A document is a document — extraction and the model are platform-level, not per lender. Adds a cross-tenant NEEDS_REVIEW queue + QcReviewService.platformReview ...
Platform Document-AI config on SystemConfiguration + cross-org corpus
Adds **************** (default 0.85) + EXTRACTION_MODEL_ID to the platform SystemConfiguration singleton — the platform-wide levers for the QC gate and the regi...
Org-wide QC queue (employee review portal)
Adds an org-scoped NEEDS_REVIEW query + QcReviewService.orgQueue so employees can work every loan's low-confidence extractions from one portal, not one loan at ...
Confidence-gated QC box + labeled training data + gift/self-employment reconcile
QC engine (Phase 4 core): - VerifiedFact gains first-class EXTRACTION_CONFIDENCE, DOC_TYPE_CODE, QC_STATE columns (QcState: **************** Reconciliation ...
Reconcile otherIncome.* facts into OtherIncome rows
Extends fact reconciliation with an otherIncome.* branch: award/benefit documents (Social Security, pension/retirement, child support) land a real OtherIncome r...
Capture + encrypt full SSN on the borrower application
The application posture needs the borrower's REAL Social, not a last-4 (a lender can't do anything with 4 digits). Borrower.ssnEncrypted existed but was never w...
Drop message-body preview paragraph from missed-message email templates
Security: notification emails no longer render any message content; the member signs in to read messages. Sender + count + CTA only.
Missed-message email notification ledger + canonical templates
MessageEmailNotice entity (MESSAGE_EMAIL_NOTICES, unique recipient+sourceKey+channel) with PENDING/SENT suppression states, repository incl. sudo-safe markRead/...
GraphMessageIdMap entity for Microsoft 365 Graph mail id mapping
Maps opaque Microsoft Graph message ids to stable synthetic numeric UIDs per mailbox, so Graph mailboxes flow through the existing numeric-uid mail contract (co...
CitySceneProfile entity + GeoLite city-lookup indexes for city-based portal scenes
- CitySceneProfile (city_scene_profile): per-city environmental scene factors (terrain/relief/silhouette, climate/koppen, hydrology, RESOLVE ecoregion + flo...
The servlet guard must define the SERVLET bean — Boot conditions on the type, not the registration
f8bcc82's ServletRegistrationBean alone name-collided with the auto-config **************** WebServicesAutoConfiguration's bean is **************** Define the s...
Disabled MessageDispatcherServlet registration — kills the multi-servlet landmine for real
Removing the web-services STARTER (55eae0a) was not enough: spring-ws-core itself carries MessageDispatcherServlet, and Boot's WebServicesAutoConfiguration cond...
Spring-ws CLIENT-ONLY — the server starter made every consuming service multi-servlet
**************** auto-registers a MessageDispatcherServlet in EVERY service that depends on shared-lib; with Spring Security 6 that breaks any string requestMat...
LOAN_STATUS_UPDATE canonical template — borrower notified at every loan-file stage change
UpdateLoanFile PATCH must not null absent fields — status-only patch wiped loanNumber/dates
Any partial loan-file patch (the portal's submit sends only {statusId:2}) unconditionally overwrote loanNumber, channelId, and every lifecycle date with null. G...
RESUME_PORTAL_LINK canonical template — borrower magic-link to continue on any device
Bound IP block lookup to a single indexed row
findByIpInRange's two-sided range predicate forced CockroachDB to scan every block with networkStart <= ip whenever the IP fell in a gap (private/bogon/ spoofed...
MortgageProviderResolver deps → ObjectProvider — was crash-looping MediaService
The @Service is component-scanned by every com.kamo service, but mlos.config repositories only exist where @EnableJpaRepositories registers them. Hard construct...
MEET_YOUR_LO canonical template — borrower intro when an LO accepts their lead
CreateFromLead saved Declarations against a transient Borrower — save the app graph first
Same latent TransientPropertyValueException the blank create() fixed at its first caller; createFromLead's first real caller is the portal promote seam (caught ...
AccountGuid insert always violated FIRST_SEEN_AT NOT NULL — ZERO portal leads ever created
Hibernate includes every mapped column in INSERT (no @DynamicInsert), so the unset timestamp went out as explicit NULL and the DB default never applied. Every v...
The doc-04 vendor RUNTIME — MortgageProviderResolver + VendorTypeBridge
The integrations tab wrote MortgageProviderConfig rows nothing consumed at runtime. Resolver: (org, VendorCategory) → activation-gated, profile-scoped, first-en...
Real verified-fact reconciliation — evidence facts now populate the URLA
Replaces the M3a log-only stub: asset.* facts (grouped per source document) become Asset rows and employment.* facts become Employment rows via BorrowerSectionS...
Like what you see shipping?
Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.