Notification Approval Security & Recovery
This guide outlines the production security architecture, authorization controls, durable recovery guarantees, and network egress defenses implemented across@siglo/notifications. For standard multi-channel messaging and interactive step setup, see the @siglo/notifications Adapter Guide.
1. Two-Phase Approval Confirmation (Email Scanner Defense)
Enterprise email systems and corporate anti-virus filters (Microsoft Defender, Proofpoint, Mimecast) aggressively prefetch and follow all HTTP links inside incoming emails to inspect target pages. If an approval link accepted decisions onGET requests, automated scanners would inadvertently approve or reject mission-critical workflows before the human recipient even opened the email.
To eliminate this vulnerability, @siglo/notifications enforces a strict Two-Phase Confirmation Protocol:
[!SECURITY] GET and HEAD requests are strictly read-only:GETandHEADnever accept approval decisions or mutate workflow state, regardless ofresponseFormat.GETrenders an interactive HTML confirmation form; only aPOSTrequest containing the signed token in the request body is accepted.OPTIONShandles preflight requests, and all other HTTP methods return405 Method Not Allowed.
Framework Callback Registration
Register bothGET and POST handlers on your callback route, and configure URL-encoded body parsing:
[!IMPORTANT] Authorization & Bearer Token Mode: For production enterprise systems, always provide anauthorize(payload, request)callback that authenticates the user session and validates identity against the expected approver. If you are building a low-risk workflow where possession of the signed link is sufficient authorization, you must explicitly opt in by settingallowBearerApproval: true. Tokens are cryptographically signed HMAC bearer credentials;toleranceSecondsvalidates issuance timestamps against future clock drift, but link possession alone does not authenticate human identity unlessauthorizeor application authentication is enforced.
2. Distributed PostgreSQL Storage Setup
In distributed production environments (Kubernetes clusters, multi-container deployments), approval callbacks and worker instances must share the same database stores:[!WARNING] Connection Pool Sizing & Advisory Lock Affinity: Configure these stores on every worker and scheduler instance connected to the same PostgreSQL database. Process-local defaults (InMemoryApprovalRevocationStore) are not suitable for multi-node deployments. Each active callback holds a PostgreSQL session-level advisory lock (pg_try_advisory_lock) during execution. Ensure yourPoolhas sufficient connections. Because session advisory locks require connection affinity, transaction-pooling connection proxies (such as PgBouncer inpool_mode = transaction) are unsupported; use session-mode pooling (pool_mode = session) or connect directly to PostgreSQL.
3. Durable Acceptance, Concurrency & Cancellation
Lock Partitioning
- Approval callbacks and token revocations coordinate via a per-correlation-key PostgreSQL session advisory lock (
withApprovalLock). - Continuation step execution and compensation sagas coordinate via a per-stack PostgreSQL advisory lock (
withWorkflowLock).
409 Conflict) and should retry with exponential backoff.
Atomic State Transitions
- Claim Phase: An incoming approval atomically transitions the wait record from
WAITING→RESUMINGand persists the accepted event intoresume_payload. - Commit Phase: The transition from
RESUMING→RESUMEDonly commits after continuation steps and execution checkpoints settle. - Worker Crash Recovery: If a worker crashes midway through executing continuation steps, the record remains in
RESUMINGstate with the originalresume_payloadintact. The@siglo/schedulerpoller detects the record and re-executes the resumption safely after acquiring the stack lock.
Saga Cancellation
When a parent workflow fails or is cancelled:- Compensation marks pending durable waits and execution checkpoints as
CANCELLEDbefore invoking LIFO rollback handlers. cancelNotificationrevokes the approval token inPostgresApprovalRevocationStorebefore updating external channels (e.g. updating a Slack message to “Workflow Cancelled”).- Once cancelled, subsequent approval clicks are rejected with HTTP 409 even if late network packets arrive.
4. Dispatch Retries & Idempotency Windows
PostgresNotificationDispatchStore persists the exact rendered message body, recipient metadata, and deterministic provider idempotency keys before attempting network dispatch:
- Resend: Passes
Idempotency-Keyheader with a 24-hour deduplication window. - Custom Webhooks / Push: Pass
Idempotency-Keyheaders; receiving endpoints must honor deduplication. - SendGrid / Twilio: Retain at-least-once dispatch semantics upon ambiguous socket disconnects; provider batch IDs do not provide automatic deduplication on ambiguous network drops.
5. Network Egress Security Perimeter
Built-in transports enforce Siglo’s AsyncLocalStorage (ASL) network egress perimeter:- Strict DNS Preflight: The socket’s DNS lookup resolves and validates target IP addresses before establishing TCP/TLS connections. Private (
10.0.0.0/8,172.16.0.0/12,192.168.0.0/16), loopback (127.0.0.0/8), link-local/cloud metadata (169.254.169.254), and multicast ranges are rejected immediately. - TLS Certificate Verification & SNI: Standard SNI and certificate authority chains are enforced; insecure HTTP and unverified TLS are denied.
- Redirect Denial: HTTP redirects (
301,302,307) are rejected to prevent open-redirect SSRF bypasses. - Resource Bounds: Incoming response streams are bounded to 1 MiB to prevent memory exhaustion DoS attacks.
6. SMS Two-Way Webhook Authentication
When receiving SMS reply approvals (e.g. Twilio SMS webhooks):parseTwilioSmsReplyvalidates the authenticity of the Twilio webhook signature (X-Twilio-Signature), not the identity of the human mobile device.- Generate an unpredictable 128-bit cryptographic challenge with
createSmsApprovalReference('deploy:101')and persist it alongside the expected phone number and expiry. validateSmsApprovalReply(reply, pending)verifies that the incoming SMS matches the expected phone number, challenge token, and valid expiration window.- For high-privilege workflows, require a second factor (e.g. Authenticator TOTP or SSO confirmation) rather than relying exclusively on unauthenticated SMS channels.
7. Related Guides
- Notifications Adapter Guide: Multi-channel messaging, Slack cards, and interactive approval step configuration.
- PostgreSQL Adapter Guide: Schema management, ACID checkpoints, and advisory locks.
- Scheduler Adapter Guide: Background polling and durable timer resumption.
- Network Egress Policy: AsyncLocalStorage network perimeter enforcement.
