Skip to content

The Inspire big flow

One page, the whole product: how a risk becomes a policy, how a policy is served and claimed against, and how the money and the reinsurance follow. The flow is described as Inspire GI implements it — the most complete core — because the other cores follow the same skeleton with variations covered in The five cores.

The authoritative source is inspire-gi/docs/06-process-flows.md, which diagrams every lifecycle with the tables each step writes. This page is the guided tour; that page is the reference.

flowchart TB
    PF["Product factory<br/>define, rate, publish"] --> QU["Quotation<br/>rated, no commitment"]
    QU --> PP["Proposal<br/>real risk, allocated number"]
    PP --> UW{"Underwriting<br/>rules"}
    UW -->|"pass"| IS["Issuance<br/>PolicyNo, version 1"]
    UW -->|"refer"| MAN["Manual decision<br/>accept, decline, or terms"]
    MAN -->|"accept"| IS
    MAN -->|"decline"| DEC["Declined"]
    IS --> IF["Policy in force"]
    IS --> BIL["Billing<br/>bill, AR per installment"]
    IS --> CES["Reinsurance<br/>cede the treaty share"]
    IF --> END["Endorsement<br/>mid-term change, delta billed"]
    IF --> REN["Renewal<br/>a new policy, linked"]
    IF --> CAN["Cancellation<br/>refund, status TX"]
    CAN --> REI["Reinstatement<br/>cover restored"]
    IF --> CLM["Claim<br/>FNOL to settlement"]
    BIL --> COL["Collection<br/>suspense, then offset"]
    CLM --> PAY["Payment<br/>clears the AP directly"]
    COL --> GL["GL posting<br/>voucher to journal"]
    PAY --> GL
    CLM --> RIR["RI recovery<br/>the ceded share of loss"]
    GL --> PC["Period close<br/>trial balance"]

Read it as five stages, each expanded below: product setup, new business, servicing, claims, and money — billing, collection, the ledger and reinsurance. After issuance, the billing, cession, document and search work happens asynchronously from a durable outbox; the policyholder does not wait for it.

Before anything can be quoted, a product must exist. This is configuration, not code:

flowchart TB
    A["Components<br/>reusable parts library"] --> B["Technical product<br/>the superset for a LOB"]
    B --> C["Market product<br/>what is actually sold"]
    C --> D["Bind fields, clauses, channels<br/>rating topics, rules, plans"]
    D --> E{"Review"}
    E -->|"approved"| F["Publish version<br/>immutable, ACTIVE"]
    E -->|"rejected"| D
    F --> G["Quotable<br/>no DDL, no deployment"]
  • No DDL at any step. A market product goes live because rows were inserted and a status column changed. A new product is a configuration exercise.
  • A published version is immutable; changes create a new version, and in-force policies stay bound to the version they were written on.
  • Publication invalidates the product, rule and rate caches.

Where it lives — inspire-gi: ProductsController, RateTablesController, RulesController; tables tproduct, tproduct_element, tdd_field, trate_table, trule; sql/04-product.sql, sql/05-dd-rules-rating.sql; docs/09-configuration-guide.md for the worked example. Group’s equivalent is the product-setup module (docs/04-module-specs/product-setup.md); credit life’s is the policy-scheme module (tplan, tproduct_package, tpremium_rate).

Stage 2 — New business: quotation to issuance

Section titled “Stage 2 — New business: quotation to issuance”

The main path. Everything else is a variation.

sequenceDiagram
    autonumber
    participant C as Client
    participant API as Policy service
    participant RATE as Rating engine
    participant UW as Underwriting
    C->>API: quotation
    API->>RATE: rate the tree, bottom-up
    RATE-->>C: premium at every level, with a trace
    C->>API: proposal
    API->>API: allocate ProposalNo, PolicyStatus PN
    API->>API: blocklist screening, validation, RD
    API->>UW: underwriting rule check
    alt all rules pass and STP allowed
        UW-->>API: pass, TV
    else a rule refers
        UW-->>API: referral with an SLA clock
        Note over UW: underwriter accepts, declines,<br/>or accepts with terms
        UW-->>API: decision, TV
    end
    C->>API: issue
    API->>API: allocate PolicyNo, IF, policy version 1
    API->>API: snapshot clause wording
    API-->>C: policy issued

