Unwrap catalog and calculation from backend response envelope
getSubscriptionCatalog returned { catalog: {...} } but was cast directly as SubscriptionCatalog, leaving catalog.plans undefined and the plan selection step bla...
Add @JsonProperty to is*-prefixed boolean DTO fields
Lombok generates isXxx() is-getters for boolean fields named isXxx. Jackson strips the leading 'is' from is-getters and serializes them as 'xxx' rather than 'is...
Use ss instead of fuser to kill stale port-forward (fuser not on k0m1)
fuser and lsof are not installed on the runner host. Use ss -tlnp with grep to extract the PID holding port 18080 and kill it directly. Also switch pkill to SIG...
Clean up stale port-forward so cancelled translate job doesn't block next run
Bash doesn't forward signals to backgrounded processes, so kubectl port-forward outlived cancelled workflow runs and held port 18080, blocking every subsequent ...
Restore all broken placeholder values across pages
Salvage-keys script had grabbed CSS classNames, inline styles, and JS template literals instead of the original English text for 114 message keys spanning notes...
Restore leads page hero title and subtitle from git history
heroTitle was 'Hero Title' (placeholder), heroSubtitle was 'flex gap-2' (salvage-keys accidentally grabbed the adjacent CSS class name). Correct values recovere...
Enable Finish button by polling widget.getState() and switching to auto=onload
The statechange event listener was not reliably enabling the Finish button after *** verification. Two root causes: 1. The drain logic read widgetAny.state whi...
Include subscription-targeting accounts in org list
listForOrg now also returns accounts whose subscriptions target the requested org — not just accounts directly owned by it. In the multi-org model the paying Ac...
Add statusWindow labels namespace and fix all setting placeholders
- Add **************** (50 keys) so the settings nav sidebar shows real text instead of key paths - Fix branchTypesLabel ICU format: \${branchLabel} → {branch...
Match other tool windows' size + color scheme
- defaultSize and minSize now 320x650, resizable: false (matches Softphone, Chat, Calculator, SMS, AI Chat) - Switched from dark slate gradient to the standard ...
Forward Range header so audio playback can scrub
Without this the VOIPService recording-streaming endpoint always returns the full file (Range header is dropped by buildForwardHeaders), which works for play-fr...
Rewrite /etc/odbc.ini to point at $MARIADB_HOST on every boot
The escomputers/freepbx:17 image bakes /etc/odbc.ini with Server=db (the docker-compose link target). On this Kubernetes deployment MariaDB lives at \$MARIADB_H...
Resolve member→extension before VM/CDR provider lookup
CallController was passing memberId where FreePBX (and other PBX-style providers) expect an extension number — voicemail listing returned empty because no PBX e...
Auto-assign first seat, Free as floor, broader org invalidation
BillingSetupService now activates the first open license slot for the creator when seeding a sub-org subscription (and same for promote-to-billing-owner) — othe...
Top-level org members get platform-owner plan, bypass billing gates
KamoCRM (top-level) org members are not subject to the billing system — they get the OWNER_UNLIMITED plan's feature matrix outright (with Free as a defensive fa...
Top-level org bypass + Free baseline fallback for orgs without subs
The org-level entitlement check **************** walks subscriptions targeting an org. With the new target_org model, orgs that don't yet have a targeting Accou...
Remove redundant Field history title from history panel
Tab label already conveys context — title and subtitle were wasting screen space. Reload button moved inline into the toolbar.
Remove layout prop causing email body bouncing
The outer motion.div's `layout` prop fought with the inner AnimatePresence height: 'auto' animation, creating a FLIP feedback loop on emails with unstable heigh...
Resolve duplicate column mapping by overriding embedded address columns to MAILING_*
Update RetailService and provider adapters for Account.notes removal and CurrencyType conversion
Always show Create Document button on doc manager page
Removed the getMemberId() > 0 guard that was hiding the button during the useUserInfo loading window. The page is already behind auth so no client-side membersh...
Restore organization import removed by accident
organization.id is still needed in the handleCreateDocument request body; only the isDocsEditor condition should have been removed.
Show Create Document button to all logged-in members
The org feature flag check (isDocsEditor → isDocs → hasFeature DOCS) was returning false because org features use deprecated key types. The button is now shown ...
Remove datagrid field-level filters and floating filter row
Disabled all column filters and the floating filter input row so the grid shows only column headers and data rows. Also removed the Filters tool panel from the ...
Move Upload button into DocManager toolbar
The Upload trigger was only in the /doc/manager page's actions prop, making it invisible when DocManager is embedded in other pages. Moved the Upload button dir...
Allow upload options to scroll in embedded DocManager
Uploads tab container was overflow:hidden, clipping per-file options (description, folder, doc type, access level) in height-constrained embedded contexts. Chan...
Fix 400 feed error and add communications sub-tabs with URL params
Fix double-? bug in MediaStream where feedEndpoint already contained query params but the fetch appended ?page=... instead of &page=..., causing a malformed URL...
Make 'All Leads' a real menu item with icons in agent filter
- Replace placeholder empty-value item with __ALL__ so the dropdown never shows blank when All Leads is selected - Add Group icon to All Leads and PersonOff i...
Consume *** secret so X-Internal-Auth matches downstream services
DaemonService -> ConversionService **************** was returning 401 Unauthorized because DaemonService was stamping its X-Internal-Auth header from INTERNAL_A...
Use @CreationTimestamp(source=DB) on ****************
The DB is the single source of truth for timestamps in this codebase. The canonical Hibernate pattern is @CreationTimestamp(source = SourceType.DB), which makes...
Let DB fill **************** via @Generated(INSERT)
INSERTs were failing with: null value in column "date_created" violates not-null constraint @ColumnDefault only declares the DB-side default for new rows; Hi...
Drop the [from-internal-custom] _X. catch-all that broke softphone calls
The catch-all exten => _X.,1 in [from-internal-custom] was intercepting every internal dial — softphones started reporting "phone is not registered" / calls wou...
Enable JPA repos for commerce + email + dao.repositories packages
ConversionService new pod CrashLoopBackOff with the same error DaemonService hit earlier: Parameter 0 of constructor in **************** required a bean of ...
Carve /api/voip/recordings/** out of the wildcard VOIP forwarder
The /api/voip/** catch-all in APIGatewayController was shadowing the dedicated VoipRecordingUploadController POST /api/voip/recordings/upload mapping when Sprin...
Write managed config files 0644 so the asterisk daemon can read them
The kamo-asterisk-support pod runs as root and writes to host-mounted **************** Asterisk inside the FreePBX pod runs as user "asterisk" and could not rea...
Use envsubst-compatible \${VAR} syntax in config template + re-render on stale placeholders
Pods were CrashLoopBackOff with "config errors: API_KEY is missing or too short" because the config template used literal __API_KEY__ markers that envsubst sile...
Drop unused watcher import
uploader.go only uses CallBatch (declared in grouper.go in the same package), not anything from internal/watcher directly. Go rejects unused imports.
Enable JPA repos for commerce + email + dao.repositories packages
DaemonService crashed on startup with: Parameter 0 of constructor in **************** required a bean of type **************** that could not be found. A r...
Capture newExtNumber as final for lambda capture in MemberVoipConfigController
newExtNumber is conditionally reassigned inside the if (isVoipEnabled && ...) block, which makes it not effectively final. The TeamMember sync block reads it fr...
Update OrgThemeProvisionServiceTest for buildConfigJson description parameter
Cast voiceActivityDetection to bypass missing TS DOM type
voiceActivityDetection is a valid WebRTC MediaTrackConstraints property but is absent from TypeScript's DOM lib, causing a type error at build time.
Configure STUN so browser ICE can complete bidirectionally
Two-party browser-to-browser calls connected at the SIP layer but had no audio either direction. Voicemail (one-way Asterisk → browser) worked because Asterisk'...
Live audio that survives load-interrupts, centered spinner, outbound ringback
Three coordinated fixes for the in-call audio path: 1. AbortError on remoteAudio.play() (visible in production console as "The play() request was interrupte...
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.
