Skip to content
KAMOUniverse

Changelog

What's new.

Every improvement to the platform, as it ships.

  1. · SecurityService

    Borrower e-signature surface — real native sign links, no stub

    GET **************** (party-gated) lists the loan's real KAMO_NATIVE disclosure/closing envelopes + recipient status via ESigService; POST **************** mints a fresh reachable signing deep-link (fail-closed: envelope must belong to the caller's loan). Backs the rebuilt closing-desk that deep-links to the native signing experience (doc 05 §5).

  2. · ESigService

    Internal mint-sign-link primitive for first-party signing surfaces

    POST **************** re-mints a recipient's access token and RETURNS the signing deep-link (no invite-email round-trip), so the MLOS borrower portal can hand an authenticated signer a live link. Refactors resend() to share the mint path; completed/decoderd recipients 409.

  3. · SecurityService

    WS3 vendor-order proxy — steward places/reads third-party orders

    Add MlosVendorClient (X-Internal-Auth → MLOSVendorService /api/vendor) + mlos.vendor.url config, and app-scoped endpoints: GET /{uid}/vendor-orders (operator view) and POST /{uid}/vendor-orders (staff — place an appraisal/title/HOI/VOE order, optionally bound to a THIRD_PARTY requirement so its callback satisfies it). orgId + loanFileUid resolved server-side; the vendor rail's honest status is relayed, never fabricated.

  4. · SecurityService

    Borrower-safe my-conditions projection for the portal conditions view

    GET /{uid}/my-conditions (party- or operator-gated) returns a narrow BorrowerConditionView **************** — never the internal actor/notes fields the steward LoanConditionDTO exposes. The portal joins these with the document requirements it already fetches (by loanConditionId) to group the checklist by underwriting condition.

  5. · SecurityService

    Per-borrower section GET endpoints to hydrate the capture UIs

    Add listPerBorrower (requireView, party-gated) + GET list endpoints for **************** returning {rows:[...]}. These back the new URLA borrower capture sections in KamoMLOS.

  6. · kamo-shared-library

    Borrower section read methods for other-income/expense/REO/gift capture

    The per-borrower repeating sections were write-only; add read projections **************** so the borrower capture UIs can hydrate existing rows via GET endpoints.

  7. · SecurityService

    Full credit-vendor abstraction + real reseller adapters

    Production tri-merge credit rail. The abstraction now passes the FULL 9-digit SSN (decrypted at order time from the borrower's encrypted record) + co-borrower for a JOINT pull — previously only ssnLast4 was passed, which no bureau accepts. New MISMO-2.4 protocol core (mismo/): CreditVendorProfile + CreditAuthScheme **************** MismoCreditRequestBuilder (individual + joint, full SSN, MeridianLink inline-login block), CreditResponseParser (tolerant score parsing across attribute orderings + bureau normalization + vendor-error detection). AbstractMismoCreditAdapter holds the shared order flow (validate → build → auth → POST with bounded timeouts → parse), config-driven with per-tenant overrides **************** from configJson). Named adapters for the most common mortgage resellers, each encoding its public protocol (auth scheme) with account creds as config: MeridianLink (inline login), Xactus (bearer), Factual Data / CBCInnovis / Credit Plus (basic) + the generic MISMO catch-all. CreditOrderService decrypts the full SSN via SecretCipher, resolves the co-borrower, and orders joint when present. Honest failures only, never a fabricated score. 12 tests green.

  8. · SecurityService

    Borrower clear-to-close proxy

    GET **************** — party-gated; resolves loanFileUid from the app and relays MLOSDocService's clear-to-close readiness.

  9. · EmailService

    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 attributes; an invalid token sets nothing, so controllers still reject with 401. Session-data protection unchanged.

  10. · APIService

    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 to the cluster service. forward() only passes the caller's session headers (X-***-Token) — no X-Internal-Auth injected — so internal endpoints stay protected and only session-gated functionality is exposed.

  11. · SecurityService

    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 member are SERVER-STAMPED from the session (never trusted from the client), and MLOSUnderwritingService re-validates the loan belongs to that org (fail-closed cross-org). Facts are server-derived downstream (DTI via LoanQualifyingRatioService, structural via ScenarioFactDeriver); the caller may still pass a fico/fresh-credit attestation. Nothing triggered a live AUS run before this — the run endpoints had zero callers.

  12. · KlusterServices

    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 the general /public/ theme route.

  13. · kamo-shared-library

    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, frozen identity, only status/result advance; a re-order is a NEW row). VendorOrderEvent = full-WORM append-only ledger (AusRun idiom: one immutable row per transition/callback, externalEventId dedup, payload for replay). VendorCategory += **************** (no ConnectionVendor peer — provenance lives here, never on locked Connection). Soft-FK-by-id, denormalized org/loanFileUid. KI @EntityScan(com.kamo) creates the tables; services stay ddl-auto:none.

  14. · SecurityService

    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) to MemberDocument.freshnessAsOf. This makes the MLOS requirement-satisfier age from the true statement/pay date instead of the upload time, so the period-coverage engine finally gets real period identity. Best-effort, idempotent, never breaks extraction; no schema change (the freshness_as_of column already exists).

  15. · kamo-shared-library

    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 principal/term fail-safe to 0.00 (never throws/divides by zero). Feeds PitiDtiCalculator's P&I input from ****************

  16. · kamo-shared-library

    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 advancement-blocking (prior-to-close/fund) conditions remain open; open non-blocking (prior-to-doc/post-close) conditions don't hold funding. Emits the deduped blockingCategories "what's left before you can close" list. Pure/stateless over caller-mapped ConditionState projections, mirroring ConditionClearabilityResolver — ships the rule, not the milestone wiring.

  17. · kamo-shared-library

    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, front/back DTI, eligible reserves, reserve months. This is the single deterministic derivation that must become the AUS 'dti' fact's sole producer — today that fact arrives borrower-typed or blank and nobody derives it. Pure/stateless, no I/O, no schema; called by nothing yet (safe to wire into ScenarioFactDeriver next). Same evidence always reproduces the same snapshot.

  18. · kamo-shared-library

    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 — divided by monthly PITIA. Completes the pure qualification suite (income + liabilities + PITI/DTI + reserves) an overlay minimum can gate on a real figure instead of a borrower-typed one. Zero PITIA → undefined. No schema, no wiring.

  19. · kamo-shared-library

    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 = (PITIA + debt) / income, as percentages. Zero income → undefined (not divide-by-zero). This is the deterministic derivation that must become the AUS 'dti' fact's sole producer. No schema, no wiring.

  20. · kamo-shared-library

    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 guard (use the lower current run-rate when trending down); rental at 75% of gross. Each line cites its rule; same inputs → same total (replay). The auditable input to a real DTI, replacing dedupe-by-employer. Operates on caller-mapped projections — no schema, no wiring, no behavior change. SE cash-flow / gross-up land on top.

  21. · kamo-shared-library

    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 always included, installments ≤10 months out, revolving-without- payment at 5% of balance, stated otherwise. The defensible foundation of a back-end DTI (replacing an injected 'dti'). Operates on a caller-mapped projection of the locked Liability — no schema, no wiring, no behavior change. Deferred-student-loan / contingent treatments land with the additive Liability flags.

  22. · kamo-shared-library

    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". PeriodCoverageEvaluator honors it and exposes requiredKeys(). Pure/additive.

  23. · kamo-shared-library

    **************** 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, no behavior change.

  24. · kamo-shared-library

    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. Zero behavior change, no consumer wired. - RequirementQuantity: immutable spec {count, periodMonths, cadence, perAccount, perParty} parsed from quantity_json; fails open to SINGLE so an unspecified requirement keeps today's whole-document behavior. - PeriodCoverageEvaluator: pure @Component (mirrors ConditionClearabilityResolver) computing required/covered/uncovered periods + derived status from a spec, the accepted satisfiers, and an anchor date — the "1 of 2, missing 2026-06" logic, with a stale out-of-window month ignored (carried forward, not re-asked). - RequirementSatisfier: four additive NULLABLE columns (period_end, effective_date, period_key, account_key) + index; WORM @PreUpdate preserved. - PARTIALLY_RECEIVED (already in the enum, isOpen()=true) simply becomes reachable. Columns apply additively via KamoInitializer (batched with the M1 write-path run); services stay ddl-auto:none; no shared-lib version bump.

  25. · kamo-marketing

    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-theming <kamo-chat> custom element served from **************** The marketing org's WebChatIntegration site key is read server-side in the locale layout **************** force-dynamic route so it resolves at request time, not baked into a static build) and passed to the new KamoChatEmbed client component, which injects the widget script and mounts <kamo-chat site-key="...">. Drops @stomp/stompjs and sockjs-client, which were only used by the deleted LiveSupportPanel.

  26. · kamo-internal

    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.

  27. · kamo-internal

    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 mock of the widget on the right, both driven off the same in-memory config so every edit reflects immediately. - **************** TS mirror of the widget's canonical DEFAULT_DESIGN_JSON (kamo-shared-library WebChatDefaultConfig.java) + deep-merge/parse helpers so a stored designConfig (null/partial/ malformed) always resolves to a fully-populated, editable config. - **************** self- contained styled mock (launcher + open panel), no remote widget bundle involved. - **************** SettingsTextField gains optional multiline/rows props (additive, backward compatible) for the welcome-message/system-prompt fields. Save PUTs the integration's designConfig + aiEnabled/humanEnabled/ aiSystemPrompt via webChatIntegrationsApi.update, with hex-color and positive-integer validation before the request.

  28. · kamo-internal

    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 tab where an org lists integrations, creates one (name + required website origins + AI/Support modes), and gets the raw site key + embeddable snippet once. Design customizer and readiness checklist are later phases.

  29. · kamo-register

    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 + ThemeLogo: register logos auto-follow the auth-logo identity (reactive) - useAuthName: register name text (landing + flow) follows the auth-name identity, reactive on theme config load; falls back to company

  30. · kamo-login

    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 to sessionStorage - brand.ts + ThemeLogo: login logos auto-follow the auth-logo identity (company/software), re-resolved on theme config load; no call-site changes needed

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