Policies & Coverage
A Policy is the master insurance contract between the insurer and an Account (an employer group or an individual). This page covers the enrollment domain: the quote-to-cancellation lifecycle and the effective-dated versioning model that lets coverage change over time without losing history.
Field reference: exhaustive columns, types and nullability for every entity here live in the catalog: glossary terms
Policy,PolicyTerm,PolicyElement,PolicyTransaction,Quote,Product,ProductVersion,Coverage,MemberCoverage. This page is the narrative.
Who owns what
| Concept | Owning service |
|---|---|
Policy, PolicyTerm, PolicyElement, PolicyTransaction, Quote, UnderwritingFlag | enrollment |
Product, ProductVersion | policy-admin |
Coverage (abstract), MemberCoverage (read-model) | eligibility |
Policy lifecycle
A policy begins as a Quote (a priced proposal). Once accepted and underwritten, the quote converts to an active Policy. The policy accrues a PolicyTerm for each coverage period as it renews. At any point it can be endorsed (changed mid-term), lapsed for non-payment, or cancelled.
| Status | Meaning |
|---|---|
ACTIVE | Coverage is in force; claims are adjudicable. |
LAPSED | Premium unpaid beyond the grace period; coverage suspended, new claims rejected; reinstatement possible. |
CANCELLED | Irrevocably terminated. |
EXPIRED | Term ended and renewal was not completed. |
The effective-dated versioning model
Olly follows a Socotra-style effective-dated model, the core of the enrollment domain: changes do not mutate records in place; they create new versions.
PolicyTermis the coverage period and the adjudication anchor. Accumulators,ClaimLines andMemberCoverageare all scoped to a term, and adjudication resolves benefits against the term in force on the claim's incident date. A renewal opens a new term, not a new policy.PolicyElementis one insured unit within a term (an employee or a dependant;element_typeisemployee | dependent). An endorsement (adding a dependant, changing a benefit) does not edit the element; it writes a new version (a new row) carrying the samestatic_id.static_idis the continuity key. It is stable across an element's versions, so accumulators (deductible / out-of-pocket spend) andClaimLine.elementIdresolve continuously even as the element is re-versioned mid-term.PolicyTransactionis the unit of change that produces those versions: issuance, renewal, endorsement, cancellation, reinstatement, reversal. Unlike the quote audit trail, a transaction is not immutable; it carries a mutablestatus(defaultDRAFT) and progresses through states. Itseffective_datecontrols when the change takes economic effect, which may differ from the processing date.
Statuses and categories are conventions, not enforced enums
PolicyTransaction.category / .status and PolicyTerm.status / PolicyElement.status are free TEXT with no DB CHECK and no Go enum. The value sets below are documented conventions the services apply, not constraints the database rejects bad values against.
PolicyTransaction.category | When | Typical status progression |
|---|---|---|
ISSUANCE | Policy first bound | DRAFT → PRICED → UNDERWRITTEN → APPLIED |
RENEWAL | Term rollover | DRAFT → PRICED → APPLIED |
ENDORSEMENT | Mid-term change | DRAFT → PRICED → APPLIED |
CANCELLATION | Policy terminated | DRAFT → APPLIED |
REINSTATEMENT | Lapsed policy restored | DRAFT → APPLIED |
REVERSAL | Corrects a prior transaction | DRAFT → REVERSED |
Quote → policy issuance
Quoteholds astatus, a pinnedProductVersion, and adocumentJSONB blob with the rated premium, benefit schedule and applicant data.QuoteEventis an append-only audit trail of status changes on the quote.UnderwritingFlagrecords an individual underwriter decision applied to a quote; multiple can coexist and the strictest wins.Policyis created when the quote is accepted and the first premium is collected;Policy.quoteIdlinks back to the originating quote.
Product and ProductVersion
A Product (owned by policy-admin) is the plan definition (e.g. "Olly Select PMI"). Its status is ACTIVE | INACTIVE only (a real DB CHECK; there is no DRAFT/RETIRED). The versioned benefit schema lives on ProductVersion (status DRAFT → PUBLISHED, immutable once published). Quotes and Policies pin a ProductVersion so their benefit schedule stays stable as the parent product evolves.
Coverage vs MemberCoverage
Coverage is the abstract entitlement (FHIR/FIBO-aligned). It is realised at runtime as MemberCoverage rows in the eligibility service, a denormalised projection of a member's in-force benefits, built by consuming enrollment events. Adjudication reads MemberCoverage (fast, term-scoped), not the enrollment tables directly. See Eligibility & Accumulators.
Invariants
- A
Policybelongs to exactly oneAccount; aPolicyTermbelongs to exactly onePolicy; aPolicyElementto exactly one term. static_idis stable across aPolicyElement's effective-dated versions and is the join key for continuous accumulators and forClaimLine.elementId.- A
PolicyElement'seffective_tois null while the version is open-ended;party_idis nullable (null for non-person elements such as a coverage). - A
Policy/Quotereferences a specificProductVersion, never the mutableProduct.
Caveats
- Term vs PolicyTerm. Claims code references
olly:Term, but the physical coverage-period record isPolicyTerm(enrollment.policy_terms). This naming is unreconciled; see the catalog caveats. - US-style benefit vocabulary.
PolicyElement.coverage_termsuses copay / coinsurance / deductible / OOP-max keys; on this UK-context platform those are placeholder semantics and the real keys may differ. locator(external, unique-per-DB) andid(internal UUID) are distinct identities, consistently across these entities.
