adapter-outbound-notification — 모듈 인벤토리
revision=a24ece9cf797f7ea647e33bf846b115208ed1ba5
generatedAt=2026-08-30T06:35:30+00:00

=== tracked file 총계 ===
$ git ls-files 'adapter/outbound/notification' | wc -l
240
exit=0

$ for d in $(git ls-files 'adapter/outbound/notification/src' | sed 's|^adapter/outbound/notification/src/||' | cut -d/ -f1 | sort -u); do n=$(git ls-files "adapter/outbound/notification/src/$d" | wc -l); l=$(git ls-files "adapter/outbound/notification/src/$d" | xargs wc -l 2>/dev/null | tail -1 | awk '{print $1}'); echo "$d: $n files, $l LOC"; done
main: 171 files, 14695 LOC
test: 65 files, 10045 LOC
exit=0

=== main 패키지 배치 ===
$ git ls-files 'adapter/outbound/notification/src/main' | grep '\.java$' | sed 's|.*/dev/caskeleton/||' | xargs -n1 dirname | sort | uniq -c | sort -rn
     23 adapter/outbound/notification/platform/dispatch
     15 adapter/outbound/notification/provider
     14 adapter/outbound/notification/platform/template
     12 adapter/outbound/notification/catalog
     11 adapter/outbound/notification/platform/provider/ses
     11 adapter/outbound/notification/platform/autoconfigure
     10 adapter/outbound/notification/platform/provider/webpush
     10 adapter/outbound/notification/platform/provider/fcm
      9 adapter/outbound/notification/platform/provider/twilio
      7 adapter/outbound/notification/template
      7 adapter/outbound/notification/platform/security
      7 adapter/outbound/notification/platform/provider/smtp
      6 adapter/outbound/notification/platform/provider/http
      5 adapter/outbound/notification/platform/observation
      4 adapter/outbound/notification/platform/provider/apns
      3 adapter/outbound/notification/slack/webhook
      3 adapter/outbound/notification/platform/reactor
      3 adapter/outbound/notification/platform/provider/webhook
      3 adapter/outbound/notification/platform/provider
      3 adapter/outbound/notification/email/google
      3 adapter/outbound/notification/core
      2 adapter/outbound/notification
exit=0

=== test 패키지 배치 ===
$ git ls-files 'adapter/outbound/notification/src/test' | grep '\.java$' | sed 's|.*/dev/caskeleton/||' | xargs -n1 dirname | sort | uniq -c | sort -rn
      9 adapter/outbound/notification/platform/testkit
      7 adapter/outbound/notification/platform/security
      7 adapter/outbound/notification/platform/dispatch
      5 adapter/outbound/notification/provider
      5 adapter/outbound/notification/platform/autoconfigure
      4 adapter/outbound/notification/platform/template
      3 adapter/outbound/notification/platform/provider/twilio
      3 adapter/outbound/notification/platform/provider/http
      3 adapter/outbound/notification/catalog
      2 adapter/outbound/notification/platform/provider/webpush
      2 adapter/outbound/notification/platform/provider/smtp
      2 adapter/outbound/notification/platform/provider/ses
      2 adapter/outbound/notification/platform/provider/fcm
      2 adapter/outbound/notification/platform/provider
      2 adapter/outbound/notification/core
      1 adapter/outbound/notification/template
      1 adapter/outbound/notification/platform/provider/webhook
      1 adapter/outbound/notification/platform/provider/apns
exit=0

=== main 상위 25 ===
$ git ls-files 'adapter/outbound/notification/src/main' | grep '\.java$' | xargs wc -l | sort -rn | head -26
 14695 total
   516 adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/catalog/NotificationBindingCompiler.java
   473 adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/template/LocalEmailRenderer.java
   363 adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/provider/NotificationProviderAttemptAdapter.java
   276 adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/platform/dispatch/ProviderRuntime.java
   258 adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/platform/provider/webhook/WebhookNotificationProviderAdapter.java
   253 adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/template/NotificationTemplateCatalog.java
   239 adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/platform/autoconfigure/NotificationProviderAssembly.java
   228 adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/platform/security/ProviderCredentialManager.java
   220 adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/platform/security/AesGcmContactPointProtector.java
   211 adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/platform/autoconfigure/NotificationSmtpProviderConfig.java
   209 adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/platform/provider/ses/SesRequestMapper.java
   197 adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/platform/dispatch/NotificationSchedulerWorker.java
   193 adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/platform/provider/webpush/Rfc8291Aes128GcmEncryptor.java
   190 adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/platform/autoconfigure/NotificationPlatformSettings.java
   185 adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/platform/template/CanonicalNotificationRenderer.java
   175 adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/template/NotificationTemplateManifest.java
   169 adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/platform/provider/ses/SesNotificationProviderAdapter.java
   164 adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/platform/autoconfigure/SmtpProviderRuntimeAssembler.java
   163 adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/provider/NotificationAdmissionReadinessAdapter.java
   162 adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/platform/template/ThymeleafStringTemplateEngine.java
   159 adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/platform/security/AesGcmNotificationPayloadProtection.java
   151 adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/provider/NotificationReconciliationAdapter.java
   151 adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/catalog/NotificationCutoverRouteCatalog.java
   151 adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/catalog/CompiledNotificationBinding.java
   147 adapter/outbound/notification/src/main/java/dev/caskeleton/adapter/outbound/notification/platform/provider/smtp/SmtpMimeMessageFactory.java
