Telematics, ELD & Maintenance Platform Integration
A DVIR record that is ingested, normalized, classified, and severity-scored has satisfied only half of its regulatory purpose. The other half is delivery: the compliant record must be pushed outward to the systems that act on it — the telematics platforms that immobilize a unit, the computerized maintenance management system (CMMS) that opens the work order, and the electronic logging device (ELD) stack that owns driver identity and Hours-of-Service. When a driver reports a cracked brake chamber and the severity scoring engine puts it at 82, the out-of-service (OOS) decision is legally meaningless until Samsara, the CMMS, and the dispatcher’s board all reflect it. This guide is the reference architecture for that outbound edge — the layer that carries a finalized compliance decision from the defect classification and repair routing core into every system of record that must obey it.
The regulatory obligation is explicit and non-transferable. A repair certified under 49 CFR § 396.11©(2) must be reflected back into the maintenance system of record, because that certification is what allows the vehicle to return to service. Systematic maintenance records required by § 396.3 live in the CMMS, and an outbound event that fails to reach it leaves the federal record incomplete. Driver identity and duty status, governed by 49 CFR Part 395, live in the ELD, and a DVIR that cannot be linked to the driver who signed it cannot be defended in an audit. The systems that consume the core DVIR architecture and the ingestion and parsing workflows that feed it all converge here: this is where a compliance decision stops being a database row and becomes an action taken across a fleet’s operational stack.
The whole of this section is built on one invariant — an outbound push must never silently drop a safety-critical OOS hold. Delivery is therefore at-least-once, idempotent, and cryptographically signed. The webhook event delivery layer provides the durable transport; the Samsara, Geotab and Motive adapters translate the canonical event into each vendor’s dialect; the CMMS work order synchronization opens and closes the maintenance record that § 396.3 demands; and the ELD identity and HOS record linkage binds every event to a Part 395 driver identity. This page defines the canonical outbound event they all carry and the delivery guarantees they all inherit.
Why § 396.11©(2) and § 396.3 Enforcement Is Non-Negotiable
Anchor link to "Why § 396.11©(2) and § 396.3 Enforcement Is Non-Negotiable"The regulations that govern maintenance and repair do not stop at the moment a defect is recorded; they follow the vehicle until the defect is resolved and the resolution is documented in a retrievable record. Under § 396.11©(2), the motor carrier must certify that a reported defect was repaired — or that repair was unnecessary — before the vehicle is operated again. That certification is an event with a legal consequence: it is the thing that lifts an OOS hold. If the certification is entered in a mechanic’s app but never propagated to the telematics platform enforcing the hold, the vehicle remains administratively out of service while operationally dispatched, and the carrier is running a unit under a hold its own systems disagree about. The outbound layer exists to make that disagreement impossible.
Under § 396.3(a) and § 396.3©, every motor carrier must systematically inspect, repair, and maintain its vehicles, and must retain the records that prove it. In a modern fleet those records do not live in the DVIR pipeline — they live in the CMMS, alongside parts, labor, and work-order history. An outbound event that opens a work order from a classified defect, and later closes it with the repair certification, is what keeps the § 396.3 record synchronized with the § 396.11 inspection record. When the two drift apart, a DOT auditor sees an open safety defect with no corresponding maintenance action, which is precisely the finding that raises a Vehicle Maintenance BASIC percentile.
These clauses translate into a single system-level invariant: a finalized, certified compliance decision must be delivered to every system of record that is legally required to reflect it, exactly once in effect, and never lost. “In effect” is the operative phrase. At-least-once delivery over an unreliable network means the same event may arrive twice; idempotency on the receiver collapses the duplicate so the compliance state is applied once. The forbidden outcome is the opposite — zero deliveries of an OOS hold — because a dropped hold puts an unsafe vehicle on the road with a clean-looking record. Everything in this section is engineered around making zero-delivery of a critical event impossible, and making double-delivery a harmless no-op.
Architecture Overview: The Outbound Compliance Edge
Anchor link to "Architecture Overview: The Outbound Compliance Edge"The outbound edge begins where classification ends. Once a DVIR record reaches a finalized, certified state, the classification core does not call the telematics API directly — a synchronous call would couple the compliance decision to the availability of a third-party platform, and a Samsara outage would block finalization of a DVIR. Instead, the core writes a DvirComplianceEvent into a transactional outbox inside the same database transaction that finalizes the record. A separate dispatcher reads unsent events, signs each with an HMAC-SHA256 signature and an idempotency key, and fans the event out to the telematics, CMMS, and ELD adapters. Deliveries that exhaust their retry budget route to a dead-letter path for human intervention, and every delivery attempt is written immutably to an audit log.
The design principle is that the compliance decision and its delivery are decoupled but not disconnected. The outbox write is transactional with finalization, so an event exists if and only if the record was truly finalized — there is no window in which a vehicle is cleared internally but no event was recorded, and none in which an event fires for a record that later rolls back. The dispatcher owns retries, signing, and fan-out, so a slow or failing downstream platform never blocks the pipeline. And because delivery is at-least-once, correctness depends on the receiver being idempotent — a property this section treats as a hard requirement, detailed in idempotent webhook retry and signature verification.
Schema-Driven Data Standardization
Anchor link to "Schema-Driven Data Standardization"Every outbound integration in this section carries the same canonical payload: the DvirComplianceEvent. Fixing one event shape across telematics, CMMS, and ELD adapters means a single signing routine, a single idempotency contract, and a single audit format serve every destination — the adapters differ only in how they translate the canonical event into a vendor payload, never in what the event means. The model is frozen (immutable once constructed) so that the exact bytes that were signed are the exact bytes that are delivered and audited; a mutation after signing would invalidate the signature and break tamper-evidence.
| Field | Type | Enumeration / range | Compliance tag |
|---|---|---|---|
event_id |
UUID |
UUIDv4, unique per event | Idempotency + dedup key |
dvir_id |
UUID |
client-generated DVIR key | Links to source inspection |
vehicle_vin |
str |
17 chars, excludes I/O/Q | Vehicle identity |
driver_id |
str |
ELD-linked identity | FMCSA_Part_395 |
severity_score |
int |
0–100 |
Drives compliance action |
compliance_action |
str (Literal) |
OOS_HOLD, REPAIR_QUEUE, SCHEDULED_PM |
DOT_OOS_CRITERIA |
audit_hash |
str |
SHA-256 over canonical JSON | Tamper-evidence |
version |
int |
monotonic schema version | Replay + migration key |
emitted_at |
datetime (tz-aware) |
ISO-8601, UTC | § 396.3 audit anchor |
The severity_score and compliance_action fields preserve the same 0–100 severity model used everywhere on this site: 0–34 minor, 35–69 major, 70–100 critical. A score of 70 or above, or any defect meeting the DOT Out-of-Service Criteria, maps to OOS_HOLD and carries an immovable critical floor no downstream mapping may relax. Major scores map to REPAIR_QUEUE (the regulated 24-hour repair window), and minor scores to SCHEDULED_PM. The event never recomputes severity — it transports the decision the classification core already made, so the meaning of a score never drifts across a system boundary.
from __future__ import annotations
import hashlib
import json
from datetime import datetime, timezone
from typing import Literal
from uuid import UUID, uuid4
from pydantic import BaseModel, Field, field_validator
ComplianceAction = Literal["OOS_HOLD", "REPAIR_QUEUE", "SCHEDULED_PM"]
class DvirComplianceEvent(BaseModel):
model_config = {"frozen": True} # immutable: signed bytes == delivered bytes
event_id: UUID = Field(default_factory=uuid4, description="Idempotency + dedup key")
dvir_id: UUID
vehicle_vin: str = Field(..., min_length=17, max_length=17)
driver_id: str = Field(..., description="ELD-linked identity, 49 CFR Part 395")
severity_score: int = Field(..., ge=0, le=100)
compliance_action: ComplianceAction
audit_hash: str = Field(..., description="SHA-256 over canonical JSON")
version: int = 1
emitted_at: datetime
@field_validator("emitted_at")
@classmethod
def must_be_tz_aware(cls, v: datetime) -> datetime:
if v.tzinfo is None:
raise ValueError("emitted_at must be timezone-aware (UTC)")
return v
@field_validator("vehicle_vin")
@classmethod
def vin_alphanumeric(cls, v: str) -> str:
if not v.isalnum() or {"I", "O", "Q"} & set(v.upper()):
raise ValueError("VIN must be 17 alphanumeric chars excluding I, O, Q")
return v
def canonical_bytes(event: DvirComplianceEvent) -> bytes:
"""Deterministic serialization used for both audit_hash and HMAC signing."""
payload = event.model_dump(mode="json", exclude={"audit_hash"})
return json.dumps(payload, sort_keys=True, separators=(",", ":")).encode()
def seal(event_fields: dict) -> DvirComplianceEvent:
"""Compute the audit_hash over the canonical payload, then freeze the event."""
provisional = {**event_fields, "audit_hash": ""}
digest = hashlib.sha256(
canonical_bytes(DvirComplianceEvent(**provisional))
).hexdigest()
return DvirComplianceEvent(**{**event_fields, "audit_hash": digest})
The audit_hash is computed over the canonical JSON of every field except the hash itself, giving a stable evidentiary fingerprint that binds severity_score, compliance_action, vehicle_vin, and driver_id together. Any downstream alteration of the delivered event is detectable by recomputing the hash. The canonical serialization is deliberately deterministic — sorted keys, no whitespace — so the sender and every receiver derive an identical byte string, which is what makes the HMAC signature verifiable on the other side.
Core Implementation Patterns: The Transactional Outbox
Anchor link to "Core Implementation Patterns: The Transactional Outbox"The outbox pattern is the single most important reliability decision in this architecture. When the classification core finalizes a DVIR, it must both persist the finalized record and guarantee an outbound event will be delivered. Doing these as two separate operations — commit the record, then call the telematics API — opens a failure window: if the process dies after commit but before the API call, the compliance decision exists but is never delivered. The outbox closes that window by writing the event into an outbox table in the same database transaction that finalizes the record. Either both commit or neither does.
import sqlalchemy as sa
def finalize_and_enqueue(session, record, event: DvirComplianceEvent) -> None:
"""Persist the finalized DVIR and its outbound event atomically.
The compliance decision and its delivery obligation commit together."""
with session.begin(): # one transaction
session.execute(
sa.update(dvir_table)
.where(dvir_table.c.dvir_id == str(record.dvir_id))
.values(state="FINALIZED")
)
session.execute(
sa.insert(outbox_table).values(
event_id=str(event.event_id),
dvir_id=str(event.dvir_id),
payload=canonical_bytes(event),
audit_hash=event.audit_hash,
status="PENDING",
attempts=0,
emitted_at=event.emitted_at,
)
)
# No external I/O inside the transaction. Delivery happens out of band.
A background dispatcher then polls the outbox for PENDING rows, signs each event, and hands it to the adapters. Because the dispatcher is the only writer of delivery status, and because it keys retries and idempotency on event_id, a crash-and-restart never produces a lost or duplicated compliance effect — a half-delivered event is simply retried, and the receiver’s idempotency check absorbs the duplicate. The full dispatcher loop, its backoff policy, and its dead-letter routing are specified in the webhook event delivery layer; the concrete mapping of an event into Samsara and Geotab payloads is worked through in syncing DVIR severity scores to Samsara and Geotab via webhook.
Compliance Boundary Enforcement
Anchor link to "Compliance Boundary Enforcement"The outbound edge must emit only records that are legally final. A DvirComplianceEvent may be written to the outbox only for a DVIR in the FINALIZED state — meaning the driver signature under § 396.11(a) is present and, where a defect was reported, the mechanic certification under § 396.11©(2) has been recorded. Emitting for a record in AWAITING_REPAIR or OOS_HOLD would push an incomplete decision downstream, and a telematics platform that acted on it could clear a hold the carrier never certified. The gate is the same principle enforced throughout the compliance boundary enforcement framework: the data cannot cross the boundary until it is legally allowed to.
FINALIZED = "FINALIZED"
CERTIFIED = "CERTIFIED_REPAIR"
def assert_emittable(record) -> None:
"""Only finalized, certified records may produce an outbound event.
§ 396.11(c)(2): an OOS clearance requires a recorded repair certification."""
if record.state not in {FINALIZED, CERTIFIED}:
raise ComplianceRejection(
f"refuse to emit for non-final state {record.state!r}"
)
if record.has_reported_defect and record.mechanic_certification is None:
raise ComplianceRejection(
"reported defect present but no § 396.11(c)(2) certification"
)
Direction of enforcement also matters. An OOS_HOLD event asserts a hold; the event that later lifts it must reference the specific repair certification that authorized the clearance, and the ELD and CMMS records must agree the certification exists. The certifying repairs under 396.11©(2) guide details the certification event this clearance references, and the CMMS work order synchronization layer is where that certification is matched against the work order that closed the defect. Every emitted event carries the acting identity and the audit_hash, so an auditor can reconstruct not only what was delivered but which certified record authorized it.
Edge Resilience and Failure Modes
Anchor link to "Edge Resilience and Failure Modes"The outbound network is the least reliable part of the entire DVIR pipeline: it depends on third-party APIs, rate limits, and the public internet. Resilience is therefore built into the delivery contract rather than bolted on. Four mechanisms carry the load. First, at-least-once delivery with bounded retry — the dispatcher retries a failed POST with exponential backoff and jitter, so a transient 503 or a rate-limit response does not drop the event. Second, idempotency keys — every request carries the event_id as an Idempotency-Key header, so a retry that the receiver already processed is acknowledged without applying the effect twice. Third, the transactional outbox — the source of truth for “what must be delivered” survives a dispatcher crash, so nothing is lost in memory. Fourth, the dead-letter queue — an event that exhausts its retry budget is not discarded; it is routed to a dead-letter path that raises an operator alert, because a permanently undeliverable OOS hold is a safety event, not a log line.
from dataclasses import dataclass
@dataclass
class Delivery:
event_id: str
attempts: int
max_attempts: int = 8
def next_state(delivery: Delivery, http_status: int | None) -> str:
"""Classify a delivery outcome. 2xx acks; retryable errors back off;
a budget-exhausted event dead-letters rather than vanishing."""
match http_status:
case s if s is not None and 200 <= s < 300:
return "DELIVERED"
case 400 | 401 | 403 | 422:
return "DEAD_LETTER" # non-retryable: bad request or auth
case _ if delivery.attempts + 1 >= delivery.max_attempts:
return "DEAD_LETTER" # retries exhausted — alert an operator
case _:
return "RETRY" # 5xx, 429, timeout, connection error
Two failure modes deserve explicit handling. A permanent client error — a 400 or a 401 — is not retried, because retrying a malformed or unauthenticated request only burns budget; it dead-letters immediately for a human to fix the credential or the mapping. A poison event that repeatedly fails on the receiver must never block the events behind it, so delivery is per-event and independent, not a strict ordered queue. This shares its dead-letter machinery with the ingestion side’s exception handling and dead-letter routing; the difference is that here the dead-lettered item is an outbound compliance action, so the alert it raises is graded by compliance_action — a dead-lettered OOS_HOLD pages on-call immediately, while a SCHEDULED_PM waits for the next business-hours sweep.
Retention and Audit Readiness
Anchor link to "Retention and Audit Readiness"Every delivery attempt is a compliance event in its own right and must be recorded immutably. The delivery audit log captures, for each attempt, the event_id, the target adapter, the HTTP status or error, the attempt number, the timestamp, and the audit_hash of the payload that was sent. Written append-only to WORM storage — S3 Object Lock in compliance mode or Azure Immutable Blob — this log proves that a certified repair under § 396.11©(2) was in fact propagated to the maintenance system of record, and it proves when. Under § 396.3©, the maintenance record must be retained; the delivery log is the evidence that the record was created from the DVIR decision rather than entered by hand.
import hashlib
def delivery_audit_entry(prev_hash: str, attempt: dict) -> str:
"""Chain each delivery attempt to its predecessor so a deleted or
reordered attempt is detectable. Mirrors the pipeline's WORM audit chain."""
body = prev_hash + repr(sorted(attempt.items()))
return hashlib.sha256(body.encode()).hexdigest()
The delivery log is chained the same way the ingestion audit ledger is: each attempt hashes the prior hash together with its own payload, so a gap or reordering in the delivery history is provable. This is the same tamper-evident construction described in audit logging and tamper-evident event chains, applied to the outbound edge. During a DOT audit, the practical query is: given a VIN and a date range, return every compliance event emitted, the certified record that authorized it, and the unbroken chain of delivery attempts proving each destination received it. When that query returns a clean chain, the carrier can demonstrate not just that a defect was fixed, but that every system legally required to know was told — which is the whole purpose of building the outbound edge as durable, signed, and audited rather than as a best-effort API call.
Frequently Asked Questions
Anchor link to "Frequently Asked Questions"Why use a transactional outbox instead of calling the telematics API directly?
A direct API call couples the compliance decision to the availability of a third-party platform and opens a failure window: if the process dies after the DVIR is finalized but before the call succeeds, the decision exists but is never delivered. Writing the event to an outbox table in the same transaction that finalizes the record makes the event exist if and only if the record was finalized. A separate dispatcher then delivers it with retries, so a downstream outage never blocks finalization and never drops a safety-critical hold.
How does at-least-once delivery avoid applying an OOS hold twice?
Delivery is at-least-once, so the same event may arrive more than once, but each request carries the event_id as an idempotency key. The receiver records processed event_ids and treats a repeat as a no-op that returns the original acknowledgment. The compliance effect — an OOS hold, a work order, an ELD annotation — is therefore applied exactly once even though the event may be delivered several times. The forbidden outcome is zero deliveries, not duplicate deliveries.
What happens when an OOS hold event can never be delivered?
After the dispatcher exhausts its bounded retry budget, the event is routed to a dead-letter queue rather than discarded. Because the dead-lettered item is graded by compliance_action, a failed OOS_HOLD raises an immediate operator alert — a permanently undeliverable out-of-service hold is treated as a safety incident requiring human intervention, not a silent log entry. The event and every failed attempt remain in the immutable delivery audit log.
Which regulations require the DVIR decision to reach the maintenance and ELD systems?
Section 396.11©(2) requires that a repair certification be reflected before a vehicle returns to service, which means the maintenance system of record must receive it. Section 396.3(a) and © require systematic maintenance and the retention of maintenance records, which in a modern fleet live in the CMMS. And 49 CFR Part 395 governs driver identity and Hours-of-Service in the ELD, so every DVIR event must be linkable to the Part 395 driver identity that signed it.
Related
Anchor link to "Related"- Webhook Event Delivery for DVIR Pipelines — the durable, signed transport every event in this section rides on.
- CMMS Work Order Synchronization — opening and closing the § 396.3 maintenance record from a classified defect.
- ELD Identity and HOS Record Linkage — binding every event to a 49 CFR Part 395 driver identity.
- Samsara, Geotab and Motive Platform Adapters — translating the canonical event into each vendor’s payload.
- Defect Classification & Repair Order Routing — the core that produces the finalized decision this edge delivers.
This guide is the top-level reference for outbound platform integration on this site. Back to Fleet Compliance home.