Allow SWITCH_MODEL to reset a session to Auto
handleSwitchModel always UUID-parsed modelId and errored on null, so a session could never be reverted to automatic model selection mid-chat. Parse modelId as a...
Accept X-***-Token for mobile clients in OTKPreAuthFilter
per-tab session id as X-***-Token (matching **************** When present (and no X-OTK), resolve the session non-consumingly and set the same request attribute...
Route /api/email + /api/support through the api host
(EmailService) and Support (MediaService, same upstream as /api/media) were unrouted → 404. Add both forwards and fix email.service.url from a localhost default...
Steward-triggered agency-AUS run proxy
Adds POST **************** — the steward "Run AUS" trigger the read-only underwriting console lacked. Gated on operator (GD); the organizationId and acting memb...
Explicit priority so the OTA updates route wins over the general theme route
Traefik ranks by rule-string length; the general /public/ theme route is longer, so the expo-updates header injection never ran. priority:100000 forces the win.
Self-hosted expo-updates headers for Mobile Copilot OTA
expo-protocol-version:1 + expo-sfv-version:0 response headers that the expo-updates client requires and static MinIO cannot emit. Longer path prefix wins over t...
VendorOrder + VendorOrderEvent entities for WS3 vendor-order spine
The greenfield 3rd-party order-of-record **************** SCRA). VendorOrder = partial-WORM async order (ClosingArtifact idiom: opaque vendorKey/externalRef, fr...
Stamp document own-date to freshness clock (WS1 activation)
After vision extraction, propagate the document's own effective date (asset.statementPeriodEnd for bank/broker/retirement, employment.payPeriodEnd for paystubs)...
Consume @kamo/* shared libs, delete duplicated web copies
kamo-internal now imports the shared TS packages it originally seeded (one - avatarUrlTransform → re-exports @kamo/media-core (getAvatarSizedUrl, transformAva...
MortgageAmortization — monthly P&I from loan terms (WS6 support)
The one PITI component not stored on the loan. Standard fully-amortizing formula P·r·(1+r)^n/((1+r)^n−1); zero rate degrades to straight-line; non-positive prin...
ClosingReadinessEvaluator — loan-level clear-to-close gate
Rolls a loan's obligations up to the funding question the end-to-end gap analysis raised ("service the loan all the way to funding"): clear-to-close iff zero ad...
QualifyingRatioEngine — the reproducible dti keystone (WS6)
Composes the four cores (income, liabilities, PITI/DTI, reserves) into ONE QualifyingSnapshot: qualifying income, reconciled monthly debt, assembled PITIA, fron...
ReservesCalculator — eligible-asset haircuts → PITIA months (WS6)
Derives reserve months from actual assets with standard agency haircuts — liquid deposits 100%, brokerage 70%, vested retirement 60%, gift/borrowed excluded — d...
PitiDtiCalculator — PITI assembly + front/back DTI (WS6)
Pure ratio core completing the DTI trio with LiabilityReconciler + the income core: PITIA = P&I + taxes + HOI + HOA + MI + flood; front = PITIA / income; back =...
QualifyingIncomeCalculator — base + variable core (WS5)
Pure/deterministic income core: base salaried = conservative lowest-of available evidence (paystub / W-2 / VOE); variable = 2-yr average with a declining-income...
LiabilityReconciler — agency payment-inclusion rules (WS6 core)
Pure/stateless computer turning each liability into the monthly payment that counts against DTI, with a cited rationale: omitted/paid-off excluded, leases alway...
Explicit-period quantity spec for delta successors
RequirementQuantity gains an explicit periods list (+ deltaJson builder); when present it IS the required set, so a successor can be scoped to "just send August...
**************** as the single period-key source
Adds periodKeyFor(date) so the write-path (satisfier stamping) and the coverage evaluator key periods identically; evaluator now delegates to it. Pure/additive,...
Period-coverage primitives for period-aware document collection
The pure, additive foundation of period-aware collection (doc 06 §4) — the first slice of the bank-statement "collect only the months I don't have yet" fix. Zer...
Replace forked chat with hosted <kamo-chat> embed; delete legacy proxy widget
Swaps the forked AI/live-support React chat (PublicChatWidget + AiChatPanel + LiveSupportPanel + the /api/chat/** server proxy routes) for the hosted, self-them...
Accept X-***-Token header on my-networks + all-networks
getMyNetworks/getAllNetworks only read the OTK request-attr or the *** cookie, — no org beyond the device-exchanged primary ever loaded, and the active org had ...
I18n the LabelManager software-identity labels via next-intl
Replace literal strings with **************** keys (added to the translation dictionary). English fallback covers locales pending translation.
Add install-QR (self-hosted APK) to Setup Mobile App tab
Install/Sign-in toggle: "Install" shows a QR to the signed release APK on the new phone can download+sideload it; "Sign in" keeps the password-gated OTK flow.
Web Chat Integration design customizer + live preview
Adds a Customize dialog to the Web Chat Integration tab: an editor form (colors, copy, layout, behavior, AI prompt) on the left and an instant, non-interactive ...
Web Chat Integration tab — list, create, snippet (BFF + UI)
Phase 2 core of the Web Chat Integration settings tab: BFF routes proxying to the Phase-1a MediaService CRUD, a typed client, and the /settings/features/chat ta...
Kamo-register honors software auth logo + name
- DynamicMetaLoader: read software identity + auth selectors from config.json, resolve tab title, persist auth logo/name state to sessionStorage - brand.ts + ...
Kamo-login honors software auth logo + tab title
- DynamicMetaLoader: read software identity + auth selectors from config.json, set tab title from resolved name (authNameBrandSource), persist auth-logo state...
LabelManager software identity UI + internal tab title
- Company Info: software name/short-name + login/register name + tab-title selectors - Branding: software full/simple logo uploads, override toggles, and per-su...
3-stage org onboarding guidance (create → finish DNS → enter)
Generalize the first-org hero into a single stage-aware guidance panel keyed on the member's owned-org count + DNS status (from /api/security/org/my-networks): ...
Dual company/software resolver + delivery + consumption
- Organization.ts: deliver software identity + per-surface selectors via OrgContext - brand.ts: **************** (+ vitest, 8 cases) - ThemeLogo: logoSoftware/l...
Software logo upload types + config.json bake
- uploadLogo: explicit object-key switch **************** with rejecting default so a software upload can never clobber the company logo.svg - copyFolder: pre...
Persist software branding fields via patchOrganization whitelist
First-org CTA hero for members on the platform org
Show an onboarding hero at the top of the home launchpad inviting a KamoCRM-platform member (not a team member) who hasn't yet created a child org to spin up th...
TURN-REST credentials endpoint for the mobile softphone
GET /api/voip/turn/credentials mints ephemeral coturn creds (HMAC-SHA1 over "<expiry>:<memberId>" with the shared static-auth-secret) so native/cellular WebRTC ...
Expose per-org primaryColor + logo URLs on /my-networks
Each org row now carries primaryColor (Organization.colors.colorPri, '#'-prefixed to match config.json) and derived logoUrl/logoSimpleUrl (theme.<domain>/public...
Make WebChatIntegration create() @Transactional (no orphaned key on integration-save failure)
Snapshot web-chat integration id on support visitor + ticket
Resolves the WebChatIntegration by creatingKeyHash (enabled-filtered, consistent with bootstrap()/AI-prompt resolution) once in createSupportSession and stamps ...
Per-integration public AI prompt + session attribution
Upgrade the public-chat system-prompt waterfall from per-org to per-integration: PublicAiChatController now reads the X-Public-Chat-Key-Hash header (nullable) f...
GET /api/public-chat/bootstrap gateway route
Add bootstrap endpoint that reuses the existing proxyWithAuth pipeline (key validation + opt-in origin + PUBLIC_CHAT scope + rate-limit + X-Public-Chat-Key-Hash...
Public-chat bootstrap config resolver
Adds an internal GET **************** that resolves a WebChatIntegration by X-Public-Chat-Key-Hash and returns its resolved design/behavior config (default-fill...
Wire optional mediaservice-push secret for FCM/APNs credentials
Mounts the FCM service-account JSON + APNs .p8 from an optional `mediaservice-push` secret at /etc/kamo/push and sets the APNs key-id/team-id from the same secr...
Tightly-cropped Copilot icon + bare NavPri entry
Added a trimmed icon.png (glyph fills ~82% of the frame) and pointed the home pill, NavPri entry, Interaction Center tab, and QR center at it. Stripped the NavP...
WebChatIntegration CRUD (mints key + integration, org-scoped)
Org-facing management API for the Phase-2 web-chat settings tab. On create, mints the underlying PublicChatApiKey (same key-gen approach as PublicChatKeyControl...
Add WEB_CHAT_INTEGRATION_ID attribution columns to visitor/ticket/ai-session
WebChatIntegration entity + repo + DTO + default design config
Add "Access Copilot Mobile App" entry points on home + NavPri
Both surfaces dispatch an `open-interaction-center` event that NavTop listens for to open the Interaction Center on the Setup Mobile App tab. Home shows a label...
Rename tab to Setup Mobile App; even full-height spacing; logo centered on title with description beneath
Password-gate the QR, single-line tab, logo-left header, 10-min code
- Member must re-enter their password (server-verified via /api/mobile-access-otk, which mints the OTK only on success) before the QR is revealed — prevents s...
Like what you see shipping?
Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.