Weld the LO chain — portal leads enter the accept-lead pool; accepted LO survives conversion
(1) PortalLeadService routes a portal lead into the credit-based assignment pool (requiresAssignment=true) the moment it has a contact point — portal leads were...
Live header KPIs from the draft; sellerCredits in cash-to-close; nav guard only when actually dirty
Keep form + What-If as one grid cell so the outputs panel stays in the right column
The What-If move made MortgageFieldsComponent render Card + whatIfSlot as sibling children; since MortgageDetailsTab lays out its children in a 2-col grid, What...
Restore two-column outputs layout (Rate above Insights in the left column)
Prior reorder pushed Rate/Insights into the right column, collapsing the balance onto one side. Keep the short summary cards in the LEFT column (Rate directly a...
Drop response-only enum string mirrors from mortgage save payload
The lead update was 400ing — UpdateLeadRequest rejects unknown fields and the form round-tripped LeadDTO's **************** strings (which only exist on the res...
Clear core-card edit on nav + guard communications composer draft
Discard the open core-card edit (release its pane lock) when the user proceeds past the unsaved-changes confirm in setTab/guardedNavigate, so editingCard no lon...
Surface recommended (yellow) fields even before a loan purpose is set
The blank-lead fallback returned only the required set, so a purpose-less lead showed red markers but never yellow. Now **************** are flagged as recommen...
Drop poller link write so server-owned contentHash isn't clobbered; collision-safe poll-unit key
ApplyLosPatch owns lastPulledAt (stamp on no-op too); single link writer
Checkbox selection no longer reloads the grid
Selecting a row checkbox called setSelectedIds(new Set(...)), which was listed in loadLeads' useCallback deps. That gave loadLeads a new identity on every click...
Align losConnectionApi.remove return type
The DELETE endpoint returns {deleted:true, marketId}, not just {deleted:boolean} — align the client type to match the backend shape.
Real soft-delete + reactivate-on-upsert for LOS connection; safe test-connection message
I1: view()/testConnection() now read via the shared-lib's active-filtered finder so a soft-deleted (market,provider) connection reads as "not configured" instea...
Fail closed on blank MeridianLink Save status + OKWithWarning test
Send X-***-Token on the upload XHR (fixes all uploads failing)
The session moved from a cookie to per-tab sessionStorage (896ea516); window.fetch is monkey-patched to attach X-***-Token to /api/* calls, but the raw XMLHttpR...
Promote base mortgage-market leads to LeadClaimMortgage on save so mortgage fields persist
A lead whose market sub-type is (residential/commercial) mortgage was stored as a base Lead unless the backend salesType itself equaled the mortgage type, so up...
Header KPIs show reliably (relax gate + wrap header row); swap output columns, **************** on left
Cap concurrent uploads (queue, max 3)
Multi-file upload fired every selected file at once, and the burst of concurrent server-side resizes OOM'd the image service. Queue the uploads and run at most ...
Bound concurrent ffmpeg to prevent OOM under upload bursts
A multi-file upload fires all files at once; each ffmpeg decode allocates the full uncompressed frame, so N concurrent large images blew past the pod's memory l...
Downscale-only (never upscale small images)
**************** scaled small images UP to fill the box (800x600 -> 1440x1080). Compute a concrete downscale factor capped at 1.0 from the probed dimensions ins...
Harden ffmpeg resize (probe safety, dim caps, bomb guard)
Adversarial-review follow-ups on the ffmpeg rewrite: - probeDimensions redirects ffprobe output to a file and calls waitFor() FIRST (destroyForcibly on timeou...
Fail the upload if resize fails (no full-size fallback)
Reverts the store-original fallback: if ConversionService cannot resize the image, return 422 instead of storing the full-size original (a huge image would then...
Resize backgrounds via ffmpeg subprocess (crash-isolated)
ImageIO + webp-imageio could native-crash the JVM (SIGSEGV in libwebp-imageio, UpsampleBgraLinePair_SSE2) on certain WebP inputs, taking the whole ConversionSer...
Fall back to the original image when resize fails
ConversionService can native-crash (libwebp-imageio SIGSEGV) or be unavailable, which made every member wallpaper upload fail ("Failed to process image" -> 500)...
Coerce deriveRelevance purpose to LoanPurpose | null
scenarioFromLeadFields' loanPurpose is LoanPurpose | null | undefined, but Relevance.purpose is LoanPurpose | null — the possible undefined failed the prod type...
Stop duplicating the memberId query in the GET proxy
The GET list proxy hand-appended ?memberId= to the apiPath, but forwardToApi already re-appends the browser's query string — producing ?memberId=X?memberId=X, w...
Center calendar watermark to container; move selector under logos
- BackgroundWatermark: make ThemeLogo a direct flex child of the container-filling box so sizePercent (e.g. /calendar 60%) is relative to the positioned con...
Keep manager open on upload/select; uploads join the slideshow
Members reported the background manager closing after every upload and every select, only one image appearing on the home slideshow, and the "use own" choice re...
Repair per-tab *** migration gaps in directory + timeout popup
The *** session moved from a shared cookie to a per-tab sessionStorage carrier (X-***-Token). A few consumers were never updated to match. - Interaction Center...
Show the "Manage Background Images" button so members can upload
The Background & Theme section used BackgroundManager under external open-control but nothing ever opened it, so the upload/select dialog was unreachable — you ...
Stop serializing computed xoauth2 getter that broke MailCredentials Redis cache
MailCredentials is cached in Redis (GenericJackson2Json). The added `isXoauth2()` boolean getter was serialized as a "xoauth2" property but has no field to read...
Scope by org server-side (empty assocObjectId) — folders/list no longer empty
Keying materials on the org-id string was fragile: the id loses precision through a JS number on the write path and resolves inconsistently across proxy→APIServ...
Folders/list empty (org-id precision) + default visibility Team-Members-Only + custom labels
Root cause: materials store assocObjectId as the org id, which round-trips through a JS number on the write path (precision loss >2^53), so reads with the preci...
Stop external-images banner flashing on already-allowed messages
The reading pane renders a message from its IndexedDB cache before the network fetch returns, and the cached copy lacks the server remoteImagesAllowed flag (und...
Folder create/rename 500 on root folders (Map.of null value)
createFolder/renameFolder built the response with Map.of(..."parentId", parentId), which throws NullPointerException when parentId is null (a root folder) — the...
Masonry layout so mixed-height option cards pack without ragged gaps
Leaf cards are short and parent cards vary with their sub-item count (Calculator has 9 modes, VoIP 2), so a uniform grid left big gaps under the short cards in ...
Add missing account-assign proxy route
The lead-account assign/unassign UI called POST/DELETE **************** but the Next.js proxy route was never created — so requests 404'd and surfaced as "Unkno...
Robust vision provider/model selection across vendors
Two-pass selectVisionProvider: prefer any org provider that has an active vision-capable model adapter already emits image_url content and reports supportsVisio...
Persist "display external images" server-side instead of localStorage
The choice now comes from the message's server-recorded remoteImagesAllowed flag and is saved via POST **************** so it's durable and consistent across de...
Parent options expose their sub-items instead of being single links
Mail, Docs, VoIP, Calculator and Support are nav options that open a sub-menu rather than navigating, so on the home launchpad they must not be a single link. E...
Persist OAuth provider selection immediately so the switch sticks
Selecting Microsoft 365 / Google Workspace / Zoho only navigated to the connect screen without saving, so leaving before completing OAuth reverted to the previo...
Scope KamoMail mailbox/domain listing to the org's own domains (cross-tenant leak)
SECURITY: **************** ran 'SELECT email FROM virtual_users' (and **************** 'SELECT name FROM virtual_domains') with no org scoping, so mailbox/domai...
Remember "display external images" per message
The unblock choice lived in the renderer's local state, but switching messages unmounts/remounts the iframe renderer (the reading pane shows a loader between me...
Treat ACTIVE status as connected in OAuth provider configs
The Microsoft 365 / Google Workspace / Zoho config views gated their connected state on providerStatus === 'CONNECTED', but the backend EmailProviderStatus enum...
Persist selected OAuth provider on callback so it stops reverting to KamoMail
Switching an org to Microsoft 365 (or Google Workspace / Zoho) never stuck: the OAuth callback stored tokens and only flipped status on a pre-existing provider ...
Resolve welcome-email logo from the org theme host, not the apex
Header/footer logos in system emails (welcome/verification) were built as **************** — an apex path that only exists on the Kamo marketing site, so for cu...
Like what you see shipping?
Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.