Sase Dev
492780d001
fix(csp): allow data: media for Remotion player audio
...
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-14 10:29:25 +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
Fusion
906eef148d
feat(FN-346): add CLS regression test for skeleton plan grid (+1 more)
...
Commits merged:
- feat(FN-346): add grid-parity integration test for skeleton CLS regression
- feat(FN-346): add CLS regression test for skeleton plan grid
Files changed:
.../subscription/__tests__/cls-regression.test.tsx | 128 +++++++++++++++++++
.../subscription/__tests__/grid-parity.test.tsx | 141 +++++++++++++++++++++
.../src/routes/dashboard/subscription/index.tsx | 4 +-
3 files changed, 271 insertions(+), 2 deletions(-)
Fusion-Task-Id: FN-346
2026-05-14 05:09:47 +00:00
Fusion
aaf2e763cb
feat(FN-345): fix skeleton layout shift, dialog overflow, and safe-area padding (+1 more)
...
Commits merged:
- fix(FN-345): add mobile-safe max-width to cancel confirm dialog
- fix(FN-345): fix skeleton layout shift, dialog overflow, and safe-area padding
Files changed:
apps/web/src/routes/dashboard/subscription/index.tsx | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
Fusion-Task-Id: FN-345
2026-05-14 03:05:45 +00:00
Fusion
561b02b3d2
feat(FN-343): remove lingering iyzico references after Stripe migration (+1 more)
...
Commits merged:
- chore(FN-343): remove lingering iyzico references from docs, config, and scripts
- feat(FN-343): remove lingering iyzico references after Stripe migration
Files changed:
CLAUDE.md | 10 +++++-----
README.md | 2 +-
apps/api/src/database/schema/core.ts | 1 +
apps/web/src/messages/en.json | 1 -
apps/web/src/messages/tr.json | 1 -
apps/web/src/routes/dashboard/billing.tsx | 6 +++---
docker-compose.coolify.yml | 5 ++---
docs/INDEX.md | 27 ++++++++++++-------------
knowledge.md | 30 ++++++++++++++--------------
packages/shared/src/constants/error-codes.ts | 1 -
packages/shared/src/index.ts | 1 -
packages/shared/src/types/payment.ts | 12 +----------
scripts/fn342-pw-verify.mjs | 2 +-
scripts/validate-env.sh | 3 +--
14 files changed, 43 insertions(+), 59 deletions(-)
Fusion-Task-Id: FN-343
2026-05-14 02:31:42 +00:00
Sase Dev
02bf7342a1
fix(subscription): recover stepper when a pending checkout is abandoned
...
Deploy / Deploy to Production (push) Has been cancelled
A user who picked a plan + brands, clicked the checkout button to
create the pending subscription, then closed the tab without paying
came back to a frozen "Mevcut Plan · Bekliyor" card with no payment
button and no way to edit. Status was "pending", which my conditional
treated as an active subscription and routed away from the stepper.
Frontend
- hasActiveSub narrowed to active|cancelled only. Pending users now
see the stepper again.
- New effect pre-fills selectedPlanKey, selectedBrandIds,
billingPeriod from the pending row on first render and jumps
straight to the payment step.
- New PendingPaymentBanner at the top of the stepper with
"Odemeye devam et" (scrolls + sets step=payment) and "Vazgec"
(calls cancel-pending then resets selection).
Backend
- subscriptions.service.create() auto-expires existing pending
rows for the user before inserting a new one — abandoned checkouts
no longer accumulate and a fresh attempt with a different plan
doesn't 409.
- New PATCH /subscriptions/cancel-pending + service method for
the banner's explicit cancel action.
i18n: subscription.pendingBanner.* (tr/en).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-13 22:57:13 +00:00
Sase Dev
9c05a05a7a
fix(drizzle): register 0004_hot_quicksilver in migration journal
...
The 0004 migration file shipped in 6a0b36a but _journal.json did not
include its entry, so the hash-based migrate runner saw "0 applied,
4 already applied" on the previous deploy. Append idx 4 so the next
deploy picks it up.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-13 22:46:54 +00:00
Sase Dev
6a0b36a7a0
feat: replace Iyzico with Stripe + single-page subscription stepper
...
Subscription/checkout flow rewritten end-to-end. The plan-card "Devam Et"
button silently wiped brand selection on re-click and the actual proceed
button lived offscreen — fixed by collapsing plan/brands/payment/confirm
into a single vertical stepper with one sticky CTA.
Backend
- Stripe Hosted Checkout (`/payments/stripe/checkout`) + webhook
(`/payments/stripe/webhook`, raw body) replacing the stubbed Iyzico
module. Webhook activates subscription on `checkout.session.completed`,
expires the pending subscription on cancel/expire so users can retry.
- New `bank_accounts` table — multiple rows, single `is_active` enforced
by a partial unique index. Admin CRUD under `/admin/bank-accounts`
with multipart QR upload to MinIO; atomic `/activate` swap in a
transaction; `GET /payments/bank-info` returns the active row.
- `payments` gains `stripe_session_id`, `stripe_payment_intent_id`,
`bank_account_id`. EFT flow now reads the active bank account at
payment time and stores the FK for reconciliation.
- Env: `IYZICO_*` removed, `STRIPE_*` added (validated by zod schema).
- `main.ts` `rawBody: true` for Stripe signature verification.
- Drizzle 0003 snapshot id collision fixed (VIEW-only migration shared
prevId with 0002, blocking new generates).
Frontend
- `/dashboard/subscription` rewritten as a 4-step vertical stepper with
step-aware sticky bottom CTA; plan re-selection is idempotent and
preserves brand state. `/dashboard/subscription/pay` deleted; Stripe
returns to the same page via `?stripe=success|cancelled` and the UI
polls `/subscriptions/me` until the webhook activates the row.
- New components: `bank-transfer-card.tsx` (DB-driven IBAN + Kolay Adres
+ uploaded QR image + receipt upload) and `stripe-checkout-button.tsx`.
- Active subscription view, trial onboarding/urgency banner, downgrade
and cancel dialogs preserved.
- TR/EN i18n: new `subscription.steps.*`, `subscription.stickyCta.*`,
`payment.stripe.*`, `payment.bank.*`; provider label updated.
PostHog: `method: "iyzico"` → `"stripe"`; new events `iban_copied`,
`kolay_adres_copied`, `qr_viewed`, `eft_initiated`,
`stripe_redirect_returned`.
Deploy runs `db:migrate` which applies 0004_hot_quicksilver
(additive: new table + nullable columns; safe to apply on prod).
Operator must add `STRIPE_SECRET_KEY`, `STRIPE_PUBLISHABLE_KEY`,
`STRIPE_WEBHOOK_SECRET` to env and create the first
`bank_accounts` row via the admin endpoint before the bank tab works.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-13 22:42:28 +00:00
Sase Dev
0b6d4bb0a7
feat(analytics): enrich PostHog VIN/parts/subscription events (SASE-PH-001 Faz 0/1 additive subset)
...
Per sase-posthog-events-prd.md, additive-only pass (no renames, no dead-feature events):
- search.tsx: add search_input_focused, search_input_validation_failed,
search_paste_detected, search_history_item_selected; track query_source
(manual|paste|history) and propagate to vin_decoded/success/error; add
response_time_ms, source, status_code on success/error; add selected_index,
candidates_count, time_to_select_ms to vin_decode_candidate_selected.
- parts-panel.tsx: add parts_panel_viewed with vehicle_id, category_id,
parts_count, has_prices, available_groups_count (one-shot per mount).
- subscription/index.tsx: enrich plan_selected (period, from_plan, status),
checkout_started (from_plan, brands_count, trial_available, status),
subscription_cancelled (from_plan, billing_period, status_before_cancel,
days_since_start, had_downgrade_offer).
2026-05-13 22:05:50 +00:00
Sase Dev
5b9af5a6a5
fix(web): hoist hooks above early returns in TrialUrgencyBanner
...
useEffect and useCallback were declared after three `return null` guards,
so when a user's subscription transitioned into the trial+≤7-days window
React saw more hooks than the previous render and crashed with #310 .
Hoisted all hooks above the single guard return; render and dismiss
behavior unchanged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-13 21:41:16 +00:00
Fusion
c8aac14d56
feat(FN-306): change trial banner threshold to ≤7 days and rename PostHog events
...
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
Deploy / Deploy to Production (push) Has been cancelled
Commits merged:
- feat(FN-306): complete Step 1 — change trial banner threshold to ≤7 days and rename PostHog events
Files changed:
apps/web/src/components/trial-urgency-banner.tsx | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
Fusion-Task-Id: FN-306
2026-05-13 09:00:22 +00:00
Fusion
4cb715f1b4
feat(FN-300): add trial urgency banner to subscription page
...
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
Commits merged:
- feat(FN-300): complete Step 1 — add trial urgency banner to subscription page
Files changed:
.../src/routes/dashboard/subscription/index.tsx | 107 +++++++++++++++++++++
1 file changed, 107 insertions(+)
Fusion-Task-Id: FN-300
2026-05-13 08:13:26 +00:00
Fusion
3dd4dc2f77
feat(FN-297): add social proof impression tracking to landing page testimonials (+2 more)
...
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
Commits merged:
- docs(FN-297): update FN-275 audit with social proof event locations
- fix(FN-297): format IntersectionObserver mock in test file
- feat(FN-297): add social proof impression tracking to landing page testimonials
Files changed:
apps/web/src/routes/__tests__/index.test.tsx | 7 ++
apps/web/src/routes/index.tsx | 111 +++++++++++++++++++++++++--
docs/product/funnel-audit-p1-cro-2026-05.md | 19 ++++-
3 files changed, 127 insertions(+), 10 deletions(-)
Fusion-Task-Id: FN-297
2026-05-13 07:28:34 +00:00
Fusion
80596a4ceb
feat(FN-285): fix EMEX parallel decode race — always await second promise
...
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
6162a8f787
feat(FN-283): add PostHog events to TrialUrgencyBanner
...
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
Commits merged:
- feat(FN-283): add PostHog events to TrialUrgencyBanner
Files changed:
apps/web/src/components/trial-urgency-banner.tsx | 34 ++++++++++++++++++++++--
1 file changed, 32 insertions(+), 2 deletions(-)
Fusion-Task-Id: FN-283
2026-05-13 06:41:04 +00:00
Fusion
c0fef5921b
feat(FN-282): add social proof impression tracking to testimonial and trust components
...
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
Commits merged:
- feat(FN-282): add social proof impression tracking to testimonial and trust components
Files changed:
apps/web/src/routes/_auth.tsx | 42 +++++++++++-
.../src/routes/dashboard/subscription/index.tsx | 80 ++++++++++++++++++++--
2 files changed, 117 insertions(+), 5 deletions(-)
Fusion-Task-Id: FN-282
2026-05-13 06:36:16 +00:00
Fusion
d855b564bf
feat(FN-281): add payment_success and payment_failed PostHog events (+1 more)
...
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
Commits merged:
- fix(FN-281): make result search param truly optional to fix typecheck
- feat(FN-281): add payment_success and payment_failed PostHog events
Files changed:
apps/api/package.json | 1 +
apps/api/src/app.module.ts | 2 +
apps/api/src/payments/payments.service.spec.ts | 99 +-
apps/api/src/payments/payments.service.ts | 40 +
apps/api/src/posthog/posthog.module.ts | 9 +
apps/api/src/posthog/posthog.service.ts | 64 ++
.../web/src/components/payment/payment-content.tsx | 24 +-
apps/web/src/routeTree.gen.ts | 1110 ++++++++++----------
apps/web/src/routes/dashboard/subscription/pay.tsx | 24 +-
packages/config/src/index.ts | 4 +
pnpm-lock.yaml | 30 +
11 files changed, 827 insertions(+), 580 deletions(-)
Fusion-Task-Id: FN-281
2026-05-13 06:30:58 +00:00
Fusion
7707443be6
feat(FN-278): add yearly_toggle_clicked PostHog events and 4-col skeleton grid
...
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
- Track yearly_toggle_clicked PostHog event on billing period toggle (monthly/yearly)
- Update skeleton grid from 2-col to 4-col layout with additional skeleton cards
- Add regression tests verifying analytics tracking and skeleton grid rendering
Fusion-Task-Id: FN-278
2026-05-13 05:55:25 +00:00
Fusion
cc2bfbe2b0
feat(FN-211): normalize typography on subscription page
...
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
Commits merged:
- fix(FN-211): normalize typography on subscription page
Files changed:
apps/web/src/routes/dashboard/subscription/index.tsx | 20 +++++++++++---------
1 file changed, 11 insertions(+), 9 deletions(-)
Fusion-Task-Id: FN-211
2026-05-13 05:30:19 +00:00
Fusion
fa49c20d09
feat(FN-263): normalize typography on subscription page (+2 more)
...
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
Commits merged:
- feat(FN-263): normalize typography on subscription page
- chore(FN-263): apply Biome formatting fix for long className lines
- feat(FN-263): normalize typography on subscription page
Files changed:
.../src/routes/dashboard/subscription/index.tsx | 116 +++++++++++----------
1 file changed, 62 insertions(+), 54 deletions(-)
Fusion-Task-Id: FN-263
2026-05-13 04:51:56 +00:00
Fusion
f0bfe6ec8b
feat(FN-280): add cancel-save flow PostHog events — cancel_flow_viewed and cancel_save_clicked
...
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
Commits merged:
- feat(FN-280): add cancel-save flow PostHog events — cancel_flow_viewed and cancel_save_clicked
Files changed:
apps/web/src/routes/dashboard/subscription/index.tsx | 17 ++++++++++++++++-
1 file changed, 16 insertions(+), 1 deletion(-)
Fusion-Task-Id: FN-280
2026-05-13 03:58:39 +00:00
Fusion
fb3fa6dff4
feat(FN-277): add @sase/shared resolve alias to vitest configs for both api and web (+1 more)
...
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
Commits merged:
- docs(FN-277): update Pre-Merge QA Gate policy with explicit sub-bullets per spec
- fix(FN-277): add @sase/shared resolve alias to vitest configs for both api and web
Files changed:
.fusion/memory/MEMORY.md | 14 +++++++++-----
apps/api/vitest.config.ts | 6 ++++++
apps/web/vitest.config.ts | 1 +
3 files changed, 16 insertions(+), 5 deletions(-)
Fusion-Task-Id: FN-277
2026-05-13 02:07:02 +00:00
Fusion
6ae26e7a62
feat(FN-213): a11y audit — fix plan card double-focus trap, trust bar ARIA, color contrast
...
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
Commits merged:
- feat(FN-213): a11y audit — fix plan card double-focus trap, trust bar ARIA, color contrast
Files changed:
apps/web/src/routes/dashboard/subscription/__tests__/index.test.tsx | 1 +
1 file changed, 1 insertion(+)
Fusion-Task-Id: FN-213
2026-05-13 01:54:30 +00:00
Fusion
e94c1e4267
feat(FN-271): implement a11y fixes (plan card focus, trust bar ARIA, color contrast)
...
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
Commits merged:
- feat(FN-271): complete Step 1 — implement a11y fixes (plan card focus, trust bar ARIA, color contrast)
Files changed:
.../subscription/__tests__/index.test.tsx | 87 ++++++++++++--------
.../src/routes/dashboard/subscription/index.tsx | 94 ++++++++++++++++++----
2 files changed, 133 insertions(+), 48 deletions(-)
Fusion-Task-Id: FN-271
2026-05-13 00:32:58 +00:00
Fusion
03e401b133
feat(FN-217): lazy-load canvas-confetti via dynamic import to avoid bloating subscription bundle (+2 more)
...
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
Commits merged:
- fix(FN-217): fix import sort order (lint)
- fix(FN-217): convert @sase/shared to emit ESM for Vite/Rollup build compatibility
- fix(FN-217): lazy-load canvas-confetti via dynamic import to avoid bloating subscription bundle
Files changed:
apps/web/src/routes/dashboard/subscription/index.tsx | 13 +++++++------
apps/web/src/routes/pricing.tsx | 2 +-
packages/shared/package.json | 5 +++--
packages/shared/tsconfig.json | 4 ++--
4 files changed, 13 insertions(+), 11 deletions(-)
Fusion-Task-Id: FN-217
2026-05-12 22:57:32 +00:00
Fusion
3dfd0de0c6
feat(FN-216): simplify plan card click handler — remove duplicate Button.onClick
...
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
Commits merged:
- fix(FN-216): simplify plan card click handler — remove duplicate Button.onClick
Files changed:
apps/web/src/routes/dashboard/subscription/index.tsx | 4 ----
1 file changed, 4 deletions(-)
Fusion-Task-Id: FN-216
2026-05-12 22:31:53 +00:00
Fusion
479000d4a1
feat(FN-215): use shared formatTRY singleton instead of per-call Intl.NumberFormat
...
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
Commits merged:
- perf(FN-215): use shared formatTRY singleton instead of per-call Intl.NumberFormat
Files changed:
apps/web/src/components/payment/payment-content.tsx | 9 +--------
apps/web/src/routes/dashboard/admin/index.tsx | 11 ++---------
apps/web/src/routes/dashboard/admin/payments.tsx | 11 ++---------
apps/web/src/routes/dashboard/admin/users.tsx | 11 ++---------
apps/web/src/routes/dashboard/billing.tsx | 9 ++-------
apps/web/src/routes/dashboard/subscription/index.tsx | 10 +---------
apps/web/src/routes/pricing.tsx | 10 +---------
7 files changed, 11 insertions(+), 60 deletions(-)
Fusion-Task-Id: FN-215
2026-05-12 22:28:23 +00:00
Fusion
e97aab6fe4
feat(FN-214): extract brandLimit 999 magic number to FULL_PLAN_BRAND_LIMIT constant in @sase/shared (+1 more)
...
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
Commits merged:
- fix(FN-214): add missing import for FULL_PLAN_BRAND_LIMIT in subscription/index.tsx
- feat(FN-214): extract brandLimit 999 magic number to FULL_PLAN_BRAND_LIMIT constant in @sase/shared
Files changed:
apps/web/src/routes/dashboard/subscription/index.tsx | 16 +++++++++++-----
apps/web/src/routes/pricing.tsx | 3 ++-
packages/shared/src/constants/plans.ts | 3 +++
packages/shared/src/index.ts | 2 +-
4 files changed, 17 insertions(+), 7 deletions(-)
Fusion-Task-Id: FN-214
2026-05-12 22:21:14 +00:00
Fusion
1a90641529
feat(FN-210): add compact testimonials strip below trust bar on landing page
...
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
Commits merged:
- feat(FN-210): add compact testimonials strip below trust bar on landing page
Files changed:
apps/web/src/routes/index.tsx | 55 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 55 insertions(+)
Fusion-Task-Id: FN-210
2026-05-12 22:12:23 +00:00
Fusion
efbd5be98e
feat(FN-212): tune plan card backgrounds, borders, and elevation for light/dark mode
...
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
Commits merged:
- feat(FN-212): tune plan card backgrounds, borders, and elevation for light/dark mode
Files changed:
.../src/routes/dashboard/subscription/__tests__/index.test.tsx | 2 +-
apps/web/src/routes/dashboard/subscription/index.tsx | 8 +++++---
2 files changed, 6 insertions(+), 4 deletions(-)
Fusion-Task-Id: FN-212
2026-05-12 22:05:59 +00:00
Fusion
0b49c164dc
feat(FN-209): implement trial urgency banner
...
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
Commits merged:
- feat(FN-209): implement trial urgency banner
Files changed:
apps/web/src/components/trial-urgency-banner.tsx | 111 +++++++++++++++++++++++
apps/web/src/messages/en.json | 7 +-
apps/web/src/messages/tr.json | 7 +-
apps/web/src/routes/dashboard.tsx | 8 +-
4 files changed, 129 insertions(+), 4 deletions(-)
Fusion-Task-Id: FN-209
2026-05-12 21:47:26 +00:00
Fusion
d14657a2c1
feat(FN-208): implement sticky checkout bar on scroll (+1 more)
...
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
Commits merged:
- chore(FN-208): format code with biome
- feat(FN-208): implement sticky checkout bar on scroll
Files changed:
.../subscription/__tests__/index.test.tsx | 10 ++++
.../routes/dashboard/subscription/index.test.tsx | 9 ++++
.../src/routes/dashboard/subscription/index.tsx | 54 +++++++++++++++++++++-
3 files changed, 71 insertions(+), 2 deletions(-)
Fusion-Task-Id: FN-208
2026-05-12 21:38:48 +00:00
Fusion
405c0067dc
feat(FN-207): Step 1 — add downgradeOffer i18n keys (tr + en) (+4 more)
...
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
Commits merged:
- style(FN-207): apply Biome formatting
- feat(FN-207): Steps 4-9 — add downgrade save-flow UI (helper, dialogs, plans query, handler)
- feat(FN-207): Step 3 — add PATCH /subscriptions/downgrade and GET /subscriptions/plans endpoints
- feat(FN-207): Step 2 — add downgrade() and getPlans() service methods
- feat(FN-207): Step 1 — add downgradeOffer i18n keys (tr + en)
Files changed:
.../src/subscriptions/subscriptions.controller.ts | 13 ++
.../api/src/subscriptions/subscriptions.service.ts | 75 ++++++
apps/web/src/messages/en.json | 10 +
apps/web/src/messages/tr.json | 10 +
apps/web/src/routes/dashboard/index.tsx | 16 +-
.../src/routes/dashboard/subscription/index.tsx | 255 ++++++++++++++++++---
6 files changed, 340 insertions(+), 39 deletions(-)
Fusion-Task-Id: FN-207
2026-05-12 21:29:12 +00:00
Fusion
396049a77a
feat(FN-252): fix 2 failing Popular badge tests — FeatureMatrix uses aria-label, not visible text
...
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
Commits merged:
- fix(FN-252): fix 2 failing Popular badge tests — FeatureMatrix uses aria-label, not visible text
Files changed:
.../subscription/__tests__/index.test.tsx | 26 ++++++++--------------
1 file changed, 9 insertions(+), 17 deletions(-)
Fusion-Task-Id: FN-252
2026-05-12 20:42:22 +00:00
Fusion
441be751c7
feat(FN-257): remove duplicated plan names and popular badge from FeatureMatrix table headers (+1 more)
...
Commits merged:
- fix(FN-257): update test assertions for non-duplicated FeatureMatrix text
- fix(FN-257): remove duplicated plan names and popular badge from FeatureMatrix table headers
Files changed:
apps/web/src/routes/dashboard/subscription/index.test.tsx | 10 ++++------
apps/web/src/routes/dashboard/subscription/index.tsx | 10 ++--------
2 files changed, 6 insertions(+), 14 deletions(-)
Fusion-Task-Id: FN-257
2026-05-12 20:13:17 +00:00
Fusion
2907008c9d
feat(FN-249): fix 15 failing regression tests — FeatureMatrix duplicate selectors
...
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
Commits merged:
- fix(FN-249): fix 15 failing regression tests — FeatureMatrix duplicate selectors
Files changed:
.../subscription/__tests__/index.test.tsx | 145 +++++++++++----------
1 file changed, 77 insertions(+), 68 deletions(-)
Fusion-Task-Id: FN-249
2026-05-12 20:03:30 +00:00
Fusion
668ab50cf2
feat(FN-245): add 20 regression tests for subscription page remaining coverage
...
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
Commits merged:
- test(FN-245): add 20 regression tests for subscription page remaining coverage
Files changed:
.../routes/dashboard/subscription/index.test.tsx | 382 ++++++++++++++++++++-
1 file changed, 379 insertions(+), 3 deletions(-)
Fusion-Task-Id: FN-245
2026-05-12 19:46:18 +00:00
Fusion
68b4abe858
feat(FN-244): fix 15 failing subscription regression tests — FeatureMatrix duplicate selectors (+1 more)
...
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
Commits merged:
- style(FN-244): biome format fix for long lines
- fix(FN-244): fix 15 failing subscription regression tests — FeatureMatrix duplicate selectors
Files changed:
.../subscription/__tests__/index.test.tsx | 69 +++++++++++++++-------
1 file changed, 49 insertions(+), 20 deletions(-)
Fusion-Task-Id: FN-244
2026-05-12 19:31:12 +00:00
Fusion
1eefd931c9
feat(FN-206): add FeatureMatrix component, ALL_FEATURES constant, and i18n keys (+1 more)
...
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
Commits merged:
- feat(FN-206): add FeatureMatrix tests and export SubscriptionPage for testing
- feat(FN-206): add FeatureMatrix component, ALL_FEATURES constant, and i18n keys
Files changed:
apps/web/src/messages/en.json | 1 +
apps/web/src/messages/tr.json | 1 +
.../routes/dashboard/subscription/index.test.tsx | 177 +++++++++++++++++++++
.../src/routes/dashboard/subscription/index.tsx | 73 +++++++++
package.json | 1 +
5 files changed, 253 insertions(+)
Fusion-Task-Id: FN-206
2026-05-12 18:42:41 +00:00
Fusion
b1e75a0771
test(FN-202): add 45 regression tests for /dashboard/subscription page
...
Covers P0-1 through P0-10 CRO fixes and edge cases:
- Rendering: plan cards, billing toggle, yearly discount (P0-1), popular
visual dominance (P0-2), current plan badge (P0-5), loading state
- Interaction: CTA labels (P0-3), order summary (P0-4), trial card
hidden on trial status (P0-6), payment navigation, non-interactive plan
- Trust & i18n: PostHog events (P0-10), i18n key usage (P0-9),
trust i18n keys exist (P0-7, P0-8)
- Edge cases: no subscription, expired, cancelled, empty state, full plan
- Accessibility: button labels, non-clickable current plan, color
- Subscription status: dates, brands, billing period, cancel button
Also exports SubscriptionPage for testability and relaxes test lint
rules (noNonNullAssertion, noForEach, useButtonType) in biome.json.
47/47 tests passing.
2026-05-12 18:23:38 +00:00
Fusion
d4e08eb36b
test(FN-202): add 45 regression tests for /dashboard/subscription page
...
Covers P0-1 through P0-10 CRO fixes and edge cases:
- Rendering: plan cards, billing toggle, yearly discount (P0-1), popular visual dominance (P0-2), current plan badge (P0-5), loading state
- Interaction: CTA labels (P0-3), order summary (P0-4), trial card hidden on trial status (P0-6), payment navigation, non-interactive current plan
- Trust & i18n: PostHog events (P0-10), i18n key usage (P0-9), trust i18n keys (P0-7, P0-8)
- Edge cases: no subscription, expired, cancelled, empty state, full plan users
- Accessibility: button labels, non-clickable current plan, color differentiation
- Subscription status display: dates, brands, billing period, cancel button visibility
Also exports SubscriptionPage for testability.
2026-05-12 18:20:03 +00:00
Fusion
ba43df45bc
feat(FN-204): i18n pricing/subscription/payment surfaces
...
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
Commits merged:
- feat(FN-204): i18n pricing/subscription/payment surfaces
Files changed:
.../web/src/components/payment/payment-content.tsx | 11 +-
apps/web/src/lib/i18n.ts | 17 ++-
apps/web/src/messages/en.json | 27 ++++-
apps/web/src/messages/tr.json | 27 ++++-
.../src/routes/dashboard/subscription/index.tsx | 4 +-
apps/web/src/routes/pricing.tsx | 127 +++++++++++----------
6 files changed, 135 insertions(+), 78 deletions(-)
Fusion-Task-Id: FN-204
2026-05-12 18:11:33 +00:00
Fusion
688db7c990
feat(FN-199): add i18n keys for trust copy, payment trust, daysLeft (+2 more)
...
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
Commits merged:
- feat(FN-199): complete Step 3 — add Clock and CreditCard to lucide-react imports
- feat(FN-199): complete Step 2 — replace hardcoded gün kaldı with i18n key
- feat(FN-199): complete Step 1 — add i18n keys for trust copy, payment trust, daysLeft
Files changed:
apps/web/src/messages/en.json | 9 ++++++++-
apps/web/src/messages/tr.json | 9 ++++++++-
apps/web/src/routes/dashboard/subscription/index.tsx | 4 +++-
3 files changed, 19 insertions(+), 3 deletions(-)
Fusion-Task-Id: FN-199
2026-05-12 16:50:29 +00:00
Fusion
9c8054d6be
feat(FN-203): implement P0-1 through P0-6 subscription page fixes
...
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
Commits merged:
- feat(FN-203): complete Step 1 — implement P0-1 through P0-6 subscription page fixes
Files changed:
apps/web/src/messages/en.json | 7 +
apps/web/src/messages/tr.json | 7 +
.../src/routes/dashboard/subscription/index.tsx | 188 +++++++++++++++------
apps/web/vitest.config.ts | 3 +
4 files changed, 153 insertions(+), 52 deletions(-)
Fusion-Task-Id: FN-203
2026-05-12 16:07:52 +00:00
Fusion
c79b23860d
feat(FN-194): update Turkish locale: Fatura→Ödeme, Fatura Geçmişi→Ödeme Geçmişi (+1 more)
...
Sync dev → Gitea / Mirror dev to Gitea (push) Has been cancelled
Commits merged:
- feat(FN-194): complete Step 2 — update English locale: Billing→Payment, Billing History→Payment History
- feat(FN-194): complete Step 1 — update Turkish locale: Fatura→Ödeme, Fatura Geçmişi→Ödeme Geçmişi
Files changed:
apps/web/src/messages/en.json | 4 ++--
apps/web/src/messages/tr.json | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
Fusion-Task-Id: FN-194
2026-05-12 13:28:47 +00:00
Fusion
2ebcdc3734
test(vehicles): add missing redis mock methods exposed by perf(vehicles) commit
...
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
cd62ae1737
fix(migrate): make 0002 timings column add idempotent
...
The previous deploy of c4f6cc1 failed because I had applied the timings
column manually via psql before the deploy ran, leaving the hash-based
migrate runner with raw ADD COLUMN that conflicts with the existing column.
Hash differs after this change so the runner will retry on next deploy
and succeed (no-op on the already-applied column, success path records
the hash).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com >
2026-05-12 11:35:05 +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