Enforce Adoption Lifecycle State Machine (Domain Integrity)
🎯 Goal
Implement a strict state machine to control valid Adoption.status transitions and prevent invalid lifecycle mutations.
Adoption state must never be mutated arbitrarily.
Control adoption transitions.
🛠 Tasks
- Define valid transitions
- Block invalid ones
- Admin override
🧠 Why This Is Needed
Without controlled transitions, we risk:
Marking completed adoptions as pending
Skipping escrow phase
Approving rejected requests
Data inconsistency between escrow + adoption status
Since adoption directly affects:
Pet ownership
Escrow release
Trust score updates
On-chain anchoring
We must guarantee integrity.
📊 Valid Adoption Status Flow
Primary Flow
REQUESTED
↓
PENDING_REVIEW
↓
APPROVED
↓
ESCROW_FUNDED
↓
COMPLETED
Alternative / Exit Flows
REQUESTED → REJECTED
PENDING_REVIEW → REJECTED
APPROVED → CANCELLED
ESCROW_FUNDED → REFUNDED
❌ Invalid Transitions
COMPLETED → PENDING_REVIEW
REJECTED → APPROVED
REFUNDED → COMPLETED
CANCELLED → APPROVED
ESCROW_FUNDED → REQUESTED
All invalid transitions must throw a DomainException.
🏗 Implementation Plan
1️⃣ Create AdoptionStateMachine service
class AdoptionStateMachine {
canTransition(from: AdoptionStatus, to: AdoptionStatus): boolean
}
2️⃣ Use explicit transition map
const transitions = {
REQUESTED: ['PENDING_REVIEW', 'REJECTED'],
PENDING_REVIEW: ['APPROVED', 'REJECTED'],
APPROVED: ['ESCROW_FUNDED', 'CANCELLED'],
ESCROW_FUNDED: ['COMPLETED', 'REFUNDED'],
COMPLETED: [],
REJECTED: [],
CANCELLED: [],
REFUNDED: []
}
3️⃣ Enforce inside AdoptionService before updating status
Never update status directly in repository.
🔒 Acceptance Criteria
Invalid transitions throw exception
Valid transitions succeed
Unit tests cover all transitions
Escrow release only allowed when status = ESCROW_FUNDED
Adoption COMPLETED updates pet ownership
EventLog entry created on every valid transition
Enforce Adoption Lifecycle State Machine (Domain Integrity)
🎯 Goal
Implement a strict state machine to control valid Adoption.status transitions and prevent invalid lifecycle mutations.
Adoption state must never be mutated arbitrarily.
Control adoption transitions.
🛠 Tasks
🧠 Why This Is Needed
Without controlled transitions, we risk:
Marking completed adoptions as pending
Skipping escrow phase
Approving rejected requests
Data inconsistency between escrow + adoption status
Since adoption directly affects:
Pet ownership
Escrow release
Trust score updates
On-chain anchoring
We must guarantee integrity.
📊 Valid Adoption Status Flow
Primary Flow
REQUESTED
↓
PENDING_REVIEW
↓
APPROVED
↓
ESCROW_FUNDED
↓
COMPLETED
Alternative / Exit Flows
REQUESTED → REJECTED
PENDING_REVIEW → REJECTED
APPROVED → CANCELLED
ESCROW_FUNDED → REFUNDED
❌ Invalid Transitions
COMPLETED → PENDING_REVIEW
REJECTED → APPROVED
REFUNDED → COMPLETED
CANCELLED → APPROVED
ESCROW_FUNDED → REQUESTED
All invalid transitions must throw a DomainException.
🏗 Implementation Plan
1️⃣ Create AdoptionStateMachine service
class AdoptionStateMachine {
canTransition(from: AdoptionStatus, to: AdoptionStatus): boolean
}
2️⃣ Use explicit transition map
const transitions = {
REQUESTED: ['PENDING_REVIEW', 'REJECTED'],
PENDING_REVIEW: ['APPROVED', 'REJECTED'],
APPROVED: ['ESCROW_FUNDED', 'CANCELLED'],
ESCROW_FUNDED: ['COMPLETED', 'REFUNDED'],
COMPLETED: [],
REJECTED: [],
CANCELLED: [],
REFUNDED: []
}
3️⃣ Enforce inside AdoptionService before updating status
Never update status directly in repository.
🔒 Acceptance Criteria
Invalid transitions throw exception
Valid transitions succeed
Unit tests cover all transitions
Escrow release only allowed when status = ESCROW_FUNDED
Adoption COMPLETED updates pet ownership
EventLog entry created on every valid transition