Skip to content
Classification & Routing

CSA Score Impact and BASIC Category Mapping

A Driver Vehicle Inspection Report (DVIR) defect that a carrier corrects on its own yard is an internal maintenance event; the same defect discovered at a roadside inspection is a federal violation that propagates into the carrier’s public safety profile and stays there for two years. The Federal Motor Carrier Safety Administration’s Compliance, Safety, Accountability (CSA) program scores every carrier through its Safety Measurement System (SMS), and a Vehicle Maintenance violation written under 49 CFR § 396.9 roadside authority carries a numeric severity weight, a time weight, and a peer-group percentile that together determine whether the carrier crosses an intervention threshold. Engineers building the Defect Classification & Repair Order Routing pipeline must understand this propagation precisely, because the severity tier a defect receives internally is a leading indicator of the CSA exposure it will create if the vehicle is dispatched with the defect unrepaired.

This guide connects the internal 0–100 severity score produced by the Severity Scoring Algorithms for DVIR Defects engine to the FMCSA construct it ultimately feeds: the seven BASICs, the Vehicle Maintenance BASIC in particular, and the weighted percentile math that turns an unrepaired brake defect into a measurable safety-rating liability. The concrete lookup table — severity tier to CFR code to BASIC to weight to out-of-service (OOS) flag — is implemented as runnable code in the companion page on Mapping Defect Severity Tiers to BASIC Violations. Treat every weight in this document as illustrative of the model’s structure; FMCSA publishes the authoritative severity-weight tables and revises them, so the numbers below teach the mechanics rather than substitute for the official source.

Propagation of a DVIR defect into a CSA Vehicle Maintenance BASIC percentile A left-to-right pipeline showing how an internal DVIR defect becomes a CSA score. A classified DVIR defect that is dispatched unrepaired is discovered at a roadside inspection under 49 CFR 396.9 and written as a violation. The violation is routed to one of seven BASIC buckets, most Vehicle Maintenance violations landing in the Vehicle Maintenance BASIC. Each violation is multiplied by an FMCSA severity weight from one to ten and a time weight of three for the most recent six months, two for six to twelve months, and one for twelve to twenty-four months. The weighted violations are summed and divided by relevant inspections, then ranked against a safety event group of carriers with a similar inspection count to produce a percentile from zero to one hundred. A percentile at or above the intervention threshold flags the carrier for FMCSA attention. DVIR defect dispatched unrepaired severity_score defect_category Roadside violation inspection report 49 CFR 396.9 CFR code cited BASIC bucket Vehicle Maintenance 1 of 7 categories peer-grouped later Severity × time weight 1–10 recent × 3 · 2 · 1 Σ ÷ inspections Percentile 0–100 vs peers safety event group CSA SAFETY MEASUREMENT SYSTEM · public two-year window ≥ threshold → FMCSA intervention score ≥ 70 or DOT_OOS_CRITERIA → OOS hold before dispatch

The diagram makes the core lesson visible: the only reliable defense against a Vehicle Maintenance percentile increase is to never dispatch the vehicle in the first place. A defect scored critical (≥ 70) or tagged DOT_OOS_CRITERIA must trigger an out-of-service hold before the wheels turn, exactly as specified in Out-of-Service Criteria and OOS Hold Triggers. Everything downstream of a roadside inspection is scored by FMCSA, not by the carrier.

Prerequisites and Environment Setup

Anchor link to "Prerequisites and Environment Setup"

The mapping layer is a deterministic reference service: given a classified defect, it returns the CSA exposure that defect represents if it escapes to a roadside inspection. It reads no live FMCSA data at request time — the SMS methodology and severity-weight tables are versioned configuration, refreshed on FMCSA’s publication cycle, not fetched per call. Target Python 3.10+ (the code uses match statements and X | Y unions) with:

  • Pydantic 2.x — immutable models for the violation catalog and the returned exposure record.
  • pandas 2.x + NumPy — aggregating historical roadside outcomes and computing weighted percentile inputs across an inspection history.
  • hashlib / datetime (stdlib) — SHA-256 audit_hash over the catalog version and timezone-aware time-weight arithmetic.
  • A versioned copy of the FMCSA SMS severity-weight table — pinned by version and effective_date, never hard-coded inline, so a percentile computed last quarter can be reproduced under the table that was in force then.

