Files
clean-architecture-backend-…/docs/superpowers/plans/2026-08-02-client-safe-error-boundary.md
T
DongHyeonkaandClaude Opus 5 5f10b791d3 chore: record pre-existing uncommitted repository state
Snapshot of the in-flight state that already existed, identically, in both
this worktree and the main checkout before this session began: the initial
HTTP Client platform implementation (previously untracked), the redis-lab
removal, and the JPA / object-storage / notification integration work.

Kept separate from this session's HTTP Client review response, which lands
in the following commit, so the two bodies of work stay reviewable apart.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-11 16:48:43 +09:00

74 lines
4.3 KiB
Markdown

# Client-Safe Error Boundary Implementation Plan
> **Execution:** Follow `superpowers:test-driven-development`; request an independent code review
> before advancing to the next P1 batch.
**Goal:** Ensure public HTTP error envelopes contain only allowlisted messages and bounded safe
metadata, never raw exceptions or request values.
**Architecture:** The inbound web adapter maps operational codes to fixed public messages. The
sample consumer owns a parallel domain-code mapping. Exception diagnostics stay behind the
transport boundary.
**Tech Stack:** Java 21, Spring Boot 4.0.0, JUnit 6/JUnit Jupiter, AssertJ, MockMvc.
## Constraints
- Preserve all completed P0 and verification-purity changes in the dirty worktree.
- Preserve every error code/status/category/retryable value.
- Preserve safe protocol details and required headers.
- Do not leak request DTOs or transport types into application/domain.
- Do not stage, commit, amend, or push.
### Task 1: Operational Handler RED Contracts
**Files:**
- Modify: `src/adapter/inbound/web/src/test/java/dev/caskeleton/adapter/inbound/web/error/GlobalExceptionHandlerTest.java`
- Modify: `src/adapter/inbound/web/src/test/java/dev/caskeleton/adapter/inbound/web/error/TransportErrorHandlingTest.java`
- Create: `src/adapter/inbound/web/src/test/java/dev/caskeleton/adapter/inbound/web/error/NoResourceFoundErrorHandlingTest.java`
- [x] Add secret-sentinel tests for mapping, illegal argument, adapter disabled, authentication,
authorization, precondition, pagination, and cursor exceptions.
- [x] Add validation tests proving rejected values, interpolated/default messages, and iterable
keys/indices are absent while normalized fields plus allowlisted reason codes/fixed messages remain.
- [x] Add transport tests proving raw request URLs and content-type values are not echoed.
- [x] Add a real MVC resource-resolver test for a sentinel-bearing static-resource 404.
- [x] Run the focused tests and record RED against the current raw-message implementation (30 tests, 9 expected failures).
### Task 2: Operational Allowlist Implementation
**Files:**
- Modify: `src/adapter/inbound/web/src/main/java/dev/caskeleton/adapter/inbound/web/error/ClientSafeErrorMessages.java`
- Create: `src/adapter/inbound/web/src/main/java/dev/caskeleton/adapter/inbound/web/error/ClientSafeValidationDetails.java`
- Modify: `src/adapter/inbound/web/src/main/java/dev/caskeleton/adapter/inbound/web/error/GlobalExceptionHandler.java`
- Modify: `src/adapter/inbound/web/README.md`
- [x] Add code-specific fixed operational messages with a safe category fallback.
- [x] Replace every public `ex.getMessage()`/rejected-value/raw-URL path.
- [x] Discard validation message/value data, normalize field paths, strip iterable keys/indices, and
emit only allowlisted reason codes with fixed messages.
- [x] Route both `NoHandlerFoundException` and `NoResourceFoundException` through the same safe 404 envelope.
- [x] Retain safe field/reason/expected-type/supported-method/media-type details and `Allow`.
- [x] Run the operational/transport tests and confirm GREEN.
### Task 3: Sample Domain RED and Implementation
**Files:**
- Create: `src/sample-portfolio/src/main/java/dev/caskeleton/sample/portfolio/adapter/inbound/web/error/PortfolioClientSafeErrorMessages.java`
- Modify: `src/sample-portfolio/src/main/java/dev/caskeleton/sample/portfolio/adapter/inbound/web/error/DomainExceptionHandler.java`
- Modify: `src/sample-portfolio/src/test/java/dev/caskeleton/sample/portfolio/adapter/inbound/web/error/DomainExceptionHandlerTest.java`
- [x] Add ID/title/reason sentinel tests and confirm RED (4 expected failures).
- [x] Map every `PortfolioErrorCode` to fixed public text and use it from the advice.
- [x] Confirm code/status/category remain unchanged and sentinels are absent.
### Task 4: Focused and Architecture Verification
- [x] Run `./gradlew :adapter:inbound:web:test --console=plain`.
- [x] Run `./gradlew :sample-portfolio:test --console=plain`.
- [x] Run focused Spotless/Checkstyle/SpotBugs tasks for both modules.
- [x] Run `./gradlew verifyCleanArchitectureDependencies --console=plain`.
- [x] Run `git diff --check` and request an independent read-only review.
- [x] Apply the independent review findings and receive a no-Critical/no-Important code re-review;
align this design/plan with the final validation and resource-404 contract.