Skip to content

Iteration 2 2#59

Merged
JuergGood merged 28 commits intomasterfrom
iteration-2-2
Mar 28, 2026
Merged

Iteration 2 2#59
JuergGood merged 28 commits intomasterfrom
iteration-2-2

Conversation

@JuergGood
Copy link
Copy Markdown
Owner

UX / UI Change PR

Scope

  • Dark mode
  • Mobile layout
  • Tables/logs/admin views
  • Tasks/list layouts
  • Other:

Acceptance criteria (must be explicit)

What changed (systemic first)

  • Tokens/theme:
  • Shared components/styles:
  • Component-specific changes (only if necessary):

Screens / viewports verified

  • Mobile 375×667 light
  • Mobile 375×667 dark
  • Desktop 1440×900 light
  • Desktop 1440×900 dark

UX Regression Checklist (must all be ✅)

Theme & contrast

  • Action icons visible in dark mode (incl. mat-icon-button + destructive actions)
  • Menus/dialogs/selects have readable contrast in dark mode
  • Focus ring visible (keyboard navigation)

Mobile space & layout

  • Header density acceptable (content above the fold on 375×667)
  • No unintended horizontal scrolling on mobile

Responsive patterns

  • Tables on mobile: cards or usable scroll (no clipped headers)
  • Toolbars/filters don’t create orphan controls / accidental wraps
  • Titles don’t break mid-word; truncation/wrapping intentional

Maintainability

  • No new hardcoded hex colors (unless added to tokens)
  • No new !important (or justified below)

Justifications (required if any)

  • New !important added because:
  • Component-specific workaround added because:

…ice: Introduce `onboarding-assistant.component.spec.ts` with comprehensive component behavior tests. Refactor `AuthService` for improved logout handling and inject dependencies. Update `auth.interceptor` to call `logoutLocally` on unauthorized errors.
…edgeCoverageController` for managing AI doc trees, implemented `FolderNodeDto` for hierarchical structure, enhanced telemetry logs, and added new frontend components for document tree display and filtering.
…mated cross-document consistency evaluations, introduced `AiConsistencyController` and DTOs to manage and expose consistency reports via API, and updated frontend to display results.
… for improved documentation organization. Reorganize AI architecture poster into the backlog and add comprehensive updates for AI-Arch doc. Polish Copilot UI layout and enhance layout consistency.
…ormalization with updates to AI-UI-INTEL-02 and ADR linkage. Add ADR-0075 and ADR-0099 references for formal decision tracking and archival.
…document cleanup and consistency. Update coverage report timestamps for synchronization. Adjust iterations and update timestamps in AI task documents for standardized tracking. Add related task references to multiple ADRs for improved traceability.
…tation for improved compliance and accountability.
… efficiency. Reorganize software development description in presentation, adjust risk item list initialization in backend, and ensure response list mutability in tests. Optimize HTML loops with $index tracking and synchronize SQL index conventions. Add user
…. Adjust AI documentation paths in `ai-admin.service.spec.ts` tests for improved accuracy. Update AI Knowledge Coverage Report timestamps for consistency.
…. Adjust AI documentation paths in `ai-admin.service.spec.ts` tests for improved accuracy. Update AI Knowledge Coverage Report timestamps for consistency.
- Switch Sonar project key to `JuergGood_angularai` for scripting and configuration
- Add comprehensive unit tests for AI client retry logic
- Introduce new frontend unit test suite for `BaseAiComponent`
- Implement intro slides generating doc template
- Expand `AiApplicationServiceTest` with delegation tests
- Integrate branch detection in `sonar-analysis.sh`
- Update `SonarProjectVersion` to `2.1.0`
- Add `RiskRadarUseCaseImplTest` for risk analysis validation
…ed readability. Update image caption and adjust timeline details.
…, and other DTOs. Update dependencies and configuration in `pom.xml`. Adapt multiple test classes to `WebMvcTest`, introduce Mockito beans, and enhance IP masking logic in `ActionLogServiceTest`. Adjust `TaskParserService` date and time parsing, and refine presentation content for better readability.
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
…r enhanced clarity. Adjust column formatting for consistent layout in `goodone-intro.md` and `goodone-intro-img.md`.
…arity and consistency. Adjust descriptions and improve narrative flow.
…arity and consistency. Adjust phrasing, headings, and narrative flow to enhance readability and comprehension.
…arity and consistency. Adjust phrasing, headings, and narrative flow to enhance readability and comprehension.
…arity and consistency. Adjust phrasing, headings, and narrative flow for improved readability and comprehension.
…ed column layouts in `goodone-intro.md`. Adjust content for improved comprehension and consistency.
… for enhanced content structure and clarity.
@@ -1,6 +1,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AdrDriftComponent } from './adr-drift.component';
import { AiService } from '../../services/ai.service';
import { AiService, TaskGroup, TaskGroupType } from '../../services/ai.service';

Check notice

Code scanning / CodeQL

Unused variable, import, function or class Note test

Unused imports TaskGroup, TaskGroupType.

Copilot Autofix

AI 6 days ago

In general, unused imports should be removed or minimized so only the actually used symbols are imported. This improves readability and avoids confusion about expected usage.

Here, the best fix is to keep importing AiService (which is used in the TestBed provider configuration) and drop TaskGroup and TaskGroupType from the import statement. This is a simple textual change confined to the import line at the top of frontend/src/app/components/adr-drift/adr-drift.component.spec.ts. No new methods, variables, or additional imports are required.

Suggested changeset 1
frontend/src/app/components/adr-drift/adr-drift.component.spec.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/frontend/src/app/components/adr-drift/adr-drift.component.spec.ts b/frontend/src/app/components/adr-drift/adr-drift.component.spec.ts
--- a/frontend/src/app/components/adr-drift/adr-drift.component.spec.ts
+++ b/frontend/src/app/components/adr-drift/adr-drift.component.spec.ts
@@ -1,6 +1,6 @@
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { AdrDriftComponent } from './adr-drift.component';
-import { AiService, TaskGroup, TaskGroupType } from '../../services/ai.service';
+import { AiService } from '../../services/ai.service';
 import { AuthService } from '../../services/auth.service';
 import { SystemService } from '../../services/system.service';
 import { GoogleRecaptchaService } from '../../services/google-recaptcha.service';
EOF
@@ -1,6 +1,6 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { AdrDriftComponent } from './adr-drift.component';
import { AiService, TaskGroup, TaskGroupType } from '../../services/ai.service';
import { AiService } from '../../services/ai.service';
import { AuthService } from '../../services/auth.service';
import { SystemService } from '../../services/system.service';
import { GoogleRecaptchaService } from '../../services/google-recaptcha.service';
Copilot is powered by AI and may make mistakes. Always verify output.
@@ -11,6 +11,7 @@
import { describe, it, expect, beforeEach, vi } from 'vitest';
import { provideRouter } from '@angular/router';
import { MatDatepickerInputEvent } from '@angular/material/datepicker';
import { AdrDriftResponse } from '../../models/retrospective.model';

Check notice

Code scanning / CodeQL

Unused variable, import, function or class Note test

Unused import AdrDriftResponse.

Copilot Autofix

AI 6 days ago

In general, to fix an unused import, you either start using it meaningfully in the code (if it was intended to be used) or remove it if it is unnecessary. Since none of the tests in this spec file use AdrDriftResponse, the simplest, behavior-preserving fix is to delete the unused import line.

Concretely, in frontend/src/app/components/adr-drift/adr-drift.component.spec.ts, remove line 14:

import { AdrDriftResponse } from '../../models/retrospective.model';

No additional code, imports, or definitions are needed. This change does not affect runtime behavior or the existing test logic; it only cleans up an unused symbol.

Suggested changeset 1
frontend/src/app/components/adr-drift/adr-drift.component.spec.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/frontend/src/app/components/adr-drift/adr-drift.component.spec.ts b/frontend/src/app/components/adr-drift/adr-drift.component.spec.ts
--- a/frontend/src/app/components/adr-drift/adr-drift.component.spec.ts
+++ b/frontend/src/app/components/adr-drift/adr-drift.component.spec.ts
@@ -11,8 +11,8 @@
 import { describe, it, expect, beforeEach, vi } from 'vitest';
 import { provideRouter } from '@angular/router';
 import { MatDatepickerInputEvent } from '@angular/material/datepicker';
-import { AdrDriftResponse } from '../../models/retrospective.model';
 
+
 describe('AdrDriftComponent', () => {
   let component: AdrDriftComponent;
   let fixture: ComponentFixture<AdrDriftComponent>;
EOF
@@ -11,8 +11,8 @@
import { describe, it, expect, beforeEach, vi } from 'vitest';
import { provideRouter } from '@angular/router';
import { MatDatepickerInputEvent } from '@angular/material/datepicker';
import { AdrDriftResponse } from '../../models/retrospective.model';


describe('AdrDriftComponent', () => {
let component: AdrDriftComponent;
let fixture: ComponentFixture<AdrDriftComponent>;
Copilot is powered by AI and may make mistakes. Always verify output.
@@ -1,4 +1,4 @@
import { Component, inject } from '@angular/core';
import { Component, inject, signal } from '@angular/core';

Check notice

Code scanning / CodeQL

Unused variable, import, function or class Note

Unused import signal.

Copilot Autofix

AI 6 days ago

In general, unused imports should be removed from the import statement to keep the code clean and avoid linter/static-analysis violations.

Here, the best fix is to update the import from @angular/core so that it only imports the actually used symbols Component and inject, and drop signal. No other parts of the file need updating, since signal is not referenced anywhere else. This change is confined to frontend/src/app/components/error-boundary/error-boundary.component.ts, at the top of the file on line 1.

No additional methods, imports, or definitions are required; we only adjust the existing import list.

Suggested changeset 1
frontend/src/app/components/error-boundary/error-boundary.component.ts

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/frontend/src/app/components/error-boundary/error-boundary.component.ts b/frontend/src/app/components/error-boundary/error-boundary.component.ts
--- a/frontend/src/app/components/error-boundary/error-boundary.component.ts
+++ b/frontend/src/app/components/error-boundary/error-boundary.component.ts
@@ -1,4 +1,4 @@
-import { Component, inject, signal } from '@angular/core';
+import { Component, inject } from '@angular/core';
 import { CommonModule } from '@angular/common';
 import { MatCardModule } from '@angular/material/card';
 import { MatButtonModule } from '@angular/material/button';
EOF
@@ -1,4 +1,4 @@
import { Component, inject, signal } from '@angular/core';
import { Component, inject } from '@angular/core';
import { CommonModule } from '@angular/common';
import { MatCardModule } from '@angular/material/card';
import { MatButtonModule } from '@angular/material/button';
Copilot is powered by AI and may make mistakes. Always verify output.
public AdrDriftResponse execute(AdrDriftRequest request) {
log.info("Detecting ADR drift for request: {}", request);
try {
log.info("Detecting ADR drift for request: {}", request);

Check failure

Code scanning / CodeQL

Log Injection High

This log entry depends on a
user-provided value
.

Copilot Autofix

AI 6 days ago

In general, to fix log injection when logging user-provided data, either (a) avoid logging the raw user-controlled object/string entirely, or (b) sanitize it to remove or neutralize control characters (particularly \r and \n) and other problematic content before logging. Another option is to log only specific, non-sensitive, and simple fields (such as IDs) instead of the full request body.

For this specific case, the simplest fix that preserves existing functionality (diagnostic logging) while preventing injection is to stop logging the full AdrDriftRequest’s toString() and instead log a safe summary that does not depend on potentially multiline user content. For example, log just an identifier such as the sprint, and possibly a boolean indicating which options are set. Since we are constrained to only edit the shown snippets, the change will be confined to AdrDriftUseCaseImpl.execute. I will replace log.info("Detecting ADR drift for request: {}", request); with a log statement that uses a short, explicit message including only selected, low-risk fields from request (e.g., request.getSprintId() if available) or even no fields at all if we cannot safely access them without seeing the DTO. To stay within the visible code, the safest and minimal change is to drop the interpolation of request entirely, e.g., log.info("Detecting ADR drift for incoming request");, which removes the tainted sink while maintaining a useful trace that the method was invoked.

No new imports or helper methods are required; we only change the logging line in backend/src/main/java/ch/goodone/backend/ai/application/AdrDriftUseCaseImpl.java.

Suggested changeset 1
backend/src/main/java/ch/goodone/backend/ai/application/AdrDriftUseCaseImpl.java

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/backend/src/main/java/ch/goodone/backend/ai/application/AdrDriftUseCaseImpl.java b/backend/src/main/java/ch/goodone/backend/ai/application/AdrDriftUseCaseImpl.java
--- a/backend/src/main/java/ch/goodone/backend/ai/application/AdrDriftUseCaseImpl.java
+++ b/backend/src/main/java/ch/goodone/backend/ai/application/AdrDriftUseCaseImpl.java
@@ -59,7 +59,7 @@
     @Transactional(readOnly = true)
     public AdrDriftResponse execute(AdrDriftRequest request) {
         try {
-            log.info("Detecting ADR drift for request: {}", request);
+            log.info("Detecting ADR drift for incoming request");
 
             List<DocSource> adrSources = resolveAdrSources(request);
             if (adrSources.isEmpty()) {
EOF
@@ -59,7 +59,7 @@
@Transactional(readOnly = true)
public AdrDriftResponse execute(AdrDriftRequest request) {
try {
log.info("Detecting ADR drift for request: {}", request);
log.info("Detecting ADR drift for incoming request");

List<DocSource> adrSources = resolveAdrSources(request);
if (adrSources.isEmpty()) {
Copilot is powered by AI and may make mistakes. Always verify output.
}

public OllamaBenchmarkDto runBenchmark(String feature, int iterations) {
log.info("Starting Ollama latency benchmark for feature: {}, iterations: {}", feature, iterations);

Check failure

Code scanning / CodeQL

Log Injection High

This log entry depends on a
user-provided value
.

Copilot Autofix

AI 6 days ago

General fix approach: Sanitize or validate any user-provided data before logging it. For plain-text logs, this typically means stripping or normalizing control characters (especially \r/\n) and potentially restricting to a safer character set. The logging call should then use the sanitized value instead of the raw user input.

Best fix here: Introduce a small helper method in OllamaBenchmarkService that sanitizes log arguments by removing carriage return and newline characters from feature (and any future strings we choose to pass through it). Then, in runBenchmark, use this sanitized value in the log.info call, leaving the rest of the logic unchanged so functionality is preserved. We do not need new dependencies; a simple String.replace or regex replacement suffices.

Concrete changes:

  • In backend/src/main/java/ch/goodone/backend/ai/evaluation/OllamaBenchmarkService.java:

    • Add a private helper sanitizeForLog(String input) that returns null unchanged and otherwise strips \r and \n (and optionally other control characters if desired) from the string.
    • Modify the log statement on line 34 to call this helper for feature, e.g.:
      String safeFeature = sanitizeForLog(feature);
      log.info("Starting Ollama latency benchmark for feature: {}, iterations: {}", safeFeature, iterations);
    • Keep all other code intact.
  • No changes are required in AiBenchmarkController, because we are not altering behavior, only how the value is logged.

No additional imports or external libraries are necessary; we rely purely on core String operations.


Suggested changeset 1
backend/src/main/java/ch/goodone/backend/ai/evaluation/OllamaBenchmarkService.java

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/backend/src/main/java/ch/goodone/backend/ai/evaluation/OllamaBenchmarkService.java b/backend/src/main/java/ch/goodone/backend/ai/evaluation/OllamaBenchmarkService.java
--- a/backend/src/main/java/ch/goodone/backend/ai/evaluation/OllamaBenchmarkService.java
+++ b/backend/src/main/java/ch/goodone/backend/ai/evaluation/OllamaBenchmarkService.java
@@ -30,8 +30,17 @@
         this.chatModel = chatModel;
     }
 
+    private String sanitizeForLog(String input) {
+        if (input == null) {
+            return null;
+        }
+        // Remove CR and LF characters to prevent log injection via line breaks
+        return input.replace("\r", "").replace("\n", "");
+    }
+
     public OllamaBenchmarkDto runBenchmark(String feature, int iterations) {
-        log.info("Starting Ollama latency benchmark for feature: {}, iterations: {}", feature, iterations);
+        String safeFeature = sanitizeForLog(feature);
+        log.info("Starting Ollama latency benchmark for feature: {}, iterations: {}", safeFeature, iterations);
         List<OllamaBenchmarkDto.CallSample> samples = new ArrayList<>();
         
         String testPrompt = getBaselinePrompt(feature);
EOF
@@ -30,8 +30,17 @@
this.chatModel = chatModel;
}

private String sanitizeForLog(String input) {
if (input == null) {
return null;
}
// Remove CR and LF characters to prevent log injection via line breaks
return input.replace("\r", "").replace("\n", "");
}

public OllamaBenchmarkDto runBenchmark(String feature, int iterations) {
log.info("Starting Ollama latency benchmark for feature: {}, iterations: {}", feature, iterations);
String safeFeature = sanitizeForLog(feature);
log.info("Starting Ollama latency benchmark for feature: {}, iterations: {}", safeFeature, iterations);
List<OllamaBenchmarkDto.CallSample> samples = new ArrayList<>();

String testPrompt = getBaselinePrompt(feature);
Copilot is powered by AI and may make mistakes. Always verify output.
.feature(feature)
.iterations(iterations)
.successfulCalls(successful)
.failedCalls(iterations - successful)

Check failure

Code scanning / CodeQL

User-controlled data in arithmetic expression High

This arithmetic expression depends on a
user-provided value
, potentially causing an underflow.

Copilot Autofix

AI 6 days ago

In general, arithmetic on user-controlled integers should be guarded by validating or normalizing the input before use, or by constraining the result to a safe, non-negative range. Here, we are computing failedCalls as iterations - successful, where iterations may be negative or otherwise inconsistent with the actual number of samples. The best fix that preserves existing functionality is to derive failedCalls in a way that (a) does not underflow and (b) matches what the code conceptually means: number of calls attempted minus number of successful calls. Since samples already contains one entry per attempted iteration, and successful is the number of successful entries, we can compute failedCalls as samples.size() - successful. Both quantities are non‑negative and bounded by Integer.MAX_VALUE, so the subtraction cannot underflow in the current data model. Additionally, to avoid other oddities from pathological iterations values, we can clamp or validate iterations once in runBenchmark (e.g., enforce a minimum of 0 and a reasonable maximum) and propagate the normalized value through to aggregateResults. Within the constraints given, we will (1) change the failedCalls calculation to use samples.size() - successful, and (2) add a small normalization step for iterations in runBenchmark so extremely negative or huge values are not used directly in the loop or DTO.

Concretely:

  • In OllamaBenchmarkService.runBenchmark, introduce a local int normalizedIterations that ensures iterations is at least 0 and at most some safe upper bound (for example, 10_000), use it in the loop and when invoking aggregateResults.
  • In OllamaBenchmarkService.aggregateResults, change .failedCalls(iterations - successful) to .failedCalls(samples.size() - successful). Both operands are non-negative ints, so no underflow arises, and the value correctly reflects the number of failed samples.

No new methods or external libraries are required; we only adjust existing logic.

Suggested changeset 1
backend/src/main/java/ch/goodone/backend/ai/evaluation/OllamaBenchmarkService.java

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/backend/src/main/java/ch/goodone/backend/ai/evaluation/OllamaBenchmarkService.java b/backend/src/main/java/ch/goodone/backend/ai/evaluation/OllamaBenchmarkService.java
--- a/backend/src/main/java/ch/goodone/backend/ai/evaluation/OllamaBenchmarkService.java
+++ b/backend/src/main/java/ch/goodone/backend/ai/evaluation/OllamaBenchmarkService.java
@@ -31,12 +31,14 @@
     }
 
     public OllamaBenchmarkDto runBenchmark(String feature, int iterations) {
-        log.info("Starting Ollama latency benchmark for feature: {}, iterations: {}", feature, iterations);
+        // Normalize iterations to avoid negative or excessively large values from user input
+        int normalizedIterations = Math.max(0, Math.min(iterations, 10_000));
+        log.info("Starting Ollama latency benchmark for feature: {}, iterations: {}", feature, normalizedIterations);
         List<OllamaBenchmarkDto.CallSample> samples = new ArrayList<>();
         
         String testPrompt = getBaselinePrompt(feature);
         
-        for (int i = 0; i < iterations; i++) {
+        for (int i = 0; i < normalizedIterations; i++) {
             long start = System.currentTimeMillis();
             try {
                 ChatResponse response = chatModel.call(new Prompt(new UserMessage(testPrompt)));
@@ -70,7 +68,7 @@
             }
         }
 
-        return aggregateResults(feature, iterations, samples);
+        return aggregateResults(feature, normalizedIterations, samples);
     }
 
     private String getBaselinePrompt(String feature) {
@@ -122,7 +120,7 @@
                 .feature(feature)
                 .iterations(iterations)
                 .successfulCalls(successful)
-                .failedCalls(iterations - successful)
+                .failedCalls(samples.size() - successful)
                 .averageLatencyMs(avgLatency)
                 .minLatencyMs(min)
                 .maxLatencyMs(max)
EOF
@@ -31,12 +31,14 @@
}

public OllamaBenchmarkDto runBenchmark(String feature, int iterations) {
log.info("Starting Ollama latency benchmark for feature: {}, iterations: {}", feature, iterations);
// Normalize iterations to avoid negative or excessively large values from user input
int normalizedIterations = Math.max(0, Math.min(iterations, 10_000));
log.info("Starting Ollama latency benchmark for feature: {}, iterations: {}", feature, normalizedIterations);
List<OllamaBenchmarkDto.CallSample> samples = new ArrayList<>();

String testPrompt = getBaselinePrompt(feature);

for (int i = 0; i < iterations; i++) {
for (int i = 0; i < normalizedIterations; i++) {
long start = System.currentTimeMillis();
try {
ChatResponse response = chatModel.call(new Prompt(new UserMessage(testPrompt)));
@@ -70,7 +68,7 @@
}
}

return aggregateResults(feature, iterations, samples);
return aggregateResults(feature, normalizedIterations, samples);
}

private String getBaselinePrompt(String feature) {
@@ -122,7 +120,7 @@
.feature(feature)
.iterations(iterations)
.successfulCalls(successful)
.failedCalls(iterations - successful)
.failedCalls(samples.size() - successful)
.averageLatencyMs(avgLatency)
.minLatencyMs(min)
.maxLatencyMs(max)
Copilot is powered by AI and may make mistakes. Always verify output.
private NodeType type;
private DocumentCoverageDto metadata;
@Builder.Default
private List<FolderNodeDto> children = new ArrayList<>();

Check notice

Code scanning / CodeQL

Exposing internal representation Note

getChildren exposes the internal representation stored in field children. The value may be modified
after this call to getChildren
.
getChildren exposes the internal representation stored in field children. The value may be modified
after this call to getChildren
.

Copilot Autofix

AI 6 days ago

In general, to fix this problem we must prevent callers from obtaining and mutating the actual children list instance held inside FolderNodeDto. This can be done either by (1) returning an unmodifiable view of the list, or (2) returning a defensive copy (and similarly copying incoming lists in setters/constructors). Both approaches avoid exposing the mutable internal representation.

The best fix here, without changing existing functionality too much, is:

  • Disable Lombok’s automatically generated getter and setter for children.
  • Provide custom getChildren() and setChildren(...) methods:
    • getChildren() should return an unmodifiable view (Collections.unmodifiableList(children)), which preserves the actual contents while preventing external modification through the returned reference.
    • setChildren(List<FolderNodeDto> children) should make a defensive copy of the provided list (e.g., this.children = new ArrayList<>(children);) or initialize an empty list if null is passed.
  • We must also import java.util.Collections to create the unmodifiable view.
  • All changes are confined to backend/src/main/java/ch/goodone/backend/dto/FolderNodeDto.java. We will keep @Data for the other fields, but override the generated accessors for children by defining explicit methods with the same signatures.
Suggested changeset 1
backend/src/main/java/ch/goodone/backend/dto/FolderNodeDto.java

Autofix patch

Autofix patch
Run the following command in your local git repository to apply this patch
cat << 'EOF' | git apply
diff --git a/backend/src/main/java/ch/goodone/backend/dto/FolderNodeDto.java b/backend/src/main/java/ch/goodone/backend/dto/FolderNodeDto.java
--- a/backend/src/main/java/ch/goodone/backend/dto/FolderNodeDto.java
+++ b/backend/src/main/java/ch/goodone/backend/dto/FolderNodeDto.java
@@ -6,8 +6,8 @@
 import lombok.NoArgsConstructor;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
-
 /**
  * DTO for hierarchical document tree nodes.
  */
@@ -23,6 +22,26 @@
     @Builder.Default
     private List<FolderNodeDto> children = new ArrayList<>();
 
+    /**
+     * Returns an unmodifiable view of the children list to avoid exposing
+     * the internal mutable representation.
+     */
+    public List<FolderNodeDto> getChildren() {
+        return Collections.unmodifiableList(children);
+    }
+
+    /**
+     * Sets the children list using a defensive copy to avoid retaining
+     * references to externally mutable collections.
+     */
+    public void setChildren(List<FolderNodeDto> children) {
+        if (children == null) {
+            this.children = new ArrayList<>();
+        } else {
+            this.children = new ArrayList<>(children);
+        }
+    }
+
     public enum NodeType {
         FOLDER, FILE
     }
EOF
@@ -6,8 +6,8 @@
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
* DTO for hierarchical document tree nodes.
*/
@@ -23,6 +22,26 @@
@Builder.Default
private List<FolderNodeDto> children = new ArrayList<>();

/**
* Returns an unmodifiable view of the children list to avoid exposing
* the internal mutable representation.
*/
public List<FolderNodeDto> getChildren() {
return Collections.unmodifiableList(children);
}

/**
* Sets the children list using a defensive copy to avoid retaining
* references to externally mutable collections.
*/
public void setChildren(List<FolderNodeDto> children) {
if (children == null) {
this.children = new ArrayList<>();
} else {
this.children = new ArrayList<>(children);
}
}

public enum NodeType {
FOLDER, FILE
}
Copilot is powered by AI and may make mistakes. Always verify output.
@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 28, 2026

Qodana Community for JVM

4 new problems were found

Inspection name Severity Problems
'Optional' used as field or parameter type 🔶 Warning 2
Constant values 🔶 Warning 1
Nullability and data flow problems 🔶 Warning 1

💡 Qodana analysis was run in the pull request mode: only the changed files were checked

View the detailed Qodana report

To be able to view the detailed Qodana report, you can either:

To get *.log files or any other Qodana artifacts, run the action with upload-result option set to true,
so that the action will upload the files as the job artifacts:

      - name: 'Qodana Scan'
        uses: JetBrains/qodana-action@v2024.3.4
        with:
          upload-result: true
Contact Qodana team

Contact us at qodana-support@jetbrains.com

@JuergGood JuergGood merged commit 853d083 into master Mar 28, 2026
6 of 17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants