Commit Graph

252 Commits

Author SHA1 Message Date
Semih
a8a2f7f58e chore: remove playwright repro scratch file
Fusion-Task-Id: FN-406
Fusion-Task-Lineage: 9616ae1a-9fa5-47cc-bf0d-3616eb4a0877
2026-05-16 23:54:18 +00:00
Semih
bd8e405843 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.

Fusion-Task-Id: FN-406
Fusion-Task-Lineage: 9616ae1a-9fa5-47cc-bf0d-3616eb4a0877
2026-05-16 23:54:18 +00:00
Semih
6b83cfe77d chore: remove playwright repro scratch file
Fusion-Task-Id: FN-406
Fusion-Task-Lineage: 9616ae1a-9fa5-47cc-bf0d-3616eb4a0877
2026-05-16 23:54:18 +00:00
Semih
d1c698da47 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.

Fusion-Task-Id: FN-406
Fusion-Task-Lineage: 9616ae1a-9fa5-47cc-bf0d-3616eb4a0877
2026-05-16 23:54:18 +00:00
Semih
83f790d02f chore: remove playwright repro scratch file
Fusion-Task-Id: FN-406
Fusion-Task-Lineage: 9616ae1a-9fa5-47cc-bf0d-3616eb4a0877
2026-05-16 23:54:18 +00:00
Semih
497e03a231 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.

Fusion-Task-Id: FN-406
Fusion-Task-Lineage: 9616ae1a-9fa5-47cc-bf0d-3616eb4a0877
2026-05-16 23:54:18 +00:00
a2cbac2197 Merge pull request #21 — feat(FN-403): parts panel manifest 2026-05-16 08:24:12 +00:00
Fusion
713ef987a0 feat(FN-403): Phase-1 parts panel selector & route manifest for FN-368
Commits merged:
- feat(FN-403): Phase-1 parts panel selector & route manifest for FN-368

Files changed:
MANIFEST-FN-403.md | 164 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 164 insertions(+)

Fusion-Task-Id: FN-403
2026-05-16 11:24:00 +03:00
8414e08213 Merge pull request #20 — feat(FN-401): blocker note 2026-05-16 08:21:43 +00:00
Fusion
68c44000a1 feat(FN-401): blocker note — planner/reviewer prompts live in Fusion platform, not sase worktree
Commits merged:
- docs(FN-401): blocker note — planner/reviewer prompts live in Fusion platform, not sase worktree

Files changed:
docs/clarification/FN-401-blocker.md | 50 ++++++++++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)

Fusion-Task-Id: FN-401
2026-05-16 11:21:32 +03:00
d7eb861673 Merge pull request #19 — feat(FN-400): selector manifest 2026-05-16 08:15:39 +00:00
Fusion
759e5c8e9a feat(FN-400): Phase-1 selector & route manifest for FN-367/FN-368
Commits merged:
- feat(FN-400): Phase-1 selector & route manifest for FN-367/FN-368

Files changed:
MANIFEST.md | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 114 insertions(+)

Fusion-Task-Id: FN-400
2026-05-16 11:15:24 +03:00
cf8f7c0b04 Merge pull request #18 — feat(FN-399): PostHog cross-session funnel audit 2026-05-16 08:07:42 +00:00
Fusion
584cda2b6c feat(FN-399): cross-session funnel attribution audit + regression check
Commits merged:
- feat(FN-399): cross-session funnel attribution audit + regression check

Files changed:
docs/product/funnel-audit-p0-cro-2026-05.md |  52 +++++++
 scripts/check-posthog-identified-only.mjs   | 220 ++++++++++++++++++++++++++++
 2 files changed, 272 insertions(+)

Fusion-Task-Id: FN-399
2026-05-16 11:07:29 +03:00
8685196ab8 Merge pull request #17 — chore(payments): Stripe-only 2026-05-16 08:04:01 +00:00
Fusion
65daf99b2e chore(payments): remove EFT/bank-transfer method, keep Stripe only
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
Removes the EFT (havale) payment surface across API, web, i18n, and docs.
Card payment via Stripe is now the only checkout path.