Every inbound defect must already conform to the canonical record contract from the Standardized DVIR JSON Schema Design, and its defect_category must resolve through the controlled vocabulary in Defect Code Standardization Across Fleets. A defect whose category cannot be resolved to a CFR citation is routed to conservative human review rather than assigned a default weight, because a silently mis-mapped violation understates real CSA exposure.

FMCSA groups every roadside violation and crash into one of seven Behavior Analysis and Safety Improvement Categories. Each BASIC is scored independently, so a carrier can sit clean in six and still be flagged for intervention in the seventh:

  • Unsafe Driving — speeding, reckless operation, seat-belt, and texting violations (Parts 392, 397).
  • Hours-of-Service (HOS) Compliance — driving beyond limits and false or missing records of duty status (Part 395).
  • Driver Fitness — invalid or improper license and medical-qualification violations (Parts 383, 391).
  • Controlled Substances / Alcohol — use or possession of impairing substances (Part 392).
  • Vehicle Maintenance — brakes, lights, tires, and other mechanical and inspection-and-repair violations (Part 393 and Part 396). This is the BASIC that DVIR pipelines feed.
  • Hazardous Materials (HM) Compliance — leaking containers, improper placarding and packaging (Parts 397, 172, 173, 180).
  • Crash Indicator — a history of state-reported crashes, not published to the public but used in FMCSA intervention decisions.

The Vehicle Maintenance BASIC is where a DVIR pipeline’s work lands, because the same physical conditions a DVIR is designed to catch under 49 CFR § 396.11 — brake adjustment, lamp function, tire condition — are precisely the conditions a roadside inspector writes up under Part 393. That symmetry is what makes an internal severity score a genuine predictor of CSA exposure: a defect your model tiers as critical is a defect an inspector will tier as high-severity, because both are reading the same regulation.

The mapping service consumes a classified defect and emits a CSA exposure record. Field names and the 0–100 severity scale are held identical to the scoring and routing pages so a single defect reconstructs across the whole pipeline:

Field Type Enumeration / range Compliance tag
defect_category str controlled vocabulary node FMCSA_396.11
severity_score int 0100 (band input) Internal tier source
cfr_code str e.g. 393.47, 393.9, 393.75 Roadside citation
basic str (enum) one of the seven BASICs CSA category
severity_weight int 110 (illustrative) FMCSA-defined, not carrier-set
is_oos bool true / false CVSA OOS eligibility
compliance_guardrail str (enum) OOS, conditional, monitor_only DOT_OOS_CRITERIA — immovable
version int monotonic SMS table version replay key
effective_date datetime (tz-aware) ISO-8601 Weight-table window anchor
audit_hash str SHA-256 hex Tamper-evidence over the record

The internal severity tier maps to representative Vehicle Maintenance violations as follows. The severity_weight column illustrates the shape of FMCSA’s model — brake and steering defects weigh heavily, a single inoperative marker lamp weighs lightly — but always resolve the operative value from the pinned SMS table, never from this page:

Internal tier Representative violation CFR code Illustrative severity weight OOS
Critical (70–100) Brakes — out of adjustment / defective § 393.47 10 Yes
Critical (70–100) Tires — flat, exposed fabric, tread separation § 393.75 8 Yes
Major (35–69) Inspection / repair / maintenance not performed § 396.3(a)(1) 4 Conditional
Major (35–69) No or false driver vehicle inspection report § 396.11 4 No
Minor (0–34) Inoperable required lamp (single marker) § 393.9 2 No

Note that a defect can straddle the tier and the OOS flag independently: a tire cut may score high on severity yet only reach OOS when it exposes fabric or belt material, so is_oos is a distinct fact from severity_weight, and both must be carried through. Model the exposure record so neither can be inferred from the other:

python
from datetime import datetime
from typing import Literal

from pydantic import BaseModel, Field


class BasicExposure(BaseModel):
    model_config = {"frozen": True}  # immutable; corrections mint a new version

    defect_category: str
    severity_score: int = Field(ge=0, le=100)
    cfr_code: str                       # e.g. "393.47"
    basic: Literal[
        "unsafe_driving", "hos_compliance", "driver_fitness",
        "controlled_substances", "vehicle_maintenance",
        "hazmat_compliance", "crash_indicator",
    ]
    severity_weight: int = Field(ge=1, le=10)   # FMCSA-defined, illustrative here
    is_oos: bool
    compliance_guardrail: Literal["OOS", "conditional", "monitor_only"]
    version: int
    effective_date: datetime
    audit_hash: str

