Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ jobs:
- run: npm test || true
- run: npm run build

# Java 8 / Maven - Report Service (LEGACY)
# Java 17 / Maven - Report Service
report-service:
needs: detect-changes
if: needs.detect-changes.outputs.report-service == 'true'
Expand All @@ -329,10 +329,9 @@ jobs:
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '8'
- run: mvn compile -B -q
- run: mvn test -B
- run: mvn package -DskipTests -B -q
java-version: '17'
cache: maven
- run: mvn -B verify

# Java 11 / Maven - Legacy Portal. Uses the checked-in wrapper rather than the
# runner's mvn: the portal builds on Spring Boot 2.x and pins its own Maven.
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/docker-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ jobs:
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '8'
java-version: '17'
cache: maven
- run: mvn test -B

legacy-portal-tests:
Expand Down
2 changes: 1 addition & 1 deletion .trivyignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# OtterWorks Trivy Ignore List
# These CVEs are acknowledged and tracked for remediation in future upgrade cycles.
# report-service is excluded via skip-dirs (intentional legacy Java 8 service for upgrade exercise).
# report-service is excluded via skip-dirs; the exclusion predates its Java 17 / Spring Boot 3.2 upgrade.

# --- etl/airflow: requires Airflow 2.9+ upgrade (major version) ---
CVE-2024-39877
Expand Down
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,8 @@ make down
| Analytics Service | Scala 3.4 | Akka HTTP | 8088 | Usage analytics, data aggregation |
| Admin Service | Ruby 3.3 | Rails 7.1 | 8089 | Admin dashboard backend |
| Audit Service | C# 12 | ASP.NET 8 | 8090 | Immutable audit trail, compliance |
| Report Service *(legacy)* | Java 8 | Spring Boot 2.5 | 8091 | PDF/CSV/Excel report generation (tech-debt: upgrade target Java 17+, Spring Boot 3.2+) |
| Report Service | Java 17 | Spring Boot 3.2 | 8091 | PDF/CSV/Excel report generation |

> **Note:** The Report Service intentionally uses outdated dependencies (Java 8, Spring Boot 2.5, JUnit 4, javax.\*) and is a candidate for a framework-upgrade exercise. See `services/report-service/pom.xml` for details.

## Frontend Applications

Expand Down Expand Up @@ -170,7 +169,7 @@ otterworks/
│ ├── analytics-service/ # Scala / Akka HTTP
│ ├── admin-service/ # Ruby / Rails
│ ├── audit-service/ # C# / ASP.NET
│ └── report-service/ # Java 8 / Spring Boot 2.5 (legacy)
│ └── report-service/ # Java 17 / Spring Boot 3.2
├── frontend/ # Web app (React/Next.js) + Admin dashboard (Angular)
├── infrastructure/
│ ├── terraform/ # App-specific AWS resources (S3, RDS, DynamoDB, etc.)
Expand Down
4 changes: 2 additions & 2 deletions docs/CI_STRATEGY.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Uses `dorny/paths-filter` for **change detection** — only services with modifi
| analytics-service | Scala/Java 17 (sbt) | `sbt compile`, `sbt test` | Passing |
| admin-service | Ruby 3.3 (Rails) | `db:schema:load`, `rspec` (with Postgres service container) | **Fixed** (was failing due to missing `table_name`) |
| audit-service | C# / .NET 8 | `dotnet restore`, `dotnet build`, `dotnet test` | Passing |
| report-service | Java 8 (Maven) — **LEGACY** | `mvn compile`, `mvn test`, `mvn package` | Passing |
| report-service | Java 17 (Maven) | `mvn verify` | Passing |
| web-app | Node.js 20 (Next.js) | `npm ci`, `npm run lint`, `npm test`, `npm run build` | Passing |
| admin-dashboard | Node.js 20 (Angular) | `npm ci`, `npm run lint \|\| true`, `npm test \|\| true`, `npm run build` | Passing |
| infrastructure | Terraform 1.7 | `terraform fmt -check`, `terraform init`, `terraform validate` | Passing |
Expand Down Expand Up @@ -56,7 +56,7 @@ After PR #31 (this PR):
### Immediate (No Changes Required)
1. **Change detection is working well** — Only affected services are built on PRs, keeping CI fast (~2-5 min per service vs 30+ min for full monorepo build).
2. **Security scanning is comprehensive** — Trivy + Gitleaks + Semgrep covers dependencies, secrets, and static analysis.
3. **Legacy service isolation** — Report service (Java 8) is correctly skipped by Trivy since it's intentionally outdated for upgrade exercises.
3. **Legacy service isolation** — Report service is still skipped by Trivy; the scan exclusion predates its Java 17 / Spring Boot 3.2 upgrade and can be revisited.

