fix(notification): close the two pre-existing gates that broke check

`./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) <noreply@anthropic.com>
This commit is contained in:
DongHyeonka
2026-08-14 17:39:39 +09:00
co-authored by Claude Opus 5
parent c3043e530a
commit ac874e49e6
2 changed files with 12 additions and 0 deletions
@@ -69,6 +69,7 @@ public record ProviderSubmissionResult(
"an ambiguous attempt may not claim provider acceptance");
}
}
default -> throw new IllegalStateException("unhandled attempt confirmation " + confirmation);
}
}
+11
View File
@@ -35,6 +35,17 @@
<Class name="dev.caskeleton.adapter.inbound.graphql.GraphqlHttpBoundaryQualificationTest$TestSecurityConfiguration"/>
</Match>
<!-- Provider notification 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 (a failure raises
CallbackValidationException -> 400), not from permitAll(). Scoped to this exact
configuration class; any other CSRF disable remains reportable. -->
<Match>
<Bug pattern="SPRING_CSRF_PROTECTION_DISABLED"/>
<Class name="dev.caskeleton.adapter.inbound.web.notification.platform.callback.CallbackMvcSecurityConfiguration"/>
</Match>
<!-- Test-only violation fixture intentionally calls unsafe Jackson default typing so
architecture tests can prove the boundary rule catches it. Production and non-fixture
test classes remain covered by SECUJDES. -->