Endpoints to set a subscription's auto-renew and an order's notes in any status
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.
Approving a card order grants paid access too
AUTO_BILL orders waited for a Stripe checkout that subscription invoicing no longer uses; the ledger charges the saved card on each billing day instead.
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...
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 PaymentI...
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 ...
The billing job takes each subscription and invoice in its own transaction
Its first run raised Harmony's October invoice and lost it when one audit insert failed, because the whole prepare step was one transaction.
Subscription events store JSON states; billing steps run one row per transaction
**************** are jsonb, and every caller wrote a bare status like ACTIVE - an invalid JSON insert that rolled back whatever it was auditing (order activatio...
The POS proxy passes a PDF or an empty reply through instead of failing it as JSON
The invoice PDF and any 204 went through response.json() and became a 500.
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 s...
Stripe bills add-on licenses held, not mailboxes or extensions in use
Every add-on now takes its quantity from AddOnLicenses, the rule the order calculator and subscription invoices share: licenses bought, defaulting to the seat c...
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 subscri...
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 n...
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. Al...
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...
Background work uses three engine slots per pod and is sent as low priority
One background slot per pod left three of the engine's four streams idle during a dictionary sync. Background callers (a wait above the 100-second default: the ...
Four streams of four threads, and a lane that keeps one free for chat
Measured on the nodes' CPU class with the dictionary sync's own traffic (15-key chunks): one stream of eight threads did 1.5 keys/s, two of eight 1.8, four of f...
Read subscription invoices, events and agreements under the keys the server sends
The server answers invoices/invoice, events and agreements/agreement; posApi read subscriptionInvoices, subscriptionEvents and subscriptionAgreements, so the In...
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. Stri...
Catalog edits reach only the caller's organization; own-order callers cannot comp or price themselves
Every update and delete of a subscription plan, price, feature, add-on, bundle, volume discount, promotion or agreement template now checks that the row belongs...
Name the organization that owns a subscription catalog row
The catalog update/delete methods take a uid alone, so a caller holding the catalog right in any organization could edit another organization's plans, prices, a...
A missing locale file renders English instead of throwing
i18n/request.ts and message-locales.ts imported messages/<locale>.json bare, so a build made while the dictionary had no file for a locale turned that locale's ...
Read Stripe events from any API version, and replay the ones that failed
The live webhook endpoint renders events at 2026-03-25.dahlia; stripe-java pins 2024-12-18.acacia, so every invoice, payment and subscription event since has fa...
Write Romanian with comma-below s and t
The model mixes the legacy cedilla forms into Romanian (6 of 90 such letters in the chat widget's regenerated file) and the dictionary's earlier Romanian did to...
Drop the old engines' deploy steps, apply MADLAD's alias Services, update audit and docs
Completes 56b37fa, which removed the manifests: without this the workflow still ran steps for directories that no longer exist. The workflow now applies madlad/...
Remove LibreTranslate, Bergamot and IndicTrans; MADLAD serves every pair
TranslateService speaks only to madlad now (translateservice 5c7605b), verified end to end: every Kamo locale including Tamil and Swahili, inbound ru->en and ta...
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 o...
Beam 4 only for labels, beam 2 up to 64 tokens
Cost is tokens x beam. Measured in the cluster with the old engines still running: one stream 77 chars/s and two 115 chars/s on short strings at beam 4. Sentenc...
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...
One pod translates an article, not every pod at once
The sweep's fleet-wide lock is held only while it queues work, which takes milliseconds, so each pod ran its own sweep a minute or two apart and queued the same...
Never send an engine a text longer than it takes
IndicTrans answers a request over 20,000 characters with a permanent HTTP 413, so a long help article could never be translated into Tamil; a LibreTranslate wor...
Translate an article's words, not its Lexical JSON
contentJson was sent to the translation engines as if it were a sentence. On 2026-10-22 one sentence of it came back from Russian with the sentence gone and the...
Memory limit 14Gi -> 20Gi, request 10Gi -> 12Gi
Seven-day peak working set was 13.8 and 13.1 GiB against the 14Gi limit, so the kernel reclaimed the mmapped argos models and en->ru on a help article paid cold...
Creating a MORTGAGE market gives the organization its lender profile at once
A MORTGAGE market's lender profile (and its five config rows) was only created by the boot-time self-heal, so a market created while SecurityService was running...
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.
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 stil...
Open deals are always expanded, the loan officer shows their photo, and the loan count reads one way
- Open view: every deal shows its loans, with no expand/collapse control. Past and All stay collapsed by default and expandable. - The loan officer avatar was...
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. Is...
Back from a loan returns to the screen it was opened from, and a loan always shows its full number
- The loan page's Back was hard-coded to /commerce, which opens the first market's home. Every opener (Pipeline, Board, document queue, applications tab) now ...
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 numb...
The mortgage pipeline loads in a handful of queries, and a deal can be renamed and take a second loan
The pipeline's two reads were N+1 on the round trip: - GET /mortgage-apps loaded plain AppMortgage rows, and each one then fired a SELECT per inverse @OneToO...
A tool menu stays selected on any of its pages and the pages beneath them
The last change lit a tool menu (Mail, Docs, Support, IoT, Settings, Cameras) only when a row's href was exactly the page open, and most rows carried no href at...
Numbers and addresses open their popups, unseen records in plain words, plain labels, rights cases
Approval follow-up 2026-10-21 (controller review of the approvals pane). - The headline draws every phone number and email address the card names (card.conta...
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 le...
Declare every right a tool's service enforces; plain words for unseen records and numbers
Approval follow-up 2026-10-21 (controller review of the approvals UI). Rights (item 4): an audit of every tool's declared rights against the rights its downstr...
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-rig...
A charter item's tool is behavior; its grant provenance is not
CharterItem gained toolName and the standing-permission provenance (53e6e2cd6), so the compile-time check that every field is listed failed the build. toolName ...
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 rev...
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 ...
Like what you see shipping?
All of it arrives in your workspace on its own. Start on the free plan and read this page again in a month.
