Members & Parties
Olly uses a unified Party model for any person or organisation that interacts with the platform: members, dependants, employers, brokers and providers all share one table, distinguished by type. A Member is not a table of its own; it is a projection over a Party plus its coverage.
Field reference: full columns, types and nullability live in the catalog: glossary terms
Party,PartyRole,Account,Member,MemberCoverage. This page is the narrative.
Who owns what
| Concept | Owning service |
|---|---|
Party, PartyRole, Account | policy-admin |
MemberCoverage | eligibility (a read-model; see Eligibility) |
ConsentRecord, AuditItem, DeletionRequest | consent (see Consent & GDPR) |
The Party model
A Party is any actor on the platform, discriminated by type (INDIVIDUAL | ORGANISATION | PROVIDER). Individuals carry first/last name and date of birth; organisations and providers carry a single name. The locator is the stable, externally shareable reference; the UUID id is internal only. Cross-service references use the party_locator (text), not a foreign key.
Security posture: PHI is not application-encrypted today
A Party holds PHI (name, date of birth, email, phone, address). At-rest protection currently relies on database/disk-level encryption only. The policy-admin code does not application-layer or column-encrypt these fields. Application-layer encryption is planned, not implemented; do not rely on it when reasoning about data exposure.
Member: a projection, not a table
"Member" is a semantic role, aligned to FHIR Patient / schema.org Person. A member is the combination of:
- a
Partyof typeINDIVIDUAL, - a
PartyRoleofINSURED(orDEPENDENT), and - one or more
MemberCoveragerows that say what they are currently covered for.
There is no members table; querying "a member" means joining these. Live entitlements for adjudication come from MemberCoverage in the eligibility service, not from the party record.
PartyRole
A Party acquires meaning in context through PartyRole. One party can hold several roles across several entities (an individual can be ACCOUNT_HOLDER on one account and INSURED on two policies).
| Role (DB CHECK) | Meaning |
|---|---|
ACCOUNT_HOLDER | Responsible for the account (typically the employer or primary individual). |
INSURED | Covered under a specific policy. |
BENEFICIARY | Designated to receive a benefit payout. |
DEPENDENT | A dependant covered under another party's policy. |
entity_type is ACCOUNT | POLICY | QUOTE and entity_id is a polymorphic UUID with no database FK; it is resolved against the named entity by entity_type. (Note dependants are represented two ways: as a DEPENDENT PartyRole and as a PolicyElement of element_type = dependent; see Policies.)
Account: the billing container
An Account owns policies and receives invoices; currency defaults to GBP. An employer group scheme has one Account (the employer organisation's party, holding the ACCOUNT_HOLDER role) linked to many policies (one per employee), with all invoices rolling up to the employer account. The scheme structure itself is covered in Group Schemes.
Consent & deletion
Member consent and the GDPR Article 17 right-to-erasure workflow live in the consent service and have their own page; see Consent & GDPR. In short: each ConsentRecord is keyed (party_locator, consent_type) with a granted boolean, every change is logged to an append-only AuditItem, and a DeletionRequest (SOFT/HARD) drives erasure while regulated records are retained.
Invariants
Party.locatorandAccount.locatorare unique per database; cross-service joins useparty_locator, not FKs.- A member's live coverage is the set of
MemberCoveragerows in eligibility, eventually consistent and projected from enrollment events. PartyRole.entity_idhas no DB FK; integrity is enforced in application code.
Caveats
- PHI is not application-layer encrypted today (see the security note above).
consent_typeis freeTEXTwith no DB CHECK; the conventional types are documented on the Consent page, but the column accepts any string.- A single cross-domain audit log is aspirational;
AuditItemis currently consent-scoped (consent.consent_audit).
