Skip to content

SonarCloud Issue Triage Report

Date: 2026-03-12 Project: devgem_forma-3d-connect Branch analyzed: feature/scaling-preparations (PR #535) Total issues: 769 issues + 6 security hotspots + 19.5% code duplication Total effort: ~3,890 min (~65 hours estimated by SonarCloud)


Summary

Severity Count Real Problems False Positive Won't Fix
BLOCKER 13 1 12 0
CRITICAL 39 36 0 3
MAJOR 132 132 0 0
MINOR 585 490 15 80
Total 769 659 27 83
Type Count
CODE_SMELL 748
VULNERABILITY 12
BUG 9
Action Issues Effort
Suppress as false positive 27 ~30 min
Suppress as won't fix 83 ~60 min
Auto-fixable (lint --fix) ~350 ~2 hours
Manual refactoring ~280 ~20 hours
Real bugs to fix immediately 9 ~2 hours
Scope exclusion (sonar config) 20 ~10 min

Configuration Fixes

Before addressing individual issues, update sonar-project.properties to exclude test infrastructure files that are incorrectly analyzed as production code:

# Add to sonar.exclusions:
  **/test/mocks/**,\
  **/test/setup.*

This removes ~15–20 issues from apps/web/src/test/mocks/ that are test mock factories, not production code.


BLOCKER Issues (13)

S2068 — Hard-coded credentials (12 issues) → FALSE POSITIVE

Files: All audit.service.ts files + change-password-modal.tsx + user-form-modal.tsx

SonarCloud flags any variable containing the word "password" as a potential hard-coded credential. In this codebase:

  • Audit services use constants like PASSWORD_CHANGED: 'password.changed' and PASSWORD_RESET: 'password.reset' — these are audit event type names, not credentials.
  • change-password-modal.tsx and user-form-modal.tsx use password as a form field variable name for validation logic — no actual secrets.

Recommended fix: Add // NOSONAR comments on the flagged lines:

File Lines Reason
apps/gridflock-service/src/audit/audit.service.ts 19, 20 Audit event name constants
apps/order-service/src/audit/audit.service.ts 27, 28 Audit event name constants
apps/print-service/src/audit/audit.service.ts 19, 20 Audit event name constants
apps/shipping-service/src/audit/audit.service.ts 19, 20 Audit event name constants
apps/web/src/components/users/change-password-modal.tsx 38, 40 Form field validation
apps/web/src/components/users/user-form-modal.tsx 77, 79 Form field validation

S2699 — Test without assertions (1 issue) → WON'T FIX

File: apps/web/src/components/ui/__tests__/pagination.test.tsx:150

This is an intentional crash/smoke test that verifies the <Pagination> component doesn't throw when given undefined props. The test name is "should handle undefined or NaN values gracefully". Not having an explicit assertion is the point — the test passes if no error is thrown.

Recommended fix: Add // NOSONAR to the test function.


BUG Issues (9)

S2871 — Array sort without compare function (8 issues) → PROBLEM

.sort() without a compare function converts elements to strings and sorts lexicographically. This can produce unexpected results for numbers and locale-sensitive strings.

File Line Context Evaluation
apps/gateway/src/auth/services/permission.service.ts 35 .sort() on permission name strings Won't Fix — string array, lexicographic sort is fine for permission names used for caching/comparison
apps/gridflock-service/src/auth/services/permission.service.ts 38 Same pattern Won't Fix
apps/order-service/src/auth/services/permission.service.ts 38 Same pattern Won't Fix
apps/print-service/src/auth/services/permission.service.ts 38 Same pattern Won't Fix
apps/order-service/src/shopify/shopify-token.service.ts 283 Object.keys(params).sort() for HMAC verification Won't Fix — ASCII key sorting for cryptographic signature verification, lexicographic is correct
apps/order-service/src/storefront/guards/shopify-app-proxy.guard.ts 113 Same HMAC pattern Won't Fix
apps/web/src/pages/settings/index.tsx 549 Unknown array sort Review — needs context check
apps/shipping-service/src/auth/services/permission.service.ts 38 Same permission pattern Won't Fix

Note: 7 of 8 are actually fine — SonarCloud flags .sort() on string arrays but lexicographic sorting is correct for these use cases (permission names, HMAC param keys). Add // NOSONAR with explanation.

S3923 — Identical conditional branches (1 issue) → PROBLEM (real bug)

File: apps/order-service/src/audit/audit.controller.ts:59

actorUserId: actorEmail ? undefined : undefined,

Both branches return undefined — this conditional is useless. The comment says "We'll filter by email below" suggesting this was a placeholder that was never completed. This should be cleaned up.

Recommended fix: Remove the conditional, just use actorUserId: undefined.


VULNERABILITY Issues (12)

All 12 are the same S2068 (hard-coded credentials) already covered in BLOCKER above. They are all false positives — audit event name constants and form field variable names.


CRITICAL Issues (39)

S3776 — Cognitive complexity too high (28 issues) → PROBLEM (refactor over time)

Functions exceeding the cognitive complexity threshold (default: 15). These are real code quality issues but not urgent bugs.

Top offenders:

File Line Likely Cause
apps/gateway/src/swagger/swagger-aggregator.service.ts 109 Complex Swagger merge logic
apps/gridflock-service/src/gridflock/gridflock-pipeline.service.ts 73 Complex generation pipeline
apps/order-service/src/orchestration/orchestration.service.ts 105 Order state machine
apps/order-service/src/shopify/shopify-webhook.service.ts 44 Webhook event routing
apps/order-service/src/shopify/shopify-backfill.service.ts 217, 307 Batch processing loops
apps/print-service/src/simplyprint/simplyprint-api.client.ts 69 API client with many methods
apps/web/src/pages/settings/index.tsx 72 Large settings page component
apps/web/src/pages/mappings/new.tsx 113 Complex form wizard

Recommendation: Track as tech debt. Refactor the worst offenders (orchestration service, settings page) when touching those files.

S2871 — Array sort (8 issues)

Already covered in BUG section above. ⅞ are won't fix, 1 needs review.

S3735 — Void used as value (3 issues) → WON'T FIX

File Line Context
apps/order-service/src/shipments/shipments.service.ts 87 void _shippingMethodId; — intentional unused parameter suppression
apps/shipping-service/src/shipments/shipments.service.ts 87 Same pattern
apps/web/src/sw.ts 160 Service worker lifecycle

Recommended fix: Suppress with // NOSONARvoid expr is a standard TypeScript pattern for acknowledging unused parameters.


MAJOR Issues (132) — All PROBLEM, sorted by auto-fixability

Auto-fixable (79 issues)

These can likely be fixed with ESLint auto-fix rules or bulk find-and-replace:

Rule Count Description Fix
S6853 19 Unneeded JSX curly braces {"text"}"text" ESLint react/jsx-curly-brace-presence
S6582 14 Prefer optional chaining a && a.ba?.b @typescript-eslint/prefer-optional-chaining
S6819 6 Self-closing JSX <Foo></Foo><Foo /> ESLint react/self-closing-comp
S7785 5 Prefer for-of loop @typescript-eslint/prefer-for-of

Manual refactoring needed (53 issues)

Rule Count Description Priority
S3358 57 Nested ternary operators Medium — extract to variables or early returns
S2933 12 Fields should be readonly Low — add readonly to constructor-injected fields
S4624 4 Missing never return type on throw functions Low
S6481 4 Constant objects in JSX (re-created each render) Medium — move useMemo or extract constants
S6479 5 Array index used as React key Medium — use stable identifiers where available
S1854 2 Dead stores in shopify-backfill.service.ts Low — hasMore = false before break is redundant
S3923 1 Identical conditional branches (real bug) High
S2234 1 Arguments possibly in wrong order (border-generator.ts:166) High — verify
S107 2 Functions with too many parameters Low

S2234 — Arguments in wrong order (1 issue) → REVIEW CAREFULLY

File: libs/gridflock-core/src/lib/border-generator.ts:166

off = writeTriangle(buf, off, 0, 0, -1, cx, cy, z0, bx, by, z0, ax, ay, z0);

The function signature is writeTriangle(buf, offset, nx, ny, nz, ax, ay, az, bx, by, bz, cx, cy, cz). SonarCloud suspects ax, ay and bx, by may be swapped. For the bottom face, the reversed winding order (swapping A and B) is intentional to flip the normal direction. This is correct 3D geometry — reversed winding = inverted normal.

Evaluation: False positive — reversed winding order is intentional for the bottom face of a 3D mesh.


MINOR Issues (585) — Bulk Categories

Auto-fixable with ESLint rules (~350 issues)

Rule Count Description ESLint Rule
S7773 143 Use ?? instead of \|\| @typescript-eslint/prefer-nullish-coalescing
S7735 46 Use as type assertion syntax @typescript-eslint/consistent-type-assertions
S7764 38 Unnecessary type parameters @typescript-eslint/no-unnecessary-type-arguments
S7748 32 Prefer ?. over && @typescript-eslint/prefer-optional-chaining
S4325 18 Unnecessary type assertions @typescript-eslint/no-unnecessary-type-assertion
S3863 18 Use shorthand properties object-shorthand
S7781 16 Prefer destructuring prefer-destructuring
S7778 9 Use includes() over indexOf() @typescript-eslint/prefer-includes
S7758 4 Dot notation over brackets dot-notation
S7726 4 Unnecessary type constraints @typescript-eslint/no-unnecessary-type-constraint
S7757 2 Consistent type imports @typescript-eslint/consistent-type-imports
S7755 2 Template literals prefer-template
S6606 2 Nullish coalescing @typescript-eslint/prefer-nullish-coalescing
S7776 2 startsWith/endsWith @typescript-eslint/prefer-string-starts-ends-with
S7780 1 Return type annotation @typescript-eslint/explicit-function-return-type

Caution with S7773 (143 issues): Changing || to ?? is NOT always safe. || treats "", 0, and false as falsy, while ?? only treats null/undefined. The configuration files (configuration.ts) use || 'default' patterns for env vars where empty string should also fall back — those should stay as ||.

Won't Fix — Stylistic/Low-value (80 issues)

Rule Count Description Reason
S7763 48 Redundant type aliases Many from third-party library patterns (Sentry, Prisma). Changing would reduce readability.
S7772 47 Sort union type constituents alphabetically Pure cosmetic, no functional impact. Adds churn for zero value.

Recommended: Suppress at project level in SonarCloud quality profile, or add // NOSONAR selectively.

Needs Manual Review (~55 issues)

Rule Count Description Notes
S6551 57 Non-null assertion ! usage Many are in code that handles validated data (e.g., after null checks). Review case-by-case.
S6759 49 JSX cognitive complexity Large React components — refactor when touching.
S1874 37 Deprecated API usage Check which APIs and plan migration.
S4323 2 Use type aliases for repeated union types Minor improvement.
S7744 1 Interface over type literal Stylistic preference.
S6754 1 React state mutation (theme-context.tsx:58) Likely false positive — uses useState correctly.

False Positive — Test Mocks (~15 issues)

Files in apps/web/src/test/mocks/ are test infrastructure, not production code. Fix by adding to sonar.exclusions in sonar-project.properties.


Security Hotspots (6)

S5852 — Regex vulnerable to backtracking DoS (3 hotspots) → REVIEW

File Line Regex
apps/web/src/components/users/user-form-modal.tsx 72 Email validation: /^[^\s@]+@[^\s@]+\.[^\s@]+$/
libs/utils/src/lib/string.ts 47, 54 String utility regexes

Evaluation: The email regex is simple and bounded — no catastrophic backtracking risk in practice. However, for defense-in-depth, consider using a well-tested email validation library.

Recommended: Mark as reviewed/safe in SonarCloud.

S2245 — Pseudorandom number generator (2 hotspots) → WON'T FIX

File Line Context
apps/order-service/src/retry-queue/retry-queue.service.ts 133 Math.random() for retry jitter
apps/shipping-service/src/retry-queue/retry-queue.service.ts 133 Same pattern

Math.random() is used to add ±10% jitter to retry delays. This is a standard distributed systems pattern — no cryptographic security requirement.

Recommended: Mark as reviewed/safe in SonarCloud, or add // NOSONAR with comment explaining jitter usage.

S5443 — Publicly writable directory (1 hotspot) → WON'T FIX

File: apps/gridflock-service/src/gridflock/gridflock.processor.ts:68

Uses /tmp/gridflock-stl as default STL output path, overridable via STL_OUTPUT_PATH env var. In production, this is configured to a secure path. The /tmp fallback is for local development only.

Recommended: Mark as reviewed/safe.


Code Duplication (19.5% / 28,008 lines)

Project totals: 66,133 lines of code, 28,008 duplicated lines (33.4% overall, 19.5% on new code), 402 duplicated blocks across 243 files.

The duplication quality gate requires ≤ 3.0% — the project is at 19.5%. This is the single largest quality gate failure.

Root Cause: Cross-Service Code Duplication

Nearly all duplication comes from identical files copied across microservices. The architecture has 5 services (gateway, order-service, print-service, shipping-service, gridflock-service) that share common infrastructure code that was copy-pasted rather than extracted into shared libraries.

Duplication by Category

1. Observability Infrastructure (~3,100 dup lines) → Extract to libs/service-common

File Pattern Services Dup Lines (total) Avg Density
src/observability/services/business-observability.service.ts 4 services 1,832 98%
src/observability/observability.controller.ts 4 services 804 93%

These files are nearly identical across all backend services. The business-observability.service.ts alone accounts for 1,832 duplicated lines.

Recommendation: Extract into libs/service-common or a new libs/observability shared library. Each service imports and configures via dependency injection.

2. Authentication & Authorization (~1,100 dup lines) → Extract to libs/service-common

File Pattern Services Dup Lines (total) Avg Density
src/auth/services/auth.service.ts 5 services 884 96%
src/auth/dto/login.dto.ts 5 services 210 91%

Auth logic is duplicated across all 5 services including the gateway.

Recommendation: Extract shared auth service and DTOs into libs/service-common. Service-specific auth customizations can extend the base class.

3. Configuration (~1,300 dup lines) → Extract to libs/config

File Pattern Services Dup Lines (total) Avg Density
src/config/system-config.service.ts 4 services 752 94%
src/config/env.validation.ts 4 services 536 91%

Environment validation and system config management is identical across services.

Recommendation: Extract shared config patterns into libs/config. Each service keeps only its service-specific env vars.

4. Event Log (~1,050 dup lines) → Extract to libs/service-common

File Pattern Services Dup Lines (total) Avg Density
src/event-log/event-log.controller.ts 4 services 544 94%
src/event-log/event-log.service.ts 4 services 504 94%

Event logging is a cross-cutting concern duplicated across all backend services.

Recommendation: Extract into a shared NestJS dynamic module in libs/service-common.

5. Notifications (~1,100 dup lines) → Extract to libs/service-common

File Pattern Services Dup Lines (total) Avg Density
src/notifications/email.service.ts 3 services 606 96%
src/notifications/notifications.service.ts 2 services 330 91%

Email and notification services are duplicated across order, print, and shipping services.

Recommendation: Extract into a shared notifications module.

6. Product Mappings (~1,500 dup lines) → Extract to shared lib or merge

File Pattern Services Dup Lines (total) Avg Density
src/product-mappings/product-mappings.repository.ts 2 services 518 98%
src/product-mappings/product-mappings.service.ts 2 services 414 93%
src/product-mappings/dto/product-mapping.dto.ts 2 services 308 98%
src/product-mappings/dto/part-library.dto.ts 2 services 84 91%

Product mapping logic is duplicated between order-service and print-service.

Recommendation: Extract shared DTOs to libs/domain-contracts. Extract repository/service to a shared module, or designate one service as the single owner.

7. Shipments & SendCloud (~1,700 dup lines) → Consolidate ownership

File Pattern Services Dup Lines (total) Avg Density
src/shipments/shipments.service.ts 2 services 588 96%
src/sendcloud/sendcloud.service.ts 1 (internal) 455 94%
src/shipments/shipments.repository.ts 2 services 226 95%
src/sendcloud/sendcloud-webhook.service.ts 1 (internal) 221 93%
src/sendcloud/sendcloud-webhook.types.ts 2 services 222 92%

Shipment and SendCloud integration code is duplicated between order-service and shipping-service.

Recommendation: Designate shipping-service as the single owner of shipment/SendCloud logic. Other services communicate via events.

8. Print Jobs (~1,070 dup lines) → Consolidate ownership

File Pattern Services Dup Lines (total) Avg Density
src/print-jobs/print-jobs.repository.ts 1 (internal) 286 98%
src/print-jobs/stuck-job-monitor.service.ts 2 services 462 95%
src/print-jobs/events/print-job.events.ts 2 services 406 97%
src/print-jobs/dto/print-job.dto.ts 2 services 170 96%

Print job management is duplicated between order-service and print-service.

Recommendation: Designate print-service as the single owner. Extract shared event types and DTOs to libs/domain-contracts.

9. Other Cross-Cutting Concerns (~1,000 dup lines)

File Pattern Services Dup Lines (total) Avg Density
src/audit/audit.service.ts 3 services 342 92%
src/retry-queue/retry-queue.service.ts 2 services 318 95%
src/webhook-idempotency/webhook-idempotency.repository.ts 2–3 services 384 96%
src/versioning/deprecated.decorator.ts 4 services 172 92%
src/tenancy/tenant-context.service.ts 2 services 180 93%
src/retry-queue/retry-queue.repository.ts 2 services 186 94%
src/sendcloud/events/shipment.events.ts 2 services 252 94%
src/simplyprint/dto/simplyprint-job.dto.ts 2 services 88 92%

Recommendation: Extract all infrastructure patterns (audit, retry, webhook idempotency, versioning, tenancy) into libs/service-common. Extract shared DTOs/events to libs/domain-contracts.

Duplication Reduction Strategy

Phase Action Estimated Dup Lines Removed Target Library
D1 Extract observability module ~3,100 libs/service-common
D2 Extract auth module + DTOs ~1,100 libs/service-common
D3 Extract config patterns ~1,300 libs/config
D4 Extract event-log module ~1,050 libs/service-common
D5 Extract notification module ~1,100 libs/service-common
D6 Consolidate product mapping DTOs ~1,500 libs/domain-contracts
D7 Consolidate shipment ownership ~1,700 shipping-service owns
D8 Consolidate print job ownership ~1,070 print-service owns
D9 Extract infrastructure patterns ~1,000 libs/service-common
Total recoverable ~12,900

Removing ~12,900 of the 28,008 duplicated lines would bring the duplication rate from 33.4% to approximately 16%. Further reductions require domain-level architectural decisions about service boundaries.

Important: Duplication extraction is a significant architectural refactoring effort. Each phase should be treated as a separate PR with thorough testing. Phases D1–D5 and D9 are infrastructure-level changes with low domain risk. Phases D6–D8 involve domain ownership decisions that require architectural review.


Phase 1: Quick Wins (30 min)

  1. Update sonar-project.properties to exclude test mocks (~15 issues removed)
  2. Add // NOSONAR to 12 false-positive S2068 credential warnings
  3. Add // NOSONAR to the S2699 test assertion warning
  4. Add // NOSONAR to 3 S3735 void-as-value warnings

Phase 2: Real Bug Fixes (1 hour)

  1. Fix S3923: Remove useless conditional in audit.controller.ts:59
  2. Add // NOSONAR to 7 legitimate S2871 .sort() calls with explanation
  3. Verify S2234 argument order in border-generator.ts:166 (likely correct)

Phase 3: Auto-fixable Code Quality (~2 hours)

  1. Enable ESLint rules matching SonarCloud findings
  2. Run eslint --fix across the codebase
  3. Review changes (especially ||?? conversions)
  4. This should resolve ~350 minor issues

Phase 4: Manual Refactoring (ongoing)

  1. Reduce cognitive complexity in top offenders
  2. Extract nested ternaries to helper functions/variables
  3. Add readonly to constructor-injected NestJS fields
  4. Move constant objects outside JSX render functions
  5. Replace array index keys with stable identifiers

Phase 5: Won't Fix Suppressions

  1. Add // NOSONAR to S7763 and S7772 issues (or suppress at quality profile level)
  2. Review S1874 deprecated API usage and plan migration

Phase 6: Duplication Reduction (multi-sprint effort)

  1. D1–D5, D9: Extract shared infrastructure into libs/service-common (observability, auth, config, event-log, notifications, audit, retry, webhook idempotency, versioning, tenancy)
  2. D6: Move shared DTOs/events to libs/domain-contracts (product mappings, print jobs, shipments)
  3. D7–D8: Consolidate domain ownership (shipping-service owns shipments/SendCloud, print-service owns print jobs)
  4. Each phase = separate PR with full test coverage verification