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:
| Doc | Feeds phases |
|---|---|
| Security | 1, 4 |
| Testing | 2 |
| Data access | 5 |
| Backend quality | 6 |
| Operations | 7, 9 |
| Frontend | 8 (parallelizable with 2+) |
Phase 0 — Make CI green again (critical, ~½ day)
Main CI has failed every run since 2026-06-28.
Back unit tests:— fixed: replaced withuuidv13 is ESM-only and crashes Jest at loadnode:crypto'srandomUUID()inauth.service.ts/upload.service.tsand dropped the dep. The durable Vitest migration (Phase 2) is still open.— fixed: both nowbuild-backend/build-frontendskipped because they depended ontestneeds: lint, so they run independently of the (still separately broken) test job.— fixed, see Frontend §6.next buildfails without a live backend- Web e2e:
e2e/create-deal.spec.ts:23—getByPlaceholder(/search/i)matches 2 inputs since header search shipped; scope the selector. Fixe2e/auth.spec.ts:11and the flaky cookie test while there. - Remove
--fixfromapps/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'inauth.service.ts:51andmessages.gateway.ts:58. env.config.ts:JWT_SECRETandDATABASE_URLbecomeJoi.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-35returns the full Prisma user —request.usercarries the bcrypt hash. Select safe fields, type asRequestUser, 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. deleteImagechecks the URL belongs to the deal'simagesbefore S3 delete (deals.service.ts:306-322).publishonly fromDRAFT|DECLINED(deals.controller.ts:112-120);startDiscussionrequires dealPUBLISHEDand rejects self-discussion; move both checks (and the existing controller-level ownership checks) into the services.messages.controller.ts:31:ForbiddenExceptioninstead ofthrow new Error(currently a 500).main.ts: helmet,enableShutdownHooks,forbidNonWhitelisted;@nestjs/throttlerreplaces the hand-rolled Postgres rate limiter (auth.service.ts:225-262).- Pagination clamp (
pageArgs, max 50) on deals/products search —?limit=10000currently 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, Float→Decimal 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)
- Vulns now:
@nestjs-modules/mailerdrags criticalhandlebars/liquidjs(+ highnodemailer,lodash) — bump major or consolidate onresend; bumpmulter≥2.2 andnext≥16.2.5; delete the dead GraphQL-era deps@as-integrations/express5and@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.