Bounded Context: Driver Management (DRV)
Responsibility: Driver onboarding, identity and background verification, vehicle registration with document expiry, availability toggling, ratings, operator-reviewed suspension, and appeal lifecycle.
Context Map
| Relation | Other Bounded Context | Position | Pattern | Description |
|---|---|---|---|---|
| DRV → RideManagement | Ride Management (RIDE) | upstream | Open Host Service (OHS) | DRV exposes match-eligible online drivers with their current location (REQ-DRV-032) for matching. RIDE is the dominant consumer. |
| DRV ↔ RideManagement | Ride Management (RIDE) | downstream | Customer/Supplier | DRV consumes RideCompleted (carrying driverRating) and DriverNoShowRecorded from RIDE; bridged into SubmitRating and into suspension-proposal context. |
| DRV → GeolocationRouting | Geolocation & Routing (GEO) | downstream | Anti-Corruption Layer (ACL) | DRV consumes DriverPositionStale from GEO through an ACL and translates it into GoOffline(reason=stalePosition). |
| DRV → IdentityVerificationProvider | external (certified third party) | downstream | Conformist (infrastructure) | DRV depends on a certified third-party for identity and background verification. Wrapped behind the IdentityVerificationProvider infrastructure-service; SLA bounded by REQ-DRV-NFR-001. |
| DRV → DocumentStorage | external infrastructure | downstream | Conformist (infrastructure) | Encrypted document store wrapped behind DocumentStorageService; meets REQ-DRV-NFR-002 and REQ-DRV-NFR-003. |
| DRV → DriverNotification | external infrastructure | downstream | Conformist (infrastructure) | Push, SMS, and email channels wrapped behind DriverNotificationService for status updates, warnings, and appeal outcomes. |
Enums
VerificationState
- Values:
pendingVerification,verified,rejected,suspended,appealInReview,permanentlySuspended. - Realizes: REQ-DRV-001, REQ-DRV-003, REQ-DRV-004, REQ-DRV-005, REQ-DRV-006, REQ-DRV-033, REQ-DRV-048, REQ-DRV-049.
AvailabilityState
- Values:
offline,online. - Realizes: REQ-DRV-030, REQ-DRV-031, REQ-DRV-032, REQ-DRV-034.
DocumentType
- Values:
driversLicence,passport,nationalId,selfie. - Realizes: REQ-DRV-002.
BackgroundCheckResult
- Values:
clear,failed. - Realizes: REQ-DRV-005, REQ-DRV-006.
OfflineReason
- Values:
voluntary,stalePosition,suspension,documentExpired. - Realizes: REQ-DRV-031, REQ-DRV-034, REQ-DRV-022.
AppealOutcome
- Values:
reinstated,permanentlySuspended. - Realizes: REQ-DRV-049.
NotificationChannel
- Values:
email,sms,push. - Realizes: REQ-DRV-008.
Value Types
EmailAddress
- Fields:
value: String —format(email)
- Realizes: REQ-DRV-001 (driver contact).
PhoneNumber
- Fields:
countryCode: Stringnumber: String
- Realizes: REQ-DRV-001 (driver contact).
FullName
- Fields:
firstName: String —maxLength(100)lastName: String —maxLength(100)
- Realizes: REQ-DRV-001.
Rating
- Fields:
value: Integer —min(1),max(5)
- Realizes: REQ-DRV-040, REQ-DRV-041.
AverageRating
Running aggregate of ratings for a driver.
- Fields:
value: Decimal —min(1.0),max(5.0)totalRatings: Integer —min(0)ratingSum: Integer —min(0)
- Invariants:
consistentAggregate: whentotalRatings > 0,value = ratingSum / totalRatings— enforcement: reject.
- Realizes: REQ-DRV-040, REQ-DRV-041, REQ-DRV-042.
VehicleDetails
- Fields:
make: Stringmodel: Stringyear: Integer —min(1990)color: StringlicencePlate: String
- Realizes: REQ-DRV-020.
InspectionResult
- Fields:
passed: BooleaninspectedAt: DateTimeexpiresAt: DateTimepartner: String
- Invariants:
expiryAfterInspection:expiresAt > inspectedAt.
- Realizes: REQ-DRV-021, REQ-DRV-022.
AppealDetails
- Fields:
reason: String —maxLength(2000)submittedAt: DateTime
- Realizes: REQ-DRV-047, REQ-DRV-048.
AppealResolution
- Fields:
outcome:AppealOutcomeoperatorId: UUIDresolvedAt: DateTimejustification: String —maxLength(2000)
- Realizes: REQ-DRV-049, REQ-DRV-NFR-005.
Entities
IdentityDocument
Driver-provided identity, licence, or selfie.
- Identifier:
documentId : UUID - Fields:
driverId: UUIDdocumentType:DocumentTypedocumentNumber: StringstorageRef: StringuploadedAt: DateTimeexpiresAt: DateTime optionalverified: Boolean — defaultfalse
- Operations:
Upload identity documenton commandUploadIdentityDocument- Realizes: REQ-DRV-002
- State changes (
sets):driverId,documentType,documentNumber,storageRef,expiresAtfrom the command;uploadedAt = now(). - Emits:
IdentityDocumentUploadedwithdocumentId,driverId,documentType,uploadedAt.
- Realizes: REQ-DRV-002, REQ-DRV-NFR-002, REQ-DRV-NFR-003.
Vehicle
Driver vehicle with documents and inspection state.
- Identifier:
vehicleId : UUID - Fields:
driverId: UUIDdetails:VehicleDetailsregistrationExpiresAt: DateTimeinsuranceExpiresAt: DateTimeinspection:InspectionResulteligible: Boolean — defaultfalseregisteredAt: DateTime
- Invariants:
eligibilityRequiresValidDocs: wheneligible = true,inspection.passed = trueandinspection.expiresAt > now()andregistrationExpiresAt > now()andinsuranceExpiresAt > now()— enforcement: reject.
- Operations:
Register vehicleon commandRegisterVehicle- Realizes: REQ-DRV-020
- State changes (
sets):driverId,details,registrationExpiresAt,insuranceExpiresAtfrom the command;registeredAt = now();eligible = false. - Emits:
VehicleRegisteredwithvehicleId,driverId,registeredAt.
Record inspection resulton commandRecordVehicleInspection- Realizes: REQ-DRV-020, REQ-DRV-021
- State changes:
inspection = recordVehicleInspection.inspection;eligible = inspection.passed and inspection.expiresAt > now() and Vehicle.registrationExpiresAt > now() and Vehicle.insuranceExpiresAt > now(). - Emits:
VehicleInspectionRecordedwithvehicleId,passed,eligibleNow.
Mark vehicle ineligible due to expired documenton commandMarkVehicleIneligible- Realizes: REQ-DRV-022, REQ-DRV-023
- Precondition
documentExpired:Vehicle.registrationExpiresAt <= now()orVehicle.insuranceExpiresAt <= now()orVehicle.inspection.expiresAt <= now(). - State change:
eligible = false. - Emits:
VehicleBecameIneligiblewithvehicleId,driverId,reason,detectedAt = now().
- Realizes: REQ-DRV-020, REQ-DRV-021, REQ-DRV-022, REQ-DRV-023.
Driver
Driver lifecycle root — verification, availability, ratings, appeals.
- Identifier:
driverId : UUID - Fields:
fullName:FullNameemail:EmailAddressphone:PhoneNumberverificationState:VerificationState— defaultpendingVerificationavailability:AvailabilityState— defaultofflineselectedVehicleId: UUID optionalaverageRating:AverageRatingoptionaltotalRidesCompleted: Integer —min(0), default0cancellationCountWindow: Integer —min(0), default0noShowCountWindow: Integer —min(0), default0appeal:AppealDetailsoptionalappealResolution:AppealResolutionoptionalregisteredAt: DateTime
- Invariants:
singleVehicleSelected:selectedVehicleId is null or count(selectedVehicleId) = 1— enforcement: reject.verifiedHasNoOpenAppeal: whenverificationState = verified,appeal is null— enforcement: alert.
- Operations:
Register driveron commandRegisterDriver- Realizes: REQ-DRV-001
- State changes:
fullName,email,phonefrom the command;verificationState = pendingVerification;availability = offline;registeredAt = now(). - Emits:
DriverRegisteredwithdriverId,registeredAt.
Complete background checkon commandCompleteBackgroundCheck- Realizes: REQ-DRV-005
- Preconditions:
awaitingVerification:Driver.verificationState = pendingVerificationresultIsClear:completeBackgroundCheck.result = clear
- State change:
verificationState = verified. - Emits:
DriverVerifiedwithdriverId,verifiedAt = now().
Reject driver applicationon commandRejectDriverApplication- Realizes: REQ-DRV-006
- Precondition
awaitingVerification:Driver.verificationState = pendingVerification. - State change:
verificationState = rejected. - Emits:
DriverApplicationRejectedwithdriverId,reason,rejectedAt = now().
Go onlineon commandGoOnline- Realizes: REQ-DRV-030, REQ-DRV-032, REQ-DRV-033, REQ-DRV-NFR-004
- Preconditions:
isVerified:Driver.verificationState = verifiednotSuspended:Driver.verificationState != suspendedhasEligibleVehicle:Driver.selectedVehicleId is defined
- State change:
availability = online. - Emits:
DriverWentOnlinewithdriverId,selectedVehicleId,onlineAt = now().
Go offlineon commandGoOffline- Realizes: REQ-DRV-031
- Precondition
wasOnline:Driver.availability = online. - State change:
availability = offline. - Emits:
DriverWentOfflinewithdriverId,reason,offlineAt = now().
Submit ratingon commandSubmitRating- Realizes: REQ-DRV-040, REQ-DRV-041, REQ-DRV-042
- Precondition
validRange:submitRating.rating.value >= 1 and submitRating.rating.value <= 5. - State changes:
averageRating = recompute(Driver.averageRating, submitRating.rating);totalRidesCompleted = Driver.totalRidesCompleted + 1. - Emits:
RatingSubmittedwithdriverId,rating,newAverage,totalRides,submittedAt = now().
Issue rating warningon commandIssueRatingWarning- Realizes: REQ-DRV-043
- Preconditions:
matureDriver:Driver.totalRidesCompleted > 20belowWarningThreshold:Driver.averageRating.value < 4.2
- Emits:
RatingWarningIssuedwithdriverId,averageRating,issuedAt = now().
Propose suspensionon commandProposeSuspension- Realizes: REQ-DRV-044, REQ-DRV-046
- Preconditions:
matureDriver:Driver.totalRidesCompleted > 20belowSuspensionThreshold:Driver.averageRating.value < 4.0
- Emits:
SuspensionProposalCreatedwithdriverId,averageRating,cancellationCount,noShowCount,proposedAt = now().
Suspend driveron commandSuspendDriver- Realizes: REQ-DRV-044, REQ-DRV-045, REQ-DRV-046, REQ-DRV-NFR-005
- Precondition
operatorApproved:suspendDriver.operatorId is defined. - State changes:
verificationState = suspended;availability = offline. - Emits:
DriverSuspendedwithdriverId,operatorId,reason,duration(Duration),suspendedAt = now().
Submit suspension appealon commandSubmitAppeal- Realizes: REQ-DRV-047, REQ-DRV-048
- Precondition
isSuspended:Driver.verificationState = suspended. - State changes:
verificationState = appealInReview;appeal = AppealDetails(reason = submitAppeal.reason, submittedAt = now()). - Emits:
AppealSubmittedwithdriverId,submittedAt = now().
Resolve appealon commandResolveAppeal- Realizes: REQ-DRV-049, REQ-DRV-NFR-005
- Precondition
appealUnderReview:Driver.verificationState = appealInReview. - State changes:
verificationState = if resolveAppeal.outcome = reinstated then verified else permanentlySuspended;appealResolution = AppealResolution(outcome, operatorId, resolvedAt = now(), justification);appeal = null. - Emits:
AppealResolvedwithdriverId,outcome,operatorId,resolvedAt = now().
- Realizes: REQ-DRV-001, REQ-DRV-003, REQ-DRV-004, REQ-DRV-005, REQ-DRV-006, REQ-DRV-030, REQ-DRV-031, REQ-DRV-032, REQ-DRV-033, REQ-DRV-040, REQ-DRV-043, REQ-DRV-044, REQ-DRV-046, REQ-DRV-047, REQ-DRV-048, REQ-DRV-049.
Aggregates
DriverAggregate
- Root:
Driver - Contains:
Vehicle,IdentityDocument - Boundary intent: consistency for driver state, vehicle eligibility, and document attachment is enforced inside this aggregate. Cross-aggregate effects (rating bridge from RIDE, stale-position from GEO) are mediated through reactions.
State Machines
DriverLifecycle on Driver
- Start state:
pendingVerification - States:
pendingVerification— state-scoped invariantnoRidesYet:Driver.totalRidesCompleted = 0verified— no extra invariants beyond the entity-levelverifiedHasNoOpenAppealrejected— finalsuspended— state-scoped invariantofflineWhileSuspended:Driver.availability = offlineappealInReview— driver awaits operator decisionpermanentlySuspended— final
- Transitions:
pendingVerification→verifiedon commandCompleteBackgroundCheckpendingVerification→rejectedon commandRejectDriverApplicationverified→suspendedon commandSuspendDriversuspended→appealInReviewon commandSubmitAppealappealInReview→verifiedon commandResolveAppeal(whenoutcome = reinstated)appealInReview→permanentlySuspendedon commandResolveAppeal(whenoutcome = permanentlySuspended)
- Final states:
rejected,permanentlySuspended.
The state-scoped invariants are conjoined with the entity-level invariants. offlineWhileSuspended together with the notSuspended precondition on GoOnline realizes REQ-DRV-033. noRidesYet together with the isVerified precondition on GoOnline realizes REQ-DRV-004.
Domain Services
DocumentExpiryChecker
Detects upcoming or expired documents and triggers the ineligibility path.
- Operations:
checkDocumentExpiry(now: datetime) : void— scans vehicles for expiry and issuesMarkVehicleIneligiblewhen needed.
- Realizes: REQ-DRV-022.
VerificationStatusReporter
Exposes onboarding status to the driver app.
- Operations:
getCurrentStatus(driverId: uuid) : VerificationStategetEstimatedTimeToVerify(driverId: uuid) : Duration
- Realizes: REQ-DRV-003, REQ-DRV-007, REQ-DRV-008.
Infrastructure Services
IdentityVerificationProvider
Certified third-party identity and background check — infrastructure boundary.
- Operations:
requestVerification(driverId: uuid, documents: list<DocumentRef>) : void— submit application to provider.getStatus(requestId: uuid) : VerificationState— poll or receive callback.
- Realizes: REQ-DRV-002, REQ-DRV-005, REQ-DRV-006, REQ-DRV-NFR-001, REQ-NFR-010.
DocumentStorageService
Encrypted document store — infrastructure boundary for identity documents and licences.
- Operations:
storeDocument(driverId: uuid, documentType: DocumentType, fileContent: bytes) : string— returns astorageRef.getDocumentUrl(storageRef: string, ttl: Duration) : string— time-limited signed URL.deleteDocument(storageRef: string) : void— used to honour erasure requests.
- Realizes: REQ-DRV-NFR-002, REQ-NFR-020.
DriverNotificationService
Push, SMS, and email channels to drivers — infrastructure boundary.
- Operations:
notifyDriver(driverId: uuid, subject: string, message: string, channel: NotificationChannel) : void
- Realizes: REQ-DRV-006, REQ-DRV-008, REQ-DRV-022, REQ-DRV-043, REQ-DRV-044, REQ-DRV-049.
Commands
| Command | Fields | Realizes |
|---|---|---|
RegisterDriver |
fullName, email, phone, correlationId |
REQ-DRV-001 |
UploadIdentityDocument |
driverId, documentType, documentNumber, storageRef, expiresAt?, correlationId |
REQ-DRV-002 |
CompleteBackgroundCheck |
driverId, result, correlationId |
REQ-DRV-005 |
RejectDriverApplication |
driverId, reason, correlationId |
REQ-DRV-006 |
RegisterVehicle |
driverId, details, registrationExpiresAt, insuranceExpiresAt, correlationId |
REQ-DRV-020 |
RecordVehicleInspection |
vehicleId, inspection, correlationId |
REQ-DRV-020, REQ-DRV-021 |
MarkVehicleIneligible |
vehicleId, reason, correlationId |
REQ-DRV-022, REQ-DRV-023 |
GoOnline |
driverId, correlationId |
REQ-DRV-030, REQ-DRV-032, REQ-DRV-033, REQ-DRV-NFR-004 |
GoOffline |
driverId, reason, correlationId |
REQ-DRV-031, REQ-DRV-034 |
SubmitRating |
driverId, rideId, rating, correlationId |
REQ-DRV-040, REQ-DRV-041 |
IssueRatingWarning |
driverId, correlationId |
REQ-DRV-043 |
ProposeSuspension |
driverId, correlationId |
REQ-DRV-044, REQ-DRV-046 |
SuspendDriver |
driverId, operatorId, reason, duration, correlationId |
REQ-DRV-044, REQ-DRV-045 |
SubmitAppeal |
driverId, reason, correlationId |
REQ-DRV-047, REQ-DRV-048 |
ResolveAppeal |
driverId, operatorId, outcome, justification, correlationId |
REQ-DRV-049, REQ-DRV-NFR-005 |
Events
Internal events
| Event | Fields | Realizes |
|---|---|---|
DriverRegistered |
driverId, registeredAt |
REQ-DRV-001 |
IdentityDocumentUploaded |
documentId, driverId, documentType, uploadedAt |
REQ-DRV-002 |
DriverVerified |
driverId, verifiedAt |
REQ-DRV-005 |
DriverApplicationRejected |
driverId, reason, rejectedAt |
REQ-DRV-006 |
VehicleRegistered |
vehicleId, driverId, registeredAt |
REQ-DRV-020 |
VehicleInspectionRecorded |
vehicleId, passed, eligibleNow |
REQ-DRV-021 |
VehicleBecameIneligible |
vehicleId, driverId, reason, detectedAt |
REQ-DRV-022 |
DriverWentOnline |
driverId, selectedVehicleId, onlineAt |
REQ-DRV-030 |
DriverWentOffline |
driverId, reason, offlineAt |
REQ-DRV-031, REQ-DRV-034 |
RatingSubmitted |
driverId, rating, newAverage, totalRides, submittedAt |
REQ-DRV-040 |
RatingWarningIssued |
driverId, averageRating, issuedAt |
REQ-DRV-043 |
SuspensionProposalCreated |
driverId, averageRating, cancellationCount, noShowCount, proposedAt |
REQ-DRV-044 |
DriverSuspended |
driverId, operatorId, reason, duration, suspendedAt |
REQ-DRV-044, REQ-DRV-045, REQ-DRV-NFR-005 |
AppealSubmitted |
driverId, submittedAt |
REQ-DRV-047, REQ-DRV-048 |
AppealResolved |
driverId, outcome, operatorId, resolvedAt |
REQ-DRV-049, REQ-DRV-NFR-005 |
External-bound events (Published Language)
DriverWentOnline, DriverWentOffline, and the implicit match-eligibility projection cross to Ride Management, which is the consumer of the supply-side state. DriverVerified, DriverSuspended, and AppealResolved are also published to the audit and notification surface.
External-consumed events
| Event | From | Used by |
|---|---|---|
RideCompleted |
Ride Management | reaction tickRatingsOnRideCompleted → SubmitRating when event.driverRating is defined |
DriverNoShowRecorded |
Ride Management | feeds noShowCountWindow and suspension-proposal context |
DriverPositionStale |
Geolocation & Routing | reaction takeOfflineOnStalePosition → GoOffline(reason=stalePosition) (ACL) |
Reactions
warnOnLowRating
“Issue rating warning when driver dips below 4.2 with maturity.”
- Trigger: event
RatingSubmitted - Guard:
event.totalRides > 20 and event.newAverage.value < 4.2 and event.newAverage.value >= 4.0 - Effect:
IssueRatingWarning(driverId = event.driverId) - Realizes: REQ-DRV-043
proposeSuspensionOnSustainedLowRating
“Queue suspension proposal when driver drops below 4.0.”
- Trigger: event
RatingSubmitted - Guard:
event.totalRides > 20 and event.newAverage.value < 4.0 - Effect:
ProposeSuspension(driverId = event.driverId) - Realizes: REQ-DRV-044, REQ-DRV-046
suspendOnVehicleIneligibility
“Take driver offline when their vehicle becomes ineligible.”
- Trigger: event
VehicleBecameIneligible - Effect:
GoOffline(driverId = event.driverId, reason = documentExpired) - Realizes: REQ-DRV-022, REQ-DRV-023
takeOfflineOnStalePosition
“Take driver offline on stale position from Geolocation.”
- Trigger: event
DriverPositionStale - Effect:
GoOffline(driverId = event.driverId, reason = stalePosition) - Realizes: REQ-DRV-034
notifyOnRejection
“Notify driver and include reason on rejection.”
- Trigger: event
DriverApplicationRejected - Effect:
DriverNotificationService.notifyDriver(driverId, subject = "Application rejected", message = event.reason, channel = push) - Realizes: REQ-DRV-006, REQ-DRV-008
notifyOnVerified
“Notify driver within 24h of verification status change.”
- Trigger: event
DriverVerified - Effect:
DriverNotificationService.notifyDriver(driverId, subject = "You are verified", message = "You can now go online and start driving.", channel = push) - Realizes: REQ-DRV-008
notifyOnSuspensionDecision
“Notify driver on appeal resolution.”
- Trigger: event
AppealResolved - Effect:
DriverNotificationService.notifyDriver(driverId, subject = "Appeal resolved", message = "Outcome: " + event.outcome, channel = push) - Realizes: REQ-DRV-049
tickRatingsOnRideCompleted
“Bridge from RideManagement — record rider rating of driver.”
- Trigger: event
RideCompleted - Guard:
event.driverRating is defined - Effect:
SubmitRating(driverId = event.driverId, rideId = event.rideId, rating = event.driverRating) - Realizes: REQ-DRV-040
Traceability Matrix
| Requirement | Realized by |
|---|---|
REQ-DRV-001 |
Driver, command RegisterDriver, op Register driver, event DriverRegistered |
REQ-DRV-002 |
IdentityDocument, command UploadIdentityDocument, op Upload identity document, event IdentityDocumentUploaded, IdentityVerificationProvider |
REQ-DRV-003 |
Driver (verificationState), VerificationStatusReporter.getCurrentStatus |
REQ-DRV-004 |
Driver precondition isVerified on GoOnline; statemachine pendingVerification/rejected states |
REQ-DRV-005 |
Driver op Complete background check, command CompleteBackgroundCheck, event DriverVerified, IdentityVerificationProvider |
REQ-DRV-006 |
Driver op Reject driver application, command RejectDriverApplication, event DriverApplicationRejected, reaction notifyOnRejection, DriverNotificationService |
REQ-DRV-007 |
VerificationStatusReporter.getEstimatedTimeToVerify |
REQ-DRV-008 |
VerificationStatusReporter, reactions notifyOnRejection, notifyOnVerified, DriverNotificationService |
REQ-DRV-020 |
Vehicle, command RegisterVehicle, op Register vehicle, event VehicleRegistered; RecordVehicleInspection |
REQ-DRV-021 |
Vehicle invariant eligibilityRequiresValidDocs, InspectionResult, op Record inspection result |
REQ-DRV-022 |
Vehicle op Mark vehicle ineligible, event VehicleBecameIneligible, DocumentExpiryChecker, reaction suspendOnVehicleIneligibility, DriverNotificationService |
REQ-DRV-023 |
Vehicle (eligibility) + Driver precondition hasEligibleVehicle on GoOnline; reaction suspendOnVehicleIneligibility |
REQ-DRV-030 |
Driver op Go online, command GoOnline, event DriverWentOnline |
REQ-DRV-031 |
Driver op Go offline, command GoOffline, event DriverWentOffline |
REQ-DRV-032 |
Driver (online state exposed to RIDE via OHS) |
REQ-DRV-033 |
Driver precondition notSuspended on GoOnline; statemachine offlineWhileSuspended invariant |
REQ-DRV-034 |
reaction takeOfflineOnStalePosition, command GoOffline (reason = stalePosition), event DriverWentOffline |
REQ-DRV-040 |
Rating, AverageRating, Driver op Submit rating, command SubmitRating, event RatingSubmitted, reaction tickRatingsOnRideCompleted |
REQ-DRV-041 |
Rating (min(1), max(5)), op Submit rating (precondition validRange) |
REQ-DRV-042 |
AverageRating, Driver.averageRating exposed to driver app |
REQ-DRV-043 |
Driver op Issue rating warning, command IssueRatingWarning, event RatingWarningIssued, reaction warnOnLowRating, DriverNotificationService |
REQ-DRV-044 |
Driver op Propose suspension and Suspend driver, commands ProposeSuspension/SuspendDriver, events SuspensionProposalCreated/DriverSuspended, reaction proposeSuspensionOnSustainedLowRating |
REQ-DRV-045 |
Driver op Suspend driver (records operatorId), event DriverSuspended, AppealResolution.operatorId |
REQ-DRV-046 |
Driver op Suspend driver (precondition operatorApproved); reaction proposeSuspensionOnSustainedLowRating only proposes — does not auto-suspend |
REQ-DRV-047 |
AppealDetails, Driver op Submit suspension appeal, command SubmitAppeal, event AppealSubmitted |
REQ-DRV-048 |
Driver op Submit suspension appeal, statemachine transition suspended → appealInReview |
REQ-DRV-049 |
AppealResolution, Driver op Resolve appeal, command ResolveAppeal, event AppealResolved, reaction notifyOnSuspensionDecision |
REQ-DRV-NFR-001 |
IdentityVerificationProvider (SLA budget) |
REQ-DRV-NFR-002 |
IdentityDocument, DocumentStorageService (encryption-at-rest baseline) |
REQ-DRV-NFR-003 |
IdentityDocument, DocumentStorageService.deleteDocument (retention/erasure) |
REQ-DRV-NFR-004 |
Driver op Go online (latency budget) |
REQ-DRV-NFR-005 |
AppealResolution, events DriverSuspended and AppealResolved (append-only audit log retained ≥ 7 years) |
Concrete syntax (.domain DSL)
The full .domain source that this page narrates. Entity declarations, value types, commands, events, invariants, preconditions, services, state machine, and reactions appear in parse order.
context DriverManagement :: "Driver onboarding, identity, vehicles, availability, ratings, suspension" {
requirements-source "driver-management.sysreq"
enum VerificationState { pendingVerification, verified, rejected, suspended, appealInReview, permanentlySuspended }
enum AvailabilityState { offline, online }
enum DocumentType { driversLicence, passport, nationalId, selfie }
enum BackgroundCheckResult { clear, failed }
enum OfflineReason { voluntary, stalePosition, suspension, documentExpired }
enum AppealOutcome { reinstated, permanentlySuspended }
enum NotificationChannel { email, sms, push }
// -----------------------------------------------------------------
// Value types
// -----------------------------------------------------------------
value EmailAddress { fields { value : string format(email) } }
value PhoneNumber { fields { countryCode : string; number : string } }
value FullName { fields { firstName : string maxLength(100); lastName : string maxLength(100) } }
value Rating { fields { value : int min(1) max(5) } }
value AverageRating :: "Running aggregate of ratings for a driver" {
satisfies [REQ-DRV-040, REQ-DRV-041, REQ-DRV-042]
fields {
value : decimal min(1.0) max(5.0)
totalRatings : int min(0)
ratingSum : int min(0)
}
invariants {
consistentAggregate :: "Average is sum / count" enforcement reject {
if totalRatings > 0 { value = ratingSum / totalRatings }
}
}
}
value VehicleDetails {
fields {
make : string
model : string
year : int min(1990)
color : string
licencePlate : string
}
}
value InspectionResult {
satisfies [REQ-DRV-021, REQ-DRV-022]
fields {
passed : boolean
inspectedAt : datetime
expiresAt : datetime
partner : string
}
invariants {
expiryAfterInspection { expiresAt > inspectedAt }
}
}
value AppealDetails {
fields { reason : string maxLength(2000); submittedAt : datetime }
}
value AppealResolution {
satisfies [REQ-DRV-049, REQ-DRV-NFR-005]
fields {
outcome : AppealOutcome
operatorId : uuid
resolvedAt : datetime
justification : string maxLength(2000)
}
}
// -----------------------------------------------------------------
// Entities
// -----------------------------------------------------------------
entity IdentityDocument :: "Driver-provided identity, licence, or selfie" {
satisfies [REQ-DRV-002, REQ-DRV-NFR-002, REQ-DRV-NFR-003]
identifier documentId : UUID
fields {
driverId : UUID
documentType : DocumentType
documentNumber : string
storageRef : string
uploadedAt : datetime
expiresAt : datetime optional
verified : boolean default(false)
}
operations {
"Upload identity document" on UploadIdentityDocument {
satisfies [REQ-DRV-002]
sets IdentityDocument {
driverId = uploadIdentityDocument.driverId
documentType = uploadIdentityDocument.documentType
documentNumber = uploadIdentityDocument.documentNumber
storageRef = uploadIdentityDocument.storageRef
uploadedAt = now()
expiresAt = uploadIdentityDocument.expiresAt
}
emits IdentityDocumentUploaded {
documentId = IdentityDocument.documentId
driverId = IdentityDocument.driverId
documentType = IdentityDocument.documentType
uploadedAt = IdentityDocument.uploadedAt
}
}
}
}
entity Vehicle :: "Driver vehicle with documents and inspection state" {
satisfies [REQ-DRV-020, REQ-DRV-021, REQ-DRV-022, REQ-DRV-023]
identifier vehicleId : UUID
fields {
driverId : UUID
details : VehicleDetails
registrationExpiresAt : datetime
insuranceExpiresAt : datetime
inspection : InspectionResult
eligible : boolean default(false)
registeredAt : datetime
}
invariants {
eligibilityRequiresValidDocs :: "Eligible only when all docs valid" enforcement reject {
if eligible = true {
inspection.passed = true
and inspection.expiresAt > now()
and registrationExpiresAt > now()
and insuranceExpiresAt > now()
}
}
}
operations {
"Register vehicle" on RegisterVehicle {
satisfies [REQ-DRV-020]
sets Vehicle {
driverId = registerVehicle.driverId
details = registerVehicle.details
registrationExpiresAt = registerVehicle.registrationExpiresAt
insuranceExpiresAt = registerVehicle.insuranceExpiresAt
registeredAt = now()
eligible = false
}
emits VehicleRegistered {
vehicleId = Vehicle.vehicleId
driverId = Vehicle.driverId
registeredAt = Vehicle.registeredAt
}
}
"Record inspection result" on RecordVehicleInspection {
satisfies [REQ-DRV-020, REQ-DRV-021]
sets Vehicle {
inspection = recordVehicleInspection.inspection
eligible = recordVehicleInspection.inspection.passed
and recordVehicleInspection.inspection.expiresAt > now()
and Vehicle.registrationExpiresAt > now()
and Vehicle.insuranceExpiresAt > now()
}
emits VehicleInspectionRecorded {
vehicleId = Vehicle.vehicleId
passed = Vehicle.inspection.passed
eligibleNow = Vehicle.eligible
}
}
"Mark vehicle ineligible due to expired document" on MarkVehicleIneligible {
satisfies [REQ-DRV-022, REQ-DRV-023]
precondition documentExpired {
Vehicle.registrationExpiresAt <= now()
or Vehicle.insuranceExpiresAt <= now()
or Vehicle.inspection.expiresAt <= now()
}
sets Vehicle { eligible = false }
emits VehicleBecameIneligible {
vehicleId = Vehicle.vehicleId
driverId = Vehicle.driverId
reason = markVehicleIneligible.reason
detectedAt = now()
}
}
}
}
entity Driver :: "Driver lifecycle root — verification, availability, ratings, appeals" {
satisfies [REQ-DRV-001, REQ-DRV-003, REQ-DRV-004, REQ-DRV-005, REQ-DRV-006,
REQ-DRV-030, REQ-DRV-031, REQ-DRV-032, REQ-DRV-033,
REQ-DRV-040, REQ-DRV-043, REQ-DRV-044, REQ-DRV-046,
REQ-DRV-047, REQ-DRV-048, REQ-DRV-049]
identifier driverId : UUID
fields {
fullName : FullName
email : EmailAddress
phone : PhoneNumber
verificationState : VerificationState default("pendingVerification")
availability : AvailabilityState default("offline")
selectedVehicleId : UUID optional
averageRating : AverageRating optional
totalRidesCompleted : int min(0) default(0)
cancellationCountWindow : int min(0) default(0)
noShowCountWindow : int min(0) default(0)
appeal : AppealDetails optional
appealResolution : AppealResolution optional
registeredAt : datetime
}
invariants {
singleVehicleSelected :: "Driver may have at most one selected vehicle at a time" enforcement reject {
selectedVehicleId is null or count(selectedVehicleId) = 1
}
verifiedHasNoOpenAppeal :: "Verified drivers do not carry an open appeal" enforcement alert {
if verificationState = verified { appeal is null }
}
}
operations {
"Register driver" on RegisterDriver {
satisfies [REQ-DRV-001]
sets Driver {
fullName = registerDriver.fullName
email = registerDriver.email
phone = registerDriver.phone
verificationState = pendingVerification
availability = offline
registeredAt = now()
}
emits DriverRegistered {
driverId = Driver.driverId
registeredAt = Driver.registeredAt
}
}
"Complete background check" on CompleteBackgroundCheck {
satisfies [REQ-DRV-005]
precondition awaitingVerification { Driver.verificationState = pendingVerification }
precondition resultIsClear { completeBackgroundCheck.result = clear }
sets Driver { verificationState = verified }
emits DriverVerified {
driverId = Driver.driverId
verifiedAt = now()
}
}
"Reject driver application" on RejectDriverApplication {
satisfies [REQ-DRV-006]
precondition awaitingVerification { Driver.verificationState = pendingVerification }
sets Driver { verificationState = rejected }
emits DriverApplicationRejected {
driverId = Driver.driverId
reason = rejectDriverApplication.reason
rejectedAt = now()
}
}
"Go online" on GoOnline {
satisfies [REQ-DRV-030, REQ-DRV-032, REQ-DRV-033, REQ-DRV-NFR-004]
precondition isVerified { Driver.verificationState = verified }
precondition notSuspended { Driver.verificationState != suspended }
precondition hasEligibleVehicle { Driver.selectedVehicleId is defined }
sets Driver { availability = online }
emits DriverWentOnline {
driverId = Driver.driverId
selectedVehicleId = Driver.selectedVehicleId
onlineAt = now()
}
}
"Go offline" on GoOffline {
satisfies [REQ-DRV-031]
precondition wasOnline { Driver.availability = online }
sets Driver { availability = offline }
emits DriverWentOffline {
driverId = Driver.driverId
reason = goOffline.reason
offlineAt = now()
}
}
"Submit rating" on SubmitRating {
satisfies [REQ-DRV-040, REQ-DRV-041, REQ-DRV-042]
precondition validRange {
submitRating.rating.value >= 1
and submitRating.rating.value <= 5
}
sets Driver {
averageRating = recompute(Driver.averageRating, submitRating.rating)
totalRidesCompleted = Driver.totalRidesCompleted + 1
}
emits RatingSubmitted {
driverId = Driver.driverId
rating = submitRating.rating
newAverage = Driver.averageRating
totalRides = Driver.totalRidesCompleted
submittedAt = now()
}
}
"Issue rating warning" on IssueRatingWarning {
satisfies [REQ-DRV-043]
precondition matureDriver { Driver.totalRidesCompleted > 20 }
precondition belowWarningThreshold { Driver.averageRating.value < 4.2 }
emits RatingWarningIssued {
driverId = Driver.driverId
averageRating = Driver.averageRating
issuedAt = now()
}
}
"Propose suspension" on ProposeSuspension {
satisfies [REQ-DRV-044, REQ-DRV-046]
precondition matureDriver { Driver.totalRidesCompleted > 20 }
precondition belowSuspensionThreshold { Driver.averageRating.value < 4.0 }
emits SuspensionProposalCreated {
driverId = Driver.driverId
averageRating = Driver.averageRating
cancellationCount = Driver.cancellationCountWindow
noShowCount = Driver.noShowCountWindow
proposedAt = now()
}
}
"Suspend driver" on SuspendDriver {
satisfies [REQ-DRV-044, REQ-DRV-045, REQ-DRV-046, REQ-DRV-NFR-005]
precondition operatorApproved { suspendDriver.operatorId is defined }
sets Driver {
verificationState = suspended
availability = offline
}
emits DriverSuspended {
driverId = Driver.driverId
operatorId = suspendDriver.operatorId
reason = suspendDriver.reason
duration = suspendDriver.duration
suspendedAt = now()
}
}
"Submit suspension appeal" on SubmitAppeal {
satisfies [REQ-DRV-047, REQ-DRV-048]
precondition isSuspended { Driver.verificationState = suspended }
sets Driver {
verificationState = appealInReview
appeal = AppealDetails(reason = submitAppeal.reason, submittedAt = now())
}
emits AppealSubmitted {
driverId = Driver.driverId
submittedAt = now()
}
}
"Resolve appeal" on ResolveAppeal {
satisfies [REQ-DRV-049, REQ-DRV-NFR-005]
precondition appealUnderReview { Driver.verificationState = appealInReview }
sets Driver {
verificationState = if resolveAppeal.outcome = reinstated then verified else permanentlySuspended
appealResolution = AppealResolution(
outcome = resolveAppeal.outcome,
operatorId = resolveAppeal.operatorId,
resolvedAt = now(),
justification = resolveAppeal.justification
)
appeal = null
}
emits AppealResolved {
driverId = Driver.driverId
outcome = resolveAppeal.outcome
operatorId = resolveAppeal.operatorId
resolvedAt = now()
}
}
}
}
aggregate DriverAggregate root Driver { contains [Vehicle, IdentityDocument] }
statemachine DriverLifecycle on Driver {
start pendingVerification
state pendingVerification {
invariant noRidesYet { Driver.totalRidesCompleted = 0 }
}
state verified {}
state rejected {}
state suspended {
invariant offlineWhileSuspended { Driver.availability = offline }
}
state appealInReview {}
state permanentlySuspended {}
transition pendingVerification -> verified on CompleteBackgroundCheck
transition pendingVerification -> rejected on RejectDriverApplication
transition verified -> suspended on SuspendDriver
transition suspended -> appealInReview on SubmitAppeal
transition appealInReview -> verified on ResolveAppeal // outcome = reinstated
transition appealInReview -> permanentlySuspended on ResolveAppeal // outcome = permanentlySuspended
final rejected
final permanentlySuspended
}
// -----------------------------------------------------------------
// Domain services
// -----------------------------------------------------------------
service DocumentExpiryChecker :: "Detects upcoming/expired documents" {
satisfies [REQ-DRV-022]
operations {
checkDocumentExpiry(now: datetime) : void
}
}
service VerificationStatusReporter :: "Exposes onboarding status to driver app" {
satisfies [REQ-DRV-003, REQ-DRV-007, REQ-DRV-008]
operations {
getCurrentStatus(driverId: uuid) : VerificationState
getEstimatedTimeToVerify(driverId: uuid) : Duration
}
}
// -----------------------------------------------------------------
// Infrastructure services
// -----------------------------------------------------------------
infrastructure-service IdentityVerificationProvider :: "Certified third-party identity & background check" {
satisfies [REQ-DRV-002, REQ-DRV-005, REQ-DRV-006, REQ-DRV-NFR-001, REQ-NFR-010]
operations {
requestVerification(driverId: uuid, documents: list<DocumentRef>) : void
getStatus(requestId: uuid) : VerificationState
}
}
infrastructure-service DocumentStorageService :: "Encrypted document store" {
satisfies [REQ-DRV-NFR-002, REQ-NFR-020]
operations {
storeDocument(driverId: uuid, documentType: DocumentType, fileContent: bytes) : string
getDocumentUrl(storageRef: string, ttl: Duration) : string
deleteDocument(storageRef: string) : void
}
}
infrastructure-service DriverNotificationService :: "Push, SMS, and email to drivers" {
satisfies [REQ-DRV-006, REQ-DRV-008, REQ-DRV-022, REQ-DRV-043, REQ-DRV-044, REQ-DRV-049]
operations {
notifyDriver(driverId: uuid, subject: string, message: string, channel: NotificationChannel) : void
}
}
// -----------------------------------------------------------------
// Commands (correlationId omitted for brevity except where critical)
// -----------------------------------------------------------------
command RegisterDriver { fields { fullName: FullName; email: EmailAddress; phone: PhoneNumber; correlationId: uuid } }
command UploadIdentityDocument { fields { driverId: uuid; documentType: DocumentType; documentNumber: string; storageRef: string; expiresAt: datetime optional; correlationId: uuid } }
command CompleteBackgroundCheck { fields { driverId: uuid; result: BackgroundCheckResult; correlationId: uuid } }
command RejectDriverApplication { fields { driverId: uuid; reason: string; correlationId: uuid } }
command RegisterVehicle { fields { driverId: uuid; details: VehicleDetails; registrationExpiresAt: datetime; insuranceExpiresAt: datetime; correlationId: uuid } }
command RecordVehicleInspection { fields { vehicleId: uuid; inspection: InspectionResult; correlationId: uuid } }
command MarkVehicleIneligible { fields { vehicleId: uuid; reason: string; correlationId: uuid } }
command GoOnline { fields { driverId: uuid; correlationId: uuid } }
command GoOffline { fields { driverId: uuid; reason: OfflineReason; correlationId: uuid } }
command SubmitRating { fields { driverId: uuid; rideId: uuid; rating: Rating; correlationId: uuid } }
command IssueRatingWarning { fields { driverId: uuid; correlationId: uuid } }
command ProposeSuspension { fields { driverId: uuid; correlationId: uuid } }
command SuspendDriver { fields { driverId: uuid; operatorId: uuid; reason: string; duration: Duration; correlationId: uuid } }
command SubmitAppeal { fields { driverId: uuid; reason: string; correlationId: uuid } }
command ResolveAppeal { fields { driverId: uuid; operatorId: uuid; outcome: AppealOutcome; justification: string; correlationId: uuid } }
// -----------------------------------------------------------------
// Events — internal
// -----------------------------------------------------------------
event DriverRegistered { satisfies [REQ-DRV-001] fields { driverId: uuid; registeredAt: datetime } }
event IdentityDocumentUploaded { satisfies [REQ-DRV-002] fields { documentId: uuid; driverId: uuid; documentType: DocumentType; uploadedAt: datetime } }
event DriverVerified { satisfies [REQ-DRV-005] fields { driverId: uuid; verifiedAt: datetime } }
event DriverApplicationRejected { satisfies [REQ-DRV-006] fields { driverId: uuid; reason: string; rejectedAt: datetime } }
event VehicleRegistered { satisfies [REQ-DRV-020] fields { vehicleId: uuid; driverId: uuid; registeredAt: datetime } }
event VehicleInspectionRecorded { satisfies [REQ-DRV-021] fields { vehicleId: uuid; passed: boolean; eligibleNow: boolean } }
event VehicleBecameIneligible { satisfies [REQ-DRV-022] fields { vehicleId: uuid; driverId: uuid; reason: string; detectedAt: datetime } }
event DriverWentOnline { satisfies [REQ-DRV-030] fields { driverId: uuid; selectedVehicleId: uuid; onlineAt: datetime } }
event DriverWentOffline { satisfies [REQ-DRV-031, REQ-DRV-034] fields { driverId: uuid; reason: OfflineReason; offlineAt: datetime } }
event RatingSubmitted { satisfies [REQ-DRV-040] fields { driverId: uuid; rating: Rating; newAverage: AverageRating; totalRides: int; submittedAt: datetime } }
event RatingWarningIssued { satisfies [REQ-DRV-043] fields { driverId: uuid; averageRating: AverageRating; issuedAt: datetime } }
event SuspensionProposalCreated { satisfies [REQ-DRV-044] fields { driverId: uuid; averageRating: AverageRating; cancellationCount: int; noShowCount: int; proposedAt: datetime } }
event DriverSuspended { satisfies [REQ-DRV-044, REQ-DRV-045, REQ-DRV-NFR-005] fields { driverId: uuid; operatorId: uuid; reason: string; duration: Duration; suspendedAt: datetime } }
event AppealSubmitted { satisfies [REQ-DRV-047, REQ-DRV-048] fields { driverId: uuid; submittedAt: datetime } }
event AppealResolved { satisfies [REQ-DRV-049, REQ-DRV-NFR-005] fields { driverId: uuid; outcome: AppealOutcome; operatorId: uuid; resolvedAt: datetime } }
// -----------------------------------------------------------------
// Events — external (consumed from other contexts)
// -----------------------------------------------------------------
external-event RideCompleted from RideManagement
external-event DriverNoShowRecorded from RideManagement
external-event DriverPositionStale from GeolocationRouting
// -----------------------------------------------------------------
// Reactions
// -----------------------------------------------------------------
reaction warnOnLowRating :: "Issue rating warning when driver dips below 4.2 with maturity" {
satisfies [REQ-DRV-043]
trigger RatingSubmitted
guard event.totalRides > 20 and event.newAverage.value < 4.2 and event.newAverage.value >= 4.0
effect IssueRatingWarning(driverId = event.driverId)
}
reaction proposeSuspensionOnSustainedLowRating :: "Queue suspension proposal when driver drops below 4.0" {
satisfies [REQ-DRV-044, REQ-DRV-046]
trigger RatingSubmitted
guard event.totalRides > 20 and event.newAverage.value < 4.0
effect ProposeSuspension(driverId = event.driverId)
}
reaction suspendOnVehicleIneligibility :: "Take driver offline when their vehicle becomes ineligible" {
satisfies [REQ-DRV-022, REQ-DRV-023]
trigger VehicleBecameIneligible
effect GoOffline(driverId = event.driverId, reason = documentExpired)
}
reaction takeOfflineOnStalePosition :: "Take driver offline on stale position from Geolocation" {
satisfies [REQ-DRV-034]
trigger DriverPositionStale
effect GoOffline(driverId = event.driverId, reason = stalePosition)
}
reaction notifyOnRejection :: "Notify driver and include reason on rejection" {
satisfies [REQ-DRV-006, REQ-DRV-008]
trigger DriverApplicationRejected
effect DriverNotificationService.notifyDriver(
driverId = event.driverId,
subject = "Application rejected",
message = event.reason,
channel = push
)
}
reaction notifyOnVerified :: "Notify driver within 24h of verification status change" {
satisfies [REQ-DRV-008]
trigger DriverVerified
effect DriverNotificationService.notifyDriver(
driverId = event.driverId,
subject = "You are verified",
message = "You can now go online and start driving.",
channel = push
)
}
reaction notifyOnSuspensionDecision :: "Notify driver on appeal resolution" {
satisfies [REQ-DRV-049]
trigger AppealResolved
effect DriverNotificationService.notifyDriver(
driverId = event.driverId,
subject = "Appeal resolved",
message = "Outcome: " + event.outcome,
channel = push
)
}
reaction tickRatingsOnRideCompleted :: "Bridge from RideManagement — record rider rating of driver" {
satisfies [REQ-DRV-040]
trigger RideCompleted
guard event.driverRating is defined
effect SubmitRating(driverId = event.driverId, rideId = event.rideId, rating = event.driverRating)
}
}