2600Hz ships a patched Kamailio (spec 16)
kazoo-configs-kamailio does not run on stock Kamailio. bflags and import_files are both absent from kamailio/kamailio's own src/core/cfg.lex, and both are rejec...
The platform org is not gated by its own catalog
The platform org was told "Requires the KamoPBX Hosting add-on" on its own phone-server screen, for an add-on it publishes. It owns the plan catalog, the add-o...
The NAT is in place; a closed port means no listener
The router forwards for 5060/5061 TCP+UDP and 20001-29999/UDP to 192.168.4.36 are confirmed. My gate reported PHASE 0 BLOCKED against them while Kamailio was cr...
Close out SW6a
Nine departures. The plan's Spring claim was measured false, its sketched test was near-tautological, and its ServiceTrade-labels-are-new claim was wrong — ther...
The work-order grid reads real service jobs
Every row in this grid was a dead link by construction. generateMockWorkOrders minted ids String(8000 + i), the row click pushed /commerce/service/8001, and the...
Plan cards show what a tier ADDS, not everything it has
The cards listed every included feature - 16 on Free, 30 on Starter, 52 on Business, 57 on Enterprise. Four cards of wildly unequal height, each a wall of text,...
Pull a patient's history from the practices they used to attend
The outbound half of exchange, on the records tab beside the release surface — records leaving and records arriving are one person's job, and somebody who has j...
The outbound half of TEFCA — ask, don't only answer
Everything built so far answers other people's queries: discovery, document query, document retrieve, the match-review queue, the accounting. A practice could b...
A line for documents retrieved from other organizations
Its own domain rather than a share of DOCUMENTS, for the reason bulk exports got one: a practice that queries a health information network routinely accumulates...
Provision a KamoPBX account when a phone server is created
Adding a KamoPBX phone server now creates the underlying account and writes the account id and realm back to configJson. Any configJson the client sent is DISCA...
KamoPBX is selectable
The provider is implemented in VOIPService, so the coming-soon gate comes off. Description no longer names the upstream project and says what actually matters t...
Right-gated service job API
**************** — list, get, update, and PATCH status. Copies ServiceTaskBookController's idiom: orgId(req) or 401, a right check or 403, a String path variabl...
An org-scoped read/write API for service jobs
ServiceJob has been a mapped entity with repositories and passing tests and no way to read a row. This gives it the header the finished work-order UI already re...
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...
Stop telling implementers to run git commit --allow-empty
--allow-empty PERMITS an empty result, it does not force one. With no pathspec it still commits the index, and these checkouts always have another session's wor...
Stop telling implementers to run git commit --allow-empty
--allow-empty PERMITS an empty result, it does not force one. With no pathspec it still commits the index, and these checkouts always have another session's wor...
Unbreak the build - undo a sweep I caused
c8ec175 was meant to be an empty rebuild commit. It was not: `git commit --allow-empty` PERMITS an empty result, it does not force one - it still commits the in...
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...
The Interaction Center bucket tabs never wrap to two lines
Six full-width tabs share the 550px conversations pane, leaving ~80px each, and "Team Members" did not fit — it wrapped and doubled the strip's height. Both mem...
K3m1 is 47.181.8.87 (pbx.k3.kluster.kamocrm.com)
Reverts an incorrect change of mine. I had propagated 42.181.8.87 and edited coturn/deployment.yaml's comment, which was right all along. Verified by DNS: pbx...
**************** 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 ...
An attachment that cannot be read says so, instead of nothing
A media element gives you one bit — it failed — and no status code, and it latches on that bit: it never retries, so whatever went wrong the control simply stay...
A picture-frame image whose bytes are gone answers 410, not 500
The frame stream caught everything as stream_failed and returned 500, so a photo whose object is not in storage rendered as a broken image with no explanation -...
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 ******...
A recording whose bytes are gone answers 410, not 500
Same split as the imaging proxy and the docs download. A call recording that is not in storage is permanently not there, and a player handed a 500 shows nothing...
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 ...
A document whose bytes are gone answers 410, not 500
The streaming download caught every storage failure as one unexpected error and returned 500, which tells a reader nothing and leaves a viewer with a blank erro...
An attachment that cannot be read says so instead of 500ing
The imaging proxy already answers 410 for revoked access and for a removed message, but let openRange's IOException escape uncaught — so the one case where the ...
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 ...
Correct four SW6a claims, one measured false
A plain @Autowired List of an interface with no implementations does NOT resolve to an empty list — it throws UnsatisfiedDependencyException. Measured, not reas...
Correct three SW6a claims, one of them measured false
An earlier draft said a plain @Autowired List of an interface with no implementations resolves to an empty list. It throws UnsatisfiedDependencyException — meas...
Actually call the fulfillment policy
SW3 implemented FulfillmentPolicy as the first member of an interface that had none, and nothing ever called it — a grep across kamo-shared-library and Security...
The tab's own session names its organization; `?org=` leaves the URL
Builds directly on 05ff51b3, which established the right source of truth — the tab asks its own session which workspace it is in, over a call the per-tab token ...
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...
Rebuild to pick up the early-bird offer copy
The dictionary change landed after the last build, and messages/ is pulled at build time.
The seat headline read a default, not a ceiling
The card printed "Up to 5 users" from plan.maxSeats, directly above its own feature list reading "Users (25)" and a comparison column reading 25 - the same card...
Catalog rows that made the pricing page contradict itself
COMMERCE_POS is ServiceType.POS(21), whose real name is "Lines of Business" - the umbrella switch for what an org sells, rents, services or lends. It was labell...
A CCD preview is not a disclosure
Previewing a summary recorded a disclosure naming the recipient — so a patient asking who has their record under §164.528 would be told it went to somebody who ...
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...
Rebuild for SubscriptionPlanFeatureDTO.unit
The catalog stores a unit per feature and the DTO now carries it, so the pricing page can render "15 GB per user" instead of a bare 15. Shared-lib reaches a ser...
Three catalog rows that made the pricing page contradict itself
Seat counts. The plan card headline reads max_seats ("Up to 5 users") while the feature list beneath it and the comparison table read the USERS feature row, whi...
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...
The page contradicted itself, and the calculator billed email per user
Included-in badge named the wrong plan. All four per-seat modules are included in Business and Enterprise, and the badge picked the FIRST id in includedInPlanId...
FreePBX is deprecated (Decision 4 revised)
No migration and no permanent coexistence. KamoPBX stays on k3m1 whose host netns is empty, so it needs none of FreePBX's ports and no shutdown is required. Des...
Plan SW6a, and split SW6 into three
The spec calls SW6 'wire the finished UI', which assumed a backend existed to wire to. ServiceJob, ServiceVisit and ServiceLineItem's new columns have zero runt...
Pin the two form rules that fail silently
Both decide what NOT to send, which is the half of a form with no visible symptom when it goes wrong. A blank remittance line must not become a zero. Every lin...
Like what you see shipping?
Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.