A control that actually opens what produced the event
The callback's description carried "Open the lead: /leads/view/123" as text, and text in a textarea cannot be clicked — the event dialog edits its description i...
Stop writing the lead path into the callback's description
It read "Open the lead: /leads/view/123" and was not a link. It could not be: a description is edited in a textarea, where text is text — and outside the applic...
Rebuild against the shared-lib event-range fix
No source change here. Service CI clones kamo-shared-library at build time, so picking up c1e68a9 — which stops an omitted date window failing every calendar ev...
Stop an omitted date window failing every event lookup
The calendar page could never list anything. It asks for every event a member has, with no window, and these queries took the range as nullable and tested it wi...
Callbacks on the calendar, and a marker on the list
Two ways to see a call you promised to make without opening the lead. On the calendar, a callback gets its own line item rather than looking like any other app...
Callback summary for the leads list marker
Answers which leads have a call still waiting, and when the soonest one is due, for the caller's organisation in one request. Its own endpoint rather than a fie...
Put a callback on a calendar the member can actually see
Callbacks were not reaching the calendar at all. This service picked the target calendar by account — findPrimaryByUser — and a user is global while a member is...
Pending callbacks for a whole organisation in one query
Feeds the leads list's per-row callback marker. The grid holds every lead the member can see, so asking per lead would be a request per row to render one column...
Stop the event dialog throwing "Invalid time value" on open
wallClockToInstant called toISOString() on a date it had not checked, so any unreadable input threw RangeError instead of returning something unusable. The dia...
Let "not established" be a value the images gate can see
Follows EmailService boxing **************** A folder listing now reports null for it rather than a primitive's false, so the types here admit null and the gate...
Stop envelopes claiming a consent answer nobody asked for
remoteImagesAllowed was a primitive boolean, and only the three endpoints that fetch a whole message ever assign it. The folder listing does not — answering it ...
A notification centre, on every page
Reminders had nowhere to arrive. The calendar's popup was a plain alert in the top corner of whichever page happened to be open, it vanished on a timer, and any...
A callback that leads back to the lead
The callback already reached the member's calendar, as an event titled "Lead Callback" with their comment in the description. Nothing said whose call it was, no...
Make event reminders actually notify someone
Three faults, one symptom. Members reported that calendar notifications did not work, and all three reasons were on this side. Reminders were never written. Th...
Member notification tables, and an event's origin columns
Two halves of one feature. A callback scheduled on a lead is mirrored onto the scheduling member's calendar, and the point of the mirror is to get back to the l...
Member notification centre, and an event's origin
Adds MemberNotification and MemberNotificationPreference: one row per member per notification, because read, dismissed and snoozed are per-person answers and a ...
Detach notes into draggable, resizable floating stickies
Each note in the list (and the editor) gets a detach control that pops it onto a screen-wide overlay. Any number can float at once; each can be dragged anywhere...
Stop flashing the external-images prompt at members who allow them
Opening a message showed the "display external images" banner for a moment and then withdrew it, for anyone who had already chosen to allow images everywhere. ...
Fold the back arrow and book icon into the header title
The /kb body repeated the gradient header title verbatim. Drop the duplicate, move its book icon onto the h1 and park the back arrow to the right of it.
Ask for the unread count, not the whole folder tree
The mail badge needs one integer and was fetching every folder in the mailbox to find it, which on the IMAP providers is the most expensive call the mail backen...
One integer for the mail badge, and count what the index path is worth
Three things, all about knowing rather than assuming. The nav-top unread badge fetched the entire folder tree and picked INBOX out of the result — the most exp...
Brand chrome around a drafting board in the signing room
The desk was tinted with the org's colour and went dark in both themes, which put the brand under the document and left the chrome neutral — exactly backwards. ...
Stop storing which side a message is on
The mirrored rule was right; what was wrong is that the answer was computed once, when a message arrived, and kept. Placement needs three things — the sender, t...
Stop making the inbox wait on two lookups it can see the answer to
Two round trips still sat in front of a rendered inbox, and by this point they were the only thing left there — the folder tree and the first page already arriv...
Prove a folder unchanged with HIGHESTMODSEQ, then serve it from the index
Turns the index-backed message list on, by fixing the thing that made it unsafe rather than by flipping the flag. The old check compared message counts and UID...
Keep the session document name as the consent card's fallback heading
Extracting FieldLayer dropped detailTitleFor, and with it the fallback to session.documents[0].name — a document with a null fileName would have headed its cons...
Render the document the wizard was measuring into a node that did not exist
The execution wizard showed a blank surface for every signable document — no pages, no field overlays, no PDF request, and nothing in any log. DocumentStep mea...
Correct what the index-backed read path actually guarantees
The previous comment claimed the read path "refuses to serve any folder it cannot prove it agrees with the server about — so a row that is wrong here is a row t...
Record all three IMAP flags, and say why the index cannot serve a list yet
The migration has run, so is_answered exists and SearchIndexService now writes it alongside is_read and is_starred. The index has recorded two of the three flag...
Map is_answered, now that the column exists
KamoInitializer added **************** on 2026-08-13 **************** verified in Yugabyte: boolean, default false, no nulls). Mapping it is safe now and was no...
Do not read or write is_answered before its column exists
Follows the shared-library change unmapping the field. Nothing in the deployed path now touches a column that KamoInitializer has not yet created. The index-ba...
Unmap is_answered until its migration has run
Mapping the column ahead of the migration that creates it is armed, and I armed it. SearchIndexEntity is hydrated from fullTextSearch, which is a native SELECT ...
Ask earlier, ask once, and stop asking for what has not changed
Three more things standing between opening /messages and seeing mail. Nothing was requested until the bundle had landed. /messages pulls several megabytes of J...
Serve a folder listing from the index when it can prove it is current
The rows behind a message list are already in Postgres — the metadata index holds sender, subject, date, size, attachment and flags for every message it has see...
Add is_answered to the mail search index
Adds **************** so the index records all three IMAP flags rather than two. The message list draws a reply marker from this one, and the index-backed listi...
Record whether a message was replied to in the mail index
email_metadata.search_index has carried is_read and is_starred since it was created but never the third IMAP flag, \Answered. That was harmless while the index ...
Only the requestor is asked how the support went
Closing a ticket put "How was your experience?" in front of every agent in the conversation — the people who did the work, invited to score themselves. Since a ...
Stop paying for a key nothing reads, and stop waiting to ask
Three things were slowing /messages down before a single message was fetched. Every email call made a round trip to /api/generate-otk first and sent the result...
A read clears the indicators immediately, not on the next reload
Reading a conversation updated the server and then waited for the news to come back: PUT /read commits, MediaService broadcasts a fresh count over core NATS, th...
Stop opening every folder, and stop refetching every message
Two round-trip problems on the /messages critical path, both invisible in the code that caused them. listFolders opened each folder read-only to read two integ...
Stop listing every visitor twice
Performance (web vitals) events were saved with no hostname — the collector's performance branch never passed one, unlike the pageview branch. All 803 stored pe...
Resolve a native PDF's source bytes instead of demanding a rendition
**************** required dat.convertedDat to be non-null. ConversionService only mints a second ImgDat when it actually converts something -- a document that a...
The ticket list survives a broken indicator
The unread read threw and took the whole ticket list with it — the page came back empty, which is a far worse outcome than a page with no markers on it. It is g...
Bind the system-event pattern — a brace in native SQL never reaches the database
Hibernate scans native SQL text for its legacy {alias.path} placeholders, so the inlined '{"systemEvent"%' raised QueryException: Unmatched braces for alias pat...
Clock-out indicator wears the same pulse as legal & compliance
The punch clock breathed a red radial glow while the obligations badge three pixels to its left pulsed two expanding rings. Both controls are asking the member ...
Connect DocsService to NATS so the badge lights without a refresh
LegalPendingCountPublisher takes its NATS Connection as required=false and returns quietly when it is null. The shared NatsConfig is **************** and this C...
Tint the mailbox loading sweep with the org's own colour
The /messages placeholders drew their travelling band of light from --accent-comms, the comms family accent (#6366f1), so every tenant watched an indigo shimmer...
Remove the payroll registration fields nothing reads
Six fields on the payroll cards were never consumed by anything. A registration field nobody loads is worse than a missing one: an operator fills it in, believe...
ADP takes per-org credentials, not a platform registration
ADP shipped classified PLATFORM_OAUTH on the strength of ADP publishing a Marketplace ISV model, where Kamo would hold one partner client id, secret and certifi...
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.