Changelog
What's new.
Every improvement to the platform, as it ships.
· kamo-internal
The Monitoring tab, the practice monitoring queue, and the organization's remote-monitoring switch
· kamo-internal
Wire remote monitoring into the chart, the practice queue, the masthead count, the chart summary and the patients tour
· DaemonService
DaemonService ticks remote-monitoring close/no-data hourly, reconciliation every 15 minutes, alert escalation every 5
· kamo-shared-library
Iot.alarm_notice email template
· kamo-shared-library
SP06 alarm logic — ISA-18.2 state machine, escalation, suppression, schedule, flood
· kamo-shared-library
SP06 rule logic — loop maths, fingerprints, fire keys, templating, reasons
· kamo-shared-library
SP06 rule logic — solar, schedules, site days, conditions, triggers
· kamo-shared-library
SP06 vocabulary, entities and read-only repositories
25 enums (stored by name), IotServiceJobOrigin (SP13 ships on it), 17 entities matching the SP06 DDL and their read-only repositories; IotActivityKind += AUTOMATION_ENABLED, AUTOMATION_DISABLED (SP11-D6).
· MediaService
Share-card endpoint and server-only system events (IoT SP04)
POST **************** IoTService posts the IOT_SHARE card into a members' support ticket or Exec2Exec conversation as the sharer's system event, through the one system-event writer (now also answering the stored message id). X-Internal-Auth = IOT_INTERNAL_AUTH_SECRET (Secret iot-internal-auth, already mounted for SP01's STOMP authz), constant-time; 503 blank, 403 mismatch. A Live Support (visitor) ticket is refused 409 SESSION_TYPE; a card may not carry a key the writer owns. Every client write path now refuses text that parses as a system event with 400 SYSTEM_EVENT_RESERVED: member send, message edit (into or out of a system event), Exec2Exec post, website visitor send, bug-report comment, and forwarding (a system event is not forwardable; a forged comment is refused). A consent card must not be forgeable by a participant.
· EmailService
NoReplySubsystem.IOT, the preview sample and mirrorToPush
IoT Devices SP06: alarm letters (iot.alarm_notice) audit under IOT; the template preview has sample values; POST /api/internal/notifications takes an optional mirrorToPush (false = bell card only, no phone push). Producers that do not send it behave exactly as before. Also maps two canonical templates the guard **************** found unattributed on main: LEADS_AVAILABLE -> LEADS, SUSPICIOUS_SIGNIN_DETECTED -> SECURITY_ALERTS.
· KBService
Internal task endpoint for IoT automations
POST /internal/checklists/iot/tasks: one task on behalf of an automation's owner, into the assignee's Inbox (SP06 CREATE_TASK). Notes must be on, the assignee eligible; a taken proposed id tells a retried run its task exists.
· kamo-internal
Settings → Phone → Do not block, next to Do not contact
Owner 2026-10-15: "remove it and add it to a do-not-block list". The organization's own numbers and staff lines, which the do-not-contact list never blocks and no opt-out puts on it. - New tab do-not-block (MANAGE_VOIP_SETTINGS via VOIPService, settingsMenu sub entry, no admin-bar link): suggestions of the organization's numbers, main numbers and staff lines (kinds, label, whose line, already protected or still on the do-not-contact list), each with Protect, which only opens the add dialog prefilled; channel filter (calls, texts, email, every channel), search, add with a note, remove with a required reason, and the history, where an opt-out it kept off the do-not-contact list shows as "Opt-out not recorded" with its source and what was said. Every number and address is a PhoneNumber / EmailAddress. - Do not contact: the add dialog shows the server's do-not-block refusal as written; an import names the addresses it left out because they are protected. - Keys: kamo-translation-dictionary (pushed first). Tests: DoNotBlockTab.test.tsx (5), DoNotContactTab.test.tsx (import case RED, then GREEN), settingsMenuTabCoverage (RED with the tab and no menu entry, then GREEN), the 20 source guards and check-i18n-keys --require-messages; tsc on the changed files.
· EmailService
An unsubscribe from one of the organization's own protected addresses is noted, not listed
Owner 2026-10-15: the do-not-block list beside the do-not-contact list. DoNotContactEmailBeans declares shared-lib's DoNotBlockList and hands it to the DoNotContactList: a protected address is never suppressed by the do-not-contact list, and EmailDoNotContactMirror's add for an unsubscribe of one leaves a SKIPPED note in the do-not-block history instead. Tests: DoNotContactEmailWiringTest (new; RED: the old beans did not compile against the new shared-lib), DoNotContactSuppressionTest, EmailDoNotContactMirrorTest, DisclosureLedgerWiringTest.
· kamo-shared-library
The do-not-block list, the allowlist beside the do-not-contact list
Owner 2026-10-15: "remove it and add it to a do-not-block list" (the company's own main line had been put on the do-not-contact list by a test call). For an organization's own numbers and staff lines, so a test call or a misheard phrase never blocks them. - DO_NOT_BLOCK (unique ORG_ID, CHANNEL, ADDRESS; CHANNEL CALL | SMS | EMAIL | ALL, ALL = a phone number's calls and texts, an address's email) and the append-only DO_NOT_BLOCK_EVENT trail (ADDED, REMOVED with its required reason, SKIPPED). - DoNotBlockList: add (idempotent; refused while the do-not-contact list holds the address on a covered channel: remove it there first, with a reason), removeById (reason of 3+ characters), protecting/isProtected, search, history, activity, entriesFor, recordSkipped. - DoNotContactList now takes the DoNotBlockList (constructor change; VOIPService, EmailService and kamoai-service declare both beans in the same push): find/isBlocked/filterBlocked never block a protected address on its channels; add() of a protected address SKIPS an automatic opt-out (VOICE_OPT_OUT, SMS_STOP, EMAIL_UNSUBSCRIBE) with a SKIPPED note and Added(null, false, keptBy), and REFUSES a person's add (MANUAL, IMPORT) with field doNotBlock and the sentence "{address} is on the do-not-block list for {channel} ({note}), so it can't be added to the do-not-contact list. Take it off Settings -> Phone -> Do not block first." DDL: voipservice **************** (applied 2026-10-18 04:16Z). Tests: DoNotBlockListTest (7, RED: did not compile on origin/main), DoNotContactListTest, **************** (both repositories' finders), SharedLibBeanSafetyTest.
· VOIPService
Settings → Phone → Do not block — the API, the suggestions, and STOP texts that skip the company's own lines
Owner 2026-10-15: "remove it and add it to a do-not-block list". The allowlist beside the do-not-contact list, for the organization's own numbers and staff lines. - DDL **************** (DO_NOT_BLOCK, DO_NOT_BLOCK_EVENT append-only for kamo_app), applied 2026-10-18 04:16Z; re-run is a no-op. - DoNotContactBeans declares shared-lib's DoNotBlockList and hands it to the DoNotContactList (VoipRepositoryScanTest pins both repositories). - /api/voip/do-not-block (MANAGE_VOIP_SETTINGS, as the do-not-contact admin): list and search, add {channel CALL|SMS|EMAIL|ALL, address, note}, POST /{id}/remove with a required reason, history, activity (with every opt-out it kept off the list), and /suggestions: the organization's numbers, phone-server main numbers and staff lines from VOIP_NUMBER_OWNERSHIP (by ORG_ID), one row per number with what protects or lists it. Suggestions add nothing. - Do not contact: a person's add of a protected address answers 409 field doNotBlock with the list's sentence; an import names those apart (protectedAddresses). - A STOP text from a protected number is not listed (the shared list skips it and notes it); the log line says so. Tests: DoNotBlockControllerTest, DoNotBlockSuggestionsTest, DoNotContactControllerTest, VoipRepositoryScanTest (RED: did not compile against the new shared-lib), SmsKeywordServiceTest, SmsGatewayTest, **************** VoipMessageServiceKeywordTest, InternalAuthFilterKamoaiTest — 98 green.
· EmailService
Gate the RPM_ALERT kind on REVIEW_CLINICAL_RESULTS and list it after LEAD_CALLBACK
· kamo-shared-library
Sharing enums, SHARE_* activity kinds, DomainAliasType.IOT
· KlusterServices
Pre-issue iot.<apex> certificates, PDB kamowebiot, availability probe
iot joins BROWSER_ONLY_ALIASES and STATIC_DOMAINS on both platform apexes so the first share recipient never meets a missing certificate; monitoring/ is applied by hand (see runbook, Task 34).
· SecurityService
SP12 remote-monitoring endpoints, the portal connect-devices handler and their guards
· SecurityService
SP12 enrollment, consent, pause/resume/end/revoke and the connect link
· SecurityService
SP12 remote-monitoring management time entries
· SecurityService
SP12 clinician-set limits and the alert worklist
· SecurityService
SP12 RPM billing preview and the draft-claim handoff
· SecurityService
SP12 monitoring reads, the portal link, and home readings kept out of the chart's recent window
· SecurityService
SP12 remote-monitoring foundations — write gate, access, audit, IoT client, merge hook
· kamo-internal
A run's tool calls say when the SI acted on a teammate's order, and with which of their rights
The No Insubordination Rule (owner 2026-10-15): a tool call an SI made on a teammate's direct order carries the order's basis, the teammate and the rights they lent (kamoai-service W4 audit rows). The run drawer adds "On {name}'s order, with their rights: …" to such a call (runs.onOrderOf / onOrderOfUnnamed, dictionary e3ba7e79). Tests: RunDetailOrderLine.test.tsx (3).
· MCPGatewayService
The No Insubordination Rule — an SI carries out a teammate's direct order on their rights
Owner 2026-10-15, refined the same day: "It should apply to any team member. But just because a team member (human or SI) has more rights, does not mean that automatically means the SI they are talking to assume their rights. It has to be a direct request or anything similar to an order. Otherwise, the SI should reinforce they do not have that level of privilege." One delegation point (OrderDelegation): for an SI's call or tool list in a run, the order is the request the SI cited, else the message or task that woke the run, verified as SP95's requests are (team chat or task only, addressed to the SI, within the hour, among the run's wakes, no outside content read), by any team member, a person or another SI (RequestVerifier.verifyOrder / inferOrderFromRun), and only when its words are an order (DirectOrder) or it is a task assigned to the SI. SecurityService then mints the SI an order-scoped *** for the run; the call runs as the same SI with that principal, so the rights check here and every downstream service see the union. A question, news or chat lends nothing, and the RIGHTS refusal then tells the SI to say plainly it lacks that level of access. - Disclosure (CP07): the run reads for the requester (OrderPrincipal), and onward sharing carries the requester's VERIFIED_REQUEST grant, judged by their own release authority. - Audit: authority_basis REQUESTED_BY_TEAM_MEMBER_ORDER, on_behalf_of_member_id, borrowed_rights (DDL **************** applied). - tools/list names the order in _meta[com.kamocrm/orderedBy] so the runtime never keeps that list. - An order-scoped session presented for any other run is no session; nothing is lent on a lent session. - Unchanged: the kill switch and pauses at the door, the charter, the risk ceiling, PHI, limits, the outreach gate and the do-not-contact list. Tests: ToolCallPipelineOrderTest (13; 9 RED without the delegation point), DirectOrderTest, OrderPrincipalTest, RequestVerifierTest (+2), CallerContextFactoryTest (+1); with ToolCallPipeline*, McpServerController*, AudienceFilter*, ReadAudience*, DisclosureGate*, *Audit*, ToolListParity*, PhonePack*, *Coverage*: 300+ green.
· SecurityService
The No Insubordination Rule — a teammate's direct order lends an SI their rights for that run
Owner 2026-10-15, refined the same day: any team member (a person or another SI) who gives an SI a direct order lends it their rights for the work that carries it out; talking with the SI lends nothing. POST **************** (KAMOAI internal secret) mints the SI an order-scoped *** for one run: its own rights UNION the requester's, less the SI floor (AiRightsFloor) and the SI's own explicit NUKE rows, closed over the rights hierarchy. A person lends their live session rights; an SI lends its standing rights only, computed from its rows, so nothing is lent on transitively. The session is the SI's own (memberID, actorType AI), lives 15 minutes, carries a delegation block {basis REQUESTED_BY_TEAM_MEMBER_ORDER, requesterMemberId, runId, orderRef, borrowedRights}, and starts nothing a sign-in starts. The exchange's stops (kill switch, org pause, the SI's pause or retirement, an inactive membership, no supervisor) refuse it, and are read again once it exists. A rights change of the SI ends such a session instead of rewriting it. The SI's standing session never gains a right. Tests: OrderDelegationServiceTest (8), KSessionServiceIdentityTest (12), AiSessionExchangeServiceTest, AiRightsChangeListenerTest, PostAuth****: 51 green.
· kamo-internal
Settings → Phone → Do not contact, and the softphone warns before calling a listed number
Owner 2026-10-15: one company-wide do-not-contact list per organization, scoped per channel. - Settings → Phone → Do not contact (MANAGE_VOIP_SETTINGS, settingsMenu sub entry, no admin-bar link): the call mode (warn and dial on confirm, the default, or block), channel filter, search, add, import (paste or .csv/.txt, up to 1000), remove with a required reason, and the history (every add and removal, by whom, why). - The softphone: SoftphoneContext hands every consumer a guarded dial, so every person's call (the Softphone window's Call, and every Call elsewhere, which opens it prefilled; the JustCall external dialer too) asks GET /api/voip/do-not-contact/check first. A listed number shows "{number} asked not to be called on {date}" with Cancel / Call anyway, or, when the organization blocks, OK only. Only the CALL entry counts. A check that fails dials (an SI's call fails closed in kamoai-service). - Keys: kamo-translation-dictionary 7b74200b (pushed first). Tests: DoNotContactTab.test.tsx, DoNotContactDialGuard.test.tsx, doNotContactDial.test.ts (RED on origin/main, GREEN here), settings menu coverage; the 20 source guards and check-i18n-keys --require-messages against the pushed dictionary.
· kamo-internal
SI routing shows what SIs use now — the effective model per kind of work and whether the org's order or the automatic default chose it; for speech-to-text, the model on phone calls and in meetings, streamed or per sentence, with the automatic accuracy-ranking hint
Owner 2026-10-15: "If a model is added and enabled to the SI Providers that supports speech to text, it should use the best one." Reads AIService's effective / effectiveCalls / effectiveMeetings on each routing entry; an AIService without them shows nothing new.

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