Computing a carrier’s Vehicle Maintenance percentile from a set of roadside violations follows an ordered sequence. The mapping service supplies the per-violation weights; the percentile itself is a peer-relative rank, so an identical violation count produces a different percentile for a small carrier than for a large one.

  1. Resolve each violation to its BASIC and weights. Look up the cited cfr_code in the versioned SMS table to obtain the basic, the severity_weight (1–10), and the is_oos flag. An unresolved code routes to human review — never default it to a low weight, which would understate exposure.
  2. Apply the time weight. Multiply each violation’s severity weight by its time weight: 3 for violations in the most recent six months, 2 for six to twelve months, 1 for twelve to twenty-four months. Violations older than 24 months drop out of the SMS window entirely. Recent problems dominate by design, so a burst of fresh brake violations moves the score far more than the same burst two years stale.
  3. Aggregate the measure. Sum the time-weighted severity weights for the Vehicle Maintenance BASIC and divide by the carrier’s number of relevant inspections (inspections that could have produced a Vehicle Maintenance violation). This normalization is why a carrier is not punished simply for being inspected more often.
  4. Rank within the safety event group. Compare the normalized measure against a peer group of carriers with a similar number of relevant inspections, and express the result as a percentile from 0 to 100. Peer grouping is the reason two carriers with identical violations can hold very different percentiles.
  5. Compare to the intervention threshold. A percentile at or above the BASIC’s intervention threshold flags the carrier for FMCSA attention. Persist the computed measure with its SMS-table version so a past percentile can be reconstructed under the table that produced it.

The time-weight and aggregation steps are pure functions of their inputs — no wall-clock reads inside the arithmetic, only the explicit inspection timestamp — so the same violation history always yields the same measure:

python
from datetime import datetime, timezone


def time_weight(inspection_ts: datetime, as_of: datetime) -> int:
    """FMCSA SMS time weighting: recent violations dominate. Deterministic in inputs."""
    months = (as_of - inspection_ts).days / 30.44
    if months <= 6:
        return 3
    if months <= 12:
        return 2
    if months <= 24:
        return 1
    return 0  # outside the 24-month SMS window


def vehicle_maintenance_measure(
    violations: list[BasicExposure],
    inspection_dates: list[datetime],
    relevant_inspections: int,
    as_of: datetime | None = None,
) -> float:
    """Normalized Vehicle Maintenance BASIC measure = Σ(severity × time) ÷ inspections."""
    as_of = as_of or datetime.now(timezone.utc)
    if relevant_inspections <= 0:
        return 0.0
    total = 0
    for v, ts in zip(violations, inspection_dates):
        if v.basic != "vehicle_maintenance":
            continue
        total += v.severity_weight * time_weight(ts, as_of)
    return total / relevant_inspections

Compliance Thresholding and Routing

Anchor link to "Compliance Thresholding and Routing"

The measure the service returns is not a compliance action on its own; it is the exposure a defect creates. The routing obligations remain governed by the internal severity bands, and those obligations are what actually keep a violation off the report in the first place:

  • Score ≥ 70 (critical), or any DOT_OOS_CRITERIA defect: trigger an out-of-service hold. A brake defect under § 393.47 or a fabric-exposed tire under § 393.75 must never leave the yard, because a dispatched OOS defect is the single most expensive Vehicle Maintenance violation a carrier can incur — high severity weight, freshly time-weighted, and often paired with a driver OOS order.
  • Score 35–69 (major): route to the regulated 24-hour repair queue. A § 396.3(a)(1) inspection-and-repair lapse or a missing DVIR under § 396.11 is a mid-weight violation; correcting it before dispatch keeps it off the roadside report and out of the percentile.
  • Score 0–34 (minor): route to scheduled preventive maintenance. A single inoperative marker lamp under § 393.9 is a low-weight violation, but note that low weight is not zero weight — a fleet-wide pattern of minor lamp defects still accumulates a measurable Vehicle Maintenance measure.

