Skip to content

SonarCloud Issue Triage Report

Date: 2026-03-13 Project: devgem_forma-3d-connect Branch analyzed: main Total issues: 244 code smells + 15.7% code duplication (10,743 lines / 202 blocks / 105 files) Previous report: 2026-03-12 — 769 issues + 19.5% duplication


Summary

Severity Count Auto-fixable Manual Refactor Won't Fix / Suppress
CRITICAL 23 0 23 0
MAJOR 87 18 59 10
MINOR 134 83 46 5
Total 244 101 128 15

All 244 issues are CODE_SMELL (no bugs or vulnerabilities remaining).

Phase Action Issues Effort
1 Quick auto-fixes (replaceAll, ??=, .at()) 22 ~30 min
2 Readonly props + template literals + a11y 70 ~2 hours
3 Nested ternaries + form labels + assertions 71 ~4 hours
4 Cognitive complexity + toString coercion 72 ~8 hours
5 Won't Fix suppressions 10 ~15 min
6 Duplication reduction ~105 ~16 hours

Phase 1: Quick Auto-fixes (22 issues)

S7781 — Prefer String#replaceAll() over String#replace() (9 issues) → FIX

File Line
apps/gateway/src/feature-flags-admin/feature-flags-admin.service.ts 20
apps/gateway/src/feature-flags-admin/feature-flags-admin.service.ts 21
apps/gateway/src/proxy/proxy.middleware.ts 124
libs/utils/src/lib/string.ts 24
libs/utils/src/lib/string.ts 25
libs/utils/src/lib/string.ts 34
libs/utils/src/lib/string.ts 45
libs/utils/src/lib/string.ts 46
libs/utils/src/lib/string.ts 47

Fix: Replace .replace(/pattern/g, ...) with .replaceAll(pattern, ...).

S7741 — Compare with undefined directly instead of typeof (2 issues) → FIX

File Line
apps/web/src/contexts/theme-context.tsx 44
apps/web/src/contexts/theme-context.tsx 49

Fix: Change typeof x !== 'undefined' to x !== undefined.

S7755 — Use .at() instead of [length - index] (2 issues) → FIX

File Line
apps/order-service/src/storefront/storefront.service.ts 152
libs/gridflock-core/src/lib/geometry/base-plate.ts 234

Fix: Replace arr[arr.length - 1] with arr.at(-1).

S6606 — Use ??= instead of assignment expression (2 issues) → FIX

File Line
apps/web/src/lib/indexed-db.ts 41
libs/gridflock-core/src/lib/geometry/grid-cells.ts 17

Fix: Replace x = x ?? value or if (x == null) x = value with x ??= value.

S3863 — Merge duplicate imports (2 issues) → FIX

File Line
apps/order-service/src/orders/orders.controller.ts 21
apps/order-service/src/orders/orders.controller.ts 31

Fix: Merge duplicate @forma3d/service-common import statements into one.

S7778 — Consolidate multiple Array#push() calls (1 issue) → FIX

File Line
libs/config/src/lib/env-validation.ts 127

Fix: Combine consecutive .push() calls into a single .push(a, b, c).

S7744 — Remove unnecessary fallback object in spread (1 issue) → FIX

File Line
apps/gateway/src/swagger/swagger-aggregator.service.ts 53

Fix: Remove the empty object fallback (e.g., { ...(obj || {}) }{ ...obj }).

S7735 — Flip negated condition (1 issue) → FIX

File Line
apps/web/src/components/mappings/simplyprint-file-picker-modal.tsx 78

Fix: Flip !condition ? a : b to condition ? b : a.

S7780 — Use String.raw for escaped backslashes (1 issue) → FIX

File Line
libs/service-common/src/lib/storefront/storefront-origins.ts 34

Fix: Use String.raw\...`` for regex patterns with backslash escapes.

S7787 — Empty export specifiers (1 issue) → SUPPRESS

File Line
apps/order-service/src/common/decorators/index.ts 1

Verdict: This export {}; was intentionally placed to keep the barrel file after moving decorators to @forma3d/service-common. Suppress in sonar properties.


Phase 2: Moderate Auto-fixes (70 issues)

S6759 — React props should be read-only (49 issues) → FIX

All 49 in apps/web/src/. Component props interfaces/types need to be wrapped with Readonly<Props> or use readonly modifiers.

