qualogy-solutions/qualogy-websites

Read-only snapshot · generated 2026-09-14T09:11:37.002Z · act on PRs directly in Bitbucket · ← all repos

🔺 Needs your review (1)

QRAD-51: Security & performance audit hardening
#24 by Prijanka Ramcharan · QRAD-51 → main · Open in Bitbucket →
high

This PR adds a new Content-Security-Policy and other security headers globally via next.config.ts, and changes the rate-limiter API contract (limiter.check now returns an object with .success instead of a boolean) across all public-facing form/API routes (contact, apply, meeting, quote, coffee-call, ATS). If the CSP is too strict or misconfigured, it can silently break scripts, styles, images, or third-party integrations (GTM, Cookiebot, Turnstile, Supabase, Vercel Analytics) site-wide. If the rate-limiter contract change is inconsistent anywhere, requests could be incorrectly blocked or rate limiting could silently no-op, affecting all public lead-gen/application endpoints.

  • Adds global security headers (CSP, HSTS, X-Frame-Options, Permissions-Policy) in next.config.ts affecting every route/page site-wide
  • Changes the rate-limiter's public contract (boolean -> {success}) and updates call sites across 6+ public API routes (contact, apply/ats, apply/hardcoded, meeting, coffee-call, quote) - security-relevant logic touching abuse/spam protection
  • CSP misconfiguration is a classic source of silent breakage for scripts/analytics/embeds (GTM, Cookiebot, Turnstile, YouTube, Supabase) that is easy to miss in review/testing
  • Adds new third-party dependency (@vercel/speed-insights) and lockfile changes across the monorepo
  • Touches multiple independent public-facing API routes simultaneously, increasing scope of potential regression
  • New logging utility (logEvent) replacing console.error across routes - low risk itself but part of a broad, cross-cutting change
  • Large number of files changed (27) spanning config, API routes, new package module, and binary asset updates, increasing chance of an overlooked interaction

Overall a solid, low-risk hardening PR: adds structured logging via a shared logger, CSP/security headers, and Vercel Speed Insights. One notable inconsistency in apply/ats/route.ts where the rate limiter API usage differs from all sibling routes — worth confirming createRateLimiter's actual return type before merge. A few other minor points below.

apps/qualogy-web/app/api/apply/ats/route.ts:12 · warning
This route now calls `await limiter.check(ip)` and checks `.success`, while every other route in this PR (contact, meeting, coffee-call, ai-oplossingen, ai-trainingen, apply/hardcoded) still uses `if (!limiter.check(ip))` (presumably synchronous boolean). Confirm which is the actual current signature of `createRateLimiter().check` — if it's synchronous returning a boolean, this route will incorrectly await a boolean and access `.success` on it (always undefined, so `!rateLimit.success` is always true, blocking every request with a 429). If the API was changed to return a Promise<{success}> only here, the other six routes are now broken instead. This needs to be verified/fixed for correctness.
apps/qualogy-web/next.config.ts:37 · info
`script-src` includes `'unsafe-inline'`, which significantly weakens the CSP's XSS protection (allows inline <script> execution). This is likely needed for GTM/Cookiebot inline snippets, but consider using nonces or hashes for the known inline scripts (e.g. the GTM snippet in layout.tsx) instead of blanket 'unsafe-inline' if feasible in a future iteration.
packages/security/src/logger.ts:16 · info
logEvent logs error messages/meta as-is; callers pass `meta: { error: String(error) } }` which could include stack traces or potentially sensitive data (e.g., request payload details) if errors are constructed with such info. Worth double-checking that no PII/secrets end up in these log lines, since Vercel logs may be retained/searchable.

⏳ Auto-reviewed, merge pending (build not yet clean) (2)

Feature/cleanup hygiene
#4 by Deborah · feature/cleanup-hygiene → main · Open in Bitbucket →
low

Pure cleanup PR: removes unused imports/variables, simplifies two Image components to use `fill` instead of fixed width/height (same visual output), and deletes an empty temp file. No business logic, routing, or data changes.

  • Only touches marketing website pages (qualogy-caribbean-web) and a leftover temp text file", "Changes are unused import removals, unused variable removals, and minor JSX restructuring with no behavioral impact", "Image component change to `fill` layout is a well-established Next.js pattern equivalent to explicit width/height with object-cover", "No changes to auth, payments, database, infra, or public API contracts", "Small, self-contained diff (47 lines added/removed) confined to presentational code</reasons>

Mostly a safe cleanup PR (removing unused imports/variables and a stray temp file), but there's one behavior-changing edit worth flagging: the two Image components switched from fixed width/height to `fill` inside a wrapper div. This is a reasonable pattern but should be verified for regressions (e.g., missing `object-cover`/aspect issues, or loss of intrinsic sizing hints for LCP). Everything else (unused `ArrowRight`/`idx`/`FadeUp`/`PRIVACY_EMAIL` removal, deleted temp file) looks like straightforward, low-risk hygiene cleanup.

apps/qualogy-caribbean-web/app/[locale]/onze-cases/strategische-offshore-partner-voor-informatie-beveiliging/page.tsx:100 · info
Switching from fixed width/height Image to a `fill`-based Image inside a relative wrapper changes how Next.js computes the image's intrinsic aspect ratio and can affect CLS/LCP if the wrapper's height isn't reserved correctly on all breakpoints. Since `className="object-cover object-center rounded-[20px]"` no longer includes `w-full h-[...]` directly on the Image, double check that the wrapper's explicit heights match what was previously produced by the width/height props (they appear to, but worth a visual QA pass).
apps/qualogy-caribbean-web/app/[locale]/onze-cases/succesvolle-offshoring-naar-suriname/page.tsx:100 · info
Same fill-based Image change as in the offshore-partner page; recommend a visual regression check to confirm no layout shift or cropping differences from the previous fixed width/height version.
apps/qualogy-caribbean-web/app/[locale]/privacy-policy/page.tsx:6 · info
Removing the `PRIVACY_EMAIL` constant leaves a blank line; confirm it wasn't used elsewhere in the file (e.g., rendered in the page) — if it was referenced anywhere below, this would be a build error rather than just unused-var cleanup.
Add GTM-NN3W3TC8 container to Meeting and Coffee Call modals
#14 by Deborah · feature/gtm-modal-container → main · Open in Bitbucket →
low

This PR shows no actual file changes or diff content, suggesting it adds a Google Tag Manager container snippet to two specific modals (Meeting and Coffee Call). If implemented as described, impact would be limited to those UI components and analytics tracking, not core business logic.

  • No diff content or changed files were provided, making it impossible to verify actual scope
  • Title suggests a narrow, isolated change to two specific modal components
  • GTM container additions are typically analytics/tracking snippets with low functional risk
  • Does not appear to touch auth, payments, database, or infrastructure
  • However, empty diff is unusual and warrants human verification before merging

The diff is empty (no files changed), so there is nothing to review. Cannot verify that the GTM-NN3W3TC8 container was actually added to the Meeting and Coffee Call modals. Please confirm the correct branch/commit is pushed before merging.

No inline comments.