5.9 KiB
Notifications Contract
Contract Metadata
{
"subsystem_id": "notifications",
"lane": "L6",
"contract_file": "docs/release-control/v6/internal/subsystems/notifications.md",
"status_file": "docs/release-control/v6/internal/status.json",
"registry_file": "docs/release-control/v6/internal/subsystems/registry.json",
"dependency_subsystem_ids": []
}
Purpose
Own notification delivery transport, provider configuration, queueing, and notification-management API surfaces.
Canonical Files
internal/notifications/notifications.gointernal/notifications/queue.gointernal/notifications/email_enhanced.gointernal/notifications/webhook_enhanced.gointernal/api/notifications.gofrontend-modern/src/api/notifications.ts
Shared Boundaries
frontend-modern/src/api/notifications.tsshared withapi-contracts: the notifications frontend client is both a notification delivery control surface and a canonical API payload contract boundary.internal/api/notifications.goshared withapi-contracts: notification handlers are both a notification delivery control surface and a canonical API payload contract boundary.
Extension Points
- Add or change provider delivery, queue processing, or retry behavior through
internal/notifications/ - Add or change notification-management request or response handling through
internal/api/notifications.go - Add or change notification-management frontend transport through
frontend-modern/src/api/notifications.ts
Forbidden Paths
- Reintroducing notification delivery behavior as implicit side effects under
alertsor generic monitoring ownership - Duplicating webhook or email delivery safety checks outside
internal/notifications/ - Letting notification queue, DLQ, or provider test paths drift away from the explicit proof routes in
registry.json
Completion Obligations
- Update this contract when canonical notification entry points move
- Keep notification API transport and backend delivery proofs aligned in
registry.json - Preserve explicit queue, webhook-security, and provider-delivery coverage when notification behavior changes
Current State
This subsystem now makes email, webhook, Apprise, queueing, and delivery safety explicit inside the current architecture lane instead of leaving them implied by the broader alerts surface. A later lane split can still promote alerts and notification delivery into their own product lane once the governed floor is ready.
internal/notifications/ is the live delivery engine. It owns provider
selection, secure webhook transport, Apprise delivery, queue persistence, DLQ
handling, retry policy, and delivery observability for alert-driven
notifications. Queue dequeue, direct-delivery fallback, and enqueue-failure
recovery now run through one owned notification-delivery executor instead of
keeping separate primary send paths. Single-alert, grouped, and resolved
webhook delivery now also share one owned rendering path for URL rendering,
service-specific enrichment, and template selection. When persistent queue
bootstrap fails, the runtime now falls back to an in-memory queue owner
instead of dropping into a separate nil-queue direct-send mode. Service-specific
webhook compatibility like Pushover app_token / user_token legacy fields is
now canonicalized at webhook-config ownership boundaries, so runtime delivery
only handles canonical token / user fields instead of injecting aliases
mid-flight. That boundary includes config persistence plus API/UI ingress for
create, update, and ad hoc test requests; internal/notifications/ may not
silently rewrite those legacy keys once webhook state is already live in the
runtime.
The webhook template registry is also the canonical source of truth for the
alert webhook service set and the metadata the frontend uses to build its
service chooser. Frontend presentation may format the options, but it must
derive the available services, labels, and descriptions from the backend
template registry instead of keeping a second hardcoded service list. Mention
field visibility plus mention-placeholder/help copy for supported services
must also come from the same backend registry so the editor does not carry a
second service-specific presentation map.
Email single-alert, grouped, resolved, and HTML send paths must follow that
same ownership rule: they may expose different calling surfaces, but they must
all route through one canonical enhanced email executor instead of rebuilding
separate manager/config setup paths.
Notification test APIs must follow that same truthfulness rule: test email and
webhook paths may keep dedicated top-level entry points, but they must route
through canonical error-returning single-delivery executors instead of
fire-and-forget wrappers that can report false success.
Webhook test service/template synthesis must also stay inside
internal/notifications/: API handlers may decode the request and delegate,
but service-template selection, safe header copying, and generic test-template
fallback may not live as a parallel owner path under internal/api/.
Saved-webhook test actions, generic webhook test actions, and ad hoc webhook
test actions must also share the same enhanced webhook test executor so
service-template ownership, header normalization, and validation cannot drift
by entry point.
Enhanced webhook test/live delivery must follow that same ownership model:
webhook_enhanced.go may expose a richer config shape, but it must bridge back
into the canonical webhook render and transport path instead of maintaining a
parallel URL-rendering, enrichment, Telegram URL sanitization, or single-send
HTTP stack.
internal/api/notifications.go and
frontend-modern/src/api/notifications.ts are shared boundaries with
api-contracts: they are the product-facing control surface for
notification-management transport, while canonical payload-shape governance
still remains explicit in the shared API contract boundary.