Reveal the preselected workspace, and give the list the org's scrollbar
Two things about the workspace picker, both about the same list. The workspace a member used last is preselected and named on the button, because this screen i...
Implement the KamoPBX provider
Replaces the stub. KamoPBX is Kamo's own platform, so the organization holds no credential at all: KamoPBXAccountProvisioner creates the account when a phone se...
Apps, media, edge manifests and network policy
- config.ini carries a [zone] block from day one so a second region is a config edit, not surgery. Secrets are substituted by an entrypoint at container start...
**************** and lock the Enterprise card
Registers the right client-side - list, colour, icon - and adds it to the coverage test's non-tab set with a note on what it actually gates, since it guards an ...
Refuse a self-serve Enterprise subscription
Enterprise is negotiated. Hiding the price is presentation; this is the boundary. A request naming the Enterprise plan is refused unless the caller holds ******...
Withhold Enterprise pricing from the catalog
Enterprise is negotiated with KamoCRM directly, so its rate is not ours to publish. Every surface that quotes a plan price reads this one endpoint - the public ...
Show what the chart says before the prescription is written
The server now refuses a prescription that conflicts with a recorded allergy, a drug the patient is already on, or a patient nobody has ever asked about allergi...
CouchDB and RabbitMQ on k3m1
CouchDB q=8 / n=1, verified live. q is fixed at database creation and KamoPBX creates a database per account plus monthly MODBs, so q is sized now for the event...
Tell "the bytes are gone" apart from "storage is down"
openRange collapsed every node failure into one IOException, so a caller could do nothing with it but return 500. A browser's <img>/<video>/<audio> cannot rende...
MANAGE_ENTERPRISE_SUBSCRIPTIONS
Enterprise is negotiated, never self-serve. This right gates both halves of that: seeing what it costs, and putting an organization on it. Category.OPERATIONS ...
Check the chart before writing a prescription
Prescribing was added with the allergy table, the interaction-checking query and a "safety context" endpoint all sitting beside it, unread. A system that record...
Phase 0 infrastructure gate
- TURN over TLS on 5349 with a real cert (turn-kamocrm-com-cert). Without turns:, a customer behind a 443-only egress firewall has no media path. Verified e...
Carry a plan feature's unit to the buying surfaces
The catalog has stored a unit per feature all along - "GB/user", "users", "contacts" - and the plan-feature DTO dropped it, so every surface rendering a measure...
Swap the inbound greeting to KamoCRM-Main-Intro-2
Uploaded as a new file rather than overwriting the old one, so rolling back is a one-line change to KAMO_ATTENDANT_INTRO plus a dialplan reload — no re-upload n...
Author a flat-rate task book, priced by the minute
Replaces the SW5 placeholder pane with the real authoring surface: three sub-views on one tab — books, categories, entries — following the SubView switcher Mark...
Right-gated task book API
SW5 Task 3, controller half. CRUD for books, categories, tasks and options, plus GET /{bookUid}/tasks/by-code/{code} - the lookup a quote or work order performs...
Task book service with org-scoped CRUD and code resolution
SW5 Task 3, library half. ServiceTaskBookService exposes books, categories, tasks and options behind an org-scoped API, plus resolveTaskByCode - the lookup a qu...
Un-gate pricing, tax and tiers for service markets
A SERVICE market got exactly three tabs — Overview, Vendors, Agreements. Customers, Tax & Shipping and Discounts & Pricing were all gated on commerceType === 'R...
Apply a remittance to a claim
"Unapplied money" is money the payer has sent that nobody attached to a claim, and the queue could only be looked at. POST_INSURANCE_PAYMENTS gated an operation...
Find a claim by the number a payer quotes
Posting a remittance needs the claim it settles, and a remittance carries no internal id — only the number the practice sent. Without this lookup, applying mone...
Four things that could be looked at and not done
Each of these had a working endpoint, a client function, and no way for a person to reach it. Closing an order loop. The open-loops queue exists because the or...
Add the flat-rate task book
A priced task catalogue whose entries carry labourMinutes — the number that both prices a line and sizes a visit. ServiceLineItem.taskCode, landed in SW3, joins...
Per-extension PBX billing schema, backfill and catalog
PbxBillingSchemaMigration is @Order(0) because it adds a column. The shared-library entity maps phone_cost_mode from the moment the build starts, so any runner ...
Bill phone service by the extension
PricingModel.PER_EXTENSION, its own reserved quantity key, an allocator, a nightly reconciler, a removal gate and the summary API - the phone twin of the per-ma...
Give the phone add-ons a phone icon
PER_EXTENSION already renders as "extension/month" - addOnUnitLabel handles it and needs no change. The icon map does: it is keyed on the lowercased catalog cod...
Show what extensions cost, where extensions are managed
ExtensionUsagePanel on the stats tab, beside the mailbox and storage panels: count by class, the catalog rate, the monthly total, and the rule in plain language...
Queue timeout and "press 0" both fall through to voicemail
Replaces the hand-rolled Dial()+Goto queue loop with app_queue. The deciding factor is DTMF: digits are NOT matched against the dialplan while Dial() is running...
Count the extensions a third-party server does not charge for
Queues, IVRs, ring groups and spares are the extensions nobody is assigned to, and under the third-party rule they are free - twelve of one production org's sev...
Count billable phone extensions
Adds the phone twin of the per-mailbox aggregator: PbxBillingClass with an exhaustive VoipProviderType switch and no default arm, OrgPbxBillingAggregator (no Sp...
Hold-music queue ringing 8000 and 8080 simultaneously
Eight hold tracks uploaded as the `kamocrm-hold` MOH class, shuffled. The random ordering comes from `random=1` on the row in FreePBX's `music` table, which is ...
An emoji on a single message, and a message you can correct
A member asked for both on the individual chat. They land on the same per-message menu the window already has, beside Copy and Unsend. Reactions render as a ch...
React to a message with an emoji, and correct one you sent
POST **************** sets or clears the caller's emoji and answers with the message's whole reaction set, so a client that raced itself converges on the server...
Per-message emoji reactions, and a message its sender can correct
Two things a member asked for on the individual chat: an emoji anyone in the conversation can put on a single message, and the ability to fix a message you have...
Recorded greeting, dial-by-extension, 1/2 to operator
Replaces the music-on-hold hold pattern with the recorded intro: - **************** plays the greeting AND listens at the same time, so a caller can dial ove...
Inbound auto-attendant — music on hold + dial-by-extension
Inbound calls had nowhere to go: the `incoming` table was completely empty, so even a delivered call would have dead-ended. Adds the attendant context plus the ...
One shared calendar per org, one primary per member
Provisioning had nothing underneath it, so two simultaneous first loads both inserted. Collapses what that already made — twenty duplicate rows across seven org...
Review emergency access, and gate the last two surfaces
The break-glass review endpoint had a client function that nothing called: every emergency chart access was recorded and there was no screen to read them on. A ...
Raise and send a claim from the queue that found the work
The revenue cycle read seven queues and could not raise a claim. Each write now hangs off the queue that surfaced the need for it rather than living on a screen...
Correct a patient's details
Details could be entered once and never fixed. The panel sits under the summary rather than in a settings screen, because the moment somebody notices a misspelt...
Set up visit types and working hours
The first screen a new practice needs, and the one that did not exist. Booking offers visit types from one table and searches availability against another, so a...
Write a prescription, an order and a vaccination
The chart could show all three and create none. One panel rather than three, because they are one moment: a clinician finishing a visit writes the prescription,...
Choose who pays for mailboxes, and show the count per invoice
The cost-mode control appears only once a billing group exists — with none the setting changes nothing, and offering it invites the belief it is broken. Invoice...
Schema for member-connected inboxes
The old member-only unique on member_imap_configs is discovered by shape rather than by its Hibernate-generated name, and dropped only after the wider key exist...
Edit demographics, set up the schedule, bill and post
The last four rights that named operations which did not exist. EDIT_PATIENT_DEMOGRAPHICS: a patient's details could be entered once and never corrected. A fie...
POST /quotes/{uid}/convert
On QuoteController rather than POSController: this controller enforces a right on every handler, POSController enforces none on any order endpoint, and it resol...
Back the personal-mailbox API the console already calls
Eighteen client methods over twelve routes that had been shipping with no backend behind them. A member reaches only their own inbox and configures it only once...
Personal mailbox entities and two consumer providers
GMAIL_PERSONAL and OUTLOOK_PERSONAL were offered by the picker and were not members of the enum, so selecting either produced an unusable org.
A closed head spins away instead of blinking out
Right-clicking a head and choosing Close, or putting one in the goal — thrown in or carried in and dropped — now plays a 500ms exit: a counter-clockwise three-q...
Prescribe, order and immunise
The chart could display medications, orders and vaccinations and could produce none of them. The read paths, the FHIR renderers and the safety queues were all b...
Like what you see shipping?
Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.