API (apps/api/src):
- Delete payments/bank-accounts/ module (controller + service + module)
- payments.service: drop EFT methods (createEftPayment, uploadEftReceipt,
  approveEft, rejectEft, getActiveBankInfo, getPendingEftPayments) and the
  BankAccountsService dependency
- payments.controller: drop /payments/eft, /payments/eft/:id/{receipt,approve,reject},
  /payments/bank-info, /payments/pending; keep /payments/me
- payments.module: drop BankAccountsModule import
- admin.service: drop pending EFT counter from getDashboardStats; drop
  getPendingPayments (admin EFT approval list)
- admin.controller: drop /admin/payments/pending endpoint
- admin.service.spec: drop the getPendingPayments + pendingPayments assertions

Web (apps/web/src):
- Delete components/payment/bank-transfer-card.tsx
- Delete routes/dashboard/admin/payments.tsx (EFT approval page); regenerate
  routeTree.gen.ts
- subscription/index.tsx: drop EFT tab from PaymentMethodSection, drop the
  paymentMethod state + handleEftCompleted, simplify ConfirmationCard to the
  Stripe-only path, drop unused imports (Tabs, BankTransferCard, Building2)
- billing.tsx: drop "eft" from method filter chips; keep methodLabels.eft and
  the legacy receipt download so historical EFT records still display
- dashboard.tsx + admin/index.tsx: drop /dashboard/admin/payments from the
  sidebar + admin quick-link grid; trim unused icon imports; KEYS_6 → KEYS_5
  for the now-5-card admin stats skeleton
- messages/{tr,en}.json: strip every EFT-only key under payment.* (eftTransfer,
  eftConfirmationDescription, eftPaid, eftStatus, bank.*, uploadReceipt* etc.)

Schema (apps/api/src/database/schema):
- bankAccounts table + payments.bankAccountId column are kept as-is: legacy
  EFT payments remain visible on the billing page and the schema preserves
  historical records.

Docs:
- README.md: "Stripe (kart) + EFT" → "Stripe (kart)"
- CLAUDE.md: stack table + PaymentsModule row + payments table note + route
  list updated; admin EFT approval route removed

Verification:
- pnpm typecheck: green (api + web + shared + config + ui)
- pnpm lint: green
- pnpm test: 20 web tests pass, 173 api tests pass
2026-05-16 11:03:30 +03:00
1278ef679d Merge pull request #16 — feat(FN-395): P1 candidate shortlist 2026-05-16 08:01:36 +00:00
Fusion
2ecc4fab8f feat(FN-395): P1 candidate shortlist 2026-05-15 (CEO deliverable)
Commits merged:
- docs(FN-395): P1 candidate shortlist 2026-05-15 (CEO deliverable)

Files changed:
docs/product/p1-shortlist-2026-05-15.md | 82 +++++++++++++++++++++++++++++++++
 1 file changed, 82 insertions(+)

