Commit Graph

34 Commits

Author SHA1 Message Date
ed74e2f361 feat(register): VIN-aware teaser + B2B copy
Hero already shows a generic vehicle preview when a 17-char VIN is typed,
so /register?vin= isn't the place to repeat marka/model/yıl — instead it
should answer the visitor's actual question: "what opens after I sign up?"

Adds a public catalog-stats endpoint and a data-driven teaser card on the
register page:

Backend:
* GET /api/vehicles/:vin/teaser-stats (Public, VIN-validated). Single SQL
  round-trip counts categories + parts + schema_pics for the VIN. Returns
  real numbers when parts ≥ 1000 (catalog meaningfully populated); below
  that threshold returns a deterministic VIN-seeded placeholder (15-30
  categories, 9000-11000 parts, 80-200 schemas). Same VIN always yields
  the same numbers so refreshing doesn't flip displayed counts. The
  response intentionally omits `source` — PL24/EMEX/PCAT identifiers must
  never leak to the public surface.

Frontend (/register):
* When ?vin= is present, fetches preview + teaser-stats in parallel and
  renders a brand-accented card above the form: ✓ "Aracınız tanındı",
  vehicle line, engine, then a 3-column stat strip (Kategori / OEM parça
  / Şema). Below: "Hesap açtığında bu araç için kataloğa anında erişim
  açılır."
* B2B copy pass on the rest of the page:
  - Heading flips to "Hesap Aç ve Katalogu Gör" when VIN present
  - Trial messaging rewritten to anti-gimmick B2B tone:
    "Kart bilgisi gerekmez · 30 gün ücretsiz · istediğin an iptal"
    (was: "30 gün Full Paket ücretsiz deneyin — kredi kartı gerekmez")
  - Subhead: "Sınırsız şase sorgulamak için ücretsiz hesap aç"
  - Submit button: "Hesap Aç ve Katalogu Gör" (vin) / "Hesap Aç" (no vin)
  - "Ücretsiz Başla" / "Full Paket" strings purged per [[sase-b2b-copy-not-consumer]]
