-
Notifications
You must be signed in to change notification settings - Fork 48
Implement JSON export service for intelligence products (risk, coalition, trends) #8048
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Implement JSON export service for intelligence products (risk, coalition, trends) #8048
Conversation
- Created IntelligenceExportService interface - Implemented DTOs for risk assessments, coalition alignment, temporal trends - Implemented IntelligenceExportServiceImpl with Jackson serialization - Added metadata structure following json-export-specs schema Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
....impl/src/main/java/com/hack23/cia/service/data/impl/export/CoalitionAlignmentExportDTO.java
Fixed
Show fixed
Hide fixed
...data.impl/src/main/java/com/hack23/cia/service/data/impl/export/RiskAssessmentExportDTO.java
Fixed
Show fixed
Hide fixed
...data.impl/src/main/java/com/hack23/cia/service/data/impl/export/TemporalTrendsExportDTO.java
Fixed
Show fixed
Hide fixed
- Fixed CoalitionAlignmentExportDTO to match actual entity structure - Updated service implementation to handle embeddedId properly - Added comprehensive unit tests with Mockito - All tests passing successfully Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
- Added implementation status section to README - Documented completed service layer components - Listed ready-for-integration export methods - Noted technical foundation and next steps Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request implements a JSON export service layer for intelligence products, enabling programmatic access to risk assessments, coalition alignment matrices, and temporal trend analyses. The implementation introduces a new service interface and implementation, along with supporting DTOs, to serialize data from existing DAO layer for CDN-ready static file generation.
Key Changes
- New service layer (
IntelligenceExportServiceinterface and implementation) with Jackson-based JSON serialization - Three DTO classes for structured JSON export:
RiskAssessmentExportDTO,CoalitionAlignmentExportDTO, andTemporalTrendsExportDTO - Common
ExportMetadataDTO for consistent metadata across exports - Unit tests using Mockito for the three main export methods
- Documentation updates in json-export-specs README
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| service.data.api/src/main/java/com/hack23/cia/service/data/api/IntelligenceExportService.java | Service interface defining JSON export methods for risk assessments, coalition alignment, temporal trends, and file writing |
| service.data.impl/src/main/java/com/hack23/cia/service/data/impl/IntelligenceExportServiceImpl.java | Spring service implementation integrating with existing DAOs and Jackson for JSON serialization |
| service.data.impl/src/main/java/com/hack23/cia/service/data/impl/export/ExportMetadata.java | Common metadata DTO with version, generation timestamp, schema identifier, and record count |
| service.data.impl/src/main/java/com/hack23/cia/service/data/impl/export/RiskAssessmentExportDTO.java | DTO for risk assessment JSON structure with metadata and violation list |
| service.data.impl/src/main/java/com/hack23/cia/service/data/impl/export/CoalitionAlignmentExportDTO.java | DTO for coalition alignment matrix with party voting cohesion metrics |
| service.data.impl/src/main/java/com/hack23/cia/service/data/impl/export/TemporalTrendsExportDTO.java | DTO for temporal trend analysis with daily decisions and moving averages |
| service.data.impl/src/test/java/com/hack23/cia/service/data/impl/IntelligenceExportServiceImplTest.java | Unit tests with Mockito for the three export methods |
| json-export-specs/README.md | Updated implementation status section documenting completed service layer components |
| metadata.setDataDate(new Date()); | ||
| dto.setMetadata(metadata); | ||
|
|
||
| for (final com.hack23.cia.model.internal.application.data.rules.impl.RuleViolation violation : violations) { |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fully-qualified class name is unnecessary here since RuleViolation is already imported at line 37 and used without FQCN on line 79. This should simply be:
for (final RuleViolation violation : violations) {| for (final com.hack23.cia.model.internal.application.data.rules.impl.RuleViolation violation : violations) { | |
| for (final RuleViolation violation : violations) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 5fc4262. Removed fully-qualified class name and used the imported RuleViolation directly.
| * $Id$ | ||
| * $HeadURL$ | ||
| */ | ||
| package com.hack23.cia.service.data.impl.export; |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The new export package lacks a package-info.java file. Following the pattern in service.data.impl (which has a package-info.java), add documentation for this package to describe its purpose, key classes, and relationships.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 5fc4262. Added package-info.java with comprehensive documentation describing the package purpose, key classes, and usage patterns.
| final List<ViewRiksdagenCoalitionAlignmentMatrix> alignments = new ArrayList<>(); | ||
| final ViewRiksdagenCoalitionAlignmentMatrix alignment = new ViewRiksdagenCoalitionAlignmentMatrix(); | ||
| final ViewRiksdagenCoalitionAlignmentMatrixEmbeddedId embeddedId = | ||
| new ViewRiksdagenCoalitionAlignmentMatrixEmbeddedId("S", "V"); |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test references a constructor ViewRiksdagenCoalitionAlignmentMatrixEmbeddedId(String, String) that doesn't exist in the model class. The class only has a no-argument constructor. The test should use the no-arg constructor followed by setter calls:
final ViewRiksdagenCoalitionAlignmentMatrixEmbeddedId embeddedId =
new ViewRiksdagenCoalitionAlignmentMatrixEmbeddedId();
embeddedId.setParty1("S");
embeddedId.setParty2("V");| new ViewRiksdagenCoalitionAlignmentMatrixEmbeddedId("S", "V"); | |
| new ViewRiksdagenCoalitionAlignmentMatrixEmbeddedId(); | |
| embeddedId.setParty1("S"); | |
| embeddedId.setParty2("V"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 5fc4262. Changed test to use no-arg constructor followed by setter calls for party1 and party2.
| @Override | ||
| public void writeJsonToFile(final String jsonContent, final String fileName, final String outputDirectory) | ||
| throws IOException { | ||
| final File directory = new File(outputDirectory); | ||
| if (!directory.exists()) { | ||
| directory.mkdirs(); | ||
| } | ||
|
|
||
| final String filePath = outputDirectory + File.separator + fileName; | ||
| Files.write(Paths.get(filePath), jsonContent.getBytes(StandardCharsets.UTF_8)); | ||
| } |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The writeJsonToFile method is not covered by unit tests. Add a test case to verify file creation, directory creation, and content writing behavior. Consider testing both scenarios: when the directory exists and when it needs to be created.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 5fc4262. Added 3 new tests for writeJsonToFile: testWriteJsonToFile (basic functionality), testWriteJsonToFileCreatesDirectory (directory creation), and testWriteJsonToFileRejectsPathTraversal (security validation).
| */ | ||
| @Service | ||
| @Transactional(readOnly = true) | ||
| public class IntelligenceExportServiceImpl implements IntelligenceExportService { |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The class is declared as public class which breaks the codebase convention. All other service implementations in this package use final class with package-private visibility (no public modifier). This should be:
@Service
@Transactional(readOnly = true)
final class IntelligenceExportServiceImpl implements IntelligenceExportService {| public class IntelligenceExportServiceImpl implements IntelligenceExportService { | |
| final class IntelligenceExportServiceImpl implements IntelligenceExportService { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 5fc4262. Changed from public class to final class to match codebase conventions.
| public void writeJsonToFile(final String jsonContent, final String fileName, final String outputDirectory) | ||
| throws IOException { | ||
| final File directory = new File(outputDirectory); | ||
| if (!directory.exists()) { | ||
| directory.mkdirs(); | ||
| } | ||
|
|
||
| final String filePath = outputDirectory + File.separator + fileName; | ||
| Files.write(Paths.get(filePath), jsonContent.getBytes(StandardCharsets.UTF_8)); |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The writeJsonToFile method is vulnerable to path traversal attacks. An attacker could provide a malicious fileName containing path traversal sequences (e.g., ../../etc/passwd) to write files outside the intended directory. Validate and sanitize the fileName parameter to ensure it doesn't contain directory separators or path traversal sequences:
// Validate fileName doesn't contain path separators
if (fileName.contains("/") || fileName.contains("\\") || fileName.contains("..")) {
throw new IllegalArgumentException("Invalid file name: must not contain path separators or traversal sequences");
}There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 5fc4262. Added validation to reject file names containing /, \, or .. to prevent path traversal attacks. Throws IllegalArgumentException with descriptive message.
| if (!directory.exists()) { | ||
| directory.mkdirs(); |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The use of mkdirs() without checking the return value can lead to silent failures. If directory creation fails (e.g., due to permissions), the subsequent Files.write() will fail. Check the return value and throw an appropriate exception:
if (!directory.exists() && !directory.mkdirs()) {
throw new IOException("Failed to create directory: " + outputDirectory);
}| if (!directory.exists()) { | |
| directory.mkdirs(); | |
| if (!directory.exists() && !directory.mkdirs()) { | |
| throw new IOException("Failed to create directory: " + outputDirectory); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 5fc4262. Added check for mkdirs() return value and throw IOException with descriptive message if directory creation fails.
| } | ||
|
|
||
| public List<PartyAlignment> getAlignments() { | ||
| return alignments; |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getAlignments exposes the internal representation stored in field alignments. The value may be modified after this call to getAlignments.
| return alignments; | |
| return List.copyOf(alignments); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These DTOs are specifically designed for Jackson JSON serialization where the service implementation populates the lists via dto.getAlignments().add(). Using List.copyOf() would return an immutable list causing UnsupportedOperationException. The current implementation is appropriate for DTOs used in serialization contexts.
| } | ||
|
|
||
| public List<RiskViolation> getViolations() { | ||
| return violations; |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getViolations exposes the internal representation stored in field violations. The value may be modified after this call to getViolations.
| return violations; | |
| return List.copyOf(violations); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These DTOs are specifically designed for Jackson JSON serialization where the service implementation populates the lists via dto.getViolations().add(). Using List.copyOf() would return an immutable list causing UnsupportedOperationException. The current implementation is appropriate for DTOs used in serialization contexts.
| this.metadata = metadata; | ||
| } | ||
|
|
||
| public List<TrendDataPoint> getTrends() { |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getTrends exposes the internal representation stored in field trends. The value may be modified after this call to getTrends.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These DTOs are specifically designed for Jackson JSON serialization where the service implementation populates the lists via dto.getTrends().add(). Using List.copyOf() would return an immutable list causing UnsupportedOperationException. The current implementation is appropriate for DTOs used in serialization contexts.
|
@copilot apply changes based on the comments in this thread |
- Remove fully-qualified class name (comment 2598282975) - Add package-info.java for export package (comment 2598283023) - Fix test constructor to use no-arg constructor + setters (comment 2598283044) - Add tests for writeJsonToFile method (comment 2598283082) - Change class to final instead of public (comment 2598283106) - Add path traversal validation in writeJsonToFile (comment 2598283138) - Check mkdirs() return value (comment 2598283162) - Keep original getter implementation in DTOs (needed for Jackson serialization) All 6 unit tests passing Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
All review comments have been addressed in commit 5fc4262:
All 6 unit tests passing. Ready for re-review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 5 comments.
| public IntelligenceExportServiceImpl() { | ||
| this.objectMapper = new ObjectMapper(); | ||
| this.objectMapper.enable(SerializationFeature.INDENT_OUTPUT); | ||
| this.objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); | ||
| } |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ObjectMapper is configured to disable WRITE_DATES_AS_TIMESTAMPS, but Jackson also needs a date format configuration to properly serialize dates as ISO 8601 strings. Without an explicit date format, dates may not serialize consistently.
Consider adding:
this.objectMapper.setDateFormat(new StdDateFormat().withColonInTimeZone(true));This ensures dates are serialized as ISO 8601 strings (e.g., "2024-12-08T11:12:00Z") as described in the PR description.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in ac4dbfe. Added StdDateFormat().withColonInTimeZone(true) configuration to ObjectMapper to ensure dates are serialized as ISO 8601 strings (e.g., "2024-12-08T11:12:00Z").
| if (fileName.contains("/") || fileName.contains("\\") || fileName.contains("..")) { | ||
| throw new IllegalArgumentException("Invalid file name: must not contain path separators or traversal sequences"); | ||
| } |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The security validation for path traversal is incomplete. The check fileName.contains("..") will reject legitimate file names like "risk-2024..2025.json" that contain ".." as part of the content, not just as a traversal sequence.
A more robust check should validate that the resolved path stays within the target directory:
final Path targetDir = Paths.get(outputDirectory).toAbsolutePath().normalize();
final Path resolvedPath = targetDir.resolve(fileName).normalize();
if (!resolvedPath.startsWith(targetDir)) {
throw new IllegalArgumentException("Invalid file name: path traversal detected");
}This approach properly prevents path traversal while allowing legitimate file names.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in ac4dbfe. Replaced simple string contains check with robust path validation using Path.normalize() and startsWith() to properly detect path traversal while allowing legitimate file names. The implementation now validates that the resolved path stays within the target directory.
| // Act & Assert - Test various path traversal attempts | ||
| assertThrows(IllegalArgumentException.class, () -> | ||
| service.writeJsonToFile(jsonContent, "../etc/passwd", tempDir.toString())); | ||
|
|
||
| assertThrows(IllegalArgumentException.class, () -> | ||
| service.writeJsonToFile(jsonContent, "..\\windows\\system32\\config", tempDir.toString())); | ||
|
|
||
| assertThrows(IllegalArgumentException.class, () -> | ||
| service.writeJsonToFile(jsonContent, "path/to/file.json", tempDir.toString())); | ||
|
|
||
| assertThrows(IllegalArgumentException.class, () -> | ||
| service.writeJsonToFile(jsonContent, "path\\to\\file.json", tempDir.toString())); | ||
| } |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The test description "Test various path traversal attempts" includes a case that tests legitimate path usage ("path/to/file.json") which should arguably be allowed for creating files in subdirectories. However, this conflicts with the current implementation which rejects all path separators.
If the intention is to only allow flat file names in the specified directory (no subdirectories), this test is correct but the error message should clarify that subdirectories are not supported. If subdirectories should be supported, both the implementation and test need adjustment.
Consider clarifying the intended behavior in the JavaDoc for writeJsonToFile().
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in ac4dbfe. Updated JavaDoc for writeJsonToFile() to clarify that subdirectories are not supported and only flat file names are accepted. The error message now specifies "subdirectories not supported" for path separator rejections, making the intended behavior clear.
json-export-specs/README.md
Outdated
| - ✅ **IntelligenceExportService** - Service interface for JSON exports (`service.data.api`) | ||
| - ✅ **IntelligenceExportServiceImpl** - Jackson-based JSON serialization (`service.data.impl`) | ||
| - ✅ **Export DTOs** - Data transfer objects for risk assessments, coalition alignment, temporal trends | ||
| - ✅ **Unit Tests** - Comprehensive tests with Mockito (3/3 passing) |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The README states "Unit Tests - Comprehensive tests with Mockito (3/3 passing)" but the test file contains 6 test methods, not 3. This discrepancy should be corrected to accurately reflect the test coverage.
Update to: "Unit Tests - Comprehensive tests with Mockito (6/6 passing)"
| - ✅ **Unit Tests** - Comprehensive tests with Mockito (3/3 passing) | |
| - ✅ **Unit Tests** - Comprehensive tests with Mockito (6/6 passing) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in ac4dbfe. Corrected test count from "3/3 passing" to "6/6 passing" to accurately reflect the actual test coverage.
| } | ||
|
|
||
| public List<TrendDataPoint> getTrends() { | ||
| return trends; |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getTrends exposes the internal representation stored in field trends. The value may be modified after this call to getTrends.
| return trends; | |
| return java.util.Collections.unmodifiableList(trends); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in ac4dbfe. Refactored all export methods to build lists first, then set them on the DTOs. This allows the getters to return Collections.unmodifiableList() to protect internal representation. Applied to all three DTOs: RiskAssessmentExportDTO, CoalitionAlignmentExportDTO, and TemporalTrendsExportDTO.
|
@copilot apply changes based on the comments in this thread |
- Add ISO 8601 date format configuration to ObjectMapper (comment 2598690792) - Improve path traversal validation using Path.normalize() (comment 2598690817) - Clarify writeJsonToFile JavaDoc about subdirectory restrictions (comment 2598690831) - Fix test count in README from 3/3 to 6/6 (comment 2598690838) - Refactor export methods to build lists before setting them (comment 2598690852) - Return unmodifiable lists from DTO getters using Collections.unmodifiableList() - Add missing imports (ArrayList, Path, Collections) All 6 unit tests passing Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
All review comments addressed in commit ac4dbfe:
All 6 unit tests passing. Ready for re-review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated 1 comment.
| final Path filePath = tempDir.resolve(fileName); | ||
| assertTrue(Files.exists(filePath)); | ||
| final String content = Files.readString(filePath); | ||
| assertTrue(content.equals(jsonContent)); |
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use assertEquals(jsonContent, content) instead of assertTrue(content.equals(jsonContent)) for better error messages when assertions fail. assertEquals provides clearer feedback showing expected vs actual values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 82ed6cb. Replaced assertTrue(content.equals(jsonContent)) with assertEquals(jsonContent, content) for better error messages showing expected vs actual values when assertions fail.
|
@copilot apply changes based on the comments in this thread |
- Replace assertTrue(content.equals(jsonContent)) with assertEquals(jsonContent, content) - Provides clearer feedback showing expected vs actual values when assertions fail - Add assertEquals import Addresses comment 2599023915 Co-authored-by: pethers <1726836+pethers@users.noreply.github.com>
Comment addressed in commit 82ed6cb. Improved test assertion to use assertEquals for clearer error messages. All 6 unit tests passing. |
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.



Description
Implements service layer for JSON export of intelligence products: risk assessments (50 rules), coalition alignment matrix, and temporal trends. Enables €5.91M revenue across Risk Intelligence, Predictive Analytics, and Decision Intelligence product lines.
Service Interface (
IntelligenceExportService)exportRiskAssessments()- Serializes rule violations with severity/metadataexportCoalitionAlignment()- Exports party voting alignment matrixexportTemporalTrends()- Exports decision trends with 7/30/90-day moving averageswriteJsonToFile()- CDN-ready static file generation with enhanced path traversal protectionImplementation (
IntelligenceExportServiceImpl)RuleViolationDAO,ViewRiksdagenCoalitionAlignmentMatrixDAO,ViewDecisionTemporalTrendsDAORiskAssessmentExportDTO,CoalitionAlignmentExportDTO,TemporalTrendsExportDTOwith unmodifiable list returnsfinal classfollowing codebase conventionsExample Output
{ "metadata": { "version": "1.0.0", "generated": "2024-12-08T11:12:00Z", "schema": "intelligence-schema", "recordCount": 125 }, "violations": [{ "ruleName": "HIGH_ABSENCE_RATE", "severity": "MAJOR", "resourceType": "POLITICIAN", "ruleGroup": "Attendance" }] }Type of Change
Primary Changes
Political Analysis
Technical Changes
Impact Analysis
Political Analysis Impact
Technical Impact
Testing
Test Coverage: 6/6 passing
testExportRiskAssessments()- Mock violations, verify JSON structuretestExportCoalitionAlignment()- Mock alignment matrix, verify party datatestExportTemporalTrends()- Mock trends, verify moving averagestestWriteJsonToFile()- File creation and content writingtestWriteJsonToFileCreatesDirectory()- Directory creation behaviortestWriteJsonToFileRejectsPathTraversal()- Security validation for path traversal attacksTest Quality Improvements:
assertEquals()instead ofassertTrue()for better error messages showing expected vs actual valuesDocumentation
Documentation Updates:
Screenshots
N/A - Service layer only
Related Issues
Checklist
Additional Notes
Ready for Integration: Service layer awaits REST endpoint wiring and scheduled job configuration for daily exports.
Database Views: Leverages existing materialized views for performance:
view_rule_violation- 50 risk rules across politician/party/committee/ministryview_riksdagen_coalition_alignment_matrix- Party alignment rates from voting dataview_decision_temporal_trends- Daily aggregates with year-over-year comparisonsCode Quality Improvements (based on review feedback - 3 rounds):
final classwith package-private visibilitySecurity Considerations
CodeQL Analysis: 0 alerts, no vulnerabilities detected
Security Hardening:
mkdirs()return value and throws descriptive IOException on failureRelease Notes
New: JSON export service for intelligence products
Technical: Service layer (
IntelligenceExportService) with Jackson-based serialization including ISO 8601 date formatting, integrates existing DAO layer, comprehensive unit tests with Mockito (6 tests including security validation). Follows codebase conventions withfinal classand package-private visibility. DTOs return unmodifiable lists to protect internal representations. Test assertions improved using assertEquals for better error messages.Security: Enhanced path traversal protection using Path.normalize() validation, directory creation error handling, input validation for flat file structure, unmodifiable list returns from DTOs.
Original prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.