Source home from the nav registry, add nav cross-highlight, fix settings scroll
The home page was rendering a stale, separately-maintained feature list (Clubhouse, Feed, Reports, Tasks, Network) that isn't even in the nav registry, so it ex...
Rename Material ID field title to 'Marketing Material ID'; drop help tip
Point-in-time resolvers include SUPERSEDED windows (historical effective-resolution)
All three effective-version resolvers (rate-sheet, guideline, lock-policy) queried only status=ACTIVE, then window-filtered. But supersession flips the prior ve...
Bounds-check assoc-type ordinal lookups (fixes Materials list 500)
DocsService was running a shared-lib built before ImageAssocType.MATERIALS (ordinal 11) was added, so listDocuments' ImageAssocType.values()[11] threw ArrayInde...
Move data dir off MinIO FUSE mount to local disk
rspamd's /var/lib/rspamd was hostPath-backed by the rclone FUSE mount of the MinIO shared-files bucket. Every hyperscan recompile / map refresh rewrote files th...
Persist scheduled-material thumb flags via targeted update
Same detached-entity orphanRemoval issue as the conversion pipeline: the headless sweep held a detached ImgDat and save()/merge() cascaded into the images colle...
Persist thumb flags via targeted update, not detached save
The image/video/PDF thumbnail steps set thumb flags on a detached ImgDat and called save(), which merges and cascades into the orphanRemoval images collection —...
Reject negative income / asset / liability amounts on section saves
Extends the requireNonNegative guard (already on loan amount + property values) to the core DTI/asset inputs in BorrowerSectionService: employment income ******...
Stop uploads hanging on 'Converting...' — route NATS progress + direct image thumbnails
The conversion-progress publish used NatsMessageService.publish(), which asserts expectedStream=<this service's stream>. The subject **************** resolves t...
Add Marketing to the security-model app editor
The model editor's app list (SERVICE_TYPES) is a hand-maintained mirror of ServiceType.java and was missing MARKETING — so Marketing had no row in the apps tab,...
Constant-time internal-auth secret compare (timing oracle)
Replace String.equals with MessageDigest.isEqual so response latency cannot leak the X-Internal-Auth shared secret byte-by-byte. Fleet-wide sweep of the copy-pa...
Constant-time internal-auth secret compare (timing oracle)
Replace String.equals with MessageDigest.isEqual so response latency cannot leak the X-Internal-Auth shared secret byte-by-byte. Fleet-wide sweep of the copy-pa...
Constant-time internal-auth secret compare (timing oracle)
Replace String.equals with MessageDigest.isEqual so response latency cannot leak the X-Internal-Auth shared secret byte-by-byte. Fleet-wide sweep of the copy-pa...
Constant-time internal-auth secret compare (timing oracle)
Replace String.equals with MessageDigest.isEqual so response latency cannot leak the X-Internal-Auth shared secret byte-by-byte. Fleet-wide sweep of the copy-pa...
/dev/shm 2Gi (headless Chrome needs >=2GB) + 6Gi mem limit
Jibri's 10-config init aborts with '/dev/shm must be at least 2GB' when shm is 512Mi, crash-looping the recorder. Bump the tmpfs to 2Gi and the memory limit to ...
Include both desktops in every SSO token, deep-link to the chosen one
Each token carried only its own connection, so the browser's reused json session lacked the other one -> opening Windows after Linux gave 'connection does not e...
Route borrower submit through the pipeline so it fires **************** (audit #3)
patchLoanFile's borrower submit (DRAFT->APPLICATION_TAKEN) now calls **************** instead of a raw updateLoanFile status set, so the submit produces the has...
Wrap recording upload so MediaService compiles
MinIOStorageService.upload throws a checked Exception that ingest() neither caught nor declared — build break on top of the isGuest fix. Wrap it and rethrow as ...
MeetingParticipant.isGuest() (was getGuest, won't compile); repoint transcribe to generic endpoint
MeetingParticipant exposes isGuest() (primitive boolean getter), not getGuest(). Also point the summary transcribe call at the shared /api/conversion/transcribe...
Correct Guacamole branding manifest version field
Manifest used guacManifestVersion:1.0; the bundled extensions use guacamoleVersion. The wrong field made Guacamole reject the branding extension ('Unable to rea...
Stop double-appending ?target in the SSO proxy route
forwardToApi already forwards the incoming query string, so passing the path with ?target= produced **************** -> target='linux?target=linux' -> 400 'Unkn...
Alias ALL turbopack content-hashed externals, not just prisma
The prior fix only aliased @prisma/client-<hash>; the build also externalizes pg-<hash> (node-postgres, via @prisma/adapter-pg) under the same content-hashed sc...
Resolve session from X-***-Token header in CallerSessionResolver
The kamo-internal -> APIService BFF path forwards the session as the X-***-Token header, but the resolver only read the X-OTK attribute or the *** cookie — so B...
PatchLoanFile is no longer a status backdoor; unblocking a condition needs the underwrite right; clear cascades
**************** status changes are the pipeline state machine's job (POST /transitions enforces legal arrows + per-arrow role gate + open-blocking-condition ga...
Partial condition PATCH can't silently clear the blocking flag; template blocking default honored; publish after commit
**************** boolean -> Boolean so a PATCH that OMITS the field is distinguishable from an explicit false. LoanConditionService.update now null-guards *****...
Alias Prisma 7 content-hashed client so DB routes stop 500ing
The prisma-client generator (engineType=client) bakes a content-hashed runtime specifier (@prisma/client-<hash>) into the Next build. The builder satisfied it v...
Inject KamoDesktop SSO env directly + wire guac-sso into tracked k8s deployment
- @Value reads KAMO_GUAC_SIGNING_KEY / DESKTOP_PASSWORD from env directly (runtime application.yml is configmap-mounted, so property indirection wouldn't bind...
Move guacd to pod network (MTU fix) + unicast WoL
guacd on hostNetwork (k1m1 eno49 MTU 1500) vs guacamole pod on cilium overlay (MTU 1420): RDP connected but large frames were dropped across the boundary -> 'Gu...
Close JWT-forge hole, fix guest join, add "Sign in with Kamo"
- sidecar /api/auth/jwt: derive the member identity (id/name/email/org) from the server-side *** session, not the request body. Previously anyone could POST...
Sign invited members into meetings via click-time OTK join links
Invite links (chat + email) previously embedded a bare meet-room URL, so recipients landed as anonymous guests instead of themselves. An OTK can't be pre-embedd...
Persist invited participants, enforce MANAGE_MEET_SETTINGS, drop double-invite path
- createMeeting: invited members are numeric snowflake IDs, not UUID strings — route them through longToUUID like the creator. Previously UUID.fromString th...
Watch the desktop namespace for IngressRoutes
desktop.kamocrm.com IngressRoute lives in the desktop ns, but Traefik's CRD provider only watched **************** — so the route was ignored and requests fell ...
Import VM disk as Filesystem, not Block
CDI's block importer crashlooped: 'blockdev: cannot open /dev/cdi-block-volume: Permission denied' — it can't access the raw Longhorn block device. Filesystem v...
Borrower submit fires the Application-Taken side effects (doc checklist + notify)
The portal borrower submit is PATCH loan-file {statusId:2}, which bypassed the operator /transitions endpoint where the Application-Taken side effects live — so...
Reject negative loan amount / property values on section saves
updateLoan and updateProperty now reject a negative monetary amount on the LTV inputs (loan amount, estimated/purchase/appraised value) via requireNonNegative —...
Correct KubeVirt VM cloud-init field + modernize spec
- cloudInitNoCloud userdata secret field is 'secretRef' (not userDataSecretRef); KubeVirt v1.8.4 pruned the wrong field -> 'must have at least one userdatasou...
Never prepend www to subdomains, only to the bare apex
The catch-all redirected ANY non-alias host to https://www.<host>, which is correct for the bare apex (kamocrm.com -> www.kamocrm.com) but wrong for a subdomain...
Borrower cannot escalate loan-file status or edit the URLA after submission
Two related borrower-authorization holes on the self-service app endpoints: - Privilege escalation (#2): patchLoanFile applied any statusId with no caller-ri...
Loan-file status accessor for borrower edit-lock, borrower-delete cascade, gift-recipient app scoping
**************** orgId): read helper backing the borrower post-submission edit lock (a borrower may only edit the URLA while the file is DRAFT). **************...
Show member avatars in the Chats tab
MediaService returns chat-session member avatarUrl=null by design (avatars are resolved on the frontend), but the Chats tab never resolved them, so it always fe...
Borrower self-create idempotency + orphan compensation; don't relay an empty checklist as success
MortgageAppController.create() borrower self-create branch: - Idempotency (#2): resume an existing owned DRAFT via findOwnedDraft instead of minting a duplica...
Readiness banner refreshes with the Refresh button and never shows an empty market name
Two follow-ups on the MLOS default-lead-source readiness banner: - Refresh (IconButton) now also calls loadMlosReadiness(), so surfacing a newly-created marke...
Idempotent borrower self-create draft + deterministic active lead-market resolution
**************** memberId): resolves the member's existing in-progress DRAFT application so a repeated borrower self-create (double-click / reload / second tab ...
Explain why the MLOS default-lead-source control is hidden instead of silently dropping it
On the vendors-products tab the "designate default lead product" control is gated on mortgage-vertical readiness — POS enabled, an active MORTGAGE commerce mark...
DbNow() use CAST(now() AS timestamp), not now()::timestamp
The ::timestamp shorthand is mangled by Hibernate's native-query parser (it reads ':' as a named-parameter prefix, turning ::timestamp into :timestamp) -> CRDB ...
Stop duplicate chat popups for the same conversation
The tool-window dedup only exact-matched a single userId key against an async-mirrored windowsRef, so the same 1:1 chat opened twice: - userId from a member ro...
Show all enabled-app permission groups in job title & department editors
JobTitleManager and DepartmentManager only ever rendered two permission groups — General and CRM — so **************** rights were invisible and uneditable ther...
Resolve member rights as a true waterfall instead of NUKE-always-wins
Effective rights were computed by folding every source (roles, department, job title, member) into one map where NUKE always won. That meant a member holding bo...
Like what you see shipping?
Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.