Stop the history fetch from deleting the text that just arrived
SmsThread loads its page and REPLACED the list with it. A message landing between the query executing and its response arriving was appended by the live subscri...
Put the stream in the config the pod actually reads
The previous commit set nats.jetstream.stream in **************** shipped, deployed β and the new pod still logged NATS stream 'CHAT_MESSAGES' already exis...
Carry an arriving text across the boundary the dock sits above
An inbound SMS never reached an open SMS window, and the reason was not the transport everyone went looking at. SmsMessageProvider was mounted in Authenticated...
Stop letting one bad boot deafen the VOIP relay for the pod's life
The relay subscribed once, from @PostConstruct, and never again. When VOIPService's voip.> stream did not exist β which it did not β both replicas logged exactl...
Give voip.* a stream to live in, and stop lying about who sent the text
There was no VOIP_MESSAGES stream in NATS at all. Every `voip.*` publish answered 503 No Responders Available and both media pods logged, once, at boot: [V...
Record what the carrier says happened to a text, and check 10DLC before it matters
Sending now succeeds and nothing arrives. Telnyx accepts the message, returns an id, and Verizon then refuses to deliver it: status delivery_failed code ...
Normalise the sender at the gateway, and stop calling a refusal retryable
The previous commit normalised the sender number where it is stored in the number inventory and on the carrier, and the send still failed with the same carrier ...
Normalise sender numbers to E.164 before they reach a carrier
Sending a text failed with "The message could not be sent. Try again in a moment.". Telnyx's own answer, from the voipservice log, was specific: Telnyx POST ...
Merge branch 'feat/one-scrollbar'
One scrollbar for every scroller in the app, with the terminal window's five controls on all of them.
Take the two "could not start" fallbacks out of the source
Both SMS refusal paths quote the server when it gives a sentence and fall back to one of their own when it gives only a machine code. Those two fallbacks were E...
Stop the prescribing-disclosure test being flaky
It passed alone and failed inside the full suite. The effect calls **************** and sets state in a .then(), so settling the mock's promise, running the con...
Pin the exact JSON the clinical client parses
Every field in these bodies is read by name in app/lib/patients/ehrApi.ts and nothing was checking the server still emits them. The service tests pin that the e...
Show why the exchange network is unreachable
The outside-records panel could only say "not connected", which reads as an outage to wait out. The server now sends the reason alongside -- this practice has n...
The exchange status says what would make it connected
The status endpoint is asked before the UI offers a network query, so a practice that is not onboarded sees an explanation instead of a button that always fails...
Mirror the EHR stage, and guard the mirror
ServiceType.ts is a hand-maintained mirror of the Java enum and nothing was checking it. RoleRightType has had a parity guard since three EHR rights went missin...
Never auto-provision Patient Records into a tenant
Two of the three paths that would hand a clinical record system to orgs that never asked for one, now that ServiceType.EHR is COMPLETED and therefore available....
Publish Patient Records, and make that safe to do
ServiceType.EHR was held at TESTING long after the vertical was finished, because AppCatalogService derives availability from COMPLETED and three separate paths...
Say what the prescribing safety check did not cover
The panel rendered a safety block only when there were warnings, so a prescription that came back clean said nothing at all -- and this platform has no licensed...
Disclose that drug interactions are not checked
Prescribing ran three checks the practice's own data can answer and no drug-drug interaction check at all. Declining to build one was right -- interaction knowl...
Tighten the screenshot drop hint
"Drag images here, paste from your clipboard, or click to browse" becomes "Drop image, paste from clipboard, or click to browse" β the three things you can do, ...
auto-cert: let the junk-cert cleanup actually see the junk it was written for
cleanup_orphan_certificates() listed with '-l auto-cert.kamo/fqdn'. That label is newer than the scanner certs the function exists to remove, so the selector ex...
auto-cert: issue an org's certificates as a batch, not one every 90 seconds
A new organization needs a certificate for all eleven of its hosts, and each one is a separate cert-manager Certificate. The loop waited for each host to become...
Prefer brotli on the theme host, and correct the previous rationale
Two things, one of them a correction to the commit before this. The previous commit justified `encodings: [br, gzip]` with a probe against api.kamocrm.com. Tha...
Prefer brotli, stop compressing what is already compressed
The shared `compress` middleware was `compress: {}`, which is three separate defaults and none of them is the one we want. Traefik picks gzip whenever the clie...
Revert "feat(security): enforce a CSP, COOP and Trusted Types"
This reverts commit ****************
Finish the details the first pass left rough
Nine small corrections, each with a visible symptom. The drawer opened on ~0.4s of blank panel: `loading` started false, so the first committed render fell thr...
Load with explicit column lists -- positional COPY corrupts silently
COPY t FROM STDIN with no column list maps CSV fields to the table's PHYSICAL column order. The CSVs come from COPY (SELECT *) on CockroachDB, and Hibernate cre...
Load with explicit column lists -- positional COPY corrupts silently
COPY t FROM STDIN with no column list maps CSV fields to the table's PHYSICAL column order. The CSVs come from COPY (SELECT *) on CockroachDB, and Hibernate cre...
Schema parity with CockroachDB -- 714 tables, 8706 columns
The drift diff earned its place. KamoInitializerService builds the schema from JPA entities and produced 599 tables; production carries 714. The 115 difference ...
Schema parity with CockroachDB -- 714 tables, 8706 columns
The drift diff earned its place. KamoInitializerService builds the schema from JPA entities and produced 599 tables; production carries 714. The 115 difference ...
Full CockroachDB->YSQL translator for the universe migrations
All 15 migrations now apply cleanly to YugabyteDB: 111 tables, matching CockroachDB exactly. Eight distinct CockroachDB-only constructs had to be handled, found...
Full CockroachDB->YSQL translator for the universe migrations
All 15 migrations now apply cleanly to YugabyteDB: 111 tables, matching CockroachDB exactly. Eight distinct CockroachDB-only constructs had to be handled, found...
CSV export via COPY TO STDOUT, plus a CSV-aware verifier
Transport is COPY ... TO STDOUT WITH (FORMAT CSV), not `cockroach sql --format=csv`. The latter renders SQL NULL as the literal string "NULL", indistinguishable...
CSV export via COPY TO STDOUT, plus a CSV-aware verifier
Transport is COPY ... TO STDOUT WITH (FORMAT CSV), not `cockroach sql --format=csv`. The latter renders SQL NULL as the literal string "NULL", indistinguishable...
Make every sweep schema-aware; kamo has 714 tables, not 680
Cross-checking SHOW BACKUP (714 objects) against a table_schema='public' inventory (680) exposed 34 tables living in five other schemas: email_metadata, email_p...
Make every sweep schema-aware; kamo has 714 tables, not 680
Cross-checking SHOW BACKUP (714 objects) against a table_schema='public' inventory (680) exposed 34 tables living in five other schemas: email_metadata, email_p...
Baseline capture for CockroachDB to YugabyteDB parity checking
Two passes: cheap batched count(*), then an order-independent checksum. The checksum sums per-row md5 hashes as integers rather than the obvious md5(string_agg...
Baseline capture for CockroachDB to YugabyteDB parity checking
Two passes: cheap batched count(*), then an order-independent checksum. The checksum sums per-row md5 hashes as integers rather than the obvious md5(string_agg...
Route the Apps & Features copy through next-intl
kamo-internal serves 22 locales and every user-facing string has to come from a message key β hardcoded English breaks every non-English operator. The tab and t...
Like what you see shipping?
Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.