ADR-016 Status: Proposed Version 0.1 2026-05-12
Requiemos / Architecture

The Domain
Aggregate Model

Three operational aggregates — Contract Management, Chain of Custody, Case Workflow — sitting over a two-layer substrate of durable Person identity and operational Case state.

In one breath

Make the three-capability mental model that we already use in pitches and PRDs architecturally explicit, and introduce a Person identity layer beneath the case so that pre-need contracts — newly in MVP scope — have a place to live.

A two-layer substrate, three operational aggregates

Person identity exists before any case. Case substrate is built on top at need-time. Three aggregates operate over this substrate, each owning its own tables. Scheduling sits beside them as a shared service.

Domain aggregate model diagram AGGREGATE Contract Management What was agreed, what it costs spans both substrate layers AGGREGATE Chain of Custody Physical possession & accountability at-need only AGGREGATE Case Workflow Orchestration & lifecycle execution at-need only pre-need references SUBSTRATE LAYER · AT NEED-TIME Case Substrate cases  ·  case_deceased  ·  case_family_members  ·  branches deceased role attaches a Person to a Case SUBSTRATE LAYER · DURABLE IDENTITY Person Identity people  ·  person_relationships  ·  exists independent of any case CROSS-CUTTING SERVICE Scheduling — calendars, resources, availability; consumed by all three aggregates

The two substrate layers

Identity lives at the base; case state sits above it. Workflow, contracts, and custody all read and write through these layers but never own them.

Substrate · Durable

Person Identity

The base layer. People exist before any case — pre-need clients, repeat-customer families, multi-generational relationships. The substrate is the only writer of identity facts; all aggregates that need to update a Person call substrate services. Identity verification follows a supersession pattern (corrections do not overwrite history).

Substrate · Operational

Case Substrate

Materialized when a death occurs (or a first-call is received). The umbrella record for one active case: who is the deceased, which family members are involved, which branch, which jurisdiction, what status. Case-scoped facts about the deceased (time, place, cause of death) live here — not on the Person record.

The three operational aggregates

Each owns a distinct source of authority. Cross-aggregate writes go through service interfaces; the database does not enforce this, code review does.

01
Contract Management
Spans Person & Case
"What was agreed to, and what it costs."

Sole writer of pricing catalogs, contracts, line items, amendments, signed documents. Pre-need contracts reference a Person directly; at-need contracts reference a Case. At-need conversion is internal to this aggregate — not a cross-aggregate handoff.

Representative tables
  • gpl_packages, gpl_line_items
  • pre_need_contracts
  • case_contracts, amendments
  • case_documents, signature_*
02
Chain of Custody
At-need only
"Physical possession and asset accountability."

The aggregate with the strongest regulatory and legal-discovery requirements. Custody events are immutable, append-only, with supersession for corrections. CoC scan modules in Workflow trigger writes through a service interface — never direct inserts. Asset terminal-state checks block case closure.

Representative tables
  • custody_events (Layer 1)
  • assets
03
Case Workflow
At-need only
"Orchestration and lifecycle execution."

The largest aggregate by table count and the most active at runtime. Owns module execution state and the context envelope. Reads extensively from substrate, contract, and CoC — writes back only through service interfaces. The module engine produces activity-event and services-rendered writes automatically on module completion.

Representative tables
  • workflow_templates, _modules
  • case_module_instances
  • case_activity_events (L3)
  • case_services_rendered (L4)
Cross-cutting

Scheduling is a service, not an aggregate. It owns calendars, resources, and availability — written to by Workflow (most often), Contract Management (arrangement conferences), and CoC (transport). Scheduled events show up on cases as Layer 3 activity events when relevant.

Pre-need is now in MVP scope

A scope discovery on 2026-05-12 added pre-arrangement contracts to MVP. Pre-need agreements predate any case — they reference a living person, with locked-in pricing that activates at need-time. Without a Person identity layer, the data model traps deceased records inside cases and cannot represent a future-deceased who has no case yet.

Pre-need is contract management, not a separate aggregate.

The regulatory grouping (FTC Funeral Rule, BC's Cremation, Interment and Funeral Services Act) treats pre-need and at-need as a single contractual continuum. Pricing structure, GPL catalogs, packages, and amendment patterns are the same.

What differs is the relationship target: pre-need points at a Person, at-need points at a Case. Same aggregate, different reference.

In MVP: pre-need agreement structure, line items, locked-in pricing. Out of MVP: trust accounting, payment schedules, escrow tracking.

PRE-NEED CONTRACT references Person locked-in pricing at need CASE CONTRACT references Case same prices preserved PERSON durable identity CASE materialized at-need conversion is internal to Contract Management

Six boundary rules

Code-organization and review rules, not database constraints. They prevent the aggregate boundaries from drifting as the system grows and turn ambiguous design questions into decided ones.

01

Exclusive write authority

Each aggregate is the only writer of its tables. Cross-aggregate writes happen through published service interfaces.

02

Substrate owns identity facts

Person fields (name, DOB, identity_verified) are updated only by substrate services. Identity verification supersession is enforced here.

03

Pre-need conversion is internal

At-need conversion of a pre-need contract is a Contract Management operation. The trigger is a substrate event Contracts subscribes to.

04

CoC and Workflow require a case

Neither aggregate has a pre-need analog. A pre-need Person has no custody history and no workflow execution. Structural fact, not a constraint.

05

Reconciliation crosses boundaries

services_rendered (Workflow) is read by Contract Management during reconciliation. The most prominent cross-aggregate read; result lands as a contract amendment.

06

Scheduling is consumed, not owned

Multiple aggregates write scheduled events through the scheduling service. The service enforces resource availability; aggregates trust it.