Expose API_SIGNATURE (E-Signature API) key scope
Add the E-Signature API scope to the org API-key manager so staff can grant Business orgs programmatic e-sign access. Usage beyond the included monthly allotmen...
Public programmatic e-sign API gateway (API_SIGNATURE scope)
Add /api/public/esign/** to PublicApiController: validates the org API key, requires the API_SIGNATURE scope, rate-limits, and forwards to ESigService's interna...
Internal programmatic envelope API (origin=API) for Business
- EsignInternalController (/api/esig/internal/*): X-Internal-Auth + X-Org-Id authed, called by APIService after it validates the API_SIGNATURE-scoped key; r...
API_SIGNATURE api-key scope + EsignGenericEnvelope.origin
Additive, no version bump: - ApiKeyScope.API_SIGNATURE — gates the programmatic e-signature API (Business) - EsignGenericEnvelope.origin (EsignUsageOrigin, null...
Send-for-signature action + envelope status in document editor
Add a 'Send for signature' button to the template editor header that opens a dialog to send the document to recipients and track signing status, calling the new...
Generic envelope create/send engine (sender side)
Add the OTK-authed /api/esig/envelopes API kamo-internal drives to send documents for signature, reusing the same shared-lib entities the public signing API rea...
Public signing API engine for sign.sign.pink
Implement the /api/esig/public/* signing API the kamo-signer app calls, turning the live signer from preview-stub into a working backend. - validate (recipient...
Platform product toggle in Organizations tab
Surface the platform-product designation where it belongs — Platform → Organizations. Adds a gated Switch per org (disabled for the top-level org), a confirmati...
Manage Organization.isPlatformProduct from Platform → Orgs
PlatformAccountSummary exposes isPlatformProduct + hasSubscriptionMarket; new PUT **************** (platform-admin gated) sets the flag and invalidates the org'...
Explicit Organization.isPlatformProduct as entitlement-root signal
Replace the derived 'owns a SUBSCRIPTION market' heuristic with an explicit, admin-set ownership flag. A platform product (e.g. sign.pink) is a white-label prod...
Scope member entitlements to product root, not KamoCRM
EntitlementService now resolves each member's entitlement root via EntitlementRootResolver (nearest market-owning ancestor-or-self) instead of walking to the to...
Resolve entitlements by product-root org, not platform top-level
Introduce EntitlementRootResolver: the nearest market-owning ancestor-or-self of an org (its product root), falling back to the platform top-level. This decoupl...
Add envelope recipient, field value, recipient status entities
Check in the in-progress esign model: EsignEnvelopeRecipient (+repo), EsignFieldValue (+repo), EsignRecipientStatus, and an ESignSignerType update. Additive; no...
Add EsignUsageRecord for per-signature usage metering
New append-only usage entity (mirrors AiUsageRecord) emitted at signature completion. Only API-origin signatures count toward a plan's monthly included quota + ...
Preserve aspect ratio, never stretch non-square logos
Favicon PNG/ICO frames were produced with keepAspectRatio(false), stretching any non-square logo into a distorted square. Center-fit the logo on a transparent s...
Pre-seed sign.pink + www.sign.pink in STATIC_DOMAINS
sign.pink is a new apex domain (consumer e-signature brand / white-label Kamo tenant org). Pre-seed apex + www so a Let's Encrypt cert exists before first HTTPS...
New monorepo + mobile-first e-signature signing app
Turborepo + pnpm workspaces monorepo housing reusable e-sign packages extracted from kamo-internal plus a new, ultra-polished kamo-signer app — the second-party...
Full-width enterprise rewrite with live preview
LoanProductForm was a single narrow column (maxWidth: 880) with hardcoded English everywhere. Now uses the same enterprise pattern as the offer page: Layout: -...
Two-column layout with live preview pane
The new-offer page was a tall narrow column on wide screens — wasted half the viewport. Now uses CSS Grid with the form on the left (5fr) and a live "Offer Prev...
Polish new-offer page — empty state, LOC badge, custom terms
Three UX gaps the offer page had after the prior refactor: 1. Empty state. When a market has no Loan Products yet, the dropdown used to silently render empt...
Per-offer overrides for rate, APR, and origination fee
LoanOfferCreateRequest gains three optional fields — interestRateBpsOverride, aprBpsOverride, originationFeeAmountOverride. createDraft applies them when set an...
Expose PERSONAL_LOANS in commerce-type & engagement pickers
Adds PERSONAL_LOANS to the COMMERCE_TYPES and EngagementType lists so the new KamoLOS personal-loans market can be created from the markets/new and markets/edit...
T6+T7 frontend polish + org reports + auto-pay UI
Frontend polish (T6): - New lib/format.ts: locale-aware Intl helpers — formatCurrency / formatDate / formatDateTime / formatPercentBps. Replaces hardcoded t...
Tier 6+7+9+10 — frontend polish, org reports, OpenAPI, JaCoCo
T6 (frontend polish): - New /lib/format.ts: locale-aware formatCurrency / formatDate / formatDateTime / formatPercentBps via Intl APIs (replaces hardcoded t...
Tier 5 compliance batch
- OfacSanctionsService: Jaro-Winkler fuzzy match @ ≥0.92 after exact-match pass. Hits surface similarity score. Configurable via los.ofac.fuzzy-threshold. - A...
LoanChargeOffReasonCode (IRS 1099-C box 6) + audit search
- New LoanChargeOffReasonCode enum (A_BANKRUPTCY..H_OTHER) per IRC §6050P - Loan.chargeOffReasonCode column - **************** multi-filter @Query for regulator...
Tier 3 security + Tier 8 bug cleanup batch
T3 — Security: - New RateLimitFilter (Bucket4j): 1000/min per IP for webhooks, 10/min per session for offer accept/decoder/rescind, 60/min general. Register...
****************
Used by **************** to reactivate an existing PAUSED plan instead of creating a duplicate row that orphans the paused one.
/api/los proxy HMAC-signs identity headers
When LOS_PROXY_HMAC_SECRET env var is set, the proxy now computes **************** secret) and sends X-Proxy-Signature + X-Proxy-Timestamp alongside the X-Org-I...
Org-side loan detail page + adjustments/promise API
- losApi: manualAdjust, waiveFee, promiseToPay - **************** full org-operations page * 4-up balance cards (current, principal, interest, next due) * M...
Final batch — compliance, packets, adjustments, Grafana, tests
Compliance: - MlaCheckService — Military Lending Act covered-borrower lookup against DoD MDC single-record query. Returns NotCovered if unconfigured so dev ...
P2 batch — observability, tests, year-end tax, real Stripe IDs
Observability: - micrometer-registry-prometheus on the classpath - /actuator/prometheus exposed via management config (both local + k8s configmap) - LoanMetrics...
LoanOrgStripeConnect + Loan tax/accrual fields + hot indexes
- New LoanOrgStripeConnect entity (one-per-org, holds stripeConnectedAccountId + Connect onboarding capabilities) + repository - Loan: stripeCustomerId (lazy-...
P1 frontend — charge-off queue + audit timeline
- losApi: chargeOffQueue / confirmChargeOff / auditByLoan - **************** D120 review queue page; org user reviews each loan, adds a reason, clicks Confirm...
P1 batch — webhooks advance state, crons, commerce vertical
Money movement (the core P1): - LoanPaymentPostingService: markSucceededAndPost / markFailed / markReturnedAndReverse / markDisbursementSucceeded / markDrawDi...
P0 hardening — forms, session resolve, payment methods
Forms (org-side): - **************** and /{productUid} edit pages - New LoanProductForm: basics / pricing / limits / terms / compliance sections, kind-aware...
P0 hardening — Stripe Connect endpoint + PDF flatten
- Fix EsignClient imports: EsignGenericEnvelopeRepository / EsignSignatureRepository live in .esign.repos, not .esign root - New StripeConnectController POST ...
/api/los/* proxy route → KamoLOS via k8s DNS
Mirrors the /api/billing/[[...path]] BillingService proxy: - *** session resolved via Redis; X-Org-Id + X-Member-Id forwarded - /api/los/webhooks/* skip session...
Add PERSONAL_LOANS commerce type front-end
- engagementTypeLabels: extend EngagementType union + vocabulary - MarketCardGrid: PERSONAL_LOANS color (#14b8a6) + Landmark icon + counter - Market detail page...
Initial personal-loan origination + servicing service
New Spring Boot 3.1.5 / Java 21 microservice modeled on BillingService. Owns personal-loan domain end-to-end: - LoanProduct / LoanOffer / Loan CRUD with REST +...
Add PERSONAL_LOANS commerce type + entity package
- CommerceType.PERSONAL_LOANS + parallel EngagementType + vocabulary - BuiltinVendorCategories entries for personal-loan vendors - 15 personal_loans JPA entitie...
Photo-album uploads use the same WS pipeline as the Uploads tab
Extracts the doc-manager upload pipeline (hashing → dedup check → register-or-upload → WebSocket-driven conversion) into a reusable useImagingUploads hook. The ...
Hide isActive=false programs from borrowers in real time
useProgramCatalog now filters out programs with isActive=false before returning them to the loan wizard. The flag is computed server-side as (base.isActive AND ...
Backfill program offerings for existing mortgage markets on boot
DataLoader now calls **************** after the AppMortgage-engagement backfill. Sweeps every existing MORTGAGE CommerceMarket and ensures its program Offerings...
Bootstrap mortgage program offerings on market create + boot backfill
When the user creates a CommerceMarket with commerceType=MORTGAGE — via the Markets & Fields settings tab — the market needs program Offerings under it for down...
Duplicate binders so users can fork without affecting the original
Adds a "Duplicate" action accessible from the binder list's context menu and from a new button in the editor header. The duplicate starts from the source binder...
Add POST ****************
Deep-copies a binder the requester can see (owned, shared, or template) into a fresh binder owned by the requester. Copies every item (DOC, SEPARATOR, GENERATED...
Mortgage Programs toggle + MORTGAGE engagement deep-link
- MortgageProgramsPanel now ships a real Switch on each program card with optimistic update + rollback on failure. Toggling a program calls PUT ************...
PUT /programs/{code}/active + deprecate legacy mortgage POS endpoints
- MortgageProgramController gains PUT **************** with body {"isActive": bool}, gated on LOS_TAKE_APPLICATION. Delegates to **************** which upse...
Per-org enable/disable + deprecate legacy commerce-only mortgage path
- **************** upserts an OrgProgramOverride row with recordState.isActive=desired; listForOrg now AND's the base program's active flag with the overrid...
Like what you see shipping?
Every one of these updates lands in your workspace automatically. Start free and watch it grow week after week.