Commit Graph

18 Commits

Author SHA1 Message Date
a3ae90ec29 fix(vin-decode): 4 RCA-confirmed decode-chain bugs
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
Root-cause analysis live re-decoded all 124 historically-undecoded prod
VINs; 38 already decode now. These 4 fixes target confirmed code bugs
that drop or mask real decodes (see undecoded-vin-rca.md):

Q2 — PL24 circuit breaker now only counts transient transport faults. A
definitive upstream negative (NotFound/BadRequest) no longer trips the
global 30s breaker that was starving PL24 for every subsequent VIN
(the sibling-VIN inconsistency in the report). Live-proven on VR7.

Q3 — previewVin / multi-candidate path no longer returns an empty
success: the pcat/emex candidate branches fill brandName (from catalogId
/ WMI), fixing the 6 "HTTP 200 with null brand+model" cases.

Q1 — EMEX fetch retries transient proxy failures with a FRESH ProxyAgent
per attempt (rotates the DataImpulse port; ~42% blip rate observed),
plus an opt-in direct fallback (EMEX_DIRECT_FALLBACK). HTTP answers are
never retried.

Q4 — VIN resolve cache keys namespaced by DECODE_CHAIN_VERSION and the
negative TTL drops 6h -> 30m, so a decode-chain fix self-heals stale
negatives on deploy instead of masking phantom-undecoded VINs for hours.
The admin cache-buster uses the same key builder.

Tests: 179 passed (+ new Q2/Q3/Q4 specs). typecheck + biome clean.

Deploy note: prod EMEX_PROXY_PORT_START/END are both 823 (single port);
widen to a real range (e.g. 10001-10099) in Coolify so Q1's port
rotation takes full effect.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 22:37:11 +03:00
1e3953417e perf(backfill): stop the prefetch worker from throttling itself (Tier 1)
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
The worker's own upstream fetches called touchActivity(), setting the
prefetch:activity:<source> cooldown key (TTL 300s) that checkCooldown then
honoured — so after each fetch the worker paused itself for up to ~5 minutes
(re-checking every 60s, ~5 empty cycles per key). At ~1 fetch / 5 min the
3387-job backlog needed ~6 days to drain.

- Wrap each worker job in an AsyncLocalStorage backfill context; touchActivity
  skips the cooldown key when invoked from the worker, so the cooldown reflects
  only real user requests (worker yields to users, never to itself).
- Cooldown TTL 300s -> 90s (a request 5 min ago isn't "active").
- checkCooldown pauses for the key's actual remaining TTL (one wait) instead of
  a fixed 60s re-check loop.

No extra upstream load — only removes the worker's self-imposed idle time.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 18:23:54 +03:00
8e9439450b feat(api): add newer Peugeot/Citroën/DS/Opel WMIs (VR1/VR3/VR7/W0V)
Prod decode failures clustered on French/Stellantis VINs that no source even
tried: the post-merger WMIs VR3/VR7 (Peugeot), VR1 (Citroën/DS) and W0V (Opel)
were missing from every map, so getServiceName/isSupported returned null and the
VIN was rejected as "Marka desteklenmiyor" before any scrape ran.

Add them to all three maps, matching the existing VF3/VF7/W0L routing:
- Corgi WMI_DATABASE (display brand)
- PL24_WMI_SERVICE_MAP (peugeot_parts / citroen_parts / opel_parts)
- EMEX CATALOG_MAP (PSA -> PEUGEOT00, Opel -> GM_OP201809)

Lets EMEX scrape and PL24 fall back for these mass-market TR brands instead of
hard-failing at the routing step. Phase 4 of 4 on decode reliability.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 00:13:43 +03:00
d14bcb7dca feat(pcat): translate part descriptions + vehicle attrs (body/engine/transmission)
PCAT was missing parity with EMEX in two places:
- Part `description` (notice) was stored raw English alongside translated `name`.
  Now batched into translateMany so users see Turkish notices.
- Vehicle body/engine/transmission attrs from VIN decode were raw upstream
  values. Wire up the existing emex.mapper dictionaries on the PCAT
  single-car, PCAT resolveById, and EMEX single-vehicle result paths.
- emex.mapper translateToTurkish now falls back to the original term on
  dictionary miss instead of null — upstream values are heterogeneous
  (engine codes, multi-word descriptors); losing them was worse than
  leaving them untranslated.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 10:45:12 +03:00
d2fb64484c perf(emex): plain-HTTP fast path with Playwright fallback (Tier 3-A)
Probe (scripts/dev) confirmed that everything PartsPanel reads from an
emexdwc.ae leaf — parts table, hotspot coordinates, and the schema image
URL — is fully server-rendered in Unit.aspx HTML. Parts arrive as
`<tr name>` rows with `td[name=c_oem|c_pnc|c_name]`; hotspots are
`<div class="dragger g_highlight" name=N style="margin-top:Ypx; margin-left:Xpx; ...">`
with the coords already in image-natural pixel space; the image URL is
in `<img class="dragger" src=...laximo...>` and its native dims can be
read from the first 24 bytes of the GIF/PNG via a Range GET.

Behaviour:
1. fetchCategoryParts now tries fetchCategoryPartsViaHttp first — two
   sequential GETs (QuickDetails → Unit) + a Range GET for image dims.
2. If the HTML yields ≥1 part, we return it.
3. If the HTML returns no Unit.aspx anchor, or 0 parts, we fall back to
   the existing Playwright scraper (same code path as before).

The plain-HTTP path skips the ~1-2s browser launch, sidesteps the
3-page semaphore in EmexBrowserService (concurrency cap was throttling
prefetch fan-out), and uses no chromium memory. Measured on dev with 5
fresh-ssd Renault Espace IV leaves: 4.9-5.5s wall per leaf (vs 6-7s on
the Tier 1 browser path, vs 12-14s pre-Tier-1). The 6th sample
(stale-ssd Fren Kaliyeri) failed both paths identically — confirms the
plain-HTTP path doesn't introduce new failure modes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 09:56:53 +03:00
a1e80c042f fix(emex): ship runtime scripts/ in prod image and forward chromium executable path
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
EMEX-decoded vehicles surfaced empty category pages on prod because two
runtime prerequisites were absent from the production image:

1. `scripts/emex-vin-scraper.js` was never copied — the build stage's
   `COPY . .` brings it in but the production stage only cherry-picks
   `apps/api/dist`, `drizzle`, and `start.sh`. Every EMEX leaf hit
   therefore failed with "Scraper file not found at: /app/scripts/…"
   and the category page rendered "Bu kategori icin parca bulunamadi."
2. `PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH=/usr/bin/chromium-browser` was
   exported in the Dockerfile but never reached `chromium.launch()` —
   that env var is consumed by `playwright install`, not at runtime.
   Playwright fell back to its bundled headless-shell cache path
   (`/root/.cache/ms-playwright/chromium_headless_shell-*/…`) which
   does not exist on the alpine image, so even with the scraper file
   present the browser pool init would have kept failing.

Fix:
- Dockerfile: `COPY --from=build /app/scripts ./scripts`.
- `emex.browser.ts` + `parts-catalogs-auth.service.ts`: read
  `process.env.PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH` and pass it as
  `executablePath` to `chromium.launch()` when set.

Verified on prod container: `ls /app/scripts` → missing pre-fix; the
binary at `/usr/bin/chromium-browser` exists, so the env-var hand-off
will resolve cleanly once the new image lands.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 08:45:18 +03:00
Fusion
f4fea1e429 feat(FN-094): add comment line for deployment verification
Some checks failed
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
- Added a comment line to main.ts for deployment verification purposes
2026-05-11 02:07:03 +00:00
3710251117 feat: EMEX VIN decode → DB catalog entegrasyonu
Some checks failed
CI / Lint, Typecheck, Test & Build (push) Has been cancelled
- CATALOG_MAP'e ~40 yeni WMI eklendi (Mitsubishi, Nissan, Volvo, vb.)
- brandFromCatalogCode listesi 55 DB kataloğuna genişletildi
- brand="UNKNOWN" olsa bile catalogCode varsa EMEX sonucu kabul edilir
- emex-catalog: linkPath'li kategorilerde parçalar DB'den yüklenir (scraper bug fix)
- VIN cache: emex_vehicle_vins tablosu ile tekrar VIN'lerde emexdwc.ae atlanır
- getCategoryTree Step 0: VIN cache lookup (~10ms)
- Match sonrası otomatik VIN cache doldurma
- Proaktif cache: ilk decode sonrası matchByName + saveVinCache

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 08:32:34 +00:00
7a6b42c2e7 feat: QuickGroups shortcut — VIN SSD + vid=0 for fast category fetch
Some checks failed
CI / Lint, Typecheck, Test & Build (push) Has been cancelled
When EMEX DB has no vehicle match (Ford EU, Mercedes etc.), instead of
falling back to full on-demand VIN decode (~8s), use the VIN-decode SSD
directly with QuickGroups.aspx?c={catalog}&vid=0&ssd={vinSsd} (~2-3s).

Tested: Ford Focus CB4 VIN SSD returns 376 categories via QuickGroups.

New step 3.5 in the cascade:
1. pathData → matchByName (DB-only, ~50ms)
2. emexVehicleName → matchByName (DB-only, ~50ms)
3. matchBySsd wizard walk (DB, ~2-3s)
3.5. VIN SSD → QuickGroups shortcut (~2-3s) ← NEW
4. Fallback → full on-demand scrape (~8s)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 15:24:38 +00:00
53a6296a91 feat: EMEX VIN decode → catalog DB matching via pathData/SSD
Some checks failed
CI / Lint, Typecheck, Test & Build (push) Has been cancelled
Parse path_data from Vehicle.aspx URLs (Base64-decoded vehicle name),
persist vehicleLabel/vid/pathData in rawData, and add 4-step matching
cascade for category resolution:
1. pathData name → matchByName (DB-only, ~50ms)
2. emexVehicleName → matchByName (DB-only, ~50ms)
3. ssd + catalogCode → matchBySsd (wizard HTTP + DB, ~2-3s)
4. Fallback → on-demand EMEX scrape (unchanged, ~6-13s)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 14:46:00 +00:00
1a552ed8fd fix: handle empty EMEX proxy env vars with proper defaults
Some checks failed
CI / Lint, Typecheck, Test & Build (push) Has been cancelled
ConfigService returns empty string (not the default) when env var
exists but is empty. Add || fallbacks in code and set proper defaults
in docker-compose to prevent invalid proxy URL like http://user:pass@:10000.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 12:21:26 +00:00
0fce6a2266 fix: use undici's own fetch for proxy dispatcher support
Some checks failed
CI / Lint, Typecheck, Test & Build (push) Has been cancelled
Node's global fetch doesn't support the dispatcher option. Use
undici's exported fetch when proxy is configured, which properly
handles ProxyAgent as a dispatcher.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 12:13:09 +00:00
016860c68a fix: route EMEX HTTP fetches through DataImpulse proxy
Some checks failed
CI / Lint, Typecheck, Test & Build (push) Has been cancelled
EMEX server blocks direct server IP requests (geo/bot protection),
causing all HTTP-based VIN decodes to return empty results. Add proxy
support to fetchEmexHtml() using undici ProxyAgent, reusing the same
EMEX_USE_PROXY / EMEX_PROXY_* env vars as the browser service.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 11:29:00 +00:00
Sase Dev
ce8784014e feat: EMEX HTTP decode + multi-candidate selection UI
Some checks failed
CI / Lint, Typecheck, Test & Build (push) Has been cancelled
Deploy / Deploy to Production (push) Has been cancelled
Replace Playwright browser with pure HTTP for EMEX VIN decode:
- Vehicles.aspx, QuickGroups.aspx, QuickDetails.aspx all work
  without authentication — no session/browser needed
- VIN decode drops from ~10-20s (Playwright) to ~1-5s (HTTP)
- Playwright browser kept as fallback if HTTP fails

Add multi-candidate selection for EMEX (mirrors PartsCatalogs flow):
- EmexCandidate interface matches PcatCar shape so VehicleSelectModal
  renders without changes
- decodeVinOrCandidates(): single HTTP fetch returns vehicle OR
  candidates (avoids double Vehicles.aspx request)
- decodeVinByIndex(): resolves user-selected candidate by index
- vehicles.service: emexCandidates in VinResolveResult, emexCarIndex
  param in decodeVin/resolveVin, resolveEmexCarByIndex() method
- vehicles.controller: @Body("emexCarIndex") accepted
- search.tsx: candidateSource state, handleCandidateSelect sends
  emexCarIndex or pcatCarId based on source

Test VIN NM417800006410193 (Fiat SIENA) now shows 2-option modal.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-05 09:46:25 +00:00
Sase Dev
f1a27810db feat: add parts catalogs integration, catalog prefetch worker, and vehicle select modal
Integrate external parts catalogs API with auth service, add BullMQ-based
catalog prefetch worker for background data caching, expand vehicles service
with shared vehicle support, and add vehicle select modal to frontend.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 18:14:36 +00:00
Sase Dev
4a06ba5fdb feat: Ford legacy support, EMEX browser pooling, collapsible sidebar
- Add PL24 Ford legacy service for fordt_parts architecture
- Refactor EMEX to use persistent browser pool instead of per-call instances
- Make vehicle decode resilient: fallback to PL24 when Corgi doesn't recognize VIN
- Add collapsible sidebar with persistent user preference
- Improve brand access guard and categories service
- Add debug/test scripts for VIN e2e testing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 22:25:06 +00:00
Sase Dev
a8eb8f4bdc refactor(emex): rewrite EMEX integration, add category fallback
Replace browser-based Puppeteer scraper with standalone scraper wrapper.
Add EMEX as fallback source for categories when PL24 is unavailable.
Update vehicle decoding to use new synchronous EMEX API.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 19:48:03 +00:00
Sase Dev
56a3c8bfaa feat: sase.tr v2 full application implementation
Complete rewrite of sase.tr VIN lookup platform with modern stack:

Backend (NestJS 10 + Drizzle ORM + PostgreSQL + Redis + BullMQ):
- 34 DB models (core + PL24 + EMEX schemas)
- Auth via Better Auth (email/password + social)
- Brands, Plans, Subscriptions, Payments (iyzico + EFT)
- VIN decode orchestration (Corgi + PL24 + EMEX + NHTSA)
- Interactive schema viewer backend (MinIO storage)
- EMEX scraping integration (Puppeteer + BullMQ workers)
- Translation module (EN→TR automotive dictionary)
- Admin dashboard API (stats, user mgmt, payment approval)
- Rate limiting, Helmet security, file upload validation

Frontend (Next.js 15 + Tailwind v4 + shadcn/ui + TanStack Query + Zustand):
- 20 routes: auth, dashboard, VIN search, schema viewer, admin
- Interactive schema viewer with zoom/pan/hotspot highlighting
- Subscription management with brand selector
- Payment flow (iyzico 3D Secure + EFT with receipt upload)
- i18n support (TR/EN)
- Error boundaries, loading skeletons, 404 page

Infrastructure:
- 85 tests (52 backend + 33 frontend, Vitest)
- CI/CD (GitHub Actions: lint, typecheck, test, build, deploy)
- Zero-downtime deploy script (PM2)
- Env validation script

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 02:03:56 +00:00