Skip to content
KAMOUniverse

Changelog

What's new.

Every improvement to the platform, as it ships.

  1. · kamo-shared-library

    Chart list reviews, allergy reaction/severity, status reasons, order diagnoses, result review note

    - ClinicalListReview (fhir_chart_list_review): a real reviewed-at record for the allergy and medication lists, so 'reviewed' stops meaning 'at least one row exists' - AllergyIntolerance: reaction_text, reaction_severity, status_reason; findActiveForChecking now excludes NKDA assertions (and refuted rows); findActiveNoKnownAllergy / findActiveRecord - Condition.status_reason, Observation.status_reason, ServiceRequest.reason_codes, DiagnosticReport.review_note - EncounterDiagnosisRepository; **************** (vitals flowsheet)

  2. · kamo-shared-library

    Schedule entities for the practice's clock, rooms, desk payments and recall outreach

    - PracticeSettings (ehr_practice_settings): the practice's time zone and default visit length - PracticeRoom (ehr_practice_room): rooms a patient is put in; retired, never deleted - PatientPayment (ehr_patient_payment): desk payments recorded (never processed), voided with a reason - RecallOutreach (ehr_recall_outreach): logged contact attempts against a recall - Appointment: room_id, rescheduled_from_id / rescheduled_to_id, checked_out_by_member_id - ScheduleBlock: label for blocked time (lunch, meeting, vacation) - PatientRecallRepository: countDue / countOverdue; WaitlistEntryRepository: findCandidatesAnyType (a null UUID in ':x IS NULL' reaches Postgres untyped) - PhiResourceType: PATIENT_RECALL, PATIENT_PAYMENT appended

  3. · kamo-shared-library

    Front-desk registration record — contact details, emergency contacts, MRN counter, coverage write fields

    Patient gains preferred contact method, primary care member and preferred pharmacy; emergency contacts are FHIR Patient.contact (fhir_patient_contact, retired not deleted); telecom and address use the existing fhir_contact_point / fhir_address tables (new repositories); PatientCommunicationRepository for the preferred language. A per-practice ehr_mrn_counter row allocates MRNs in one atomic upsert. Patient search gains given-name, birth-date-only, prefix-with-birth-date and by-id queries. PriorAuthorization gains a service description and EligibilityCheck a verifier's note. DDL applied to production before this push.

  4. · kamo-shared-library

    Chart documents, practice note templates, note read-side text and withdrawal record

    - PatientDocument (ehr_patient_document): category, title, document date, content type, size, SHA-256, imaging Img id + storage key, uploader, entered-in-error with who/when/why. Never deleted. - ClinicalNoteTemplate (ehr_note_template): a practice's own note templates. - ClinicalNote: entered_in_error_at/_by/_reason columns; transient current body, version kind, SI flag, author/cosigner/patient names for reads. - ClinicalNoteVersion: transient author name. DDL applied to production by hand (additive).

  5. · SecurityService

    Real refusals, break-glass review decisions, honest claim sending, hand-keyed EOBs

    - EhrRuleViolationException: a business-rule refusal (unsigned note at close, double booking, not the author/cosigner, self-cosign, already signed, restricted from the insurer, break-glass without a reason, too many exports, suppressed match) now answers 409/422 with its plain-language sentence instead of the opaque 'No such record'. Relationship denials stay 404. - EhrExceptionHandler runs at highest precedence over the global commerce advice, and covers Quality, Portal admin, CCD, Bulk export and FHIR (a missing right there was a 500). - Break-glass review: queue with names plus history, and a decision (appropriate / inappropriate / needs follow-up, note required, never your own). - Exchange partner directory for clinicians (VIEW_CHART, names only). - Claims: CPT/HCPCS, modifier, ICD-10, pointer, NPI and place-of-service format checks; payer and member id from the chosen coverage; a visit must be closed to bill; billed procedures leave the uncharged queue; a claim-draft read for the builder. ClaimTransport seam: with no clearinghouse, submit marks READY and says so; mark-sent records channel, who and note. - Remittances can be keyed in from a paper EOB, and posting now moves money from unapplied to applied.

  6. · kamo-shared-library

    Record how a claim was sent, and list reviewed emergency accesses

    A claim gains ready_at, submission_channel, submitted_by_member_id and submission_note, so a claim sent by hand through a payer portal or on paper is recorded honestly instead of a status flip that pretends a clearinghouse transmitted it. The break-glass grant repository gains the reviewed-history finder the new review screen lists beneath its queue.

  7. · kamo-internal

    The invoice shows the Receivables remittance block, as quotes do

    The invoice dialog renders the same QuoteRemittanceBlock the quote preview uses, from the seller's Receivables details, while anything is owed. The Receivables switch now says it covers quotes and invoices.

  8. · kamo-signer-monorepo

    The invoice's remittance block reads exactly as the quote's

    Same heading, labels and ACH Credit Only notice (signer.quote.remit), with the invoice-number reference kept beneath it.

  9. · SecurityService

    Invoices print the Receivables ACH details exactly as quotes do

    The PDF and the email now carry the quote's remittance block, word for word: - Remit payment to - payee (legal name) - bank - routing number (ABA) - account number - the ACH Credit Only notice These are followed by the invoice-number reference and the market's own instructions. GET **************** gives the console the same block. As on quotes, it appears when Receivables has the ACH info switched on and both numbers saved.

  10. · kamo-internal

    Change seats and licenses from a date, with the prorated charge previewed

    Change seats & licenses opens a dialog to set: - seats and each add-on's licenses (per-user licenses follow the seats until typed over); - the date it takes effect (today, or later); - whether the prorated charge goes on its own invoice now (even ahead of the date) or on the next renewal; - for reductions, a credit for the unused part. The server's live preview shows the period, the days left, each prorated line, any setup fee, the total, how it will be billed, and the recurring charge before and after. Scheduled changes are listed on the subscription and can be cancelled. Replaces the old immediate seat dialog.

  11. · SecurityService

    Endpoints for dated, prorated seat and license changes; the job applies them

    New endpoints: - POST **************** - POST /subscriptions/{uid}/changes - GET /subscriptions/{uid}/changes - POST **************** The hourly billing job applies changes whose date has come before raising invoices, so renewals bill the new counts.

  12. · kamo-shared-library

    Seat and add-on license changes mid-period, on a chosen date, prorated

    SubscriptionChangeService records a change to a live subscription's seats and add-on licenses effective on any date from today. It previews the exact prorated charge: each added unit's per-period price x days left / days in the period it falls in, e.g. Harmony +6 seats from Nov 1 = 6 x $124 x 17/31 = $408.00. The charge is invoiced when the operator chooses: its own draft invoice now (even before the effective date) or on the next renewal invoice. On the effective date the billing job applies the change: - the subscription's seats, licenses and MRR; - the customer's access (seat count, seat rows, add-on licenses, cache); - every later renewal draft, rebuilt, or given an adjustment line if staff had edited it. Edge cases: - a change exactly on a billing day is carried by that renewal rather than prorated twice; - a reduction charges nothing and can credit the unused part on the next renewal; - a scheduled change can be cancelled, voiding its draft invoice; - setup fees for added seats read the CUSTOMER's agreement. The old change-seats path now goes through this service. New table commerce_subscription_changes; new column ****************

  13. · kamo-internal

    Plain-language statuses everywhere; agreed add-on prices and a monthly discount in the order wizard

    StatusChip (89 call sites) showed raw codes such as PENDING_APPROVAL; it now shows the dictionary's words (common.statusCodes), or the code read aloud for one it does not name. The orders list filter and CSV use the same labels. Staff can enter an agreed per-license price for each selected add-on and a monthly discount; both are sent as addonUnitPrices / recurringDiscount and billed on every invoice.

  14. · kamo-signer-monorepo

    Pay by card on the invoice page

    When the server offers it (platform-sold invoices with a balance), the invoice page shows Pay by card. It posts to /<locale>/i/<token>/pay, which sends the customer to a Stripe-hosted payment page (bank confirmation happens there) and back. A returning customer sees the payment acknowledged.

  15. · SecurityService

    Customers pay invoices by card online; a bank's SCA request reaches the customer

    On invoices sold by the platform org (the only seller whose Stripe account it is): - the public invoice offers Pay by card: POST **************** opens a Stripe-hosted page that returns to the same invoice link (built server-side, never from the request); - the payment is recorded when the customer comes back and by the hourly job, exactly once. When an automatic charge needs the customer to confirm it with their bank, they are emailed the invoice with that request, and the owners are alerted as before.

  16. · BillingService

    Pay a subscription invoice by card on a Stripe-hosted page

    Internal POST **************** creates a payment-mode Checkout session for the amount owed. It saves the card for future automatic charges when the customer has an account, and the bank's SCA confirmation happens there. GET /checkout/{id} reports whether it was paid and with which card. Consumer checkout ignores these sessions.

  17. · kamo-shared-library

    Track an invoice's pending online card payment

    New nullable column **************** plus helpers to list and settle pending sessions idempotently (a payment carrying the same processor reference is never recorded twice).

  18. · kamo-shared-library

    Negotiated add-on prices and a quote's discount carry into the subscription

    Converting a quote now carries: - each add-on's agreed per-license price (when it differs from the catalog's) - the quote's or accepted option's discount, as a recurring monthly amount (an option's period discount is spread over its months) Orders record both in custom_pricing, so a draft reprice keeps them. Activation puts the agreed price on the add-on licenses and the discount on the subscription (new nullable column **************** so every invoice bills the deal and MRR reflects it. Staff orders can state both directly (addonUnitPrices, recurringDiscount).

  19. · kamo-internal

    Auto-renew and notes work on live subscriptions; card on file and charge card now

    - The auto-renew switch sets the subscription's own renewal (it posted a field the draft-only order update ignored) and says when a non-renewing one ends. - Notes save on an order in any status. - A card-paying subscription shows the card on file. - Its open invoices offer Charge card now and show why the last card attempt failed.

  20. · kamo-internal

    Show licenses held and in use where mailboxes and extensions are assigned

    Owner rule 2026-10-22: per-user add-ons bill the licenses purchased, and the licenses are the only limit on what may be in use. A LicenseUsageMeter ("4 of 10 licenses in use", animated bar in the org's brand colour, corner ribbon, warning chip and note when already over, link to Plans & Billing) reads GET /api/billing/licenses/usage and appears on: - Settings > Email mailbox management (KamoMail or 3rd-party licenses) - the member phone-settings extension picker (KamoPBX or 3rd-party) - Plans & Billing add-on rows Refusals (409, the server's plain-language sentence) now reach the person: mailbox assign, shared-mailbox grant, personal inbox assign/IMAP save/OAuth connect and callback all show it in that mailbox's panel (several used to throw unhandled or say a generic failure); every such action refreshes the meters. New strings: settings.billing.licenses (kamo-translation-dictionary).

  21. · kamo-internal

    Quotes start subscriptions; offline acceptance; tenant orders; plain-language billing

    - Quotes: "Add from subscription catalog" fills a row from the live plans/add-ons (name, monthly price, "per user / month" / "per 10 GB block / month") and keeps the catalog reference; accepted subscription quotes convert through a dialog (payment method; target organization for the platform only) into a subscription order; "Record acceptance" for paper/email/PO acceptances; previews of a DRAFT carry a watermark and every print is logged; terms fill {orgName} with the seller's short name. - Order wizard: target organization only for the platform org; staff-only negotiated per-seat price and setup-fee override. - Signups list: next billing date, balance due, overdue badge; one shared payment-method label helper for all six methods. - Subscription page: events in plain sentences (Active → Past due), order number instead of the record's id. - Contact sales: name, email and phone read from the platform org via a narrow endpoint.

  22. · SecurityService

    Refuse a department or contact mailbox past the email licenses

    Owner rule 2026-10-22: per-user add-ons bill the licenses purchased; how many mailboxes may be in use is limited only by them. Under a 3rd-party provider a department reached at a mailbox, or the organization's contact information pointing at one, maps it into Kamo (OrgMailboxBillingAggregator), so these two saves can put a mailbox into use as surely as assigning it to a member. - MailboxLicenseCapGuard asks BillingService's internal license check (X-Internal-Auth) before POST/PUT /api/security/departments and PUT /org/{id} change the mailbox; a refusal is a 409 with the sentence in error/message and reason LICENSE_LIMIT. Keeping or clearing the mailbox is never checked; a BillingService outage fails OPEN with a warning. - The billing relay door also passes GET /licenses/usage (same rights as the other usage reads).

  23. · SecurityService

    Record offline acceptance, log prints, convert quotes into subscriptions

    - POST **************** (SEND_QUOTES or MANAGE_QUOTES) - POST **************** (VIEW_QUOTES or MANAGE_QUOTES) - POST .../{uid}/convert takes an optional body (target organization, payment method); converting as COMP also needs CREATE_SUBSCRIPTION_ORDERS - POSController refuses negotiatedUnitPrice / setupFeeOverride from OWN-only callers - GET **************** the platform org's published name, contact email and phone, for the Contact sales dialog, instead of hard-coded constants

  24. · kamo-shared-library

    Quotes convert into subscriptions; tenant orders never comp the seller

    - A quote in a SUBSCRIPTION market, or whose accepted rows were filled from the subscription catalog, converts into a SubscriptionOrder (plan, seats from the quote quantity, add-ons with their licenses, the accepted per-seat rate as a negotiated price, the setup fee the customer saw, the accepted option's commitment as the cycle, payment method chosen at conversion). The order carries quote_uid; a second conversion is refused; a CONVERTED event is logged. Retail conversion is unchanged. - QuoteService.acceptOffline: staff record an acceptance given on paper/email/PO — draft, sent, viewed or expired quotes; totals through applyOptionHeadlineTotals; event names who and why. - recordPrinted logs a PRINTED event (draft prints say so). - Per-seat rows store the quote's seat count on every save and revision; the line view sends the quantity a row is priced at. - Quote lines carry catalog_ref_code / catalog_ref_uid. - Terms support {orgName}, filled with the seller's short name on the customer's page. - provisionOnApproval and activateCompOrder require a target organization — an order with none used to provision the SELLER's own subscription. - **************** / setupFeeOverride, applied after calculatePrice and remembered in custom_pricing so a draft reprice keeps the deal. - Order and subscription DTOs carry next billing date, outstanding balance and an overdue flag, read in two queries per list.

  25. · EmailService

    Refuse a mailbox past the organization's email licenses

    Owner rule 2026-10-22: per-user add-ons bill the licenses purchased; how many mailboxes may be in use is limited only by them. Before a mailbox is put into use, BillingService's **************** is asked (X-Internal-Auth); a refusal is a 409 carrying its plain-language sentence (StatusReasonAdvice), e.g. "All 10 of your 3rd-party email licenses are in use. Add licenses in Billing to connect another mailbox." Enforced, before anything is written: - creating a mailbox (KamoMail counts it at once; 3rd-party only once mapped) - assigning a mailbox to a member - creating a shared mailbox, granting access to one, switching one back on - connecting a personal inbox (IMAP save, OAuth consent and callback) and assigning an already-connected one - AI member mailbox provisioning (NOT_READY / LICENSE_LIMIT) An address already counted is never refused, nothing existing is unassigned, and a BillingService outage fails OPEN with a warning. The mailbox-assign, shared-access and personal-mailbox endpoints now pass a refusal's status and sentence through instead of a 500.

  26. · VOIPService

    Refuse a phone extension past the organization's licenses

    Owner rule 2026-10-22: per-user add-ons bill the licenses purchased; how many extensions may be in use is limited only by them. Before an extension is put into use, BillingService's **************** is asked (X-Internal-Auth); a refusal is a 409 carrying its plain-language sentence (LicenseCapAdvice), e.g. "All 10 of your 3rd-party phone licenses are in use. Add licenses in Billing to assign another extension." Enforced, before anything is written: - PUT /api/voip/member/{id}/config (member phone settings), naming the extension the member holds now so a move on a 3rd-party system is free - POST **************** (new extension; KamoPBX counts every active one, 3rd-party only an assigned one) - PUT **************** when the result is ACTIVE - AI voice line provisioning (NOT_READY / LICENSE_LIMIT) An extension already counted is never refused, nothing existing is unassigned, and a BillingService outage fails OPEN with a warning.

  27. · BillingService

    License usage and per-unit license checks for per-user add-ons

    Owner rule 2026-10-22: every per-user add-on bills the licenses purchased, like seats; how many mailboxes or extensions may be in use is limited only by them. - GET /api/billing/licenses/usage (session, X-Org-Id): per add-on code (EMAIL_3P_INTEGRATION, EMAIL_HOSTING, PBX_3P_INTEGRATION, PBX_HOSTING) the licenses held, in use, available, over-by, and whether the org is exempt. - GET **************** guarded by X-Internal-Auth (constant-time compare with billing.internal-auth-secret), for EmailService and VOIPService to ask before putting one more unit into use. - Licensed = AddOnLicenses.licensed over the primary subscription's active_addon_codes / addon_quantities (or a plan that includes the add-on); the reserved __mailboxes:/__extensions: keys are never read as licenses. In use = OrgMailboxBillingAggregator / OrgPbxBillingAggregator, the counts the nightly bill uses. - Platform org and OWNER_UNLIMITED are exempt; PAID and COMP are capped; TRIAL, FREE and no subscription are left to the existing entitlement gates. - Only a change that ADDS a unit past the licenses is refused; a unit already counted, or a 3rd-party extension move that frees one, always goes through.

  28. · SecurityService

    Endpoints to set a subscription's auto-renew and an order's notes in any status

  29. · kamo-shared-library

    Turn renewal on or off for a live subscription; notes on any order

    The console's auto-renew switch sent a field the draft-only order update did not have, so it never saved; and notes failed on any order past draft.

  30. · SecurityService

    Card customers are charged automatically on the billing day

    For AUTO_BILL subscriptions the billing job charges each approved invoice to the customer's saved card on its billing day through BillingService's internal card endpoint, records the payment (method CARD, reference = PaymentIntent) and retries a failed charge every three days up to four times. A failure alerts the owners. Approving and sending an invoice whose billing day has come charges first, so the customer's email is a receipt. New endpoints: - POST **************** - GET ****************

Your universe is waiting.

Start free in minutes. Add products whenever you are ready — no migration, no new logins.

Free forever — no credit card required