Full file list (49 files) | File | Line | |------|-----:| | `apps/web/src/components/analytics/analytics-period-dropdown.tsx` | 15 | | `apps/web/src/components/analytics/order-status-chart.tsx` | 26 | | `apps/web/src/components/analytics/print-job-status-chart.tsx` | 25 | | `apps/web/src/components/analytics/shipment-status-chart.tsx` | 26 | | `apps/web/src/components/charts/bar-chart.tsx` | 23 | | `apps/web/src/components/charts/chart-card.tsx` | 13 | | `apps/web/src/components/charts/donut-chart.tsx` | 27 | | `apps/web/src/components/charts/line-chart.tsx` | 22 | | `apps/web/src/components/inventory/stock-adjustment-modal.tsx` | 31 | | `apps/web/src/components/logo.tsx` | 11 | | `apps/web/src/components/logo.tsx` | 44 | | `apps/web/src/components/logs/log-detail-modal.tsx` | 116 | | `apps/web/src/components/logs/log-detail-modal.tsx` | 175 | | `apps/web/src/components/mappings/part-library-modal.tsx` | 30 | | `apps/web/src/components/mappings/shopify-product-picker-modal.tsx` | 29 | | `apps/web/src/components/mappings/simplyprint-file-picker-modal.tsx` | 22 | | `apps/web/src/components/orders/shipping-info.tsx` | 43 | | `apps/web/src/components/ui/badge.tsx` | 10 | | `apps/web/src/components/ui/card.tsx` | 42 | | `apps/web/src/components/ui/confirm-modal.tsx` | 18 | | `apps/web/src/components/ui/empty-state.tsx` | 12 | | `apps/web/src/components/ui/loading.tsx` | 8 | | `apps/web/src/components/ui/loading.tsx` | 42 | | `apps/web/src/components/ui/loading.tsx` | 55 | | `apps/web/src/components/ui/modal.tsx` | 14 | | `apps/web/src/components/ui/pagination.tsx` | 47 | | `apps/web/src/components/users/change-password-modal.tsx` | 12 | | `apps/web/src/components/users/user-form-modal.tsx` | 32 | | `apps/web/src/contexts/auth-context.tsx` | 40 | | `apps/web/src/contexts/service-worker-context.tsx` | 32 | | `apps/web/src/contexts/socket-context.tsx` | 20 | | `apps/web/src/contexts/theme-context.tsx` | 57 | | `apps/web/src/pages/dashboard.tsx` | 67 | | `apps/web/src/pages/inventory/config.tsx` | 44 | | `apps/web/src/pages/inventory/config.tsx` | 217 | | `apps/web/src/pages/inventory/index.tsx` | 44 | | `apps/web/src/pages/inventory/index.tsx` | 65 | | `apps/web/src/pages/inventory/replenishment.tsx` | 48 | | `apps/web/src/pages/mappings/new.tsx` | 25 | | `apps/web/src/pages/orders/index.tsx` | 34 | | `apps/web/src/pages/orders/index.tsx` | 48 | | `apps/web/src/pages/settings/feature-flags.tsx` | 16 | | `apps/web/src/pages/settings/feature-flags.tsx` | 48 | | `apps/web/src/pages/settings/simplyprint-files.tsx` | 219 | | `apps/web/src/pages/settings/simplyprint-files.tsx` | 367 | | `apps/web/src/pwa/pull-to-refresh.tsx` | 11 | | `apps/web/src/pwa/push-permission.tsx` | 85 | | `apps/web/src/router.tsx` | 87 | | `apps/web/src/router.tsx` | 113 |

Fix pattern: Change function Component(props: Props) or interface Props { ... } to use Readonly<Props>.

S4624 — Nested template literals (10 issues) → FIX

File Line
apps/order-service/src/print-jobs/print-jobs.service.ts 341, 355
apps/print-service/src/internal/internal.controller.ts 208
apps/print-service/src/print-jobs/print-jobs.service.ts 344, 358
apps/web/src/components/analytics/order-status-chart.tsx 55
apps/order-service/src/shopify/shopify-admin.controller.ts 99
apps/order-service/src/shopify/shopify-api.client.ts 316, 419
apps/print-service/src/simplyprint/simplyprint-api.client.ts 1301

Fix: Extract inner template literal to a variable before the outer template.

