Skip to content

Instantly share code, notes, and snippets.

@heumn
Created April 25, 2026 09:22
Show Gist options
  • Select an option

  • Save heumn/65b76f18cb5ad6b5b1bb42c31a4cbea3 to your computer and use it in GitHub Desktop.

Select an option

Save heumn/65b76f18cb5ad6b5b1bb42c31a4cbea3 to your computer and use it in GitHub Desktop.
Drive-away detection illustration for enode/api#11388
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Drive-Away Detection Change</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: 'Inter', system-ui, -apple-system, sans-serif;
-webkit-font-smoothing: antialiased;
background: #FFFFFF;
color: #423F35;
}
.container {
max-width: 72rem;
margin: 0 auto;
padding: 0 1rem;
}
/* Header */
.header {
background: #191610;
padding: 2.5rem 0;
text-align: center;
}
.header h1 {
color: #FCFCFB;
font-size: 1.75rem;
font-weight: 500;
letter-spacing: -0.05em;
line-height: 1.0;
margin-bottom: 0.5rem;
}
.header .subtitle {
color: rgba(252, 252, 251, 0.6);
font-size: 0.9375rem;
font-weight: 400;
}
.header .pr-badge {
display: inline-block;
background: #5D770D;
color: #FFFFFF;
font-size: 0.8125rem;
font-weight: 500;
padding: 0.25rem 0.75rem;
border-radius: 5.5rem;
margin-top: 0.75rem;
font-family: 'JetBrains Mono', monospace;
}
/* Sentry stats */
.stats-section {
background: #F5F3EE;
padding: 2.5rem 0;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1.5rem;
max-width: 48rem;
margin: 0 auto;
}
.stat-card {
background: #FFFFFF;
border-radius: 6px;
padding: 1.25rem;
text-align: center;
}
.stat-card .number {
font-size: 2rem;
font-weight: 500;
color: #002203;
letter-spacing: -0.05em;
line-height: 1.0;
}
.stat-card .number.red { color: #E2722C; }
.stat-card .number.green { color: #5D770D; }
.stat-card .label {
font-size: 0.8125rem;
color: #505038;
margin-top: 0.375rem;
}
/* Flow section */
.flow-section {
padding: 3rem 0;
}
.flow-section h2 {
font-size: 1.5rem;
font-weight: 500;
color: #002203;
letter-spacing: -0.05em;
text-align: center;
margin-bottom: 2rem;
}
.flow-comparison {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 2rem;
max-width: 56rem;
margin: 0 auto;
}
.flow-column {
border-radius: 8px;
overflow: hidden;
}
.flow-column.before { background: #FFF; border: 1px solid rgba(66, 63, 53, 0.12); }
.flow-column.after { background: #FFF; border: 2px solid #5D770D; }
.flow-header {
padding: 0.75rem 1rem;
font-weight: 500;
font-size: 0.9375rem;
text-align: center;
letter-spacing: -0.03em;
}
.flow-column.before .flow-header {
background: rgba(226, 114, 44, 0.1);
color: #E2722C;
}
.flow-column.after .flow-header {
background: rgba(93, 119, 13, 0.1);
color: #5D770D;
}
.flow-body {
padding: 1.25rem;
}
.flow-step {
display: flex;
align-items: flex-start;
gap: 0.625rem;
padding: 0.5rem 0;
}
.flow-step + .flow-step {
border-top: 1px solid rgba(66, 63, 53, 0.06);
}
.step-icon {
flex-shrink: 0;
width: 1.5rem;
height: 1.5rem;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.75rem;
font-weight: 500;
margin-top: 0.125rem;
}
.step-icon.check { background: rgba(93, 119, 13, 0.15); color: #5D770D; }
.step-icon.cross { background: rgba(226, 114, 44, 0.15); color: #E2722C; }
.step-icon.arrow { background: rgba(80, 80, 56, 0.1); color: #505038; }
.step-icon.new { background: #5D770D; color: #FFFFFF; }
.step-text {
font-size: 0.8125rem;
line-height: 1.4;
color: #423F35;
}
.step-text strong { color: #002203; font-weight: 500; }
.step-text code {
font-family: 'JetBrains Mono', monospace;
font-size: 0.75rem;
background: #F5F3EE;
padding: 0.1rem 0.3rem;
border-radius: 3px;
color: #505038;
}
.step-text .dim { color: rgba(66, 63, 53, 0.5); }
/* Vehicle grid */
.vehicles-section {
background: #F5F3EE;
padding: 2.5rem 0;
}
.vehicles-section h2 {
font-size: 1.5rem;
font-weight: 500;
color: #002203;
letter-spacing: -0.05em;
text-align: center;
margin-bottom: 0.375rem;
}
.vehicles-section .section-sub {
text-align: center;
font-size: 0.8125rem;
color: #505038;
margin-bottom: 1.5rem;
}
.vendor-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 1rem;
max-width: 48rem;
margin: 0 auto;
}
.vendor-card {
background: #FFFFFF;
border-radius: 6px;
padding: 1rem 1.25rem;
}
.vendor-card-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 0.625rem;
}
.vendor-card-header h3 {
font-size: 0.9375rem;
font-weight: 500;
color: #002203;
letter-spacing: -0.03em;
}
.badge {
display: inline-block;
font-size: 0.6875rem;
font-weight: 500;
padding: 0.125rem 0.5rem;
border-radius: 5.5rem;
}
.badge.suppressed { background: rgba(93, 119, 13, 0.12); color: #5D770D; }
.badge.active { background: rgba(226, 114, 44, 0.12); color: #E2722C; }
.badge.safe { background: rgba(93, 119, 13, 0.12); color: #5D770D; }
.vendor-list {
display: flex;
flex-wrap: wrap;
gap: 0.375rem;
}
.vendor-tag {
font-family: 'JetBrains Mono', monospace;
font-size: 0.6875rem;
padding: 0.1875rem 0.5rem;
border-radius: 4px;
font-weight: 400;
}
.vendor-tag.capable {
background: #F5F3EE;
color: #505038;
}
.vendor-tag.incapable {
background: rgba(226, 114, 44, 0.08);
color: #E2722C;
border: 1px solid rgba(226, 114, 44, 0.2);
}
.vendor-note {
font-size: 0.75rem;
color: #505038;
margin-top: 0.5rem;
line-height: 1.4;
}
/* Spot check */
.spotcheck-section {
padding: 2.5rem 0;
}
.spotcheck-section h2 {
font-size: 1.5rem;
font-weight: 500;
color: #002203;
letter-spacing: -0.05em;
text-align: center;
margin-bottom: 1.5rem;
}
.spotcheck-bar {
max-width: 36rem;
margin: 0 auto 1rem;
display: flex;
border-radius: 6px;
overflow: hidden;
height: 2rem;
}
.bar-segment {
display: flex;
align-items: center;
justify-content: center;
font-size: 0.6875rem;
font-weight: 500;
color: #FFFFFF;
}
.bar-segment.real { background: #5D770D; }
.bar-segment.phantom { background: #E2722C; }
.bar-segment.ambiguous { background: #505038; }
.bar-legend {
display: flex;
justify-content: center;
gap: 1.5rem;
max-width: 36rem;
margin: 0 auto;
}
.legend-item {
display: flex;
align-items: center;
gap: 0.375rem;
font-size: 0.75rem;
color: #505038;
}
.legend-dot {
width: 0.5rem;
height: 0.5rem;
border-radius: 50%;
}
.legend-dot.real { background: #5D770D; }
.legend-dot.phantom { background: #E2722C; }
.legend-dot.ambiguous { background: #505038; }
/* Footer */
.footer {
background: #184602;
padding: 1.5rem 0;
text-align: center;
}
.footer p {
color: rgba(252, 252, 251, 0.7);
font-size: 0.8125rem;
}
.footer strong {
color: #E6F77E;
font-weight: 500;
}
</style>
</head>
<body>
<!-- Header -->
<section class="header">
<div class="container">
<h1>Drive-Away Detection: Capability Gate</h1>
<div class="subtitle">Sentry API-2P8 &middot; staleDataScrubber.ts</div>
<div class="pr-badge">enode/api#11388</div>
</div>
</section>
<!-- Stats -->
<section class="stats-section">
<div class="container">
<div class="stats-grid">
<div class="stat-card">
<div class="number red">517</div>
<div class="label">warnings in 3 days</div>
</div>
<div class="stat-card">
<div class="number">~170</div>
<div class="label">false positives per day</div>
</div>
<div class="stat-card">
<div class="number green">0</div>
<div class="label">BMW / MINI / XPENG events</div>
</div>
</div>
</div>
</section>
<!-- Flow comparison -->
<section class="flow-section">
<div class="container">
<h2>How the detection logic changes</h2>
<div class="flow-comparison">
<!-- Before -->
<div class="flow-column before">
<div class="flow-header">Before (all vendors)</div>
<div class="flow-body">
<div class="flow-step">
<div class="step-icon arrow">&darr;</div>
<div class="step-text">Vehicle has a <strong>locationId</strong> (assigned to geofence)</div>
</div>
<div class="flow-step">
<div class="step-icon arrow">&darr;</div>
<div class="step-text">Update arrives with <strong>no GPS</strong>, <strong>no odometer</strong></div>
</div>
<div class="flow-step">
<div class="step-icon arrow">&darr;</div>
<div class="step-text">Vehicle is <code>UNPLUGGED</code></div>
</div>
<div class="flow-step">
<div class="step-icon arrow">&darr;</div>
<div class="step-text">Battery dropped &ge;10% from baseline</div>
</div>
<div class="flow-step">
<div class="step-icon cross">&times;</div>
<div class="step-text"><strong>Clear locationId</strong> for <em>all</em> vendors<br><span class="dim">Including Tesla sleep mode, Renault charge-only polls...</span></div>
</div>
</div>
</div>
<!-- After -->
<div class="flow-column after">
<div class="flow-header">After (capability-gated)</div>
<div class="flow-body">
<div class="flow-step">
<div class="step-icon arrow">&darr;</div>
<div class="step-text">Vehicle has a <strong>locationId</strong> (assigned to geofence)</div>
</div>
<div class="flow-step">
<div class="step-icon arrow">&darr;</div>
<div class="step-text">Update arrives with <strong>no GPS</strong>, <strong>no odometer</strong></div>
</div>
<div class="flow-step">
<div class="step-icon arrow">&darr;</div>
<div class="step-text">Vehicle is <code>UNPLUGGED</code></div>
</div>
<div class="flow-step">
<div class="step-icon new">&#x2713;</div>
<div class="step-text"><strong>Is odometer capable?</strong><br>
<span class="dim">Yes &rarr; skip battery fallback, wait for GPS/odometer</span></div>
</div>
<div class="flow-step">
<div class="step-icon check">&darr;</div>
<div class="step-text">Only <strong>odometer-incapable</strong> vehicles (BMW, MINI, XPENG) proceed to battery check</div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Vendor cards -->
<section class="vehicles-section">
<div class="container">
<h2>Impact by vendor</h2>
<p class="section-sub">Based on 500 sampled Sentry events &middot; 22 vehicles spot-checked in production</p>
<div class="vendor-grid">
<div class="vendor-card">
<div class="vendor-card-header">
<h3>Odometer-capable (suppressed)</h3>
<span class="badge suppressed">500 / 500 events</span>
</div>
<div class="vendor-list">
<span class="vendor-tag capable">RENAULT</span>
<span class="vendor-tag capable">CUPRA</span>
<span class="vendor-tag capable">DACIA</span>
<span class="vendor-tag capable">SKODA</span>
<span class="vendor-tag capable">AUDI</span>
<span class="vendor-tag capable">TESLA</span>
<span class="vendor-tag capable">SEAT</span>
<span class="vendor-tag capable">POLESTAR</span>
<span class="vendor-tag capable">ALPINE</span>
</div>
<div class="vendor-note">These vendors sometimes omit odometer from individual polls (e.g. Tesla sleep, Renault charge-only). Phantom drain on parked vehicles crosses the 10% threshold, causing false positives.</div>
</div>
<div class="vendor-card">
<div class="vendor-card-header">
<h3>Odometer-incapable (still active)</h3>
<span class="badge active">0 / 500 events</span>
</div>
<div class="vendor-list">
<span class="vendor-tag incapable">BMW</span>
<span class="vendor-tag incapable">MINI</span>
<span class="vendor-tag incapable">XPENG</span>
</div>
<div class="vendor-note">These vendors can never report odometer. Battery fallback is the only drive-away signal beyond GPS. Currently zero events in production &mdash; the fallback remains available if needed.</div>
</div>
</div>
</div>
</section>
<!-- Spot-check -->
<section class="spotcheck-section">
<div class="container">
<h2>22 vehicles spot-checked</h2>
<div class="spotcheck-bar">
<div class="bar-segment real" style="width: 59%">59% real</div>
<div class="bar-segment phantom" style="width: 18%">18%</div>
<div class="bar-segment ambiguous" style="width: 23%">23%</div>
</div>
<div class="bar-legend">
<div class="legend-item"><div class="legend-dot real"></div> Real drive-away (13)</div>
<div class="legend-item"><div class="legend-dot phantom"></div> Phantom drain false positive (4)</div>
<div class="legend-item"><div class="legend-dot ambiguous"></div> Ambiguous (5)</div>
</div>
</div>
</section>
<!-- Footer -->
<section class="footer">
<div class="container">
<p>After this change, Sentry API-2P8 volume drops to <strong>~0 events/day</strong> from current vendors.<br>
BMW/MINI/XPENG retain the battery fallback for genuine no-odometer scenarios.</p>
</div>
</section>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment