PHI access audit tab layout + its missing menu entry
The tab rendered its content flush against the card border: SettingsView's tab panel supplies no padding of its own, and this tab was the one manager that never...
Browsers kept serving a stale app bundle after every deploy
index.html shipped a hardcoded `libs/app.bundle.min.js?v=139` that no build ever changed, the bundle filenames are stable, and nginx sent no Cache-Control at al...
The avatar fallback URL could never resolve
Both avatar-lookup catch blocks built **************** Avatars moved to the fixed, domain-independent `platform/` prefix (SecurityService AvatarObjectPaths) whe...
Colibri-ws proxying always 502'd — nginx had no resolver
The /colibri-ws/<jvb-id>/ location builds its upstream from a capture group. nginx resolves such names at request time and only when a resolver is configured, s...
Fall back through every number the agent holds
An extension with no org line to hang it off is undialable, so the resolver falls back to a number the member actually has rather than publishing nothing.
Publish the agent's cell when it is the only number they have
An agent's number can live in any of three columns and commonly sits in only one: e_phone_number on the team member, m_phone_number and m_cell_number on the mem...
Cleaner invite mark in the chat message
The chat invite led with the video-camera emoji, which the message renderer scales to 1.4em — so it landed as an oversized colour sticker rather than an icon. R...
A dead avatar URL rendered a permanent broken image instead of initials
A participant whose photo is missing from storage showed a broken-image icon to everyone else in the call, forever — it never degraded to initials. Upstream ca...
STUN answered on the wrong node, so kamocrm.com:3478 was dead
coturn is hostNetwork with no nodeSelector, so it was scheduled on k3m1 (public 47.181.8.87). Its own --external-ip, and every client's `stun:kamocrm.com:3478`,...
Stop classifying a multipart/related HTML root as an attachment
Every transactional email we send with an inlined org logo arrived in our own /messages viewer with a correct subject and a completely empty body. isAttachment...
Bridge advertised only private ICE candidates — no meet had media for 35 days
The bridge never completed a single ICE connection in the 35 days this pod has been up (0 successes, 18 terminations). Every conference joined over XMPP fine an...
Send the company line as text, not markup
Pairs with the template fix in kamo-shared-library. Per-org template rows are insert-only, so the rows seeded before the markup change still wrap this variable ...
The opportunity templates own their own markup again
The company line was changed to arrive as a complete <p> element from the sender, so an absent company would not leave an empty paragraph. That was the wrong tr...
An approver who files a request still gets the approver email
The actor was stripped from every audience, so an approver who raised a request was cut from their own notification about it — and in an organization with a sin...
Liveness probe could never pass — cause of 920 restarts in 35 days
Root cause: the liveness probe was `tcpSocket: port 10000`, but Scylla's REST API binds to api_address 127.0.0.1 (its default) while a tcpSocket probe dials the...
Stop rounding the lead id through a JS number
Number("1189175700550025222") is 1189175700550025200 — lead ids are unique_rowid() values above Number.MAX_SAFE_INTEGER. The quotes pane converted the route par...
Carry lead ids as strings — a JS number silently corrupts them
Lead ids are CockroachDB unique_rowid() values above Number.MAX_SAFE_INTEGER: 1189175700550025222 becomes 1189175700550025200 the moment it touches a JS number....
Resync drifted manifests with live before enabling full reconciles
Auditing what a full reconcile would apply turned up two manifests that had drifted far enough from the cluster that re-applying them would have caused an outag...
Line the commission-split controls up with the text fields
The Percent/Amount and One-time/Recurring toggles rendered at MUI's default toggle height while the member picker and the share amount beside them come out at 4...
Pane owns its spacing and scroll; drop the addressee fields from the form
The lead view's content card is overflow:hidden with no padding — every pane supplies its own, as Details and History do. The quotes pane supplied neither, so t...
Review findings on the reserved list and split editor
Five defects an adversarial review confirmed against the first cut: - The page rendered "You don't have access" on every load. checkRole returns false while ...
Give the commitment and setup fee fields room for their labels
"Commitment (months)" shares its width with an info adornment and "One-time setup fee" is the longest label on its row; both were truncating.
Resolve the org's real hostname and logo extension for the letterhead
Correcting the theme URL was necessary but not sufficient — the logo still did not render, for two further reasons found in the live data. org_domains stores a...
Keep the profile heading on the current membership type
The heading reads "<Member> Profile" or "<Team Member> Profile" off the type MyAccountTab reports through onMemberTypeLoaded, which only fired from the mount-ti...
Fill the Position card the moment a member is promoted
Department, job title, official title, work location, membership status and the two Autocomplete option lists were only ever loaded inside the memberType === 'T...
Summary moves into the header, records get the full page width
The summary sat in a fixed 320px right-hand column on every record page, permanently costing a fifth of the width. On the quote editor that squeezed the line-it...
Point the letterhead logo at the path the theme bucket actually serves
The logo URL was built as **************** which that host answers with a 308 rather than an image — so every quote, sent as well as previewed, silently fell ba...
Department contact fields showed raw i18n keys
The contact block added with the bulk-email work called departments.departmentEmail / departmentEmailHelper / departmentPhone / departmentExtension, but the dic...
Deliver attached images, and stop two compose windows sharing a toolbar
AI chat attachments were never reaching the AI. AiChatInput sent the storage paths as `imageUrls`, but the REST body in AiChatWebSocketContext reads `imageObjec...
Stop tool windows losing and leaking member-typed content
Follow-up to the popup-window persistence work. Each of these was verified against real code first; three of the original reports turned out to be wrong or over...
Departments no longer open invisible on first render
The Directory tab came up empty until you switched to Chats and back. The members were always there — every department was parked at opacity 0. Sections were r...
Stop losing popup tool windows (and unsent drafts) on page changes
Tool windows lived only in a module-level in-memory store, so any full document load destroyed every open window and everything typed into it. Several internal ...
Require ACTIVATED god mode to read the trail, not eligibility
PhiAuditController.hasRight() bypassed the right check on session GD alone. GD means "may activate god mode"; godModeActive means "has activated it, deliberatel...
Selecting Quotes no longer bounces back to the first sub-tab
Clicking Quotes set the index to 2 and wrote ?sub=quotes, but the effect syncing state back from the URL mapped anything that was not "commitments" to 0 — so it...
Harden the original session-timeout stack
Review of the **************** path after removing the duplicate idle stack turned up four real defects: - sessionMonitor.start() left its 3s bootstrap setTime...
Let the stage grow so the chrome pod gets an even gap
The pod (now taller with the tone slider) becomes the stage's only in-flow child: fixed height becomes a minHeight, with 16px padding above and below the pod (c...
Retry npm ci in the Docker build against flaky runner egress
The k1m1 runner intermittently corrupts TLS streams mid-fetch **************** killing the image build in npm ci. Give npm fetch retries and retry the whole ins...
Route the transaction pipeline screen through ConsoleShell
The Pipeline steward screen was the only console screen rendered without a layout wrapper, so its heading, filter labels, and table sat flush against the consol...
Take the percent sign from Intl, not the translated string
A literal "%" in the source text does not survive machine translation — zh returned "保存 {percent}" — so non-English users saw a bare number where a percentage w...
Repair the quote-option FK defaults ddl-auto cannot reach
The existing dynamic sweep only covers nullable FK columns that already carry a FOREIGN KEY constraint. commerce_quote_options.quote_id is NOT NULL, so it is ex...
Pin option FK column definitions so they do not inherit gen_random_uuid()
Hibernate copies the referenced id's columnDefinition onto a new @JoinColumn, so quote_id and option_id were both created DEFAULT gen_random_uuid(). An insert t...
Unbreak application.yml, and replace the test that never ran
Three things, all from trying to answer "why not just fix the context test?". 1. **************** declared `kamo:` TWICE and therefore did not parse at all ...
Surface quotes in every vertical, not just retail
The Quotes tab was only wired into the RETAIL sub-tab set, so on an org whose active markets are SUBSCRIPTION / MORTGAGE / PERSONAL_LOANS there was no way to re...
Treat SERVFAIL/timeout (TRY_AGAIN) as pending, not hard error
Flaky customer authoritative servers (seen: migo.host for rodaris.md) intermittently answer SERVFAIL on healthy zones, which /setup/dns rendered as a red 'DNS l...
Slug map in a plain module — client-reference proxy made server metadata render Article Not Found
Time out the *** call instead of hanging every login
A bare `new RestTemplate()` has no connect or read timeout. When the *** service became unreachable today, every login thread blocked on this call indefinitely ...
Stop the avatar-resolver policy blocking every login
This policy took the whole platform's login offline for hours. Cilium enforces egress against the RESOLVED BACKEND, after service DNAT, so the port it matches ...
Resolve the org from the real request host, not the internal address
checkAccess resolves the tenant by looking up `org:domain:<hostname>`, and was being handed request.nextUrl.hostname — which behind Traefik is 127.0.0.1. That k...
Annotate the injectable StewardNotifier constructor
DaemonService has been in CrashLoopBackOff for days — 1654 restarts on the pod before the last deploy, 60 on the current one — and never started: Failed to i...
500s on dynamic-segment pages + en fallback for missing locale keys
Removing the global force-dynamic made routes with generateStaticParams attempt static rendering for on-demand params, which throws DYNAMIC_SERVER_USAGE because...
Like what you see shipping?
Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.