# Domain model Use UUID primary keys internally. Human-facing references are immutable unique strings. ## User - id - public_ref (`USR-...`) - display_name - role: `operations_manager | rental_employee` - active ## Customer - id - public_ref (`CUS-0001`) - first_name, last_name - email, phone - postal_code, city - date_of_birth (optional) - merged_into_customer_id (optional) - created_at, updated_at ## Vehicle - id - public_ref (`MO-001`) - make, model, model_year - registration_number - location - operational_status: `available | rented | cleaning | maintenance | blocked` - odometer_km - next_service_km - active - version for optimistic concurrency ## Booking - id - public_ref (`BK-...`) - customer_id, vehicle_id - starts_at, ends_at - status: `reserved | active | returned | cancelled | blocked` - start_odometer_km, end_odometer_km - requirements_complete Database invariant: active/reserved bookings for the same vehicle may not overlap after validation. A deliberate seeded conflict may be imported as an external-data quality issue through a controlled bypass, never created through the normal command API. ## Inspection - id - public_ref - booking_id, vehicle_id - type: `checkout | return` - fuel_level_percent - cleanliness_ok - damage_reported - technical_warning - notes - odometer_km - completed_at, completed_by ## MaintenanceRecord - id - vehicle_id - occurred_at - odometer_km - category - summary ## DataQualityIssue - id - public_ref - rule_type: - `possible_duplicate_customer` - `missing_required_field` - `odometer_regression` - `booking_overlap` - `vehicle_status_conflict` - entity_type, entity_id - severity: `low | medium | high` - status: `open | deferred | resolved | rejected` - evidence_json - proposed_action_json - detected_at, resolved_at, resolved_by ## OutboxEvent / WorkflowRun - id / event_id - event_type - aggregate_type, aggregate_id - payload_json - occurred_at - delivery_status: `pending | delivering | succeeded | failed` - attempts, next_attempt_at, last_error - external_run_id ## AuditEvent - id - actor_type: `user | service | system` - actor_id / actor_label - action - entity_type, entity_id - correlation_id - before_json, after_json, metadata_json - occurred_at ## Required invariants - a vehicle return cannot reduce the canonical odometer; - a return with a lower submitted reading is recorded as an inspection and issue, while canonical odometer remains unchanged; - damage or a critical warning blocks the vehicle; - merged customers remain as tombstones linked to the survivor; - resolving a quality issue and applying its correction is transactional and audited; - public references never change after creation.