Do not present the returned weights as exact CSA points. The SMS methodology converts weighted violations into a normalized measure and then a peer-relative percentile; there is no fixed “points per violation” a carrier can add up. The correct framing for a dispatcher is comparative: this defect, if it reaches a roadside inspection, contributes a high-, medium-, or low-severity violation to the Vehicle Maintenance BASIC, weighted more heavily the more recent it is. The Automating Critical DVIR Defect Alerts to Dispatchers path is where that comparative signal reaches the human who can hold the truck.

Production Integration and Platform Synchronization

Anchor link to "Production Integration and Platform Synchronization"

The exposure record is a read-model that other services consume, so publish it as immutable, versioned data rather than a mutable lookup:

  • Idempotent publication. Key each exposure event on (defect_id, version) so a retried publish is a no-op; a consumer that already applied a version ignores the duplicate.
  • Cryptographic chaining. Compute an audit_hash (SHA-256 over the canonical JSON of the record and its SMS-table version) and chain each catalog version to its predecessor, so a silently swapped severity weight is detectable during a DOT audit.
  • Version pinning on every score. Persist the SMS-table version and effective_date alongside every computed measure. When FMCSA revises the severity-weight table, historical percentiles must still reproduce under the table that was in force — never retroactively rescore old violations under a new table.
  • Sync to the safety dashboard. Emit the Vehicle Maintenance measure to the telematics and CMMS layer via the Webhook Event Delivery for DVIR Pipelines path so the same signal that holds a truck also updates the carrier’s internal safety view.

Because a single physical defect can be written as more than one CFR violation at the roadside, the exposure record models a one-to-many relationship from defect to violation. The companion implementation page handles that fan-out explicitly, and it is the reason a naive one-code-per-defect lookup understates exposure.

  • Version every weight table — pin the SMS severity-weight table by version and effective_date; never hard-code weights inline.
  • Never default an unresolved code — a defect whose CFR code cannot be resolved routes to conservative human review, not a low weight.
  • Carry is_oos independently of severity_weight — a defect’s OOS eligibility is a distinct fact from its severity weight; model both.
  • Respect the 24-month window — drop violations older than 24 months from the measure; apply the 3/2/1 time weights inside it.
  • Normalize by relevant inspections — divide the weighted sum by inspection count so inspection frequency alone never inflates a percentile.
  • Do not claim exact CSA points — report comparative severity, not additive point totals; the percentile is peer-relative.
  • Chain and hash every record — SHA-256 audit_hash chained to the prior catalog version keeps the mapping tamper-evident.
How does a DVIR defect actually turn into a CSA score?

Only if the vehicle is dispatched with the defect unrepaired and the defect is then discovered at a roadside inspection under 49 CFR § 396.9. The inspector writes the condition as a violation citing a specific CFR code, mostly under Parts 393 and 396, which FMCSA routes to the Vehicle Maintenance BASIC. The violation is multiplied by its severity weight and a time weight, summed with the carrier’s other violations, normalized by relevant inspections, and ranked against a peer group to produce a percentile. A defect corrected before dispatch never enters this pipeline.

Why does the Vehicle Maintenance BASIC matter most for a DVIR pipeline?

Because the conditions a DVIR is legally required to catch under § 396.11 — brakes, lamps, tires, coupling devices — are the same conditions a roadside inspector writes under Part 393, which map to the Vehicle Maintenance BASIC. The other six BASICs cover driver behavior, hours of service, licensing, substances, hazardous materials, and crash history, which a mechanical inspection pipeline does not feed. An internal severity tier is therefore a direct predictor of Vehicle Maintenance exposure.

Are the severity weights something a carrier can set?

No. Severity weights on a scale of 1 to 10 are defined by FMCSA and published in the SMS methodology, and they change only when FMCSA revises the tables. A carrier’s pipeline can map a defect to its likely weight for planning, but it cannot alter the weight FMCSA applies. Treat the weights shown here as illustrative of the model and always resolve the operative value from the pinned SMS table.

Can I compute an exact CSA point total for a single defect?

No, and presenting one is misleading. The SMS produces a normalized measure and then a peer-relative percentile, not a running point tally, so there is no fixed number of points a violation adds. Report a defect’s exposure comparatively — high, medium, or low severity within the Vehicle Maintenance BASIC, weighted more heavily the more recent it is — and let the percentile math live where FMCSA computes it.

Back to Defect Classification & Repair Order Routing.