S6819 — Use <section> tag instead of ARIA role="region" (6 issues) → FIX

File Line
apps/web/src/components/charts/chart-card.tsx 22
apps/web/src/components/mappings/part-library-modal.tsx 86
apps/web/src/components/mappings/shopify-product-picker-modal.tsx 111, 184, 206
apps/web/src/components/mappings/simplyprint-file-picker-modal.tsx 90

Fix: Replace <div role="region" aria-label="..."> with <section aria-label="...">.

S4323 — Type aliases should be used (2 issues) → FIX

File Line
apps/order-service/src/shopify/shopify-api.client.ts 164
apps/web/src/lib/constants.ts 7

Fix: Extract inline union types to named type aliases.

S6571 — Redundant unknown in union type (2 issues) → FIX

File Line
libs/service-common/src/lib/auth/decorators/current-user.decorator.ts 6
libs/domain-contracts/src/lib/types.ts 68

Fix: unknown absorbs all other types in a union — simplify to just unknown or remove it.

S6754 — useState should be destructured symmetrically (1 issue) → FIX

File Line
apps/web/src/contexts/theme-context.tsx 58

Fix: Ensure useState is destructured as [value, setValue] with matching naming.


Phase 3: Manual Refactoring (71 issues)

S3358 — Nested ternary operations (45 issues) → MIXED

Most appear in React JSX where ternaries are a common rendering pattern. Some in backend services are genuinely hard to read.

Full file list (45 locations) | File | Line | |------|-----:| | `apps/gateway/src/health/health.controller.ts` | 79 | | `apps/order-service/src/common/guards/ws-api-key.guard.ts` | 47 | | `apps/order-service/src/simplyprint/simplyprint-api.client.ts` | 286 | | `apps/print-service/src/simplyprint/simplyprint-api.client.ts` | 439 | | `apps/web/src/components/charts/chart-card.tsx` | 45 | | `apps/web/src/components/inventory/stock-adjustment-modal.tsx` | 73 | | `apps/web/src/components/logs/log-detail-modal.tsx` | 152 | | `apps/web/src/components/mappings/part-library-modal.tsx` | 80 | | `apps/web/src/components/mappings/shopify-product-picker-modal.tsx` | 90, 96, 98 | | `apps/web/src/components/mappings/simplyprint-file-picker-modal.tsx` | 68, 68, 76, 78, 82 | | `apps/web/src/components/users/user-form-modal.tsx` | 213 | | `apps/web/src/pages/admin/audit-logs/index.tsx` | 294 | | `apps/web/src/pages/admin/users.tsx` | 252 | | `apps/web/src/pages/dashboard.tsx` | 323, 367 | | `apps/web/src/pages/inventory/config.tsx` | 170 | | `apps/web/src/pages/inventory/index.tsx` | 214 | | `apps/web/src/pages/logs/index.tsx` | 301 | | `apps/web/src/pages/mappings/index.tsx` | 87 | | `apps/web/src/pages/mappings/new.tsx` | 567 | | `apps/web/src/pages/orders/[id].tsx` | 313 | | `apps/web/src/pages/orders/index.tsx` | 147, 149, 249 | | `apps/web/src/pages/settings/index.tsx` | 688, 879, 887, 889, 954, 986, 1038, 1040, 1288 | | `apps/web/src/pages/settings/integrations.tsx` | 520, 582, 733 | | `apps/web/src/pages/settings/simplyprint-files.tsx` | 253, 399 | | `apps/web/src/pwa/push-permission.tsx` | 228 |

