intermediate
juicer
fraud
security

Juicer Fraud Detection

The six independent fraud vectors Levy Swap checks on every Juicer session — GPS drift, photo timestamps, drop-zone polygon, charge duration, photo hash, and radius violations

Levy Fleets TeamMay 18, 20267 min read

Juicer Fraud Detection

Every Juicer session is evaluated against six independent fraud vectors. A single failed vector doesn't usually ban a Juicer — but the platform tracks a running fraud score per Juicer, and crossing thresholds triggers automatic action.

Target outcome: fewer than 3% fraud incidents in the pilot city.

The Six Vectors

#VectorWhat It Catches
1GPS drift at pickupJuicer not actually at the vehicle when they claim pickup
2Photo timestamp driftJuicer waited too long between claim and pickup, or photo was taken in a different session
3Drop-zone polygonJuicer dropped the vehicle outside any allowed drop zone
4Charge duration plausibilityJuicer claims an SoC delta that's impossible given the elapsed time
5Photo hash collisionJuicer is reusing a previous photo (theirs or someone else's)
6Radius violationJuicer is operating outside their verified home radius

Each vector emits one of three signals — clean, warn, or block. Warns add to the fraud score; blocks reject the action and also add to the score.

Vector 1: GPS Drift at Pickup

Pickup photo GPS is compared to the vehicle's last telemetry GPS.

DriftSignalFraud-Score Delta
≤50 mclean0
50–200 mwarn+5
>200 mblock+10

The 50 m threshold accounts for GPS jitter on the phone and the vehicle's IoT module. The 200 m threshold catches Juicers attempting to claim from a parking lot away from the actual vehicle.

If the vehicle hasn't reported telemetry in the last 30 minutes, the platform falls back to the bounty's stored vehicle location and logs a "stale telemetry" note — the pickup still proceeds.

Vector 2: Photo Timestamp Drift

The pickup photo carries an EXIF timestamp. The platform compares it to the claim timestamp.

DriftSignalFraud-Score Delta
≤5 minclean0
5–30 minwarn+3
>30 minblock+5

A drift past 30 minutes usually means the Juicer claimed, didn't actually pick up immediately, and then took a photo later (or pulled an old photo from their library). Most genuine pickups complete within 5 minutes.

EXIF metadata is stripped from the stored copy of the photo after the timestamp is read — we keep the timestamp on the session row, not the EXIF block, so we don't accidentally leak location data on shared images.

Vector 3: Drop-Zone Polygon

The drop photo's GPS is checked against the operator's active drop zones via PostGIS ST_Contains. There's no fuzz margin — the drop is either inside an active zone or it isn't.

ResultSignalFraud-Score Delta
Inside zoneclean0
Outside zoneblock+10

The Juicer cannot complete the bounty until the drop is inside a zone. They can move the vehicle and try again — there's no penalty for a retried attempt, only for the failed one.

Drop zones are a subset of the operator's existing zone catalog — operators mark specific zones as Juicer-eligible. See Drop Zones in the zones docs for managing zone polygons.

Vector 4: Charge Duration Plausibility

The platform tracks pickup_soc, the latest reported SoC during charge-checkins, and the elapsed time. The required minimum is 0.6 minutes per percent of SoC delta — anything faster is physically impossible on a standard wall charger and triggers a block.

Example: A pack picked up at 12% SoC reported at 95% SoC needs at least (95 - 12) × 0.6 = 49.8 minutes of elapsed charge time. If the Juicer reports 95% after only 18 minutes, the drop is blocked and flagged for manual review.

Elapsed vs. ExpectedSignalFraud-Score Delta
≥0.6 min/%clean0
0.3–0.6 min/%warn+5
<0.3 min/%block+15

The 0.6 threshold is intentionally generous — fast chargers exist, and pack chemistry varies. The point is to catch "I just made up an SoC number" cases, not to police charge speed.

Vector 5: Photo Hash Collision

Every pickup and drop photo is hashed (perceptual hash, not bitwise). Each session's photo hashes are compared against:

  • The same Juicer's prior session photos
  • All other Juicers' photos in the same subaccount (last 90 days)
ResultSignalFraud-Score Delta
No collisionclean0
Soft collision (similar but not identical)warn+5
Hard collision (identical hash)block+20

A hard collision usually means a Juicer is reusing a single photo across multiple pickups, or sharing photos with a friend who's also a Juicer. Both are explicit fraud.

The +20 demerit is the largest single hit because the intent is unambiguous.

Vector 6: Radius Violation

The Juicer's home address (set at onboarding) creates a home_geo PostGIS point. Every claim is checked against the Juicer's configured claim_radius_m (default 8047 m ≈ 5 mi, configurable per subaccount).

ResultSignalFraud-Score Delta
Within radiusclean0
Outside radiusblock+5

A Juicer in TX can't claim a vehicle in FL. They can't operate while traveling out of state, period. The point is to keep KYC ground-truth meaningful — the verified address has to be where they actually work.

If a Juicer moves, they can request a home_geo update from the dashboard; operators approve the change manually after a quick review.

Fraud Score Thresholds

Each Juicer carries a running fraud_score on their row. The lifetime score is accumulated as warnings and blocks fire.

ScoreAction
0 – 24Normal — no action
25 – 49Warning displayed on operator dashboard
50 – 99Auto-suspend — Juicer cannot claim until operator reviews
100+Auto-banstatus = 'banned', all queued payouts held

The auto-suspend at 50 and auto-ban at 100 are platform defaults; operators can change them per subaccount.

Scores do not decay automatically. Operators can manually reduce a Juicer's score from the dashboard with a reason note — used when an isolated false-positive is clearly explainable (e.g., GPS jitter near a tunnel).

Manual Operator Tools

In addition to the automatic system, operators can:

  • Hold a payout — pause a queued payout pending investigation
  • Reverse a payout — claw back a paid payout (via Stripe reversal)
  • Cancel a session — end a session early without paying
  • Suspend / ban — instantly lock a Juicer out
  • Add to ban list — a banned Juicer's auth.users.id is recorded; new applications from the same identity are rejected

All actions are logged on the Juicer's detail page with the operator who took them and the timestamp.

What the Juicer Sees

When a check fails, the Juicer gets a specific message:

  • "Pickup location is too far from the vehicle. Move closer and try again."
  • "Drop is outside an allowed zone. Move the vehicle into a drop zone."
  • "Charge duration is too short — please check in regularly while charging."
  • "Photo appears identical to a previous photo. Please take a fresh photo of the vehicle."

When fraud-score thresholds trigger, they see a "Your account is under review" banner with the operator's contact info.

Common Fraud Patterns the System Has Caught

  • The phantom Juicer — claims, never picks up, hopes the TTL doesn't reset. Caught by the no-show counter and the 3-point demerit per expired claim.
  • The photo recycler — reuses one good pickup photo across many claims. Caught by hash collision (+20).
  • The teleporter — claims a vehicle, photos a different one a block away. Caught by GPS drift (+10).
  • The instant charger — claims at 15%, drops at 95% in 12 minutes. Caught by charge plausibility (+15).
  • The out-of-state operator — claims a vehicle in a city they don't live in. Caught by radius violation (+5).
  • The duplicate identity — same name and SSN-last-4 from a different email. Caught by Stripe Identity dedup at KYC.