Skip to content
KAMOUniverse

Changelog

What's new.

Every improvement to the platform, as it ships.

  1. · BillingService

    Internal card endpoints for subscription invoice auto-charge

    GET **************** and POST /charge, guarded by the shared X-Internal-Auth secret (constant-time compare; 403 without it). A charge is an off-session PaymentIntent on the customer's default saved card with a caller-supplied idempotency key; decoders and authentication-required come back as statuses, not errors.

  2. · kamo-shared-library

    Card auto-charge bookkeeping on subscription invoices

    AUTO_BILL invoices are charged on their billing day once approved and retried every three days, up to four attempts. Each attempt is numbered before it is made so its idempotency key is never reused. New nullable columns: - card_charge_attempts - last_charge_attempt_at - last_charge_error - last_payment_intent_id

  3. · kamo-internal

    Subscription billing console — invoice drawer, draft editor, payments, market invoicing

    Invoices tab: plain-language rows (period, total, amount due, due date, status) open a drawer with the lines, totals, payments received, where and when it was sent, notes and the PDF. A draft gets a line editor (type, description, qty, unit price per period, credits, tax, due date, notes) with a live client-side preview, then Approve & send through a dialog prefilled from the billing contact. Record payment replaces the one-click Mark paid: amount (defaults to amount due, part payments allowed), date received, method, reference, notes. Void (with reason), Refund and Resend. Overview: next invoice date and whether its draft exists, the outstanding balance, and Prepare next invoice now. The order's single Total is split into recurring per period, one-time setup fee and first invoice total. Market settings: an Invoicing tab for subscription markets (hold for approval vs send on the billing day, draft lead days, payment due days, payment instructions). Order wizard: per-add-on license quantity (seat count by default for per-user add-ons), sent as addonQuantities; ACH and Check payment methods. Notifications: BILLING_INVOICE kind, gated on VIEW_SUBSCRIPTION_INVOICES, after DISCLOSURE_REQUESTED. Also: updateSubscriptionOrder is sent as PUT (the route POSController maps; PATCH answered nothing), so notes can be added to a draft order; the note box says so on any other order.

  4. · SecurityService

    Automatic subscription invoicing - drafts, owner review, email with PDF, payments, reminders

    SubscriptionBillingJob (hourly, one pod, and at startup) runs the cycle: - raise each renewal invoice as a draft lead-days before its billing day - move subscriptions onto the next period once invoiced - tell the seller's owners in-app (BILLING_INVOICE) and by email that a draft is waiting - send drafts on the billing day only in markets set to auto-send (default: hold for approval) - mark late invoices overdue, alert the owners and remind the customer weekly InvoiceDelivery emails the customer the invoice with a PDF (InvoicePdfRenderer, PDFBox) and a view-online link on the signer host, with the org's remittance details. InvoicePublicController serves that link (token in the body, rate limited, one answer for unknown tokens). POS endpoints: - edit a draft - send/resend with recipient and message - default recipient - PDF - record payments with the date received, method and reference (partial OK) - void with a reason - per-market invoicing policy - add-on license quantities in the price calculator

  5. · kamo-signer-monorepo

    The customer's invoice, online — branded, printable, with a PDF download

    /[locale]/i/[token] resolves the invoice server-side (token in a POST body, never a URL) and renders it in the seller's own name and colour, falling back to a neutral near-black rather than a platform blue. Big status up top, bill-to, dates, service period, lines, totals, how to pay, payments received and notes. /pdf streams SecurityService's PDF back with a sanitised filename and no-store. Any failure is one indistinguishable 'no longer available' page.

  6. · EmailService

    BILLING_INVOICE, gated on viewing subscription invoices

    Raised by SecurityService to the selling organization's owners when a subscription invoice draft is waiting for review or a customer's invoice goes past due. Also rebuilds onto the shared library carrying the commerce.invoice_* email templates.

  7. · kamo-shared-library

    License-based add-on pricing and a real subscription invoice lifecycle

    One rule for add-on quantity (AddOnLicenses): every add-on bills the licenses PURCHASED, like seats - per-user add-ons default to the seat count, storage to the blocks bought - never usage. The order calculator charged anything not PER_SEAT once, so a 10-seat order with 3rd-party e-mail and phone was priced $5 instead of $50. Order lines now carry real quantity and unit price; a draft reprice keeps the licenses it states. Activation turns the order's add-on lines into licensed add-on instances (they were dropped, so no invoice ever billed an add-on), anchors the billing day, includes add-ons in MRR, and raises the first invoice as a draft. Approving an order paid by invoice, wire, ACH or check now grants access as PAID; only COMP did anything. SubscriptionInvoiceService: - renewal drafts raised lead-days ahead, once per period (unique constraint) - periods roll on the billing day only once invoiced - trials convert; non-renewing subscriptions end - payments recorded with the date received, method and reference, partial payments supported (new **************** - draft editing with server-side totals - guarded void/refund - overdue marking and reminder scheduling - view-online tokens (SHA-256 at rest) - race-safe INV-YYYY-NNNN numbering on the shared document counter Per-market MarketInvoicePolicy: auto-send vs hold (default hold), lead days, due days, payment instructions. PaymentMethod gains ACH and CHECK. New email templates commerce.invoice_sent / invoice_reminder / invoice_ready and NotificationKind BILLING_INVOICE.

  8. · BillingService

    Rebuild the Stripe mirror from Stripe nightly and on startup

    Events older than 30 days cannot be fetched, so the September invoice and subscription events lost to the API-version mismatch are unrecoverable as events. StripeMirrorReconciler reads each Stripe-backed subscription and its invoices directly and writes account_subscriptions / account_invoices, at 03:30 and once after startup (off the startup thread). A reconcile can clear a stale delinquency clock on a paid invoice but never starts dunning.

  9. · TranslateService

    One engine, MADLAD-400, for every language pair

    Replaces the LibreTranslate, Bergamot and IndicTrans providers with MadladProvider (klusterservices madlad/). Their languages did not overlap, and a pair none of them had came back as its English source and was saved as the translation; MADLAD translates between any two of ~400 languages, so inbound chat in any language reaches English too. - The provider sends a list of texts in one request: a 3B model is bound by reading its weights, and 16 short strings took 9.7 s together against 25.8 s one by one. ProviderRouter.translateAll groups a batch's keys (32 texts / 6,000 characters), and a group the engine fails is retried text by text so one bad text fails alone. - TranslationService.batch masks protected names first, sends each distinct text once, in groups, and restores the names after; a reply that lost one is still translated around the names. The caller's deadline is checked between groups. - Until the engine has answered /languages the provider claims Kamo's 22 languages, never none: an unclaimed pair is returned as its English source and saved as the translation. - A timeout is still never retried; 503 busy and 5xx are, inside the caller's deadline. Background work holds one slot per pod so a chat message never queues behind a sync.

  10. · KlusterServices

    One translation engine for every pair, MADLAD-400-3B on CPU

    Replaces LibreTranslate (Argos), Bergamot and Kamo IndicTrans, whose language sets did not overlap and whose gaps came back as English. MADLAD-400-3B-MT (Apache-2.0, int8 CTranslate2 by Santhosh Thottingal) translates between any two of ~400 languages, so inbound chat in any language now reaches English too. - 8 cores / 16 GiB reserved, up to 16 cores / 32 GiB, as asked. Two streams of eight threads: sixteen threads on one stream measured slower (83 vs 123 chars/s) on the nodes' CPU class (Haswell, AVX2). - The API takes lists: 16 short strings in one call took 9.7 s against 25.8 s one by one. - Every input ends with </s>; without it a short label ran on (Save came back three times, and in Arabic as 'Save 10% of the order value'). The beam follows the length of the piece. - Placeholders go to the model as {0}, not KMPH0: lost in 0 of 60 strings in each of ar, hi, sw and zh against 11, 6, 6 and 4. A reply that still loses one is asked again wider, then translated around it. - Same pattern as indictrans/: hash-pinned model and wheels fetched by a Job, serving pod has no egress, auth proxy in front, read-only root, k3m1. The old engines keep running and are removed in the next commit, once TranslateService speaks to this one.

  11. · kamo-internal

    The Pipeline's loan officer filter shows faces and opens the member card

    Each officer in the filter's options, and the one selected, is their avatar and name wrapped in the shared MemberHoverCard. A click still selects.

  12. · kamo-internal

    The Pipeline's loan officer opens the shared member card

    The loan officer on each deal is wrapped in MemberHoverCard, the popup every other surface uses for a member. It opens on hover and keyboard focus; a click still opens the assign-loan-officer dialog.

  13. · kamo-internal

    A full-width, full-height HMDA LAR page; readable brand buttons on the loan page

    - HMDA LAR: the register is an AG Grid that takes the whole width and every pixel under the header, and scrolls inside itself — the page no longer scrolls. Issue details open in a popover on the body instead of inside the table's overflow box (which put scrollbars on the table whenever one was opened). Summary tiles (loans, volume, errors, warnings), search, an issues-only filter, pinned loan and issue columns. - Five brand-coloured buttons on the loan page (Pricing, Pipeline, Disclosures) had text-gray-900 on the brand colour; they are white like the rest. - HMDA LAR, the Board and the delete-loan redirect went to /applications, which has no page; they now return to where the member came from, else /commerce. The Pipeline's HMDA LAR and Board buttons pass their location. Completes 50fee1b25.

  14. · kamo-internal

    A new mortgage Pipeline — open deals first, past ones a click away, and every deal managed from its card

    The Pipeline tab under a mortgage market is rebuilt around transactions: - Open | Past | All views (past = completed or cancelled), with counts - headline numbers that count up and double as filters: open transactions, loans in flight, volume in flight, closing in 30 days, need attention (past target close, or a denied loan) - a stage rail showing where the open deals sit; click a stage to filter - each deal is a card: progress ring around the borrower, stage, total amount, how many days to target close (amber soon, red overdue), and the loan officer; it expands in place to its loans - manage from the card: rename, assign/change the loan officer (the shared member picker), add another loan to the deal, remove a draft loan, copy the transaction number, open any loan - search ("/" to focus), loan-officer filter, four sorts, CSV export, Find loan, Board and HMDA LAR kept; guided-tour anchors kept - colours come from the org's brand; reduced motion respected Faster to open: - PrimeReact (its DataTable, theme CSS and icon font) is gone from the page — it was used here and nowhere else - every steward screen but the Pipeline now loads on first visit instead of all eight in one chunk - the last read is kept for the page's life, so coming back to the tab paints at once and refreshes behind it - PipelineView resolved a ?tab= deep link only in an effect, so the first paint mounted market 0 and started its loads before switching - pairs with SecurityService 7ca04ac3, which removes the N+1 queries behind both pipeline reads Steward tabs reordered: Pipeline, Documents, Pricing, Underwriting, Capital & Risk, Ingestion, Catalog — Governance, not in the requested order, stays last.

  15. · SecurityService

    Approve and always allow checks the rights a tool needs in one case only

    Approval follow-up 2026-10-21: the Tool Plane's card now names the rights a tool's service enforces in some cases only (alwaysAllow.rightsWhen: a colleague's lead's contact details, another member's timecard, ...). The preview takes them as when=CODE=RIGHT|RIGHT (or CODE=any:...) and answers each under cases, checked like the tool's own rights: what the SI still lacks, and whether this person may give it.

  16. · kamo-internal

    Corner ribbons on every edge, on tabs, and on the top bar's open pages

    Following the left-edge round, the other three edges get the same treatment, on a fixed mapping: a top rule becomes a top-left ribbon, a right rule a bottom-right ribbon, a bottom rule a bottom-left ribbon. CornerRibbon learns its corner. The component takes `corner`; cornerRibbonSx takes an options object ({ size, corner, pseudo, anchor }, the old positional form still works); the CSS class gains --tr, --bl and --br. The light still comes from above, so on a bottom corner the shading reverses and the shadow falls between the band and the corner. Tabs: the root theme hides MUI's tab indicator and gives every selected tab an xs bottom-left ribbon (bottom-right on a vertical bar) in the tab's own colour. A bar that wants another colour sets --tab-ribbon-color; per-site indicator styles are removed or carried over to it, and hand-built tab bars (IoT, lead view, softphone, emoji picker, Docs) mark their tab the same way. Nav: the top bar selects an option exactly as the rail does, lit with a white xs ribbon instead of an underline, and a tool menu (Mail, Docs, Phone and the rest) is selected while any of its pages is open, in both navs. Left alone as before: dividers, progress and loading bars, spinners, full borders, connector lines, handles, and content the member styles themselves.

  17. · SecurityService

    S-I1 accepts REPLACED, so IoTService revokes a superseded Alexa link's grant

    Owner 2026-10-21. KamoOAuthRevokeReason.REPLACED already exists (STRING-persisted, no CHECK on revoked_reason), so no shared-lib or DDL change; the internal revoke whitelist adds it and audits OAUTH_GRANT_REVOKED (REPLACED). SecurityService-only reasons (CODE_REUSE, REFRESH_REUSE, CLIENT_REVOKED, ORG_VOIDED) stay refused (pinned).

  18. · kamo-internal

    Corner ribbons replace every left-edge accent rail

    The System Bugs page went first. This change does the rest of kamo-internal: about 120 files where an item was marked by a coloured rule down its left edge — a borderLeft, a Tailwind border-l-N, an inset box-shadow, a ::before or absolutely placed bar, or a short leading flex bar — now carry the corner ribbon in the same colour and under the same condition. CornerRibbon gains two forms for places a child element cannot go, both drawing the identical ribbon from one 135-degree gradient: - cornerRibbonSx(color, size, pseudo, anchor) — an sx fragment on the element's own pseudo-element. anchor=false leaves position alone for AG Grid rows, which the grid places itself; '&::after' avoids the grid's ::before tints. - the kamo-corner-ribbon class in globals.css (--xs/--md, colour via --corner-ribbon-color), for Tailwind, styled-jsx and rich-text CSS. Rich-text blockquotes use the same rule. LegalStateRail becomes LegalStateRibbon. Grid cell renderers render the ribbon with no positioned wrapper, so it anchors to the absolutely positioned .ag-cell and sits in the row's corner. The nav's active marker in the rail is an xs white ribbon; the bar variant keeps its bottom underline. Animated rails (alarm arrival, available-lead pulse) keep their glow and lose only the rail. These were left alone because they are not item indicators: 1px pane dividers, timeline/tree connectors, progress bars, resize handles, the audio waveform's selection range, and top-edge or bottom-edge bars.

  19. · kamo-internal

    Approve and always allow, the named why, the SI's own picture, the org's own colours

    Always allow: from the decision bar, the approver picks just this action or the whole kind (in plain words), reads exactly what changes in the SI's job description, and confirms; SecurityService writes the rule (preview/grant/revoke relays), then the request is approved and the SI told. Someone who may not change the job description is told why and who can, and may approve once; a right the action needs is offered only to someone who may give it. "Ask me again" in the result and on the rule in the SI's job description takes it back. Why: a follow-up names the earlier request in its own card's words, who decided it and when, with a link; the job description line says which rule asks. Avatar: the chat windows' lookup (fetchMemberAvatar: photo, then picked avatar, initials last) on the card and in the inbox. Colours: the approvals UI paints from --color-primary through ApprovalBrandScope (buttons, chips, focus, badges, progress, alerts, status); words on a brand fill are black or white by the brand's own luminance, so any brand reads at AA. Risk and state keep their semantic colours.

  20. · kamo-login

    Alexa consent names links by location and points a re-link to Replace

  21. · kamo-internal

    Alexa section says each Alexa account is its own link

  22. · MCPGatewayService

    Honour standing permissions; offer Approve and always allow on the card

    CharterPolicy reads resolved.toolApprovals and each rule's standing flag. A member's rule about one tool stands for its class's rule for that tool; a standing permission (granted from an approval) holds under a SUPERVISED ceiling but never for a SHADOW SI or a charter that could not be read, and a FORBIDDEN class still wins. The pipeline and the first-contact check judge by tool, so an always-allowed send still asks before a first contact. The approval card gains alwaysAllow: offered unless the tool is person-only, moves money, touches security or devices, or its kind of action is never allowed for good, with the reason in plain words, the tool's title, the kind in plain words and the rights the tool needs.

  23. · SecurityService

    Approve and always allow, from an SI's approval

    GET **************** POST **************** {approvalId, scope TOOL|CLASS, grantRights?} DELETE **************** (Ask me again) The approval names the tool and kind of action; only someone who may edit the SI's charter (CharterAccess.editRefusal) grants it, through MemberCharterWriter (validation, new stamp, runtime told). Refused for the kinds StandingPermissions never allows, a communication-policy or disclosure approval, a decided request, a shadow SI, a rule another layer set, and a forbidden class; each refusal and the before/after are said in plain words. A right the tool needs that the SI lacks is offered only to someone who manages member security and holds it.

  24. · kamo-shared-library

    Standing permissions from an approval (Approve and always allow)

    A member's own APPROVAL item may now name one tool (tool_name) and record the approval it came from, who granted it and when (item_origin APPROVAL). The resolver answers resolved.toolApprovals for tool rules that sit under a class rule that is the default or the member's own and not FORBIDDEN; a layer's rule is never loosened. StandingPermissions lists the kinds of action that are never allowed for good (money, devices, the SI's computer, information release, outside sharing, first contact) and says each kind in plain words. The view and stamp are byte-for-byte unchanged for charters without these items. DDL: securityservice **************** (applied).

  25. · kamo-internal

    Corner ribbons replace the left-edge accent rails on System Bugs

    CornerRibbon is the indicator form of kamo-login's sign-in pane ribbon: a thin shaded diagonal band across an item's top-left corner, in any colour, at three sizes. It clips itself to its own corner box and inherits the parent's radius, so a parent only needs position: relative. It replaces the rail on the bug card, the drawer's status-reason callout, the thread's quoted parent and its replying-to bar, and the SI handoff card shown in the thread (shared with Live Support).

  26. · KlusterServices

    Svc_iot may subscribe to iot.live.device.> — the IoT production canary watches its own live frame (SP14)

  27. · kamo-marketing

    Announce IoT Devices — the /features category, the capabilities group and /device-compatibility go live (SP14 T+0)

    IoT Devices was published on 2026-10-21 03:47 UTC (catalog override COMPLETED + available, owner-approved). The compatibility page reads the live feed: 8 services today.

  28. · kamo-internal

    Plain-language approval cards and a premium approvals inbox

    Owner order 2026-10-20: the Interaction Center's Approvals tab and the approval popups showed members GUIDs and JSON. Every approval now reads as a card a non-technical person understands: the SI's face and name, one sentence of what it wants to do ('Missir Juan Jesus wants to mark the task “Call back Jane about the appraisal” as done'), the records it touches as chips that open them, the exact message it will send (email, text, chat, call, meeting), the details as labelled fields (money, times in the reader's zone, phones and addresses as their popups), why it is asking, the risk in plain words, what approving and declining do, and a countdown to when it lapses. The raw request sits only under a closed Technical details. Approve, decoder with a note, ask the SI in a chat, and edit the wording before approving where the server allows it; A / D / E shortcuts. The inbox (Interaction Center tab, and the Workforce hub with a reading pane beside the list): search, filters by kind and risk, sorting (soonest to lapse first), multi-select with Approve all / Decoder all (high-risk ones named first), quick approve and decoder on each row (a high-risk request opens instead), keyboard navigation, optimistic rows that leave as they are decided, loading skeletons and a warm empty state; Framer Motion under MotionConfig reducedMotion=user, CSS transitions with their own query; light and dark; phone layouts. Strings in the dictionary (pushed first); a phrase the dictionary lacks or that drifted from the server falls back to the server's English, never a key.

  29. · kamo-internal

    The Devices (IoT) nav option badges open alarms, pulses while one waits, and its menu leads to Alarms

    Owner, 2026-10-20 (IoT close-out F12): IoT alerts stay e-mail only; alarms reach people in the app. - Devices (IoT) is a menu (toolKey iot) of its pages, the tab bar's own rows (IOT_TABS), Alarms among them with the open-alarm count, then Devices (IoT) settings for a member who may open a settings tab. - The trigger's badge is the open alarms the member may see (the alarm summary, shelved/suppressed left out by the server); the icon pulses (blinkIcon, the mail/support treatment) while one waits for an acknowledgement. Live by the IoT notification pulse, rt.org.iot, focus/reconnect and a one-minute floor; a failed read keeps the last count rather than claiming none. - Launchpad (sectionsForTool) and the command palette (lands on /iot) follow. - Nav badges: the light palette's error red in both themes (dark #f44336 under white was 3.7:1). Shots /tmp/iot-wt/fu-shots/F12 (rail expanded/collapsed, bar; light/dark; axe clean).

  30. · InitializerService

    KamoCameras is included in Business and up, and on every universe's Premium rung and above

    Owner, 2026-10-20 (IoT close-out F11): Business, Enterprise and their equivalents in the other universes. - PlatformTierMatrixMigration: Business gains KAMO_CAMERAS (Enterprise inherits). - UniversePackages: Family/Community/Personal Premium gain it (Enterprise/Pro inherit). - TIER_LADDER: businessUp (was platformOnly) plus the universe rungs from UniversePackages. - KamoCamerasTiersTest pins the ladder; UniverseCatalogMigrationTest's contracted packages follow. Production rows were written first **************** 2 catalog rows, 20 plan rows; sign.pink's plans exclude it, as SP14 E2 did for IoT), because pushing KI runs nothing.

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