Recommendation: - Backend (5 issues): Refactor to if/else or lookup maps — these are readable improvements. - Frontend JSX (40 issues): Many are idiomatic JSX patterns (conditional rendering). Consider suppressing S3358 for apps/web/src/** in sonar properties if the team accepts this pattern, or refactor the most deeply nested ones (3+ levels) into helper functions.

S6853 — Form labels must be associated with a control (19 issues) → FIX

All in apps/web/src/. These are accessibility violations where <label> elements lack htmlFor or don't wrap the associated <input>.

Full file list (19 locations) | File | Line | |------|-----:| | `apps/web/src/components/inventory/stock-adjustment-modal.tsx` | 147 | | `apps/web/src/components/orders/shipping-info.tsx` | 230 | | `apps/web/src/components/users/user-form-modal.tsx` | 152 | | `apps/web/src/pages/inventory/config.tsx` | 271, 283, 299, 318 | | `apps/web/src/pages/inventory/transactions.tsx` | 90 | | `apps/web/src/pages/mappings/new.tsx` | 157, 174, 195, 219 | | `apps/web/src/pages/settings/integrations.tsx` | 622, 634, 776, 793, 842, 854 | | `apps/web/src/pwa/push-permission.tsx` | 246 |

Fix: Add htmlFor="inputId" to <label> and matching id="inputId" to the input, or wrap the input inside the label element.

S4325 — Unnecessary type assertions (7 issues) → CAREFUL REVIEW

File Line
apps/order-service/src/sendcloud/sendcloud.service.ts 84
apps/order-service/src/users/users.repository.ts 170
apps/order-service/src/users/users.service.ts 143, 158, 178
apps/shipping-service/src/sendcloud/sendcloud.service.ts 107
apps/web/src/components/logs/log-detail-modal.tsx 106

⚠️ Caution: Previous attempts to remove type assertions in sendcloud.service.ts and users.service.ts caused TypeScript compilation errors. Each must be individually verified — only remove if the compiler agrees the type is already correct.


Phase 4: Complex Refactoring (72 issues)

S3776 — Cognitive Complexity too high (23 issues) → REFACTOR

These are the most architecturally significant issues. Each function exceeds the complexity threshold of 15.

File Line Description
libs/service-common/src/lib/shipments/shipments.service.ts 192 Shipment status sync
apps/gateway/src/swagger/swagger-aggregator.service.ts 109 Swagger merge
apps/gridflock-service/src/gridflock/gridflock-pipeline.service.ts 73 Generation pipeline
apps/order-service/src/orchestration/orchestration.service.ts 100 Order orchestration
apps/order-service/src/print-jobs/print-jobs.service.ts 248, 370 Print job sync
apps/order-service/src/shopify/shopify-backfill.service.ts 237, 312 Shopify backfill
apps/order-service/src/stock-replenishment/stock-replenishment.service.ts 80 Stock replenishment
apps/print-service/src/internal/internal.controller.ts 157 Internal endpoint
apps/print-service/src/print-jobs/print-jobs.service.ts 251, 373 Print job sync
apps/print-service/src/simplyprint/simplyprint-reconciliation.service.ts 95 Reconciliation
apps/shipping-service/src/sendcloud/sendcloud-reconciliation.service.ts 89 Reconciliation
apps/web/src/components/mappings/simplyprint-file-picker-modal.tsx 22 File picker UI
apps/web/src/pages/orders/index.tsx 98 Orders page
apps/web/src/pages/settings/index.tsx 123, 475, 767 Settings page
apps/web/src/pages/settings/integrations.tsx 71 Integrations
libs/gridflock-core/src/lib/border-generator.ts 209 Border generation
libs/gridflock-core/src/lib/plate-set-calculator.ts 45 Plate calculation
libs/gridflock-core/src/lib/preview-generator.ts 199 Preview generation

Recommendation: Prioritize functions with complexity > 25. Extract helper functions, use early returns, replace nested if/else with guard clauses. settings/index.tsx alone has 3 flagged functions — consider splitting into sub-components.

S6551 — Objects coerced to strings without toString() (47 issues) → MIXED

Concentrated in 3 files: - libs/service-common/src/lib/notifications/email.service.ts — 5 issues - apps/order-service/src/simplyprint/simplyprint-api.client.ts — 18 issues - apps/print-service/src/simplyprint/simplyprint-api.client.ts — 21 issues - apps/web/src/components/charts/donut-chart.tsx — 1 issue - apps/web/src/components/logs/log-detail-modal.tsx — 2 issues

Analysis: Most are template literal interpolations like `${context['someKey']}` where the value is typed as unknown or Record<string, unknown> but is actually a string at runtime. These are typically safe but SonarCloud flags them because the static type could be an object.

Recommendation: - For email.service.ts: Add explicit String(value) casts or narrow the type of context values. - For simplyprint-api.client.ts (both services): These are API response interpolations — add String() wrapping or type-narrow the response fields.

S107 — Too many parameters (2 issues) → MIXED

File Line Verdict
apps/order-service/src/audit/audit.controller.ts 28 Fix — consolidate query params into a DTO
libs/gridflock-core/src/lib/border-generator.ts 26 Won't fix — geometric parameters are inherently numerous

Phase 5: Won't Fix / Suppress (10 issues)

S7785 — Top-level await preferred (5 issues) → WON'T FIX

File Line
apps/gateway/src/main.ts 270
apps/gridflock-service/src/main.ts 75
apps/order-service/src/main.ts 83
apps/print-service/src/main.ts 72
apps/shipping-service/src/main.ts 70

Reason: NestJS bootstrap uses bootstrap().catch(...) by convention. Top-level await changes module loading semantics and is not recommended for NestJS entry points.

S7726 — Default exports should be named (4 issues) → WON'T FIX

File Line
apps/gridflock-service/src/config/configuration.ts 26
apps/order-service/src/config/configuration.ts 88
apps/print-service/src/config/configuration.ts 38
apps/shipping-service/src/config/configuration.ts 47

Reason: NestJS registerAs() returns a factory function — naming it is unnecessary and adds noise.

S7787 — Empty export specifiers (1 issue) → WON'T FIX

File Line
apps/order-service/src/common/decorators/index.ts 1

Reason: Intentional empty barrel file after moving decorators to @forma3d/service-common. Keeps import paths stable.


Phase 6: Duplication Reduction

Overall duplication dropped from 19.5% → 15.7% after the D1–D9 extraction effort (2026-03-12). Remaining duplication: 10,743 lines across 105 files in 202 blocks.

Top Duplication Clusters

D1: Retry Queue — order-service ↔ shipping-service (~95%)

File Dup %
apps/order-service/src/retry-queue/retry-queue.repository.ts 94.9%
apps/shipping-service/src/retry-queue/retry-queue.repository.ts 94.9%
apps/order-service/src/retry-queue/retry-queue.service.ts 94.6%
apps/shipping-service/src/retry-queue/retry-queue.service.ts 94.6%
apps/order-service/src/retry-queue/retry-queue.processor.ts 48.2%
apps/shipping-service/src/retry-queue/retry-queue.processor.ts 60.4%

Recommendation: Extract to libs/service-common/src/lib/retry-queue/. Repository and service are nearly identical. Processor has service-specific job handling but a shared base class could be extracted.

D2: SendCloud — order-service ↔ shipping-service (~90%)

File Dup %
apps/order-service/src/sendcloud/sendcloud.service.ts 94.4%
apps/shipping-service/src/sendcloud/sendcloud.service.ts 90.3%
apps/order-service/src/sendcloud/sendcloud-webhook.service.ts 90.2%
apps/shipping-service/src/sendcloud/sendcloud-webhook.service.ts 92.9%
apps/order-service/src/sendcloud/sendcloud.controller.ts 74.9%
apps/shipping-service/src/sendcloud/sendcloud.controller.ts 65.8%
apps/order-service/src/sendcloud/sendcloud-initializer.service.ts 81.3%
apps/shipping-service/src/sendcloud/sendcloud-initializer.service.ts 81.3%
apps/shipping-service/src/sendcloud/sendcloud-api.client.ts 73.4%

Recommendation: Extract shared SendCloud service, webhook handler, and initializer to libs/service-common/src/lib/sendcloud/. The API client is only in shipping-service but shares patterns.

D3: SimplyPrint — order-service ↔ print-service (~88%)

File Dup %
apps/order-service/src/simplyprint/dto/simplyprint-job.dto.ts 91.7%
apps/print-service/src/simplyprint/dto/simplyprint-job.dto.ts 91.7%
apps/order-service/src/simplyprint/dto/simplyprint-printer.dto.ts 85.2%
apps/print-service/src/simplyprint/dto/simplyprint-printer.dto.ts 85.2%
apps/order-service/src/simplyprint/simplyprint.service.ts 89.8%
apps/print-service/src/simplyprint/simplyprint.service.ts 87.4%
apps/order-service/src/simplyprint/simplyprint-api.client.ts 89.2%
apps/print-service/src/simplyprint/simplyprint-api.client.ts 50.1%
apps/order-service/src/simplyprint/simplyprint-initializer.service.ts 50.8%
apps/print-service/src/simplyprint/simplyprint-initializer.service.ts 48.5%
apps/order-service/src/simplyprint/simplyprint-files.controller.ts 56.3%
apps/print-service/src/simplyprint/simplyprint-files.controller.ts 19.0%

Recommendation: Extract shared SimplyPrint DTOs, base API client, and shared service to a libs/simplyprint-common or libs/service-common/src/lib/simplyprint/ module. The API client in print-service is a superset — use it as the shared base.

D4: Cross-Service Infrastructure (~85%)

File Dup % Count
*/auth/permissions.ts 87.7% 4 services
*/common/correlation/correlation.service.ts 87.5% 4 services
*/common/correlation/correlation.middleware.ts 85.7% 4 services
*/common/guards/api-key.guard.ts 67.0% 4 services
*/throttler/throttler.module.ts 73.3% 4 services