### Short-Term Improvements
1. **Add `concurrency` groups** to cancel stale CI runs when new commits are pushed:
Expand Down
4 changes: 2 additions & 2 deletions docs/SDLC-COVERAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ documented in `README.md` (branch from `main`, open PR, CI must pass).
`dorny/paths-filter` that fans out to **one job per service/language**, each running the idiomatic
toolchain:
- Go `go vet` + `go test -race` + build (`api-gateway`)
- Java 17 `gradle check` (`auth-service`, `notification-service`), Java 8 `mvn` (`report-service`, legacy)
- Java 17 `gradle check` (`auth-service`, `notification-service`), Java 17 `mvn` (`report-service`)
- Rust `cargo fmt/clippy/test/build` (`file-service`)
- Python `ruff` + `pytest --cov` (`document-service`, `search-service`)
- Node `npm ci/lint/test/build` (`collab-service`, `web-app`)
Expand Down Expand Up @@ -350,7 +350,7 @@ shared-services EKS + Airflow/Spark; actual is standalone `platform/terraform` +
| **CVE remediation / closed-loop security** | §7 | Trivy/Semgrep/SonarCloud + event-driven Devin auto-fix with escalation is a complete, differentiated loop |
| **Cloud-native IaC provisioning** | §4, §3 | Real two-layer Terraform + EKS + IRSA; live apply, including finding & fixing a managed-policy bug |
| **Observability / incident-response with Devin** | §8–§11 | admin-service incident→Devin auto-investigation is a unique narrative (needs runtime wired) |
| **Legacy modernization** | §13, §2 (report-service Java 8) | Cron ETL and the intentionally-legacy `report-service` are ready-made "before" states |
| **Legacy modernization** | §13, §2 (report-service) | Cron ETL is a ready-made "before" state; `report-service` has since been migrated to Java 17 / Spring Boot 3.2 |
| **Analytics lakehouse re-architecture** | §13 | Durable PostgreSQL analytics store is the "before" for an S3 + Apache Iceberg (Glue/Athena) migration, with old-vs-new reconciliation as continuous validation |