What makes this flow Inspire rather than a legacy core:

  • Rating is explainable. The engine walks the policy tree bottom-up and writes a rating trace, so “why is this the premium?” always has an answer.
  • Underwriting is rules plus people. The auto path is configured rules; the referral path carries an SLA and records the underwriter’s decision and terms.
  • Issuance fans out after commit. Billing creates the bill and AR; reinsurance cedes; documents generate; search indexes — all from the outbox, so a briefly unavailable downstream cannot block issuing a policy.

Where it lives — inspire-gi: QuotationsController, ProposalsController (POST {proposalNo}/rate, /underwrite, /decision, /issue), PoliciesController; tables tquotation, tpolicy, tpolicy_element, tunderwriting and friends; docs/06-process-flows.md §2. Group adds proposal handling via GMPS/EBPS-style flows (docs/04-module-specs/policy.md).

Endorsement — changing a policy mid-term

Section titled “Endorsement — changing a policy mid-term”
flowchart TB
    A["Load current policy version"] --> B["Apply the change<br/>to a working copy"]
    B --> C{"Endorsement type"}
    C -->|"non-financial"| D1["No re-rating"]
    C -->|"sum insured, rate, cover, risk"| D2["Re-rate at new terms"]
    C -->|"period extend or shorten"| D3["Recompute the period factor"]
    D1 & D2 & D3 --> E["Validate, underwrite if required"]
    E --> F["Compute the delta<br/>pro-rated for the unexpired period"]
    F --> G["Version the changed elements only<br/>same ElementKey, new window"]
    G --> H["Re-accumulate premium bottom-up"]
    H --> I["Bill the delta, not the total"]
    I --> J["Adjust the cessions"]

Two rules prevent the classic errors: the header keeps full-term premium while the endorsement carries the pro-rated delta (different quantities — adding them breaks reconciliation), and only changed elements are versioned (unchanged siblings stay live because the tree is keyed, not row-linked).

An endorsement can even be out of sequence — effective before one already issued. Because element rows carry explicit version windows, inserting v3 effective before v2 is a query over windows, and v2’s premium is rebuilt on the new basis with the net delta billed.

Seeded endorsement types include BIE (basic information, non-financial), TSI (sum insured), RATE, ADDCOV / DELCOV, ADDRISK / DELRISK, period changes (POIEXT / POISHORT / POIMOVE), CAN, REINSTATE, PC and UNDO.

Renewal — a new policy, not a new version

Section titled “Renewal — a new policy, not a new version”
flowchart TB
    A["Batch identifies policies<br/>expiring within the notice window"] --> B["Gather experience<br/>claims, incurred, loss ratio"]
    B --> C{"Eligible?"}
    C -->|"no"| D["Refer to underwriter<br/>with the reason"]
    C -->|"yes"| E["Copy the expiring tree<br/>as a new proposal"]
    E --> F["Apply the no-claim discount step"]
    F --> G["Re-rate on current rates<br/>and product version"]
    G --> H{"Premium variance within<br/>auto-renew tolerance?"}
    H -->|"yes"| I["Auto-renew"]
    H -->|"no"| D
    I --> J["Issue<br/>linked both ways, RenewalCount plus one"]

The renewal is a new policy — a new contract period, a new number, its own claims — linked in both directions (RenewedFromPolicyID / RenewedToPolicyID) so continuous cover and no-claim-discount entitlement are provable.

Cancellation is FROMINCEPTION (full refund, only with no claims) or MIDTERM (short-rate or pro-rata refund on the unexpired period). It sets ExpiryDate = EndoEffectiveDate so the policy period matches the premium actually charged, produces a negative bill → AP (a refund payable), and reverses the cessions. Reinstatement reverses all of it: cover restored from the reinstatement date, reinstatement premium billed, the period re-ceded.

Where it lives — inspire-gi: PoliciesController endorsement endpoints, RenewalsController; EndorsementProcessService, EndorsementRatingService; docs/06-process-flows.md §3–5. Group’s renewal is a module of its own (docs/04-module-specs/renewal.md) with an average-rate engine inherited from Compass.

