@cat-factory/integrations 0.143.1 → 0.144.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.
Files changed (24) hide show
  1. package/dist/modules/notificationWebhook/NotificationWebhookService.d.ts +9 -7
  2. package/dist/modules/notificationWebhook/NotificationWebhookService.d.ts.map +1 -1
  3. package/dist/modules/notificationWebhook/NotificationWebhookService.js +57 -12
  4. package/dist/modules/notificationWebhook/NotificationWebhookService.js.map +1 -1
  5. package/dist/modules/notificationWebhook/WebhookNotificationChannel.d.ts +2 -0
  6. package/dist/modules/notificationWebhook/WebhookNotificationChannel.d.ts.map +1 -1
  7. package/dist/modules/notificationWebhook/WebhookNotificationChannel.js +29 -22
  8. package/dist/modules/notificationWebhook/WebhookNotificationChannel.js.map +1 -1
  9. package/dist/modules/notificationWebhook/WebhookPlatformAlertSink.d.ts +1 -0
  10. package/dist/modules/notificationWebhook/WebhookPlatformAlertSink.d.ts.map +1 -1
  11. package/dist/modules/notificationWebhook/WebhookPlatformAlertSink.js +10 -11
  12. package/dist/modules/notificationWebhook/WebhookPlatformAlertSink.js.map +1 -1
  13. package/dist/modules/notificationWebhook/WebhookRunLifecycleSink.d.ts +1 -0
  14. package/dist/modules/notificationWebhook/WebhookRunLifecycleSink.d.ts.map +1 -1
  15. package/dist/modules/notificationWebhook/WebhookRunLifecycleSink.js +12 -11
  16. package/dist/modules/notificationWebhook/WebhookRunLifecycleSink.js.map +1 -1
  17. package/dist/modules/notificationWebhook/signedDelivery.d.ts +56 -0
  18. package/dist/modules/notificationWebhook/signedDelivery.d.ts.map +1 -1
  19. package/dist/modules/notificationWebhook/signedDelivery.js +114 -12
  20. package/dist/modules/notificationWebhook/signedDelivery.js.map +1 -1
  21. package/dist/modules/notificationWebhook/support.d.ts +3 -0
  22. package/dist/modules/notificationWebhook/support.d.ts.map +1 -1
  23. package/dist/modules/notificationWebhook/support.js.map +1 -1
  24. package/package.json +4 -4
@@ -1,4 +1,4 @@
1
- import type { NotificationWebhook, PutNotificationWebhookInput } from '@cat-factory/contracts';
1
+ import { type NotificationWebhook, type PutNotificationWebhookInput } from '@cat-factory/contracts';
2
2
  import type { Clock, NotificationWebhookRepository, SecretCipher, UrlSafetyPolicy } from '@cat-factory/kernel';
