Sub-scope 07 (notification) slack/webhook + email/google + testkit + template resources — manifest and probes
revision=a24ece9cf797f7ea647e33bf846b115208ed1ba5
generatedAt=2026-08-30T07:01:25+00:00

=== OWNED FILES ===
8d8fe37be09d243fb97df633b23729fb30382956 main/java/dev/caskeleton/adapter/outbound/notification/email/google/GoogleEmailClient.java 19
88514a5f083ea33705176543ef257ba6f60c18af main/java/dev/caskeleton/adapter/outbound/notification/email/google/GoogleEmailNotificationAdapterConfig.java 25
69e42abedab03da18483238b1618254292c0a80d main/java/dev/caskeleton/adapter/outbound/notification/email/google/GoogleEmailProvider.java 41
78e64152922eb35ce07a498a507adbe6b38e325d main/java/dev/caskeleton/adapter/outbound/notification/slack/webhook/SlackClient.java 19
a09129dfab637aa5b32bd15c44eba03f2cc43ae8 main/java/dev/caskeleton/adapter/outbound/notification/slack/webhook/SlackNotificationAdapterConfig.java 25
b7805947e3e04e799712e6448bf822e8444c1418 main/java/dev/caskeleton/adapter/outbound/notification/slack/webhook/SlackWebhookProvider.java 42
0bf316a4e6e68ca17bbff6cd5e53cb81b05ea91e test/java/dev/caskeleton/adapter/outbound/notification/platform/testkit/CallbackContract.java 96
6f4e1d597f0ccb31a015f582135286b7a78bde16 test/java/dev/caskeleton/adapter/outbound/notification/platform/testkit/ContractAdapters.java 274
346fc17c930bb3170dbc668f1a3f7347f01c4ad1 test/java/dev/caskeleton/adapter/outbound/notification/platform/testkit/CrossProviderContractSuiteTest.java 137
199d6ba156a53f6899cc1129db4b425a1f96d701 test/java/dev/caskeleton/adapter/outbound/notification/platform/testkit/NotificationChaosSecurityTest.java 124
cbcc07ee440a1ea6a8b64dd4766ae0ecb65e428b test/java/dev/caskeleton/adapter/outbound/notification/platform/testkit/NotificationPerformanceCertificationTest.java 141
76c5365f47107d10bf37e5c47dcb92cb1c16a82b test/java/dev/caskeleton/adapter/outbound/notification/platform/testkit/PiiLeakScanner.java 36
5c64b64a1b550ed32d64dba8827cb77e323909cf test/java/dev/caskeleton/adapter/outbound/notification/platform/testkit/ProviderAdapterContract.java 109
6a4e2bc808ea46db2b381bcd9e386121ea779229 test/java/dev/caskeleton/adapter/outbound/notification/platform/testkit/ProviderFaultHarness.java 125
8d1790dc425fc39d978cdcbe408293ca736cb20b test/java/dev/caskeleton/adapter/outbound/notification/platform/testkit/ProviderFixtures.java 127
c1000b004248ba20ad12fea292535bd604331434 test/resources/notification/templates/email/contract-v1.html 2
bea116c3fc2ce9008071ea1d49b486de0b6a5984 test/resources/notification/templates/email/contract-v1.subject.txt 1
756df6f304c23cf6a225d1184ae7dbe5032831a7 test/resources/notification/templates/email/contract-v1.text.txt 2
ce4b590959b647ef653dd931c78b1d2016b1ea89 test/resources/notification/templates/slack/contract-v1.txt 3
main_count=6  test_count=9  resource_count=4

