Five states, one table of legal moves
Enrollment status is a five-value enum — pending consent, active, paused, disenrolled, deceased — with pending consent as the server default. Every legal transition is enumerated in a module-level map: pending consent may become active, disenrolled or deceased; active may become paused, disenrolled or deceased; disenrolled is terminal except for death; deceased is fully terminal.
Creation always writes the row as pending consent regardless of what the client asks for, and two service guards run before the insert. The first checks eligibility — at least two active chronic conditions, computed as the maximum of three independent sources rather than one. The function's own docstring explains why: relying on a single source made every published candidate un-enrollable. The second rejects a second open enrollment for the same patient and program, enforced in the service layer because MySQL cannot express a partial unique index.
Consent is captured as columns on the enrollment row — the date it was given, the method it was given by, and a reference to the signed document. They are written at creation and travel with the enrollment for the life of the programme, so the record of agreement sits on the same row as the care it authorised.
