Skip to content
KAMOUniverse

Changelog

What's new.

Every improvement to the platform, as it ships.

  1. · kamo-internal

    KamoMLOS portal default-product designation in vendors-products (#11)

    A star toggle on each product designates the org's single KamoMLOS portal auto-assign product (single-active). Gated via GET /lead-vendors/mlos-readiness: shown only when the edited market IS the org's residential-mortgage lead market AND POS + a MORTGAGE commerce market are configured. Reflects/edits the live default via PUT .../products/{id}/mlos-default. (i18n in the P6 sweep.)

  2. · SecurityService

    P3 default-product designation backend (single-active) + operator readiness

    - **************** designates ONE LeadVendorProduct as the org's KamoMLOS portal auto-assign product; single-active (demotes any other, org-scoped, fail-closed) via JPQL bulk updates. - LeadVendorController: PUT **************** and GET /mlos-readiness (which product is default + whether POS + RESIDENTIAL_MORTGAGE lead market + MORTGAGE commerce market are configured) — backs the settings gate + shows current state. Compiles clean; no schema/shared-lib change.

  3. · SecurityService

    P2c leads-first portal backend

    - MortgageVerticalResolver: resolves an org's RESIDENTIAL_MORTGAGE LeadMarket, MORTGAGE CommerceMarket, designated default LeadVendorProduct, and EFFECTIVE POS-enabled — one deterministic readiness read backing both the settings gate (#11) and the portal gate (#12). - PortalLeadService: leads-first — createOrGetAnonymousLead (keyed to an AccountGuid cookie, auto-assigned the default product in the mortgage market, fail-closed on readiness — NO signup, NO AppMortgage), patchEstimate, and the sign-in mergeGuidIntoMember (binds the GUID to the member's Account + reparents the lead(s), mirroring assignLeadAccount's history writes). - PortalController **************** lead POST/PATCH, merge}: anonymous (org-from-host, GUID from the trusted BFF X-Kamo-Guid header); merge is ***-bound. Compiles clean. Anonymous routes pass the permitAll filter chain (controllers self-gate).

  4. · kamo-internal

    Account-merge admin UI (MERGE_ACCOUNTS)

    AccountManager gains a Merge Accounts action (gated by **************** select exactly two customer accounts, pick the survivor, optionally keep the duplicate's Stripe customer / primary member, then merge — reparents all children onto the survivor and soft-deactivates the duplicate. accountsApi.mergeCustomer() → POST /account/customers/{uid}/merge. (i18n keys to be added in the P6 sweep.)

  5. · SecurityService

    P2a account-merge tool + P2b transaction backend

    P2a — admin account merge (owner requirement A), gated by MERGE_ACCOUNTS: - AccountMergeService: reparents EVERY account_uid child via native UPDATE (bypasses JPA orphanRemoval so the loser's leads/apps survive), dedups the globally-unique account_members + (account,market,target) subscriptions, reconciles stripe_customer_id / primaryMember / pointer FKs (survivor-wins + keep-from-loser overrides), soft-deactivates the loser. Same-org only. - AccountController POST **************** gated by MERGE_ACCOUNTS (or god). P2b — deal-grouping backend: - LoanTransactionService: ensureTransactionForApp (auto single-loan group on create, idempotent), deriveStatus (rolled up from member LoanFileStatus via LoanTransactionStatusDeriver), **************** (TransactionSummaryDTO), isMemberPartyToTransaction (D52 generalized to the group), backfillOrganization. - MortgageAppController: create() now auto-groups the loan; GET /transactions lists per-transaction (operators=org pipeline, borrower=own account). - Register mlos.transaction + mlos.docs repos in SecurityServiceApplication @EnableJpaRepositories. Schema already created by KI (P1). Compiles clean against installed shared-lib.

  6. · kamo-shared-library

    P1 entity foundation — lead-first / account-centric / transaction-grouped refactor

    NEW entities (additive; KI runs DDL): - TransactionGroupStatus enum + LoanTransactionStatusDeriver: derived group lifecycle (Created→…→Completed) rolled up from member LoanFileStatus (never stored authoritatively). - AccountGuid (accounts): long-lived cookie GUID↔Account (nullable) for the leads-first anonymous flow. - AccountBorrowerParty (accounts): shared loan-borrower identity (Member optional) + doc-vault key. - MemberDocument (mlos.docs): account/member-level reusable document vault. - LoanTransactionTimeline (+event enum), SharedTransactionTask (+status/severity enums): shared group feed + tasks. - repos for all of the above. Enum appends (id-stable / ordinal-safe): - LoanFileStatus.SOLD_BOARDED(9) — appended at END (ORDINAL storage); +isTerminal; fixed exhaustive switches. - **************** — imaging-member-vault bucket. - **************** — General Settings (serviceType=null) for the admin account-merge tool. FK columns (nullable, pinned columnDefinition, no default — unique_rowid/gen_random_uuid orphan trap): - LoanFile.loan_transaction_id, **************** Lead.account_guid_id, CommerceMarket.lead_market_id, **************** **************** Design: **************** No version bump.

  7. · SecurityService

    Borrower self-service authorization (loan-party IDOR guard)

    A borrower is a plain org Member with no operator LOS rights; they may act on the ONE application they are a party to — and only that one. Layered guard: operator gate first, else a fail-closed loan-party check (isMemberPartyToApp). MortgageAppController: - **************** overloads applied to get, all 23 per-app write endpoints, and the 3 repeating-section helpers. - list: operators see the org pipeline; a borrower sees only owned apps. - create: operator takes app (incl. from-lead); a borrower self-creates their own (ownership-stamped) — the KamoMLOS reward-gate mint. - delete: operator suspend-right OR the owning borrower; lookups: any authenticated session (reference enums the intake needs); journey stays operator-only. MortgageProgramController: closed a pre-existing IDOR on setPersona/setSelectedProgram (org-only check) — now operator-LOS-role OR loan-party. Operators unchanged; borrowers owner-scoped; cross-borrower IDOR closed (D52).

  8. · kamo-shared-library

    Borrower loan-party ownership on AppMortgageService

    Adds the ownership primitives for borrower self-service (a borrower is a plain org Member with no operator LOS rights): - createBlankOwnedByMember(orgId, memberId): createBlank + stamp ownership by attaching (or reusing) an Account whose primaryMember is the borrower. - isMemberPartyToApp(appUid, orgId, memberId): fail-closed loan-party guard — org match AND caller is primaryMember/AccountMember of the app's Account. - listOwnedByMember(orgId, memberId): the borrower's own applications. Ownership is the design-mandated **************** link; Account/ AccountMember already exist, so no schema/KI. Additive only (D52).

  9. · kamo-internal

    Borrower-journey column + intake filter in the loan pipeline

    The sub=pipeline datagrid (ApplicationsPipelineConsole) now shows pre-app-taken borrower-journey progress so org employees can review an application's status as the borrower completes their own loan through the KamoMLOS portal. - 'Borrower Journey' column: state chip (Just started / Filling in / Ready to submit) + determinate progress bar + sections n/total, with a pending-sections tooltip; '—' for already-taken loans. - 'Borrower Intake' filter bucket: loans with a live self-serve journey entry. - listJourney() API client + BorrowerJourneyDTO type + i18n keys. Sourced from GET /mortgage-apps/journey (D51).

  10. · SecurityService

    Pre-app-taken borrower-journey endpoint for the operator pipeline

    New GET **************** (LOS_VIEW_PIPELINE) returns per-DRAFT borrower-intake progress so pipeline stewards can watch a loan take shape while the borrower is still self-serving it through the KamoMLOS portal. BorrowerJourneyService recomputes the portal wizard's section completeness server-side over the canonical AppMortgage graph (tolerant presence checks — the canonical DTOs and the portal client DTOs have diverged field names). State = STARTED / IN_PROGRESS / READY_TO_SUBMIT over 7 pre-submission sections; reverse mortgages skip the financial sections, matching the portal. Nothing persisted; capped at 300 drafts/view. BorrowerJourneyDTO is a SecurityService-side record so donotmodify stays untouched. Part of doc03 pipeline repurpose (D51).

  11. · SecurityService

    LOS controllers accept per-borrower *** sessions (doc03 §0.1)

    BaseLosController now resolves the caller's session via CallerSessionResolver (X-OTK-validated attribute FIRST — operators/BFF unchanged — then a first-party *** cookie fallback) instead of only the X-OTK attribute. This is the keystone that lets the KamoMLOS borrower portal reach /api/security/mortgage-apps/** with a real per-borrower session (a borrower is a plain org Member via the standard login→OTK→validate-otk→*** flow) rather than a shared service account. Backward- compatible; all 7 LOS controllers benefit. Compiles clean.

  12. · SecurityService

    LOE-Core server-authoritative program scorer + /programs/scores (doc03 §9 Phase 2)

    Ports the KamoMLOS client scorer (lib/los/scoring.ts) into SecurityService LOE-Core: LoeCoreScorer scores the org's effective program catalog (baseline deep-merged with org overlay) against a borrower AppSnapshot — identical LTV/DTI/occupancy/reserves/ VA-entitlement/reverse-age checks — returning ProgramScoreDTO in the exact client ProgramScore shape. POST **************** Server-first: this ships before the §9 Phase 3 client-scorer deletion. 3 tests green.

  13. · InitializerService

    Seed the 17 real program rulesets (doc03 §9 Phase 1)

    Migrates the authoritative ProgramRuleset data from the KamoMLOS client ruleset files into **************** (17 codes, extracted faithfully) and replaces ProgramSeederRunner's rulesetJson("{}") placeholder with real per-code rulesets loaded from the classpath. Idempotent: inserts missing programs and upgrades existing "{}" placeholders to real data, never clobbering operator edits. Applied on the next KamoInitializer run (user-run). Prereq for the §9 Phase 2 server scorer that deletes the client scorer.

  14. · kamo-shared-library

    Real deep-merge for org program-ruleset overrides (doc03 §9 Phase 0)

    Replaces the M2 last-write-wins mergeOverlay placeholder (which silently discarded the authoritative baseline on any org override) with a recursive JSON deep-merge: org overrides supply only the keys they change, nested objects recurse, arrays replace wholesale, and a malformed override fails safe to the baseline. Locks the ProgramRuleset contract ahead of the server-authoritative scorer (§9 Phase 2) that will delete the client scorer. Program/ProgramService javadoc repointed. 3 tests green.

  15. · kamo-shared-library

    MlosExtractedCandidate staging entity for the ingestion pipeline (D48)

    The terminal per-field output of MLOSIngestionService's parser: a staged, reviewable extraction candidate (segment/source-doc FK, targetEntity, fieldPath, cellRef, raw/normalized value, DECIMAL(4,3) confidence, reviewStatus). Candidates NEVER promote into canonical catalog entities except through MLOSCatalogService's RateSheetSanityGate + human approval. Completes the ingestion substrate **************** ExtractionTemplate pre-existed). mlos.catalog already in KI scan → table auto-creates on next KI run; services run ddl-auto:none.

  16. · kamo-shared-library

    Isolated best-effort profile write-back for legal-wall paths (D47)

    mergeFactsBestEffort runs the enrichment write-back in its OWN transaction (REQUIRES_NEW) so a failure can never roll back the caller's transaction — the safe write-back for a legal-wall decision path (AUS/internal-rules) whose decision-of-record must persist regardless. Skips silently when no profile exists. +1 shared-lib test (skip-when-absent / delegate-when-present).

  17. · kamo-internal

    State Based Licensing section on member my-profile

    New SectionCard (NMLS ID + per-state licensed table with actively- providing checkbox and renewal/expiry dates, renewal<=expiry validated). Gated by **************** Adds Next proxy route, TS RoleRightType mirror, and design/plan docs.

  18. · SecurityService

    Member state-licensing API + license-aware lead availability

    Add MemberStateLicensingController (GET/PUT /api/security/members/{id}/ state-licensing) gated by STATE_LICENSING_* rights with server-side renewal<=expiry validation. Enable mlos.legal JPA repos. Popup summary and Leads-Available grid now respect state-licensing eligibility.

  19. · kamo-shared-library

    State-based member licensing + lead-acceptance gate

    Reuse mlos.legal StewardLicense as the single per-member/per-state NMLS registry (add activelyProvidingBusiness). Add member-level Member.nmlsId. Add General-Permissions rights **************** CreditLeadAssignmentService now skips mortgage-lead candidates whose explicit property state the member is not actively licensed in.

  20. · kamo-internal

    Add Source to the mappable lead fields

    Lead 'source' is shown on the lead detail page but was missing from the import field list; add it (path 'source') now that the backend importer + CreateLeadRequest support it.

  21. · SecurityService

    Map an imported column to the lead `source` field

    Add case "source" to setDirectFieldOnCreateRequest so the mapping path 'source' is honored.

  22. · kamo-shared-library

    Add importable `source` field to CreateLeadRequest + persist it in createLead

    The Lead has a free-text `source` (shown/edited on the lead detail page) but it was not importable — CreateLeadRequest had no source field, so createLead never set it. Add it so manual imports can map a file column to the lead's source.

  23. · kamo-shared-library

    Add ScenarioProfileSource.PRICING for scenario-writer FICO/ratio write-back (D45)

  24. · kamo-shared-library

    Canonical scenario-fact spine — genesis deriver + factsJson populate + write-back + overlay matcher (D45)

    D1/D45 broadens BorrowerScenarioProfile consumption. Populates the dormant factsJson and makes it the shared source of truth for borrower/loan facts: - ScenarioFactKeys: single canonical fact-key vocabulary + tier (structural vs enrichment) + normalize(); the D21 whitelist/deriver/consumers reference these. - ScenarioFactDeriver: promotes the D18 LTV/CLTV/HCLTV + categorical derivation out of MLOSPricingService into shared-lib (one home for entity-derived facts). - BorrowerScenarioProfileService: produceFromUrla now populates structural facts (preserving enrichment); resolveFacts() for advisory gap-fill; mergeFacts() write-back that filters to the enrichment tier (genesis owns structural, D45.3). - ScenarioFacts.fillGapsFrom(): advisory merge (request wins, profile fills gaps). - InvestorOverlayMatcher: pure fail-safe matcher (present-and-violating only). No schema/KI change (factsJson column pre-exists). 27 targeted tests green.

  25. · kamo-internal

    Channel Rules tab — completes the §3.2 config surface

  26. · SecurityService

    Channel applicability rules collection CRUD — completes §3.2 config

    createChannelRule/update/delete on the D31 flat-collection spine (profile-level, org fail-closed, WORM change-log); controller /channel-rules GET/POST/PUT (delete via active:false). Scope/channel/outcome required; **************** authority/funding + effective window optional. Last §3.2 config entity.

  27. · kamo-internal

    Product Enablement tab (per-program, versioned)

  28. · SecurityService

    Product enablement config — per-program single-active, effective-dated

    **************** (program-scoped demote-then-insert) + reads; controller /product-enablements GET (active per program) / PUT (publish). Body carries programId, enabled, lifecycleVariant, channelRestriction, effectiveFrom.

  29. · kamo-internal

    Policies tab — effective-dated pricing/capital/servicing config

    New MortgagePoliciesTab: current active version + publish-new-version form + version history for each of the three effective-dated policies; configTypes/configApi + tab registration.

  30. · SecurityService

    Effective-dated profile policies — pricing/capital/servicing publish

    New MlosPolicyWriteService (isolated; its own repos so the config-collection write- service is untouched): single-active demote-then-insert versioning on the same audit spine. Controller /pricing-policy, /capital-policy, /servicing-policy GET (current+ history) / PUT (publish new version). ServicingPolicy SCRA/FDCPA invariants stay true.

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