feat(api): backfill vehicles.vin from the DIMO VIN VC (pull-once)#86
Merged
Conversation
vehicles.vin was only ever filled from uploaded registration documents, so
it stayed NULL for most of the fleet. Almost every vehicle carries a DIMO
VIN verifiable credential, readable via telemetry-api's vinVCLatest { vin }
with privilege 5 — which our vehicle-JWT exchange already requests.
- TelemetryAPIService.VINFromVC: one vinVCLatest query per vehicle through
the existing per-vehicle-JWT GQL path; null VC / blank vin = found=false.
- LicensePlateSyncService: VC fallback after the registration-document pass
whenever the VIN is still unknown, and a lean SyncVINOnly that skips the
fetch-api pull entirely. Fill-if-missing — never overwrites; VIN is
immutable, so the vin IS NULL gate makes every path pull-once (bounds DCX
cost to a one-time backfill plus one read per new vehicle).
- import-group-attestations -vin-only: one-shot backfill restricted to
vehicles with no VIN, dry-run-able; the normal cron pass now converges
new vehicles via the fallback.
No migration, no config, no frontend changes (/vehicles already returns
vin). Plan: docs/VIN_SYNC_PLAN.md. Live-verified on mainnet: dry-run
resolves the VC VIN, live run caches it, re-run checks 0 vehicles.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UxoaxTXSLqUwkYfewdwGBM
JamesReate
added a commit
that referenced
this pull request
Jul 10, 2026
Ships #85 (IndexedDB paint cache, shared freshness loader in list view, remove global Live Tracking) and #86 (vehicles.vin backfill from the DIMO VIN VC). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UxoaxTXSLqUwkYfewdwGBM
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
vehicles.vinis only populated from uploaded registration documents (LicensePlateSyncServicescrapingdimo.document.vehicle.registration), so most of the fleet shows no VIN. Almost all vehicles already carry a DIMO VIN verifiable credential, readable directly from telemetry-api — and our vehicle-JWT exchange already requests privilege 5 (GetVINCredential), so no permission or config changes are needed.What
TelemetryAPIService.VINFromVC—query { vinVCLatest(tokenId: N) { vin } }through the existing per-vehicle-JWT GraphQL path. Null VC / blank VIN →found=false; GraphQL errors surface as errors (callers skip + retry later).LicensePlateSyncService— VC fallback after the registration-document pass whenever the VIN is still unknown, plus a leanSyncVINOnly(no fetch-api pull) for backfill. Fill-if-missing — an existing VIN is never overwritten.import-group-attestations -vin-only— one-shot, dry-run-able backfill restricted in SQL tovin IS NULL OR vin = ''. The regular cron pass converges new vehicles via the fallback.Pull-once by construction: VIN is immutable, so everything gates on the VIN being absent — once cached, a vehicle never costs another telemetry query (DCX). Total spend ≈ one query per VIN-less vehicle, once.
No migration, no config, no frontend changes (
/vehiclesalready returnsvin; quick-view VIN row, list column, and search already render it). Plan doc:docs/VIN_SYNC_PLAN.md.Verification (live, mainnet)
-vin-only -dry-run -token-id 191347→ resolvedLSH14J7C2SA820026from the VC, loggedwould cache vin from vc, no writevehicles.vinchecked: 0— the filled vehicle is excluded by the SQL gate before any telemetry call (pull-once proven)go build/go vet/go test/golangci-lint runall clean;parseVINVCResponseunit-tested (present / null / blank / whitespace / malformed)After merge
One manual backfill per env:
🤖 Generated with Claude Code
https://claude.ai/code/session_01UxoaxTXSLqUwkYfewdwGBM