ELD Identity and HOS Record Linkage
A driver vehicle inspection report is a legal attestation, and an attestation is only worth the identity behind it. When a DVIR records its certifying driver as free-text — a typed name, a scanned signature, a badge number keyed by hand — you have a record no auditor can trust, because nothing ties that string to the authenticated person who actually operated the vehicle. Under 49 CFR Part 395, that same driver’s on-duty and driving time is already captured against a verified electronic logging device (ELD) identity; the next driver’s pre-trip review and sign-off under § 396.11©(2)(iii) is likewise supposed to be a real login, not a checkbox. This guide specifies how to link each DVIR to a verified ELD driver identity and correlate it with Hours-of-Service records, so every certification is attributable to an authenticated person.
This section sits inside the Telematics, ELD & Maintenance Platform Integration section, whose canonical DvirComplianceEvent carries a driver_id this layer must resolve to a real ELD identity before the event is trusted. It works alongside CMMS Work Order Synchronization, which closes the repair loop, and it depends on the same field contract enforced by the Standardized DVIR JSON Schema Design. The concrete join-and-verify procedure is detailed in Linking DVIR Events to ELD Driver Identity; this page defines the schema, the correlation algorithm, and the rejection rules those steps implement.
Prerequisites and Environment Setup
Anchor link to "Prerequisites and Environment Setup"Identity linkage is a validation service that runs on every DVIR before its compliance event is trusted. Target Python 3.10+ (the code uses X | Y unions and match/case) with:
- Pydantic 2.x — model the
EldIdentityLinkcontract and validate inbound ELD directory and HOS payloads. - httpx — query the ELD provider’s driver directory and HOS endpoints; the vendor-neutral adapter layer normalizes these across Samsara, Geotab, and Motive.
hashlib(stdlib) — SHA-256 hashing of the license number before storage; the raw number is personally identifiable information and must not be persisted in the clear.- A time-window join capability — SQL range join or an interval index, because the match is on
(driver, vehicle, time window), not an exact-timestamp equality. - The canonical event contract — the inbound
DvirComplianceEventfrom the Telematics, ELD & Maintenance Platform Integration section, carrying thedriver_idandvehicle_vinthis layer resolves.
Handle the license number as PII from the first line. Hash it before it lands anywhere durable, apply the same protections as Encrypting DVIR Data at Rest and in Transit, and never log it.
Data Schema and Normalization
Anchor link to "Data Schema and Normalization"Linkage produces one record: the EldIdentityLink that binds a DVIR to a verified ELD identity. Its field names stay consistent with the section’s event and the DVIR schema so a single inspection can be reconstructed end to end.
| Field | Type | Enumeration / range | Compliance tag |
|---|---|---|---|
dvir_id |
str |
matches the source DVIR | FMCSA_396.11 |
eld_driver_id |
str |
authenticated ELD identity | § 396.11©(2)(iii) sign-off |
license_number_hash |
str |
SHA-256 hex | PII — never stored in clear |
vehicle_ems_id |
str |
ELD equipment/vehicle id | Asset correlation key |
hos_status |
str (enum) |
on_duty, driving, off_duty, sleeper |
49 CFR Part 395 |
verified_at |
datetime (tz-aware) |
ISO-8601 | Verification audit anchor |
The hos_status must be one the driver could legally hold while certifying an inspection: a certification stamped while the driver’s ELD shows off_duty in a different vehicle is a mismatch to reject, not to reconcile. Enforce the contract in Pydantic so an unverifiable link is never persisted:
import hashlib
from datetime import datetime
from enum import Enum
from pydantic import BaseModel, field_validator
class HosStatus(str, Enum):
ON_DUTY = "on_duty"
DRIVING = "driving"
OFF_DUTY = "off_duty"
SLEEPER = "sleeper"
class EldIdentityLink(BaseModel):
model_config = {"use_enum_values": True}
dvir_id: str
eld_driver_id: str
license_number_hash: str # SHA-256 hex, 64 chars
vehicle_ems_id: str
hos_status: HosStatus
verified_at: datetime
@field_validator("license_number_hash")
@classmethod
def _looks_hashed(cls, v: str) -> str:
if len(v) != 64 or not all(c in "0123456789abcdef" for c in v):
raise ValueError("license_number_hash must be a SHA-256 hex digest")
return v
def hash_license(license_number: str) -> str:
"""SHA-256 the license number before storage. Never persist the raw value."""
return hashlib.sha256(license_number.strip().upper().encode()).hexdigest()
Core Algorithm or Workflow
Anchor link to "Core Algorithm or Workflow"Linkage is a join followed by a verification gate. Run it as an ordered sequence so an unmatched or unauthenticated record is rejected before it can be trusted as a certification.
- Read the claimed identity. Take
driver_id,vehicle_vin, andinspection_tsoff the DVIR event. Treat these as a claim, not a fact. - Resolve the ELD identity. Query the ELD driver directory for the authenticated
eld_driver_idand license number that correspond to the claimeddriver_id. If no authenticated identity exists, reject the certification outright — a free-text or unknown driver cannot certify a DVIR. - Correlate with the HOS record. Join against the Part 395 log to confirm the driver was on duty in that vehicle during a tolerance window around
inspection_ts. The join is on(eld_driver_id, vehicle, time window), absorbing the clock skew between mobile capture and the ELD clock. - Verify the credential and window. Confirm the license credential is valid and the HOS window matches. A mismatch — wrong vehicle, no on-duty period, expired credential — fails the gate.
- Hash and persist, or quarantine. On success, hash the license number, build the
EldIdentityLink, and stampverified_at. On failure, quarantine the record for human review and refuse to mark the DVIR certified.
Two design choices make this pipeline defensible. The join is on (eld_driver_id, vehicle, time window) rather than on the raw driver_id string, because the string is the untrusted claim and the ELD identity is the fact; resolving one to the other is the whole point of the exercise. And the tolerance window is bounded and recorded, not open-ended — an unbounded window would eventually match an unrelated on-duty period and manufacture a false attribution, so the window is sized to the observed skew and every match records the actual offset for later tuning. A record that fails to resolve is never coerced into validity; the pipeline would rather quarantine a legitimate handoff for a human to confirm than silently attach the wrong driver to a legal attestation.
The verification gate is a pure predicate over the resolved identity and the HOS window, so the same inputs always yield the same verdict:
from datetime import datetime, timedelta
TOLERANCE = timedelta(minutes=15) # absorbs mobile-vs-ELD clock skew
def within_window(inspection_ts: datetime, hos_start: datetime, hos_end: datetime) -> bool:
return (hos_start - TOLERANCE) <= inspection_ts <= (hos_end + TOLERANCE)
def verify_identity(
claimed_driver_id: str,
eld_identity: dict | None,
hos_record: dict | None,
inspection_ts: datetime,
vehicle_vin: str,
) -> bool:
"""Reject unauthenticated or mismatched certifications. A DVIR may be
certified only by an authenticated ELD identity on duty in that vehicle."""
if eld_identity is None:
return False # free-text / unknown driver — reject (§ 396.11(c)(2)(iii))
if hos_record is None or hos_record["vehicle_vin"] != vehicle_vin:
return False # not on duty in this vehicle
return within_window(inspection_ts, hos_record["start"], hos_record["end"])
Compliance Thresholding and Routing
Anchor link to "Compliance Thresholding and Routing"Identity verification is a gate, not a score, and its outcomes are binary with a clear regulatory basis:
- Verified: the DVIR is certified by an authenticated ELD identity confirmed on duty in the inspected vehicle. Emit the
EldIdentityLinkand let the compliance event proceed to routing. - Unauthenticated: the claimed
driver_idresolves to no ELD identity. Reject the certification. A DVIR certified by a name no ELD can authenticate does not satisfy the driver-attribution intent of § 396.11©(2)(iii), and the next driver’s review cannot be tied to a real login. - Mismatched: the identity resolves but the HOS record places the driver off duty, in another vehicle, or outside the tolerance window. Quarantine for review — this is the signature of a shared login, a team-driving handoff recorded against the wrong driver, or a driver logged into the wrong vehicle.
A verified linkage is also the precondition for a trustworthy repair certification downstream: the mechanic sign-off recorded by CMMS Work Order Synchronization and the driver review under Certifying Repairs Under 396.11©(2) both rely on the certifying party being a real, authenticated identity. Where a driver operates across state lines, correlate against the jurisdiction that issued the HOS record rather than the carrier’s home state, because Part 395 exemptions vary and an identity valid in one context may be out of hours in another.
The mismatch outcome deserves particular care, because most mismatches are not fraud — they are the ordinary friction of real operations. A team-driving pair swaps the wheel mid-shift and the DVIR is certified by the resting co-driver while the log still shows the other driver as driving; a driver forgets to select the correct asset in the ELD app after a yard move; a mobile device with a stale time zone stamps a certification an hour off. Each of these produces a technically failing join, and each has a legitimate reconciliation. The system’s job is to distinguish the correctable mismatch from the certification that names a driver who never operated the vehicle at all. Attach both the claimed and the resolved identity, the HOS window, and both vehicle references to every quarantined record, so a reviewer can resolve the common cases quickly and escalate only the genuine attribution failures. The concrete reconciliation for each case is worked through in Linking DVIR Events to ELD Driver Identity.
Production Integration and Platform Synchronization
Anchor link to "Production Integration and Platform Synchronization"- Reject at the boundary, do not repair silently. An unauthenticated certification is a compliance failure, not a data-quality nuisance. Reject it at ingestion and surface it; never invent an identity to make the record validate.
- Tolerance windows, not exact matches. Mobile DVIR capture and the ELD clock drift. Join on a bounded time window sized to your fleet’s observed skew, and record the actual skew so the window can be tuned rather than guessed.
- Hash PII on the way in. SHA-256 the license number before it touches durable storage, and keep the raw value out of logs and events. The hash is enough to match and to prove attribution without holding the identifier in the clear.
- Chain the verification into the audit trail. Record each
EldIdentityLinkwith averified_attimestamp and link it into the tamper-evident chain from Audit Logging and Tamper-Evident Event Chains, so an auditor can see who certified what and when. - Quarantine, then reconcile. Route mismatches to a review queue with enough context — claimed id, resolved id, HOS window, vehicle — for a human to reconcile a legitimate handoff or confirm a genuine violation. Absorb bursts with a dead-letter queue rather than blocking ingestion.
Engineering Standards Checklist
Anchor link to "Engineering Standards Checklist"- Authenticated certifiers only — a DVIR that resolves to no ELD identity is rejected, never certified on a free-text name.
- Time-window join — correlate DVIR and HOS on a bounded tolerance window, not exact-timestamp equality, to absorb clock skew.
- PII hashed at the boundary — SHA-256 the license number before storage; keep the raw value out of logs and events.
- Mismatches quarantined — off-duty, wrong-vehicle, or out-of-window certifications route to human review, not silent acceptance.
- Verification is deterministic — the gate is a pure predicate over the resolved identity and HOS window; same inputs, same verdict.
- Chained into the audit trail — every
EldIdentityLinkcarriesverified_atand joins the tamper-evident chain.
Frequently Asked Questions
Anchor link to "Frequently Asked Questions"Why can’t a DVIR just record the driver’s typed name?
Because a typed name is not an authenticated identity, and § 396.11©(2)(iii) intends the next driver’s review to be a real, attributable act. A free-text name ties the certification to nothing an auditor can verify. Resolving the claimed driver_id to an authenticated ELD identity, confirmed on duty in the inspected vehicle, makes the certification attributable to a real person.
How do you handle clock skew between the mobile DVIR app and the ELD?
Join on a bounded tolerance window rather than an exact timestamp. Mobile capture and the ELD clock drift by seconds to minutes, so an equality join would reject legitimate records. Size the window to your fleet’s observed skew — often around 15 minutes — and record the actual skew per match so the window can be tuned from data instead of guessed.
What should happen when the identity resolves but the HOS record does not match?
Quarantine the record for human review and refuse to mark the DVIR certified. A resolved identity with a non-matching HOS window is the signature of a shared login, a team-driving handoff logged against the wrong driver, or a driver logged into the wrong vehicle. A human must reconcile a legitimate handoff or confirm a genuine violation before the certification is trusted.
Related
Anchor link to "Related"- Linking DVIR Events to ELD Driver Identity — the concrete join-and-verify implementation.
- Certifying Repairs Under 396.11©(2) — the driver review that depends on a verified identity.
- Encrypting DVIR Data at Rest and in Transit — the PII protections the license-hash step applies.
- Samsara, Geotab and Motive Platform Adapters — normalizes the ELD directory and HOS queries across vendors.
- Audit Logging and Tamper-Evident Event Chains — the chain each verification record joins.