Product Setup
Complete employer-backed salary loan configuration
Updated: 2 October 2026
Audience: tenant administrators, lending operations, employer relationship managers, finance and acceptance testers.
This is a reference configuration for a salary-deduction loan backed by an employer MOU. Set amounts, rates, fees, eligibility limits and permitted jurisdictions using your approved product policy and employer agreement. Example turnaround times below are operational starting points, not existing contractual commitments.
1. Readiness and the missing employer email
The employer-request wiring is repaired in code. Apply tenant migration 000237_external_approval_delivery and deploy/restart the updated API and workers before testing. The existing application still has an incomplete frozen workflow; this release does not rewrite it or resend historical messages.
Read-only inspection before the repair found:
| Check | Finding |
|---|---|
| Current workflow stage | employer_approval |
| Product requires employer pre-approval | Yes |
| Configured employer verification step | employer_approval — correctly matches the workflow |
| Employer-backed guarantee | Present, with a contact email populated |
Actual EMPLOYER_APPROVAL request | Absent |
| Existing approvals | Four pending generic LOAN_APPLICATION_APPROVAL rows; these are staff approvals, not an employer request |
| Application-linked employer email notification | No notification found using the application's request reference |
| Workflow notification intents | Four completed intents; completed milestone processing is not proof of employer-email delivery |
The earlier implementation only triggered employer-specific request creation through an obsolete movement path and limited email preparation to the literal approval step. Normal completion into employer_approval therefore left no external request. This was a request-generation problem before email transport, not evidence of spam filtering.
The repaired implementation creates approvals bound to their own configured task and approval level. The durable stage notification worker prepares the employer request when that task becomes current, including custom employer step keys. Preparation failures remain visible and retryable; stale stage intents do not send employer requests.
No email was resent during this inspection. Do not repeatedly submit applications or change the step name to approval just to trigger an email: that risks bypassing the intended employer/internal approval separation.
2. Set up the tenant and employer first
Before configuring the product:
- Create the jurisdiction, currency and active staff accounts. Use separate intake/review, final approval and funding users; the application maker cannot also be its independent checker.
- Set the lender's customer-facing name, support email and contact information.
- Configure a real email sender, verified sender identity, notification templates and notification processing. A mock sender does not deliver to an inbox.
- Create the employer, mark it active and enter the authorized approval contact email. Verify that the address belongs to the person authorized under the employer relationship. If the employer requires its own multi-level sign-off (for example a Salaries team then HR), configure its approval chain — see Section 4a. Employer approval chains. With no chain configured, the single contact email is used.
- Create and activate the employer MOU, link it to the product, set its validity dates and approved exposure/deduction conditions. Do not use expired MOUs.
- Link the borrower's current employment to that employer. A free-text employer name alone is insufficient. Where employee self-service uses an employer code, ensure the code resolves to this same active employer.
- Configure the employer representative's account/linkage for portal approval where used. A generic staff role with an “Employer Approval” display label is not an employer identity.
Do not copy real borrower IDs, email addresses, identity documents or approval tokens into configuration examples or support screenshots.
3. Product tabs: typical baseline
Open Admin → Loan Products → the product → Configuration (/admin/products/{product_id}/config). Configure and save the following before publishing.
| Area | Baseline setup | Completion check |
|---|---|---|
| Product and pricing | Salary loan; chosen currency; approved amount/term ranges; monthly repayment for monthly payroll; explicit rate period, calculation method and day-count convention | Offer and repayment schedule show the intended units. Enter percentage rates as percentages, for example 12.5, not 0.125. This is a format example, not a recommended price. |
| Intake | Personal/contact details, jurisdiction, linked employment, income, existing obligations and payout details | Borrower can finish every required field and save/resume a draft. |
| Required documents | Identity document, employment confirmation, current payslip and income/bank evidence required by policy; configure active mandatory types and quantities | Uploaded files belong to the borrower, are referenced by the application and can be reviewed individually. |
| Identity | Enable document KYC and verified selfie. If face matching is required, configure supported evidence capture and minimum scores; define freshness | Verification satisfies every enabled requirement. A manual selfie approval is not a substitute for a missing face match. |
| Guarantor | Requires employer verification = on; employer must pre-approve = on; employer verification step = employer_approval; require employer MOU for this MOU-backed product | Employer, employment, guarantee and MOU refer to the same intended relationship. |
| Additional guarantor | Leave additional guarantor approval off unless the product actually requires a separate guarantor | An unnecessary extra approval must not block every salary loan. |
| MOU | Product/employer association, validity, exposure conditions, deduction method, employer approval timeout | Set one agreed timeout and reconcile it with task due dates/reminder settings. Start with 72 hours for an operational pilot if appropriate. |
| Credit risk | Approved scoring inputs, assessment requirements and risk limits; configure only data sources that are available | Missing provider data results in an explicit review requirement, not invented evidence. |
| Affordability | Income verification, existing commitments, disposable-income/deduction limits from approved policy | Proposed deduction is affordable and within the employer agreement's rules. |
| Fees | Explicit amounts/formulas, mandatory/optional status, tax where applicable, collection timing and GL mappings | Preview explains deductions, capitalized fees and net payout. Principal is not fee income. |
| Approval | External employer confirmation and independent internal final approval, with roles and quorum below | A borrower or intake maker cannot approve their own application. |
| Agreement/consent | Active approved agreement template/version, required consent records, borrower and lender signing, witness if required | Accepted terms and signed agreement refer to the same proposal version. |
| Disbursement/checklist | Allowed payout methods, verified destination, required checklist, release/confirmation controls | Funding remains separate from application approval and loan creation. |
| Servicing | Repayment allocation order, accrual/late-fee policy, permitted collections actions, settlement/closure process | Payments, subledger balances and statements reconcile. |
For the reported product, the minimum liveness score was 70, and face matching was enabled. The selfie's liveness result met the threshold but face_match_performed was false. Keep that application pending identity completion rather than assuming it passed.
4. Complete application workflow
Use all the following stages as the unconditional baseline. Set unique increasing step order values. Use the exact task types; a friendly display name alone does not activate the corresponding service.
| Order | Key / task type | Mode and owner | Evidence that completes the stage | Suggested due time |
|---|---|---|---|---|
| 1 | document_upload / DOCUMENT_UPLOAD | MANUAL; loan officer monitors borrower upload | All mandatory document references present | 7 days |
| 2 | document_review / DOCUMENT_REVIEW | MANUAL; LOAN_OFFICER | Required active documents verified; rejected/missing evidence corrected | 2 working days |
| 3 | kyc_verification / KYC_CHECK | MANUAL; COMPLIANCE_OFFICER | Aggregate document/selfie/liveness/face-match policy satisfied | 2 working days |
| 4 | fraud_screening / FRAUD_CHECK | AUTOMATED; handler fraud_screening; CREDIT_ANALYST monitors. Optional — include when your credit-risk policy requires fraud screening (loan stacking, velocity, device trust). Omit if your policy does not use it. | Fraud screening outcome recorded; auto-decline applied if configured | 1 working day |
| 5 | employer_approval / APPROVAL | APPROVAL; employer identity at level 1; officer monitors | Authorized employer confirms employment and required deduction/guarantee conditions | 72 hours |
| 6 | credit_check / CREDIT_CHECK | AUTOMATED; handler credit_decision; CREDIT_ANALYST monitors | Credit assessment and configured checks recorded | 2 working days |
| 7 | underwriting / UNDERWRITING | MANUAL; CREDIT_ANALYST | Claimed review and recorded underwriting assessment | 2 working days |
| 8 | offer_proposal / OFFER_PROPOSAL | MANUAL; LOAN_OFFICER prepares | Current offer prepared; counteroffer/rejection follows the applicable process | Offer validity period |
| 9 | offer_acceptance / OFFER_ACCEPTANCE | MANUAL; borrower responds, officer monitors | Borrower accepts or rejects the current offer; counteroffer follows the applicable process | Offer validity period |
| 10 | consent_capture / CONSENT_CAPTURE | MANUAL; borrower acts, officer monitors | Required consent evidence captured | 3 days |
| 11 | agreement_generation / AGREEMENT_GENERATION | MANUAL; borrower/lender sign, officer monitors | Matching agreement fully signed, including required witness | 3 days |
| 12 | approval / APPROVAL | APPROVAL; OPERATIONS_MANAGER, level 2 | Independent final quorum and approved terms confirmed | 2 working days |
Do not use a generic "complete" button to fabricate credit, consent or signature evidence. Use the corresponding review, proposal, consent and agreement screens. Use the modes in the table. CREDIT_CHECK requires AUTOMATED mode with credit_decision; FRAUD_CHECK requires AUTOMATED mode with fraud_screening when included. KYC can use MANUAL review or AUTOMATED mode with kyc_verification (the canonical step key for KYC_CHECK is kyc_verification, not kyc_check). A generic manual credit or fraud step is not supported. OFFER_PROPOSAL and OFFER_ACCEPTANCE must be configured together; the proposal stage prepares the offer and the acceptance stage records the borrower's response.
The suggested times must be translated into the units supported by the relevant form; reconcile task due days with approval timeout hours. Configure actual tenant working-time/SLA policies where applicable rather than assuming due days mean working days.
Step availability and where to act
The configuration dropdown displays Document Review (human-readable labels); its stored API task type is DOCUMENT_REVIEW. The editor and response/save schemas include OFFER_PROPOSAL, OFFER_ACCEPTANCE, CONSENT_CAPTURE, AGREEMENT_GENERATION and FRAUD_CHECK. OFFER_PROPOSAL and OFFER_ACCEPTANCE are both required — the proposal stage prepares the offer and the acceptance stage records the borrower's decision; omitting either one is rejected by validation. FRAUD_CHECK is optional — include it with AUTOMATED mode and fraud_screening when your credit-risk policy requires fraud screening (loan stacking, velocity, device trust); omit it if your policy does not use it. Selecting a step type in the dropdown automatically sets the canonical step key (for example KYC_CHECK → kyc_verification, FRAUD_CHECK → fraud_screening); approval steps keep a customizable key so you can distinguish employer_approval from a final approval.
The Approval tab includes the EMPLOYER role for the external level; a loan officer is the monitoring owner, not a substitute employer decision-maker. Save errors appear on the form.
The key (for example document_review) identifies the task; the type selects the evidence action, and the mode selects manual service completion, automation or approval quorum. Selecting a friendly name alone does not implement a task.
| Work | Screen/action |
|---|---|
| Task list and retry/rework | Application → Workflow (/loans/applications/{id}?mode=view&tab=workflow) |
| Document verification/rejection | Document review queue (/admin/documents/queue); normal document endpoints synchronize the active review task and its audit history |
| Identity | KYC queue (/admin/kyc-verifications) and linked borrower document/selfie review; required face match must actually be performed |
| Underwriting | Application → Workflow, current UNDERWRITING task: save assessment draft or finalize; saving claims the review |
| Offer, acceptance and agreement | Application → Term Proposals; borrower responds/signs in their portal |
| Final approval | Application → Approval; configured level and independent role/quorum |
| Funding | Originate first, then the linked disbursement/checklist screens |
Staff need the corresponding API permissions as well as workflow roles. Generic “complete” commands cannot replace evidence-producing actions. For automated KYC, correcting saved evidence is followed by retry of the current automated task; it does not automatically jump to another stage. Saved/published versions are immutable for existing applications.
Approval chain
Approval levels are configured in three places that must agree:
-
Workflow tab → "Approval Levels" (top-level count) — a number field near the top of the workflow builder. Set this to the total number of distinct approval levels your workflow uses. For the employer-backed workflow, set it to
2. -
Workflow tab → each APPROVAL step → "Approval Level" — on each step whose step type is
APPROVAL, there is an "Approval Level" input. Set this to the level number that step should use:employer_approval(step 5) → Approval Level 1approval(step 12, final) → Approval Level 2
-
Approval tab → approval chain builder — for each level number, configure who can approve and how many approvals are required. This is a separate tab from the Workflow tab. Each level has: level name, required role, required count, min/max amount, timeout hours, escalation, delegation, and comment requirements.
| Level | Where used (step) | Level name (suggested) | Required role | Required approvals | Timeout |
|---|---|---|---|---|---|
| 1 | employer_approval (step 5) | Employer confirmation | EMPLOYER | 1 authorized employer decision | 72 hours |
| 2 | approval (step 12, final) | Final lender decision | OPERATIONS_MANAGER | 1 for a pilot; raise only under the approved authority matrix | 48 hours |
Save both the Approval tab and the Workflow tab before publishing. The publish validation checks that every approval step references a level that exists in the Approval tab, and that the top-level count matches.
A loan officer may own follow-up but cannot replace the employer's external consent. Configure amount bands without gaps or conflicting overlaps. A single person's duplicate clicks must not count as multiple independent approvals. An employer rejection stops/rejects the application according to the product policy; it is not merely a missing document.
Approval scope: each step creates only its configured approval level. The employer step checks its own quorum; future staff approvals do not block it. Final completion still requires the applicable approval chain. The workflow's employer-approval level stays at 1 external request — where an employer needs several internal sign-offs, that is modeled by the employer's approval chain (Section 4a), not by extra workflow levels. Use separate internal staff levels for committee decisions.
4a. Employer approval chains (multi-level external sign-off)
Some employers require their own internal hierarchy — for example the Salaries department signs off first, then HR — before the lender's staff approval resumes. This is configured per employer, not per product.
Where to configure
- UI: Admin → Employers → select the employer → Approval chain (
/admin/employers/{id}/approvals) - API:
GET/PUT /api/v1/employers/{id}/approval-chain
Each level has: a level name (for example "Salaries Department"), a list of approver email addresses, and a required count — the number of that level's approvers who must approve for the level to clear.
Behavior
- No chain configured → the default single-contact flow applies (guarantee contact email, falling back to the employer contact email).
- Chain configured → the
employer_approvalstep fans out into one tracked request per (level, approver). Every approver at the current level receives an individual email link. - Sequential levels — only the lowest outstanding level is notified. Level 2 recipients are not contacted (and cannot act on a link) until level 1 has reached its required count.
- Any-of quorum — once a level reaches its required count, its remaining pending requests are cancelled; the next level is notified immediately.
- Decline — a decline at any level rejects the application per the product policy, same as a single-contact decline.
- Survivability — each request carries the email it was issued to. Editing the chain mid-flight does not retarget live links; the new chain applies to the next application.
- Timeout — a level's deadline starts when that level is notified, not at application submission.
Configuration contract
- Array order is the level order — level numbers are assigned automatically on save.
- Emails are validated, lowercased and deduplicated;
required_countmust be between 1 and the number of approvers on that level. - The whole chain is replaced atomically on save — a partial chain can never persist.
5. Corrections and notifications
For each stage, configure its entry, completion and rework recipients where supported. Use borrower-safe wording such as “Application under review” and “Please replace the requested document.” Do not expose internal risk notes.
| Event | Intended recipient | Required action |
|---|---|---|
| Submission accepted | Borrower; assigned intake team | Acknowledge receipt and provide status-page link |
| Documents need correction | Borrower; assigned reviewer | Identify required replacement; return to document upload |
| KYC evidence incomplete | Borrower when action is needed; compliance reviewer | Request recapture/correction without claiming identity verified |
| Employer approval stage entered | Authorized employer; monitoring officer separately | Secure approve/decline request and deadline |
| Employer overdue | Monitoring officer/escalation contact | Follow up; do not auto-approve |
| Offer available | Borrower | Review and accept/reject/counter the current offer |
| Agreement ready | Borrower and required lender signer | Review and sign the correct agreement version |
| Final outcome | Borrower and relevant operations staff | Communicate approval/rejection without claiming funds already transferred |
| Funds confirmed | Borrower; finance | Confirm actual release and servicing information |
| Closure completed | Borrower; servicing/finance | Make closure statement available |
Per-step notification policy
Each workflow step has four notification buckets in the builder: stage_entry, stage_completion, rework, and assignment. Tick the recipients that apply for each step. "—" means leave all recipients unchecked for that bucket. The table below is the recommended baseline for the employer-backed workflow; adjust roles and borrower notifications to match your tenant's communication policy.
| Step | stage_entry | stage_completion | rework | assignment |
|---|---|---|---|---|
1 document_upload | Borrower, Assignee | — | Borrower, Assignee | Assignee |
2 document_review | Assignee | Borrower (documents accepted) | Borrower, Assignee | Assignee |
3 kyc_verification | Assignee | — | Borrower, Assignee | Assignee |
4 fraud_screening (optional) | — (automated, no staff notification) | — | — | — |
5 employer_approval | EMPLOYER role, Assignee | Borrower (employer confirmed) | — | EMPLOYER role, Assignee |
6 credit_check | — (automated, no staff notification) | — | — | — |
7 underwriting | Assignee | — | Borrower, Assignee | Assignee |
8 offer_proposal | Borrower, Assignee | — | Borrower, Assignee | Assignee |
9 offer_acceptance | Borrower, Assignee | Assignee (response recorded) | Borrower, Assignee | Assignee |
10 consent_capture | Borrower, Assignee | — | Borrower, Assignee | Assignee |
11 agreement_generation | Borrower, Assignee | Borrower, Assignee (signed) | Borrower, Assignee | Assignee |
12 approval (final) | Assignee, OPERATIONS_MANAGER role | Borrower (final decision) | — | Assignee, OPERATIONS_MANAGER role |
Guidance for each bucket:
- stage_entry — fires when the workflow advances to this step. Notify the borrower for steps they must act on (upload, offer response, consent, signature). Notify the assignee for manual steps so they pick up the task. For automated steps (
fraud_screening,credit_check), leave stage_entry empty — the handler runs without a staff notification. For approval steps, add the authorized role (e.g.EMPLOYERfor step 5,OPERATIONS_MANAGERfor step 12) so the approver is alerted. - stage_completion — fires when the step's evidence is recorded and the workflow advances. Use it sparingly to avoid notification fatigue. Recommended completions: notify the borrower when documents are accepted (step 2), when the employer confirms (step 5), when the agreement is fully signed (step 11), and when the final decision is made (step 12). Notify the assignee when the borrower's offer response is recorded (step 9) so staff can proceed to consent.
- rework — fires when a rework rule sends the application back to an earlier step. Tick Borrower and Assignee for any step that can be a rework target. The first step (
document_upload) cannot be a rework source, but it is the most common rework target — keep its rework notification on. - assignment — fires when a task is (re)assigned to a user. Tick Assignee for all manual and approval steps so the new owner is notified. For approval steps, also tick the authorized role.
The EMPLOYER role appears in the Auto Assign Role dropdown and in the role checkbox list for notification policies. Selecting it for the employer_approval step's stage_entry and assignment buckets ensures the external employer representative is notified through the workflow notification system. This is separate from the dedicated employer approval email described in section 6 — both paths must be configured and tested.
Per-step rework rules
Rework rules are configured on each step in the workflow builder. A rework rule sends the application back to an earlier required step when the current step's reviewer determines the earlier evidence needs correction. Each rule specifies: the target step, the roles permitted to trigger rework, the reason codes, whether the borrower must act, and any compensation handlers for crossed automated steps.
The table below shows the recommended rework rules for the employer-backed workflow. "—" means no rework rule is needed for that step. Only configure rework rules where a reviewer at that step could reasonably need to send the application back.
| Step (source) | Rework target | Permitted roles | Reason codes (code → label) | Borrower action | Compensation |
|---|---|---|---|---|---|
1 document_upload | — | — | — | — | — |
2 document_review | document_upload | LOAN_OFFICER | DOCUMENT_NEEDS_CORRECTION → "Document needs correction", DOCUMENT_UNREADABLE → "Document is unreadable", DOCUMENT_EXPIRED → "Document has expired", INCOME_EVIDENCE_MISSING → "Income evidence is missing", SELFIE_RECAPTURE_REQUIRED → "Selfie recapture required" | Yes | — |
3 kyc_verification | document_upload | COMPLIANCE_OFFICER | SELFIE_RECAPTURE_REQUIRED → "Selfie recapture required", IDENTITY_DOCUMENT_UNREADABLE → "Identity document is unreadable", FACE_MATCH_FAILED → "Face match verification failed" | Yes | — |
4 fraud_screening (optional) | — | — | — | — | — (automated; auto-decline applies if configured) |
5 employer_approval | document_upload | OPERATIONS_MANAGER | EMPLOYMENT_DETAILS_INCONSISTENT → "Employment details are inconsistent", EMPLOYMENT_NOT_CONFIRMED → "Employment not confirmed by employer", AMOUNT_EXCEEDS_POLICY → "Requested amount exceeds employer policy" | Yes | — |
6 credit_check | — | — | — | — | — (automated) |
7 underwriting | document_upload | CREDIT_ANALYST | INCOME_EVIDENCE_MISSING → "Income evidence is missing", EMPLOYMENT_DETAILS_INCONSISTENT → "Employment details are inconsistent" | Yes | credit_decision_compensation; add fraud_screening_compensation too when fraud_screening is also crossed |
8 offer_proposal | underwriting | LOAN_OFFICER | UNDERWRITING_REASSESSMENT_REQUIRED → "Underwriting reassessment required", TERMS_OUTSIDE_POLICY → "Proposed terms are outside policy" | No | — |
9 offer_acceptance | offer_proposal | LOAN_OFFICER | BORROWER_COUNTEROFFER → "Borrower submitted a counteroffer", BORROWER_REJECTED_TERMS → "Borrower rejected the offered terms" | Yes | — |
10 consent_capture | offer_acceptance | LOAN_OFFICER | OFFER_CHANGED_REQUIRES_REACCEPTANCE → "Offer changed; borrower must re-accept" | Yes | — |
11 agreement_generation | consent_capture | LOAN_OFFICER | CONSENT_INCOMPLETE → "Consent capture is incomplete", CONSENT_REVOKED → "Borrower revoked consent" | Yes | — |
12 approval (final) | offer_proposal | OPERATIONS_MANAGER | TERMS_REJECTED_BY_FINAL_APPROVAL → "Final approval rejected the proposed terms", COUNTEROFFER_REQUIRED → "Counteroffer required before final approval" | No | — |
Guidance for each column:
- Step (source) — the step where the reviewer triggers rework. The first step (
document_upload) cannot be a rework source because there is no earlier step to return to. - Rework target — must be an earlier required step. The backend rejects targets that are later, optional, or missing. The target step's
stage_entrynotification fires when rework is applied, so keep the target's rework notification bucket ticked (see the per-step notification table above). - Permitted roles — the staff roles allowed to trigger rework from this step. Must be valid system roles (not
BORROWER). Use the role that owns the current step's review. - Reason codes — each code must be upper snake_case (
^[A-Z][A-Z0-9_]*$) with a human-readable label (e.g.DOCUMENT_NEEDS_CORRECTION→ "Document needs correction"). The label is what staff and borrowers see in the rework UI and notifications. Require notes (requires_notes: true) for all reason codes so the reviewer explains why rework is needed. The codes listed above are suggested configurable values, not built-in guarantees — create the ones that match your policy. - Borrower action — tick
borrower_action_requiredwhen the borrower must do something (replace a document, re-sign, re-accept the offer). The backend requires the rework target's notification policy to include the borrower when this is true. - Compensation — when rework passes through a crossed automated step, map the crossed step key to its compensation handler. Every automated step between the rework target and the source step needs a handler — otherwise its stale result silently carries forward past the rework. For example, if
underwritingreworks back todocument_uploadandcredit_check(step 6) is between them, addcredit_check→credit_decision_compensationso the credit decision is reversed. Iffraud_screening(step 4, automated) is also in the path, addfraud_screening→fraud_screening_compensationas well. Only automated steps can have compensation handlers. Available compensation handlers:credit_decision_compensation,fraud_screening_compensation,kyc_verification_compensation(no-op).
For automatic document-rejection routing, the document_review → document_upload rule with reason DOCUMENT_NEEDS_CORRECTION is the most common. These exact keys match the document service. Other typical rework reasons: DOCUMENT_UNREADABLE, DOCUMENT_EXPIRED, INCOME_EVIDENCE_MISSING, SELFIE_RECAPTURE_REQUIRED, EMPLOYMENT_DETAILS_INCONSISTENT. These are suggested configurable codes, not built-in guarantees. Require notes and specify the target step, permitted actor, borrower action and downstream work to invalidate.
Use the actual rework/resubmit workflow for corrections. Material changes to income, employer, amount or terms require the affected assessment/approval/offer/signature evidence to be reviewed again. Rework after irreversible funding is a servicing matter, not a shortcut back into intake.
Borrower/assignee/role milestone notifications do not configure the separate employer approval email. Both paths must be tested.
6. Email setup and delivery diagnosis
Verify:
- The employer-specific approval record exists for the application and the configured step.
- Its resolved authorized employer contact is populated and correct.
EMPLOYER_APPROVAL_REQUESTexists, is active and uses email. Its links use a reachable public application/API address.localhostlinks are not usable by an external employer.- The approval token and deadline agree; expiry, rejection and repeated clicks behave safely.
- A notification record was created. Its status/error explains queueing or delivery failures.
- Notification processing and the real sender are running. Check provider acceptance/delivery/bounce information if available, then the employer's spam/quarantine rules.
Distinguish approval task created → message prepared/queued → provider accepted → delivered. A completed workflow notification intent is not an inbox receipt. Never paste a live approval token into tickets or logs. The API access logger excludes query strings; configure any reverse proxy and provider tracking logs to redact token-bearing URLs too.
Implemented delivery and decision controls
- Stage-bound approval requests use the configured step and level, with one group shared by the slots in that level. They do not duplicate every level at every task.
- When stage notification processing first prepares the current task, it starts and persists the configured timeout. Future tasks have no running deadline. Delivery retries reuse the persisted deadline. An external request without a positive level timeout uses the product MOU timeout, or 72 hours if neither is set; configure an explicit value for your policy.
- Token hashes live in the tenant database, so links survive API restarts and cannot resolve in another tenant. Links include the tenant identifier and use
APP_BASE_URL, which must address the public API routes over HTTPS in production. - Opening an email link displays a confirmation form. Only submitting that form records the decision. Consuming the token, saving the decision and advancing/rejecting the workflow are one transaction; an error rolls all of them back. Expired, already-used and obsolete-stage decisions are rejected.
- The authorized employer/guarantor identity is retained with the request. Staff cannot impersonate that decision through the generic staff approval action.
- Token, deadline, delivery outbox entry and the request's notification marker commit together. An approval-specific event ID and workflow lock prevent duplicate preparation. Provider delivery has its own retries; provider acceptance still does not prove inbox delivery.
Operations and existing applications
After correcting missing contact or template configuration, authorized staff with loan-approval permission can call POST /api/v1/applications/{id}/workflow/approval-notification/retry with JSON such as {"reason":"Authorized contact configuration corrected and reviewed"}. This retries preparation for the current pending external request and appends the operator/reason to workflow history. It does not change workflow stages, extend deadlines or send another copy of an already queued request. Inspect notification_delivery_outbox and provider delivery status separately for transport failures. The action is an API capability; no new administrative frontend button is included.
The normal worker also retries failed stage intents. Do not replay completed historical intents or create database approval rows manually. If an old application has no task-bound employer request, the retry action reports that its saved workflow needs review. For the reported incomplete three-step test application, publish the complete configuration and use a reviewed replacement test submission, retaining/cancelling the old test through authorized operations. Structural repair of a live contractual application requires a separate audited migration; this release performs no backfill.
The unit and disposable-PostgreSQL checks cover preparation retries, stage quorum, confirmation GETs, persistence, tenant isolation, expiry and token rollback. Finish the controlled inbox and complete-journey rehearsal below after deployment; these checks do not certify provider delivery or the customer's product policy.
7. Internal accounting and separate funding
Before origination, configure the required internal principal, interest, fee and penalty subledgers and the applicable GL accounts. Review product fee mappings, cash/bank clearing accounts, interest/fee income, reversals and period controls with finance. External accounting export can remain unconfigured; internal balances must still reconcile.
Preview an example using your own agreed terms. Confirm gross principal, capitalized fees, deducted fees, net cash paid and repayment schedule agree with the accepted offer and agreement. Do not charge or report loan principal as interest/fee income.
After the complete application workflow, staff originate the loan. Origination requires the latest accepted offer, matching approved terms and fully signed agreement. Funding is then a separate linked disbursement workflow; do not add a funds-release task that has to complete before the loan can exist.
Required funding checks typically include verified payout destination, current employer/MOU evidence, required mandate/guarantee signatures, completed product checklist, independent authorization and confirmed transfer evidence. Payment-provider configuration is separate from this guide; do not treat a simulated response as real funds transfer.
Disbursement checklist template
The "product checklist" funding refers to is configured per product: Admin → Products → (product) → Disbursement Checklist tab (API GET/POST/PUT /api/v1/products/:id/checklist-template). The template defines the items staff must verify before funds release; every loan originated on the product gets a checklist instance generated from the active template. Items with required ticked block approval/release until completed — the release call returns the incomplete item names.
Each item has a name, a type (DOCUMENT_VERIFY, CREDIT_CHECK, FRAUD_CHECK, COMPLIANCE_CHECK, OTHER), a required flag and a display order. For an employer-MOU product, a typical 12-point template:
| # | Item | Type | Required |
|---|---|---|---|
| 1 | MOU active and unexpired for the borrower's employer | COMPLIANCE_CHECK | Yes |
| 2 | Employer confirmation recorded (approval or chain decision complete) | DOCUMENT_VERIFY | Yes |
| 3 | Employment still current (recent payslip / employer confirmation not stale) | DOCUMENT_VERIFY | Yes |
| 4 | Loan agreement signed by all required parties | DOCUMENT_VERIFY | Yes |
| 5 | Payroll-deduction mandate / consent captured for the instalment amount | DOCUMENT_VERIFY | Yes |
| 6 | Instalment within employer deduction cap and affordability limits | CREDIT_CHECK | Yes |
| 7 | Credit decision still in force (not reworked or expired since approval) | CREDIT_CHECK | Yes |
| 8 | Fraud screening cleared, no open flags on the application | FRAUD_CHECK | Yes |
| 9 | Verified payout destination (bank account or mobile wallet confirmed to the borrower) | OTHER | Yes |
| 10 | Independent release authorization (maker-checker, second staff sign-off) | COMPLIANCE_CHECK | Yes |
| 11 | Required consents and disclosures acknowledged by the borrower | DOCUMENT_VERIFY | Yes |
| 12 | Transfer confirmation evidence captured (provider reference before release posts) | OTHER | Yes |
Suggested item names in display order, ready to enter in the editor:
MOU status active
Employer confirmation recorded
Employment still current
Agreement signed
Deduction mandate captured
Within employer deduction cap
Credit decision in force
Fraud screening cleared
Payout destination verified
Independent release authorization
Consents and disclosures acknowledged
Transfer confirmation captured
Keep the checklist aligned with the workflow: items the intake stages already prove (documents, KYC, credit decision) do not need duplicating as manual checks where the system already blocks on them — the checklist is the last gate before money moves, not a second review of earlier evidence. The items above carry what earlier stages could have invalidated between approval and funding (employment ended, MOU lapsed, destination changed, decision reworked) plus the release-side controls (authorization and confirmation) that no intake stage owns.
During servicing, reconcile repayments and allocations, payroll deductions, accruals, fees, adjustments and reversals. Closure requires every relevant balance component resolved and a closure statement. Historic balances are not backfilled or rewritten to make a workflow look complete.
8. Save, publish and handle existing applications
- Save the product's commercial, intake, document, identity, employer/MOU and accounting/funding settings.
- Save the complete workflow, approval chain, rework rules and notification policies. Review the agreement/consent templates and required signers.
- Resolve validation errors and publish the immutable workflow version.
- Check that a new test application uses the intended version and contains every expected task.
- Complete the acceptance rehearsal below before inviting customers.
The reported application froze only document upload, employer approval and final approval. Publishing a new configuration does not insert the missing stages into it. The existing structural migration capability rejects adding required tasks. For a controlled pilot, use a reviewed replacement test submission after deploying the repaired code and fixing the product, retaining/cancelling the old test through authorized operations. Alternatively, implement an explicit audited structural migration that reopens required evidence. Do not edit the saved task list directly.
9. Acceptance rehearsal
Use controlled test accounts and an explicitly authorized test employer inbox. Record application ID, workflow version, task transitions and notification status; omit sensitive content and tokens.
- Submit and resume a saved draft; a stale tab must not overwrite a newer revision.
- Verify document upload and document review are separate. Reject and replace one required document, then resubmit.
- Confirm missing required face-match evidence blocks aggregate identity completion.
- Reach employer approval. Verify exactly one intended external request is generated per current chain level (or one for an unchained employer) and inspect actual inbox delivery.
- With a chain configured: confirm level-1 approvers are emailed while level-2 recipients receive nothing yet; after level-1 quorum, verify level-2 links arrive and the level-1 surplus links are cancelled (expired-link behavior). Confirm the step completes only after the last level clears and the staff chain then proceeds.
- Exercise employer approve, decline, expired-link and repeated-click cases. Employer approval must not skip credit, offers, agreements or final lender approval.
- Complete credit/underwriting, generate an offer, counter once, accept the final version and capture required consent.
- Sign as borrower and lender, plus witness when required. Missing signatures or changed accepted terms must block origination.
- Complete independent final approval. Attempt duplicate origination and verify only one loan exists.
- Complete the funding checklist and independent release/confirmation. Confirm the loan becomes funded only after valid confirmation.
- Post a repayment, inspect allocation/subledger/statement, exercise an authorized reversal, settle the remaining balance and complete closure.
- Reconcile internal accounting and retain the audit history. Test external provider integrations separately when enabled.
Readiness means the configured journey and these failure cases pass, not simply that the workflow publishes successfully.
Offer preparation and issuance (September 2026)
Entering OFFER_PROPOSAL prepares a DRAFT automatically. Keep this step manual for staff review. The draft uses the latest final approving underwriting assessment (amount, term, term unit, annual percentage rate and conditions). A workflow without underwriting requires an approved saved credit assessment for this application. Missing approval blocks preparation; there is no fallback interest rate or client-supplied score override.
Staff review the draft in Term Proposals, then select Issue offer. Issuance records the actor and assessment evidence, starts the seven-day acceptance period and completes OFFER_PROPOSAL. Configure the next borrower OFFER_ACCEPTANCE step and its notification policy. Draft preparation itself does not notify the borrower or make the draft acceptable. Repeated preparation returns the same draft; use Refresh draft after assessment rework. Changed terms must return through underwriting rather than a separate manual offer form.
For existing applications already at the offer stage, opening Term Proposals prepares a missing draft. If preparation fails, the page shows the reason and a retry action. Apply tenant migration 254 before running this version.
The displayed installment follows the product repayment frequency and the term retains its actual unit, including days for nano loans. Mandatory fees are itemized separately from interest. Repayment dates calculated at preparation are indicative; origination must reconcile the accepted terms with the actual funding schedule and configured fee treatment.
Final approval and signed terms
At APPROVAL, use the application approval review. The amount, interest rate, term and term unit come from the latest accepted offer and are read-only. The agreement must be fully signed before approval; a missing lender or required witness signature keeps approval blocked. To change terms, use the configured return-to-offer workflow, obtain fresh acceptance and signatures, then return for approval.
Final approval enforces the product amount and term limits, the exact product term unit, a nonnegative interest rate with at most six decimal places, the configured approval role/quorum and maker/checker separation. There is no universal minimum term for large amounts, amount-per-month threshold or restriction on round amounts. Configure additional lending policy during assessment, before the offer is accepted.
For products requiring a guarantee, an active, effective, unexpired guarantee covering the accepted amount must already exist. Complete guarantee review before final approval. Final approval does not create a guarantee or apply another interest-rate discount after signing.
The signing session coordinates required participants for one agreement version and document hash. Use electronic signing with explicit consent; borrower and lender signatures are required, with any configured additional participants. Digital certificate signing and wet-signature uploads are not currently implemented signing options. Invitations must reference the current session; replaced sessions require fresh invitations. Origination and payment confirmation remain separate operations after approval.
A generated agreement with its document ready can be reviewed and signed directly in the borrower portal; sending an email invitation is optional. The borrower selects Review and sign agreement, reviews the document and provides electronic consent. Staff then open Term Proposals → Signing and use Sign as lender. The signing checklist refreshes while signatures are pending. Final approval remains blocked until all required participants have signed.
Automatic loan creation after final approval
Completing the application workflow queues loan creation in the same database transaction. No separate workflow step, product toggle or additional API call is required. The worker creates the loan from the approved and signed terms, including its schedule and accounts. It checks workflow completion and signed evidence again before creation. Failures remain queued and retry automatically; the approved application's panel shows progress, the failure reason and an authorized retry action. Repeated requests return the existing loan. The legacy auto_create_loan request flag is deprecated and does not disable this handoff.
Open the created loan to proceed with the disbursement request and its separate funding workflow. Automatic origination does not release funds.
Assigned funding workflow
Loan creation also creates a linked funding workflow. An available loan officer receives Prepare disbursement request in My Tasks, which opens the loan. Use Manage funding to confirm the payout destination and submit the request. Verification is assigned to an operations manager, release to a finance officer distinct from the requester and verifier, and transfer reconciliation to someone other than the releasing officer. An available tenant administrator can cover an unstaffed role while preserving these separations. Missing independent staff blocks setup with an actionable error; do not bypass it by editing task records.
The loan's funding checklist shows the current step and every assignee. The borrower can see the approved loan as Awaiting disbursement. It becomes active only after transfer confirmation and posting succeed; pre-funding schedules are provisional, and unfunded loans are excluded from scheduled payment selection.