Remove standalone Applications icon — LOS lives under Commerce
The mortgage application pipeline is one vertical of the commerce system, not a top-level nav. Loan officers, processors, and underwriters reach it via Commerce...
Resolve ambiguous /org/domain handler — Commerce nav was disappearing
SecurityController had a second **************** that collided with **************** Spring rejected the request with "Ambiguous handler methods mapped" → 500 →...
Flatten add-item menu so Generated Docs are reachable
The "Add Generated Doc" submenu approach didn't work: clicking the menu item closed the parent menu, which unmounted the MenuItem before the nested Menu could a...
Drive journey sky from SkyToggle, unstack from personality chip
- Move SkyToggle to its own top-right row at top-14 so the slider stops overlapping LoGuideChip, which is positioned at right-14 assuming it only needs to c...
Stop double-appending render query string; add share + meta dialogs
Render fix: - **************** was manually appending ?inline=true to apiPath, but forwardToApi already preserves the incoming query string. The duplicated quer...
Include com.kamo.z.shared.binder in @EnableJpaRepositories
DocsService boots with an explicit basePackages list, not classpath scanning, so BinderRepository wasn't being discovered — startup failed with "No qualifying b...
Lift home CTA cluster above the LenderFooter
Buttons at bottom-12/sm:bottom-14 were clipped by the lender attribution footer (~76px tall on desktop). Bumped offsets so the cluster clears it.
Stop personality chip overlapping the SoundToggle
LoGuideChip was absolutely positioned at top-3/right-3 in JourneyHero and JourneyApplyLayout, the same spot as the global SoundToggle in app/layout.tsx. Shifted...
Stop racing hydration with a 404 — render the logo URL that actually exists
The tenant MinIO bucket holds logo-full.svg / logo.svg as canonical names; nobody uploads the -on-dark variants. We were trying the dark-mode URL first, 404'ing...
Unwrap SecurityService's nested color wire-format so tenant brand vars actually populate
SecurityService returns Organization with colors nested inside an EmbColorPalettePair ({ colors: { colorPri: { colorPri, colorLight, ... } } }) and stores hex w...
Render the logo img on the SSR pass — no more wordmark-only flash
ThemeLogo's empty-string initial logoSrc + useEffect-to-fill pattern meant the SSR render returned the wordmark fallback, then hydration populated the src. If a...
Kill fake-tenant defaults, render the actual org's branding only
Removes the Apex Mortgage demo I should never have added and the Kamo "default" fallback I replaced it with. Both were just papering over a missing-tenant condi...
Ship default logos so unbranded hosts render a real lockup
Ported ThemeLogo dropped the local-file fallback the kamo-internal original had, so any host whose tenant MinIO bucket hadn't been provisioned (or doesn't exist...
Preserve aspect ratio on sky atmospherics so clouds + sun + birds don't stretch on portrait
CloudsLayer, BirdsLayer and the sun/star portion of SkyLayer were using preserveAspectRatio="none" so on a tall portrait phone the SVG coordinate system stretch...
Mobile portrait tuning for hero illustration + chrome
On a portrait phone the 100x60 viewBox of every layer was being stretched into a tall narrow rectangle, which made the home and foreground look squashed and wei...
Illustration wrapper had no height — every layer rendered into a 0px strip
The JourneyIllustration root div was `relative overflow-hidden` with no explicit dimensions. Its parent was sized via absolute inset-0, but the relative child o...
Sky no longer washes to white — golden-hour default + tuned sky shader
Sky was reading white because: - toneMappingExposure 1.05 + Bloom@0.45 with luminanceThreshold 0.72 was blowing the bright procedural sky into the bloom buffe...
Post-porch borrower lands in the 3D world (/journey/persona then /journey), not the legacy MUI wizard
Reward gate + auto-resume now route to /journey/persona?app=<uid>, persona pick lands in /journey?app=...&persona=..., and a persistent 'Continue your applicati...
Welcome-back gate must only trigger for true returning visitors
Brand-new visitors were hitting the welcome-back gate the moment they entered their name, because hasPriorProgress was recomputed from current state on every re...
Default flow + remove isDone-only auto-advance to estimate
The real bug behind users landing on the estimate-reveal screen even after "Start over": the flow engine returns DONE when state.flow is null (no flow chosen → ...
Force-dynamic so fresh deploys aren't masked by cached HTML
The homepage was statically prerendered (○ / in the build output), which means the same HTML — and its embedded references to specific chunk hashes — was served...
Welcome-back gate + always-available "Start over"
Returning visitors with persisted IDB state were being dropped straight into whatever stage they last reached — including the estimate-reveal screen, which (wit...
Align Dockerfile with kamomarketing pattern (node:24-alpine, 2-stage)
CI build failed in node:20-alpine on `npm ci` because npm 10.8 (bundled with Node 20) resolves Next.js's @swc/helpers peerDep (>=0.5.17) to 0.5.21 while the loc...
Bypass service worker for attachment + inline-image fetches
Clicking an <a download> attachment row navigated to the file instead of downloading it. The email service worker was intercepting every /api/email/* GET, inclu...
Resolve cid: inline images at sanitize time to stop signature flicker
Cid: rewriting was happening in a post-commit useEffect, so the sanitized HTML hit the DOM with literal src="cid:..." and the effect mutated each img on the nex...
Resolve subdomain-tenant org bucket to its own MinIO folder
getThemePath() was reducing the hostname to apex+tld for both the themed host and the bucket folder, so subdomain tenants like gnosia.demo.kamocrm.com loaded th...
Resolve subdomain-tenant org bucket to its own MinIO folder
getThemePath() was reducing the hostname to apex+tld for both the themed host and the bucket folder, so subdomain tenants like gnosia.demo.kamocrm.com loaded th...
Route NavTop picker through /me/language
The picker called the generic member PUT, which SystemUserGuard 403s for the System User signed into a sub-org. The catch logged silently, so the kamo-locale co...
Add /me/language endpoint that bypasses SystemUserGuard
The NavTop language picker did nothing for the System User signed into a sub-org: PUT **************** runs SystemUserGuard first, which 403s every System-User ...
Resolve subdomain-tenant org bucket to its own MinIO folder
getThemePath() was reducing the hostname to apex+tld (mainDomain.tld) for both the themed host AND the bucket folder. For subdomain tenants like gnosia.demo.kam...
Stop clipping dark-variant color inputs in ModernColorGroup
Color picker rows had a hardcoded 280px wrapper inside a 1fr 1fr grid with overflow:hidden, so the input was chopped on narrow columns. Use flex:1 + minWidth:0 ...
Treat thrown subscription stub as no-subscription, not error
The legacy getCurrentSubscription stub throws by design so callers fall back to the ungated path. StatsManager was surfacing the throw as "Could not load subscr...
Return empty meters instead of null from getCurrentUsage
StatsManager rendered <UsageMeters usage={null}> when the legacy stub resolved to null, crashing on usage.meters. Return { meters: [] } so the component takes t...
Gate My Account slide-out section on CONFIGURE_SYSTEM
Hide the "My Account" menu from members who lack CONFIGURE_SYSTEM so they don't see links (Stats & Costs, Apps & Features, Branch Types, Automation Streams) tha...
Auto-route child-org owners to their permitted org
When /settings/account loads for a user who lacks CONFIGURE_SYSTEM on the current org, the previous behavior was a silent redirect to /settings — a dead-end for...
Use full FQDN, not eTLD+1, when fetching org by domain
registrableDomainFromAlias strips any multi-label subdomain (e.g. "gnosia.demo.kamocrm.com") down to its eTLD+1 ("kamocrm.com"). That was fine for the API base ...
Preserve full FQDN for subdomains deeper than two labels
organize_by_root() was extracting only the first label and the last two labels from each Traefik-logged hostname. For the common two-level case (login.b11capita...
Never gate Kamo-owned subdomains on TXT ownership
Child orgs that picked a Kamo web alias (e.g. gnosia.demo.kamocrm.com) were getting "TXT record found but verification code doesn't match" in the DNS setup UI. ...
Don't show global loading overlay for client-handled forms
NavigationInterceptor's submit listener treated any form whose form.action was truthy and method=get as a navigation, and called setLoading(true) on the global ...
Grant top-level org owners cross-org delete/update access
deleteDomain and updateDomain previously rejected platform admins operating on child-org domains because they checked isUserOwnerOfOrg against the target org di...
Allow deleting per-org *.kamocrm.com subdomains
The endsWith(".kamocrm.com") guard blocked every demo org from swapping its platform subdomain (e.g. gmosia.demo.kamocrm.com) for a custom domain. The platform ...
Advertise new public IP 47.181.8.83 for external media
JVB-k1m1 was advertising 75.83.113.11 and coturn was advertising the node's LAN IP via status.hostIP — both broke external WebRTC media now that the public WAN ...
Guard admin-essential rights + re-seed roles on template edit
HIGH: **************** now refuses to persist a NUKE or FORCE_NUKE setting on any of the ADMINISTRATOR template's admin-essential rights (CONFIGURE_SYSTEM, MANA...
Propagate child-org-creator admin status to parent-org membership
When a user creates a child org they become its owner + admin (via **************** Their PARENT-org membership, however, is whatever it was before — typically ...
Wrap toolbar and shrink search/date so New Event stays on-page
Toolbar packed too much fixed-width content into a single non-wrapping flex row; with the parent main area set to overflow: hidden, the right section (New Event...
Read *** from master after session refresh to avoid replica lag
The previous fix had /api/user-info call /api/security/session/refresh before reading Redis, but the read went through readKsemJsonFromRedisWithRetry which uses...
Track tab by name + refresh session before reading user-info
Two related navigation bugs that both manifest as "the wrong tab opens": 1. SettingsView tracked the active tab by *index*. childrenArray can recompose ...
Replace heredoc with grouped echos so YAML literal block parses
The /etc/odbc.ini heredoc body sat at column 1, which dedented out of the surrounding startup.sh: | literal-block scalar and broke `kubectl apply` of the Config...
Follow rclone remounts via HostToContainer mount propagation
Without slave propagation the pod captures the FUSE bind mount once at container start; if rclone-mount.service restarts on the host, the pod keeps pointing at ...
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.
