Stop a support ticket opening a plain chat window full of JSON
Two faults, one symptom. Assignment makes the agent a member of the ticket's media session, so the incoming-message notification reached them and ChatNotificati...
Tell the client which kind of conversation a message arrived in
Every member of a media session receives the incoming-message notification, and assigning a support ticket makes the agent a member of that ticket's session. Th...
Declare the calendar tokens at :root, and rebuild the event dialog
The tokens were declared on the calendar wrapper element, which reads as the tidy thing to do and is wrong. MUI dialogs and menus render through a portal into d...
Actually override the operator label ink
The previous attempt raised specificity, which was the wrong diagnosis: tailwind.config.js sets `important: true`, so every declaration in .operator-label ships...
Rebuild the event dialog around when, not around fields
Ten identically weighted outlined fields in a column, in the order the columns happen to sit in the table: title, description, location, calendar, all-day, star...
Auto Assignment strategy, and open an assigned conversation automatically
Topics settings gains the fourth strategy. The list rows and the edit dialog share the same label, and the key shipped to kamo-translation-dictionary first — me...
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...
Widen the support topic assignment_strategy range CHECK to 0..3
SupportAssignmentStrategyType is @Enumerated(ORDINAL), so Hibernate emitted CHECK (assignment_strategy >= 0 AND assignment_strategy <= 2) on CREATE TABLE rather...
AUTO_ASSIGNMENT strategy and a durable record of an unseen handover
AUTO_ASSIGNMENT(3) is appended to SupportAssignmentStrategyType — assign immediately to an agent who is genuinely online, preferring whoever holds the least wor...
Make every line of the hero readable
The kicker and the three readout labels were painted by .operator-label's own dark ink, not by the colour set beside it: a class and an sx rule carry the same s...
Make the pinned-app eyebrow actually white
The previous attempt overrode .operator-label's ink with a class-qualified sx rule, which could never have worked: tailwind.config.js sets `important: true`, so...
A pinned app's chip launches the app, not its settings
The leading chip of a pinned band was linking to the app's settings landing — the same place its first entry already goes. It now borrows that app's nav option ...
Restore CRLF endings on the three session files
The previous commit rewrote them with LF, inflating a ~56-line change into a 700-line whole-file diff. Content is unchanged; this puts the endings back so the h...
One writer of the *** TTL, and it is the activity tracker
/api/user-info wrote the session TTL straight to Redis, bypassing every service-side rule — and useUserInfo polls it every five minutes forever, so that one lin...
Reading a session no longer renews it
The expiration on the Redis record IS the session; when it lapses the member is signed out. This service holds its own copy of KSessionService against that SHAR...
Reading a session no longer renews it
The expiration on the Redis record IS the session; when it lapses the member is signed out. This service holds its own copy of KSessionService against that SHAR...
Reading a session no longer renews it
The expiration on the Redis record IS the session; when it lapses the member is signed out. This service holds its own copy of KSessionService against that SHAR...
Make reads read-only, leaving one writer of the *** TTL
The expiration on the Redis record IS the session: when it lapses the member is signed out. Reading a session no longer touches it. Only genuine interaction ext...
Sync the organisation calendar to phones, without opening a hole
The shared calendar has no owner, so the account-scoped DAV listing could never return it: company events were plainly there on the web and invisible on every p...
Refresh planner statistics after the weekly GeoLite rebuild
YugabyteDB does not auto-analyze, and the staging+rename swap replaces geolite_blocks wholesale -- so after every Sunday sync the planner had no statistics for ...
Add and backfill accounts.date_created
Hibernate cannot add this one itself: ddl-auto emits it NOT NULL, which CockroachDB refuses on a table that already has rows. So it is added nullable here, back...
Return the account's creation date to the account list
buildAccountSummary never emitted dateCreated, so the field the list's Date Created column reads was simply absent from the response. Now that Account records t...
Record when an account was created
Account carried no creation timestamp at all — not a null column, no column. The account list has a Date Created column and orders by it, so that column has bee...
Pin an Enabled App to the home launchpad
Each Enabled Apps topic now carries a pin toggle, in the Settings sub-option menu and on its section header on the settings landing page. A pinned app gets its ...
A live chat is claimed through the popup, never allocated
Routing chat requests through round-robin was the wrong model and it broke the thing it was meant to fix. An assigned ticket leaves the claimable queue (Support...
Geolite range index must be ASC, not YugabyteDB's default HASH
The IP lookup is a range scan: WHERE network_start <= ? ORDER BY network_start DESC LIMIT 1 YugabyteDB partitions the LEADING index column by HASH unless tol...
Geolite range index must be ASC, not YugabyteDB's default HASH
The IP lookup is a range scan: WHERE network_start <= ? ORDER BY network_start DESC LIMIT 1 YugabyteDB partitions the LEADING index column by HASH unless tol...
Give Mobile Copilot setup its own full-width page
The phone-provisioning surface was the third tab of the Interaction Center slideout, which capped it at a 500px rail — too narrow to show the install code and t...
Rebuild the calendar around the current moment
The page was a functional grid with the chrome doing the talking: a 3px rainbow rule under the toolbar, a second one over the content, gradient buttons, and fou...
Move calendars onto memberships and give each org a shared one
Calendars and events were owned by an account and carried no organisation. This attaches each to its owner's earliest membership — the organisation the account ...
Take the caller from the session, not from the query string
GET /api/calendar/calendars took userId as a request parameter, so changing a number in the URL read anyone's calendars — and because calendars carried no organ...
Scope calendars to the member, and add the org-wide publishing right
UserCalendar and CalendarEvent hung off USER_ID alone and carried no organisation. A user is global and a member is that user inside one organisation, so an acc...
Stop assignment failures destroying the ticket that triggered them
Routing a new ticket ran inside the creation transaction, so anything it hit rolled the ticket back with it and the member asking for help got "Failed to create...
Give each account tab the default order it should open in
The three tabs opened in whatever order the API happened to return, which for members meant the newest sign-ups were buried and for team members meant no order ...
Stop BUSY surviving every future login
Logout writes AWAY and login clears it, so AWAY is a state the system puts you in and takes you out of. Nothing ever cleared BUSY. A member who set it once stay...
Route a chat request through the topic's assignment strategy
A support chat request is filed as a PRE_TICKET, and createTicket skipped assignment for those outright. The guard was written for the web-chat widget, where a ...
SecurityService pool exhaustion caused liveness kills
Hikari had no explicit maximum-pool-size, so it ran on the default of 10 while fronting org/rights lookups for every service and the internal site. Observed tot...
Scope the default-lead-source readiness banner to Residential Mortgage markets
The vendors/products tab showed the "Finish the mortgage vertical to designate a default lead source" warning on every market tab, including Product/Service and...
Centre the selection bar on the contact list, not the page
The bar that appears when rows are selected is absolutely positioned at left 50% with a translateX(-50%), but its nearest positioned ancestor was the whole page...
Give YugabyteDB real resources and pin its memory
It was running on LESS than the CockroachDB it replaced -- 20Gi/6cpu against CockroachDB's 32Gi/8cpu -- while needing more, because YSQL runs a separate Postgre...
Give YugabyteDB real resources and pin its memory
It was running on LESS than the CockroachDB it replaced -- 20Gi/6cpu against CockroachDB's 32Gi/8cpu -- while needing more, because YSQL runs a separate Postgre...
Make MKCOL create a book that can actually be stored
mkCol built a ContactBook carrying neither an organisation nor an owner and returned 201 regardless, so creating an address book from a CardDAV client failed at...
PublicChatApiKey.scopes jsonb binding
A field with an initializer was skipped by the earlier jsonb sweep, so this one still bound as varchar: 'column scopes is of type jsonb but expression is of typ...
Stop defaulting new contacts into the shared org book
The create dialog targeted the book flagged isOrgDefault, so every member's contacts landed in the one book the whole organisation could read — half of why the ...
CockroachDB-only SQL that PostgreSQL rejects
CockroachDB spells the text type STRING; PostgreSQL and YugabyteDB use TEXT. 25 casts across native queries were still emitting CAST(x AS STRING) and ::STRING, ...
CockroachDB-only SQL that PostgreSQL rejects
CockroachDB spells the text type STRING; PostgreSQL and YugabyteDB use TEXT. 25 casts across native queries were still emitting CAST(x AS STRING) and ::STRING, ...
CockroachDB-only SQL that PostgreSQL rejects
CockroachDB spells the text type STRING; PostgreSQL and YugabyteDB use TEXT. 25 casts across native queries were still emitting CAST(x AS STRING) and ::STRING, ...
Like what you see shipping?
Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.