@adcp/sdk 14.0.0-beta.14 → 14.0.0-beta.15
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/dist/lib/auth/oauth/authorization-required.d.mts +25 -11
- package/dist/lib/auth/oauth/authorization-required.d.ts +25 -11
- package/dist/lib/auth/oauth/authorization-required.js +18 -4
- package/dist/lib/auth/oauth/authorization-required.mjs +17 -4
- package/dist/lib/auth/oauth/index.d.mts +1 -1
- package/dist/lib/auth/oauth/index.d.ts +1 -1
- package/dist/lib/auth/oauth/index.js +2 -0
- package/dist/lib/auth/oauth/index.mjs +2 -0
- package/dist/lib/auth/oauth/resource-url.d.mts +8 -0
- package/dist/lib/auth/oauth/resource-url.d.ts +8 -0
- package/dist/lib/auth/oauth/resource-url.js +42 -0
- package/dist/lib/auth/oauth/resource-url.mjs +40 -0
- package/dist/lib/core/ConversationTypes.d.mts +10 -0
- package/dist/lib/core/ConversationTypes.d.ts +10 -0
- package/dist/lib/core/SingleAgentClient.d.mts +5 -2
- package/dist/lib/core/SingleAgentClient.d.ts +5 -2
- package/dist/lib/core/SingleAgentClient.js +133 -28
- package/dist/lib/core/SingleAgentClient.mjs +138 -29
- package/dist/lib/core/TaskExecutor.d.mts +1 -0
- package/dist/lib/core/TaskExecutor.d.ts +1 -0
- package/dist/lib/core/TaskExecutor.js +7 -1
- package/dist/lib/core/TaskExecutor.mjs +7 -1
- package/dist/lib/core/webhook-registration.d.mts +8 -1
- package/dist/lib/core/webhook-registration.d.ts +8 -1
- package/dist/lib/core/webhook-registration.js +65 -5
- package/dist/lib/core/webhook-registration.mjs +61 -4
- package/dist/lib/errors/index.d.mts +9 -0
- package/dist/lib/errors/index.d.ts +9 -0
- package/dist/lib/errors/index.js +33 -0
- package/dist/lib/errors/index.mjs +32 -0
- package/dist/lib/index.d.mts +3 -2
- package/dist/lib/index.d.ts +3 -2
- package/dist/lib/index.js +4 -0
- package/dist/lib/index.mjs +4 -0
- package/dist/lib/media-buy/compatibility.js +14 -2
- package/dist/lib/media-buy/compatibility.mjs +14 -2
- package/dist/lib/protocols/index.js +23 -7
- package/dist/lib/protocols/index.mjs +24 -8
- package/dist/lib/protocols/mcp.js +8 -6
- package/dist/lib/protocols/mcp.mjs +9 -7
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/server/decisioning/async-outcome.d.mts +11 -0
- package/dist/lib/server/decisioning/async-outcome.d.ts +11 -0
- package/dist/lib/server/decisioning/context.d.mts +11 -1
- package/dist/lib/server/decisioning/context.d.ts +11 -1
- package/dist/lib/server/decisioning/index.d.mts +3 -2
- package/dist/lib/server/decisioning/index.d.ts +3 -2
- package/dist/lib/server/decisioning/index.js +9 -0
- package/dist/lib/server/decisioning/index.mjs +10 -0
- package/dist/lib/server/decisioning/runtime/from-platform.d.mts +5 -2
- package/dist/lib/server/decisioning/runtime/from-platform.d.ts +5 -2
- package/dist/lib/server/decisioning/runtime/from-platform.js +40 -8
- package/dist/lib/server/decisioning/runtime/from-platform.mjs +40 -8
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.d.mts +8 -1
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.d.ts +8 -1
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.js +10 -1
- package/dist/lib/server/decisioning/runtime/postgres-task-registry.mjs +9 -1
- package/dist/lib/server/decisioning/runtime/postgres-task-settlement.d.mts +79 -0
- package/dist/lib/server/decisioning/runtime/postgres-task-settlement.d.ts +79 -0
- package/dist/lib/server/decisioning/runtime/postgres-task-settlement.js +391 -0
- package/dist/lib/server/decisioning/runtime/postgres-task-settlement.mjs +369 -0
- package/dist/lib/server/decisioning/runtime/task-registry.d.mts +2 -0
- package/dist/lib/server/decisioning/runtime/task-registry.d.ts +2 -0
- package/dist/lib/server/decisioning/runtime/task-registry.js +2 -1
- package/dist/lib/server/decisioning/runtime/task-registry.mjs +2 -1
- package/dist/lib/server/decisioning/runtime/to-context.js +15 -11
- package/dist/lib/server/decisioning/runtime/to-context.mjs +15 -11
- package/dist/lib/server/index.d.mts +2 -2
- package/dist/lib/server/index.d.ts +2 -2
- package/dist/lib/server/index.js +4 -0
- package/dist/lib/server/index.mjs +4 -0
- package/dist/lib/server/webhook-delivery/index.d.mts +2 -2
- package/dist/lib/server/webhook-delivery/index.d.ts +2 -2
- package/dist/lib/server/webhook-delivery/index.js +4 -0
- package/dist/lib/server/webhook-delivery/index.mjs +5 -1
- package/dist/lib/server/webhook-delivery/pg.d.mts +3 -1
- package/dist/lib/server/webhook-delivery/pg.d.ts +3 -1
- package/dist/lib/server/webhook-delivery/pg.js +25 -2
- package/dist/lib/server/webhook-delivery/pg.mjs +25 -2
- package/dist/lib/server/webhook-delivery/recovery.d.mts +44 -0
- package/dist/lib/server/webhook-delivery/recovery.d.ts +44 -0
- package/dist/lib/server/webhook-delivery/recovery.js +146 -43
- package/dist/lib/server/webhook-delivery/recovery.mjs +144 -43
- package/dist/lib/signing/agent-resolver/index.d.mts +1 -1
- package/dist/lib/signing/agent-resolver/index.d.ts +1 -1
- package/dist/lib/signing/agent-resolver/resolve-agent.d.mts +9 -0
- package/dist/lib/signing/agent-resolver/resolve-agent.d.ts +9 -0
- package/dist/lib/signing/agent-resolver/resolved-agent-jwks.d.mts +4 -1
- package/dist/lib/signing/agent-resolver/resolved-agent-jwks.d.ts +4 -1
- package/dist/lib/signing/agent-resolver/resolved-agent-jwks.js +17 -4
- package/dist/lib/signing/agent-resolver/resolved-agent-jwks.mjs +17 -4
- package/dist/lib/signing/jwks.d.mts +7 -0
- package/dist/lib/signing/jwks.d.ts +7 -0
- package/dist/lib/signing/server.d.mts +2 -2
- package/dist/lib/signing/server.d.ts +2 -2
- package/dist/lib/signing/webhook-verifier.d.mts +6 -0
- package/dist/lib/signing/webhook-verifier.d.ts +6 -0
- package/dist/lib/signing/webhook-verifier.js +38 -4
- package/dist/lib/signing/webhook-verifier.mjs +38 -4
- package/dist/lib/testing/client.d.mts +1 -0
- package/dist/lib/testing/client.d.ts +1 -0
- package/dist/lib/testing/client.js +6 -2
- package/dist/lib/testing/client.mjs +6 -2
- package/dist/lib/testing/compliance/comply.d.mts +2 -2
- package/dist/lib/testing/compliance/comply.d.ts +2 -2
- package/dist/lib/testing/compliance/comply.js +41 -31
- package/dist/lib/testing/compliance/comply.mjs +44 -21
- package/dist/lib/testing/storyboard/oauth-metadata-graph/grader.d.mts +1 -7
- package/dist/lib/testing/storyboard/oauth-metadata-graph/grader.d.ts +1 -7
- package/dist/lib/testing/storyboard/oauth-metadata-graph/grader.js +6 -42
- package/dist/lib/testing/storyboard/oauth-metadata-graph/grader.mjs +10 -40
- package/dist/lib/testing/storyboard/validations.d.mts +1 -1
- package/dist/lib/testing/storyboard/validations.d.ts +1 -1
- package/dist/lib/utils/adcp-version-config.d.mts +2 -0
- package/dist/lib/utils/adcp-version-config.d.ts +2 -0
- package/dist/lib/utils/adcp-version-config.js +5 -0
- package/dist/lib/utils/adcp-version-config.mjs +4 -0
- package/dist/lib/version.d.mts +3 -3
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.js +3 -3
- package/dist/lib/version.mjs +3 -3
- package/docs/llms.txt +3 -1
- package/docs/migration-12-to-14.md +6 -5
- package/docs/migration-13-to-14.md +48 -7
- package/docs/migration-task-registry-scoping.md +164 -11
- package/package.json +1 -1
- package/skills/build-decisioning-platform/advanced/REFERENCE.md +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { PgQueryable } from '../postgres-task-store';
|
|
2
|
-
import type { WebhookDeliveryStore } from '../webhook-emitter';
|
|
2
|
+
import type { WebhookDeliveryKey, WebhookDeliveryStore } from '../webhook-emitter';
|
|
3
3
|
import type { WebhookDeliveryRecoveryBackend } from './recovery';
|
|
4
4
|
export interface PgWebhookDeliveryStoreOptions {
|
|
5
5
|
/** Defaults to `adcp_webhook_deliveries`. */
|
|
@@ -12,6 +12,8 @@ export interface PgWebhookDeliveryRecoveryOptions {
|
|
|
12
12
|
tableName?: string;
|
|
13
13
|
/** Assert that the database/schema is dedicated to this deployment. */
|
|
14
14
|
acknowledgeIsolatedDatabase?: boolean;
|
|
15
|
+
/** Restrict recovery leases to this trusted publisher/tenant namespace. */
|
|
16
|
+
claimScope?: Pick<WebhookDeliveryKey, 'publisherScope' | 'tenantScope'>;
|
|
15
17
|
}
|
|
16
18
|
export declare function getWebhookDeliveryMigration(options?: PgWebhookDeliveryStoreOptions): string;
|
|
17
19
|
export declare const WEBHOOK_DELIVERY_MIGRATION: string;
|
|
@@ -89,6 +89,9 @@ CREATE TABLE IF NOT EXISTS ${table} (
|
|
|
89
89
|
CONSTRAINT ${raw}_valid_disposition CHECK (disposition IS NULL OR disposition IN ('delivered', 'terminal'))
|
|
90
90
|
);
|
|
91
91
|
|
|
92
|
+
ALTER TABLE ${table}
|
|
93
|
+
ADD COLUMN IF NOT EXISTS intent_fingerprint TEXT;
|
|
94
|
+
|
|
92
95
|
CREATE INDEX IF NOT EXISTS idx_${raw}_pending
|
|
93
96
|
ON ${table}(next_attempt_at, lease_expires_at) WHERE state = 'pending';
|
|
94
97
|
`.trim();
|
|
@@ -169,6 +172,14 @@ function pgWebhookDeliveryRecoveryBackend(db, options = {}) {
|
|
|
169
172
|
const tableName = options.tableName ?? DEFAULT_OUTBOX_TABLE;
|
|
170
173
|
const table = (0, import_common.quoteWebhookTable)(tableName);
|
|
171
174
|
assertPgDeploymentNamespace("pgWebhookDeliveryRecoveryBackend", tableName, DEFAULT_OUTBOX_TABLE, options);
|
|
175
|
+
if (options.claimScope) {
|
|
176
|
+
(0, import_common.assertDeliveryKey)({ ...options.claimScope, deliveryId: "claim-scope-validation" });
|
|
177
|
+
}
|
|
178
|
+
const assertConfiguredScope = (key) => {
|
|
179
|
+
if (options.claimScope && (key.publisherScope !== options.claimScope.publisherScope || key.tenantScope !== options.claimScope.tenantScope)) {
|
|
180
|
+
throw new Error("Webhook recovery key is outside the configured claim scope");
|
|
181
|
+
}
|
|
182
|
+
};
|
|
172
183
|
async function query(operation, text, values) {
|
|
173
184
|
try {
|
|
174
185
|
return await db.query(text, values);
|
|
@@ -182,7 +193,7 @@ function pgWebhookDeliveryRecoveryBackend(db, options = {}) {
|
|
|
182
193
|
try {
|
|
183
194
|
await db.query(
|
|
184
195
|
`SELECT publisher_scope, tenant_scope, delivery_id, snapshot, snapshot_fingerprint,
|
|
185
|
-
storage_fingerprint, state, disposition, attempt_count, next_attempt_at, lease_owner,
|
|
196
|
+
storage_fingerprint, intent_fingerprint, state, disposition, attempt_count, next_attempt_at, lease_owner,
|
|
186
197
|
lease_claim_id, lease_version, lease_expires_at FROM ${table} LIMIT 0`
|
|
187
198
|
);
|
|
188
199
|
} catch (cause) {
|
|
@@ -194,6 +205,7 @@ function pgWebhookDeliveryRecoveryBackend(db, options = {}) {
|
|
|
194
205
|
},
|
|
195
206
|
async checkpoint(key, snapshot, snapshotFingerprint, storageFingerprint, initialLease) {
|
|
196
207
|
(0, import_common.assertDeliveryKey)(key);
|
|
208
|
+
assertConfiguredScope(key);
|
|
197
209
|
(0, import_common.assertLeaseControls)(initialLease.ownerToken, initialLease.leaseMs);
|
|
198
210
|
const leaseClaimId = (0, import_node_crypto.randomUUID)();
|
|
199
211
|
const result = await query(
|
|
@@ -259,6 +271,7 @@ function pgWebhookDeliveryRecoveryBackend(db, options = {}) {
|
|
|
259
271
|
},
|
|
260
272
|
async settle(key, disposition) {
|
|
261
273
|
(0, import_common.assertDeliveryKey)(key);
|
|
274
|
+
assertConfiguredScope(key);
|
|
262
275
|
(0, import_common.assertWebhookDisposition)(disposition);
|
|
263
276
|
await query(
|
|
264
277
|
"settle",
|
|
@@ -271,12 +284,14 @@ function pgWebhookDeliveryRecoveryBackend(db, options = {}) {
|
|
|
271
284
|
},
|
|
272
285
|
async claimPending({ ownerToken, leaseMs, limit }) {
|
|
273
286
|
(0, import_common.assertLeaseControls)(ownerToken, leaseMs, limit);
|
|
287
|
+
const scopePredicate = options.claimScope ? "AND publisher_scope = $4 AND tenant_scope = $5" : "";
|
|
274
288
|
const result = await query(
|
|
275
289
|
"claimPending",
|
|
276
290
|
`WITH candidates AS (
|
|
277
291
|
SELECT publisher_scope, tenant_scope, delivery_id
|
|
278
292
|
FROM ${table}
|
|
279
293
|
WHERE state = 'pending'
|
|
294
|
+
${scopePredicate}
|
|
280
295
|
AND next_attempt_at <= clock_timestamp()
|
|
281
296
|
AND (lease_expires_at IS NULL OR lease_expires_at < clock_timestamp())
|
|
282
297
|
ORDER BY next_attempt_at, created_at
|
|
@@ -299,12 +314,18 @@ function pgWebhookDeliveryRecoveryBackend(db, options = {}) {
|
|
|
299
314
|
FLOOR(EXTRACT(EPOCH FROM outbox.next_attempt_at) * 1000)::bigint AS next_attempt_at_ms,
|
|
300
315
|
outbox.lease_owner, outbox.lease_version,
|
|
301
316
|
FLOOR(EXTRACT(EPOCH FROM outbox.lease_expires_at) * 1000)::bigint AS lease_expires_at_ms`,
|
|
302
|
-
[
|
|
317
|
+
[
|
|
318
|
+
ownerToken,
|
|
319
|
+
leaseMs,
|
|
320
|
+
limit,
|
|
321
|
+
...options.claimScope ? [options.claimScope.publisherScope, options.claimScope.tenantScope] : []
|
|
322
|
+
]
|
|
303
323
|
);
|
|
304
324
|
return result.rows.map(rowToRecoveryRecord);
|
|
305
325
|
},
|
|
306
326
|
async renew(lease, leaseMs) {
|
|
307
327
|
(0, import_common.assertDeliveryKey)(lease.key);
|
|
328
|
+
assertConfiguredScope(lease.key);
|
|
308
329
|
(0, import_common.assertLeaseControls)(lease.leaseOwner, leaseMs);
|
|
309
330
|
const result = await query(
|
|
310
331
|
"renew",
|
|
@@ -326,6 +347,7 @@ function pgWebhookDeliveryRecoveryBackend(db, options = {}) {
|
|
|
326
347
|
},
|
|
327
348
|
async release(lease, retryAfterMs) {
|
|
328
349
|
(0, import_common.assertDeliveryKey)(lease.key);
|
|
350
|
+
assertConfiguredScope(lease.key);
|
|
329
351
|
(0, import_common.assertLeaseControls)(lease.leaseOwner, 1);
|
|
330
352
|
(0, import_common.assertRetryAfterMs)(retryAfterMs);
|
|
331
353
|
const result = await query(
|
|
@@ -349,6 +371,7 @@ function pgWebhookDeliveryRecoveryBackend(db, options = {}) {
|
|
|
349
371
|
},
|
|
350
372
|
async settleLease(lease, disposition) {
|
|
351
373
|
(0, import_common.assertDeliveryKey)(lease.key);
|
|
374
|
+
assertConfiguredScope(lease.key);
|
|
352
375
|
(0, import_common.assertLeaseControls)(lease.leaseOwner, 1);
|
|
353
376
|
(0, import_common.assertWebhookDisposition)(disposition);
|
|
354
377
|
const result = await query(
|
|
@@ -70,6 +70,9 @@ CREATE TABLE IF NOT EXISTS ${table} (
|
|
|
70
70
|
CONSTRAINT ${raw}_valid_disposition CHECK (disposition IS NULL OR disposition IN ('delivered', 'terminal'))
|
|
71
71
|
);
|
|
72
72
|
|
|
73
|
+
ALTER TABLE ${table}
|
|
74
|
+
ADD COLUMN IF NOT EXISTS intent_fingerprint TEXT;
|
|
75
|
+
|
|
73
76
|
CREATE INDEX IF NOT EXISTS idx_${raw}_pending
|
|
74
77
|
ON ${table}(next_attempt_at, lease_expires_at) WHERE state = 'pending';
|
|
75
78
|
`.trim();
|
|
@@ -150,6 +153,14 @@ function pgWebhookDeliveryRecoveryBackend(db, options = {}) {
|
|
|
150
153
|
const tableName = options.tableName ?? DEFAULT_OUTBOX_TABLE;
|
|
151
154
|
const table = quoteWebhookTable(tableName);
|
|
152
155
|
assertPgDeploymentNamespace("pgWebhookDeliveryRecoveryBackend", tableName, DEFAULT_OUTBOX_TABLE, options);
|
|
156
|
+
if (options.claimScope) {
|
|
157
|
+
assertDeliveryKey({ ...options.claimScope, deliveryId: "claim-scope-validation" });
|
|
158
|
+
}
|
|
159
|
+
const assertConfiguredScope = (key) => {
|
|
160
|
+
if (options.claimScope && (key.publisherScope !== options.claimScope.publisherScope || key.tenantScope !== options.claimScope.tenantScope)) {
|
|
161
|
+
throw new Error("Webhook recovery key is outside the configured claim scope");
|
|
162
|
+
}
|
|
163
|
+
};
|
|
153
164
|
async function query(operation, text, values) {
|
|
154
165
|
try {
|
|
155
166
|
return await db.query(text, values);
|
|
@@ -163,7 +174,7 @@ function pgWebhookDeliveryRecoveryBackend(db, options = {}) {
|
|
|
163
174
|
try {
|
|
164
175
|
await db.query(
|
|
165
176
|
`SELECT publisher_scope, tenant_scope, delivery_id, snapshot, snapshot_fingerprint,
|
|
166
|
-
storage_fingerprint, state, disposition, attempt_count, next_attempt_at, lease_owner,
|
|
177
|
+
storage_fingerprint, intent_fingerprint, state, disposition, attempt_count, next_attempt_at, lease_owner,
|
|
167
178
|
lease_claim_id, lease_version, lease_expires_at FROM ${table} LIMIT 0`
|
|
168
179
|
);
|
|
169
180
|
} catch (cause) {
|
|
@@ -175,6 +186,7 @@ function pgWebhookDeliveryRecoveryBackend(db, options = {}) {
|
|
|
175
186
|
},
|
|
176
187
|
async checkpoint(key, snapshot, snapshotFingerprint, storageFingerprint, initialLease) {
|
|
177
188
|
assertDeliveryKey(key);
|
|
189
|
+
assertConfiguredScope(key);
|
|
178
190
|
assertLeaseControls(initialLease.ownerToken, initialLease.leaseMs);
|
|
179
191
|
const leaseClaimId = randomUUID();
|
|
180
192
|
const result = await query(
|
|
@@ -240,6 +252,7 @@ function pgWebhookDeliveryRecoveryBackend(db, options = {}) {
|
|
|
240
252
|
},
|
|
241
253
|
async settle(key, disposition) {
|
|
242
254
|
assertDeliveryKey(key);
|
|
255
|
+
assertConfiguredScope(key);
|
|
243
256
|
assertWebhookDisposition(disposition);
|
|
244
257
|
await query(
|
|
245
258
|
"settle",
|
|
@@ -252,12 +265,14 @@ function pgWebhookDeliveryRecoveryBackend(db, options = {}) {
|
|
|
252
265
|
},
|
|
253
266
|
async claimPending({ ownerToken, leaseMs, limit }) {
|
|
254
267
|
assertLeaseControls(ownerToken, leaseMs, limit);
|
|
268
|
+
const scopePredicate = options.claimScope ? "AND publisher_scope = $4 AND tenant_scope = $5" : "";
|
|
255
269
|
const result = await query(
|
|
256
270
|
"claimPending",
|
|
257
271
|
`WITH candidates AS (
|
|
258
272
|
SELECT publisher_scope, tenant_scope, delivery_id
|
|
259
273
|
FROM ${table}
|
|
260
274
|
WHERE state = 'pending'
|
|
275
|
+
${scopePredicate}
|
|
261
276
|
AND next_attempt_at <= clock_timestamp()
|
|
262
277
|
AND (lease_expires_at IS NULL OR lease_expires_at < clock_timestamp())
|
|
263
278
|
ORDER BY next_attempt_at, created_at
|
|
@@ -280,12 +295,18 @@ function pgWebhookDeliveryRecoveryBackend(db, options = {}) {
|
|
|
280
295
|
FLOOR(EXTRACT(EPOCH FROM outbox.next_attempt_at) * 1000)::bigint AS next_attempt_at_ms,
|
|
281
296
|
outbox.lease_owner, outbox.lease_version,
|
|
282
297
|
FLOOR(EXTRACT(EPOCH FROM outbox.lease_expires_at) * 1000)::bigint AS lease_expires_at_ms`,
|
|
283
|
-
[
|
|
298
|
+
[
|
|
299
|
+
ownerToken,
|
|
300
|
+
leaseMs,
|
|
301
|
+
limit,
|
|
302
|
+
...options.claimScope ? [options.claimScope.publisherScope, options.claimScope.tenantScope] : []
|
|
303
|
+
]
|
|
284
304
|
);
|
|
285
305
|
return result.rows.map(rowToRecoveryRecord);
|
|
286
306
|
},
|
|
287
307
|
async renew(lease, leaseMs) {
|
|
288
308
|
assertDeliveryKey(lease.key);
|
|
309
|
+
assertConfiguredScope(lease.key);
|
|
289
310
|
assertLeaseControls(lease.leaseOwner, leaseMs);
|
|
290
311
|
const result = await query(
|
|
291
312
|
"renew",
|
|
@@ -307,6 +328,7 @@ function pgWebhookDeliveryRecoveryBackend(db, options = {}) {
|
|
|
307
328
|
},
|
|
308
329
|
async release(lease, retryAfterMs) {
|
|
309
330
|
assertDeliveryKey(lease.key);
|
|
331
|
+
assertConfiguredScope(lease.key);
|
|
310
332
|
assertLeaseControls(lease.leaseOwner, 1);
|
|
311
333
|
assertRetryAfterMs(retryAfterMs);
|
|
312
334
|
const result = await query(
|
|
@@ -330,6 +352,7 @@ function pgWebhookDeliveryRecoveryBackend(db, options = {}) {
|
|
|
330
352
|
},
|
|
331
353
|
async settleLease(lease, disposition) {
|
|
332
354
|
assertDeliveryKey(lease.key);
|
|
355
|
+
assertConfiguredScope(lease.key);
|
|
333
356
|
assertLeaseControls(lease.leaseOwner, 1);
|
|
334
357
|
assertWebhookDisposition(disposition);
|
|
335
358
|
const result = await query(
|
|
@@ -10,9 +10,23 @@ export interface WebhookAuthenticationAdapter {
|
|
|
10
10
|
protect(authentication: Exclude<WebhookAuthentication, null>, context: Readonly<WebhookAuthenticationContext>): Promise<ProtectedWebhookAuthentication> | ProtectedWebhookAuthentication;
|
|
11
11
|
resolve(protectedValue: unknown, context: Readonly<WebhookAuthenticationContext>): Promise<WebhookAuthentication> | WebhookAuthentication;
|
|
12
12
|
}
|
|
13
|
+
/** Retryable failure while calling an application's KMS/secret adapter. */
|
|
14
|
+
export declare class WebhookAuthenticationProtectionError extends Error {
|
|
15
|
+
readonly name = "WebhookAuthenticationProtectionError";
|
|
16
|
+
}
|
|
17
|
+
/** Retryable failure while resolving protected authentication for delivery. */
|
|
18
|
+
export declare class WebhookAuthenticationResolutionError extends Error {
|
|
19
|
+
readonly name = "WebhookAuthenticationResolutionError";
|
|
20
|
+
}
|
|
13
21
|
export interface WebhookAuthenticationContext {
|
|
14
22
|
key: WebhookDeliveryKey;
|
|
15
23
|
url: string;
|
|
24
|
+
/**
|
|
25
|
+
* Domain-separates task payload validation tokens. Undefined is the
|
|
26
|
+
* original transport-authentication context and is intentionally preserved
|
|
27
|
+
* so pending encrypted snapshots remain decryptable across SDK upgrades.
|
|
28
|
+
*/
|
|
29
|
+
purpose?: 'payload_token';
|
|
16
30
|
snapshotContextFingerprint: string;
|
|
17
31
|
}
|
|
18
32
|
export interface StoredWebhookDeliverySnapshot {
|
|
@@ -25,8 +39,32 @@ export interface StoredWebhookDeliverySnapshot {
|
|
|
25
39
|
protectedValue: unknown;
|
|
26
40
|
fingerprint: string;
|
|
27
41
|
};
|
|
42
|
+
/**
|
|
43
|
+
* A top-level task-webhook `token`, protected independently from transport
|
|
44
|
+
* authentication. The cleartext is restored only after a recovery lease is
|
|
45
|
+
* claimed and is never written to the outbox JSON payload.
|
|
46
|
+
*/
|
|
47
|
+
payloadToken?: {
|
|
48
|
+
kind: 'protected';
|
|
49
|
+
protectedValue: unknown;
|
|
50
|
+
fingerprint: string;
|
|
51
|
+
};
|
|
28
52
|
retries: WebhookDeliverySnapshot['retries'];
|
|
29
53
|
}
|
|
54
|
+
/** Storage-ready snapshot used by transactional outbox coordinators. */
|
|
55
|
+
export interface PreparedWebhookDeliverySnapshot {
|
|
56
|
+
snapshot: StoredWebhookDeliverySnapshot;
|
|
57
|
+
snapshotFingerprint: string;
|
|
58
|
+
storageFingerprint: string;
|
|
59
|
+
}
|
|
60
|
+
export interface PrepareWebhookDeliveryOptions {
|
|
61
|
+
/**
|
|
62
|
+
* Protect and remove the top-level `payload.token` before persistence.
|
|
63
|
+
* This is opt-in because generic webhook payloads may legitimately use a
|
|
64
|
+
* non-secret field with that name.
|
|
65
|
+
*/
|
|
66
|
+
protectPayloadToken?: boolean;
|
|
67
|
+
}
|
|
30
68
|
export interface WebhookRecoveryRecord {
|
|
31
69
|
key: WebhookDeliveryKey;
|
|
32
70
|
snapshot: StoredWebhookDeliverySnapshot;
|
|
@@ -71,6 +109,12 @@ export interface WebhookDeliveryRecoveryBackend {
|
|
|
71
109
|
}
|
|
72
110
|
export interface DurableWebhookDeliveryRecovery extends WebhookDeliveryRecovery {
|
|
73
111
|
probe(): Promise<void>;
|
|
112
|
+
/**
|
|
113
|
+
* Protect and fingerprint a snapshot without writing it. This is reserved
|
|
114
|
+
* for coordinators that insert the returned value in the same database
|
|
115
|
+
* transaction as their domain mutation.
|
|
116
|
+
*/
|
|
117
|
+
prepare(key: Readonly<WebhookDeliveryKey>, snapshot: Readonly<WebhookDeliverySnapshot>, options?: Readonly<PrepareWebhookDeliveryOptions>): Promise<PreparedWebhookDeliverySnapshot>;
|
|
74
118
|
claimPending(options: {
|
|
75
119
|
ownerToken?: string;
|
|
76
120
|
leaseMs?: number;
|
|
@@ -10,9 +10,23 @@ export interface WebhookAuthenticationAdapter {
|
|
|
10
10
|
protect(authentication: Exclude<WebhookAuthentication, null>, context: Readonly<WebhookAuthenticationContext>): Promise<ProtectedWebhookAuthentication> | ProtectedWebhookAuthentication;
|
|
11
11
|
resolve(protectedValue: unknown, context: Readonly<WebhookAuthenticationContext>): Promise<WebhookAuthentication> | WebhookAuthentication;
|
|
12
12
|
}
|
|
13
|
+
/** Retryable failure while calling an application's KMS/secret adapter. */
|
|
14
|
+
export declare class WebhookAuthenticationProtectionError extends Error {
|
|
15
|
+
readonly name = "WebhookAuthenticationProtectionError";
|
|
16
|
+
}
|
|
17
|
+
/** Retryable failure while resolving protected authentication for delivery. */
|
|
18
|
+
export declare class WebhookAuthenticationResolutionError extends Error {
|
|
19
|
+
readonly name = "WebhookAuthenticationResolutionError";
|
|
20
|
+
}
|
|
13
21
|
export interface WebhookAuthenticationContext {
|
|
14
22
|
key: WebhookDeliveryKey;
|
|
15
23
|
url: string;
|
|
24
|
+
/**
|
|
25
|
+
* Domain-separates task payload validation tokens. Undefined is the
|
|
26
|
+
* original transport-authentication context and is intentionally preserved
|
|
27
|
+
* so pending encrypted snapshots remain decryptable across SDK upgrades.
|
|
28
|
+
*/
|
|
29
|
+
purpose?: 'payload_token';
|
|
16
30
|
snapshotContextFingerprint: string;
|
|
17
31
|
}
|
|
18
32
|
export interface StoredWebhookDeliverySnapshot {
|
|
@@ -25,8 +39,32 @@ export interface StoredWebhookDeliverySnapshot {
|
|
|
25
39
|
protectedValue: unknown;
|
|
26
40
|
fingerprint: string;
|
|
27
41
|
};
|
|
42
|
+
/**
|
|
43
|
+
* A top-level task-webhook `token`, protected independently from transport
|
|
44
|
+
* authentication. The cleartext is restored only after a recovery lease is
|
|
45
|
+
* claimed and is never written to the outbox JSON payload.
|
|
46
|
+
*/
|
|
47
|
+
payloadToken?: {
|
|
48
|
+
kind: 'protected';
|
|
49
|
+
protectedValue: unknown;
|
|
50
|
+
fingerprint: string;
|
|
51
|
+
};
|
|
28
52
|
retries: WebhookDeliverySnapshot['retries'];
|
|
29
53
|
}
|
|
54
|
+
/** Storage-ready snapshot used by transactional outbox coordinators. */
|
|
55
|
+
export interface PreparedWebhookDeliverySnapshot {
|
|
56
|
+
snapshot: StoredWebhookDeliverySnapshot;
|
|
57
|
+
snapshotFingerprint: string;
|
|
58
|
+
storageFingerprint: string;
|
|
59
|
+
}
|
|
60
|
+
export interface PrepareWebhookDeliveryOptions {
|
|
61
|
+
/**
|
|
62
|
+
* Protect and remove the top-level `payload.token` before persistence.
|
|
63
|
+
* This is opt-in because generic webhook payloads may legitimately use a
|
|
64
|
+
* non-secret field with that name.
|
|
65
|
+
*/
|
|
66
|
+
protectPayloadToken?: boolean;
|
|
67
|
+
}
|
|
30
68
|
export interface WebhookRecoveryRecord {
|
|
31
69
|
key: WebhookDeliveryKey;
|
|
32
70
|
snapshot: StoredWebhookDeliverySnapshot;
|
|
@@ -71,6 +109,12 @@ export interface WebhookDeliveryRecoveryBackend {
|
|
|
71
109
|
}
|
|
72
110
|
export interface DurableWebhookDeliveryRecovery extends WebhookDeliveryRecovery {
|
|
73
111
|
probe(): Promise<void>;
|
|
112
|
+
/**
|
|
113
|
+
* Protect and fingerprint a snapshot without writing it. This is reserved
|
|
114
|
+
* for coordinators that insert the returned value in the same database
|
|
115
|
+
* transaction as their domain mutation.
|
|
116
|
+
*/
|
|
117
|
+
prepare(key: Readonly<WebhookDeliveryKey>, snapshot: Readonly<WebhookDeliverySnapshot>, options?: Readonly<PrepareWebhookDeliveryOptions>): Promise<PreparedWebhookDeliverySnapshot>;
|
|
74
118
|
claimPending(options: {
|
|
75
119
|
ownerToken?: string;
|
|
76
120
|
leaseMs?: number;
|
|
@@ -18,6 +18,8 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var recovery_exports = {};
|
|
20
20
|
__export(recovery_exports, {
|
|
21
|
+
WebhookAuthenticationProtectionError: () => WebhookAuthenticationProtectionError,
|
|
22
|
+
WebhookAuthenticationResolutionError: () => WebhookAuthenticationResolutionError,
|
|
21
23
|
createWebhookDeliveryRecovery: () => createWebhookDeliveryRecovery,
|
|
22
24
|
memoryWebhookDeliveryRecoveryBackend: () => memoryWebhookDeliveryRecoveryBackend,
|
|
23
25
|
pollWebhookDeliveryRecovery: () => pollWebhookDeliveryRecovery
|
|
@@ -26,6 +28,12 @@ module.exports = __toCommonJS(recovery_exports);
|
|
|
26
28
|
var import_node_crypto = require("node:crypto");
|
|
27
29
|
var import_jcs = require('../../utils/jcs.js');
|
|
28
30
|
var import_common = require('./common.js');
|
|
31
|
+
class WebhookAuthenticationProtectionError extends Error {
|
|
32
|
+
name = "WebhookAuthenticationProtectionError";
|
|
33
|
+
}
|
|
34
|
+
class WebhookAuthenticationResolutionError extends Error {
|
|
35
|
+
name = "WebhookAuthenticationResolutionError";
|
|
36
|
+
}
|
|
29
37
|
function memoryWebhookDeliveryRecoveryBackend(options = {}) {
|
|
30
38
|
const records = /* @__PURE__ */ new Map();
|
|
31
39
|
const now = options.now ?? Date.now;
|
|
@@ -135,13 +143,25 @@ function createWebhookDeliveryRecovery(options) {
|
|
|
135
143
|
return {
|
|
136
144
|
durability: "durable",
|
|
137
145
|
probe: () => options.backend.probe(),
|
|
146
|
+
async prepare(key, snapshot, prepareOptions) {
|
|
147
|
+
(0, import_common.assertDeliveryKey)(key);
|
|
148
|
+
const stored = await protectSnapshot(
|
|
149
|
+
snapshot,
|
|
150
|
+
key,
|
|
151
|
+
options.authenticationAdapter,
|
|
152
|
+
prepareOptions?.protectPayloadToken === true
|
|
153
|
+
);
|
|
154
|
+
assertStoredSnapshotSize(stored, maxSnapshotBytes);
|
|
155
|
+
return {
|
|
156
|
+
snapshot: stored,
|
|
157
|
+
snapshotFingerprint: snapshotFingerprint(stored),
|
|
158
|
+
storageFingerprint: (0, import_jcs.canonicalJsonSha256)(stored)
|
|
159
|
+
};
|
|
160
|
+
},
|
|
138
161
|
async checkpoint(key, snapshot) {
|
|
139
162
|
(0, import_common.assertDeliveryKey)(key);
|
|
140
|
-
const stored = await protectSnapshot(snapshot, key, options.authenticationAdapter);
|
|
141
|
-
|
|
142
|
-
if (storedBytes > maxSnapshotBytes) {
|
|
143
|
-
throw new TypeError(`Webhook recovery snapshot exceeds maxSnapshotBytes (${maxSnapshotBytes})`);
|
|
144
|
-
}
|
|
163
|
+
const stored = await protectSnapshot(snapshot, key, options.authenticationAdapter, false);
|
|
164
|
+
assertStoredSnapshotSize(stored, maxSnapshotBytes);
|
|
145
165
|
const fingerprint = snapshotFingerprint(stored);
|
|
146
166
|
const storageFingerprint = (0, import_jcs.canonicalJsonSha256)(stored);
|
|
147
167
|
const ownerToken = (0, import_node_crypto.randomUUID)();
|
|
@@ -313,59 +333,101 @@ function assertPollOutcome(outcome) {
|
|
|
313
333
|
throw new TypeError("Webhook recovery deliver() returned an invalid disposition");
|
|
314
334
|
}
|
|
315
335
|
}
|
|
316
|
-
async function protectSnapshot(snapshot, key, adapter) {
|
|
336
|
+
async function protectSnapshot(snapshot, key, adapter, protectPayloadToken) {
|
|
337
|
+
const payload = structuredClone(snapshot.payload);
|
|
338
|
+
const cleartextPayloadToken = protectPayloadToken && typeof payload.token === "string" ? payload.token : void 0;
|
|
339
|
+
if (cleartextPayloadToken !== void 0) delete payload.token;
|
|
317
340
|
const base = {
|
|
318
341
|
url: snapshot.url,
|
|
319
|
-
payload
|
|
342
|
+
payload,
|
|
320
343
|
retries: { ...snapshot.retries }
|
|
321
344
|
};
|
|
322
345
|
(0, import_jcs.canonicalJsonSha256)(base);
|
|
323
|
-
if (snapshot.authentication
|
|
324
|
-
if (!adapter) {
|
|
346
|
+
if ((snapshot.authentication !== null || cleartextPayloadToken !== void 0) && !adapter) {
|
|
325
347
|
throw new TypeError(
|
|
326
|
-
"Durable webhook recovery requires authenticationAdapter when bearer or
|
|
348
|
+
"Durable webhook recovery requires authenticationAdapter when bearer/HMAC authentication or a payload token is present"
|
|
327
349
|
);
|
|
328
350
|
}
|
|
329
|
-
const
|
|
330
|
-
const protectedAuth = await adapter.protect(structuredClone(snapshot.authentication), context);
|
|
331
|
-
if (!protectedAuth || typeof protectedAuth.fingerprint !== "string" || protectedAuth.fingerprint.length < 16) {
|
|
332
|
-
throw new TypeError(
|
|
333
|
-
"WebhookAuthenticationAdapter.protect() must return a stable fingerprint of at least 16 characters"
|
|
334
|
-
);
|
|
335
|
-
}
|
|
336
|
-
(0, import_jcs.canonicalJsonSha256)(protectedAuth.protectedValue);
|
|
337
|
-
return {
|
|
351
|
+
const stored = {
|
|
338
352
|
...base,
|
|
339
|
-
authentication: {
|
|
340
|
-
kind: "protected",
|
|
341
|
-
protectedValue: structuredClone(protectedAuth.protectedValue),
|
|
342
|
-
fingerprint: protectedAuth.fingerprint
|
|
343
|
-
}
|
|
353
|
+
authentication: { kind: "none" }
|
|
344
354
|
};
|
|
355
|
+
if (snapshot.authentication !== null) {
|
|
356
|
+
const protectedAuth = await protectAuthentication(
|
|
357
|
+
adapter,
|
|
358
|
+
structuredClone(snapshot.authentication),
|
|
359
|
+
authenticationContext(key, base)
|
|
360
|
+
);
|
|
361
|
+
stored.authentication = { kind: "protected", ...protectedAuth };
|
|
362
|
+
}
|
|
363
|
+
if (cleartextPayloadToken !== void 0) {
|
|
364
|
+
const protectedToken = await protectAuthentication(
|
|
365
|
+
adapter,
|
|
366
|
+
{ type: "bearer", token: cleartextPayloadToken },
|
|
367
|
+
authenticationContext(key, base, "payload_token")
|
|
368
|
+
);
|
|
369
|
+
stored.payloadToken = { kind: "protected", ...protectedToken };
|
|
370
|
+
}
|
|
371
|
+
return stored;
|
|
345
372
|
}
|
|
346
373
|
async function resolveSnapshot(snapshot, key, adapter) {
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
if (
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
374
|
+
try {
|
|
375
|
+
let authentication = null;
|
|
376
|
+
if (snapshot.authentication.kind === "protected") {
|
|
377
|
+
if (!adapter) throw new Error("Cannot recover protected webhook authentication without authenticationAdapter");
|
|
378
|
+
authentication = await adapter.resolve(
|
|
379
|
+
structuredClone(snapshot.authentication.protectedValue),
|
|
380
|
+
authenticationContext(key, snapshot)
|
|
381
|
+
);
|
|
382
|
+
if (authentication === null)
|
|
383
|
+
throw new Error("WebhookAuthenticationAdapter.resolve() returned null for protected state");
|
|
384
|
+
}
|
|
385
|
+
const payload = structuredClone(snapshot.payload);
|
|
386
|
+
if (snapshot.payloadToken) {
|
|
387
|
+
if (!adapter) throw new Error("Cannot recover protected webhook payload token without authenticationAdapter");
|
|
388
|
+
const resolved = await adapter.resolve(
|
|
389
|
+
structuredClone(snapshot.payloadToken.protectedValue),
|
|
390
|
+
authenticationContext(key, snapshot, "payload_token")
|
|
391
|
+
);
|
|
392
|
+
if (resolved?.type !== "bearer" || typeof resolved.token !== "string") {
|
|
393
|
+
throw new Error("WebhookAuthenticationAdapter.resolve() returned an invalid protected payload token");
|
|
394
|
+
}
|
|
395
|
+
payload.token = resolved.token;
|
|
396
|
+
}
|
|
397
|
+
return {
|
|
398
|
+
url: snapshot.url,
|
|
399
|
+
payload,
|
|
400
|
+
authentication,
|
|
401
|
+
retries: { ...snapshot.retries }
|
|
402
|
+
};
|
|
403
|
+
} catch (cause) {
|
|
404
|
+
if (cause instanceof WebhookAuthenticationResolutionError) throw cause;
|
|
405
|
+
throw new WebhookAuthenticationResolutionError("Webhook authentication resolution failed", { cause });
|
|
356
406
|
}
|
|
357
|
-
return {
|
|
358
|
-
url: snapshot.url,
|
|
359
|
-
payload: structuredClone(snapshot.payload),
|
|
360
|
-
authentication,
|
|
361
|
-
retries: { ...snapshot.retries }
|
|
362
|
-
};
|
|
363
407
|
}
|
|
364
|
-
function authenticationContext(key, snapshot) {
|
|
365
|
-
|
|
408
|
+
function authenticationContext(key, snapshot, purpose) {
|
|
409
|
+
const base = {
|
|
366
410
|
key: { ...key },
|
|
367
|
-
url: snapshot.url
|
|
411
|
+
url: snapshot.url
|
|
412
|
+
};
|
|
413
|
+
if (purpose === void 0) {
|
|
414
|
+
return {
|
|
415
|
+
...base,
|
|
416
|
+
// This is the exact pre-payload-token context hash. Do not change it:
|
|
417
|
+
// applications may bind KMS AAD to this value for pending snapshots.
|
|
418
|
+
snapshotContextFingerprint: (0, import_jcs.canonicalJsonSha256)({
|
|
419
|
+
key,
|
|
420
|
+
url: snapshot.url,
|
|
421
|
+
payload: snapshot.payload,
|
|
422
|
+
retries: snapshot.retries
|
|
423
|
+
})
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
return {
|
|
427
|
+
...base,
|
|
428
|
+
purpose,
|
|
368
429
|
snapshotContextFingerprint: (0, import_jcs.canonicalJsonSha256)({
|
|
430
|
+
purpose,
|
|
369
431
|
key,
|
|
370
432
|
url: snapshot.url,
|
|
371
433
|
payload: snapshot.payload,
|
|
@@ -421,9 +483,48 @@ function snapshotFingerprint(snapshot) {
|
|
|
421
483
|
url: snapshot.url,
|
|
422
484
|
payload: snapshot.payload,
|
|
423
485
|
retries: snapshot.retries,
|
|
424
|
-
authentication: snapshot.authentication.kind === "none" ? { kind: "none" } : { kind: "protected", fingerprint: snapshot.authentication.fingerprint }
|
|
486
|
+
authentication: snapshot.authentication.kind === "none" ? { kind: "none" } : { kind: "protected", fingerprint: snapshot.authentication.fingerprint },
|
|
487
|
+
...snapshot.payloadToken && { payloadToken: { fingerprint: snapshot.payloadToken.fingerprint } }
|
|
425
488
|
});
|
|
426
489
|
}
|
|
490
|
+
async function protectAuthentication(adapter, authentication, context) {
|
|
491
|
+
let protectedAuth;
|
|
492
|
+
try {
|
|
493
|
+
protectedAuth = await adapter.protect(authentication, context);
|
|
494
|
+
} catch (cause) {
|
|
495
|
+
throw new WebhookAuthenticationProtectionError("Webhook authentication protection failed", { cause });
|
|
496
|
+
}
|
|
497
|
+
if (!protectedAuth || typeof protectedAuth.fingerprint !== "string" || protectedAuth.fingerprint.length < 16) {
|
|
498
|
+
throw new TypeError(
|
|
499
|
+
"WebhookAuthenticationAdapter.protect() must return a stable fingerprint of at least 16 characters"
|
|
500
|
+
);
|
|
501
|
+
}
|
|
502
|
+
(0, import_jcs.canonicalJsonSha256)(protectedAuth.protectedValue);
|
|
503
|
+
const cleartext = authentication.type === "bearer" ? authentication.token : authentication.secret;
|
|
504
|
+
if (protectedValueContainsSecret(protectedAuth.protectedValue, cleartext) || protectedAuth.fingerprint.includes(cleartext)) {
|
|
505
|
+
throw new TypeError("WebhookAuthenticationAdapter.protect() returned durable state containing cleartext");
|
|
506
|
+
}
|
|
507
|
+
return {
|
|
508
|
+
protectedValue: structuredClone(protectedAuth.protectedValue),
|
|
509
|
+
fingerprint: protectedAuth.fingerprint
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
function protectedValueContainsSecret(value, cleartext) {
|
|
513
|
+
if (typeof value === "string") return value.includes(cleartext);
|
|
514
|
+
if (Array.isArray(value)) return value.some((item) => protectedValueContainsSecret(item, cleartext));
|
|
515
|
+
if (value && typeof value === "object") {
|
|
516
|
+
return Object.entries(value).some(
|
|
517
|
+
([key, item]) => key.includes(cleartext) || protectedValueContainsSecret(item, cleartext)
|
|
518
|
+
);
|
|
519
|
+
}
|
|
520
|
+
return false;
|
|
521
|
+
}
|
|
522
|
+
function assertStoredSnapshotSize(snapshot, maxSnapshotBytes) {
|
|
523
|
+
const storedBytes = Buffer.byteLength(JSON.stringify(snapshot));
|
|
524
|
+
if (storedBytes > maxSnapshotBytes) {
|
|
525
|
+
throw new TypeError(`Webhook recovery snapshot exceeds maxSnapshotBytes (${maxSnapshotBytes})`);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
427
528
|
function assertLeaseMs(value) {
|
|
428
529
|
if (!Number.isSafeInteger(value) || value < 1e3 || value > 36e5) {
|
|
429
530
|
throw new TypeError("leaseMs must be an integer from 1000 through 3600000");
|
|
@@ -431,6 +532,8 @@ function assertLeaseMs(value) {
|
|
|
431
532
|
}
|
|
432
533
|
// Annotate the CommonJS export names for ESM import in node:
|
|
433
534
|
0 && (module.exports = {
|
|
535
|
+
WebhookAuthenticationProtectionError,
|
|
536
|
+
WebhookAuthenticationResolutionError,
|
|
434
537
|
createWebhookDeliveryRecovery,
|
|
435
538
|
memoryWebhookDeliveryRecoveryBackend,
|
|
436
539
|
pollWebhookDeliveryRecovery
|