Files
clean-architecture-backend-…/docs/notification/migration-guide.md
T
DongHyeonkaandClaude Opus 5 701ba67456 feat(notification): implement the notification delivery platform
Maps the 31-module plan onto the registry's 19 leaves as packages; the two
edges the registry forbids (provider->httpclient, inbox->messaging) are
replaced by application-owned ports. See docs/notification/module-mapping.md.

Acceptance is not delivery: ProviderSubmissionResult refuses to carry a
delivery outcome, and AMBIGUOUS is a first-class terminal state that blocks
automatic retry and fallback until reconciliation resolves it.

Providers: SES (SigV4 + SNS callback), Twilio (X-Twilio-Signature +
reconciliation), FCM (FID-primary batch), APNs, Web Push (RFC 8030/8291/8292),
SMTP and webhook. Contact points are AES-256-GCM encrypted with a separate
HMAC lookup fingerprint; nothing raw reaches a log, metric tag or exception.

Dispatch commits the attempt row, calls the provider with no transaction open,
then records the outcome; the durable queue uses FOR UPDATE SKIP LOCKED.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-14 13:57:27 +09:00

1.5 KiB

Migration guide

From the R0 routing seam

The pre-existing dev.caskeleton.adapter.outbound.notification router (RoutingNotifier, FailOpenNotificationProvider, the Google email and Slack webhook seams) stays untouched. The delivery platform lives beside it under …notification.platform and does not modify or delete any R0 class.

Migration order per capability:

  1. Register the contact points behind ContactPointStorePort so the platform owns protected values.
  2. Publish the template version, and pin the template id, version and locale at every call site.
  3. Move the call site from the router to the N1 typed facade for the channel.
  4. Verify evidence in the snapshot rather than in the caller's return value: submit() is durable acceptance and nothing more.
  5. Remove the R0 route only after the platform route has produced provider evidence in the target environment.

Return-value semantics change

The R0 seam returned a send-shaped result. NotificationReceipt returns notificationId, a request status and an acceptance time. Callers that treated the old return value as proof of delivery must be changed; there is no compatibility shim, because a shim would have to invent the delivery claim this platform exists to avoid.

FCM target migration

Registration tokens keep working through LegacyFcmRegistrationToken. New registrations should use FcmInstallationId. The two are distinct types, so a migration is a compile-time task rather than a runtime guess.