From ac874e49e608b35429f82aa098574b52a68f2069 Mon Sep 17 00:00:00 2001 From: DongHyeonka Date: Fri, 14 Aug 2026 17:39:39 +0900 Subject: [PATCH] fix(notification): close the two pre-existing gates that broke `check` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `./gradlew check` failed on main before this change. Both failures came from the notification platform and neither was reachable from the graphql merge. - `application-core:checkstyleMain` — ProviderSubmissionResult switches over AttemptConfirmation and covers all three constants, so the switch is exhaustive, but checkstyle's MissingSwitchDefault does not model exhaustive arrow switches. Add the repository's existing idiom (`default -> throw new IllegalStateException`), the same shape SwitchNotificationWriterOwnershipCommand and DefaultCleanupService already use. The branch stays unreachable; it exists to satisfy the linter and to fail loudly if the enum ever grows a constant. - `adapter:inbound:web:spotbugsMain` — SPRING_CSRF_PROTECTION_DISABLED x2 on CallbackMvcSecurityConfiguration. Provider callbacks are inbound webhooks: an external provider POSTs to /internal/notification/callbacks/**, so it can never carry a CSRF token, and the chain is SESSION-STATELESS with no ambient cookie auth for CSRF to protect. Authenticity comes from the provider signature the callback package verifies (failure -> CallbackValidationException -> 400), not from permitAll(). Register it in the spotbugs exclude filter scoped to that exact class, matching the existing narrow-exception style; every other CSRF disable stays reportable. Verified on the merged tree by replaying the CI jobs locally: - quality-gates: `check verifyPublicPathSnapshot verifyDependencyLocks --warning-mode=fail --no-daemon` -> BUILD SUCCESSFUL (13m47s) - sample-off, redis-sdk, jpa-candidate-evidence, gate-matrix-lint, conditionalTransportQualification (graphql 8 / grpc 15 / websocket 5 / composition 1, zero skips) - notification-platform architecture gate (CleanArchitectureTest + NotificationArchitectureTest) - runtime: `:app-bootstrap:bootRun` against the compose-local database started and served GET /api/healthcheck 200; actuator/health and /api/worklogs answered 401, so the authentication boundary is live. Co-Authored-By: Claude Opus 5 (1M context) --- .../platform/provider/ProviderSubmissionResult.java | 1 + src/config/spotbugs/exclude.xml | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/src/application-core/src/main/java/dev/caskeleton/application/notification/platform/provider/ProviderSubmissionResult.java b/src/application-core/src/main/java/dev/caskeleton/application/notification/platform/provider/ProviderSubmissionResult.java index f39dea88..c175b998 100644 --- a/src/application-core/src/main/java/dev/caskeleton/application/notification/platform/provider/ProviderSubmissionResult.java +++ b/src/application-core/src/main/java/dev/caskeleton/application/notification/platform/provider/ProviderSubmissionResult.java @@ -69,6 +69,7 @@ public record ProviderSubmissionResult( "an ambiguous attempt may not claim provider acceptance"); } } + default -> throw new IllegalStateException("unhandled attempt confirmation " + confirmation); } } diff --git a/src/config/spotbugs/exclude.xml b/src/config/spotbugs/exclude.xml index 975d7893..a8fff6fa 100644 --- a/src/config/spotbugs/exclude.xml +++ b/src/config/spotbugs/exclude.xml @@ -35,6 +35,17 @@ + + + + + +