# notification-services Specification ## Purpose Defines transport-independent notification services whose delivery configuration is bound before consumers submit semantically tagged text messages. ## Requirements ### Requirement: Transport-independent bound notification contract The notification API SHALL provide a non-generic bound service under `com.r35157.service.notification` whose only delivery input is an `ΩNotificationMessageΩ` and whose synchronous failures use `IOException`. A consumer using an already bound service SHALL NOT need a transport-specific message type or an implementation-package dependency. #### Scenario: Bound consumer sends a message - **WHEN** a consumer receives a configured `BoundNotificationService` - **THEN** it can call `push(message)` using only an `ΩNotificationMessageΩ` #### Scenario: Delivery failure is reported synchronously - **WHEN** a bound transport encounters a delivery failure - **THEN** `push(message)` reports the failure through its `IOException` contract ### Requirement: Addressed services bind destination configuration The notification API SHALL provide an `AddressedNotificationService` generic only over a `NotificationDestination` type. Binding a destination SHALL produce a `BoundNotificationService` that captures the destination so later calls require only an `ΩNotificationMessageΩ`. #### Scenario: Destination is bound once - **WHEN** a destination is passed to an addressed notification service's binding operation - **THEN** the returned bound service sends subsequent messages to that captured destination without requiring it again ### Requirement: Notification message validation Every public notification-service `push(...)` entry point SHALL reject a null, empty, or blank `ΩNotificationMessageΩ` with `IllegalArgumentException` before attempting any network or transport operation. #### Scenario: Null message is rejected - **WHEN** a caller pushes a null notification message - **THEN** the service throws `IllegalArgumentException` before delivery is attempted #### Scenario: Empty or blank message is rejected - **WHEN** a caller pushes an empty or whitespace-only notification message - **THEN** the service throws `IllegalArgumentException` before delivery is attempted ### Requirement: Pushover delivery remains functional The Pushover implementation SHALL accept `ΩNotificationMessageΩ` directly, preserve its existing synchronous HTTP delivery behavior, and expose it as `PushoverNotificationService` implementing `BoundNotificationService`. #### Scenario: Valid Pushover message is submitted - **WHEN** a caller pushes a valid message through a configured Pushover notification service - **THEN** the service submits the same message through the existing Pushover API request flow #### Scenario: Pushover rejects delivery - **WHEN** Pushover returns a non-successful HTTP response or communication fails - **THEN** the service reports the delivery failure as an `IOException` ### Requirement: SMTP binding captures address and subject An SMTP destination SHALL contain both an `ΩEmailAddressΩ` and a fixed `ΩEmailSubjectΩ`. SMTP SHALL support binding these two values into a `BoundNotificationService`, and SHALL reject a null, empty, or blank address or subject with `IllegalArgumentException` when the destination is created. #### Scenario: SMTP service is fully bound - **WHEN** a caller binds a valid email address and subject - **THEN** the returned bound service requires only an `ΩNotificationMessageΩ` for each push #### Scenario: Invalid SMTP binding is rejected - **WHEN** a caller creates or requests an SMTP binding with a null, empty, or blank email address or subject - **THEN** the operation throws `IllegalArgumentException` #### Scenario: Valid SMTP delivery remains unimplemented - **WHEN** a valid message is pushed through a valid SMTP binding - **THEN** the service reports that SMTP delivery is not implemented ### Requirement: Discord delivery remains unimplemented The Discord stub SHALL implement `BoundNotificationService`, accept `ΩNotificationMessageΩ` directly, and SHALL NOT implement webhook delivery as part of this capability. #### Scenario: Valid Discord delivery remains unimplemented - **WHEN** a valid message is pushed through the configured Discord service - **THEN** the service reports that Discord delivery is not implemented without performing webhook delivery ### Requirement: Obsolete notification API is removed The notification framework SHALL reside exclusively under `com.r35157.service.notification`. It SHALL NOT retain compatibility aliases under `com.r35157.libs.notification`, notifier-named public interfaces or implementations, the `NotificationMessage` marker, or transport-specific message wrapper types. #### Scenario: Production code uses the new service API - **WHEN** the production source tree is inspected after migration - **THEN** notification framework code and consumers reference only the new package and service-oriented types #### Scenario: Removed types are unavailable - **WHEN** downstream code attempts to import an old notifier or message-wrapper type - **THEN** that type is no longer part of the source or compiled API