Submission Work Queue
The submission work queue is the front door of the underwriting workflow. Every new submission enters a triage pipeline that scores, routes, and surfaces the right opportunities to the right underwriters. The queue is powered by the submissions API (apps/api/src/routes/submissions.ts) and rendered in the underwriting workbench (apps/underwriting-workbench/app/submissions/).
Submission Lifecycle
A submission moves through a defined set of statuses. The work queue surfaces items that need underwriter attention and tracks progress through each stage:
draft -> submitted -> received -> in_review -> quoted -> bound
|
+-> referred
+-> rejected
+-> endorsed
| Status | Description |
|---|---|
draft | Incomplete submission, not yet sent for review |
submitted | Sent by producer, awaiting intake |
received | Intake acknowledged, entering triage |
in_review | Actively being underwritten |
quoted | Quote issued, awaiting bind decision |
bound | Policy bound and issued |
referred | Escalated to senior authority |
rejected | Declined by underwriter |
endorsed | Post-bind endorsement processed |
Triage Scoring
Every submission receives a lightweight triage score (0--100) computed at list time. This score drives swimlane bucketing without the cost of running the full underwriting rules engine on every row.
Score Calculation
The computeTriageScore() function in the submissions route evaluates four factors from the submission's extractedData:
Prior Loss Ratio
| Loss Ratio | Score Impact |
|---|---|
| > 1.5 | +30 |
| 0.75 -- 1.5 | +15 |
| ≤0.4 | -20 |
Prior Claim Count
| Claim Count | Score Impact |
|---|---|
| > 10 | +25 |
| 5 -- 10 | +10 |
| ≤1 | -10 |
Years in Business
| Years | Score Impact |
|---|---|
| < 2 | +15 |
| >= 5 | -10 |
Priority Override
Submissions with priority: 'high' receive an additional +10 boost.
The base score starts at 50. The final score is clamped to the 0--100 range.
Swimlane Routing
The triage score maps to three swimlanes:
| Score Range | Swimlane | Handling |
|---|---|---|
| 0 -- 29 | Auto-process | Low-risk, eligible for straight-through processing |
| 30 -- 69 | Underwriter Review | Standard queue, manual review required |
| 70 -- 100 | Senior Referral | High-complexity, escalated to senior authority |
Experience Mod Staleness
When loss runs are updated after a submission has been scored, the platform sets a KV staleness marker at rating:stale:{orgId}. The next time a stale submission is accessed, the recomputeStaleExperienceMod() function:
- Fetches the latest loss run linked to the submission.
- Converts it to
LossHistoryInputvia@openinsure/loss-runs. - Recalculates the experience modification factor via
calculateExperienceRating()from@openinsure/rating. - Updates the submission's
extractedData.experienceModand setsexperienceModSourcetostale_recomputed.
This ensures triage scores and rating decisions always reflect the most current loss history.
Underwriting Workbench UI
The work queue is rendered as a data table in the underwriting workbench at /submissions. The page is a server component that fetches submissions from the API, with a client component (SubmissionsClient) handling interactivity.
Table Columns
| Column | Description |
|---|---|
| Insured Name | Linked to the submission detail page |
| Omniscient Risk | Fraud flags from the AI risk engine, shown as badges |
| LOB | Line of business |
| State | Garaging or domicile state |
| Status | Faceted filter with color-coded badges |
| Created | Submission creation timestamp |
Filtering
The work queue supports:
- Status faceted filter -- Multi-select from the status options (draft, submitted, received, in_review, quoted, bound, rejected, referred, endorsed).
- Text search -- Filter by insured name via the toolbar search input.
- URL-synced state -- Filter values are persisted to URL query parameters via
nuqsfor shareable, bookmarkable views.
Actions
From the submissions list, underwriters can:
- New Submission -- Create a new submission manually.
- Wizard -- Launch the guided submission intake wizard.
- Upload ACORD -- Parse and ingest an ACORD 130/140 application PDF.
- Export -- Download the current filtered view as CSV or Excel via the
ExportToolbar.
Submission Intake Channels
Submissions enter the queue through multiple channels:
Manual Entry
POST /v1/submissions creates a new submission with the provided extractedData, lob, state, and insuredName. The submission starts in draft or submitted status.
ACORD Upload
The /submissions/upload page in the workbench accepts ACORD PDF uploads. The document is parsed by the API's document pipeline, which extracts structured data and populates the submission's extractedData.
Email Ingest
The POST /v1/submissions/ingest-email endpoint accepts forwarded emails. The email-parser service extracts ACORD attachments and insured information, creating a new submission in received status.
Producer Portal
Producers submit applications through the producer portal, which calls the same POST /v1/submissions endpoint with the producer's credentials. These submissions include the producerId for commission tracking.
Rules Engine Integration
When a submission moves beyond triage, the full rules engine evaluates it:
- System rules from
@openinsure/rules(SYSTEM_RULES) are evaluated against the submission context. - Organization rules stored in the
rulestable are fetched and evaluated. - The combined
EvaluationResultproduces a set ofRuleActionitems:decline-- Generates decline reasons, may auto-decline.refer-- Generates referral reasons, triggers escalation.flag-- Adds risk flags visible in the Omniscient Risk column.modify-- Suggests modifications to terms or conditions.
The evaluation result is translated to a legacy shape for downstream consumers (checklist, decision, referral reasons) via mapEvaluationToLegacyShape().
Underwriting Evaluation
The @openinsure/underwriting package provides three key functions used during submission processing:
| Function | Purpose |
|---|---|
evaluateSubmission() | Full underwriting evaluation producing risk profile and recommendation |
classifyRiskAppetite() | Determines if the risk fits the organization's appetite |
determineAuthority() | Identifies which authority level is required to bind |
Priority and Assignment
Submissions have a priority field (low, normal, high) that influences triage scoring and queue ordering. High-priority submissions surface first and receive a scoring boost.
Assignment is implicit through the authority system -- submissions in the referral swimlane are routed to underwriters whose authority profile matches the required level (see the Approval Matrix page for details on authority profiles).
API Endpoints
| Method | Path | Description |
|---|---|---|
GET | /v1/submissions | List submissions with cursor pagination |
POST | /v1/submissions | Create new submission |
GET | /v1/submissions/:id | Get submission detail |
POST | /v1/submissions/:id/quote | Generate quote with rating |
POST | /v1/submissions/:id/rerate | Recalculate with updated data |
POST | /v1/submissions/:id/refer | Escalate to senior authority |
POST | /v1/submissions/:id/decline | Decline the submission |
POST | /v1/submissions/:id/bind | Bind and issue the policy |
POST | /v1/submissions/ingest-email | Ingest from forwarded email |
Related
- Approval Matrix -- Authority profiles and referral rules
- Underwriting -- Rules engine and risk evaluation
- Compliance -- Sanctions screening and regulatory checks