sequenceDiagram
    autonumber
    participant R as Reporter
    participant FNOL as Notification
    participant CLM as Claim service
    participant AUTH as Authority
    participant BCP as Billing
    R->>FNOL: report a loss, any channel
    FNOL->>FNOL: insert the notification row, never lost
    FNOL->>CLM: match to a policy
    CLM->>CLM: resolve the version in force at the loss date
    CLM->>CLM: snapshot it immutably, open claim items
    CLM->>CLM: open reserves from matrix defaults
    Note over CLM: investigate, survey, adjust
    CLM->>CLM: revise reserves as movements
    CLM->>CLM: calculate: gross minus deductible, depreciation,<br/>salvage, scaled by underinsurance and coinsurance
    alt within authority
        AUTH-->>CLM: approved
    else exceeds
        AUTH->>AUTH: approval up the matrix chain
    end
    CLM->>BCP: settlement, payable, payment
    BCP-->>R: paid
    CLM->>CLM: RI recovery per cession and layer, claim complete

Three things to internalise:

  • The claim is assessed against the policy as at the loss date. The snapshot makes this true even if the policy is endorsed afterwards.
  • Reserves are movements, not balances. Every change is an immutable row with an accounting date; the invariant current reserve − paid to date = outstanding is asserted in the schema checks.
  • Recovery is part of the claim, not an afterthought. After payment, the claim looks for subrogation (third party at fault), salvage (damaged property), reinsurance (the ceded share) and recoverable deductibles — each tracked from expected to recovered and booked as a RECOVERY movement that reduces net incurred.

A declared catastrophe tags claims to an event with an hours clause, so accumulated incurred can be measured against catastrophe reinsurance layers, which are then consumed reinstatement by reinstatement.

Where it lives — inspire-gi: ClaimNotificationsController, ClaimCalculationsController, ClaimSettlementsController, ClaimPaymentsController, ClaimRecoveriesController, CatastrophesController; ClaimRegistrationService, ClaimReserveService; tables tclaim_notification, tclaim, tclaim_policy, tclaim_item, tclaim_reserve_movement; §6. Group’s claims modules add adjudication edits and the provider network (docs/04-module-specs/claims.md).

Stage 5 — Money: billing, collection, ledger, reinsurance

Section titled “Stage 5 — Money: billing, collection, ledger, reinsurance”
flowchart TB
    EV["Business event<br/>issuance, endorsement, settlement"] --> B["Bill, immutable once created"]
    B --> F["Fees: net premium, tax,<br/>commission, stamp"]
    F --> AR["AR or AP<br/>one row per installment"]
    M["Money arrives"] --> S["Suspense<br/>park now"]
    S --> O["Offset<br/>allocate to AR"]
    O --> OK["AR balance zero"]
    P["Money goes out<br/>claim, refund, commission"] --> PAY["Payment<br/>clears the AP directly"]

Collection goes through suspense and offset; payment clears its payable directly — there is no offset step. Small residual balances clear by tolerance offset; uncollectible debt by write-off; both are authority-controlled. An agent’s or reinsurer’s many debits and credits net into one statement settlement.

Fees flagged for the ledger match a posting template by transaction and fee type, expand into balanced debit and credit legs with accounts and up to 12 dimensions, stage as vouchers, then post as immutable journals per open accounting period, updating the trial balance and — in EXTERNAL or BOTH mode — transmitting to the external ledger. Vouchers are staged deliberately: a posting run can be reviewed, corrected and re-run before it becomes immutable. Closing a period blocks posting into it and triggers the statutory and IFRS 17 extracts.

Proportional treaties cede at issuance — a share of sum insured and premium. Non-proportional treaties attach at claim — a share of loss above the attachment point. Everything downstream derives from cessions, so the retention calculation happens once:

flowchart TB
    A["Policy issued or endorsed"] --> B["Determine retention<br/>by LOB, object type, SI band"]
    B --> C{"Within treaty capacity?"}
    C -->|"yes"| D["Cede to the treaty<br/>proportional"]
    C -->|"no"| E["Place facultatively"]
    D & E --> F["Split across participants<br/>shares total 100 percent"]
    F --> G["RI premium<br/>ceded minus commission and brokerage"]
    H["Claim settled"] --> I["Recover<br/>ceded share or layers above attachment"]
    G & I --> J["Bordereaux, statements,<br/>accounts per reinsurer"]

Where it lives — billing: BillsController, BillingListsController, ArapController, StatementsController (sql/08-finance-bcp.sql); ledger: JournalPostingController, VouchersController, TrialBalanceController (sql/09-gl.sql); reinsurance: TreatiesController, CessionsController, FacultativesController, BordereauxController (sql/10-reinsurance.sql); §7–9. Bulk variants — partner file in, certificates out, one consolidated AR — are §10 and are central to credit life; see the next page.