## Top gaps to fix before OtterWorks is a clean all-around reference
Expand Down
2 changes: 1 addition & 1 deletion infrastructure/helm/report-service/Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
apiVersion: v2
name: report-service
description: OtterWorks Report Service - Legacy Java 8/Spring Boot 2.5 report generation
description: OtterWorks Report Service - Java 17/Spring Boot 3.2 report generation
type: application
version: 0.1.0
appVersion: "0.1.0"
9 changes: 5 additions & 4 deletions security/deps/expected/report-service.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
"advisory": "CVE-2022-42889",
"artifact": "org.apache.commons:commons-text",
"cases_sha256": "ea3ac7b9e1fc1dc7049222d7b4157e34b435927389036138b00feaabb28f225c",
"recorded_at": "2026-08-17T22:51:46.629685+00:00",
"reason": "baseline: commons-text 1.9 behavior before CVE-2022-42889 remediation",
"recorded_at": "2026-09-01T00:21:00.792251+00:00",
"reason": "report-service now builds on JDK 17 (Spring Boot 3.2): Nashorn is gone, so the script lookup no longer evaluates",
"cases": [
{
"id": "banner-title",
Expand Down Expand Up @@ -49,8 +49,9 @@
},
{
"id": "attack-script-lookup",
"outcome": "ok",
"value": "7"
"outcome": "error",
"error_type": "java.lang.IllegalArgumentException",
"error_message": "Error in script engine [javascript] evaluating script [3+4]."
},
{
"id": "attack-dns-lookup",
Expand Down
12 changes: 6 additions & 6 deletions security/deps/modules.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,16 @@
# dependency tree, and the report names it. A module whose candidates all fail is
# reported unmeasured. `test` is the arguments appended to the resolved tool.
modules:
# Both Maven modules pin JDK 11: their recorded transcripts include the
# ${script:javascript:...} lookup, which only resolves while the JVM still ships
# Nashorn (JDK <= 14). Measured on a newer JDK the script case would report a
# behavior change that never happened, so an absent JDK 11 must read as unmeasured.
# report-service builds on JDK 17 (Spring Boot 3.2), whose JVM no longer ships
# Nashorn: its ${script:javascript:...} case cannot evaluate on any JDK the module
# compiles on, which is why that case's baseline records the IllegalArgumentException
# the script engine lookup now raises instead of an evaluated value.
- id: report-service
path: services/report-service
build: maven
java_home:
- $JAVA_HOME_11_X64
- /usr/lib/jvm/java-11-openjdk-amd64
- $JAVA_HOME_17_X64
- /usr/lib/jvm/java-17-openjdk-amd64
# No wrapper in this module; the `mvn` on PATH is what ci.yml uses for it too.
test: -B test
cases: cases/report-service.json
Expand Down
7 changes: 2 additions & 5 deletions services/report-service/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
# LEGACY: Uses JDK 8 (target: JDK 17+ or 21+)
# Maven build instead of Gradle (matches legacy Java enterprise pattern)
FROM maven:3.8.7-eclipse-temurin-8 AS builder
FROM maven:3.9-eclipse-temurin-17 AS builder

WORKDIR /app
COPY pom.xml .
Expand All @@ -10,8 +8,7 @@ RUN mvn dependency:go-offline -B
COPY src/ src/
RUN mvn package -DskipTests -B

# LEGACY: JRE 8 runtime (target: eclipse-temurin:17-jre or 21-jre)
FROM eclipse-temurin:8-jre
FROM eclipse-temurin:17-jre

RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*

Expand Down
6 changes: 5 additions & 1 deletion services/report-service/UPGRADE_GUIDE.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
# Report Service Dependency Upgrade Guide

This document describes 11 upgrade axes for migrating the report-service from its
current legacy stack to a modern, supported baseline. Each axis lists the exact
legacy stack to a modern, supported baseline. Each axis lists the exact
files, imports, and annotations that change, together with a verification step.

**Status:** axes 1-5 and 11 (Java 17, Spring Boot 3.2, `jakarta.*`, JUnit 5,
springdoc-openapi, Mockito 5) are done. Axes 6-10 (iText, Commons IO, Guava,
Apache POI) remain open; Commons Lang 3 (axis 7) is in place via the Boot BOM.

---

## Overview
Expand Down
89 changes: 26 additions & 63 deletions services/report-service/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<!-- LEGACY: Spring Boot 2.5.14 — last 2.5.x release. Upgrade target: 3.2+ -->
<!-- Pinned via 2.5.15 patch release pending security review; see internal ticket OW-4471 -->
<version>2.5.15</version>
<version>3.2.12</version>
<relativePath/>
</parent>

Expand All @@ -18,28 +16,18 @@
<version>0.1.0</version>
<packaging>jar</packaging>
<name>OtterWorks Report Service</name>
<description>Legacy report generation service — PDF, CSV, Excel exports from analytics and audit data</description>
<description>Report generation service — PDF, CSV, Excel exports from analytics and audit data</description>

<properties>
<!-- LEGACY: Java 8 source/target. Upgrade target: Java 17+ -->
<java.version>1.8</java.version>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<java.version>17</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

<!-- LEGACY: SpringFox 3.0 (dead project). Upgrade target: springdoc-openapi 2.x -->
<springfox.version>3.0.0</springfox.version>
<!-- LEGACY: Apache POI 4.1.2 (2020). Upgrade target: 5.2+ -->
<springdoc.version>2.5.0</springdoc.version>
<poi.version>4.1.2</poi.version>
<!-- LEGACY: iText 5.5.13.3 (AGPL, pre-license-change). Upgrade target: OpenPDF or iText 7+ -->
<itext.version>5.5.13.3</itext.version>
<!-- LEGACY: Commons Lang 2.6 (EOL). Upgrade target: commons-lang3 -->
<commons-lang.version>2.6</commons-lang.version>
<!-- LEGACY: Commons IO 2.6 (2018). Upgrade target: 2.15+ -->
<commons-io.version>2.6</commons-io.version>
<!-- LEGACY: Guava 28.0 (2019, many CVEs). Upgrade target: 33+ -->
<guava.version>28.0-jre</guava.version>
<!-- Commons Text 1.9 — report banner/footer interpolation -->
<!-- Commons Text — report banner/footer interpolation -->
<commons-text.version>1.9</commons-text.version>
</properties>

Expand All @@ -66,12 +54,10 @@
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

<!-- LEGACY: javax.servlet — removed in Jakarta EE 9+. Upgrade: jakarta.servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
<scope>test</scope>
</dependency>

<!-- Database -->
Expand All @@ -80,15 +66,12 @@
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>

<!-- LEGACY: SpringFox Swagger 2 (dead project, last release 2020) -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>${springfox.version}</version>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
</dependency>

<!-- LEGACY: Apache POI 4.x for Excel generation -->
<!-- Apache POI for Excel generation -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
Expand All @@ -99,19 +82,22 @@
<artifactId>poi-ooxml</artifactId>
<version>${poi.version}</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>${springdoc.version}</version>
</dependency>

<!-- LEGACY: iText 5 for PDF generation (AGPL license concerns) -->
<!-- iText 5 for PDF generation -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>${itext.version}</version>
</dependency>

<!-- LEGACY: Commons Lang 2 (EOL since 2012) -->
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>${commons-lang.version}</version>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>

<!-- Commons Text — report banner and footer interpolation -->
Expand All @@ -121,59 +107,40 @@
<version>${commons-text.version}</version>
</dependency>

<!-- LEGACY: Commons IO 2.6 (outdated) -->

<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons-io.version}</version>
</dependency>

<!-- LEGACY: Guava 28 (2019, multiple CVEs including DoS) -->

<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>

<!-- LEGACY: RestTemplate HTTP client (deprecated in favor of WebClient) -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
</dependency>

<!-- Observability (also legacy versions) -->
<!-- Observability -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>

<!-- LEGACY: OpenCSV 4.6 (2018). Upgrade target: 5.9+ -->

<dependency>
<groupId>com.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>4.6</version>
</dependency>

<!-- Testing -->
<!-- LEGACY: JUnit 4 (not JUnit 5/Jupiter). Upgrade target: junit-jupiter -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
Comment thread
devin-ai-integration[bot] marked this conversation as resolved.
<scope>test</scope>
<!-- Exclude JUnit 5 to force JUnit 4 usage -->
<exclusions>
<exclusion>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
Expand All @@ -183,7 +150,6 @@
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.12.4</version>
<scope>test</scope>
</dependency>
</dependencies>
Expand All @@ -198,16 +164,13 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<release>${java.version}</release>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
</plugin>
Comment on lines 171 to 174

@devin-ai-integration devin-ai-integration Bot Sep 1, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Info: Converted tests still execute

Surefire selects JUnit Platform and runs all seven classes. The suite completes 50 tests, with only the opt-in transcript test skipped.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

</plugins>
</build>
Expand Down
Loading
Loading