Keep the is-prefix on PlatformAccountSummary's wire names too
Same Lombok/Jackson hazard as PlatformOrgRow: isTopLevel() loses its `is` on serialization, so the DTO put `topLevel`/`platformProduct` on the wire while the fr...
Declare security matchers explicitly before the next build breaks startup
kamo-shared-library 1.5.0 was republished today with spring-ws-core as a new transitive dependency, so Spring Boot now auto-registers a second servlet (MessageD...
Keep the is-prefix on the wire for isTopLevel/isPlatformProduct
Lombok generates isTopLevel() for a `boolean isTopLevel` field and Jackson strips the `is` prefix, so the live endpoint was serializing `topLevel` and `platform...
Grandfather orgs already running a gated commerce market
Gating MORTGAGE behind MLOS made the gate unsatisfiable for tenants: MLOS is still PLANNING, and FeatureController.enable refuses a non-COMPLETED app for a chil...
Declare security matchers explicitly so the service can start
The service has not deployed since 2026-07-03; every pod since has crash-looped before the context loaded: This method cannot decide whether these patterns a...
Seed app entitlement for every root, and stop inventing plan tiers
Two defects found by checking prod before flipping kamo.entitlement.fail-open. Sign Pink is a second entitlement root (isPlatformProduct, with its own FREE/BUS...
Raise the Next body cap that was truncating every large upload
THE cause of the failing 3 GiB attachments, and it was ours, not the network. **************** was '500mb'. It is not a rewrite/middleware setting: Next wraps ...
Fail a dead upload in minutes instead of holding it for an hour
connectionUploadTimeout is the tolerated SILENCE between reads, not a budget for the whole transfer. Setting it to an hour to 'match Traefik' confused the two: ...
Stop a dead upload spinning forever, and say what 100% means
A stalled upload sat at 100% with the bar full and no way out. Three separate reasons, all of them mine. XMLHttpRequest has no useful read timeout: when bytes ...
Let an in-flight upload finish instead of dying on a rollout
A 2 GiB chat attachment reached 100% and then failed with 'Bad Gateway' because a deploy landed on top of it: the pod took SIGTERM at 03:34:36 and the transfer,...
Make a failed upload say what happened, and log enough to diagnose it
A 2 GiB attachment failed at the end of a four-minute transfer with 'Upload failed: upload failed Internal Server Error' — a doubled prefix wrapped around a mes...
Stop Tomcat's 60s connection timeout killing a long upload
A 2 GiB chat attachment failed after nearly four minutes of successful transfer with MultipartException wrapping a bare SocketTimeoutException, and the member w...
Apply custom status labels to the status tabs
Every other status display on /leads resolves its description through resolveLabel() from useStatusLabels — the grid cell renderers, both filter dropdowns, and ...
Stop the 60s entrypoint read timeout capping uploads
respondingTimeouts.readTimeout is the deadline for reading a WHOLE request, body included, and Traefik v3 defaults it to 60s where v2 had no limit. That silentl...
Stop the runtime theme sheet whitening the canvas on light-mode machines
DynamicMetaLoader appends theme.<domain>/css/globals.css to <head> after our own stylesheet, and that file still carries create-next-app boilerplate: :root{--ba...
Report user idle time so an abandoned tab can expire
The client activity tracker only ever gated whether we asked to extend; it never told the backend anything. SecurityService renewed the session TTL on every req...
Only slide the *** TTL when a human is actually there
getSession() refreshed the Redis TTL on every read, and OTKPreAuthFilter resolves the session before any controller runs — so every API call renewed the session...
Leave the individual out of a department signature too
A message sent from a department mailbox is written by the department: the reply lands there, not with whoever typed it, so signing it with a member's name and ...
Stop next/image breaking every proxied logo preview
The org branding screen **************** showed the full and simple logos as missing images even though the very same files render fine everywhere else in the a...
Pin the remaining hostPath workloads to the node holding their data
Same fault as embedding-model, found by auditing every hostPath volume in the repo. A hostPath is node-local and nothing replicates it, so an unpinned pod can b...
Sort departments alphabetically
The roster rendered department sections in whatever order the backend returned them. Sort the section keys A→Z (locale-aware); member order inside each section ...
Catch OptimisticLockException, the type 40001 actually wraps as
Round 3 review fix: hibernate-core's **************** tests LockAcquisitionException (what SQLState 40001 converts to) against four specific types in order, non...
Stop the first list row wearing a permanent focus ring
is but hide its ring until j/k is actually pressed; the first press just reveals it in place, and changing folders hides it again.
Share the accept-popup snooze across tabs, and stop a poll race clearing a live offer
Pin to the node its model weights are actually on
The model is a hostPath under /var/lib/embedding-model on k1m1, and nothing replicates it. When k3m1 joined, the new ReplicaSet's pod was scheduled there and ne...
Catch the exception type the claim conflict actually throws
Round 2 review fix: the statement-level 40001 (the common case, detected inside executeUpdate() rather than at commit) surfaces as **************** via Hibernat...
Stop the mailbox pointer from failing startup platform-wide
DepartmentService is a @Service, and every service carries @ComponentScan("com.kamo"), so all ~40 of them construct it. Giving it a MailboxRepository therefore ...
Return 409 on every lost claim race, add manager claim path
Round 1 review fixes for the accept-popup claim endpoint: - an ordinary lost race (loser's isClaimableBy already false post-commit) now raises TicketAlreadyCl...
Scan the email repositories DepartmentService now needs
MediaService CrashLooped on every pod since shared-lib 1.5.0: DepartmentService is a @Service, so the wildcard @ComponentScan("com.kamo") builds it here whether...
The expiry sweep ran with no transaction
@Transactional is applied by a proxy and sweep() called expireDue() on this, so the annotation was inert. The expiry notices read the envelope's organization do...
A party who already signed gets their copy, not the document again
The session always started at "welcome", so a signer following the link in their completion email — or simply reopening the invitation — was walked through the ...
Keep co-borrowers on one routing order
deriveSigners numbered borrowers 1, 2, 3… as a display index. ESigService now ENFORCES routing order instead of merely reporting it, so leaving the counter in p...
Close out the signing lifecycle — notices, routing, guards, expiry
Everything after a signer presses Finish was incomplete. Notices: an envelope's last signature produced a flattened PDF in MinIO that only the final signer eve...
Match the TypeScript DTOs to the Java ones they proxy
/api/webinar/* is a passthrough, so every TS field name that drifted from the Java DTO silently read as undefined instead of failing to compile. The settings ta...
Populate the Quick Tips and use the shared help primitives
The scheduled-support tips rendered four placeholder strings ("How Step1"…); replace them with real guidance covering the type → presenters → slots → reminders ...
Compose from the mailbox you have open, and offer every one you can access
New Message opened the composer on the member's default mailbox: only onBehalfOf was passed, and only for another member's mailbox, so a personal or shared mail...
Stop losing organizations to swallowed exceptions, and accept the full create payload
createOrganization could destroy a customer's signup and report nothing useful. Transaction integrity: - Five Docstors ran behind try/catch that only looked sa...
Encode the decoded token exactly once on the way upstream
21670e5 routed SocialWebhookController through UpstreamUri's FULLY-PRE-ENCODED entry point, but its URL is a hybrid: `token` is an @PathVariable, so Spring hand...
Make the create-account form tell you what happened
Creating an account from a lead appeared to do nothing. The server was returning a 500 (see the AccountAddress fix in kamo-shared-library), but the only error U...
Make the create-account form tell you what happened
Creating an account from a lead appeared to do nothing. The server was returning a 500 (see the AccountAddress fix in kamo-shared-library), but the only error U...
Make account creation atomic, org-scoped and rights-gated
createCustomer saved the Account before writing its addresses, and was not transactional — so when the address insert failed, the half-built Account stayed comm...
Keep the right-click menus inside the viewport
Right-clicking a folder low in the sidebar opened its menu below the fold. The flip-at-the-edge logic was there but never ran: the component returns null until ...
Stamp AccountAddress dates so an address can actually be saved
DATE_CREATED is NOT NULL with a DEFAULT now(), but nothing ever set the field. Hibernate names every insertable column in its INSERT, so it sent an explicit NUL...
Forward the caller's query bytes on the public-facing proxies
The gateway stopped double-encoding forwarded query strings in 3c24d32, but four other proxies in this service still concatenated already-percent-encoded bytes ...
Stop a menu click on an open settings page from bouncing back, and repair the dead tab links
Clicking Apps & Features (or Stats & Costs) while /settings/account was already open landed on the tab you came from. Next.js swaps the query string without rem...
Like what you see shipping?
All of it arrives in your workspace on its own. Start on the free plan and read this page again in a month.