2026-06-02 01:07:18 +03:00
59e40d6ccd feat(api): identify-but-no-catalog fallback instead of a bare "unsupported"
When no catalog source can decode a VIN, the decode dead-ended with "Şase
numarası tanınamadı. Marka desteklenmiyor." even for valid, recognizable cars.
Now, before that error, run a best-effort identification (offline Corgi WMI +
NHTSA); if it yields a brand/model/year, tell the dealer what the car is and that
the request was logged ("Bu araç X olarak tanındı, ancak ... katalog henüz yok.
Talebiniz kaydedildi."). Logged distinctly (identified_no_catalog) so the coverage
backlog can be mined. Skipped on budget-abort.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 01:47:36 +03:00
f5e4de2aab feat(api): fastest-source-wins decode race (PCAT+EMEX parallel, PL24 on PCAT miss)
Replaces the capped-EMEX-then-sequential-PL24 fallback (incl. the Phase-3 8s EMEX
cap) with a dynamic first-definitive race. PCAT + EMEX fire in parallel; the
instant PCAT settles without a single car, PL24 joins the race (a definitive EMEX
would already have returned). Whichever source yields a definitive result FIRST
wins — no artificial wait. At the parts counter the dealer gets the OEM match as
fast as any one source can answer.

- Removes EMEX_RACE_MS (reverts the 8s cap from 9b13c4a).
- PL24 still gated by isDecodeable + circuit breaker, raced against the 25s budget.
- Preserves Phase-1 transient tagging (no negative-cache poisoning), ctx timings,
  and the candidate fallback.
- Adds race tests: PCAT-1-car wins (no PL24); PCAT-miss + EMEX vehicle;
  PCAT-miss + EMEX-miss -> PL24 wins; all-miss -> throws.

Supersedes the Phase-3 EMEX-cap approach.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 00:54:16 +03:00
9b13c4a21f fix(api): give EMEX a realistic race window in the decode chain (3s -> 8s)
EMEX HTTP scrapes typically answer in ~4-5s, but the decode race capped EMEX at
3s (EMEX_RACE_MS) and fell back to PL24 — which doesn't cover EMEX-only brands.
Prod logs show the exact loss: "PL24 fallback triggered (EMEX: timeout)" at the
3s mark, immediately followed by "EMEX HTTP: found 334 categories". The win was
thrown away.

Raise the default cap to 8s and make it env-tunable (EMEX_RACE_MS), still well
inside the 25s decode budget. Only adds latency on the harder VINs where
PartsCatalogs didn't already resolve. Phase 3 of 4 on decode reliability.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 00:10:41 +03:00
257052162e fix(api): don't poison the VIN negative cache on transient source failures
A decode that failed from a transient proxy/network blip (PartsCatalogs
DataImpulse ConnectTimeout, EMEX timeout, PL24 transport error) was written to
the 6h negative cache identically to a genuine "brand not supported" miss. A
user who hit a blip then got "Şase tanınamadı" for 6h with no way to retry out —
and prod analytics showed this hitting SUPPORTED brands (Fiat/Toyota/Hyundai
decode fine once the proxy responds).

Thread a `transient` outcome flag through resolveVin -> doResolveVin:
- PartsCatalogs.decodeVin sets it when it swallows a transport error (vs a clean
  "no cars" miss), via a new optional outcome param.
- EMEX surfaces it via its existing {type:"error"} result.
- PL24 sets it on transport/timeout errors in the fallback catch.
resolveVin then skips the negative cache when transient=true; genuine misses
still cache for 6h. Phase 1 of 4 on decode reliability.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 00:08:08 +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
0defbe7eb6 Revert "feat(telemetry): enrich VIN decode events for Süper Panel observability"
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
Reverts PR #32 (commit 0b1f033 / 4645c27).

Reason: the backend telemetry was duplicating data that already lives
in query_logs. Every field the new PostHog events carried — provider
chain, response_time_ms, success/error, cache_source, pl24_circuit_open,
brandId, aborted, partial_result — is captured per-row in:

  query_logs { userId, vin, brandId, source, success, errorMessage,
               responseTimeMs, timings (jsonb), createdAt }

Süper Panel already has read-only access to the Sase.tr Postgres via
DATABASE_URL_SASE_RO; the VIN Decode Observability Module (SP-VIN-001)
will read query_logs directly. PostHog hop adds latency (5min poll),
event-volume cost, KVKK weight (even sanitized VINs leaving the
service), and architectural duplication for zero observability gain.

Frontend PostHog events (vin_decode_candidates, candidate_selected,
search_input_validation_failed, vin_decode_retry_clicked) stay — those
are user-interaction signals query_logs doesn't capture.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 11:04:15 +03:00
4645c2700e feat(telemetry): enrich VIN decode events for Süper Panel observability
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
Süper Panel VIN Decode Observability Module (SP-VIN-001) prerequisite.
The dashboard needs provider chain + cache + fallback context the
frontend can't see — emit those events from the backend.

VehiclesService.decodeVin now emits, at every terminal path:

1. provider_response_received (one per provider that ran)
   - provider, response_time_ms, status (success/no_data), cached,
     vin_brand, vin_sanitized, attempt_in_chain
   - Derived from ctx.timings.{pcat,emex,pl24,vin_api}; only providers
     that actually executed get an event.

2. provider_fallback_triggered (between consecutive attempts)
   - from_provider, to_provider, reason (timeout if budget aborted,
     else no_data), auto, attempt_number.

3. vin_decode_succeeded — winning provider, cache_hit, cache_source,
   response_time_ms, partial_result, fallback_used, provider_attempts,
   pl24_circuit_open, vin_sanitized.

4. vin_decode_failed — error_code (BUDGET_EXCEEDED | UNKNOWN_VIN),
   error_message, provider_attempted, response_time_ms, vin_sanitized.

Wired at three terminal points:
- DB cache hit (existing vehicle, no chain run)
- Unknown VIN failure (chain returned null)
- Full chain success (savedVehicle return)

Notes:
- VINs are sanitized (`WAUZZZ8K****`) before leaving the backend.
- Emission is wrapped in try/catch; a PostHog hiccup never breaks a
  user-facing decode.
- Frontend's legacy `vin_decoded` / `vin_decode_success` /
  `vin_decode_error` events stay as-is. The new backend events live
  alongside them with richer props.
- ML decoder fields default to false — VAG ML pipeline lands later.

Spec updated to pass the new PostHogService mock.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-18 10:55:47 +03:00
Semih
33e3a7a7d6 fix(vehicles): make decoded vehicles readable by any authenticated user
Decoded vehicle data is shared across the platform — once any user
decodes a VIN, the vehicle, its categories, and its parts should be
visible to every authenticated user. The previous getById enforced a
user↔vehicle junction via inner join, returning 404 "Araç bulunamadı"
when a user tried to view a vehicle they hadn't decoded themselves.
This surfaced as "Veriler yüklenirken bir hata oluştu" on the category
detail page for any vehicle the current user wasn't linked to.

Drop the ownership filter from getById; the userVehicles junction is
now used only for per-user history listing and delete operations.
Verified with Playwright: GET /api/vehicles/.../categories/... was
returning 404 from the ownership check for non-owner users.
2026-05-14 20:17:38 +00:00
Fusion
80596a4ceb feat(FN-285): fix EMEX parallel decode race — always await second promise
Some checks failed
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
Commits merged:
- fix(FN-285): fix EMEX parallel decode race — always await second promise

Files changed:
apps/api/src/vehicles/vehicles.service.spec.ts | 63 ++++++++++++++++++++++++++
 apps/api/src/vehicles/vehicles.service.ts      |  5 +-
 2 files changed, 66 insertions(+), 2 deletions(-)

Fusion-Task-Id: FN-285
2026-05-13 06:56:18 +00:00
Fusion
2ebcdc3734 test(vehicles): add missing redis mock methods exposed by perf(vehicles) commit
Some checks failed
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
c4f6cc1 added this.redis.exists/setNx/incr/expire calls to vehicles.service
(dedup lock + circuit breaker) but vehicles.service.spec.ts redisService
mock was not updated. Result: 1 failing test broke pnpm test, which broke
Fusion merger's in-merge build verification on every subsequent task.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 13:15:47 +00:00
Sase Dev
e4b430f69c feat(analytics): enrich query_logs metadata + query_log_insights view
For continuous optimization we need to attribute slow/failed decodes to
the right cause. query_logs.timings jsonb is now a structured decode-meta
blob, not just stage timings:

- wmi: first 3 chars of VIN (per-brand aggregation)
- result_kind: vehicle / pcat_candidates / emex_candidates / unknown / aborted
- cache_source: db_hit / redis_positive / redis_negative / lock_wait / miss
- candidate_pick: pcat / emex / none (when user picks from candidate modal)
- pcat_car_count, emex_candidate_count (cardinality, drives candidate-modal rate)
- pl24_circuit_open, pl24_skipped (CB state at request time)
- vin_api_used, vin_api timing (NHTSA fallback frequency)

Migration 0003 adds a query_log_insights VIEW that flattens these keys
into typed columns, so ad-hoc SQL doesn't need json operators. New meta
keys appear automatically as NULL; the VIEW stays stable.

docs/analytics-queries.sql has 8 starter queries: cache hit ratio,
per-source latency, slowest WMIs, stage breakdowns, CB/abort frequency,
candidate-modal rate, top failing VINs, dedup effectiveness.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 12:04:23 +00:00
Sase Dev
c4f6cc1caf perf(vehicles): dedup, abort budget, circuit breaker for VIN decode
Production p99 was 18min for failed decodes and 15min for PL24 successes;
same VIN could trigger N parallel 10+ min decodes. Three layered fixes:

- In-flight dedup via Redis SETNX (vin🔒*); concurrent same-VIN requests
  poll the resolve cache instead of re-firing the upstream chain.
- 24h positive cache (vin:resolve:*) and 6h negative cache
  (vin:resolve:neg:*); previously 5min positive / no negative.
- 25s hard abort budget via AbortController; PCAT gets the signal natively
  (AbortSignal.any), PL24/EMEX wrapped with raceWithSignal at the boundary.
  Aborted decodes don't poison the negative cache.
- PCAT/EMEX real race: first definitive single-result wins; the slower
  source is skipped (previously PCAT was always awaited first).
- PL24 circuit breaker: 3 consecutive failures opens a 30s cooldown
  (pl24:cb:cooldown_until); successes reset the counter.
- Stage-level timings in query_logs.timings (jsonb): pcat/emex/pl24/
  lock_wait/cache_hit/aborted. Failed source now logged as "none" or
  "aborted" instead of misleading "corgi".

Verified locally with 3 parallel decodes of a fresh VIN: 1 real decode
(3.59s), 2 lock-waits (3.53s) sharing the result, 4th request 23ms cache
hit. Previously this would have been 3 separate 10+ min PL24 decodes.

Migration 0002 adds query_logs.timings jsonb (NULL default). Must be
applied manually before deploy (deploy.sh does not run db:push).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 11:31:25 +00:00
Fusion
53a0dfab7d feat(FN-186): update all header/nav logo instances from Sase.tr to SASE with tracking-wider (+2 more)
Some checks failed
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
Commits merged:
- fix(FN-186): fix pre-existing Biome formatting error in vehicles.service.spec.ts
- feat(FN-186): complete Step 2 — update i18n tabSasetr keys from Sase.Tr to SASE
- feat(FN-186): complete Step 1 — update all header/nav logo instances from Sase.tr to SASE with tracking-wider

Files changed:
apps/api/src/vehicles/vehicles.service.spec.ts | 38 ++++++++++++++------------
 apps/web/src/messages/en.json                  |  2 +-
 apps/web/src/messages/tr.json                  |  2 +-
 apps/web/src/routes/_auth.tsx                  |  4 +--
 apps/web/src/routes/about.tsx                  |  4 +--
 apps/web/src/routes/blog.tsx                   |  4 +--
 apps/web/src/routes/blog_/$slug.tsx            |  4 +--
 apps/web/src/routes/contact.tsx                |  4 +--
 apps/web/src/routes/dashboard.tsx              |  6 ++--
 apps/web/src/routes/demo.tsx                   |  4 +--
 apps/web/src/routes/index.tsx                  |  4 +--
 apps/web/src/routes/kvkk.tsx                   |  4 +--
 apps/web/src/routes/pricing.tsx                |  4 +--
 apps/web/src/routes/privacy.tsx                |  4 +--
 apps/web/src/routes/terms.tsx                  |  4 +--
 15 files changed, 47 insertions(+), 45 deletions(-)

Fusion-Task-Id: FN-186
2026-05-11 14:13:41 +00: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
adfba6c543 test: bypass pcat/pl24 in VIN resolve — EMEX-only test
Some checks failed
CI / Lint, Typecheck, Test & Build (push) Has been cancelled
Temporarily disable PartsCatalogs and PL24 decode steps to test
EMEX-only VIN resolution speed and reliability.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 13:35:10 +00:00
7a322c5574 fix(service-test): handle emex notFound/error as failures
Some checks failed
CI / Lint, Typecheck, Test & Build (push) Has been cancelled
decodeVinOrCandidates returns { type: "notFound" } or { type: "error" }
instead of null, so data !== null was incorrectly marking these as
success. Now explicitly checks emex result type.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 11:04:43 +00:00
dd75495a1d fix(service-test): show error message when service returns null
Some checks failed
CI / Lint, Typecheck, Test & Build (push) Has been cancelled
testService() was swallowing errors — services like parts-catalogs catch
internally and return null, so the outer try/catch never fired. Now each
service call has its own try/catch, and null responses get an explicit
error message.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 10:56:37 +00:00
866ea42dee fix(service-test): rename response 'data' field to 'result' to avoid api client unwrap conflict
Some checks failed
CI / Lint, Typecheck, Test & Build (push) Has been cancelled
The api client unwraps response.data automatically, which conflicts
with our testService response having its own 'data' field.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 10:26:02 +00:00
03353a703a feat: add service test page for individual VIN decode testing
Some checks failed
CI / Lint, Typecheck, Test & Build (push) Has been cancelled
Admin-only page at /dashboard/service-test with dropdown to test
each VIN decode service (Corgi, PartsCatalogs, PL24, EMEX, VIN API)
individually or the full cascade. Results shown as JSON on page,
no DB writes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 10:12:50 +00:00
465349734b fix: remove extra userId argument from pl24Service.decodeVin call
Some checks failed
CI / Lint, Typecheck, Test & Build (push) Has been cancelled
Deploy / Deploy to Production (push) Has been cancelled
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 13:34:23 +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
72c0de65de docs: update INDEX.md + add catalog module, Ford/PSA legacy catalog, shared vehicles
- CatalogModule: VIN-less PL24 catalog browser (brands, models, categories, parts)
  - Supports P5 Modern (REST) and P4 Legacy (Ford, PSA) catalog architectures
  - Ford variant selector (model-year/engine/gearbox), PSA variant selector (body/engine/gearbox)
  - New API endpoints: ford-config, psa-bodies, psa-engines, psa-gearboxes, brands/:name/catalogs
- Shared vehicles: vehicles table decoupled from users via userVehicles junction table
- PL24 Ford Legacy service: comprehensive HTML-scraping for Ford/PSA/Hyundai/Kia/Nissan/Opel/Volvo
- PL24 types and service updated for P4 Legacy brand support
- Categories/parts service updated for dual FK (vehicleId + catalogVehicleId) pattern
- Catalog browser frontend routes and components
- docs/INDEX.md: updated with all new endpoints, components, hooks, routes (2026-03-02)
- docs/pl24-catalog/: per-brand catalog exploration docs
- scripts/migration-shared-vehicles.sql, pl24-catalog-explorer.js, posthog-dashboards.sh

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 00:31:15 +00:00
Sase Dev
7194393e6d feat: SEO altyapısı — pre-render, meta tags, blog posts, robots/sitemap
- vite-plugin-prerender yerine Playwright tabanlı post-build pre-render scripti
  (apps/web/scripts/prerender.mjs): 10 public route statik HTML'e dönüştürülüyor
- usePageMeta hook: her public route'da özgün title/description/canonical/OG tags
- index.html: favicon.svg, canonical, OG/Twitter Card, geliştirilmiş title+desc
- apps/web/public/: robots.txt, sitemap.xml (10 URL), favicon.svg
- nginx HSTS header eklendi (Strict-Transport-Security)
- Blog post sayfaları: blog_/$slug.tsx (4 tam yazı, 600-800 kelime)
- blog.tsx: post kartlarına Link eklendi
- Homepage: Schema.org JSON-LD (Organization + SoftwareApplication)
- Footer: placeholder href="#" sosyal linkler kaldırıldı
- deploy.sh + deploy.yml: playwright install chromium + prerender adımı

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-22 14:15:35 +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
f2126754a6 feat: add OEM code copy tracking, PostHog analytics, Postal email integration
- Add oem_code_copies table and analytics module for tracking part code copies
- Integrate PostHog for frontend product analytics (VIN decode, OEM copy events)
- Switch email service from stub to Postal API with proper error handling
- Add copy button to parts panel with clipboard + server-side logging
- Add admin copy-logs page with filtering and top-copied-codes view
- Add VIN report endpoint for users to flag unrecognized chassis numbers
- Add Postal email env vars to config schema

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 18:09:07 +00:00
Sase Dev
87d8eea298 feat: onboarding trial flow, Google sign-in, dark mode hotspot fixes
- Move trial creation from auth hook to dedicated /subscriptions/trial endpoint
  with eligibility checks (3-day Full Paket trial)
- Add animated onboarding progress (Remotion) with confetti on completion
- Register redirects to subscription page with welcome flow
- Add Google social login/signup support with config injection
- Improve hotspot overlay visibility in dark mode
- Show "Panele Git" on landing page when authenticated
- Turkish translations for API error messages
- Add toast utility wrapper, UUID generation for auth IDs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 14:53:57 +00:00
Sase Dev
25278d386a feat: landing page CRO revision, demo page, auto-trial, multi-catalog messaging
- Rewrite landing page copy with Jobs-to-be-Done and loss framing
- Add VIN live preview via backend pl24+emex decode chain
- Add comparison table (mobile-responsive), stats, pricing teaser, referral banner
- Replace testimonials with aggregate social proof stats
- Create demo page with 3-step VIN decode flow for unregistered users
- Add public /vehicles/preview/:vin endpoint (no auth required)
- Auto-create 7-day trial subscription on user registration
- Highlight multi-catalog cross-querying advantage in OEM feature and comparison
- Update register page with trial messaging and VIN param support

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-15 00:38:52 +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
996d614d50 feat: admin user creation, Vite migration, dialog fix, pl24 integration
- Add POST /admin/users endpoint with password hashing and role support
- Add user creation dialog to admin users page
- Migrate web from Next.js to Vite + TanStack Router
- Fix Dialog component positioning for Tailwind CSS v4
- Add @source directive for @sase/ui package scanning
- Add pl24 integration parsers and vehicle decode flow
- Backup old Next.js app to apps/web-nj

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 14:24:58 +00:00
Sase Dev
8fb7bbbaca test: add comprehensive unit tests for all API services and guards
Add 11 new test files covering roles guard, brand-access guard, users,
brands, plans, payments, vehicles, categories, parts, referrals, and
admin services. Total test count increases from ~52 to 164, all passing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 04:24:55 +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