Recommendation: Extract correlation service/middleware, API key guard, and throttler module to libs/service-common. The permissions.ts files are intentionally per-service (different permission sets) — these are expected duplicates.

D5: Print Jobs — order-service ↔ print-service (~83%)

File Dup %
apps/order-service/src/print-jobs/print-jobs-admin.controller.ts 87.6%
apps/print-service/src/print-jobs/print-jobs-admin.controller.ts 87.6%
apps/order-service/src/print-jobs/print-jobs.controller.ts 82.9%
apps/print-service/src/print-jobs/print-jobs.controller.ts 82.9%
apps/order-service/src/print-jobs/print-jobs.service.ts 80.9%
apps/print-service/src/print-jobs/print-jobs.service.ts 76.3%

Recommendation: The admin controllers and main controllers are near-identical. Extract shared controllers to libs/service-common (similar to the existing D8 pattern for print-job DTOs/events/repository). The services differ more — keep service-specific.

D6: Auth Controllers (~83%)

File Dup %
apps/print-service/src/auth/auth.controller.ts 82.9%
apps/gridflock-service/src/auth/auth.controller.ts 82.9%
apps/gateway/src/auth/auth.controller.ts 28.8%

Recommendation: Extract shared auth controller to libs/service-common. Gateway's auth controller is a superset (SSO + standard auth).

