PENDING → ACTIVE → MATURED → SETTLED → ARCHIVED, and why status is derived rather than stored.
Every vault, without exception, moves through the same five stages in the same order — there is no branching path and no shortcut. Only three genuinely irreversible milestones are ever stored as timestamps — activatedAt, settledAt, archivedAt — and the human-readable status you see is derived on read directly from them, not stored as its own field.
This one decision quietly eliminates an entire class of bugs. Storing the status enum directly would create a synchronization hazard: nothing would automatically stop status == ACTIVE from being true after maturity passes, unless every single code path remembered to write MATURED at exactly the right moment — an easy thing to get subtly wrong once, and hard to catch in review. Deriving status instead means there’s nothing to forget and nothing to get out of sync.
archivedAt != 0 -> ARCHIVED settledAt != 0 -> SETTLED activatedAt != 0 && block.timestamp >= maturityAt -> MATURED activatedAt != 0 -> ACTIVE (none of the above) -> PENDING