Building a Tire Inspection Data Contract for Calgary Fleets
Why an inspection contract matters more than another form
A tire inspection record looks simple until several people, devices, depots, and seasons must agree on what it means. One technician writes “6,” another system stores 6.0, a mobile form assumes millimetres, and an export labels the same field as thirty-seconds of an inch. Each entry appears plausible. Together they create data that cannot safely support trend analysis, exception handling, or a defensible service decision.
A data contract solves that problem by defining the shape, meaning, allowed values, and evidence attached to every record before the information reaches a dashboard. This is narrower than building a sensor pipeline and more rigorous than designing a pleasant inspection screen. The contract sits at the boundary between observation and software. It states what producers must send, what consumers may assume, and how failures are represented without silently changing their meaning.
Calgary fleet work makes those guarantees valuable. A chinook can move ambient temperature sharply within hours. Vehicles may begin near a warm depot, run Deerfoot Trail at speed, stop in exposed industrial areas, and finish after sunset in much colder air. Highway 1 west introduces grades and changing weather. Stoney Trail creates long, sustained operating periods. Gravel, road salt, packed snow, and freeze-thaw cycles influence what an inspector can see and how trustworthy a reading is. A bare numeric value cannot preserve that context.
The goal is not to automate judgement or label a tire safe from one field. The goal is to make inspection evidence interpretable. If a condition needs professional tire attention, KMJ Tire provides tire services and oil changes. A suspected mechanical issue belongs with an appropriate mechanical provider. Keeping that boundary explicit is part of honest data design, because a schema should never imply that one organization performed work outside its actual scope.
For useful driver-side background before defining fields, the Be Tire Smart guide provides a practical vocabulary. A data team can then translate observable facts into stable keys rather than inventing ambiguous labels.
Start with the decisions the record must support
Schema design should begin with questions, not columns. Write down the decisions that a future reader must make and the uncertainty that must remain visible. A fleet may need to determine whether an inspection happened, identify the exact wheel position, compare readings taken with compatible methods, route damage for review, and prove who changed a record. None of those needs requires predicting remaining tire life or turning the inspection payload into a maintenance state machine.
Separate three categories of information:
- Observation: what was seen or measured, such as tread depth at three grooves.
- Context: circumstances that affect interpretation, such as temperature, precipitation, surface contamination, and elapsed time since operation.
- Administration: who captured the event, which procedure version applied, and which software accepted it.
This separation prevents a common mistake: embedding conclusions inside measurements. tread_status: good cannot be audited unless “good” has a definition, a unit, a threshold version, and a reliable input. Store the measurement and any assessment as different properties. Give the assessment its own rule identifier. A consumer may then recalculate or challenge the conclusion without rewriting history.
Write non-goals beside the supported decisions. An inspection contract is not a promise that every visible defect has been found. It does not infer vehicle steering, suspension, brake, or alignment condition. It does not authorize a repair. It does not replace the tire maker’s instructions or a qualified physical review. Those limits reduce accidental coupling and stop a downstream report from making a stronger claim than the source evidence supports.
Name identities before recording measurements
Every event needs stable identity at several levels. The fleet vehicle should use an internal opaque identifier rather than a licence plate as the primary key. Plates can change and are unnecessary in many analytical systems. A tire assembly may have its own fleet asset tag. The wheel position needs a controlled representation. The inspection itself requires a unique event identifier that survives retries.
Avoid a single free-text value such as left rear inner. Model position through explicit fields:
{
"vehicle_id": "veh_7G2M4",
"inspection_id": "insp_01J9K7R3V8F4T2",
"axle_index": 2,
"side": "left",
"wheel_slot": "inner",
"assembly_id": "asm_88421"
}
axle_index should have a documented reference direction, normally front to rear, starting at one. side needs a perspective, usually the driver’s seated orientation. wheel_slot can be single, inner, or outer; it should not accept inside, dual-one, and other near-synonyms. For a trailer, include the attached unit identity rather than pretending its axle belongs to the tractor.
Position identity deserves independent validation. A passenger vehicle configuration should reject an inner dual slot. A known two-axle asset should not accept axle five. If configuration data is temporarily unavailable, ingestion can mark identity validation as pending rather than fabricate compatibility. That distinction preserves the event while preventing it from entering position-sensitive analysis.
Sidewall fields also need careful names. The sidewall information reference explains markings that humans often compress into one string. Capture a source photo reference and parsed values separately, so parsing corrections do not erase what the inspector actually observed.
Use explicit units and decimal semantics
Never make a consumer infer units from field names, fleet location, or historical habit. A robust contract either chooses one canonical unit or stores value and unit together. Canonical units simplify queries, but the raw observed representation should remain available when conversion occurs.
For tread depth, millimetres are a clear canonical choice:
{
"tread_depth": {
"value": 6.4,
"unit": "mm",
"resolution": 0.1,
"raw_value": "8/32",
"raw_unit": "in_32nds",
"conversion_rule": "depth-32nds-to-mm-v1"
}
}
The decimal 6.4 is not infinitely precise. resolution: 0.1 describes the reporting increment, while the raw fields retain what the tool displayed. Conversion policy must define rounding. Eight thirty-seconds equals 6.35 millimetres mathematically; reporting 6.4 at one-decimal resolution is a transformation, not a new observation.
JSON numbers do not preserve decimal scale reliably across all languages. If exact decimal representation matters, define the value as a string matching a numeric pattern, or use an integer in a smaller unit. For example, value_tenths_mm: 64 avoids binary floating-point differences. The trade-off is readability. Choose one representation and test every supported client.
Inflation pressure needs the same discipline. Record kPa, the instrument resolution, and whether the value was observed warm, cold, or with thermal state unknown. Never interpret a pressure reading without the vehicle specification and operating context. Load-related fields must also avoid vague labels; the load index explainer is a useful domain reference, while the contract should preserve the exact marking or configured limit used.
Distinguish null, absent, unknown, and not applicable
One of the most damaging schema shortcuts is treating every missing value as null. Missingness has several meanings. A producer might not support a field. An inspector might be unable to obtain a reading. The item might not apply to the wheel configuration. A value might have been intentionally withheld. These cases should not collapse into one bucket.
Use a measurement envelope with a status enum:
{
"pressure": {
"status": "unavailable",
"reason": "valve_access_obstructed",
"value": null,
"unit": "kPa"
}
}
Recommended statuses include observed, not_observed, unavailable, and not_applicable. Require a value only when status is observed. Require a controlled reason when status is unavailable. For not_applicable, reject both value and tool metadata. An absent property should mean the producer’s declared contract version does not send it or the entire measurement was outside that inspection procedure.
This extra structure pays off in analytics. A chart can separate true measurement coverage from legitimate exclusions. Operations can find recurring access problems. A migration can distinguish old producers from current inspections where a technician tried but could not collect evidence.
Do not use zero as missing. Zero millimetres is a numeric observation with grave implications, while null plus a reason is an inability to measure. Do not use an empty string for unknown enums. Do not silently default weather to clear, wheel slot to single, or measurement status to observed. Defaults create attractive but false completeness.
Preserve measurement provenance as first-class evidence
Provenance answers how a value came into existence. At minimum, each physical measurement should identify the method, tool class, tool identifier or anonymized asset reference, calibration state, operator, capture time, and whether a human transcribed it.
{
"provenance": {
"method": "manual_depth_gauge",
"tool_id": "tool_31C8",
"calibration_checked_at": "2026-07-18T15:30:00Z",
"operator_id": "op_Q42",
"entry_mode": "direct_manual_entry",
"procedure_version": "fleet-tire-inspection-3.2"
}
}
A tool identifier does not need to expose a serial number outside the operational system. It only needs to join to an authorized calibration registry. calibration_checked_at is not the same as a calibration certificate or an assertion that the device remained accurate. Record the status available at capture and retain the evidence reference.
Entry mode reveals different risks. Direct typed entry can suffer transposition. Optical parsing can misread a display. Import from a vendor file can change units. A corrected record may be derived from a prior event. Encoding those pathways permits targeted validation without declaring one method perfect.
Image evidence should be referenced by an object identifier and integrity hash, not embedded as a huge base64 string. The operational store can enforce retention and access rules. The event may include evidence_sha256, MIME type, capture timestamp, and a URI that is meaningful only inside authorized infrastructure. A hash helps detect accidental alteration; it does not prove that the image depicts the claimed wheel.
Represent groove-level depth without hiding variation
A single tread number often hides the shape of the reading. Where the procedure calls for multiple grooves, store them as distinct observations with an explicit lateral reference. Do not average at ingestion and discard the components.
{
"tread_observations": [
{"groove": "outer", "depth_tenths_mm": 61, "status": "observed"},
{"groove": "centre", "depth_tenths_mm": 65, "status": "observed"},
{"groove": "inner", "depth_tenths_mm": 59, "status": "observed"}
],
"orientation_reference": "vehicle_outboard_to_inboard"
}
The orientation reference prevents a detached tire or rotated photo from reversing inner and outer. For dual assemblies, “inner” can describe both a groove and a wheel slot, so distinct property names are essential. wheel_slot: inner and groove: inner are understandable when separated; a flat string is not.
Derived minima or spreads belong in a computed view with rule versioning. If a consumer calculates minimum_depth_tenths_mm: 59, label it derived and point to the source fields. Reprocessing can then correct an algorithm without changing original observations.
Inspection teams also need a consistent way to represent damage observations. Controlled categories might cover puncture evidence, cuts, exposed material, bulges, sidewall abrasion, embedded objects, or unknown visual anomalies. These are observations, not automated repair decisions. For tire damage guidance and professional review boundaries, reference the Calgary tire repair page. A qualified assessment must decide whether service is appropriate.
Capture Calgary time, weather, and thermal context
Every timestamp should include an offset or use UTC, while a separate IANA zone communicates the local civil-time interpretation. Calgary uses America/Edmonton. Avoid bare strings such as 2026-08-02 09:10; they are ambiguous during integrations and daylight-saving transitions.
{
"captured_at": "2026-08-02T15:10:22Z",
"local_time_zone": "America/Edmonton",
"ambient_temperature_c": 12.5,
"weather_source": "manual_observation",
"surface_condition": "dry",
"thermal_state": "unknown",
"minutes_since_vehicle_stopped": 18
}
Temperature should include its source. A depot wall sensor, public weather station, vehicle display, and manual estimate have different spatial and measurement qualities. Do not assign false precision to an approximate value. If a public station observation is joined later, preserve its station, observation time, and join distance.
Chinooks and large day-night swings make thermal state important. minutes_since_vehicle_stopped is useful evidence, but it does not prove that a tire is cold. Sun exposure, route speed, load, indoor storage, and braking heat may matter. Use thermal_state: unknown when the procedure cannot establish it.
Route context should be categorical and privacy-conscious. A fleet may need operating_context: highway, urban_arterial, yard, or mixed rather than a continuous GPS trail. Deerfoot and Stoney operations can be represented through a route class if precise location adds no operational value. Highway 1 west may justify a mountain-corridor category. Gravel exposure and road-salt contamination can be booleans or controlled levels when they affect visual confidence.
Draft an enforceable JSON Schema core
JSON Schema can enforce syntax, required fields, enums, numeric bounds, and conditional relationships. The following abbreviated Draft 2020-12 schema demonstrates a strict event envelope:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://schemas.example.invalid/tire-inspection/1-0-0",
"title": "Fleet tire inspection event",
"type": "object",
"additionalProperties": false,
"required": [
"schema_version", "inspection_id", "vehicle_id",
"captured_at", "position", "measurements", "provenance"
],
"properties": {
"schema_version": {"const": "1.0.0"},
"inspection_id": {"type": "string", "pattern": "^insp_[A-Za-z0-9]{10,32}$"},
"vehicle_id": {"type": "string", "pattern": "^veh_[A-Za-z0-9]{3,40}$"},
"captured_at": {"type": "string", "format": "date-time"},
"local_time_zone": {"const": "America/Edmonton"},
"position": {"$ref": "#/$defs/position"},
"measurements": {"$ref": "#/$defs/measurements"},
"provenance": {"$ref": "#/$defs/provenance"}
},
"$defs": {
"position": {
"type": "object",
"additionalProperties": false,
"required": ["axle_index", "side", "wheel_slot"],
"properties": {
"axle_index": {"type": "integer", "minimum": 1, "maximum": 12},
"side": {"enum": ["left", "right"]},
"wheel_slot": {"enum": ["single", "inner", "outer"]}
}
},
"measurements": {
"type": "object",
"additionalProperties": false,
"required": ["tread_observations"],
"properties": {
"tread_observations": {
"type": "array",
"minItems": 1,
"maxItems": 5,
"items": {"$ref": "#/$defs/tread"}
}
}
},
"tread": {
"type": "object",
"additionalProperties": false,
"required": ["groove", "status"],
"properties": {
"groove": {"enum": ["outer", "centre", "inner", "other"]},
"status": {"enum": ["observed", "not_observed", "unavailable"]},
"depth_tenths_mm": {"type": "integer", "minimum": 0, "maximum": 300},
"reason": {"type": "string", "maxLength": 80}
},
"allOf": [{
"if": {"properties": {"status": {"const": "observed"}}},
"then": {"required": ["depth_tenths_mm"], "not": {"required": ["reason"]}},
"else": {"not": {"required": ["depth_tenths_mm"]}, "required": ["reason"]}
}]
},
"provenance": {
"type": "object",
"additionalProperties": false,
"required": ["method", "operator_id", "procedure_version"],
"properties": {
"method": {"enum": ["manual_depth_gauge", "visual_only", "file_import"]},
"operator_id": {"type": "string", "maxLength": 64},
"procedure_version": {"type": "string", "maxLength": 32}
}
}
}
}
Use a validator configured to enforce formats; some libraries treat format as annotation by default. Pin the draft and test the exact implementation used in production. A schema passing in one language does not guarantee identical behaviour in another when regex or date-time handling differs.
Add semantic validation beyond the schema
JSON Schema cannot know the fleet’s vehicle configuration, whether a tool calibration was current, or whether an event timestamp is plausible relative to receipt. Build validation in layers and record the result of each layer.
Layer one checks parsing and structural schema. Layer two applies domain relationships: groove labels must be unique within one wheel observation, a single-wheel configuration cannot use an inner slot, and a pressure value requires an accepted unit. Layer three checks referenced entities such as active vehicle identity, expected axle count, procedure version, and tool registry. Layer four applies operational plausibility without rewriting data.
A plausible numeric range is not a service threshold. Bounds such as zero through thirty millimetres protect against unit mistakes and corrupted input. They should be deliberately broad enough to allow unusual but physically representable observations. Narrower business rules belong in versioned policies and may generate review warnings rather than reject evidence.
Cross-field checks should return machine-readable errors:
{
"code": "POSITION_INCOMPATIBLE_WITH_CONFIGURATION",
"path": "/position/wheel_slot",
"severity": "error",
"rule_version": "fleet-position-rules-2.1",
"message": "inner slot is invalid for configured single-wheel axle",
"retryable": false
}
Do not rely on the human message as an integration contract. Codes and paths remain stable; wording can improve. Preserve all detected errors when practical so a producer fixes a batch once instead of discovering one problem per retry.
Make idempotency and deduplication explicit
Mobile clients retry. Networks fail in industrial yards. A request can succeed while its response disappears. Without idempotency, the server may store several copies of one inspection and distort coverage metrics.
The producer should generate inspection_id before transmission. The server stores that key with a canonical payload hash. Repeating the same identifier with identical canonical content returns the original acceptance result. Reusing it with different content produces a conflict, not an overwrite.
Canonicalization needs a specification. Sort object keys, normalize Unicode, preserve array order where order is meaningful, and define numeric serialization. Hash only stable event content; exclude transport headers and server receipt time. A common pattern is RFC 8785 JSON Canonicalization Scheme, provided every producer can implement it consistently.
Deduplication heuristics are a secondary defence. Two different identifiers for the same vehicle, position, capture time, and measurement signature may indicate a duplicate, but the system should flag rather than automatically delete. Legitimate repeated readings can occur during verification. Store a possible_duplicate_of relationship and evidence score for review.
Batch imports need an idempotency key at both file and row level. File hash prevents accidental reprocessing, while row identifiers preserve independent outcomes. A partially accepted file can safely resume without creating duplicates or losing valid inspections.
Design an error taxonomy operators can act on
An error taxonomy should answer three questions: who can fix the problem, whether retrying can help, and whether the original evidence should be retained. A simple HTTP status is insufficient.
Use categories such as:
-
SYNTAX: malformed JSON, invalid encoding, or truncated payload. -
CONTRACT: missing required property, wrong type, unknown enum, or extra field. -
IDENTITY: vehicle, assembly, position, or operator reference cannot be resolved. -
PROVENANCE: tool evidence or procedure metadata is incomplete. -
PLAUSIBILITY: value is structurally valid but conflicts with broad physical bounds. -
TEMPORAL: capture time is impossible, too far in the future, or ordered incorrectly. -
POLICY: accepted evidence triggers review under a named fleet rule. -
DEPENDENCY: registry or storage service is unavailable and retry may succeed.
Separate rejected, quarantined, accepted-with-warning, and accepted outcomes. Rejection means the contract cannot interpret the event. Quarantine preserves a readable event that lacks trustworthy references. A warning indicates usable evidence with a non-fatal concern. Policy review is not the same as schema invalidity.
Never make an error say that a mechanical condition has been diagnosed from tire inspection data. If wear prompts concern about another vehicle system, the output should recommend evaluation by an appropriate provider. KMJ’s scope remains tire services and oil changes.
Preserve immutable events and auditable corrections
Do not update an accepted inspection row in place when correcting a transcription error. Append a correction event that identifies the superseded record, changed fields, reason code, actor, timestamp, and authorization source. Consumers can build a current view while auditors retain the sequence.
{
"event_type": "inspection_correction",
"correction_id": "corr_01J9M2Q8V7",
"supersedes_inspection_id": "insp_01J9K7R3V8F4T2",
"changed_paths": ["/measurements/tread_observations/1/depth_tenths_mm"],
"reason": "transposed_manual_entry",
"authorized_by": "op_R91",
"recorded_at": "2026-08-02T17:42:10Z"
}
The corrected payload should be complete or use a formally defined patch standard. Ad hoc partial objects are difficult to replay. If JSON Patch is chosen, restrict permitted operations and validate the resulting document against the original contract version.
Audit storage needs access controls and retention policy. Record who viewed or exported sensitive evidence when risk warrants it. Hash chaining can reveal sequence tampering, but it does not replace backups, permissions, or independent storage controls. The practical objective is traceability: a reviewer should reconstruct what arrived, what rules ran, what changed, and what consumers received.
Version contracts without breaking field crews
Use semantic versions as communication, not decoration. A patch version clarifies validation without changing accepted data meaning. A minor version adds backward-compatible optional capability. A major version changes required fields, removes values, or alters semantics.
Keep producers and consumers decoupled through a compatibility matrix. Ingestion can accept versions 1.0 and 1.1 while emitting a normalized internal representation. Record both schema_version and normalizer_version. Never pretend old data originally contained a new field; mark derived or unavailable values honestly.
A migration plan should include:
- Publish the schema and examples in a versioned registry.
- Add consumer support before producers start sending new fields.
- Shadow-validate upcoming rules and measure failures without rejecting events.
- Update one producer cohort, then compare acceptance and missingness.
- Announce a deprecation window tied to observed usage.
- Retire old acceptance only after lagging devices are accounted for.
Avoid enum reuse when meaning changes. If visual_only once meant no measuring tool and later means an image-assisted workflow, add a new value. Historical analysis depends on stable semantics more than compact vocabularies.
Seasonal deployment timing matters in Calgary. Avoid forcing a major client update during the busiest changeover period if field devices cannot update reliably. The seasonal tire change guide offers operational context; engineering teams should plan schema rollout with actual service rhythms rather than a calendar abstraction.
Build observability around data quality, not vanity volume
Counting ingested records cannot tell whether evidence is usable. Monitor contract health with rates and distributions segmented by producer version, depot, procedure, and device class.
Useful measures include schema rejection rate, quarantine rate, missingness by field, unknown-enum attempts, duplicate conflicts, future timestamps, calibration-reference failures, position mismatches, and correction frequency. Track latency from capture to receipt separately from server processing time. A rise in one client version often reveals a form or serialization defect.
Cardinality must be controlled. Do not use vehicle identifiers, inspection identifiers, or raw error messages as metric labels. Put high-cardinality details in structured logs with governed access. Metrics should use bounded dimensions such as contract version and error code.
Set service objectives around interpretability. For example, the team might define an internal target for structurally valid events with resolvable position identity, then review the target against real operations. This is an engineering reliability objective, not a public business claim.
Dashboards need denominators. “Two hundred missing readings” is meaningless without attempted inspections and legitimate not-applicable counts. Show transitions after releases and Calgary weather changes. A sudden increase in surface-contamination reasons during road-salt conditions may reflect honest observation rather than degraded staff performance.
Create adversarial fixtures and contract tests
Happy-path samples are not enough. Build fixtures that represent messy field reality and run them in every producer and consumer implementation.
Include cases for:
- exactly valid single-wheel and dual-wheel positions;
- unknown vehicle identity with otherwise readable evidence;
- duplicated groove labels;
- zero depth as an observed value rather than missing data;
- comma decimal input rejected or normalized before JSON creation;
- thirty-seconds input converted with a declared rule;
- leap-day and daylight-saving timestamps;
- future device clocks and late offline synchronization;
- stale calibration references;
- gravel or salt contamination lowering visual confidence;
- duplicate identifiers with equal and conflicting payload hashes;
- extra properties sent by a newer producer;
- corrected records that fail after patch application;
- very long strings, unexpected Unicode, and hostile file references.
Property-based testing can generate combinations across axles, sides, slots, status values, and conditional requirements. Mutation testing confirms that tests fail when a required constraint is removed. Keep golden canonicalization vectors so every language produces the same hash.
Test fixtures should not contain real driver names, exact routes, or identifiable photographs. Synthetic identifiers are enough. When training examples need practical service vocabulary, the fleet management overview and commercial tire services information provide public context without exposing operational records.
Apply privacy and minimum-data discipline
Inspection quality does not require collecting everything available. The schema should justify each personal or location field against a decision. Use operator pseudonyms outside the workforce identity system. Avoid driver identity unless a specific authorized workflow genuinely depends on it. Do not collect passenger information.
Precise GPS is often unnecessary. Depot identifier, route class, and weather source may support quality analysis without reconstructing movement. If evidence images can include faces, licence plates, screens, or property, define capture guidance, redaction, access, and deletion periods.
Separate analytical exports from operational records. An analyst studying measurement completeness likely needs vehicle class, axle configuration, procedure version, and broad operating context, but not an assembly serial or evidence URI. Apply least privilege to both humans and services.
Document retention by data category. Numeric observations may remain useful longer than photos. Audit corrections may require a different retention period from transient ingestion logs. Deletion jobs should be testable and produce counts without leaking identifiers.
Privacy also improves reliability. A smaller payload reduces entry burden, synchronization cost, accidental mismatches, and the blast radius of improper access. Minimum data is an engineering control, not merely a legal footer.
Walk through one Calgary fleet inspection event
Consider a delivery vehicle inspected at an east Calgary depot after a mixed route that included Stoney Trail and a gravel access road. It stopped eighteen minutes before the reading. The air is cooler than at midday, road residue is visible, and the operator uses a manual depth gauge.
{
"schema_version": "1.0.0",
"inspection_id": "insp_01J9N4A7K2P6D8",
"vehicle_id": "veh_7G2M4",
"assembly_id": "asm_88421",
"captured_at": "2026-08-02T03:14:32Z",
"local_time_zone": "America/Edmonton",
"position": {"axle_index": 2, "side": "right", "wheel_slot": "single"},
"context": {
"ambient_temperature_c": 9.0,
"temperature_source": "depot_sensor_DS14",
"minutes_since_vehicle_stopped": 18,
"thermal_state": "unknown",
"operating_context": ["ring_road", "gravel_access"],
"surface_contamination": "light_road_residue"
},
"measurements": {
"tread_observations": [
{"groove": "outer", "status": "observed", "depth_tenths_mm": 58},
{"groove": "centre", "status": "observed", "depth_tenths_mm": 62},
{"groove": "inner", "status": "unavailable", "reason": "contamination_obscured_groove"}
]
},
"provenance": {
"method": "manual_depth_gauge",
"tool_id": "tool_31C8",
"operator_id": "op_Q42",
"entry_mode": "direct_manual_entry",
"procedure_version": "fleet-tire-inspection-3.2"
}
}
The record does not invent the inner-groove value. It preserves two readings and explains the third. Thermal state remains unknown despite the elapsed time. Route context is broad enough for analysis without a movement trace. A review process may ask for the obscured groove to be cleaned and measured, but the original event remains honest.
If the event later supports a wheel-balance discussion, use the wheel balancing resource for service context rather than deriving a diagnosis from this payload. The contract contains observations, not an explanation for every wear pattern or vibration.
Review a rejected event and its repair path
Now consider a producer sending depth: 7, omitting units, using wheel_position: "rear passenger", and providing 2026-08-02 8:10 PM as local text. The values are human-readable, yet the contract cannot interpret them safely. The server should reject the event with multiple issues in one response.
{
"status": "rejected",
"errors": [
{"code": "REQUIRED_PROPERTY_MISSING", "path": "/position", "retryable": false},
{"code": "UNKNOWN_PROPERTY", "path": "/wheel_position", "retryable": false},
{"code": "UNIT_REQUIRED", "path": "/measurements/depth", "retryable": false},
{"code": "INVALID_DATE_TIME", "path": "/captured_at", "retryable": false}
],
"contract_version": "1.0.0"
}
The producer maps passenger side to right only if its interface explicitly defines the perspective. It obtains axle and slot identity from the chosen vehicle configuration. It converts or labels the depth using the actual tool display. It serializes the instant with an offset. Resubmission uses the same inspection identifier after correcting the pre-acceptance payload, because no accepted record exists yet.
If the first payload had already been accepted under an older contract, the fix would require a correction event. The distinction between rejected transport and accepted evidence prevents mutable history.
Use contract reviews to connect software and field reality
A data contract should have named owners from engineering, fleet operations, and tire service knowledge. Engineering understands serialization and compatibility. Field staff know which readings are realistic in cold yards, tight dual positions, contaminated surfaces, and hurried route transitions. Service experts can identify dangerous ambiguity without turning schema validation into remote diagnosis.
Run reviews against actual workflows. Ask an inspector to explain each field while handling gloves, glare, and poor connectivity. Observe where the form tempts guesses. Confirm that unavailable reasons match reality. Check whether axle position is obvious on trailers. Verify that evidence capture does not encourage unsafe roadside behaviour.
Calgary’s service area information can help teams describe geographic operating context at an appropriate level. For tire service logistics, mobile tire service details provide a public reference. Neither page should become a substitute for verified fleet procedures or emergency planning.
Contract governance needs a change log, designated approver, compatibility tests, and retirement policy. A field label change can be semantically breaking even when the JSON key stays the same. Review words, defaults, help text, and enum descriptions alongside code.
Operate ingestion under partial connectivity and batch pressure
Field software must assume that connectivity will be intermittent. A Calgary yard can have reliable Wi-Fi near an office and weak service beside trailers, while a route inspection may happen far from either. The client therefore needs a durable local outbox rather than a fragile request tied to the screen lifecycle. Save the event and its producer-generated identifier locally, mark it pending, and retry with bounded exponential backoff. Do not create a new identifier for each attempt.
The outbox should distinguish capture completion from server acceptance. A green local state can mean “saved on this device,” while a separate state communicates “accepted by ingestion.” Blurring those outcomes encourages staff to assume evidence reached the fleet record when it remains queued. If a payload is rejected, preserve the response code and highlight only fields the operator can reasonably correct. Infrastructure failures should retry automatically; semantic conflicts need deliberate resolution.
Clock handling deserves special attention offline. Capture the device-reported instant, its offset, and a monotonic sequence where available. At receipt, add the server timestamp without replacing capture time. If clock drift exceeds policy, quarantine the event with temporal evidence rather than changing the instant to make it plausible. Later reconciliation may use nearby trusted events, but any derived correction needs an auditable rule and should never masquerade as the original reading.
Large imports require backpressure. Limit batch size by bytes and event count, stream validation where possible, and return row-level outcomes. A single malformed item should not obscure the status of every readable neighbour unless the file is defined as an atomic transaction. Record accepted identifiers so a retry submits only unresolved rows.
Rate limits should be explicit in transport documentation. Return a retry interval and a stable dependency error code. Clients need jitter so many depot devices do not reconnect simultaneously after an outage. Server-side queues should bound memory, isolate tenants or fleet groups, and move persistently failing items to a governed quarantine store rather than retrying forever.
Security applies at the same boundary. Authenticate the producer, authorize its fleet scope, cap payload and image-reference sizes, reject unexpected content types, and validate any referenced object identifier. Never fetch an arbitrary URL supplied in inspection JSON; that pattern can expose internal services. Evidence uploads should use constrained storage credentials, short expirations, content checks, and server-generated destinations.
Operational replay must be intentional. Revalidating archived events under a newer rule can be useful for analysis, but it must not rewrite the original acceptance outcome. Store a new evaluation record containing the rule bundle, execution time, result, and input event hash. This lets teams ask, “How would current policy classify last winter’s evidence?” without claiming that the current policy existed then.
Finally, rehearse failure recovery. Disconnect a test device after local save but before response. Repeat an accepted request. Corrupt one item in a batch. Disable the vehicle registry. Rotate a schema version while an old device remains offline. Restore a queue from backup and prove idempotency prevents duplicates. These exercises expose contract gaps more effectively than an architecture diagram because they test the boundary where field uncertainty meets deterministic software.
A production readiness checklist
Before accepting live inspection events, verify the following controls:
- Every measurement has an explicit unit or unit-bearing canonical key.
- Missingness states are distinct and conditionally validated.
- Vehicle, assembly, axle, side, and wheel-slot identities are unambiguous.
- Capture time includes an offset, with Calgary’s IANA zone stored where relevant.
- Provenance covers method, procedure, operator reference, and tool evidence.
- Raw observations remain separate from derived assessments.
- JSON Schema draft and format behaviour are pinned in each runtime.
- Cross-field and registry checks return stable error codes and JSON pointers.
- Idempotent retries compare a canonical payload hash.
- Possible duplicates are flagged without deleting plausible repeat readings.
- Accepted evidence is immutable; corrections append an auditable event.
- Version migration has shadow validation, compatibility tests, and producer cohorts.
- Metrics expose missingness, rejection, quarantine, conflict, and correction rates.
- Logs avoid high-cardinality metric labels and protect sensitive identifiers.
- Adversarial fixtures cover offline capture, seasonal context, and configuration edges.
- Location, identity, and imagery are minimized according to actual decisions.
- The schema never claims mechanical diagnosis or service outside the provider’s scope.
This checklist is deliberately more demanding than “valid JSON.” Valid syntax only proves that braces and types align. A dependable contract must preserve meaning across people, software releases, weather, retries, and later scrutiny.
Closing principle: retain uncertainty instead of manufacturing certainty
The strongest inspection record is not the one with the most populated fields. It is the one that communicates exactly what was observed, how it was measured, where its limitations lie, and which rules interpreted it. Unknown values are acceptable. Ambiguous values disguised as facts are not.
For Calgary fleets, weather and route context can shift quickly, so timestamps, thermal evidence, contamination, and measurement provenance deserve the same care as the numeric reading. Explicit wheel identity keeps observations attached to the correct assembly. Versioned validation makes failures actionable. Idempotency protects totals. Audit events allow correction without erasing history.
When a tire needs physical attention, use a qualified tire service. The local tire service overview explains KMJ Tire’s tire-focused role, and the all-weather tire guide offers additional Calgary-specific education. Questions involving other vehicle systems should go to an appropriate mechanical provider.
A contract built on these principles gives developers a stable interface and gives operators evidence they can challenge, improve, and trust. That is the practical standard: not automated certainty, but enforceable honesty from the first field entry to the final audit.
Top comments (0)