exit=0

=== 비 Java ===
$ git ls-files 'adapter/outbound/notification' | grep -v '\.java$'
adapter/outbound/notification/CLAUDE.md
adapter/outbound/notification/README.md
adapter/outbound/notification/build.gradle
adapter/outbound/notification/gradle.lockfile
adapter/outbound/notification/src/test/resources/notification/templates/email/contract-v1.html
adapter/outbound/notification/src/test/resources/notification/templates/email/contract-v1.subject.txt
adapter/outbound/notification/src/test/resources/notification/templates/email/contract-v1.text.txt
adapter/outbound/notification/src/test/resources/notification/templates/slack/contract-v1.txt
exit=0

=== 레지스트리 ===
$ python3 -c "
import json;d=json.load(open('config/architecture/modules.json'))
for m in d['modules']:
    if m['id']=='adapter-outbound-notification': print(json.dumps(m,ensure_ascii=False,indent=2))
"
{
  "id": "adapter-outbound-notification",
  "gradle_path": ":adapter:outbound:notification",
  "source_path": "src/adapter/outbound/notification",
  "allowed_dependencies": [
    "domain-core",
    "application-core",
    "shared-contract",
    "adapter-outbound-support"
  ],
  "runtime_memberships": [
    "app-bootstrap"
  ]
}
exit=0

=== build.gradle ===
$ cat -n 'adapter/outbound/notification/build.gradle'
     1	dependencies {
     2	    implementation project(':application-core')
     3	    implementation project(':shared-contract')
     4	    implementation project(':adapter:outbound:support')
     5	
     6	    implementation 'org.springframework.boot:spring-boot-autoconfigure'
     7	    implementation 'org.springframework:spring-web'   // Slack webhook client (RestClient)
     8	    implementation 'org.slf4j:slf4j-api'
     9	
    10	    // Notification Delivery Platform.
    11	    // - mail: the SMTP provider adapter is built on JavaMailSender/MimeMessageHelper, which is where
    12	    //   multipart/alternative, inline resources and header validation already live. Rebuilding MIME
    13	    //   by hand to avoid one dependency would be the more dangerous choice.
    14	    // - jackson-databind: provider payloads, callback bodies and the canonical variables payload are
    15	    //   JSON. It stays inside this adapter; application-core never sees a JSON type.
    16	    // - reactor-core: only the optional Reactor facade uses it. The core async type stays
    17	    //   CompletionStage, so nothing else on this classpath depends on Reactor.
    18	    implementation 'org.springframework.boot:spring-boot-starter-mail'
    19	    implementation 'org.springframework.boot:spring-boot-starter-json'
    20	    implementation 'io.projectreactor:reactor-core'
    21	    // JSON Schema 2020-12 validation of template variables, using the same validator and version the
    22	    // messaging adapter already depends on rather than a second implementation of the same spec.
    23	    //
    24	    // Jackson's YAML dataformat is excluded because schemas arrive as JSON strings and a second
    25	    // parser for a format this leaf never reads is surface for nothing. It does not remove YAML from
    26	    // the runtime — org.yaml:snakeyaml is on this classpath via spring-boot-starter, which is how
    27	    // Spring Boot reads application.yml. The comment here used to claim the stronger outcome, and
    28	    // the resolved graph had said otherwise for as long as it stood; dependencyPolicy below now
    29	    // states the claim the build can check.
    30	    // Thymeleaf is the reference HTML renderer, added as the engine only — not the Spring
    31	    // starter, which would drag a view resolver and a servlet integration onto an outbound
    32	    // adapter that renders strings and never serves a request.
    33	    implementation 'org.thymeleaf:thymeleaf'
    34	
    35	    implementation('com.networknt:json-schema-validator:3.0.2') {
    36	        exclude group: 'tools.jackson.dataformat', module: 'jackson-dataformat-yaml'
    37	        exclude group: 'com.fasterxml.jackson.dataformat', module: 'jackson-dataformat-yaml'
    38	    }
    39	
    40	    annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
    41	
    42	    testImplementation 'io.projectreactor:reactor-test'
    43	}
    44	tasks.withType(JavaCompile).configureEach { options.encoding = 'UTF-8' }
    45	
    46	// The exclusion above, stated as something the build verifies rather than something a comment
    47	// asserts. verifyDependencyPolicy resolves runtimeClasspath and fails if the coordinate is present.
    48	dependencyPolicy {
    49	    absent 'com.fasterxml.jackson.dataformat:jackson-dataformat-yaml',
    50	            because: 'schemas arrive as JSON strings; a second YAML parser is surface for a format ' +
    51	                    'this leaf never reads'
    52	    absent 'tools.jackson.dataformat:jackson-dataformat-yaml',
    53	            because: 'the Jackson 3 coordinate of the same parser, excluded for the same reason'
    54	}
exit=0

=== leaf 밖 소비자 ===
$ git grep -l 'dev.caskeleton.adapter.outbound.notification' -- . | grep -v '^adapter/outbound/notification/' | sed 's|/src/.*||' | sort | uniq -c
     21 app-bootstrap
      1 gradle/notification-api-surface.gradle
exit=0