Fusion-Task-Id: FN-395
2026-05-16 11:01:24 +03:00
09dba7d6ff Merge pull request #15 — broaden leaf detection 2026-05-16 07:30:56 +00:00
33605ead25 fix(categories): broaden leaf detection to all /extern/*/{vin,mdl}_items endpoints
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
The leaf-path checks only matched /servicepart/vin_items literally, but
PL24's P5 modern catalog ships the same shape under /chemicals/vin_items,
/accessories/vin_items, /chemicals/mdl_items, etc. When user clicked a
"Rötuşkalemseti" (touch-up paint set) category whose linkPath was
/p5vwag/extern/chemicals/vin_items, the code drilled in, treated each
paint chemical's per-part URL (?partno=LLSMAX010) as a sub-category,
and inserted 228 ghost rows under it. Replace the literal substring
match with a regex that covers the whole /extern/{kind}/(vin|mdl)_items
pattern; apply to both the user-vehicle (categories.service) and the
catalog (catalog.service) flows.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 10:30:46 +03:00
4a72f2482b Merge pull request #14 — fix(pl24): Ford VIN flow 2026-05-16 07:04:52 +00:00
af4142077f fix(categories): treat image-board.action linkPaths as leaves in user-vehicle flow
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
getChildren had a leaf-detection whitelist that covered BOM/partinfo paths
but missed PL24's image-board.action (and the VIN variant). When users
clicked into a vin-image-board.action leaf, fetchSubGroupsByPath ran on
its HTML, parsed the BOM rows' jsonUrl="...json-vin-bom-detail.action..."
attributes as if they were sub-groups, and inserted 10+ ghost category
rows under the leaf — each pointing to a per-part endpoint that's not
a sub-group at all. Drilling into one of those ghosts then surfaced the
"0 parça listeleniyor" empty state instead of the real BOM table.

Add both image-board.action and json-vin-bom-detail.action to the leaf
detection list so the flow short-circuits and getCategoryWithParts
handles them via fetchPartsByPath as designed.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 10:03:59 +03:00
2bf5e1622c fix(pl24): pass Ford VIN BOM detail URL through fetchP4Page baseUrl prefix
fetchFordVinBomParts was forwarding the relative HTML jsonUrl with
isFullUrl=true, which made undici try to parse \`/ford/fordp_parts/…\`
as an absolute URL and throw "Failed to parse URL" for every PNC row.
The Hyundai BOM expander next door calls fetchP4Page with the default
isFullUrl=false (relative path) — match that.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 10:03:59 +03:00
be3fb2a4b5 feat(pl24): wire Ford/Volvo VIN-decode flow end-to-end via json-vin endpoints
VIN-decoded Ford P/T and Volvo legacy vehicles used to land on an empty
category page: the .action HTML the decoder scraped only carried header
breadcrumbs (Portal / Model seçimi / VIN). The real catalog hangs off
three JSON endpoints that the partslink24 UI calls in the background
once a VIN session is established. None of them need mode/upds/JSESSIONID
beyond the standard PL24TOKEN cookie. Plumb the whole chain so a user
who decoded a VIN sees real Turkish part categories and OEM part
numbers in the user-vehicle flow:

  json-vin-main-group.action   → real top-level groups (8 for Mondeo)
  json-vin-sub-group.action    → 58 leaf subgroups (filters subheaders)
  vin-image-board.action       → BOM table with pncHierCode + jsonUrl
  json-vin-bom-detail.action   → final OEM partno entries (per variant)

Schema image fetch reuses the existing image-ticket extractor since the
ticket URL lives in the same jsIlluData payload as Hyundai/Opel/Volvo.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 10:03:59 +03:00
032217716e fix(pl24): drop P4 nav-crumb links from decoded categories
VIN-group HTML for Ford/Volvo legacy services exposes the header
breadcrumb links (Portal / Model seçimi / current VIN) via the same
.action pattern the parser relied on, so they were being persisted as
"part categories" — users saw three useless rows instead of real groups.
The PSA flow already documented this trap and bypassed rawData; extend
the same defense to the rest of P4 legacy (parser-side + categories
insert fallback).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-16 10:03:59 +03:00
a9611b913e Merge pull request 'dev' (#13) from dev into main
Reviewed-on: #13
2026-05-14 20:54:54 +00:00
Semih
de84d8d267 fix(schema-viewer): drop empty schema panel for image-less BOM overviews
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
PL24's bomOverviewlist widget (PR-code-filtered overview tables like
"Alternatöre genel bakış · Start-Stop modu bulunan araçlar için
[PR:7L6,7L8]") returns parts but no illustration — upstream genuinely
has no schema for these. Previously the 60% left panel rendered the
text "Sema goruntusu bulunamadi", which reads like a failure and
wastes most of the layout for what is actually a complete result.

When schemaPic is null, skip the schema panel entirely and let the
parts list take the full container width. The parts panel already
handles its own header/empty state, so no other adjustment needed.
2026-05-14 20:47:43 +00:00
Semih
7ffff32cac chore(pl24): remove [imgdbg] diagnostic log
Diagnostic served its purpose: confirmed that PL24 bomOverviewlist
URLs (e.g. illustrationId=4336125, "Alternatöre genel bakış" with
PR-code filters) return only a records array with no images field —
upstream genuinely has no schema illustration for these overview
tables. Frontend UX for this case is handled separately.
2026-05-14 20:47:03 +00:00
Semih
7f0f17580e chore(pl24): log full response shape when images field is missing (temp diagnostic) 2026-05-14 20:33:24 +00:00
Semih
cf82e49678 chore: remove playwright repro scratch file 2026-05-14 20:17:43 +00: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
Semih
47f76e47d2 fix(FN-373): stop stack reset on every render in CategoryGrid
useTranslation returns a fresh `t` each render, so including it in the
useEffect deps caused the effect to re-fire continuously, resetting the
drill-down stack immediately after handleSelect pushed a child level.
Result: clicking a parent category in grid view did nothing — no API
call, no UI change, no navigation. Reproduced via Playwright on
dev.sase.tr.

Drop `t` from the dep array (key is static; locale changes mid-session
are rare and acceptable to render stale until the next prop change).
2026-05-14 20:02:14 +00:00
Fusion
6c28688283 feat(FN-373): grid view drill-down for parent categories (+1 more)
Commits merged:
- chore(FN-373): verify grid drill-down lint + typecheck clean
- fix(FN-373): grid view drill-down for parent categories

Files changed:
.../src/components/categories/category-grid.tsx    | 175 ++++++++++++++++-----
 apps/web/src/messages/en.json                      |   3 +
 apps/web/src/messages/tr.json                      |   3 +
 3 files changed, 138 insertions(+), 43 deletions(-)

Fusion-Task-Id: FN-373
2026-05-14 18:56:08 +00:00
Fusion
0ce68a7b99 feat(FN-368): parts panel loading state, inert unavailable rows, escape hatch (gitea #10)
Commits merged:
- fix(FN-368): parts panel loading state, inert unavailable rows, escape hatch (gitea #10)

Files changed:
.../schema/__tests__/parts-panel.test.tsx          | 151 ++++++++++++++
 apps/web/src/components/schema/parts-panel.tsx     | 230 ++++++++++++---------
 apps/web/src/components/schema/schema-viewer.tsx   |   7 +-
 3 files changed, 291 insertions(+), 97 deletions(-)

Fusion-Task-Id: FN-368
2026-05-14 18:43:20 +00:00
0b03415997 Merge pull request 'feat(FN-367): add inline retry affordance after VIN decode failure (FN-367, gitea #11)' (#12) from dev into main
Reviewed-on: #12
2026-05-14 14:42:44 +00:00
Fusion
e274e02c23 feat(FN-367): add inline retry affordance after VIN decode failure (FN-367, gitea #11)
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
Commits merged:
- fix(web): add inline retry affordance after VIN decode failure (FN-367, gitea #11)

Files changed:
apps/api/src/telemetry/__tests__/telemetry.spec.ts |   2 +-
 .../src/routes/__tests__/dashboard-search.test.tsx | 172 +++++++++++++++++++++
 apps/web/src/routes/dashboard/search.tsx           | 145 ++++++++++-------
 3 files changed, 266 insertions(+), 53 deletions(-)

Fusion-Task-Id: FN-367

Fusion-Task-Lineage: 5dccf49f-5c77-4fe4-ae2d-0273016d517d
2026-05-14 13:55:36 +00:00
d97c04c933 Merge pull request 'dev' (#9) from dev into main
Reviewed-on: #9
2026-05-14 10:42:27 +00:00
Fusion
a0deefd4b2 chore(remotion): acknowledge Remotion license on Player instances
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
Suppresses the 'license required' console warning on the homepage.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 10:40:57 +00:00
Fusion
d59451968b chore(gitignore): ignore fusion agent runlogs and wrangler local state
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 10:34:16 +00:00
e1b1920e7a Merge pull request 'dev' (#8) from dev into main
Reviewed-on: #8
2026-05-14 10:32:17 +00:00
Fusion
09901899d1 fix(csp): allow data: media for Remotion player audio
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 10:31:12 +00:00
Fusion
36d041d514 fix(csp,faro): allow t.sase.tr in CSP and proxy /collect/ to Grafana Cloud
CSP was blocking PostHog scripts/connections (t.sase.tr) and the theme-FOUC
inline script in index.html. Faro /collect/ requests were aborting because
the bare-metal nginx route disappeared during the Coolify migration.

- Add https://t.sase.tr to scriptSrc + connectSrc
- Add sha256 hash for the theme-FOUC inline script in index.html
- Exclude /collect/* from the /api global prefix
- Add FaroCollectController that forwards POST /collect/:id to
  faro-collector-prod-eu-west-2.grafana.net (overridable via FARO_UPSTREAM)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 10:08:18 +00:00
Fusion
5bd5325367 feat(FN-356): add checkout_started PostHog event to subscription checkout flow (+1 more)
Commits merged:
- chore(FN-356): verify checkout_started event is in place
- feat(FN-356): add checkout_started PostHog event to subscription checkout flow

Files changed:
apps/web/src/routes/dashboard/subscription/index.tsx | 4 ++++
 1 file changed, 4 insertions(+)

Fusion-Task-Id: FN-356
2026-05-14 10:00:40 +00:00
05f6f9072a Merge pull request 'docs(readme): spacing tweak — measure cache-enabled dev deploy speed' (#7) from dev into main
Reviewed-on: #7
2026-05-14 09:55:41 +00:00
Fusion
69d07fc488 docs(readme): spacing tweak — measure cache-enabled dev deploy speed
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 09:34:17 +00:00
448cc021dc Merge pull request 'docs(readme): add staging URL — gitea deploy flow smoke test' (#4) from dev into main
Reviewed-on: #4
2026-05-14 08:58:36 +00:00
Fusion
97b2973eee docs(readme): add staging URL — gitea deploy flow smoke test
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-14 08:56:28 +00:00
854dd63d63 Merge pull request 'dev' (#3) from dev into main
Reviewed-on: #3
2026-05-14 08:45:48 +00:00
Fusion
12bc1228b9 ci: drop deploy.yml + sync-dev-to-gitea.yml — pipeline now Gitea-only
Some checks failed
QA Gate (P0/P1) / Test affected app (pull_request) Has been cancelled
Gitea (git.semih.ai) is the canonical remote. Coolify pulls from Gitea
and triggers builds via Gitea webhooks. Deployment notifications come
from Coolify's built-in Telegram integration (team-level, configured
2026-05-14).

What used to be done by GH Actions:
- deploy.yml (push main → SSH → PM2 → bare-metal sase.tr)
- sync-dev-to-gitea.yml (mirror github/dev → gitea/dev)

What replaces it:
- Push to gitea/main → Coolify webhook → sparkling-snake (production env, prod-iskelet ready)
- Push to gitea/dev  → Coolify webhook → good-gerenuk (staging env, dev.sase.tr)
- Both deploys notified via Coolify → Telegram (chat 7840804807)

qa-gate.yml retained for now (PR test gating); will revisit when Gitea
Actions / Drone are wired or removed if obsolete.
2026-05-14 07:47:52 +00:00
Fusion
3267984395 ci: Telegram notify on prod deploy + dev→Gitea sync (success/fail with commit info)
Some checks failed
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
2026-05-14 06:38:12 +00:00