- Shipped
- July 4, 2026 at 2:05 PM UTC
- Author
- Kamo
- Commit
- 3c9b732
Per the owner's §5.A directive: ScenarioSupportPolicy must consume a canonical Borrower Scenario Profile generated from normalized URLA data, never raw forms/UI, and future sources (AUS/OCR/AI/manual) UPDATE that canonical record rather than bypass it. - BorrowerScenarioProfile (mlos.intake, new table **************** the single per-loan source of truth — the 5 typed URLA product dims + an extensible calculated-facts JSONB + lastSource + version. Mutable (accretes truth), audited by source+version. - BorrowerScenarioProfileService: produceFromUrla(loanFile, orgId) is the genesis (reads normalized Loan/Property immediately after URLA normalization); applyUpdate is the ONLY seam later sources use (fails loudly if no profile exists — genesis is URLA's alone, enforcing update-don't-bypass); toSupportProfile projects the 5 dims. - ProductDiscoveryGate: the §5.A legal wall consulted BEFORE eligibility/pricing — resolves ScenarioSupportPolicy (tenant overrides + code default) over the canonical profile and, on a refusal, records a WORM AiDecision routed to a steward (NO_ELIGIBLE_PRODUCT, legallyRequiresHuman; DEFERRED_HARD_STOP=HIGH, STEWARD_ONLY= MEDIUM) via an optional DecisionSpine. SUPPORTED writes nothing. 10 tests green. Build-and-flag: needs a KI run (new table) + the service-flow wiring (call produceFromUrla at the URLA-normalization hook + gate.evaluate at product- discovery entry) in the owning service.