Delegate AvatarObjectPaths to the shared library
MediaService now names avatar objects too — the support chats list shows the requestor's photo, and a support requestor is in somebody else's organization, so n...
Resolve a member's photo URL from the shared library
The Chats → Support list is about to show the requestor's face, and a support requestor is — on the platform's own desk — always somebody else's member. Every o...
Return each member's accepted-today count per product
Manage-Credits shows Max Daily Spend but nothing about how much of it is used, so a manager could not tell whether a member was one lead from their cap or had n...
Count today's spend across a member's products in one query
Manage-Credits wants to show, per member, how many leads they have accepted so far today — the running total the Max Daily Spend cap is compared against. ******...
Drop imports left unused by removing the @EntityGraph
Page, Specification and EntityGraph were only needed by the findAll override that was removed after it took /leads down. Leaving an unused EntityGraph import on...
Stop cutting note bodies off at 500 characters in the timeline
The All tab of a lead's communications rendered a note through LeadCommunicationMapper, which capped the body at 500 characters — with no ellipsis and no flag, ...
Take leads-available from the server's per-product counts
leadsByProduct was derived from the allotment rows, which only cover products someone already holds a credit rule for. The grid lists products from the vendor c...
Report leads available for products with no allotment
/manage built its whole response by looping over allotments, calling countAssignablePool once per row. But the Manage-Credits grid lists products from the vendo...
Count the assignable pool for every vendor product at once
countAssignablePool answers for one product, so a caller can only ask about products it already holds. Manage-Credits was iterating allotments to decide what to...
Give the composer its caret back after each send
Every chat box in a tool window locks itself while a message goes out — the input carries `disabled` so nothing typed mid-flight is discarded when the draft res...
Composite indexes for geolite_locations
Country alone was the only index on an 80,429-row table. Measured on production: city resolution (country + subdivision) index-scanned all 18,870 US rows to kee...
Stop scanning every market x product after the answer is known
/leads/available-summary returns three things — hasAcceptable, hasAcceptableCredit and one example product — but visited every market x product pair regardless,...
Index the two shapes geolite_locations is actually queried by
Country alone was the only index on an 80,429-row table, and neither real query used it well. Measured on production: city resolution (country + subdivision)...
Show the requestor's org, and offer the System User door to their agent
The support chat header now names the organization the request came from, to everyone working the conversation and to nobody else — the person who raised it wou...
Name the requestor's org, and end System User access when the ticket moves
Three things, all about a support desk that answers more than one tenant. The ticket detail now carries a per-viewer verdict on whether to offer "open the requ...
Mint a System User session for a support agent's open ticket
enter-as gains a second reason to say yes. SystemUserEntryPolicy turns the caller's *** into the facts the shared SupportSystemAccessResolver takes, and that re...
Let an open ticket grant its agent the requestor's org, and expire with it
A support agent needs to look inside the customer's tenant to answer the ticket they are holding. Until now the only way in was the blanket SYSTEM_USER platform...
Record that the unprocessed claim is now batched
getUnprocessedPayloads() returned every unprocessed payload, and this job holds each one's raw and flattened text for its whole run — so its memory was a functi...
Count in the database instead of hydrating every commit
GET /changelog/public/stats loaded all 16,571 commit logs as entities and tallied them in a Java loop to produce two small maps and a total. It takes no authent...
Index member_rights_applied on (member_id, the_right)
The table had no indexes at all, while every finder on it filters by MEMBER_ID. At 10,524 rows a single member's rights lookup was a full sequential scan — meas...
Restore CRLF in MemberRightsApplied
The previous commit rewrote this file with a script and silently converted its line endings, so 53 unchanged lines showed as modified and buried the actual 15-l...
Index member_rights_applied, bound the intake claim, aggregate changelog stats
Three findings from an endpoint-by-endpoint audit, each measured against production rather than inferred. member_rights_applied declared no indexes at all whil...
An opt-in probe that executes the grid's SQL, not just its HQL
/leads went down on 2026-08-20 with 'missing FROM-clause entry for table a2_1' and no test caught it, because none of them could: the library compiles against H...
Remove the @EntityGraph that broke /leads on Hibernate 6.2
The grid page query failed in production with: ERROR: missing FROM-clause entry for table "a2_1" ... left join member_team_member a2_0 on **************** ...
Fetch one server-filtered page instead of the whole organisation
The grid fetched every lead in the org and narrowed it in a ~300-line useMemo. Measured on production 2026-08-20: 1,427 leads fetched so seven could be shown, 2...
Page the grid endpoint and take the PHI audit write off the request thread
GET /api/security/leads returned every lead in the organisation. It now takes page/size/sort plus the filters the grid actually uses, and returns a page with a ...
Filter and page the grid in the database, batch the PHI audit trail
Loading /leads took 23.3 s at 1,427 leads. 23.3 s of that was the HIPAA audit trail: recordLeadList writes one phi_access_log row per lead returned, and each on...
Composite lead indexes, and unblock the run that creates them
The /leads grid now filters and pages in the database instead of shipping the whole organisation to the browser. With only IX_LEADS_ORG_ID that would relocate t...
Mark payload outcomes by column, not through the entity
payloadRepo.save() on a detached payload makes Hibernate walk its graph — organization pulls in org_domains — and that read lands in a transaction that has alre...
Settle each backlog payload as it is processed
processBacklog mirrored the scheduled job's two defects: it mutated payload statuses in memory and saved them in one batch at the end, and it saved the whole en...
Record a payload's outcome by column, not by entity
Marking a payload IMPORTED with payloadRepo.save() makes Hibernate walk the detached entity's graph — including organization, which pulls in org_domains — and t...
Stop overlapping runs importing the same payloads twice
The trigger fires every minute and each run claims work by selecting payloads still in RECEIVED. A backlog that takes longer than a minute therefore still had R...
Bump the processed counter instead of rewriting the endpoint
The job finished a batch by mutating totalProcessed on the endpoint entity it loaded before the batch began and saving the whole row. Two consequences: - it ...
Never fail a submission because its counter update lost a race
storePayload no longer bumps the endpoint's received counter; the receive controller now calls recordReceipt separately, in its own transaction, and swallows th...
Prefer brotli on the theme host, and correct the previous rationale
Two things, one of them a correction to the commit before this. The previous commit justified `encodings: [br, gzip]` with a probe against api.kamocrm.com. Tha...
Prefer brotli, stop compressing what is already compressed
The shared `compress` middleware was `compress: {}`, which is three separate defaults and none of them is the one we want. Traefik picks gzip whenever the clie...
Stop losing payloads to endpoint-counter contention
storePayload saved the payload and then bumped totalReceived/lastReceivedAt by dirtying the endpoint entity — in the same transaction. Every submission to an en...
Every country flag in the app was a blocked image
Eight more screens had the defect found in the marketing visitor drawer. The app is served under img-src 'self' data: blob: https://theme.kamocrm.com https:/...
Compress every response, not just the document
server-nonce.js asks upstream for `identity` so the HTML can be stamped with a CSP nonce without a decompress/recompress round trip, then recompresses on the wa...
Drain deferred work one item per idle period
Four components waited for the main thread to go quiet before doing their work — the toast/consent bundle, the scroll chrome, the touch target sweep and the ref...
Read the scroll position from an observer, not from layout
The nav's scrolled/at-top state came from a scroll handler that read window.scrollY, and the mount effect called that handler synchronously during React's commi...
Flags are emoji, because the CSP blocks every flag CDN
The visitor drawer painted a broken-image glyph where each country flag should be. react-country-flag's `svg` mode reads like a self-contained component and is ...
Rebuild against kamo-shared-library 811db57
Picks up the createLead fix that moves the pool-availability recount to afterCommit. Before it, a read-after-write in the lead's own transaction hit YugabyteDB'...
Rebuild against kamo-shared-library 811db57
Picks up the createLead fix that moves the pool-availability recount to afterCommit. Before it, a read-after-write in the lead's own transaction hit YugabyteDB'...
Persist each payload's outcome as it happens, not in one batch
processEndpointPayloads looped over the batch mutating statuses in memory and saved them all at the end. createLead commits per lead, so any failure of that fin...
Move the pool-availability recount after commit
createLead saved the lead and then, in the same transaction, ran countAssignablePool to broadcast the new "Leads Available" figure. On YugabyteDB a read after a...
Offer Company Name as a mappable import field
leadFields.ts is the list the mapping canvas draws from, and it must mirror the backend switch in LeadImportController — a path missing from either side is acce...
Map companyName so a spreadsheet can carry the business name
setDirectFieldOnCreateRequest had no companyName case, so the field was unreachable from the manual-import wizard even though CreateLeadRequest carries it and L...
Let a mapped payload carry companyName and source
The intake job's direct-field switch stopped at vendorLeadID, so a mapping onto companyName or source was accepted by the UI, stored on the endpoint and then si...
Serve static assets as build-time brotli
The flagged chunk is react-dom, and I checked it properly before concluding anything: it is the production build (no dev markers, and the profiling hooks `injec...
Je, unaona nini kuhusu usafiri?
Kila moja ya hizi updates ardhi katika nafasi yako ya kazi moja kwa moja. Kuanza bure na kuangalia kukua wiki baada ya wiki.