Say plainly why every JustCall agent reads as ACTIVE
The user listing decided its status with "available is Yes or No -> ACTIVE, else UNKNOWN", which is a roundabout way of asking whether JustCall answered at all,...
Stop the inline image toolbar re-rendering on every scroll frame
measure() runs on each scroll and resize event and built a fresh state object every time, so the toolbar re-rendered whether or not anything about the image had...
Wire JustCall in through the phone provider abstraction
JustCall (api.justcall.io/v2.1) as a full PhoneProvider: call history, texts, voicemail, recordings, the agent directory and availability, plus signed account w...
Internal endpoint for importing contacts from an external system
VOIPService's JustCall integration needs to land a customer's contacts in the right member's address book, and this is where contacts are written: a Contact map...
The Desktop size tooltip no longer covers its own options
The Tooltip wrapped the whole TextField, so it anchored to the same box the select's option list opens over — at the default bottom placement it landed directly...
Add JUST_CALL as a phone provider type
Appended at ordinal 5. **************** is EnumType.ORDINAL and carries no CHECK constraint, so appending is safe and inserting anywhere else would silently re-...
Give next build 8 GB, it has been thrashing against 4
Builds went from 7-9 minutes to 30+ a few commits ago and nobody had a reason why. Measured on the runner rather than guessed: `next build` sat at exactly 4.39 ...
Rebuild against kamo-shared-library 8dc3ea4c
Picks up entitlement-cache invalidation on comp provisioning. This service owns both halves: it approves the order and it serves the cached entitlements, so wit...
The upgrade offer no longer chases comped organizations
The pill suppressed itself for coverage.source === 'PAID' and nothing else, so a comped organization was shown "33% off your plan" — a discount on a price it do...
Comping an account now drops its cached entitlements
SecurityService answers /api/security/entitlements/me out of Redis with a 15-minute TTL, invalidated by messages on kamo.entitlements.invalidate. Every self-ser...
Rebuild against kamo-shared-library 31b72fe9
Picks up the draft-order reprice fix: changing a draft's seat count or billing cycle left every money field and line item describing the order's previous shape,...
Editing a draft order's seats or cycle now reprices it
updateDraftOrder set seatCount and billingCycle and saved. Both are price drivers, and neither the order's money fields nor its line items were touched, so the ...
A paper colour per block, and blocks that fit their text
BLOCKS NOW FIT THEIR CONTENT. The reader's blocks were all 200px tall whatever they held, because richTextExtension configures the editor with minHeight: 200px ...
Add the JustCall provider logo
The VOIP logo folder had FreePBX, Microsoft and RingCentral but no JustCall mark, so any surface listing JustCall as a provider had nothing to render.
Rebuild against kamo-shared-library 63827887
Picks up the comp-provisioning fix. A comped order granted its plan and none of the add-ons it sold, because provisionCompSubscription never wrote active_addon_...
A paper colour per block
**************** holding a palette ID — "lemon", "glass" — and never a hex value. Stored the way notes and launchpad panes store theirs, for the reason that ma...
The order wizard must name the organization it entitles
The wizard collected a customer and never a target organization, so every order it wrote carried target_org_id NULL. On approval provisionCompSubscription falls...
A comped order now grants the add-ons it sold
Comping an account granted the plan and nothing else. provisionCompSubscription copied plan, seats, cycle, source and status onto the AccountSubscription and ne...
Never send a cid: the message is not carrying
Completes the inline-image work that landed inside b08f3b34, whose message describes only the KB and sales-scripts fix it was committed alongside. extractInlin...
ReadOnly now actually stops you typing
REPORTED: the script blocks in the Interaction Center are editable. They were, and so is every other "read-only" rich-text surface in the app. `readOnly` on Kb...
Let a sent message carry images inside its body
The body had four possible shapes and send() could only build three. The multipart/related branch — the one that puts an image where the HTML's cid: points at i...
The org's colour, not indigo, and a real scrollbar
THE PURPLE WAS A HARDCODED ACCENT. Every tinted surface in the panel and the Sales Scripts pane drew from --accent-comms (#6366f1), so a white-labelled org got ...
Do not mail a tenant its own domain until that domain is verified
A domain typed into the create form is a CLAIM, not a host. Ownership is proven by a DNS TXT record afterwards and a certificate is issued after that, so betwee...
Stop a failed welcome email from destroying the member
MemberCreationService documented steps 4-6 as best effort, and for the emails it was not true. sendVerificationEmail is @Transactional, so it joined the member-...
Restore the transaction the attachment overload left behind
baf3c88 added an attachment parameter to sendToUser by moving the whole body into a new six-argument overload. The @Transactional stayed on the five-argument si...
The composer is a sub-page, and collapsing no longer eats your text
Four reported problems, one of them destructive. COLLAPSING A PART DESTROYED IT. Collapse UNMOUNTED the editor, and KbArticleEditor is seeded once from a value...
Bind content_json as JSON, or every insert fails
REPORTED: "Failed to create sales script". The server said exactly why: column "content_json" is of type jsonb but expression is of type character varying ...
Impersonate was disabled on every row
Gated on canEnterOrg, which is the VIEWER's own membership — and a platform operator has no membership in the organizations impersonation exists for. So the but...
Archived is a SUB-TAB of Sales Scripts, and pad the page
Two bugs, both mine. ARCHIVED WAS A PEER TAB. Active Scripts and Archived Scripts are two views of one screen, not two screens, and they belong as sub-tabs the...
Pin direct_media=no, and correct the "(+) cannot override" claim
FreePBX's PJSip driver defaults direct_media to YES (generateDefaultDeviceSettings, PJSip.class.php:210) and the GraphQL addExtension mutation has no field to o...
Stop an attachment holding an IMAP connection open forever
getAttachment returned Jakarta Mail's lazy IMAPInputStream straight out of withStore, which puts the Store back in the pool the instant the lambda returns. Two ...
Add 8777 to the WebRTC endpoint roster
Aiden Perry's extension was created from KamoCRM, which cannot write this file — so it registered over WSS with no DTLS or ICE and its calls would have carried ...
Show a pasted screenshot instead of a broken image
Jakarta Mail hands back a MIME header exactly as it arrived, folds and all: RFC 5322 lets a mail header run over several lines by breaking it at a CRLF followed...
Reconcile per-extension WebRTC blocks instead of hand-editing a roster
An extension created through FreePBX's API gets no WebRTC block, so it registers over WSS and then has no DTLS or ICE — the browser softphone shows a connected ...
Apply FreePBX config after every write, or the extension never reaches Asterisk
Extension 8777 (Aiden Perry, kamocrm) was created from KamoCRM on 2026-09-02 and never rang. The FreePBX GraphQL `addExtension` mutation had written `users`, `d...
Impersonate, so an operator can open an org as one of its members
Shown beside Enter on every /network view for a platform administrator holding the new IMPERSONATE right. A different right from SYSTEM_USER and deliberately no...
Enter a tenant organization as one of its members, from /network
A second door beside the same-org god-mode one. Gated on the new IMPERSONATE platform right via @RequirePlatformRight, where the existing door is gated on the s...
IMPERSONATE, so an operator can enter a tenant as one of its members
Appended to PlatformRightType rather than inserted: getSortOrder() returns ordinal(), so a right added in the middle renumbers every right below it in the conso...
The owner can see the tab that grants the right
REPORTED: "I am also an admin and I don't see the new Sales Scripts tab under /settings/features/crm." Correct, and it was invisible to EVERY organization, not ...
Admit the organization owner, or nobody can turn this on
A brand-new right is granted to NOBODY on the day it deploys. These two are deliberately absent from **************** — seeding them from an existing right woul...
Un-skip the parity guards, and pin without blocking the page
TWO PARITY TESTS HAVE NEVER RUN. Both resolved RoleRightType.java through **************** — that is ~/Java/kamo-shared-library, while the checkout is *********...
Price every line against the seat count, everywhere it is shown
The row Amount under 'What you are quoting' was still previewLineTotal, so the quantity cell showed the quote's seat count while the Amount beside it priced the...
Reprice the live totals when the seat count changes
A line that opts into the quote's shared 'Seats / units' driver is priced against it, not against its own quantity. The editor's live rail summed the lines with...
Putting a script back into use should not need a password
ConfirmationDialog always makes you type a challenge word. That is right for archiving — the script leaves every agent's panel mid-shift — and right for deletin...
An archived market's scripts leave the Interaction Center
findMarketIdsWithActiveScripts asked only whether the SCRIPT was active, so a market the organization had retired still appeared as a sub-tab for as long as any...
Mirror the two rights, and parent MANAGE on VIEW client-side
checkRight matches plain strings, so the gates worked without this — but the security role editor cascades grants through RIGHT_PARENT, and with the pair missin...
Author scripts in CRM settings, read them on a call
Two CRM settings tabs behind MANAGE_SALES_SCRIPTS — the live scripts and the archive — plus a Sales Scripts tab in the Interaction Center behind VIEW_SALES_SCRI...
Serve the scripts an agent reads on a call
/api/kb/sales-scripts, gated on the two new rights. Reads take VIEW_SALES_SCRIPTS or MANAGE_SALES_SCRIPTS, writes take MANAGE. SessionHelper.hasRight fails clos...
The script a member reads on a call, as ordered blocks
Two tables and two rights. SALES_SCRIPTS hangs off a lead market the way a LeadVendor does; SALES_SCRIPT_BLOCKS holds the parts, each one a Lexical document plu...
Move a message's controls to the side facing the conversation
The hover rail sat on the message's outer edge — right for your own messages, left for everyone else's. It now sits on the inner side, the one facing the middle...
Like what you see shipping?
Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.