3
3
  export interface NotificationWebhookServiceDependencies {
4
4
  notificationWebhookRepository: NotificationWebhookRepository;
@@ -15,11 +15,13 @@ export interface NotificationWebhookServiceDependencies {
15
15
  export declare class NotificationWebhookService {
16
16
  private readonly deps;
17
17
  constructor(deps: NotificationWebhookServiceDependencies);
18
- /** The workspace's webhook as exposed to clients, or null when none is registered. */
19
- get(workspaceId: string): Promise<NotificationWebhook | null>;
20
- /** Register or update the workspace's webhook. */
21
- put(workspaceId: string, input: PutNotificationWebhookInput): Promise<NotificationWebhook>;
22
- /** Remove the workspace's webhook. Idempotent. */
23
- remove(workspaceId: string): Promise<void>;
18
+ /** One endpoint as exposed to clients, or null when nothing is registered under that id. */
19
+ get(workspaceId: string, id: string): Promise<NotificationWebhook | null>;
20
+ /** Every endpoint the workspace has registered, ordered by id. */
21
+ list(workspaceId: string): Promise<NotificationWebhook[]>;
22
+ /** Register or update one endpoint. */
23
+ put(workspaceId: string, id: string, input: PutNotificationWebhookInput): Promise<NotificationWebhook>;
24
+ /** Remove one endpoint. Idempotent, and never touches a sibling. */
25
+ remove(workspaceId: string, id: string): Promise<void>;
24
26
  }
25
27
  //# sourceMappingURL=NotificationWebhookService.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"NotificationWebhookService.d.ts","sourceRoot":"","sources":["../../../src/modules/notificationWebhook/NotificationWebhookService.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAA;AAC9F,OAAO,KAAK,EACV,KAAK,EAEL,6BAA6B,EAC7B,YAAY,EACZ,eAAe,EAChB,MAAM,qBAAqB,CAAA;AAmB5B,MAAM,WAAW,sCAAsC;IACrD,6BAA6B,EAAE,6BAA6B,CAAA;IAC5D,YAAY,EAAE,YAAY,CAAA;IAC1B,KAAK,EAAE,KAAK,CAAA;IACZ;;;;;OAKG;IACH,eAAe,CAAC,EAAE,eAAe,CAAA;CAClC;AAED,qBAAa,0BAA0B;IACzB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAjC,YAA6B,IAAI,EAAE,sCAAsC,EAAI;IAE7E,sFAAsF;IAChF,GAAG,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAGlE;IAED,kDAAkD;IAC5C,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,2BAA2B,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA6C/F;IAED,kDAAkD;IAC5C,MAAM,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE/C;CACF"}
1
+ {"version":3,"file":"NotificationWebhookService.d.ts","sourceRoot":"","sources":["../../../src/modules/notificationWebhook/NotificationWebhookService.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,mBAAmB,EAExB,KAAK,2BAA2B,EACjC,MAAM,wBAAwB,CAAA;AAC/B,OAAO,KAAK,EACV,KAAK,EAEL,6BAA6B,EAC7B,YAAY,EACZ,eAAe,EAChB,MAAM,qBAAqB,CAAA;AAwB5B,MAAM,WAAW,sCAAsC;IACrD,6BAA6B,EAAE,6BAA6B,CAAA;IAC5D,YAAY,EAAE,YAAY,CAAA;IAC1B,KAAK,EAAE,KAAK,CAAA;IACZ;;;;;OAKG;IACH,eAAe,CAAC,EAAE,eAAe,CAAA;CAClC;AAED,qBAAa,0BAA0B;IACzB,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAjC,YAA6B,IAAI,EAAE,sCAAsC,EAAI;IAE7E,4FAA4F;IACtF,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC,CAG9E;IAED,kEAAkE;IAC5D,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAG9D;IAED,uCAAuC;IACjC,GAAG,CACP,WAAW,EAAE,MAAM,EACnB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,2BAA2B,GACjC,OAAO,CAAC,mBAAmB,CAAC,CA0E9B;IAED,oEAAoE;IAC9D,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAE3D;CACF"}
@@ -1,17 +1,29 @@
1
- import { ValidationError } from '@cat-factory/kernel';
1
+ import { MAX_NOTIFICATION_WEBHOOKS_PER_WORKSPACE, notificationWebhookIdSchema, } from '@cat-factory/contracts';
2
+ import { ConflictError, ValidationError } from '@cat-factory/kernel';
3
+ import * as v from 'valibot';
2
4
  import { assertSafeNotificationWebhookUrl } from './webhookUrl.js';
3
5
  export class NotificationWebhookService {
4
6
  deps;
5
7
  constructor(deps) {
6
8
  this.deps = deps;
7
9
  }
8
- /** The workspace's webhook as exposed to clients, or null when none is registered. */
9
- async get(workspaceId) {
10
- const record = await this.deps.notificationWebhookRepository.get(workspaceId);
10
+ /** One endpoint as exposed to clients, or null when nothing is registered under that id. */
11
+ async get(workspaceId, id) {
12
+ const record = await this.deps.notificationWebhookRepository.get(workspaceId, id);
11
13
  return record ? toWire(record) : null;
12
14
  }
13
- /** Register or update the workspace's webhook. */
14
- async put(workspaceId, input) {
15
+ /** Every endpoint the workspace has registered, ordered by id. */
16
+ async list(workspaceId) {
17
+ const records = await this.deps.notificationWebhookRepository.list(workspaceId);
18
+ return records.map(toWire);
19
+ }
20
+ /** Register or update one endpoint. */
21
+ async put(workspaceId, id, input) {
22
+ // Validated HERE rather than in the path-param schema, so the two management surfaces and any
23
+ // later caller share one rule and one machine-readable `reason`. A malformed id on a READ is
24
+ // left alone: it simply matches nothing, and answering "no such endpoint" is both true and
25
+ // the answer the caller was going to act on anyway.
26
+ assertValidWebhookId(id);
15
27
  // Reject a private/internal/metadata endpoint HERE, where an operator sees the error, rather
16
28
  // than leaving it to fail per-delivery later. The wire schema's `https://` prefix check is the
17
29
  // friendly first pass; this is the guard that actually holds (and the same one the delivery
@@ -26,15 +38,25 @@ export class NotificationWebhookService {
26
38
  if (input.url !== undefined) {
27
39
  assertSafeNotificationWebhookUrl(input.url, this.deps.urlSafetyPolicy);
28
40
  }
29
- const existing = await this.deps.notificationWebhookRepository.get(workspaceId);
41
+ // Read for the keep-on-omit merge ONLY. The cap is not decided here: a count read now and
42
+ // acted on a statement later binds nothing, because two enrolments racing each other would
43
+ // both see room. `put` takes the limit and admits or refuses under it atomically, which is the
44
+ // only place the two can be one step. This read can therefore be stale about the count without
45
+ // costing anything, which it always could have been.
46
+ const existing = await this.deps.notificationWebhookRepository.get(workspaceId, id);
30
47
  // Keep-on-omit needs something to keep. Refusing here is what keeps the rule uniform across
31
48
  // every field without letting a body that names no endpoint store a half-registered row.
32
49
  const url = input.url ?? existing?.url;
33
50
  if (url === undefined) {
34
- throw new ValidationError('No webhook is registered for this workspace, so `url` is required to register one', { reason: 'webhook_url_required' });
51
+ throw new ValidationError(`No webhook is registered under \`${id}\` in this workspace, so \`url\` is required to register one`, { reason: 'webhook_url_required' });
35
52
  }
36
53
  const record = {
37
54
  workspaceId,
55
+ id,
56
+ // A registration that names no label gets the id, which is the only value here that is
57
+ // already meaningful to whoever chose it. Defaulting to the URL would put a receiver's
58
+ // address in every operator-facing list, and defaulting to a blank renders as a gap.
59
+ name: input.name ?? existing?.name ?? id,
38
60
  url,
39
61
  types: input.types ?? existing?.types ?? [],
40
62
  // Omitted `runEvents` KEEPS the current subscription, like every other field here. The
@@ -51,17 +73,40 @@ export class NotificationWebhookService {
51
73
  : (existing?.secretSealed ?? null),
52
74
  updatedAt: this.deps.clock.now(),
53
75
  };
54
- await this.deps.notificationWebhookRepository.put(record);
76
+ // The cap bounds only what CREATES an endpoint: replacing one that already exists is admitted
77
+ // even on a workspace at (or, after a lowered cap, over) the limit, because disabling and
78
+ // deleting are exactly the edits an operator makes to get back under it. The store decides
79
+ // that under its own lock and reports which happened; this layer only chooses the status.
80
+ const outcome = await this.deps.notificationWebhookRepository.put(record, MAX_NOTIFICATION_WEBHOOKS_PER_WORKSPACE);
81
+ if (outcome === 'limit_reached') {
82
+ throw new ConflictError(`This workspace already has ${MAX_NOTIFICATION_WEBHOOKS_PER_WORKSPACE} notification webhooks registered`, 'webhook_limit_reached', { limit: MAX_NOTIFICATION_WEBHOOKS_PER_WORKSPACE });
83
+ }
55
84
  return toWire(record);
56
85
  }
57
- /** Remove the workspace's webhook. Idempotent. */
58
- async remove(workspaceId) {
59
- await this.deps.notificationWebhookRepository.delete(workspaceId);
86
+ /** Remove one endpoint. Idempotent, and never touches a sibling. */
87
+ async remove(workspaceId, id) {
88
+ await this.deps.notificationWebhookRepository.delete(workspaceId, id);
89
+ }
90
+ }
91
+ /**
92
+ * Refuse an id that is not a lowercase slug. The id is a path segment on both management surfaces
93
+ * and an operator reads it beside the endpoint's URL, so the shape is part of the contract rather
94
+ * than a storage detail. Derived from the contracts' own schema, so the rule the API documents and
95
+ * the rule the service enforces cannot drift apart.
96
+ */
97
+ function assertValidWebhookId(id) {
98
+ const parsed = v.safeParse(notificationWebhookIdSchema, id);
99
+ if (!parsed.success) {
100
+ throw new ValidationError(parsed.issues[0]?.message ?? 'Invalid webhook id', {
101
+ reason: 'invalid_webhook_id',
102
+ });
60
103
  }
61
104
  }
62
105
  /** Project the persisted record onto the wire shape — the sealed secret becomes a boolean. */
63
106
  function toWire(record) {
64
107
  return {
108
+ id: record.id,
109
+ name: record.name,
65
110
  url: record.url,
66
111
  types: record.types,
67
112
  runEvents: record.runEvents,
@@ -1 +1 @@
1
- {"version":3,"file":"NotificationWebhookService.js","sourceRoot":"","sources":["../../../src/modules/notificationWebhook/NotificationWebhookService.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"NotificationWebhookService.js","sourceRoot":"","sources":["../../../src/modules/notificationWebhook/NotificationWebhookService.ts"],"names":[],"mappings":"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"}
@@ -25,6 +25,7 @@ export interface WebhookNotificationChannelDependencies {
25
25
  workspaceId: string;
26
26
  notificationId: string;
27
27
  type: string;
28
+ webhookId?: string;
28
29
  }) => void;
29
30
  /**
30
31
  * Where a spent delivery is COUNTED, beside the per-failure report `onError` makes. The
@@ -39,6 +40,7 @@ export declare class WebhookNotificationChannel implements NotificationChannel {
39
40
  constructor(deps: WebhookNotificationChannelDependencies);
40
41
  deliver(workspaceId: string, notification: Notification): Promise<void>;
41
42
  private post;
43
+ private reportFailure;
42
44
  }
43
45
  export { WEBHOOK_SIGNATURE_HEADERS };
44
46
  //# sourceMappingURL=WebhookNotificationChannel.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"WebhookNotificationChannel.d.ts","sourceRoot":"","sources":["../../../src/modules/notificationWebhook/WebhookNotificationChannel.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,KAAK,EACL,YAAY,EACZ,mBAAmB,EAGnB,6BAA6B,EAC7B,kBAAkB,EAClB,YAAY,EACZ,eAAe,EAChB,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAA;AAoBjE,MAAM,WAAW,sCAAsC;IACrD,6BAA6B,EAAE,6BAA6B,CAAA;IAC5D,YAAY,EAAE,YAAY,CAAA;IAC1B,KAAK,EAAE,KAAK,CAAA;IACZ,oFAAoF;IACpF,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;IACxB,yFAAyF;IACzF,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC;;;;;OAKG;IACH,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,CACR,KAAK,EAAE,OAAO,EACd,OAAO,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,KACnE,IAAI,CAAA;IACT;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,kBAAkB,CAAA;CACxC;AAED,qBAAa,0BAA2B,YAAW,mBAAmB;IACxD,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAjC,YAA6B,IAAI,EAAE,sCAAsC,EAAI;IAEvE,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAoB5E;YAEa,IAAI;CAuBnB;AAcD,OAAO,EAAE,yBAAyB,EAAE,CAAA"}
1
+ {"version":3,"file":"WebhookNotificationChannel.d.ts","sourceRoot":"","sources":["../../../src/modules/notificationWebhook/WebhookNotificationChannel.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EACV,KAAK,EACL,YAAY,EACZ,mBAAmB,EAGnB,6BAA6B,EAC7B,kBAAkB,EAClB,YAAY,EACZ,eAAe,EAChB,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAA;AAqBjE,MAAM,WAAW,sCAAsC;IACrD,6BAA6B,EAAE,6BAA6B,CAAA;IAC5D,YAAY,EAAE,YAAY,CAAA;IAC1B,KAAK,EAAE,KAAK,CAAA;IACZ,oFAAoF;IACpF,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;IACxB,yFAAyF;IACzF,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC;;;;;OAKG;IACH,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,CACR,KAAK,EAAE,OAAO,EACd,OAAO,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,KACvF,IAAI,CAAA;IACT;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,kBAAkB,CAAA;CACxC;AAED,qBAAa,0BAA2B,YAAW,mBAAmB;IACxD,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAjC,YAA6B,IAAI,EAAE,sCAAsC,EAAI;IAEvE,OAAO,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAa5E;YAEa,IAAI;IA8BlB,OAAO,CAAC,aAAa;CAqBtB;AAcD,OAAO,EAAE,yBAAyB,EAAE,CAAA"}
@@ -1,5 +1,5 @@
1
1
  import { DEFAULT_NOTIFICATION_WEBHOOK_TYPES, } from '@cat-factory/contracts';
2
- import { postSignedWebhook } from './signedDelivery.js';
2
+ import { fanOutSignedWebhook } from './signedDelivery.js';
3
3
  import { WEBHOOK_SIGNATURE_HEADERS } from './webhookSignature.js';
4
4
  export class WebhookNotificationChannel {
5
5
  deps;
@@ -14,30 +14,26 @@ export class WebhookNotificationChannel {
14
14
  // Best-effort: never let a receiver outage/misconfig break the notification lifecycle
15
15
  // (CompositeNotificationChannel also isolates us, belt-and-braces). Surface it through the
16
16
  // optional observability hook so the failure is diagnosable instead of silently dropped.
17
- this.deps.onError?.(error, {
18
- workspaceId,
19
- notificationId: notification.id,
20
- type: notification.type,
21
- });
22
- // The notification TYPE is a bounded enum, so it is safe as a dimension and is the one
23
- // split worth having: an endpoint that only fails on a particular card is a receiver
24
- // bug, where a flat failure across types is an outage.
25
- this.deps.operationalMetrics?.increment('notification.delivery_failed', {
26
- channel: 'webhook',
27
- type: notification.type,
28
- });
17
+ //
18
+ // With the fan-out below reporting each endpoint's own failure, what reaches HERE is the
19
+ // read or the compose failing — a fault of the workspace's configuration rather than of any
20
+ // one receiver, which is why this report names no `webhookId`.
21
+ this.reportFailure(error, workspaceId, notification);
29
22
  }
30
23
  }
31
24
  async post(workspaceId, notification) {
32
- const webhook = await this.deps.notificationWebhookRepository.get(workspaceId);
33
- if (!webhook || !webhook.enabled)
34
- return;
35
- if (!deliversType(webhook, notification.type))
25
+ const endpoints = (await this.deps.notificationWebhookRepository.list(workspaceId)).filter((webhook) => webhook.enabled && deliversType(webhook, notification.type));
26
+ if (endpoints.length === 0)
36
27
  return;
37
28
  const body = {
38
29
  // Stable per notification-and-status: a retried attempt repeats it, so a receiver dedupes on
39
30
  // it. The status suffix keeps the delivery of a RESOLVED card (channels are re-delivered on
40
31
  // resolve) distinct from the original open one, which is a genuinely different event.
32
+ //
33
+ // Deliberately NOT scoped by endpoint: each receiver only ever sees its own copy, so an
34
+ // endpoint segment would put a value in the dedupe key that no receiver can act on, and
35
+ // would break the one case where two subscriptions DO collapse correctly (the same URL
36
+ // registered twice, which should deliver one card once).
41
37
  deliveryId: `${notification.id}-${notification.status}`,
42
38
  sentAt: this.deps.clock.now(),
43
39
  workspaceId,
@@ -45,11 +41,22 @@ export class WebhookNotificationChannel {
45
41
  taskId: notification.blockId,
46
42
  notification,
47
43
  };
48
- await postSignedWebhook(this.deps, {
49
- url: webhook.url,
50
- secretSealed: webhook.secretSealed,
51
- payload: JSON.stringify(body),
52
- sentAt: body.sentAt,
44
+ await fanOutSignedWebhook(this.deps, endpoints, { payload: JSON.stringify(body), sentAt: body.sentAt }, (error, target) => this.reportFailure(error, workspaceId, notification, target.id));
45
+ }
46
+ reportFailure(error, workspaceId, notification, webhookId) {
47
+ this.deps.onError?.(error, {
48
+ workspaceId,
49
+ notificationId: notification.id,
50
+ type: notification.type,
51
+ ...(webhookId === undefined ? {} : { webhookId }),
52
+ });
53
+ // The notification TYPE is a bounded enum, so it is safe as a dimension and is the one
54
+ // split worth having: an endpoint that only fails on a particular card is a receiver
55
+ // bug, where a flat failure across types is an outage. The webhook ID is deliberately NOT a
56
+ // dimension: it is operator-chosen, so every workspace's naming would mint its own series.
57
+ this.deps.operationalMetrics?.increment('notification.delivery_failed', {
58
+ channel: 'webhook',
59
+ type: notification.type,
53
60
  });
54
61
  }
55
62
  }
@@ -1 +1 @@
1
- {"version":3,"file":"WebhookNotificationChannel.js","sourceRoot":"","sources":["../../../src/modules/notificationWebhook/WebhookNotificationChannel.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kCAAkC,GAEnC,MAAM,wBAAwB,CAAA;AAY/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AACvD,OAAO,EAAE,yBAAyB,EAAE,MAAM,uBAAuB,CAAA;AAsDjE,MAAM,OAAO,0BAA0B;IACR,IAAI;IAAjC,YAA6B,IAA4C;oBAA5C,IAAI;IAA2C,CAAC;IAE7E,KAAK,CAAC,OAAO,CAAC,WAAmB,EAAE,YAA0B;QAC3D,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAA;QAC5C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,sFAAsF;YACtF,2FAA2F;YAC3F,yFAAyF;YACzF,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE;gBACzB,WAAW;gBACX,cAAc,EAAE,YAAY,CAAC,EAAE;gBAC/B,IAAI,EAAE,YAAY,CAAC,IAAI;aACxB,CAAC,CAAA;YACF,uFAAuF;YACvF,qFAAqF;YACrF,uDAAuD;YACvD,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,SAAS,CAAC,8BAA8B,EAAE;gBACtE,OAAO,EAAE,SAAS;gBAClB,IAAI,EAAE,YAAY,CAAC,IAAI;aACxB,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,IAAI,CAAC,WAAmB,EAAE,YAA0B;QAChE,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,6BAA6B,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QAC9E,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO;YAAE,OAAM;QACxC,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,YAAY,CAAC,IAAI,CAAC;YAAE,OAAM;QAErD,MAAM,IAAI,GAAgC;YACxC,6FAA6F;YAC7F,4FAA4F;YAC5F,sFAAsF;YACtF,UAAU,EAAE,GAAG,YAAY,CAAC,EAAE,IAAI,YAAY,CAAC,MAAM,EAAE;YACvD,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE;YAC7B,WAAW;YACX,KAAK,EAAE,YAAY,CAAC,WAAW;YAC/B,MAAM,EAAE,YAAY,CAAC,OAAO;YAC5B,YAAY;SACb,CAAA;QACD,MAAM,iBAAiB,CAAC,IAAI,CAAC,IAAI,EAAE;YACjC,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;YAC7B,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC,CAAA;IACJ,CAAC;CACF;AAED;;;;GAIG;AACH,SAAS,YAAY,CAAC,OAAkC,EAAE,IAAsB;IAC9E,MAAM,KAAK,GAAgC,OAAO,CAAC,KAAK,CAAC,MAAM;QAC7D,CAAC,CAAC,OAAO,CAAC,KAAK;QACf,CAAC,CAAC,kCAAkC,CAAA;IACtC,OAAO,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;AAC7B,CAAC;AAED,OAAO,EAAE,yBAAyB,EAAE,CAAA"}
1
+ {"version":3,"file":"WebhookNotificationChannel.js","sourceRoot":"","sources":["../../../src/modules/notificationWebhook/WebhookNotificationChannel.ts"],"names":[],"mappings":"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"}
@@ -19,6 +19,7 @@ export interface WebhookPlatformAlertSinkDependencies {
19
19
  workspaceId: string;
20
20
  accountId: string;
21
21
  event: string;
22
+ webhookId?: string;
22
23
  }) => void;
23
24
  }
24
25
  export declare class WebhookPlatformAlertSink implements PlatformAlertSink {
@@ -1 +1 @@
1
- {"version":3,"file":"WebhookPlatformAlertSink.d.ts","sourceRoot":"","sources":["../../../src/modules/notificationWebhook/WebhookPlatformAlertSink.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,KAAK,EACL,6BAA6B,EAC7B,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,EACZ,eAAe,EAChB,MAAM,qBAAqB,CAAA;AAuB5B,MAAM,WAAW,oCAAoC;IACnD,6BAA6B,EAAE,6BAA6B,CAAA;IAC5D,YAAY,EAAE,YAAY,CAAA;IAC1B,KAAK,EAAE,KAAK,CAAA;IACZ,oFAAoF;IACpF,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;IACxB,yFAAyF;IACzF,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,8FAA8F;IAC9F,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,CACR,KAAK,EAAE,OAAO,EACd,OAAO,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAC/D,IAAI,CAAA;CACV;AAED,qBAAa,wBAAyB,YAAW,iBAAiB;IACpD,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAjC,YAA6B,IAAI,EAAE,oCAAoC,EAAI;IAErE,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAUzF;YAEa,IAAI;CAuCnB"}
1
+ {"version":3,"file":"WebhookPlatformAlertSink.d.ts","sourceRoot":"","sources":["../../../src/modules/notificationWebhook/WebhookPlatformAlertSink.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,KAAK,EACL,6BAA6B,EAC7B,kBAAkB,EAClB,iBAAiB,EACjB,YAAY,EACZ,eAAe,EAChB,MAAM,qBAAqB,CAAA;AAwB5B,MAAM,WAAW,oCAAoC;IACnD,6BAA6B,EAAE,6BAA6B,CAAA;IAC5D,YAAY,EAAE,YAAY,CAAA;IAC1B,KAAK,EAAE,KAAK,CAAA;IACZ,oFAAoF;IACpF,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;IACxB,yFAAyF;IACzF,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,8FAA8F;IAC9F,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,CACR,KAAK,EAAE,OAAO,EACd,OAAO,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,KACnF,IAAI,CAAA;CACV;AAED,qBAAa,wBAAyB,YAAW,iBAAiB;IACpD,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAjC,YAA6B,IAAI,EAAE,oCAAoC,EAAI;IAErE,qBAAqB,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAUzF;YAEa,IAAI;CA8CnB"}
@@ -1,4 +1,4 @@
1
- import { postSignedWebhook } from './signedDelivery.js';
1
+ import { fanOutSignedWebhook } from './signedDelivery.js';
2
2
  export class WebhookPlatformAlertSink {
3
3
  deps;
4
4
  constructor(deps) {
@@ -17,13 +17,12 @@ export class WebhookPlatformAlertSink {
17
17
  }
18
18
  }
19
19
  async post(workspaceId, event) {
20
- const webhook = await this.deps.notificationWebhookRepository.get(workspaceId);
21
- if (!webhook || !webhook.enabled)
22
- return;
20
+ const endpoints = (await this.deps.notificationWebhookRepository.list(workspaceId)).filter(
23
21
  // EMPTY means NONE, like the run-lifecycle filter and unlike the notification `types` one: an
24
22
  // endpoint registered to hear about parked decisions must never start paging an on-call
25
23
  // rotation because the deployment shipped a new event family.
26
- if (!webhook.alertEvents.includes(event.event))
24
+ (webhook) => webhook.enabled && webhook.alertEvents.includes(event.event));
25
+ if (endpoints.length === 0)
27
26
  return;
28
27
  const body = {
29
28
  deliveryId: deliveryIdFor(event),
@@ -49,12 +48,12 @@ export class WebhookPlatformAlertSink {
49
48
  failedTotal: event.failedTotal,
50
49
  },
51
50
  };
52
- await postSignedWebhook(this.deps, {
53
- url: webhook.url,
54
- secretSealed: webhook.secretSealed,
55
- payload: JSON.stringify(body),
56
- sentAt: body.sentAt,
57
- });
51
+ await fanOutSignedWebhook(this.deps, endpoints, { payload: JSON.stringify(body), sentAt: body.sentAt }, (error, target) => this.deps.onError?.(error, {
52
+ workspaceId,
53
+ accountId: event.accountId,
54
+ event: event.event,
55
+ webhookId: target.id,
56
+ }));
58
57
  }
59
58
  }
60
59
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"WebhookPlatformAlertSink.js","sourceRoot":"","sources":["../../../src/modules/notificationWebhook/WebhookPlatformAlertSink.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"WebhookPlatformAlertSink.js","sourceRoot":"","sources":["../../../src/modules/notificationWebhook/WebhookPlatformAlertSink.ts"],"names":[],"mappings":"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"}
@@ -18,6 +18,7 @@ export interface WebhookRunLifecycleSinkDependencies {
18
18
  workspaceId: string;
19
19
  runId: string;
20
20
  event: string;
21
+ webhookId?: string;
21
22
  }) => void;
22
23
  }
23
24
  export declare class WebhookRunLifecycleSink implements RunLifecycleSink {
@@ -1 +1 @@
1
- {"version":3,"file":"WebhookRunLifecycleSink.d.ts","sourceRoot":"","sources":["../../../src/modules/notificationWebhook/WebhookRunLifecycleSink.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,KAAK,EACL,6BAA6B,EAC7B,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,eAAe,EAChB,MAAM,qBAAqB,CAAA;AAgB5B,MAAM,WAAW,mCAAmC;IAClD,6BAA6B,EAAE,6BAA6B,CAAA;IAC5D,YAAY,EAAE,YAAY,CAAA;IAC1B,KAAK,EAAE,KAAK,CAAA;IACZ,oFAAoF;IACpF,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;IACxB,yFAAyF;IACzF,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,8FAA8F;IAC9F,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC;;;;OAIG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAA;CACnG;AAED,qBAAa,uBAAwB,YAAW,gBAAgB;IAClD,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAjC,YAA6B,IAAI,EAAE,mCAAmC,EAAI;IAEpE,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAUlF;YAEa,IAAI;CAmCnB"}
1
+ {"version":3,"file":"WebhookRunLifecycleSink.d.ts","sourceRoot":"","sources":["../../../src/modules/notificationWebhook/WebhookRunLifecycleSink.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,KAAK,EACL,6BAA6B,EAC7B,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,eAAe,EAChB,MAAM,qBAAqB,CAAA;AAmB5B,MAAM,WAAW,mCAAmC;IAClD,6BAA6B,EAAE,6BAA6B,CAAA;IAC5D,YAAY,EAAE,YAAY,CAAA;IAC1B,KAAK,EAAE,KAAK,CAAA;IACZ,oFAAoF;IACpF,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;IACxB,yFAAyF;IACzF,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,8FAA8F;IAC9F,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC;;;;OAIG;IACH,OAAO,CAAC,EAAE,CACR,KAAK,EAAE,OAAO,EACd,OAAO,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,KAC/E,IAAI,CAAA;CACV;AAED,qBAAa,uBAAwB,YAAW,gBAAgB;IAClD,OAAO,CAAC,QAAQ,CAAC,IAAI;IAAjC,YAA6B,IAAI,EAAE,mCAAmC,EAAI;IAEpE,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAYlF;YAEa,IAAI;CA0CnB"}
@@ -1,4 +1,4 @@
1
- import { postSignedWebhook } from './signedDelivery.js';
1
+ import { fanOutSignedWebhook } from './signedDelivery.js';
2
2
  export class WebhookRunLifecycleSink {
3
3
  deps;
4
4
  constructor(deps) {
@@ -9,6 +9,8 @@ export class WebhookRunLifecycleSink {
9
9
  await this.post(workspaceId, event);
10
10
  }
11
11
  catch (error) {
12
+ // A per-endpoint failure is reported by the fan-out with the endpoint named; what reaches
13
+ // here is the read or the compose failing, which belongs to no one receiver.
12
14
  this.deps.onError?.(error, {
13
15
  workspaceId,
14
16
  runId: event.runId,
@@ -17,12 +19,11 @@ export class WebhookRunLifecycleSink {
17
19
  }
18
20
  }
19
21
  async post(workspaceId, event) {
20
- const webhook = await this.deps.notificationWebhookRepository.get(workspaceId);
21
- if (!webhook || !webhook.enabled)
22
- return;
22
+ const endpoints = (await this.deps.notificationWebhookRepository.list(workspaceId)).filter(
23
23
  // EMPTY means NONE here, unlike the notification `types` filter next door: an endpoint
24
24
  // registered before run events existed must not silently start receiving a new event family.
25
- if (!webhook.runEvents.includes(event.event))
25
+ (webhook) => webhook.enabled && webhook.runEvents.includes(event.event));
26
+ if (endpoints.length === 0)
26
27
  return;
27
28
  const body = {
28
29
  // `<runId>:<event>` — stable across retries AND across a re-delivery, so it is the dedupe
@@ -45,12 +46,12 @@ export class WebhookRunLifecycleSink {
45
46
  failure: event.failure,
46
47
  },
47
48
  };
48
- await postSignedWebhook(this.deps, {
49
- url: webhook.url,
50
- secretSealed: webhook.secretSealed,
51
- payload: JSON.stringify(body),
52
- sentAt: body.sentAt,
53
- });
49
+ await fanOutSignedWebhook(this.deps, endpoints, { payload: JSON.stringify(body), sentAt: body.sentAt }, (error, target) => this.deps.onError?.(error, {
50
+ workspaceId,
51
+ runId: event.runId,
52
+ event: event.event,
53
+ webhookId: target.id,
54
+ }));
54
55
  }
55
56
  }
56
57
  //# sourceMappingURL=WebhookRunLifecycleSink.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"WebhookRunLifecycleSink.js","sourceRoot":"","sources":["../../../src/modules/notificationWebhook/WebhookRunLifecycleSink.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAiCvD,MAAM,OAAO,uBAAuB;IACL,IAAI;IAAjC,YAA6B,IAAyC;oBAAzC,IAAI;IAAwC,CAAC;IAE1E,KAAK,CAAC,eAAe,CAAC,WAAmB,EAAE,KAAwB;QACjE,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,CAAA;QACrC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE;gBACzB,WAAW;gBACX,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,KAAK,EAAE,KAAK,CAAC,KAAK;aACnB,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,IAAI,CAAC,WAAmB,EAAE,KAAwB;QAC9D,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,6BAA6B,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QAC9E,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO;YAAE,OAAM;QACxC,uFAAuF;QACvF,6FAA6F;QAC7F,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC;YAAE,OAAM;QAEpD,MAAM,IAAI,GAAuB;YAC/B,0FAA0F;YAC1F,2FAA2F;YAC3F,wFAAwF;YACxF,wFAAwF;YACxF,UAAU,EAAE,GAAG,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,EAAE;YAC3C,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE;YAC7B,WAAW;YACX,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,GAAG,EAAE;gBACH,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,YAAY,EAAE,KAAK,CAAC,YAAY;gBAChC,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,cAAc,EAAE,KAAK,CAAC,cAAc;gBACpC,OAAO,EAAE,KAAK,CAAC,OAAO;aACvB;SACF,CAAA;QACD,MAAM,iBAAiB,CAAC,IAAI,CAAC,IAAI,EAAE;YACjC,GAAG,EAAE,OAAO,CAAC,GAAG;YAChB,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;YAC7B,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC,CAAA;IACJ,CAAC;CACF"}
1
+ {"version":3,"file":"WebhookRunLifecycleSink.js","sourceRoot":"","sources":["../../../src/modules/notificationWebhook/WebhookRunLifecycleSink.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAuCzD,MAAM,OAAO,uBAAuB;IACL,IAAI;IAAjC,YAA6B,IAAyC;oBAAzC,IAAI;IAAwC,CAAC;IAE1E,KAAK,CAAC,eAAe,CAAC,WAAmB,EAAE,KAAwB;QACjE,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,CAAA;QACrC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,0FAA0F;YAC1F,6EAA6E;YAC7E,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE;gBACzB,WAAW;gBACX,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,KAAK,EAAE,KAAK,CAAC,KAAK;aACnB,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,IAAI,CAAC,WAAmB,EAAE,KAAwB;QAC9D,MAAM,SAAS,GAAG,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,6BAA6B,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM;QACxF,uFAAuF;QACvF,6FAA6F;QAC7F,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CACxE,CAAA;QACD,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;YAAE,OAAM;QAElC,MAAM,IAAI,GAAuB;YAC/B,0FAA0F;YAC1F,2FAA2F;YAC3F,wFAAwF;YACxF,wFAAwF;YACxF,UAAU,EAAE,GAAG,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,EAAE;YAC3C,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE;YAC7B,WAAW;YACX,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,GAAG,EAAE;gBACH,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,YAAY,EAAE,KAAK,CAAC,YAAY;gBAChC,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,cAAc,EAAE,KAAK,CAAC,cAAc;gBACpC,OAAO,EAAE,KAAK,CAAC,OAAO;aACvB;SACF,CAAA;QACD,MAAM,mBAAmB,CACvB,IAAI,CAAC,IAAI,EACT,SAAS,EACT,EAAE,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,EACtD,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAChB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE;YACzB,WAAW;YACX,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,SAAS,EAAE,MAAM,CAAC,EAAE;SACrB,CAAC,CACL,CAAA;IACH,CAAC;CACF"}
@@ -23,6 +23,24 @@ export interface SignedDeliveryRequest {
23
23
  payload: string;
24
24
  /** The epoch-ms stamp inside the payload; signed alongside it so a replay is detectable. */
25
25
  sentAt: number;
26
+ /**
27
+ * Absolute epoch-ms ceiling for this delivery across all of its attempts. Omitted ⇒
28
+ * {@link TOTAL_DELIVERY_BUDGET_MS} from now, which is the single-delivery case.
29
+ *
30
+ * A fan-out supplies its own so that N endpoints share ONE budget: the whole point of the number
31
+ * is the latency the caller pays on a run's terminal path, and that is a property of the fan-out,
32
+ * not of each delivery in it.
33
+ */
34
+ deadline?: number;
35
+ }
36
+ /**
37
+ * Raised for an endpoint the fan-out never got to before the shared budget ran out. Distinct from
38
+ * a delivery error on purpose: "the receiver rejected us" and "we ran out of time to ask" need
39
+ * different fixes, and reporting the second as the first would send an operator to debug a
40
+ * receiver that was never contacted.
41
+ */
42
+ export declare class WebhookDeliveryNotAttemptedError extends Error {
43
+ constructor(endpointId: string);
26
44
  }
27
45
  /**
28
46
  * POST one signed delivery, retrying within the shared wall-clock budget. Throws the last error
@@ -30,4 +48,42 @@ export interface SignedDeliveryRequest {
30
48
  * treat it as best-effort and report it through their observability hook).
31
49
  */
32
50
  export declare function postSignedWebhook(deps: SignedDeliveryDependencies, request: SignedDeliveryRequest): Promise<void>;
51
+ /** One subscribed endpoint, as the fan-out needs it: where to POST and what to sign with. */
52
+ export interface SignedDeliveryTarget {
53
+ id: string;
54
+ url: string;
55
+ secretSealed: string | null;
56
+ }
57
+ /**
58
+ * POST one already-composed body to EVERY subscribed endpoint, isolating each.
59
+ *
60
+ * Three properties are the whole reason this is a helper rather than a loop at each of the three
61
+ * call sites:
62
+ *
63
+ * - **Concurrent, but BOUNDED.** The caller awaits the fan-out, so its cost is latency on the
64
+ * engine step that produced the event: the step that parks or settles a run. Running the
65
+ * deliveries in series would multiply the budget by the endpoint count, so a workspace would pay
66
+ * for enrolling a second integration in the latency of every run. Running them all at once is
67
+ * the opposite mistake, and a quieter one, because the concurrency past `MAX_CONCURRENT_DELIVERIES`
68
+ * is imaginary on the Worker (see that constant) while the budget it burns is real.
69
+ * - **ONE wall-clock budget for the whole fan-out**, not one per endpoint. The number exists to
70
+ * bound what the caller waits for, and the caller waits for all of this, so a per-endpoint budget
71
+ * would let ten endpoints bound nothing at all. Each delivery is clamped to what is left when it
72
+ * actually starts, so its own retry loop still stops on time.
73
+ * - **One failing receiver costs only its own delivery.** A rejected `Promise.all` would abandon
74
+ * nothing (the others are already in flight) but would report ONE failure for the batch, so a
75
+ * permanently broken endpoint would mask the health of every sibling. Each result is settled and
76
+ * reported on its own, naming the endpoint.
77
+ *
78
+ * An endpoint the budget never reached is reported too, as {@link WebhookDeliveryNotAttemptedError}
79
+ * rather than as a delivery failure: it is a cap, and a cap records what it dropped. Silence there
80
+ * would read as a delivery that succeeded, and a generic failure would read as a broken receiver.
81
+ *
82
+ * Never throws: every outcome goes to `onEndpointError` and the fan-out carries on, which is what
83
+ * "best-effort" means for this transport.
84
+ */
85
+ export declare function fanOutSignedWebhook(deps: SignedDeliveryDependencies, targets: readonly SignedDeliveryTarget[], delivery: {
86
+ payload: string;
87
+ sentAt: number;
88
+ }, onEndpointError: (error: unknown, target: SignedDeliveryTarget) => void): Promise<void>;
33
89
  //# sourceMappingURL=signedDelivery.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"signedDelivery.d.ts","sourceRoot":"","sources":["../../../src/modules/notificationWebhook/signedDelivery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AAkC/E,yFAAyF;AACzF,MAAM,WAAW,0BAA0B;IACzC,YAAY,EAAE,YAAY,CAAA;IAC1B,KAAK,EAAE,KAAK,CAAA;IACZ,oFAAoF;IACpF,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;IACxB,yFAAyF;IACzF,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC;;;;OAIG;IACH,eAAe,CAAC,EAAE,eAAe,CAAA;CAClC;AAED,oFAAoF;AACpF,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,MAAM,CAAA;IACX,4EAA4E;IAC5E,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,6FAA6F;IAC7F,OAAO,EAAE,MAAM,CAAA;IACf,4FAA4F;IAC5F,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,0BAA0B,EAChC,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,IAAI,CAAC,CAiEf"}
1
+ {"version":3,"file":"signedDelivery.d.ts","sourceRoot":"","sources":["../../../src/modules/notificationWebhook/signedDelivery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAA;AA8C/E,yFAAyF;AACzF,MAAM,WAAW,0BAA0B;IACzC,YAAY,EAAE,YAAY,CAAA;IAC1B,KAAK,EAAE,KAAK,CAAA;IACZ,oFAAoF;IACpF,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;IACxB,yFAAyF;IACzF,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC;;;;OAIG;IACH,eAAe,CAAC,EAAE,eAAe,CAAA;CAClC;AAoBD,oFAAoF;AACpF,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,MAAM,CAAA;IACX,4EAA4E;IAC5E,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,6FAA6F;IAC7F,OAAO,EAAE,MAAM,CAAA;IACf,4FAA4F;IAC5F,MAAM,EAAE,MAAM,CAAA;IACd;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED;;;;;GAKG;AACH,qBAAa,gCAAiC,SAAQ,KAAK;IACzD,YAAY,UAAU,EAAE,MAAM,EAK7B;CACF;AAED;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,0BAA0B,EAChC,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,IAAI,CAAC,CAiEf;AAED,6FAA6F;AAC7F,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAA;IACV,GAAG,EAAE,MAAM,CAAA;IACX,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,0BAA0B,EAChC,OAAO,EAAE,SAAS,oBAAoB,EAAE,EACxC,QAAQ,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAC7C,eAAe,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,oBAAoB,KAAK,IAAI,GACtE,OAAO,CAAC,IAAI,CAAC,CAiCf"}
@@ -2,30 +2,71 @@ import { ValidationError } from '@cat-factory/kernel';
2
2
  import { DEFAULT_MAX_REDIRECTS, safeFetch } from '../shared/safe-fetch.js';
3
3
  import { assertSafeNotificationWebhookUrl } from './webhookUrl.js';
4
4
  import { signWebhookDelivery } from './webhookSignature.js';
5
- // The one outbound-delivery core the workspace's registered webhook endpoint is driven through.
6
- // Both families that POST to it — the notification cards and the run-lifecycle events share
7
- // this rather than each carrying its own retry loop, because everything interesting about the
8
- // delivery (the wall-clock budget, which failures are worth retrying, re-validating the URL on
9
- // every redirect hop, the signature headers) is a property of the ENDPOINT, not of the payload.
10
- // A second copy would be a second place to get the SSRF guard subtly wrong.
5
+ // The one outbound-delivery core every registered webhook endpoint is driven through. All three
6
+ // families that POST to one — the notification cards, the run-lifecycle events and the
7
+ // platform-health alerts — share this rather than each carrying its own retry loop, because
8
+ // everything interesting about the delivery (the wall-clock budget, which failures are worth
9
+ // retrying, re-validating the URL on every redirect hop, the signature headers) is a property of
10
+ // the ENDPOINT, not of the payload. A second copy would be a second place to get the SSRF guard
11
+ // subtly wrong.
12
+ //
13
+ // A workspace registers SEVERAL endpoints, so the three families reach this through
14
+ // `fanOutSignedWebhook` rather than calling `postSignedWebhook` per endpoint themselves: the
15
+ // bounded concurrency, the shared wall-clock budget and the per-endpoint isolation are properties
16
+ // of the fan-out, and three hand-rolled copies of it is exactly the drift this file exists to
17
+ // prevent one layer down.
11
18
  /** How many attempts one delivery gets, and how long to wait between them (exponential). */
12
19
  const MAX_ATTEMPTS = 3;
13
20
  const BASE_RETRY_MS = 250;
14
21
  /** Give up on a single HTTP attempt after this long, so a black-holing endpoint can't hang us. */
15
22
  const REQUEST_TIMEOUT_MS = 5000;
16
23
  /**
17
- * The ceiling on ONE delivery across all of its attempts. This is the number that matters, and it
18
- * is not the per-attempt timeout multiplied out: the caller AWAITS the delivery, so every
19
- * millisecond spent here is latency added to the engine step that produced the event — the very
20
- * step that parks or settles a run. Three 5s attempts plus backoff would let a dead receiver add
21
- * ~15.8s, which the in-app and Slack channels never do.
24
+ * The ceiling on one EMISSION: a single delivery, or a whole fan-out across every subscribed
25
+ * endpoint. This is the number that matters, and it is not the per-attempt timeout multiplied out.
26
+ * The caller AWAITS it, so every millisecond spent here is latency added to the engine step that
27
+ * produced the event, the very step that parks or settles a run. Three 5s attempts plus backoff
28
+ * would let a dead receiver add ~15.8s, which the in-app and Slack channels never do.
22
29
  *
23
30
  * So the retry budget is a WALL-CLOCK deadline, not an attempt count: attempts stop as soon as the
24
31
  * remaining budget is gone, and each attempt's own timeout is clamped to what is left. Delivery is
25
32
  * best-effort by contract, so a receiver too slow to answer inside the budget is treated exactly
26
33
  * like one that failed.
34
+ *
35
+ * `fanOutSignedWebhook` hands the SAME deadline to every endpoint it drives rather than giving each
36
+ * a fresh one, so registering a tenth webhook cannot turn a bounded wait into a ten-times-bounded
37
+ * one. What that trades away is stated at the fan-out: past the budget, endpoints are reported as
38
+ * not attempted rather than delivered late.
27
39
  */
28
40
  const TOTAL_DELIVERY_BUDGET_MS = 6000;
41
+ /**
42
+ * How many deliveries may be in flight at once during a fan-out.
43
+ *
44
+ * Six because that is the Cloudflare Workers ceiling on simultaneous open connections per
45
+ * invocation: a seventh `fetch` does not fail, it QUEUES, invisibly to the code that issued it. An
46
+ * unbounded fan-out therefore does not buy parallelism past six, it only hides the queue, and the
47
+ * hiding is the bug: each delivery's wall-clock budget starts when `postSignedWebhook` is entered,
48
+ * so a queued endpoint spends its budget waiting for a connection and is then reported as a
49
+ * failure it never actually attempted. Bounding the fan-out is what makes a reported failure mean
50
+ * the receiver failed.
51
+ *
52
+ * Deliberately ONE number rather than a per-runtime one. Node has no such ceiling, but the cap is
53
+ * ten endpoints, so the parallelism it would unlock is a second wave at most, and both facades
54
+ * behaving identically is worth more than that: the fan-out's timing is what the conformance and
55
+ * unit suites assert against.
56
+ */
57
+ const MAX_CONCURRENT_DELIVERIES = 6;
58
+ /**
59
+ * Raised for an endpoint the fan-out never got to before the shared budget ran out. Distinct from
60
+ * a delivery error on purpose: "the receiver rejected us" and "we ran out of time to ask" need
61
+ * different fixes, and reporting the second as the first would send an operator to debug a
62
+ * receiver that was never contacted.
63
+ */
64
+ export class WebhookDeliveryNotAttemptedError extends Error {
65
+ constructor(endpointId) {
66
+ super(`Webhook delivery to \`${endpointId}\` was not attempted: the fan-out spent its ${TOTAL_DELIVERY_BUDGET_MS}ms budget on earlier endpoints`);
67
+ this.name = 'WebhookDeliveryNotAttemptedError';
68
+ }
69
+ }
29
70
  /**
30
71
  * POST one signed delivery, retrying within the shared wall-clock budget. Throws the last error
31
72
  * when every attempt is spent — the CALLER decides what a failure means (both current callers
@@ -49,7 +90,7 @@ export async function postSignedWebhook(deps, request) {
49
90
  // `safeFetch` also strips the body and credential headers on a cross-origin hop, so a permitted
50
91
  // host cannot bounce the delivery to a different one.
51
92
  const assertSafe = (u) => assertSafeNotificationWebhookUrl(u, deps.urlSafetyPolicy);
52
- const deadline = deps.clock.now() + TOTAL_DELIVERY_BUDGET_MS;
93
+ const deadline = request.deadline ?? deps.clock.now() + TOTAL_DELIVERY_BUDGET_MS;
53
94
  let lastError;
54
95
  for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
55
96
  if (attempt > 0) {
@@ -92,6 +133,67 @@ export async function postSignedWebhook(deps, request) {
92
133
  }
93
134
  throw lastError ?? new Error('Webhook delivery failed');
94
135
  }
136
+ /**
137
+ * POST one already-composed body to EVERY subscribed endpoint, isolating each.
138
+ *
139
+ * Three properties are the whole reason this is a helper rather than a loop at each of the three
140
+ * call sites:
141
+ *
142
+ * - **Concurrent, but BOUNDED.** The caller awaits the fan-out, so its cost is latency on the
143
+ * engine step that produced the event: the step that parks or settles a run. Running the
144
+ * deliveries in series would multiply the budget by the endpoint count, so a workspace would pay
145
+ * for enrolling a second integration in the latency of every run. Running them all at once is
146
+ * the opposite mistake, and a quieter one, because the concurrency past `MAX_CONCURRENT_DELIVERIES`
147
+ * is imaginary on the Worker (see that constant) while the budget it burns is real.
148
+ * - **ONE wall-clock budget for the whole fan-out**, not one per endpoint. The number exists to
149
+ * bound what the caller waits for, and the caller waits for all of this, so a per-endpoint budget
150
+ * would let ten endpoints bound nothing at all. Each delivery is clamped to what is left when it
151
+ * actually starts, so its own retry loop still stops on time.
152
+ * - **One failing receiver costs only its own delivery.** A rejected `Promise.all` would abandon
153
+ * nothing (the others are already in flight) but would report ONE failure for the batch, so a
154
+ * permanently broken endpoint would mask the health of every sibling. Each result is settled and
155
+ * reported on its own, naming the endpoint.
156
+ *
157
+ * An endpoint the budget never reached is reported too, as {@link WebhookDeliveryNotAttemptedError}
158
+ * rather than as a delivery failure: it is a cap, and a cap records what it dropped. Silence there
159
+ * would read as a delivery that succeeded, and a generic failure would read as a broken receiver.
160
+ *
161
+ * Never throws: every outcome goes to `onEndpointError` and the fan-out carries on, which is what
162
+ * "best-effort" means for this transport.
163
+ */
164
+ export async function fanOutSignedWebhook(deps, targets, delivery, onEndpointError) {
165
+ const deadline = deps.clock.now() + TOTAL_DELIVERY_BUDGET_MS;
166
+ // A shared cursor rather than pre-sliced waves: a worker that finishes early picks up the next
167
+ // endpoint immediately, so one slow receiver delays only itself and not the whole batch behind
168
+ // it. With fixed waves, six healthy endpoints would all wait on the slowest of their six.
169
+ let next = 0;
170
+ const deliverFrom = async () => {
171
+ for (;;) {
172
+ const index = next;
173
+ next += 1;
174
+ const target = targets[index];
175
+ if (!target)
176
+ return;
177
+ if (deps.clock.now() >= deadline) {
178
+ onEndpointError(new WebhookDeliveryNotAttemptedError(target.id), target);
179
+ continue;
180
+ }
181
+ try {
182
+ await postSignedWebhook(deps, {
183
+ url: target.url,
184
+ secretSealed: target.secretSealed,
185
+ payload: delivery.payload,
186
+ sentAt: delivery.sentAt,
187
+ deadline,
188
+ });
189
+ }
190
+ catch (error) {
191
+ onEndpointError(error, target);
192
+ }
193
+ }
194
+ };
195
+ await Promise.all(Array.from({ length: Math.min(MAX_CONCURRENT_DELIVERIES, targets.length) }, deliverFrom));
196
+ }
95
197
  /** Builds the redirect/size errors `safeFetch` raises, carrying its status for the log line. */
96
198
  function makeWebhookError(status, message) {
97
199
  return new Error(`Webhook delivery failed (${status}): ${message}`);
@@ -1 +1 @@
1
- {"version":3,"file":"signedDelivery.js","sourceRoot":"","sources":["../../../src/modules/notificationWebhook/signedDelivery.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"signedDelivery.js","sourceRoot":"","sources":["../../../src/modules/notificationWebhook/signedDelivery.ts"],"names":[],"mappings":"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"}
@@ -25,12 +25,14 @@ export interface NotificationWebhookSupportDependencies {
25
25
  workspaceId: string;
26
26
  notificationId: string;
27
27
  type: string;
28
+ webhookId?: string;
28
29
  }) => void;
29
30
  /** The same hook for a RUN-LIFECYCLE delivery, whose context names a run rather than a card. */
30
31
  onRunEventError?: (error: unknown, context: {
31
32
  workspaceId: string;
32
33
  runId: string;
33
34
  event: string;
35
+ webhookId?: string;
34
36
  }) => void;
35
37
  /**
36
38
  * The same hook for a PLATFORM-HEALTH delivery, whose context names the account whose health
@@ -41,6 +43,7 @@ export interface NotificationWebhookSupportDependencies {
41
43
  workspaceId: string;
42
44
  accountId: string;
43
45
  event: string;
46
+ webhookId?: string;
44
47
  }) => void;
45
48
  }
46
49
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"support.d.ts","sourceRoot":"","sources":["../../../src/modules/notificationWebhook/support.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,KAAK,EACL,6BAA6B,EAC7B,YAAY,EACZ,eAAe,EAChB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAA;AAC5E,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAA;AAC5E,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAA;AACxE,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAA;AAEtE;;;;GAIG;AACH,eAAO,MAAM,gCAAgC,qCAAqC,CAAA;AAElF,MAAM,WAAW,sCAAsC;IACrD,6BAA6B,EAAE,6BAA6B,CAAA;IAC5D,YAAY,EAAE,YAAY,CAAA;IAC1B,KAAK,EAAE,KAAK,CAAA;IACZ;;;;OAIG;IACH,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;IACxB,8FAA8F;IAC9F,OAAO,CAAC,EAAE,CACR,KAAK,EAAE,OAAO,EACd,OAAO,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,KACnE,IAAI,CAAA;IACT,gGAAgG;IAChG,eAAe,CAAC,EAAE,CAChB,KAAK,EAAE,OAAO,EACd,OAAO,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAC3D,IAAI,CAAA;IACT;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,CACrB,KAAK,EAAE,OAAO,EACd,OAAO,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAC/D,IAAI,CAAA;CACV;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,+BAA+B,CAAC,IAAI,EAAE,sCAAsC,GAAG;IAC7F,OAAO,EAAE,0BAA0B,CAAA;IACnC,OAAO,EAAE,0BAA0B,CAAA;IACnC,gBAAgB,EAAE,uBAAuB,CAAA;IACzC,iBAAiB,EAAE,wBAAwB,CAAA;CAC5C,CAiCA"}
1
+ {"version":3,"file":"support.d.ts","sourceRoot":"","sources":["../../../src/modules/notificationWebhook/support.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,KAAK,EACL,6BAA6B,EAC7B,YAAY,EACZ,eAAe,EAChB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAA;AAC5E,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAA;AAC5E,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAA;AACxE,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAA;AAEtE;;;;GAIG;AACH,eAAO,MAAM,gCAAgC,qCAAqC,CAAA;AAElF,MAAM,WAAW,sCAAsC;IACrD,6BAA6B,EAAE,6BAA6B,CAAA;IAC5D,YAAY,EAAE,YAAY,CAAA;IAC1B,KAAK,EAAE,KAAK,CAAA;IACZ;;;;OAIG;IACH,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAA;IAKxB,8FAA8F;IAC9F,OAAO,CAAC,EAAE,CACR,KAAK,EAAE,OAAO,EACd,OAAO,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,KACvF,IAAI,CAAA;IACT,gGAAgG;IAChG,eAAe,CAAC,EAAE,CAChB,KAAK,EAAE,OAAO,EACd,OAAO,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,KAC/E,IAAI,CAAA;IACT;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,CACrB,KAAK,EAAE,OAAO,EACd,OAAO,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,KACnF,IAAI,CAAA;CACV;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,+BAA+B,CAAC,IAAI,EAAE,sCAAsC,GAAG;IAC7F,OAAO,EAAE,0BAA0B,CAAA;IACnC,OAAO,EAAE,0BAA0B,CAAA;IACnC,gBAAgB,EAAE,uBAAuB,CAAA;IACzC,iBAAiB,EAAE,wBAAwB,CAAA;CAC5C,CAiCA"}
@@ -1 +1 @@
1
- {"version":3,"file":"support.js","sourceRoot":"","sources":["../../../src/modules/notificationWebhook/support.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAA;AAC5E,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAA;AAC5E,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAA;AACxE,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAA;AAEtE;;;;GAIG;AACH,MAAM,CAAC,MAAM,gCAAgC,GAAG,kCAAkC,CAAA;AAkClF;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,+BAA+B,CAAC,IAA4C;IAM1F,OAAO;QACL,iBAAiB,EAAE,IAAI,wBAAwB,CAAC;YAC9C,6BAA6B,EAAE,IAAI,CAAC,6BAA6B;YACjE,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,eAAe,EAAE,IAAI,CAAC,eAAe;YACrC,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,OAAO,EAAE,IAAI,CAAC,oBAAoB;SACnC,CAAC;QACF,gBAAgB,EAAE,IAAI,uBAAuB,CAAC;YAC5C,6BAA6B,EAAE,IAAI,CAAC,6BAA6B;YACjE,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,eAAe,EAAE,IAAI,CAAC,eAAe;YACrC,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,OAAO,EAAE,IAAI,CAAC,eAAe;SAC9B,CAAC;QACF,OAAO,EAAE,IAAI,0BAA0B,CAAC;YACtC,6BAA6B,EAAE,IAAI,CAAC,6BAA6B;YACjE,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,eAAe,EAAE,IAAI,CAAC,eAAe;SACtC,CAAC;QACF,OAAO,EAAE,IAAI,0BAA0B,CAAC;YACtC,6BAA6B,EAAE,IAAI,CAAC,6BAA6B;YACjE,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,eAAe,EAAE,IAAI,CAAC,eAAe;YACrC,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAC;KACH,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"support.js","sourceRoot":"","sources":["../../../src/modules/notificationWebhook/support.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAA;AAC5E,OAAO,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAA;AAC5E,OAAO,EAAE,wBAAwB,EAAE,MAAM,+BAA+B,CAAA;AACxE,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAA;AAEtE;;;;GAIG;AACH,MAAM,CAAC,MAAM,gCAAgC,GAAG,kCAAkC,CAAA;AAsClF;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,+BAA+B,CAAC,IAA4C;IAM1F,OAAO;QACL,iBAAiB,EAAE,IAAI,wBAAwB,CAAC;YAC9C,6BAA6B,EAAE,IAAI,CAAC,6BAA6B;YACjE,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,eAAe,EAAE,IAAI,CAAC,eAAe;YACrC,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,OAAO,EAAE,IAAI,CAAC,oBAAoB;SACnC,CAAC;QACF,gBAAgB,EAAE,IAAI,uBAAuB,CAAC;YAC5C,6BAA6B,EAAE,IAAI,CAAC,6BAA6B;YACjE,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,eAAe,EAAE,IAAI,CAAC,eAAe;YACrC,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,OAAO,EAAE,IAAI,CAAC,eAAe;SAC9B,CAAC;QACF,OAAO,EAAE,IAAI,0BAA0B,CAAC;YACtC,6BAA6B,EAAE,IAAI,CAAC,6BAA6B;YACjE,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,eAAe,EAAE,IAAI,CAAC,eAAe;SACtC,CAAC;QACF,OAAO,EAAE,IAAI,0BAA0B,CAAC;YACtC,6BAA6B,EAAE,IAAI,CAAC,6BAA6B;YACjE,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,eAAe,EAAE,IAAI,CAAC,eAAe;YACrC,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAC;KACH,CAAA;AACH,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cat-factory/integrations",
3
- "version": "0.143.1",
3
+ "version": "0.144.0",
4
4
  "description": "External-system integration domain logic for the Agent Architecture Board (GitHub, documents, tasks, environments, runners).",
5
5
  "repository": {
6
6
  "type": "git",
@@ -27,15 +27,15 @@
27
27
  "ai": "^7.0.51",
28
28
  "p-map": "^7.0.6",
29
29
  "yaml": "^2.9.0",
30
- "@cat-factory/contracts": "0.267.0",
31
- "@cat-factory/kernel": "0.265.0"
30
+ "@cat-factory/contracts": "0.268.0",
31
+ "@cat-factory/kernel": "0.266.0"
32
32
  },
33
33
  "devDependencies": {
34
34
  "typescript": "7.0.2",
35
35
  "undici": "^8.10.0",
36
36
  "valibot": "^1.4.2",
37
37
  "vitest": "^4.1.10",
38
- "@cat-factory/caching": "0.18.6"
38
+ "@cat-factory/caching": "0.18.7"
39
39
  },
40
40
  "scripts": {
41
41
  "build": "tsc -b tsconfig.build.json",