D7: Health Controllers (~55%)

File Dup %
apps/print-service/src/health/health.controller.ts 54.5%
apps/shipping-service/src/health/health.controller.ts 54.5%
apps/gridflock-service/src/health/health.controller.ts 26.0%
apps/order-service/src/health/health.controller.ts 8.4%

Recommendation: Extract a shared health controller base class. Each service adds its own health indicators, but the boilerplate is identical.

D8: Notification Event Handlers (~71%)

File Dup %
apps/order-service/src/notifications/notification-event-handlers.service.ts 71.1%
apps/print-service/src/notifications/notification-event-handlers.service.ts 71.1%
apps/shipping-service/src/notifications/notification-event-handlers.service.ts 71.1%

Recommendation: Extract shared event handler patterns. Each service handles different events but the handler structure (logging, error handling, notification dispatch) is identical.

D9: App Modules (~60%)

File Dup %
apps/print-service/src/app/app.module.ts 60.4%
apps/shipping-service/src/app/app.module.ts 60.4%
apps/gridflock-service/src/app/app.module.ts 26.4%
apps/order-service/src/app/app.module.ts 14.8%

Recommendation: The shared module imports (Database, Auth, Observability, Config, etc.) are already extracted to libs/service-common. The remaining duplication is the import list itself — this is structural and expected for NestJS. Won't fix.

Duplication Priority

Priority Cluster Est. Reduction Effort
High D1: Retry Queue ~700 lines 4 hours
High D4: Infrastructure (correlation, guards, throttler) ~600 lines 3 hours
Medium D2: SendCloud ~1,200 lines 6 hours
Medium D3: SimplyPrint ~1,500 lines 8 hours
Low D5: Print Jobs controllers ~400 lines 2 hours
Low D6: Auth Controllers ~200 lines 1 hour
Low D7: Health Controllers ~150 lines 1 hour
Low D8: Notification Handlers ~200 lines 1 hour
Skip D9: App Modules Structural duplication

Progress Since Previous Report

Metric 2026-03-12 2026-03-13 Change
Total issues 769 244 -68%
Bugs 9 0 -100%
Vulnerabilities 12 0 -100%
Code smells 748 244 -67%
Duplication 19.5% 15.7% -3.8pp
Duplicated lines ~13,300 10,743 -19%
Security hotspots 6 (TO_REVIEW) 6 (suppressed) resolved