feat: AR-VINchecker v1.0 — VIN report generator with AI analysis

FastAPI server querying NHTSA/EPA APIs, generating PDF reports
with risk scoring, and local Ollama AI analysis via DealAnalyzer.
Security hardened: XSS fix, SSRF protection, CORS restricted.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-07-03 11:40:35 -04:00
commit dc3ec90109
18 changed files with 1970 additions and 0 deletions
+91
View File
@@ -0,0 +1,91 @@
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>AR-VinReport</title>
<link rel="stylesheet" href="/static/css/styles.css" />
</head>
<body>
<header class="topbar">
<span class="topbar-logo">🚗 AR-VinReport</span>
<span class="topbar-version">v1.0 — NHTSA · EPA · PDF</span>
</header>
<div class="layout">
<!-- ── Left panel: form ──────────────────────────────────────────── -->
<aside class="panel-form">
<h2 class="panel-title">Nuevo Reporte</h2>
<form id="fetchForm" autocomplete="off">
<div class="field">
<label for="vin">VIN <span class="req">*</span></label>
<input id="vin" name="vin" type="text" maxlength="17"
placeholder="17 caracteres" required />
</div>
<div class="field">
<label for="odometer">Odómetro (mi)</label>
<input id="odometer" name="odometer" type="text" placeholder="ej: 57,909" />
</div>
<div class="field">
<label for="primary_damage">Daño Primario</label>
<input id="primary_damage" name="primary_damage" type="text"
placeholder="ej: Normal Wear" />
</div>
<div class="field">
<label for="secondary_damage">Daño Secundario</label>
<input id="secondary_damage" name="secondary_damage" type="text"
placeholder="ej: Damage History" />
</div>
<div class="field">
<label for="title">Título</label>
<input id="title" name="title" type="text"
placeholder="ej: NY - Certificate of Title" />
</div>
<div class="field">
<label for="bid">Bid actual ($)</label>
<input id="bid" name="bid" type="text" placeholder="ej: 4,100" />
</div>
<div class="field">
<label for="auction">Subasta</label>
<input id="auction" name="auction" type="text" placeholder="ej: Copart" />
</div>
<div class="field">
<label for="photo_url">URL de foto (opcional)</label>
<input id="photo_url" name="photo_url" type="url"
placeholder="https://..." />
</div>
<button type="submit" class="btn btn-primary" id="fetchBtn">
⚡ FETCH DATA
</button>
</form>
<hr class="divider" />
<p class="hint">VIN de prueba:<br />
<code class="mono">1FTVW1EL1NWG14881</code>
</p>
</aside>
<!-- ── Right panel: active cards ─────────────────────────────────── -->
<main class="panel-cards">
<h2 class="panel-title">Reportes Activos</h2>
<div id="cardsContainer" class="cards-container">
<div class="empty-state">
<span class="empty-icon">📋</span>
<p>Ingresa un VIN y haz click en <b>FETCH DATA</b> para comenzar.</p>
</div>
</div>
</main>
</div>
<script src="/static/js/app.js"></script>
</body>
</html>