@siglo/notifications 1.0.3 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  > Security migration: read [approval authorization, POST confirmation, durable recovery and delivery guarantees](../../docs/adapters/notification-hardening.md). GET is read-only; configure `authorize` or explicitly opt into `allowBearerApproval`.
4
4
 
5
-
6
5
  Enterprise multi-channel notifications, tamper-proof cryptographic approval tokens, and durable human-in-the-loop callback resumption for Siglo workflows.
7
6
 
8
7
  [![npm version](https://img.shields.io/npm/v/@siglo/notifications.svg)](https://www.npmjs.com/package/@siglo/notifications)
@@ -65,6 +64,7 @@ npm install @siglo/notifications @siglo/crypto @siglo/http @siglo/core
65
64
  ```
66
65
 
67
66
  Peer dependencies:
67
+
68
68
  - `@siglo/core`: `^1.0.0`
69
69
  - `@siglo/crypto`: `^1.0.0`
70
70
  - `@siglo/http`: `^1.0.0`
@@ -81,14 +81,14 @@ import { flow, waitForEvent, Step, useStorage } from '@siglo/core';
81
81
  import { PostgresStorageAdapter } from '@siglo/postgres';
82
82
  import { StaticKeyRing } from '@siglo/crypto';
83
83
  import {
84
- registerNotificationTransport,
85
- SlackTransport,
86
- sendInteractiveApprovalStep,
87
- createNotificationExpressMiddleware,
88
- configureApprovalRevocationStore,
89
- PostgresApprovalRevocationStore,
90
- PostgresNotificationDispatchStore,
91
- configureNotificationDispatchStore
84
+ registerNotificationTransport,
85
+ SlackTransport,
86
+ sendInteractiveApprovalStep,
87
+ createNotificationExpressMiddleware,
88
+ configureApprovalRevocationStore,
89
+ PostgresApprovalRevocationStore,
90
+ PostgresNotificationDispatchStore,
91
+ configureNotificationDispatchStore,
92
92
  } from '@siglo/notifications';
93
93
  import { Pool } from 'pg';
94
94
 
@@ -106,62 +106,64 @@ await dispatchStore.initialize();
106
106
  configureNotificationDispatchStore(dispatchStore);
107
107
 
108
108
  // 2. Register transports globally (or pass per-step)
109
- registerNotificationTransport(new SlackTransport({
110
- apiKey: process.env.SLACK_BOT_TOKEN!
111
- }));
109
+ registerNotificationTransport(
110
+ new SlackTransport({
111
+ apiKey: process.env.SLACK_BOT_TOKEN!,
112
+ }),
113
+ );
112
114
 
113
115
  // 3. Define KeyRing for HMAC signing and key rotation
114
116
  const approvalKeyRing = new StaticKeyRing('primary', {
115
- primary: process.env.APPROVAL_SECRET_CURRENT!,
116
- previous: process.env.APPROVAL_SECRET_PREVIOUS!
117
+ primary: process.env.APPROVAL_SECRET_CURRENT!,
118
+ previous: process.env.APPROVAL_SECRET_PREVIOUS!,
117
119
  });
118
120
 
119
121
  // 4. Define the approval workflow
120
122
  export const deploymentWorkflow = flow(
121
- // Step 1: Send Slack Block Kit card with signed Approve/Reject buttons
122
- sendInteractiveApprovalStep('requestApproval', {
123
- channel: 'slack',
124
- recipient: (ctx: { leadDevSlackId: string }) => ({ slackUserId: ctx.leadDevSlackId }),
125
- title: (ctx: { service: string; version: string }) => `Deploy ${ctx.service}@${ctx.version}?`,
126
- description: (ctx: { deploymentId: string }) => `Deployment ID: ${ctx.deploymentId}`,
127
- correlationKey: (ctx: { deploymentId: string }) => `deploy:${ctx.deploymentId}`,
128
- timeout: '2h',
129
- onApproveEvent: 'APPROVAL_RESOLVED',
130
- onRejectEvent: 'APPROVAL_RESOLVED',
131
- callbackBaseUrl: 'https://orchestrator.acme.com/api/siglo/callback',
132
- signingSecret: approvalKeyRing,
133
- autoCompensate: true // Updates Slack card to 'Cancelled' on failure or rollback
134
- }),
135
-
136
- // Step 2: Suspends workflow into PostgreSQL durable checkpoint with a 2h timer
137
- waitForEvent('APPROVAL_RESOLVED', {
138
- correlationKey: (ctx: { deploymentId: string }) => `deploy:${ctx.deploymentId}`,
139
- timeout: '2h'
140
- }),
141
-
142
- // Step 3: Guard on approved decision before executing side effects
143
- new Step('verifyDecision', async (ctx: { approved?: boolean; event?: { type: string } }) => {
144
- if (ctx.approved !== true || ctx.event?.type === 'timer:expired') {
145
- throw new Error('Deployment approval was rejected or expired');
146
- }
147
- return { verified: true };
148
- }),
149
-
150
- deployServiceStep
123
+ // Step 1: Send Slack Block Kit card with signed Approve/Reject buttons
124
+ sendInteractiveApprovalStep('requestApproval', {
125
+ channel: 'slack',
126
+ recipient: (ctx: { leadDevSlackId: string }) => ({ slackUserId: ctx.leadDevSlackId }),
127
+ title: (ctx: { service: string; version: string }) => `Deploy ${ctx.service}@${ctx.version}?`,
128
+ description: (ctx: { deploymentId: string }) => `Deployment ID: ${ctx.deploymentId}`,
129
+ correlationKey: (ctx: { deploymentId: string }) => `deploy:${ctx.deploymentId}`,
130
+ timeout: '2h',
131
+ onApproveEvent: 'APPROVAL_RESOLVED',
132
+ onRejectEvent: 'APPROVAL_RESOLVED',
133
+ callbackBaseUrl: 'https://orchestrator.acme.com/api/siglo/callback',
134
+ signingSecret: approvalKeyRing,
135
+ autoCompensate: true, // Updates Slack card to 'Cancelled' on failure or rollback
136
+ }),
137
+
138
+ // Step 2: Suspends workflow into PostgreSQL durable checkpoint with a 2h timer
139
+ waitForEvent('APPROVAL_RESOLVED', {
140
+ correlationKey: (ctx: { deploymentId: string }) => `deploy:${ctx.deploymentId}`,
141
+ timeout: '2h',
142
+ }),
143
+
144
+ // Step 3: Guard on approved decision before executing side effects
145
+ new Step('verifyDecision', async (ctx: { approved?: boolean; event?: { type: string } }) => {
146
+ if (ctx.approved !== true || ctx.event?.type === 'timer:expired') {
147
+ throw new Error('Deployment approval was rejected or expired');
148
+ }
149
+ return { verified: true };
150
+ }),
151
+
152
+ deployServiceStep,
151
153
  );
152
154
 
153
155
  // 5. Expose callback endpoint in Express
154
156
  const app = express();
155
157
  app.use(express.urlencoded({ extended: false }));
156
158
  app.all(
157
- '/api/siglo/callback',
158
- createNotificationExpressMiddleware({
159
- workflow: deploymentWorkflow,
160
- signingSecret: approvalKeyRing,
161
- authorize: authorizeApproval, // Application identity and CSRF check; see migration guide.
162
- responseFormat: 'html',
163
- allowedOrigins: ['https://orchestrator.acme.com', 'https://dashboard.acme.com']
164
- })
159
+ '/api/siglo/callback',
160
+ createNotificationExpressMiddleware({
161
+ workflow: deploymentWorkflow,
162
+ signingSecret: approvalKeyRing,
163
+ authorize: authorizeApproval, // Application identity and CSRF check; see migration guide.
164
+ responseFormat: 'html',
165
+ allowedOrigins: ['https://orchestrator.acme.com', 'https://dashboard.acme.com'],
166
+ }),
165
167
  );
166
168
  app.listen(3000);
167
169
  ```
@@ -172,71 +174,91 @@ app.listen(3000);
172
174
 
173
175
  `@siglo/notifications` ships with built-in adapters that adhere to Siglo's AsyncLocalStorage (ASL) network egress perimeter and require zero third-party SDK dependencies (using native HTTPS with validated socket DNS resolution):
174
176
 
175
- | Transport | Channel | Allowed Hosts | Key Features |
176
- |---|---|---|---|
177
- | `SlackTransport` | `slack` | `slack.com` | Block Kit action buttons, message cancellation via `chat.update`, modal forms via `openModal` |
178
- | `ResendTransport` | `email` | `api.resend.com` | Responsive HTML email action templates |
179
- | `SendGridTransport` | `email` | `api.sendgrid.com` | HTML email dispatch with `x-message-id` tracking |
180
- | `PostmarkTransport` | `email` | `api.postmarkapp.com` | HTML + plain-text email with server token auth |
181
- | `SmtpTransport` | `email` | User-defined host | Injected SMTP client (`sendMail`) without bundled dependencies |
182
- | `DiscordTransport` | `discord` | `discord.com` | Webhook embeds with clickable action links |
183
- | `TwilioTransport` | `sms` | `api.twilio.com` | Basic SMS dispatch and two-way signed webhook parsing |
184
- | `PushWebhookTransport` | `push` | Webhook hostname | Provider-neutral JSON push payloads over HTTPS |
177
+ | Transport | Channel | Allowed Hosts | Key Features |
178
+ | ---------------------- | --------- | --------------------- | --------------------------------------------------------------------------------------------- |
179
+ | `SlackTransport` | `slack` | `slack.com` | Block Kit action buttons, message cancellation via `chat.update`, modal forms via `openModal` |
180
+ | `ResendTransport` | `email` | `api.resend.com` | Responsive HTML email action templates |
181
+ | `SendGridTransport` | `email` | `api.sendgrid.com` | HTML email dispatch with `x-message-id` tracking |
182
+ | `PostmarkTransport` | `email` | `api.postmarkapp.com` | HTML + plain-text email with server token auth |
183
+ | `SmtpTransport` | `email` | User-defined host | Injected SMTP client (`sendMail`) without bundled dependencies |
184
+ | `DiscordTransport` | `discord` | `discord.com` | Webhook embeds with clickable action links |
185
+ | `TwilioTransport` | `sms` | `api.twilio.com` | Basic SMS dispatch and two-way signed webhook parsing |
186
+ | `PushWebhookTransport` | `push` | Webhook hostname | Provider-neutral JSON push payloads over HTTPS |
185
187
 
186
188
  ### Transport Configuration Examples
187
189
 
188
190
  ```typescript
189
191
  import {
190
- SlackTransport, ResendTransport, SendGridTransport, PostmarkTransport,
191
- DiscordTransport, TwilioTransport, SmtpTransport, PushWebhookTransport,
192
- registerNotificationTransport
192
+ SlackTransport,
193
+ ResendTransport,
194
+ SendGridTransport,
195
+ PostmarkTransport,
196
+ DiscordTransport,
197
+ TwilioTransport,
198
+ SmtpTransport,
199
+ PushWebhookTransport,
200
+ registerNotificationTransport,
193
201
  } from '@siglo/notifications';
194
202
 
195
203
  // Slack
196
- registerNotificationTransport(new SlackTransport({
197
- apiKey: process.env.SLACK_BOT_TOKEN!
198
- }));
204
+ registerNotificationTransport(
205
+ new SlackTransport({
206
+ apiKey: process.env.SLACK_BOT_TOKEN!,
207
+ }),
208
+ );
199
209
 
200
210
  // Resend Email
201
- registerNotificationTransport(new ResendTransport({
202
- apiKey: process.env.RESEND_API_KEY!,
203
- from: 'ops@acme.com'
204
- }));
211
+ registerNotificationTransport(
212
+ new ResendTransport({
213
+ apiKey: process.env.RESEND_API_KEY!,
214
+ from: 'ops@acme.com',
215
+ }),
216
+ );
205
217
 
206
218
  // SendGrid Email
207
- registerNotificationTransport(new SendGridTransport({
208
- apiKey: process.env.SENDGRID_API_KEY!,
209
- from: 'ops@acme.com'
210
- }));
219
+ registerNotificationTransport(
220
+ new SendGridTransport({
221
+ apiKey: process.env.SENDGRID_API_KEY!,
222
+ from: 'ops@acme.com',
223
+ }),
224
+ );
211
225
 
212
226
  // Postmark Email
213
- registerNotificationTransport(new PostmarkTransport({
214
- apiKey: process.env.POSTMARK_SERVER_TOKEN!,
215
- from: 'ops@acme.com'
216
- }));
227
+ registerNotificationTransport(
228
+ new PostmarkTransport({
229
+ apiKey: process.env.POSTMARK_SERVER_TOKEN!,
230
+ from: 'ops@acme.com',
231
+ }),
232
+ );
217
233
 
218
234
  // Discord
219
235
  registerNotificationTransport(new DiscordTransport());
220
236
 
221
237
  // Twilio SMS
222
- registerNotificationTransport(new TwilioTransport({
223
- accountSid: process.env.TWILIO_ACCOUNT_SID!,
224
- authToken: process.env.TWILIO_AUTH_TOKEN!,
225
- from: '+15551234567'
226
- }));
238
+ registerNotificationTransport(
239
+ new TwilioTransport({
240
+ accountSid: process.env.TWILIO_ACCOUNT_SID!,
241
+ authToken: process.env.TWILIO_AUTH_TOKEN!,
242
+ from: '+15551234567',
243
+ }),
244
+ );
227
245
 
228
246
  // Generic SMTP (e.g. Nodemailer)
229
- registerNotificationTransport(new SmtpTransport({
230
- host: 'smtp.mailgun.org',
231
- from: 'no-reply@acme.com',
232
- sendMail: async (mail) => nodemailerTransport.sendMail(mail)
233
- }));
247
+ registerNotificationTransport(
248
+ new SmtpTransport({
249
+ host: 'smtp.mailgun.org',
250
+ from: 'no-reply@acme.com',
251
+ sendMail: async mail => nodemailerTransport.sendMail(mail),
252
+ }),
253
+ );
234
254
 
235
255
  // Generic HTTPS Push Webhook
236
- registerNotificationTransport(new PushWebhookTransport({
237
- url: 'https://push.acme.com/v1/notify',
238
- headers: { 'X-Service-Token': process.env.PUSH_SERVICE_TOKEN! }
239
- }));
256
+ registerNotificationTransport(
257
+ new PushWebhookTransport({
258
+ url: 'https://push.acme.com/v1/notify',
259
+ headers: { 'X-Service-Token': process.env.PUSH_SERVICE_TOKEN! },
260
+ }),
261
+ );
240
262
  ```
241
263
 
242
264
  ---
@@ -251,10 +273,10 @@ Dispatches one-way alerts (email, chat, SMS, push) with automatic idempotency de
251
273
  import { sendNotificationStep } from '@siglo/notifications';
252
274
 
253
275
  const alertOps = sendNotificationStep('alertOps', {
254
- channel: 'slack',
255
- recipient: { slackChannelId: 'C_OPS_ALERTS' },
256
- template: (ctx) => `High latency detected on ${ctx.serviceName}: ${ctx.p99}ms`,
257
- deduplicationTtl: 3600 // Suppresses duplicate alerts within 1 hour
276
+ channel: 'slack',
277
+ recipient: { slackChannelId: 'C_OPS_ALERTS' },
278
+ template: ctx => `High latency detected on ${ctx.serviceName}: ${ctx.p99}ms`,
279
+ deduplicationTtl: 3600, // Suppresses duplicate alerts within 1 hour
258
280
  });
259
281
  ```
260
282
 
@@ -266,17 +288,17 @@ Generates signed action tokens, formats interactive cards/emails, registers comp
266
288
  import { sendInteractiveApprovalStep } from '@siglo/notifications';
267
289
 
268
290
  const approvalStep = sendInteractiveApprovalStep('legalApproval', {
269
- channel: 'email',
270
- recipient: (ctx) => ({ email: ctx.legalReviewerEmail }),
271
- title: (ctx) => `Contract Review Required: ${ctx.contractTitle}`,
272
- description: (ctx) => `Value: $${ctx.contractValue}`,
273
- correlationKey: (ctx) => `contract:${ctx.contractId}`,
274
- timeout: '72h',
275
- onApproveEvent: 'CONTRACT_APPROVED',
276
- onRejectEvent: 'CONTRACT_REJECTED',
277
- callbackBaseUrl: 'https://api.acme.com/siglo/callback',
278
- signingSecret: process.env.APPROVAL_SECRET!,
279
- autoCompensate: true
291
+ channel: 'email',
292
+ recipient: ctx => ({ email: ctx.legalReviewerEmail }),
293
+ title: ctx => `Contract Review Required: ${ctx.contractTitle}`,
294
+ description: ctx => `Value: $${ctx.contractValue}`,
295
+ correlationKey: ctx => `contract:${ctx.contractId}`,
296
+ timeout: '72h',
297
+ onApproveEvent: 'CONTRACT_APPROVED',
298
+ onRejectEvent: 'CONTRACT_REJECTED',
299
+ callbackBaseUrl: 'https://api.acme.com/siglo/callback',
300
+ signingSecret: process.env.APPROVAL_SECRET!,
301
+ autoCompensate: true,
280
302
  });
281
303
  ```
282
304
 
@@ -289,6 +311,7 @@ Action tokens embed callback metadata in a compact URL-safe format:
289
311
  $$\text{Token} = \text{base64url}(\text{Payload}) \,\|\, \text{base64url}(\text{HMAC-SHA256}(\text{Payload}, \text{Secret}))$$
290
312
 
291
313
  ### Features:
314
+
292
315
  - **No Database Lookup on Verification**: Validates authenticity and expiration instantly before accessing storage.
293
316
  - **Constant-Time Verification**: Uses `@siglo/crypto`'s `timingSafeCompare` to defeat timing attacks.
294
317
  - **Replay handling**: Durable claims reject completed requests. `toleranceSeconds` checks future issuance only; nonces are not independently consumed.
@@ -299,13 +322,13 @@ import { StaticKeyRing } from '@siglo/crypto';
299
322
  import { signActionToken, verifyActionToken } from '@siglo/notifications';
300
323
 
301
324
  const keyRing = new StaticKeyRing('v2', {
302
- v2: 'current-secret-key-2026',
303
- v1: 'legacy-secret-key-2025'
325
+ v2: 'current-secret-key-2026',
326
+ v1: 'legacy-secret-key-2025',
304
327
  });
305
328
 
306
329
  // Verify token
307
330
  const payload = await verifyActionToken(tokenString, keyRing, {
308
- toleranceSeconds: 60 // Allow 60s future clock skew
331
+ toleranceSeconds: 60, // Allow 60s future clock skew
309
332
  });
310
333
  ```
311
334
 
@@ -316,6 +339,7 @@ const payload = await verifyActionToken(tokenString, keyRing, {
316
339
  First-class route handlers are provided for `@siglo/express`, `@siglo/fastify`, and `@siglo/hono` with built-in security headers, CORS preflight handling, and response customization:
317
340
 
318
341
  ### Supported Security Headers
342
+
319
343
  - `Cache-Control: no-store`
320
344
  - `Referrer-Policy: no-referrer`
321
345
  - `X-Content-Type-Options: nosniff`
@@ -331,17 +355,17 @@ const app = express();
331
355
  app.use(express.urlencoded({ extended: false }));
332
356
 
333
357
  app.all(
334
- '/api/siglo/callback',
335
- createNotificationExpressMiddleware({
336
- workflow: orderFlow,
337
- signingSecret: process.env.APPROVAL_SECRET!,
338
- authorize: authorizeApproval, // Application identity and CSRF check; see migration guide.
339
- responseFormat: 'html', // Renders accessible confirmation page
340
- allowedOrigins: ['https://orchestrator.acme.com', 'https://dashboard.acme.com'],
341
- onSuccessRedirect: 'https://dashboard.acme.com/approvals/success',
342
- onExpiredRedirect: 'https://dashboard.acme.com/approvals/expired',
343
- onErrorRedirect: 'https://dashboard.acme.com/approvals/error'
344
- })
358
+ '/api/siglo/callback',
359
+ createNotificationExpressMiddleware({
360
+ workflow: orderFlow,
361
+ signingSecret: process.env.APPROVAL_SECRET!,
362
+ authorize: authorizeApproval, // Application identity and CSRF check; see migration guide.
363
+ responseFormat: 'html', // Renders accessible confirmation page
364
+ allowedOrigins: ['https://orchestrator.acme.com', 'https://dashboard.acme.com'],
365
+ onSuccessRedirect: 'https://dashboard.acme.com/approvals/success',
366
+ onExpiredRedirect: 'https://dashboard.acme.com/approvals/expired',
367
+ onErrorRedirect: 'https://dashboard.acme.com/approvals/error',
368
+ }),
345
369
  );
346
370
  ```
347
371
 
@@ -353,9 +377,9 @@ import { createNotificationFastifyHandler } from '@siglo/notifications';
353
377
 
354
378
  const fastify = Fastify();
355
379
  const handler = createNotificationFastifyHandler({
356
- workflow: orderFlow,
357
- signingSecret: process.env.APPROVAL_SECRET!,
358
- authorize: authorizeApproval // Application authentication and CSRF check.
380
+ workflow: orderFlow,
381
+ signingSecret: process.env.APPROVAL_SECRET!,
382
+ authorize: authorizeApproval, // Application authentication and CSRF check.
359
383
  });
360
384
  fastify.route({ method: ['GET', 'POST'], url: '/api/siglo/callback', handler });
361
385
  ```
@@ -367,11 +391,14 @@ import { Hono } from 'hono';
367
391
  import { createNotificationHonoHandler } from '@siglo/notifications';
368
392
 
369
393
  const app = new Hono();
370
- app.all('/api/siglo/callback', createNotificationHonoHandler({
371
- workflow: orderFlow,
372
- signingSecret: process.env.APPROVAL_SECRET!,
373
- authorize: authorizeApproval
374
- }));
394
+ app.all(
395
+ '/api/siglo/callback',
396
+ createNotificationHonoHandler({
397
+ workflow: orderFlow,
398
+ signingSecret: process.env.APPROVAL_SECRET!,
399
+ authorize: authorizeApproval,
400
+ }),
401
+ );
375
402
  ```
376
403
 
377
404
  ---
@@ -384,19 +411,19 @@ Parse and cryptographically verify inbound SMS approval webhooks (`APPROVE <ref>
384
411
  import { parseTwilioSmsReply } from '@siglo/notifications';
385
412
 
386
413
  app.post('/api/twilio/sms', express.urlencoded({ extended: false }), async (req, res) => {
387
- const reply = parseTwilioSmsReply(req.body, {
388
- publicUrl: 'https://api.acme.com/api/twilio/sms',
389
- authToken: process.env.TWILIO_AUTH_TOKEN!,
390
- signature: req.headers['x-twilio-signature'] as string
391
- });
392
-
393
- // reply: { approved: true, reference: 'deploy:123', from: '+15550001', messageId: 'SM...' }
394
- // Validate a persisted, unpredictable challenge and expected sender first.
395
- // Atomically consume the pending request and deduplicate MessageSid in your
396
- // application approval service. See the security migration guide.
397
- await approvalService.acceptVerifiedSmsReply(reply);
398
-
399
- res.type('text/xml').send('<Response></Response>');
414
+ const reply = parseTwilioSmsReply(req.body, {
415
+ publicUrl: 'https://api.acme.com/api/twilio/sms',
416
+ authToken: process.env.TWILIO_AUTH_TOKEN!,
417
+ signature: req.headers['x-twilio-signature'] as string,
418
+ });
419
+
420
+ // reply: { approved: true, reference: 'deploy:123', from: '+15550001', messageId: 'SM...' }
421
+ // Validate a persisted, unpredictable challenge and expected sender first.
422
+ // Atomically consume the pending request and deduplicate MessageSid in your
423
+ // application approval service. See the security migration guide.
424
+ await approvalService.acceptVerifiedSmsReply(reply);
425
+
426
+ res.type('text/xml').send('<Response></Response>');
400
427
  });
401
428
  ```
402
429
 
@@ -405,6 +432,7 @@ app.post('/api/twilio/sms', express.urlencoded({ extended: false }), async (req,
405
432
  ## 9. Saga Compensation & Shared Revocations
406
433
 
407
434
  When a downstream step fails or a workflow times out, Siglo triggers Named Saga Compensation (`cancelNotification`):
435
+
408
436
  1. **Chat Channels (Slack)**: Calls `chat.update` to replace interactive buttons with an alert (e.g. `"Workflow Cancelled"`).
409
437
  2. **Email & SMS**: Records the `correlationKey` into the revocation store so any future clicks on existing email links return `409 Conflict`.
410
438
 
@@ -427,12 +455,9 @@ Standard recipient identifiers, credentials, and tokens are automatically redact
427
455
  ```typescript
428
456
  import { NotificationMonitor } from '@siglo/notifications';
429
457
 
430
- const monitor = new NotificationMonitor([
431
- 'outputSummary.customers.*.contact',
432
- 'order.shippingAddress.phone'
433
- ]);
458
+ const monitor = new NotificationMonitor(['outputSummary.customers.*.contact', 'order.shippingAddress.phone']);
434
459
 
435
- workflow.execute(input, { monitor });
460
+ workflow.run(input, { monitor });
436
461
  ```
437
462
 
438
463
  ---
@@ -447,15 +472,15 @@ import { sendNotificationStep } from '@siglo/notifications';
447
472
 
448
473
  const mock = new MockNotificationTransport();
449
474
  const step = sendNotificationStep('notify', {
450
- channel: 'email',
451
- recipient: 'user@example.com',
452
- template: 'Hello world',
453
- transport: mock
475
+ channel: 'email',
476
+ recipient: 'user@example.com',
477
+ template: 'Hello world',
478
+ transport: mock,
454
479
  });
455
480
 
456
481
  await step.execute({});
457
482
  console.log(mock.messages.length); // 1
458
- console.log(mock.messages[0].to); // 'user@example.com'
483
+ console.log(mock.messages[0].to); // 'user@example.com'
459
484
  ```
460
485
 
461
486
  ### Running Test Suites
@@ -1 +1 @@
1
- {"version":3,"file":"approvals.d.ts","sourceRoot":"","sources":["../src/approvals.ts"],"names":[],"mappings":"AAEA,uFAAuF;AACvF,MAAM,WAAW,uBAAuB;IACtC,MAAM,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,SAAS,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACpD,gBAAgB,CAAC,CAAC,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CACnF;AACD,qBAAa,+BAAgC,YAAW,uBAAuB;IAC7E,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,KAAK,CAA6B;IAC1C,OAAO,CAAC,KAAK,CAAgD;IACvD,gBAAgB,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAQtE,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAClC,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAC/C;AAED,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,uBAAuB,GAAG,IAAI,CAAmB;AACzG,wBAAgB,0BAA0B,IAAI,uBAAuB,CAAkB;AACvF,UAAU,UAAU;IAClB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,GAAG,EAAE,CAAA;KAAE,CAAC,CAAC;IAC7D,OAAO,CAAC,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;CAC/B;AACD,UAAU,MAAO,SAAQ,UAAU;IAAG,OAAO,CAAC,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAA;CAAE;AAC9E,kGAAkG;AAClG,qBAAa,+BAAgC,YAAW,uBAAuB;IAGjE,OAAO,CAAC,MAAM;IAF1B,OAAO,CAAC,KAAK,CAAiF;IAC9F,OAAO,CAAC,gBAAgB,CAAS;gBACb,MAAM,EAAE,MAAM;IAC5B,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAG3B,gBAAgB,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAsBtE,MAAM,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAa7C,SAAS,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAI1D"}
1
+ {"version":3,"file":"approvals.d.ts","sourceRoot":"","sources":["../src/approvals.ts"],"names":[],"mappings":"AAEA,uFAAuF;AACvF,MAAM,WAAW,uBAAuB;IACpC,MAAM,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,SAAS,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACpD,gBAAgB,CAAC,CAAC,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CACrF;AACD,qBAAa,+BAAgC,YAAW,uBAAuB;IAC3E,OAAO,CAAC,OAAO,CAAqB;IACpC,OAAO,CAAC,KAAK,CAA6B;IAC1C,OAAO,CAAC,KAAK,CAAgD;IACvD,gBAAgB,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAWtE,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOlC,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAGjD;AAED,wBAAgB,gCAAgC,CAAC,KAAK,EAAE,uBAAuB,GAAG,IAAI,CAErF;AACD,wBAAgB,0BAA0B,IAAI,uBAAuB,CAEpE;AACD,UAAU,UAAU;IAChB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,GAAG,EAAE,CAAA;KAAE,CAAC,CAAC;IAC7D,OAAO,CAAC,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;CACjC;AACD,UAAU,MAAO,SAAQ,UAAU;IAC/B,OAAO,CAAC,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;CAC1C;AACD,kGAAkG;AAClG,qBAAa,+BAAgC,YAAW,uBAAuB;IAG/D,OAAO,CAAC,MAAM;IAF1B,OAAO,CAAC,KAAK,CAAiF;IAC9F,OAAO,CAAC,gBAAgB,CAAS;gBACb,MAAM,EAAE,MAAM;IAC5B,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAK3B,gBAAgB,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAuCtE,MAAM,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkB7C,SAAS,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAO5D"}
package/dist/approvals.js CHANGED
@@ -23,14 +23,26 @@ class InMemoryApprovalRevocationStore {
23
23
  this.locks.delete(key);
24
24
  }
25
25
  }
26
- async revoke(key) { await this.withApprovalLock(key, async () => { this.revoked.add(key); const waiting = core_1.defaultDurableManager.getWaiting(key); if (waiting)
27
- waiting.status = 'failed'; }); }
28
- async isRevoked(key) { return this.revoked.has(key); }
26
+ async revoke(key) {
27
+ await this.withApprovalLock(key, async () => {
28
+ this.revoked.add(key);
29
+ const waiting = core_1.defaultDurableManager.getWaiting(key);
30
+ if (waiting)
31
+ waiting.status = 'failed';
32
+ });
33
+ }
34
+ async isRevoked(key) {
35
+ return this.revoked.has(key);
36
+ }
29
37
  }
30
38
  exports.InMemoryApprovalRevocationStore = InMemoryApprovalRevocationStore;
31
39
  let store = new InMemoryApprovalRevocationStore();
32
- function configureApprovalRevocationStore(value) { store = value; }
33
- function getApprovalRevocationStore() { return store; }
40
+ function configureApprovalRevocationStore(value) {
41
+ store = value;
42
+ }
43
+ function getApprovalRevocationStore() {
44
+ return store;
45
+ }
34
46
  /** Use a Pool in multi-worker deployments; locks hold a dedicated connection until completion. */
35
47
  class PostgresApprovalRevocationStore {
36
48
  client;
@@ -54,8 +66,10 @@ class PostgresApprovalRevocationStore {
54
66
  let connection;
55
67
  let locked = false;
56
68
  try {
57
- connection = pooled ? await this.client.connect() : this.client;
58
- const result = await connection.query('SELECT pg_try_advisory_lock(hashtextextended($1, 0)) AS locked', [`siglo:approval:${key}`]);
69
+ connection = pooled ? (await this.client.connect()) : this.client;
70
+ const result = await connection.query('SELECT pg_try_advisory_lock(hashtextextended($1, 0)) AS locked', [
71
+ `siglo:approval:${key}`,
72
+ ]);
59
73
  locked = result.rows[0]?.locked === true;
60
74
  if (!locked)
61
75
  throw new core_1.DuplicateEventException(key);
@@ -70,7 +84,9 @@ class PostgresApprovalRevocationStore {
70
84
  finally {
71
85
  try {
72
86
  if (locked)
73
- await connection.query('SELECT pg_advisory_unlock(hashtextextended($1, 0))', [`siglo:approval:${key}`]);
87
+ await connection.query('SELECT pg_advisory_unlock(hashtextextended($1, 0))', [
88
+ `siglo:approval:${key}`,
89
+ ]);
74
90
  }
75
91
  catch (error) {
76
92
  if (pooled) {
@@ -94,7 +110,9 @@ class PostgresApprovalRevocationStore {
94
110
  const cancel = async () => {
95
111
  // Cancel recovery first: a crash before the revocation INSERT must fail closed.
96
112
  await adapter?.cancelWaitRecord?.(correlationKey);
97
- await this.scope.getStore().client.query('INSERT INTO siglo_approval_revocations (correlation_key) VALUES ($1) ON CONFLICT (correlation_key) DO NOTHING', [correlationKey]);
113
+ await this.scope
114
+ .getStore()
115
+ .client.query('INSERT INTO siglo_approval_revocations (correlation_key) VALUES ($1) ON CONFLICT (correlation_key) DO NOTHING', [correlationKey]);
98
116
  };
99
117
  if (record && adapter?.withWorkflowLock)
100
118
  await adapter.withWorkflowLock(record.stackId, cancel);
@@ -1 +1 @@
1
- {"version":3,"file":"approvals.js","sourceRoot":"","sources":["../src/approvals.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"approvals.js","sourceRoot":"","sources":["../src/approvals.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"callbacks.d.ts","sourceRoot":"","sources":["../src/callbacks.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAGjD,MAAM,WAAW,4BAA4B;IAC3C,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AACD,wBAAsB,0BAA0B,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,sBAAsB,GAAG,OAAO,CAAC,4BAA4B,CAAC,CA+BtI;AACD,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,4BAA4B,GAAG,MAAM,CAEvF;AAwBD,wBAAgB,mCAAmC,CAAC,OAAO,EAAE,sBAAsB,SAC9D,GAAG,OAAO,GAAG,KAAG,OAAO,CAAC,IAAI,CAAC,CAUjD;AACD,wBAAgB,gCAAgC,CAAC,OAAO,EAAE,sBAAsB,SAC3D,GAAG,SAAS,GAAG,KAAG,OAAO,CAAC,IAAI,CAAC,CAUnD;AACD,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,sBAAsB,OAC1D,GAAG,KAAG,OAAO,CAAC,QAAQ,CAAC,CASzC"}
1
+ {"version":3,"file":"callbacks.d.ts","sourceRoot":"","sources":["../src/callbacks.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC;AAGjD,MAAM,WAAW,4BAA4B;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AACD,wBAAsB,0BAA0B,CAC5C,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,sBAAsB,GAChC,OAAO,CAAC,4BAA4B,CAAC,CAoEvC;AACD,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,4BAA4B,GAAG,MAAM,CAEvF;AAqDD,wBAAgB,mCAAmC,CAAC,OAAO,EAAE,sBAAsB,SAC5D,GAAG,OAAO,GAAG,KAAG,OAAO,CAAC,IAAI,CAAC,CAmBnD;AACD,wBAAgB,gCAAgC,CAAC,OAAO,EAAE,sBAAsB,SACzD,GAAG,SAAS,GAAG,KAAG,OAAO,CAAC,IAAI,CAAC,CAoBrD;AACD,wBAAgB,6BAA6B,CAAC,OAAO,EAAE,sBAAsB,OACxD,GAAG,KAAG,OAAO,CAAC,QAAQ,CAAC,CAkB3C"}