Add DEFAULT false to email_verified column definition
Hibernate's schema migrator generates ALTER TABLE without a default, failing on tables with existing rows. columnDefinition forces it to include DEFAULT false s...
Resolve duplicate emailTemplateServiceClient bean conflict
**************** and **************** were identical @Components with the same default bean name, causing **************** at startup. Delete the duplicate in r...
Bump kamo-shared-library to 1.4.0
Docker Stage 1 builds kamo-shared-library main (now 1.4.0) and installs it to the local .m2; the service pom still referenced 1.0.0 which Maven could not find, ...
Apply SP6 correctness and implementation quality fixes
C1: use NEXT_PUBLIC_H***_SITE_KEY env var instead of hardcoded placeholder C2: change RegisterResponse.userId and all API params from number to string (Cockroac...
Address 4 code-review findings in registration and login paths
- Hide raw exception message in /register 500 path; log instead - Fail-closed (503) on email-verified DB check failure in login - verifyEmailToken throws if use...
Append Z to dateCommitted so JS parses it as UTC
LocalDateTime.toString() produces no timezone designator, causing JavaScript's new Date() to treat the UTC value as local time and display timestamps 7-8 hours ...
Convert PT midnight cutoff to UTC for today-count query
Commits are stored in UTC but the cutoff was a naive LocalDateTime in PT, causing yesterday-evening PT commits (00:00–06:59 UTC) to be counted as today.
Rename mailboxId→id and providerStatus→status in mailbox list response
Align field names with frontend expectations for member mailbox listings.
Replace all CSS-filter logo instances with white SVG
Navigation, SubNavigation, Footer, SubFooter, and Preloader all used the same broken filter brightness-0 invert pattern. Replaced with logo-full-white.svg acros...
Use white SVG logo in footer instead of CSS filter
Same fix as the nav — CSS filter on img inside backdrop-filter is unreliable on iOS Safari.
Guard color-scheme with !important against theme CSS override
DynamicMetaLoader can inject remote CSS that wins the cascade. Adding !important ensures color-scheme: dark can never be overridden by theme stylesheets.
Exclude footer and nav links from TouchOptimized min-height enforcement
TouchOptimized was setting minHeight:44px on all <a> elements shorter than 44px, including footer nav links (~20px tall). This ran during hydration on hard refr...
Use pre-rendered white SVG logo instead of CSS filter
CSS filter on img inside backdrop-filter is unreliable on iOS Safari. Generate logo-full-white.svg with all fills set to #ffffff and load it directly — no filte...
Lock Tailwind dark mode variant to class-based, never OS media query
Tailwind v4 defaults dark: utilities to respond to prefers-color-scheme (OS preference). The @variant override ensures dark: classes only activate when a .dark ...
Use inline filter style on logo link for reliable white rendering
Tailwind filter classes on img elements are inconsistent across mobile browsers. Inline style on the anchor element guarantees brightness(0) invert(1) applies e...
Force dark color-scheme so browser never applies light mode rendering
Changing from 'light only' to 'dark' in globals.css, generateViewport, and the html element style — this stops the browser from rendering SVGs and native UI in ...
Prevent logo from rendering behind nav row on mobile
The div wrapper with CSS filter created a new stacking context that conflicted with the header's backdrop-filter on mobile browsers, causing the logo to paint b...
Resolve scrollbar and mobile clipping on JumpToBar and PreviewBanner
- Add overflowY: hidden to JumpToBar inner container to prevent vertical scrollbar - Allow PreviewBanner content to wrap on mobile so text isn't clipped on port...
Replace space-y-4 with inline flex gap on footer link lists
Tailwind space-y-4 uses :where() (specificity 0) which races with CSS loading on hard refresh causing inconsistent vertical spacing. Inline styles are embedded ...
Set Traefik externalTrafficPolicy=Local to preserve client IP
With the default "Cluster" policy, kube-proxy SNATs external traffic to the node IP before forwarding to Traefik. That caused Traefik to see the node IP as the ...
Add missing requestIntegration i18n key across all locales
The "Submit a request" button under the "Need a custom integration?" CTA on /integrations was falling back to the raw key **************** because the key wasn'...
Use pg Pool options instead of connection string for geo DB
CockroachDB rejects insecure connections and node-pg can't verify self-signed certs via connection string alone. Parse the URL into Pool options and pass ssl:{r...
Backlink target to www.kamocrm.com (canonical host)
The PoweredByKamo component shipped pointing at apex https://kamocrm.com/ but the canonical kamo-marketing host is https://www.kamocrm.com/. Updating all three ...
*** session check, loading spinner, rebrand analytics to Kamo Analytics
Use redis get instead of exists for more reliable *** validation on logout. Replace "Authenticating..." text with an animated spinner on the OTK auth page. Rena...
Copy GeoLite2 database to production image for country detection
The /geo/ directory containing GeoLite2-City.mmdb was built during the builder stage but never copied to the runner stage, so all country/region lookups returne...
Move CSP to proxy.ts instead of middleware.ts to avoid build conflict
Next.js 16 doesn't allow both middleware.ts and proxy.ts. The Docker build copies proxy.ts as the middleware, so add CSP frame-ancestors header there instead. T...
Clean up legacy analytics deployment on each CI run
Delete old analytics deployment, service, and ingressroute that conflict with the kamo-analytics deployment managed by its own CI/CD pipeline.
Use Next.js middleware for CSP so frame-ancestors works at runtime
The standalone build bakes next.config.ts headers at build time, so ALLOWED_FRAME_URLS was always empty. Move CSP to a Next.js middleware that reads the env var...
Strip X-Frame-Options header in iframe-compatible middleware
Set X-Frame-Options to empty string to remove the SAMEORIGIN value that was being inherited, allowing CSP frame-ancestors to control iframe embedding instead.
Read ALLOWED_FRAME_URLS at runtime so CSP frame-ancestors works in standalone mode
The env var was being read at module scope during build, baking an empty value into the standalone server. Move CSP and all header construction into functions c...
Reset document.title in rebrand() when React overwrites it
React re-applies RSC payload after hydration, resetting the title to "analytics". Add a title check inside the MutationObserver callback so it gets corrected ev...
Replace "analytics" text nodes with "Kamo Analytics" instead of clearing
Like what you see shipping?
Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.