Portal the break-glass dialog to the body
Clicking break glass opened the dialog inside the nav rail instead of over the page. The overlay is a bare fixed-position motion.div, not a MUI Dialog, so it ha...
Mirror Maven Central and retry, so a corrupt transfer stops killing the build
The session security-level fix failed to deploy because bcprov-jdk18on:1.72 arrived corrupted — 'Tag mismatch' is a TLS auth-tag failure mid-transfer, not a mis...
Name the full logo correctly and resolve an org's domain deterministically
Three defects in how an organization's branding location is derived. my-networks named the full logo "logo-full." + logoFullExt, defaulting to "svg" when the c...
Rebuild for the dedup uploader fix
Picks up **************** now setting createdByMember, so deduplicated documents record who uploaded them.
Record the uploader on a deduplicated document
registerExistingDocument built its Img without .createdByMember(member), which the normal upload path sets. Every document registered through dedup therefore la...
Proxy foreign org logos so the tenant img-src policy can't block them
/network is the one page that renders another tenant's branding: it lists every organization in the network and loads each logo from that org's own theme.<domai...
Read the member security level the column actually stores
members.security_level is a VARCHAR holding the ImageAccessLevelType NAME — 'PRIVILEGED', 'MEMBER', 'TEAM_MEMBER'. The session builder tested the value with ins...
Merge a caller's query with the browser's instead of concatenating
forwardToApi appended the browser's query string to whatever it was given, so a caller passing its own query produced a URL with two '?'. Everything after the f...
Use targeted conversion updates instead of saving a detached ImgDat
convertAndGenerateThumbnails runs on a virtual thread with a detached ImgDat, so imgDatRepository.save() merged a stale orphan-removal collection and threw befo...
Targeted conversion updates, so a detached ImgDat save cannot abort conversion
Conversion runs on a virtual thread against a DETACHED ImgDat. save() therefore merges an instance whose LAZY `images` collection is no longer the managed one, ...
Keep upload Folder/Doc Type labels shrunk over native selects
The per-file Folder and Doc Type selects start with an empty value, so MUI left their labels at rest position while the native <select> still painted its first ...
Rebuild against kamo-shared-library 8f3c1ec
Picks up the intake-pool fix: LeadService.createLead now flags unowned leads with requiresAssignment so imported leads are counted by countAssignablePool and ca...
Rebuild against kamo-shared-library 8f3c1ec
Picks up the intake-pool fix: LeadService.createLead now flags unowned leads with requiresAssignment so imported leads are counted by countAssignablePool and ca...
Rebuild against kamo-shared-library 8f3c1ec
Picks up the intake-pool fix: LeadService.createLead now flags unowned leads with requiresAssignment so imported leads are counted by countAssignablePool and ca...
Put unowned intake leads into the auto-assignment pool
Every lead-creation path funnels through LeadService.createLead — CSV import, the lead-intake endpoints and their scheduled DaemonService job, the public webina...
Let a tab fill the content area, so the document manager gets full height
The content wrapper was a plain block, so a page's `flex: 1` had no flex parent to resolve against and the wrapper sized to its contents. DocManager's root is `...
Merge same-named vendors and products in the filter bar
An org routinely holds one lead supplier under several vendor records, so on the "All Markets" tab the Vendor dropdown listed the same name once per record — id...
Remove the filter button from datagrid column headers
AG Grid 32 defaults to the "new" column menu. On Community (no enterprise module) that means no header menu button ever renders — the only header-cell affordanc...
Purge lead e-mail links whose lead-side address is the company's
Clears what the old company-address rule wrote before it read org_domains. Live production was purged by hand at the time (126 rows, 6 leads, one org); this exi...
Never match a lead against the company's own addresses
A lead whose e-mail was set to noreply@kamocrm.com matched every message that address had ever sent — one lead record surfaced the company's entire outbound mai...
Drop the description line above the Resources document manager
It described a tab that now shows its own contents, so it was only taking space. descriptionKey goes optional rather than staying as an unrendered string: a tab...
Mirror Maven Central and retry, so a corrupt transfer stops killing the build
The HR_RESOURCE rebuild failed on hibernate-core:6.5.3.Final with 'Tag mismatch' — a transfer corrupted in flight, not a missing artifact. The shared-lib stage ...
Stop double-appending the query string on the communications route
All / Calls / Texts / Emails failed with "We couldn't load this lead's communications". The backend was fine — direct calls returned 200 with real entries. The ...
Resources tab is the org's HR document library
Replaces the Resources placeholder with DocManager on a document collection of its own — ImageAssocType.HR_RESOURCE, bucket imaging-hr-resources — org-scoped th...
Rebuild for ImageAssocType.HR_RESOURCE
ImagingUploadController reads ImageAssocType.values(); without this rebuild an upload from the HR Resources tab cannot resolve ordinal 13 to its bucket.
Rebuild for ImageAssocType.HR_RESOURCE
**************** resolve the assoc type with values()[ordinal]; without this rebuild values()[13] throws on the stale 13-constant array as soon as the HR Resour...
HR_RESOURCE assoc type for the org HR resource library
The /hr Resources tab publishes handbooks, policies, forms and reference material to the whole team, and no existing assoc type fits: MY_DOCS is a person's own ...
Remove the god-mode time-box
Checking in work left uncommitted in this working tree by a concurrent session. Not authored here; committed so it is not lost and so main is not left with a tr...
Timeline a11y, timezone-correct day headings, and a summary card that isn't zero
Three defects, each invisible until it bites. The row expander wrapped the whole header in a <button>, and DateTimeDisplay renders its own interactive tooltip ...
Real chat direction, and stop the timeline mapper writing or fanning out
Chat entries claimed no direction and attributed every message to its row's author. Social conversations record BOTH sides against a Kamo Member — the visitor's...
Stop re-querying call history per extension when the provider is instance-wide
RingCentral's endpoint is extension/~ and ignores the argument, so it returns the same log for every extension. Once a page adds nothing new, the remaining exte...
Pin the contact-point and linker invariants, and drop timeline count queries
The two classes the whole feature rests on had no tests, and all three properties they guarantee fail silently in production: an unmatched call is indistinguish...
Human Resources module shell with five route-backed tabs
Adds /hr with the accounts-page chrome in its route-backed form (the same one /marketing already uses): a layout owning the gradient hero and underlined tab bar...
Isolate call ingest per row and link only after it commits
Two faults with one root: ingest participated in the sweep's transaction. A throw inside a participating transaction marks the SHARED transaction rollback-only...
Make communication source ids natural keys, not row ids
A source id derived from the source row's generated UUID is only stable if that row commits. The VOIP ingest paths write inside the sync transaction while LeadC...
State honestly why chat entries carry no direction
The javadoc claimed direction was derived from the author while the code hardcoded UNKNOWN. Social conversations record both sides against a Kamo Member — the v...
Skip soft-deleted extensions in the call-history sweep
syncExtensions soft-deletes by flipping status to UNKNOWN rather than removing the row, so the list accumulates every extension an instance has ever had. Each o...
Page the lead sweep until the window is covered
A single fixed page silently lost mail whenever a mailbox took more than pageSize messages between ticks — a newsletter burst, a busy shared inbox, or just the ...
Complete the Communications tab
Each sub-tab now holds its own data, and All interleaves every channel by date. Notes keeps MediaStream, because notes are authored here — but readOnlyChrome s...
Unified communications timeline API
GET **************** returns one date-ordered page across notes, calls, voicemails, texts, e-mails and chat; ?channel= narrows it. Three sources are merged. Ca...
Drive the mail-to-lead association sweep
Five-minute tick against EmailService's internal sweep endpoint, mirroring VoipGlobalSyncJob. The schedule lives here because EmailService runs several pods and...
Associate lead correspondence, and fix the dead push indexer
Adds the mail half of the lead Communications tab, plus the ingestion it needed to exist at all. The platform has no working mail push: IMAP IDLE is hardcoded ...
Persist calls and associate calls, texts and voicemail with leads
Calls were never recorded anywhere — VoipCallEventService published a NATS event for the browser and kept nothing, and RECORDINGS only exists when audio was cap...
Schema and contact-point seed for lead communications
Hibernate creates the three new tables from the shared-lib entities; this adds what it cannot express — the partial unique index that keeps at most one open con...
Point-in-time contact-point index and lead communication links
Adds the spine the lead Communications tab reads from. LEAD_CONTACT_POINTS records every phone number and e-mail a lead has ever had, as a window with activeFr...
Submit the lead at step 1 instead of only on booking
handleFormSubmit checked the *** and advanced the step — it made no network call at all, so the contact details a visitor typed were only ever persisted if they...
Capture the demo lead before the booking step
The marketing site's demo form collected name, email, company, company size, industry and a message, then advanced to scheduling without telling anyone. Lead cr...
Public demo-request lead capture primitives
A visitor who fills in the marketing site's demo form but never books a time left no trace: the lead was only ever written inside the booking transaction. Captu...
Withhold the reply box from senders that cannot receive one
Sending a quick reply to a KamoCRM notification put the literal text `{"error":"Invalid Addresses"}` in the reply box. The mail server had rejected NoReply@Kamo...
Address replies at Reply-To, and stop leaking SMTP exceptions to the UI
A quick reply to a KamoCRM notification failed with `{"error":"Invalid Addresses"}` rendered verbatim in the reply box. That string is Jakarta Mail's own wordin...
Like what you see shipping?
Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.