A bad assocType index is a 400, not a 500
The upload/register paths indexed ImageAssocType.values() with the client's raw index, so an out-of-range value surfaced as an ArrayIndexOutOfBoundsException (5...
Filter non-ACTIVE members from live-participant pickers
Defense-in-depth behind the SecurityService gates: never render a non-ACTIVE team member as a selectable/live participant. Add teamMembershipStatus to the membe...
Exclude non-ACTIVE members from chat participation & routing
A non-ACTIVE **************** member must not appear as, or be targeted as, a live chat participant. Gate every chat path on the shared-lib **************** pre...
Enforce ACTIVE member status on every session & off-boarding path
The ACTIVE-member login gate previously lived only in the password-login controller. Extend it to every session-minting path via the shared-lib ****************...
Gate live sessions & participation on ACTIVE member status
Add **************** as the single source of truth for the "only ACTIVE members may sign in or appear as a live participant" invariant: base members must be rec...
Load history images via query, not lazy getImages() (WS path)
**************** runs on the WebSocket path (called from AiChatWebSocketHandler), which is NOT an HTTP request, so open-session-in-view does not apply. Iteratin...
Rate-lock commit gate + cross-org loan resolution + borrower vendor-order projection
Verified defects from the session review: - CRITICAL: commitLock hardcoded **************** which the RCE commit engine rejects with a 400 (only LOCK_ELIGIBLE...
Mirror native e-sign completion to the disclosure stub + fix sent status
(1) BorrowerSignatureService now mirrors a terminal native envelope status back onto the locked disclosure stub (doc 05 §4.2 map) on the borrower's my-signature...
**************** (was findById)
VendorOrder extends BaseUuidEntity (key = uid, not id); the derived-query parse failed at boot ("No property 'id' for VendorOrder"), crash-looping MLOSVendorSer...
Revive soft-deleted member pref on upsert instead of 500
Per-member UI preferences (nav layout, hex-head sizes, etc.) are stored one row per (member_id, pref_key) in MEMBER_UI_PREFERENCES, guarded by the unique constr...
Allow SWITCH_MODEL to reset a session to Auto
handleSwitchModel always UUID-parsed modelId and errored on null, so a session could never be reverted to automatic model selection mid-chat. Parse modelId as a...
Explicit priority so the OTA updates route wins over the general theme route
Traefik ranks by rule-string length; the general /public/ theme route is longer, so the expo-updates header injection never ran. priority:100000 forces the win.
Accept X-***-Token header on my-networks + all-networks
getMyNetworks/getAllNetworks only read the OTK request-attr or the *** cookie, — no org beyond the device-exchanged primary ever loaded, and the active org had ...
Make WebChatIntegration create() @Transactional (no orphaned key on integration-save failure)
Tightly-cropped Copilot icon + bare NavPri entry
Added a trimmed icon.png (glyph fills ~82% of the frame) and pointed the home pill, NavPri entry, Interaction Center tab, and QR center at it. Stripped the NavP...
Defer mandatory-origin to Phase 1 — OriginMatcher opt-in (empty allow-list / missing Origin allowed)
Phase-0 widgets still call via their server-side proxy, so origin-locking has no benefit yet and every live public-chat key has an empty allow-list. Strict enfo...
Don't cache-invalidate keys on transient downstream errors (only on definitive invalid)
Only cache-invalidate genuinely-invalid keys, not origin-denied (prevents valid-key DoS)
On a cold Redis cache, a valid public-chat key with a wrong/absent Origin was cached as INVALID for 60s, denying the correct origin's requests for that window. ...
Bind WS relay handshake to Origin + add cold-cache key validation fallback
Extracts PublicChatController's private validateViaDownstream() into a shared PublicChatKeyResolver bean so PublicChatWebSocketHandler can reuse the same downst...
Make public-chat origin allow-list mandatory (deny on missing Origin / empty list)
Resolve public-chat system member per-org (drop hardcoded snadjafinia alias)
createSupportSession, createPublicTicket, and the owner notification helpers all resolved the org's "system member" via a hardcoded usernameAlias="snadjafinia" ...
Trainer must not clobber its own claim or an operator's pause
After the atomic claim() bulk-updates the row to RUNNING, mirror that in the in-memory entity — the pool thread has no open session, so a later full-row save wo...
Raise guacamole memory 1Gi→2Gi to stop OOM mid-RDP-session
The Tomcat webapp idles near ~800Mi, so a 1Gi ceiling left almost no headroom. Opening an RDP session pushed RSS over 1Gi and the container was OOMKilled (exit ...
Load history via per-tab OTK path + retry/error UI; drop preview toggle
- Root cause of empty chat history on long-lived tabs: media proxy routes forwarded only the *** cookie (lapses ~30min) instead of the per-tab X-***-Token; ...
Stop putting message content into missed-message emails
Remove messagePreview computation, the ledger PREVIEW write, and the messagePreview template variable; drop the includePreview preference. Emails now carry send...
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.
Raise memory 1Gi→2Gi; pod idled at ~900Mi and OOM-killed during background uploads
Crystalline/metamorphic basement classifies correctly (was VOLCANIC)
Macrostrat 'metamorphic and undivided crystalline (...may include volcanic...)' tripped the volcan substring; check metamorphic/crystalline before volcanic. Als...
Ridge petrology search to 25km, no relief gate
The gazetteer point often sits in the valley floor with the range 15-20km off; the 15km search + relief gate missed them (Yucca Valley returned alluvium despite...
Petrology reads the ridge bedrock, not the valley floor
A town centroid usually sits on valley ALLUVIUM while the mountains the scene draws are bedrock — so a granite-ringed desert town returned 'alluvium' and got no...
Register mlos.notification JPA repos so SecurityService starts
EconsentService autowires DisclosureTextRepository **************** but that package was absent from @EnableJpaRepositories — the context failed to start, Crash...
Prepare-signin authenticates on api.<root> — the auth path can't resolve the myloan.* alias
Same constraint as in-cluster login: provider resolution keys on the canonical api host, not the portal alias, so a correct password still 401'd.
AntPathRequestMatcher — immune to multi-servlet contexts
Belt-and-braces with the shared-lib SoapClientOnlyGuard (c4a3b2c): the 891c58c build raced the guard's push into shared-lib main and kept crash-looping on 'more...
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...
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...
Never render literal "null" in lead view header name
The header and headerName memo built the contact name with template literals, so a NULL middle/last name stringified to the word "null" (e.g. "Sage null"). Buil...
Guard /internal/voip with InternalAuthFilter as documented — it 401'd on session auth
VoipInternalSyncController always documented InternalAuthFilter as its guard, but /internal/voip was never in PROTECTED_PREFIXES nor excluded from the OTK sessi...
VoipGlobalSyncJob stamps the MLOS internal-auth secret VOIP actually validates
After the hostname fix the job 401'd: VOIP's InternalAuthFilter checks the mlos-internal-auth value, but the job read internal.auth.secret, which in DaemonServi...
VoipGlobalSyncJob targeted a nonexistent host — kamovoip-service, not voip-service
Every minute the job failed DNS on **************** the actual Service (and what StewardNotifier already uses) is kamovoip-service. Fixed the configmap default ...
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...
Re-parent geolite config under daemon: so the weekly sync actually runs
Commit 53eed7b re-parented the geolite block under internal: while the code reads daemon.geolite.* — with SPRING_CONFIG_LOCATION replacing classpath defaults, G...
Boot crash — Ant matchers for the multi-servlet context (spring-ws /services/*)
MVC-implicit string requestMatchers are rejected by Spring Security 6 once the MeridianLink integration's MessageDispatcherServlet joins the DispatcherServlet —...
Preferred name fills AKA+first; pool entry publishes the realtime lead event
(1) The funnel's preferred name now writes nameFirstAKA AND stands in for nameFirst until the legal name arrives (owner rule) — it was landing on first name onl...
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...
Reply-all no longer CCs yourself; blank lines survive send
Reply All excluded only activeMailbox.emailAddress, which is unset on the default personal mailbox view — so your own address (from the original To:) landed in ...
Like what you see shipping?
Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.