KwadMarket Docs
Remediation Plan

Remaining Work — Ordered Phases

Everything still open from the 2026-07-02 reviews, in execution order

Consolidated from the 2026-07-02 reviews (frontend + backend, at commit 0b38d35). Everything already fixed has been removed; what's listed here is verified still open. One PR per step, run the verification gates after each.

State in one line

Frontend is healthy (maintenance-level work only); backend carries the risk; main CI has been red since 2026-06-28.

Detailed specs (with code) live in this section:

DocFeeds phases
Security1, 4
Testing2
Data access5
Backend quality6
Operations7, 9
Frontend8 (parallelizable with 2+)

Phase 0 — Make CI green again (critical, ~½ day)

Main CI has failed every run since 2026-06-28.

  1. Back unit tests: uuid v13 is ESM-only and crashes Jest at load — fixed: replaced with node:crypto's randomUUID() in auth.service.ts/upload.service.ts and dropped the dep. The durable Vitest migration (Phase 2) is still open.
  2. build-backend/build-frontend skipped because they depended on test — fixed: both now needs: lint, so they run independently of the (still separately broken) test job.
  3. next build fails without a live backend — fixed, see Frontend §6.
  4. Web e2e: e2e/create-deal.spec.ts:23getByPlaceholder(/search/i) matches 2 inputs since header search shipped; scope the selector. Fix e2e/auth.spec.ts:11 and the flaky cookie test while there.
  5. Remove --fix from apps/back's lint script (linting must not mutate the tree).

Accept: full CI pipeline green on main, build jobs actually run.

Phase 1 — Secrets fail-fast (critical, ~½ day)

  • Delete || 'default-secret' in auth.service.ts:51 and messages.gateway.ts:58.
  • env.config.ts: JWT_SECRET and DATABASE_URL become Joi.when('NODE_ENV', { is: 'production', then: required() }) (spec in Security §1).

Accept: grep -rn "default-secret" apps/back → 0; booting with NODE_ENV=production and no JWT_SECRET crashes.

Phase 2 — Backend test harness (1–2 days)

Vitest + supertest + testcontainers per Testing; write the authorization regression suites (deals, discussions, auth). Do this before Phases 3–4 so those changes land tested.

Accept: suites green in CI; reverting one ownership check makes a test fail.

Phase 3 — Auth response hygiene (~½ day)

  • jwt.strategy.ts:32-35 returns the full Prisma user — request.user carries the bcrypt hash. Select safe fields, type as RequestUser, replace every @CurrentUser() user: any (Security §2).

Accept: grep -rn "user: any" apps/back/src → 0; /auth/me-style responses contain no password field (e2e locks it).

Phase 4 — Security patch set (~1 day)

All specified in Security:

  • OAuth callback: token moves from query param to URL fragment (auth.controller.ts:88,111) + the matching web callback change, same PR.
  • deleteImage checks the URL belongs to the deal's images before S3 delete (deals.service.ts:306-322).
  • publish only from DRAFT|DECLINED (deals.controller.ts:112-120); startDiscussion requires deal PUBLISHED and rejects self-discussion; move both checks (and the existing controller-level ownership checks) into the services.
  • messages.controller.ts:31: ForbiddenException instead of throw new Error (currently a 500).
  • main.ts: helmet, enableShutdownHooks, forbidNonWhitelisted; @nestjs/throttler replaces the hand-rolled Postgres rate limiter (auth.service.ts:225-262).
  • Pagination clamp (pageArgs, max 50) on deals/products search — ?limit=10000 currently returns 10,000 rows.

Phase 5 — Data access (module by module)

Data access: PrismaService DI (kills the global singleton, incl. discussions.controller.ts:16,83 — a controller querying the DB); CI migration drift check; follow-up migration: FK indexes, FloatDecimal prices, drop RememberMeToken + RateLimit; $transaction for multi-writes; mappers + Prisma.validator payload types.

Accept: grep -rn "import { prisma }" apps/back/src → 0; drift check green.

Phase 6 — Backend code quality (with Phase 5, per module: deals → products → discussions → users)

Backend quality: kill the 70 Promise<any> + 8 as any; Logger replaces the 19 console.*; throw new Error → Nest exceptions everywhere; query DTOs; decompose products.service.ts (822 lines) and split ScraperService (793).

Accept: all backend grep gates in the conventions return 0 repo-wide, not just on touched files.

Phase 7 — Dependencies & ops (~1 day + ongoing)

Operations:

  • Vulns now: @nestjs-modules/mailer drags critical handlebars/liquidjs (+ high nodemailer, lodash) — bump major or consolidate on resend; bump multer ≥2.2 and next ≥16.2.5; delete the dead GraphQL-era deps @as-integrations/express5 and @nestjs/microservices.
  • Then: health endpoint (terminus), Sentry, scheduled jobs (deal expiry, token purge), Swagger, config namespaces, Renovate/Dependabot.

Phase 8 — Frontend maintenance (independent — can run in parallel from Phase 2 on)

Frontend, in order: quick wins (dead historyRef, server.ts error message, 8 lint warnings, README stack table) → Prettier + one format commit → review-queue refactor (the one structural item: shared useReviewQueue on React Query, unmount-safe auto-validate, mutations with invalidation) → status-config dedup + dialog convergence → consistency sweep (qk keys, tokens, formatPrice) → build hermeticity (/ must build without a live API) → MSW test harness.

Phase 9 — Production gaps (before public launch)

The functional/operational gaps that are neither bugs nor refactors — tracked in Operations §10 "Launch checklist": email verification for local accounts, account deletion (GDPR), password change, notification emails, image orphan cleanup + thumbnails, backups, uptime monitoring, SEO basics (metadata/sitemap/robots), legal pages, Meilisearch API key required in prod, tighten the hostname: "**" image pattern once scraped images are re-uploaded to S3.

Feature ideas

Product roadmap (not fixes) lives in the Roadmap section.

On this page