# Report Preview and Legacy API Removal Implementation Plan > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. **Goal:** Remove the unused public HTML preview API and deprecated generic report creation endpoint while preserving typed report creation, status query, PDF generation, and PDF download. **Architecture:** Treat this as an API contract cleanup: tests first lock the desired public contract, contracts/application/controller are then simplified to remove `previewHtmlUrl` and preview methods, and the PDF generation pipeline keeps using internal HTML renderers. The runtime controller should expose only typed creation, detail query, and PDF download endpoints. **Tech Stack:** Java 17, Spring Boot MVC, Maven reactor, JUnit 5, AssertJ, MockMvc, Jackson records/DTOs. --- ## Working Directory Run all commands from this worktree unless a step says otherwise: ```text /Users/exiao/Codes/dcjxb.microservice/.worktrees/report-api-cleanup ``` Baseline already verified before writing this plan: ```bash mvn -pl ability-center-runtime -am -Dtest=ExamSprintReportControllerWebMvcTest,ExamSprintReportControllerTest test mvn -pl abilities/exam-sprint/application -am -Dtest=ExamSprintReportApplicationServiceTest test ``` Both commands passed on `2026-04-27`. Do not create a git commit unless the user explicitly asks for one. --- ### Task 1: Update Runtime Controller Tests for Removed Public Contract **Files:** - Modify: `ability-center-runtime/src/test/java/cn/yunzhixue/ability/center/examsprint/adapter/http/ExamSprintReportControllerWebMvcTest.java` - Modify: `ability-center-runtime/src/test/java/cn/yunzhixue/ability/center/examsprint/adapter/http/ExamSprintReportControllerTest.java` **Step 1: Write the failing controller-level tests** In `ExamSprintReportControllerWebMvcTest.java`: 1. Remove the import of `ExamSprintReportApplicationService.ReportHtmlPreviewContent`. 2. Update `new CreateExamSprintReportWithUrlResponse(...)` calls so they pass only these fields: ```java new CreateExamSprintReportWithUrlResponse( "report-sync-001", ExamSprintReportType.OUTLOOK, ExamSprintReportGenerationStatus.SUCCESS, Instant.parse("2026-01-01T00:00:00Z"), Instant.parse("2026-01-01T00:01:00Z"), Instant.parse("2026-01-02T00:00:00Z"), "https://dcjxb-cdntest.yunzhixue.cn/exam-assault-report/exam-sprint-outlook-report-report-sync-001.pdf") ``` 3. Update the achievement sync fixture the same way, keeping only the `downloadUrl` as the final argument. 4. Update `new ExamSprintReportDetailResponse(...)` calls so they pass only these fields: ```java new ExamSprintReportDetailResponse( "report-001", ExamSprintReportType.OUTLOOK, ExamSprintReportGenerationStatus.SUCCESS, Instant.parse("2026-01-01T00:00:00Z"), Instant.parse("2026-01-01T00:05:00Z"), Instant.parse("2026-01-02T00:00:00Z"), "https://dcjxb-cdntest.yunzhixue.cn/exam-assault-report/exam-sprint-outlook-report-report-001.pdf", null) ``` 5. Remove assertions that check `$.data.previewHtmlUrl`. 6. Replace the old `oldGenericCreateReportEndpointIsRemoved` test with a test that proves removed endpoints are no longer exposed: ```java @Test void removedReportEndpointsAreNotExposed() throws Exception { mockMvc.perform(post("/api/exam-sprint/reports") .contentType(MediaType.APPLICATION_JSON) .content("{\"reportType\":\"OUTLOOK\",\"payload\":{}}")) .andExpect(status().isNotFound()); mockMvc.perform(get("/api/exam-sprint/reports/{reportId}/preview/html", "report-001")) .andExpect(status().isNotFound()); verifyNoInteractions(applicationService); } ``` 7. Delete the `previewHtmlReturnsTextHtmlForSucceededReport` test. 8. Remove any stubbing of `applicationService.previewReportHtml(...)`. In `ExamSprintReportControllerTest.java`: 1. Remove `jsonPath("$.data.previewHtmlUrl").isNotEmpty()` assertions. 2. Remove extraction of `previewHtmlUri`. 3. Remove `mockMvc.perform(get(previewHtmlUri))` calls and HTML-content assertions. 4. Keep the PDF download assertions for both report types. **Step 2: Run controller tests to verify they fail before implementation** Run: ```bash mvn -pl ability-center-runtime -am -Dtest=ExamSprintReportControllerWebMvcTest,ExamSprintReportControllerTest test ``` Expected: FAIL. Accept either compile failures from the still-old DTO constructor shapes, or test failures because the preview endpoint still exists / `previewHtmlUrl` still appears. **Step 3: Checkpoint status** Run: ```bash git status --short ``` Expected: only the two runtime test files and this plan file should be modified so far. Do not commit. --- ### Task 2: Update Application Service Tests for Removed `previewHtmlUrl` and Preview Service Method **Files:** - Modify: `abilities/exam-sprint/application/src/test/java/cn/yunzhixue/ability/center/examsprint/application/report/ExamSprintReportApplicationServiceTest.java` **Step 1: Write failing application-contract tests** Add imports near the other `java.*` imports: ```java import cn.yunzhixue.ability.center.examsprint.contracts.report.CreateExamSprintReportWithUrlResponse; import cn.yunzhixue.ability.center.examsprint.contracts.report.ExamSprintReportDetailResponse; import java.lang.reflect.Method; import java.lang.reflect.RecordComponent; import java.util.Arrays; ``` Add this test near the top of `ExamSprintReportApplicationServiceTest`: ```java @Test void publicReportContractsDoNotExposeHtmlPreview() { assertThat(recordComponentNames(CreateExamSprintReportWithUrlResponse.class)) .contains("downloadUrl") .doesNotContain("previewHtmlUrl"); assertThat(recordComponentNames(ExamSprintReportDetailResponse.class)) .contains("downloadUrl") .doesNotContain("previewHtmlUrl"); assertThat(Arrays.stream(ExamSprintReportApplicationService.class.getDeclaredMethods()) .map(Method::getName)) .doesNotContain("previewReportHtml"); } ``` Add this helper near the other private helpers: ```java private List recordComponentNames(Class recordType) { return Arrays.stream(recordType.getRecordComponents()) .map(RecordComponent::getName) .toList(); } ``` Update existing application service tests: 1. In `createOutlookReportSyncGeneratesUploadAndReturnsDownloadUrl`, delete the `response.previewHtmlUrl()` assertion. 2. In `createAchievementReportSyncGeneratesUploadAndReturnsDownloadUrl`, delete the `response.previewHtmlUrl()` assertion. 3. Rename `getReportReturnsDownloadAndPreviewUrlsForSuccessfulReport` to `getReportReturnsDownloadUrlForSuccessfulReport`. 4. In that renamed test, delete the `response.previewHtmlUrl()` assertion. 5. Delete `previewReportHtmlRendersSavedPayloadForSuccessfulReport`. 6. Delete `previewReportHtmlRejectsPendingReport`. **Step 2: Run application tests to verify they fail before implementation** Run: ```bash mvn -pl abilities/exam-sprint/application -am -Dtest=ExamSprintReportApplicationServiceTest test ``` Expected: FAIL because `previewHtmlUrl` is still a record component and `previewReportHtml` is still on the application service interface. **Step 3: Checkpoint status** Run: ```bash git status --short ``` Expected: runtime tests, application test, and this plan file are modified. Do not commit. --- ### Task 3: Remove Preview Fields from Contract Records **Files:** - Modify: `abilities/exam-sprint/contracts/src/main/java/cn/yunzhixue/ability/center/examsprint/contracts/report/CreateExamSprintReportWithUrlResponse.java` - Modify: `abilities/exam-sprint/contracts/src/main/java/cn/yunzhixue/ability/center/examsprint/contracts/report/ExamSprintReportDetailResponse.java` **Step 1: Implement the contract change** Change `CreateExamSprintReportWithUrlResponse` to: ```java public record CreateExamSprintReportWithUrlResponse( String reportId, ExamSprintReportType reportType, ExamSprintReportGenerationStatus generationStatus, Instant createdAt, Instant updatedAt, Instant expiresAt, String downloadUrl) { } ``` Change `ExamSprintReportDetailResponse` to: ```java public record ExamSprintReportDetailResponse( String reportId, ExamSprintReportType reportType, ExamSprintReportGenerationStatus generationStatus, Instant createdAt, Instant updatedAt, Instant expiresAt, String downloadUrl, String failureReason) { } ``` **Step 2: Run targeted compile/tests to expose remaining call sites** Run: ```bash mvn -pl abilities/exam-sprint/application,ability-center-runtime -am -DskipTests compile test-compile ``` Expected: FAIL with constructor or method references that still include `previewHtmlUrl` or preview service methods. **Step 3: Checkpoint status** Run: ```bash git status --short ``` Do not commit. --- ### Task 4: Remove Preview Method from Application Service and Implementation **Files:** - Modify: `abilities/exam-sprint/application/src/main/java/cn/yunzhixue/ability/center/examsprint/application/report/ExamSprintReportApplicationService.java` - Modify: `abilities/exam-sprint/application/src/main/java/cn/yunzhixue/ability/center/examsprint/application/report/DefaultExamSprintReportApplicationService.java` - Modify as needed: `abilities/exam-sprint/application/src/test/java/cn/yunzhixue/ability/center/examsprint/application/report/ExamSprintReportApplicationServiceTest.java` **Step 1: Remove preview from the service interface** In `ExamSprintReportApplicationService.java`: 1. Delete `ReportHtmlPreviewContent previewReportHtml(String reportId);`. 2. Delete the nested `ReportHtmlPreviewContent` record. 3. Keep `ReportDownloadContent`. Final shape should be: ```java public interface ExamSprintReportApplicationService { CreateExamSprintReportResponse createOutlookReport(JsonNode payload); CreateExamSprintReportResponse createAchievementReport(JsonNode payload); CreateExamSprintReportWithUrlResponse createOutlookReportSync(JsonNode payload); CreateExamSprintReportWithUrlResponse createAchievementReportSync(JsonNode payload); ExamSprintReportDetailResponse getReport(String reportId); ReportDownloadContent downloadReport(String reportId); record ReportDownloadContent(String fileName, byte[] bytes, String contentType) { } } ``` **Step 2: Remove preview implementation** In `DefaultExamSprintReportApplicationService.java`: 1. Remove the import of `ExamSprintReportRenderer` if it is no longer needed. 2. Remove the `private final List renderers;` field. 3. Remove the `List renderers` constructor parameter. 4. Remove `this.renderers = List.copyOf(renderers);`. 5. In `submitReportGenerationSync`, remove `previewHtmlUrl` construction and return `CreateExamSprintReportWithUrlResponse` with `downloadUrl` as the final argument. 6. In `getReport`, remove the `previewHtmlUrl` local variable, remove its assignment, and return `ExamSprintReportDetailResponse` with `failureReason` immediately after `downloadUrl`. 7. Delete the entire `previewReportHtml(String reportId)` method. 8. Keep `List` import if still used for another type; otherwise remove it. **Step 3: Update test service factory constructor call** In `ExamSprintReportApplicationServiceTest.java`, update `new DefaultExamSprintReportApplicationService(...)` to remove the final `List.of(new PreviewTestRenderer())` argument. Keep `PreviewTestRenderer` if it is still used by `ExamSprintReportGenerationPipeline` in the test helper. Expected constructor call shape: ```java return new DefaultExamSprintReportApplicationService( repository, dispatcher, new ExamSprintReportGenerationPipeline( repository, renderers, pdfGenerator, storage, FIXED_CLOCK), storage, properties(), FIXED_CLOCK, OBJECT_MAPPER, VALIDATOR); ``` **Step 4: Run application tests** Run: ```bash mvn -pl abilities/exam-sprint/application -am -Dtest=ExamSprintReportApplicationServiceTest test ``` Expected: PASS. **Step 5: Checkpoint status** Run: ```bash git status --short ``` Do not commit. --- ### Task 5: Remove Public Controller Endpoints and Update Runtime Tests **Files:** - Modify: `ability-center-runtime/src/main/java/cn/yunzhixue/ability/center/examsprint/adapter/http/ExamSprintReportController.java` - Modify if needed: `ability-center-runtime/src/test/java/cn/yunzhixue/ability/center/examsprint/adapter/http/ExamSprintReportControllerWebMvcTest.java` - Modify if needed: `ability-center-runtime/src/test/java/cn/yunzhixue/ability/center/examsprint/adapter/http/ExamSprintReportControllerTest.java` **Step 1: Remove controller endpoint methods** In `ExamSprintReportController.java`: 1. Remove imports: ```java import cn.yunzhixue.ability.center.examsprint.application.report.ExamSprintReportApplicationService.ReportHtmlPreviewContent; import org.springframework.http.HttpStatus; ``` 2. Delete `createReportDeprecated()`. 3. Delete `previewReportHtml(String reportId)`. 4. Keep `downloadReport(String reportId)` unchanged. **Step 2: Fix runtime test compile errors** If compile errors remain in runtime tests: 1. Remove imports that only supported deleted preview tests. 2. Ensure `CreateExamSprintReportWithUrlResponse` and `ExamSprintReportDetailResponse` constructor calls use the new DTO shapes. 3. Ensure no test references `previewHtmlUrl`. 4. Keep the `removedReportEndpointsAreNotExposed` test from Task 1. **Step 3: Run runtime tests** Run: ```bash mvn -pl ability-center-runtime -am -Dtest=ExamSprintReportControllerWebMvcTest,ExamSprintReportControllerTest test ``` Expected: PASS. **Step 4: Checkpoint status** Run: ```bash git status --short ``` Do not commit. --- ### Task 6: Search for Remaining Preview API References **Files:** - Inspect only unless references require cleanup. **Step 1: Search source and test code for removed public contract names** Run: ```bash rg "previewHtmlUrl|previewReportHtml|/preview/html|createReportDeprecated" ability-center-runtime abilities/exam-sprint ``` Expected: no matches in `src/main/java` or active tests. It is acceptable for this implementation plan or historical docs to mention the removed names. **Step 2: If matches remain in production or active test code, remove them** Rules: - Remove public URL construction for `/preview/html`. - Remove preview endpoint stubs/assertions. - Do not remove HTML templates, renderer implementations, or PDF pipeline renderer usage. **Step 3: Run compile for affected modules** Run: ```bash mvn -pl abilities/exam-sprint/application,ability-center-runtime -am -DskipTests compile test-compile ``` Expected: PASS. Do not commit. --- ### Task 7: Final Verification **Files:** - No code edits expected. **Step 1: Run targeted application tests** Run: ```bash mvn -pl abilities/exam-sprint/application -am -Dtest=ExamSprintReportApplicationServiceTest test ``` Expected: PASS. **Step 2: Run targeted runtime tests** Run: ```bash mvn -pl ability-center-runtime -am -Dtest=ExamSprintReportControllerWebMvcTest,ExamSprintReportControllerTest test ``` Expected: PASS. **Step 3: Run broader affected-module verification** Run: ```bash mvn -pl abilities/exam-sprint/application,ability-center-runtime -am test ``` Expected: PASS. **Step 4: Inspect final diff** Run: ```bash git status --short git diff -- ability-center-runtime abilities/exam-sprint docs/plans/2026-04-27-report-preview-and-legacy-api-removal.md ``` Expected: - Removed preview endpoint and old generic endpoint from the controller. - Removed `previewHtmlUrl` from response records. - Removed preview service method and content record. - Runtime/application tests updated to assert the new contract. - Internal HTML renderers/templates and PDF generation pipeline remain intact. Do not commit unless the user explicitly asks.