Deliver cluster alerts into a member's chat thread
Alertmanager webhook receiver at /api/internal/alerts/chat, so a KamoDesktop alert reaches a person instead of a dashboard. This is the BEST-EFFORT leg. Email ...
Bug CRUD, screenshots and the one visibility rule
A system bug crosses the tenancy line in one direction: the platform organization sees every tenant's, and no tenant sees another's. That rule lives in ********...
Guard social messaging and Canva at their credential chokepoints
SOCIAL_MESSAGING is enforced in SocialCredsResolver.resolve — the narrowest point covering every adapter and both directions. No credentials means no Telegram, ...
The Affiliate Sales Scoreboard endpoint
GET **************** answers this organisation's top ten for one metric over one window, plus the caller's own standing when they are not on it. The counters o...
Refuse meeting recording for a tenant that handles PHI
The capability split made ServiceType.MEET permitted — a live conference on self-hosted Meet never leaves the cluster — while MEETING_RECORDING stayed blocked, ...
Let the public config be addressed by org id, not only by host
The meet sidecar looks up an org's meet config to decide whether a guest needs a meeting password. It asked by hostname, which on the shared meet host resolves ...
Carry the type description in both of its shapes
The description is a Lexical document now, so the service stores the plain-text mirror the client sends alongside it and hands readers whichever shape they can ...
Relay "the classic version was just saved" to the editor
DocsService publishes docs.classic-saved.{memberId} after a WOPI save lands on a CLASSIC version; this puts it on /topic/docs/saves/{memberId} over the STOMP co...
Enforce the org chat policy, and close two holes it sat on
Applies the policy at the three places a conversation can start or continue: session creation, member adds, and the send path. A room is not policed pair by pai...
Put the requestor's face and name on each support chat row
A Chats → Support row showed the same support glyph on every line, so a queue of them was a wall of identical blue circles. The face people actually scan for is...
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 an opaque UUID token, in one insert
createCode generates the token itself, so there is nothing to read first and nothing for two tabs to collide over. That removes the whole apparatus the old sequ...
Move credit on a newer link, and record the moment it moves
The ingest worker now calls reattributeWhileAnonymous after the traffic bumps. The repository method carries the entire rule, so there is nothing to check here ...
Serve the tracking-codes tab and ingest the visitor beacon
MediaService already backs the other marketing tabs, so it takes both halves of tracking codes: the authenticated CRUD and stats surface at /api/media/marketing...
Creating and resolving a meeting take the rights that name them
/api/meet/create checked only that you had a session, so every authenticated member of every organization could create a meeting with the org's provider — START...
Relay the outstanding-course count onto the member's own topic
The twin of the legal relay, because NavTop sums the two counts into one badge and a pair of halves that behaved differently would give the member chrome that w...
Unread means the requestor spoke, or the ticket just became yours
The badge counted "live tickets nobody has picked up, plus the ones I hold" — message-blind, and it only ever fell when a ticket reached a terminal status. So i...
Stamp unseen counts on the ticket list, and keep the queue live
getTickets now bulk-loads an unseen-message count per row for the caller, beside the visitor rows it already loads that way, and getTicketDetail computes its ow...
One conversation, many hands — join on open, name every message, re-open on a reply
A support ticket is worked by whoever is helping, not only by whoever it is currently stamped with. Assignment decides who the work is offered to and whose list...
Reassignment reaches the new agent, and the requestor is told who is there
Reassignment did not reach anybody. assignmentOpenedAt records that a client put the conversation on screen, and it is what raises a ticket at sign-in — but it ...
Endpoints for the sign-in auto-open handover
GET /sessions/chat/auto-open returns the chat conversations this member's client should raise; POST /sessions/{guid}/auto-opened records that it did. The durabl...
AUTO_ASSIGNMENT, and raise an assigned conversation on the agent's screen
A chat request and a submitted ticket are the same unit of work; the topic's strategy is the only thing that decides how either is handed over. The PRE_TICKET s...
Point at YugabyteDB and use PostgreSQLDialect
CockroachDB has been replaced by YugabyteDB. Connection strings move from cockroachdb-public:26257 to yb-tserver-service:5433, and the Hibernate dialect from **...
Attach an already-stored file without uploading it again
Forwarding a 2 GB video to three colleagues cost three full uploads. Storage deduplicated them into one object, but only after each transfer had completed and b...
Accept 3 GiB attachments by streaming them to storage
file.getBytes() cannot represent an upload this large — a Java array stops just above 2 GiB — so every attachment past that died on an OutOfMemoryError regardle...
GET /types/{typeId}/slots so the settings editor can list slots
The settings UI has always fetched this path, but only POST/PUT/DELETE were mapped, so the Availability Slots tab got a 405 and rendered empty. Unlike /slots/av...
Relay the legal-package count and guard per-member SUBSCRIBEs
legal.packages.> -> **************** core NATS, no stream — the same shape SupportStompRelayController and PlatformStompRelayController already use. topicFor is...
Relay SecurityService platform events onto STOMP
SecurityService owns the platform-admin surface — system configuration, DNS provisioning, commerce sync — but has no WebSocket endpoint, so every screen backed ...
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...
Meeting provider abstraction with Zoom and Microsoft Teams
Meetings were Kamo Meets by construction — MeetService persisted a Meet room name and nothing else. This introduces the abstraction and two remote providers beh...
Persist MediaService PHI access trail to phi_access_log
Chat message reads were recorded through the Slf4j default writer, which puts the §164.312(b) trail in a 14-day log stream against a six-year retention obligati...
Record chat message reads on the endpoints that return bodies
Sending a message left a row; reading one left nothing. Every chat, support and social thread on the platform renders from a handful of endpoints here, and none...
Carry the AI conversation into the human thread on handoff
Creates or reuses the support session, copies the AI transcript in as one system event, routes it, and tells the visitor honestly what happens next. Confidenti...
Accept agent-authored outreach into an open borrower thread
The counterpart AIService's outreach dispatcher calls. Without it the whole outbound path terminated in a recorded 404 - the gate authorized a touch, the messag...
Assign a sales agent per channel + report LO availability
- WebChatIntegration CRUD threads salesAgentId (null clears the assignment) - lo-presence now returns the member's availabilityStatus alongside online, so the ...
Verify routing token, persist leadUid, reassign chat on lead move
- createSupportSession takes a signed routingToken (not preferredAgentMemberId); verified via ChatRoutingTokenCodec + cluster internal.auth.secret, enforces ...
Snapshot web-chat integration id on support visitor + ticket
Resolves the WebChatIntegration by creatingKeyHash (enabled-filtered, consistent with bootstrap()/AI-prompt resolution) once in createSupportSession and stamps ...
Public-chat bootstrap config resolver
Adds an internal GET **************** that resolves a WebChatIntegration by X-Public-Chat-Key-Hash and returns its resolved design/behavior config (default-fill...
WebChatIntegration CRUD (mints key + integration, org-scoped)
Org-facing management API for the Phase-2 web-chat settings tab. On create, mints the underlying PublicChatApiKey (same key-gen approach as PublicChatKeyControl...
Bust APIService key cache immediately on public-chat key toggle/delete
Persist creating key hash on public-chat visitor + ticket for attribution
Mobile push dispatch (FCM data + direct APNs) with presence gate
chat incoming (MediaController), support ticket (SupportNotificationService), SMS/voicemail (VoipStompRelayController), social **************** Presence-gated l...
Accept X-***-Token on REST; slide TTL with per-session timeout
OTKPreAuthFilter resolves X-***-Token when no X-OTK is present (same call MediaService REST without the BFF. KSessionService now slides the Redis TTL with the s...
Reach the borrower's OWN officer directly, no support-right gate
Drop the ACCEPT_SUPPORT_TICKETS requirement from assignToPreferredAgent: the borrower's assigned loan officer is reachable regardless of whether they're a confi...
Direct-to-assigned-LO routing + LO presence endpoint
Powers the borrower portal's merged LO/chat widget: - **************** direct-assigns a public-chat ticket to a SPECIFIC agent (the borrower's assigned loan o...
Missed-message email notifications (chat + support) with per-source suppression
Durable NATS consumer chat-email-notifier on chat.session.> feeding a MESSAGE_EMAIL_NOTICES ledger (PENDING/SENT, per-sender for chat, per-ticket for support), ...
Durable last-seen timestamps + bulk endpoint
PRESENCE:{id} is deleted the moment a member goes offline, so nothing recorded when they were last active. Stamp PRESENCE_LAST_SEEN:{id} (orgId + ts, 400d TTL) ...
Like what you see shipping?
Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.