Internal executor for notification channel delivery attempts.
NiFi owns orchestration, rule decisions, template selection, retries, and audit callbacks. This service owns provider-specific send behavior behind a stable HTTP contract.
The executor supports dry_run mode for validating the end-to-end pipeline
without provider credentials. Provider mode currently supports browser push and
SMTP email delivery.
GET /healthzGET /readyzGET /openapi.jsonPOST /internal/notifications/:id/deliveries
Example delivery request:
{
"channel": "email",
"provider_key": "smtp:default",
"recipient": {
"type": "email",
"address": "[email protected]"
},
"message": {
"subject": "Deployment failed",
"text": "The production deployment failed during prod-deploy."
},
"options": {},
"metadata": {
"notification_request_id": "00000000-0000-0000-0000-000000000000"
}
}Dry-run response:
{
"ok": true,
"status": "sent",
"channel": "email",
"provider_key": "smtp:default",
"provider_message_id": "dry-run-00000000-0000-0000-0000-000000000000",
"response_json": {
"mode": "dry_run"
}
}Provider implementations plug into the DeliveryProvider contract exported from
src/delivery/provider.ts. A provider declares a manifest and an execute
function:
export type DeliveryProvider = {
manifest: {
providerKey: string;
displayName: string;
channels: NotificationChannel[];
configSchema?: JsonRecord;
secretSchema?: JsonRecord;
metadata?: JsonRecord;
};
execute: (
notificationRequestId: string,
providerKey: string,
input: DeliveryRequest
) => Promise<DeliveryResult>;
};The core executor registry maps a provider_key to a provider. Built-in
providers currently include:
web-push:browser_pushsmtp:default
Community providers should use stable provider keys such as
slack:default, discord:default, twilio:sms, or ses:default. A packaged
provider should accept the stable delivery request and return:
okstatuschannelprovider_keyprovider_message_idresponse_jsonerror_message
Provider credentials must be resolved from Vault at runtime. Do not commit provider tokens, SMTP passwords, SMS credentials, push keys, or webhook secrets.
Separately deployed provider sidecars are a good future extension point, but they need an explicit allowlist, auth model, and payload-redaction rules before the core executor should forward delivery payloads to arbitrary URLs.
Email delivery uses nodemailer with the smtp:default provider key. Direct
email recipients should use:
{
"type": "email",
"address": "[email protected]",
"channels": ["email"]
}SMTP configuration can be provided directly with environment variables or from Vault. The deployment manifest grants access to the Cloudflare SMTP token at:
secret/data/cloudflare-smtp-secret
Google Cloud-backed Vault secrets expose their secret payload under a single
value key. The Cloudflare SMTP token is read from that key. Non-secret SMTP
connection settings are configured with environment variables:
EMAIL_SMTP_HOST=smtp.mx.cloudflare.netEMAIL_SMTP_PORT=465EMAIL_SMTP_SECURE=trueEMAIL_SMTP_USERNAME=api_tokenEMAIL_FROMEMAIL_REPLY_TO
Important environment variables:
EXECUTOR_MODE:dry_runorproviderINTERNAL_TOKEN_VAULT_PATHVAULT_ADDRVAULT_TOKEN_FILEREQUEST_TIMEOUT_MSEMAIL_SMTP_VAULT_PATHEMAIL_SMTP_HOSTEMAIL_SMTP_PORTEMAIL_SMTP_SECUREEMAIL_SMTP_USERNAMEEMAIL_SMTP_PASSWORDEMAIL_FROMEMAIL_REPLY_TO
npm install
npm run build