=== 8.1 도달성: 공유 provider 계약을 상속하는 어댑터 테스트 ===
$ grep -rn 'extends ProviderAdapterContract' adapter/outbound/notification/src/test
adapter/outbound/notification/src/test/java/dev/caskeleton/adapter/outbound/notification/platform/provider/ses/SesNotificationProviderAdapterTest.java:50:class SesNotificationProviderAdapterTest extends ProviderAdapterContract {
adapter/outbound/notification/src/test/java/dev/caskeleton/adapter/outbound/notification/platform/provider/twilio/TwilioSmsProviderAdapterTest.java:24:class TwilioSmsProviderAdapterTest extends ProviderAdapterContract {
adapter/outbound/notification/src/test/java/dev/caskeleton/adapter/outbound/notification/platform/provider/apns/ApnsNotificationProviderAdapterTest.java:31:class ApnsNotificationProviderAdapterTest extends ProviderAdapterContract {
exit=0

$ grep -n 'new [A-Za-z]*ProviderAdapter\|new [A-Za-z]*SmsProviderAdapter' adapter/outbound/notification/src/test/java/dev/caskeleton/adapter/outbound/notification/platform/testkit/ContractAdapters.java
108:        new SesNotificationProviderAdapter(
148:        new TwilioSmsProviderAdapter(
175:        new ApnsNotificationProviderAdapter(
199:        new WebPushNotificationProviderAdapter(
236:        new WebhookNotificationProviderAdapter(
exit=0

=== 8.2 조건 형제 비교: transport 실패가 ambiguous 로 번역되는 어댑터 ===
$ grep -rln 'ProviderResults.fromTransport' adapter/outbound/notification/src/main
adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/platform/provider/ses/SesNotificationProviderAdapter.java
adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/platform/provider/webpush/WebPushNotificationProviderAdapter.java
adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/platform/provider/twilio/TwilioSmsProviderAdapter.java
adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/platform/provider/apns/ApnsNotificationProviderAdapter.java
adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/platform/provider/webhook/WebhookNotificationProviderAdapter.java
exit=0

$ grep -n 'sendBatch\|try\|catch' adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/platform/provider/fcm/FcmBatchCoordinator.java
83:    FcmBatchResult batch = gateway.sendBatch(messages);
exit=0

$ grep -rln 'AMBIGUOUS' adapter/outbound/notification/src/test/java/dev/caskeleton/adapter/outbound/notification/platform/provider
adapter/outbound/notification/src/test/java/dev/caskeleton/adapter/outbound/notification/platform/provider/smtp/SmtpNotificationProviderAdapterTest.java
adapter/outbound/notification/src/test/java/dev/caskeleton/adapter/outbound/notification/platform/provider/webhook/WebhookNotificationProviderAdapterTest.java
exit=0

=== 8.3 SPI provider 두 종의 배선 ===
$ grep -n 'ConditionalOnProperty' -A 4 adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/slack/webhook/SlackNotificationAdapterConfig.java adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/email/google/GoogleEmailNotificationAdapterConfig.java
adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/slack/webhook/SlackNotificationAdapterConfig.java:4:import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/slack/webhook/SlackNotificationAdapterConfig.java-5-import org.springframework.context.annotation.Bean;
adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/slack/webhook/SlackNotificationAdapterConfig.java-6-import org.springframework.context.annotation.Configuration;
adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/slack/webhook/SlackNotificationAdapterConfig.java-7-
adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/slack/webhook/SlackNotificationAdapterConfig.java-8-/**
--
adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/slack/webhook/SlackNotificationAdapterConfig.java:18:  @ConditionalOnProperty(
adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/slack/webhook/SlackNotificationAdapterConfig.java-19-      name = "app.notification.slack-webhook.enabled",
adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/slack/webhook/SlackNotificationAdapterConfig.java-20-      havingValue = "true",
adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/slack/webhook/SlackNotificationAdapterConfig.java-21-      matchIfMissing = false)
adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/slack/webhook/SlackNotificationAdapterConfig.java-22-  public NotificationProvider slackWebhookProvider(SlackClient slackClient) {
--
adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/email/google/GoogleEmailNotificationAdapterConfig.java:4:import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/email/google/GoogleEmailNotificationAdapterConfig.java-5-import org.springframework.context.annotation.Bean;
adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/email/google/GoogleEmailNotificationAdapterConfig.java-6-import org.springframework.context.annotation.Configuration;
adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/email/google/GoogleEmailNotificationAdapterConfig.java-7-
adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/email/google/GoogleEmailNotificationAdapterConfig.java-8-/**
--
adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/email/google/GoogleEmailNotificationAdapterConfig.java:18:  @ConditionalOnProperty(
adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/email/google/GoogleEmailNotificationAdapterConfig.java-19-      name = "app.notification.google-email.enabled",
adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/email/google/GoogleEmailNotificationAdapterConfig.java-20-      havingValue = "true",
adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/email/google/GoogleEmailNotificationAdapterConfig.java-21-      matchIfMissing = false)
adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/email/google/GoogleEmailNotificationAdapterConfig.java-22-  public NotificationProvider googleEmailProvider(GoogleEmailClient googleEmailClient) {
exit=0

=== 8.4 테스트 레인 실행 ===
$ tail -6 /tmp/ntf_test.log
> Task :adapter:outbound:notification:test

BUILD SUCCESSFUL in 5s
19 actionable tasks: 1 executed, 18 up-to-date
Consider enabling configuration cache to speed up this build: https://docs.gradle.org/9.0.0/userguide/configuration_cache_enabling.html
GRADLE_EXIT=0
exit=0

