@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
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { canonicalJsonSha256 } from "../../../utils/jcs.mjs";
|
|
3
|
+
import { isAdcpVersionAtLeast, isValidAdcpVersion } from "../../../utils/adcp-version-config.mjs";
|
|
4
|
+
import { sanitizeStructuredAdcpError } from "../../errors.mjs";
|
|
5
|
+
import { quoteWebhookTable } from "../../webhook-delivery/common.mjs";
|
|
6
|
+
import {
|
|
7
|
+
createWebhookDeliveryRecovery,
|
|
8
|
+
WebhookAuthenticationProtectionError
|
|
9
|
+
} from "../../webhook-delivery/recovery.mjs";
|
|
10
|
+
import { pgWebhookDeliveryRecoveryBackend } from "../../webhook-delivery/pg.mjs";
|
|
11
|
+
import { protocolForTool, SPEC_WEBHOOK_TASK_TYPES } from "./protocol-for-tool.mjs";
|
|
12
|
+
import {
|
|
13
|
+
_postgresTaskRegistryBinding
|
|
14
|
+
} from "./postgres-task-registry.mjs";
|
|
15
|
+
import { sanitizeTaskResultForWire } from "./task-registry.mjs";
|
|
16
|
+
class TaskPushSettlementConfigurationError extends Error {
|
|
17
|
+
name = "TaskPushSettlementConfigurationError";
|
|
18
|
+
}
|
|
19
|
+
const TERMINAL = /* @__PURE__ */ new Set(["completed", "failed", "rejected", "canceled"]);
|
|
20
|
+
const MAX_RESULT_BYTES = 4 * 1024 * 1024;
|
|
21
|
+
const TOKEN_CONTROL_CHAR_RE = /[\x00-\x1f\x7f]/;
|
|
22
|
+
function createPostgresTaskSettlementCoordinator(options) {
|
|
23
|
+
const binding = _postgresTaskRegistryBinding(options.registry);
|
|
24
|
+
if (!binding) {
|
|
25
|
+
throw new TypeError("createPostgresTaskSettlementCoordinator requires a registry from createPostgresTaskRegistry");
|
|
26
|
+
}
|
|
27
|
+
const pool = binding.pool;
|
|
28
|
+
if (typeof pool.connect !== "function") {
|
|
29
|
+
throw new TypeError(
|
|
30
|
+
"Crash-safe task settlement requires a pg Pool with connect(); a query-only adapter cannot own a transaction"
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
if (typeof options.registry.registryId !== "string" || options.registry.registryId.length === 0) {
|
|
34
|
+
throw new TypeError("Crash-safe task settlement requires task registry storageId/registryId binding");
|
|
35
|
+
}
|
|
36
|
+
if (typeof options.publisherScope !== "string" || options.publisherScope.length === 0) {
|
|
37
|
+
throw new TypeError("publisherScope must be a non-empty string");
|
|
38
|
+
}
|
|
39
|
+
const outboxOptions = options.outbox ?? {};
|
|
40
|
+
const outboxTable = quoteWebhookTable(outboxOptions.tableName ?? "adcp_webhook_outbox");
|
|
41
|
+
const claimScope = {
|
|
42
|
+
publisherScope: options.publisherScope,
|
|
43
|
+
tenantScope: stableRegistryScope(options.registry.registryId, binding.namespace)
|
|
44
|
+
};
|
|
45
|
+
const backend = pgWebhookDeliveryRecoveryBackend(binding.pool, { ...outboxOptions, claimScope });
|
|
46
|
+
const recovery = createWebhookDeliveryRecovery({
|
|
47
|
+
...options.recovery,
|
|
48
|
+
backend,
|
|
49
|
+
...options.authenticationAdapter && { authenticationAdapter: options.authenticationAdapter }
|
|
50
|
+
});
|
|
51
|
+
const retries = resolveRetries(options.retries);
|
|
52
|
+
return {
|
|
53
|
+
durability: "durable",
|
|
54
|
+
recovery,
|
|
55
|
+
async settle(ref, terminal, push) {
|
|
56
|
+
if (ref.registryId !== options.registry.registryId) {
|
|
57
|
+
return { outcome: "not_found_in_scope", delivery: "not_applicable" };
|
|
58
|
+
}
|
|
59
|
+
let client;
|
|
60
|
+
try {
|
|
61
|
+
client = await pool.connect();
|
|
62
|
+
await client.query("BEGIN");
|
|
63
|
+
const locked = await client.query(
|
|
64
|
+
`SELECT tool, status, result, error, has_webhook
|
|
65
|
+
FROM ${binding.tableName}
|
|
66
|
+
WHERE task_id = $1 AND registry_namespace = $2 AND account_id = $3 AND owner_scope = $4
|
|
67
|
+
FOR UPDATE`,
|
|
68
|
+
[ref.taskId, binding.namespace, ref.accountId, ref.ownerScope]
|
|
69
|
+
);
|
|
70
|
+
if (locked.rows.length === 0) {
|
|
71
|
+
await client.query("ROLLBACK");
|
|
72
|
+
return { outcome: "not_found_in_scope", delivery: "not_applicable" };
|
|
73
|
+
}
|
|
74
|
+
const row = locked.rows[0];
|
|
75
|
+
validatePush(push);
|
|
76
|
+
if (row.has_webhook !== true) {
|
|
77
|
+
throw new TaskPushSettlementConfigurationError(
|
|
78
|
+
"Crash-safe push settlement requires a task created with hasWebhook: true"
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
let result;
|
|
82
|
+
let error;
|
|
83
|
+
try {
|
|
84
|
+
result = terminal.status === "completed" ? sanitizeTaskResultForWire(structuredClone(terminal.result), ref) : terminal.result === void 0 ? { errors: [sanitizeStructuredAdcpError(terminal.error)] } : sanitizeTaskResultForWire(structuredClone(terminal.result), ref);
|
|
85
|
+
error = terminal.status === "failed" ? sanitizeStructuredAdcpError(terminal.error) : void 0;
|
|
86
|
+
canonicalJsonSha256({ result, error });
|
|
87
|
+
assertPayloadSize(result, error);
|
|
88
|
+
} catch (cause) {
|
|
89
|
+
if (cause instanceof TaskPushSettlementConfigurationError) throw cause;
|
|
90
|
+
throw new TaskPushSettlementConfigurationError("Task terminal result/error must be serializable JSON", {
|
|
91
|
+
cause
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
const compatible = terminalMatches(row, terminal.status, result, error);
|
|
95
|
+
if (TERMINAL.has(row.status) && !compatible) {
|
|
96
|
+
await client.query("COMMIT");
|
|
97
|
+
return {
|
|
98
|
+
outcome: "already_terminal",
|
|
99
|
+
status: row.status,
|
|
100
|
+
compatibility: "conflicting",
|
|
101
|
+
delivery: "not_applicable"
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
const deliveryKey = {
|
|
105
|
+
...claimScope,
|
|
106
|
+
deliveryId: stableScope("task-webhook", ref)
|
|
107
|
+
};
|
|
108
|
+
const existing = await readOutbox(client, outboxTable, deliveryKey);
|
|
109
|
+
if (TERMINAL.has(row.status) && !existing) {
|
|
110
|
+
throw new TaskPushSettlementConfigurationError(
|
|
111
|
+
"Terminal task has no atomic webhook delivery checkpoint; refusing to create a duplicate notification"
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
let inserted = false;
|
|
115
|
+
let delivery = existing ? deliveryState(existing) : void 0;
|
|
116
|
+
if (!SPEC_WEBHOOK_TASK_TYPES.has(row.tool)) {
|
|
117
|
+
throw new TaskPushSettlementConfigurationError(
|
|
118
|
+
`Task type ${row.tool} cannot be emitted by the closed AdCP task-webhook schema`
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
const existingTimestamp = existing?.state === "pending" ? existing.snapshot.payload.timestamp : void 0;
|
|
122
|
+
const payload = {
|
|
123
|
+
idempotency_key: `pending.${deliveryKey.deliveryId.slice(-48)}`,
|
|
124
|
+
operation_id: resolveOperationId(push, row.tool, ref.taskId),
|
|
125
|
+
task_id: ref.taskId,
|
|
126
|
+
task_type: row.tool,
|
|
127
|
+
status: terminal.status,
|
|
128
|
+
timestamp: typeof existingTimestamp === "string" ? existingTimestamp : (/* @__PURE__ */ new Date()).toISOString(),
|
|
129
|
+
protocol: protocolForTool(row.tool),
|
|
130
|
+
result,
|
|
131
|
+
...push.token !== void 0 && { token: push.token },
|
|
132
|
+
...terminal.status === "failed" && { message: error.message }
|
|
133
|
+
};
|
|
134
|
+
let prepared;
|
|
135
|
+
try {
|
|
136
|
+
prepared = await recovery.prepare(
|
|
137
|
+
deliveryKey,
|
|
138
|
+
{
|
|
139
|
+
url: push.url,
|
|
140
|
+
payload,
|
|
141
|
+
authentication: push.authentication ?? null,
|
|
142
|
+
retries
|
|
143
|
+
},
|
|
144
|
+
{ protectPayloadToken: push.token !== void 0 }
|
|
145
|
+
);
|
|
146
|
+
} catch (cause) {
|
|
147
|
+
if (cause instanceof WebhookAuthenticationProtectionError) throw cause;
|
|
148
|
+
throw new TaskPushSettlementConfigurationError("Terminal webhook delivery configuration is invalid", {
|
|
149
|
+
cause
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
const intentFingerprint = taskPushIntentFingerprint(prepared.snapshot);
|
|
153
|
+
if (existing?.state === "settled") {
|
|
154
|
+
if (!TERMINAL.has(row.status)) {
|
|
155
|
+
throw new Error("Settled webhook outbox row exists for a non-terminal task");
|
|
156
|
+
}
|
|
157
|
+
if (existing.intent_fingerprint && existing.intent_fingerprint !== intentFingerprint) {
|
|
158
|
+
throw new TaskPushSettlementConfigurationError(
|
|
159
|
+
"Terminal webhook delivery identity is already bound to a conflicting route or payload"
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
await client.query("COMMIT");
|
|
163
|
+
return {
|
|
164
|
+
outcome: "already_terminal",
|
|
165
|
+
status: row.status,
|
|
166
|
+
compatibility: "compatible",
|
|
167
|
+
delivery: deliveryState(existing)
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
if (existing && existing.snapshot_fingerprint !== prepared.snapshotFingerprint) {
|
|
171
|
+
throw new TaskPushSettlementConfigurationError(
|
|
172
|
+
"Terminal webhook delivery identity is already bound to a conflicting route or payload"
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
if (!existing) {
|
|
176
|
+
const write = await client.query(
|
|
177
|
+
`INSERT INTO ${outboxTable} (
|
|
178
|
+
publisher_scope, tenant_scope, delivery_id, snapshot, snapshot_fingerprint,
|
|
179
|
+
storage_fingerprint, intent_fingerprint, state, attempt_count, next_attempt_at
|
|
180
|
+
) VALUES ($1, $2, $3, $4::jsonb, $5, $6, $7, 'pending', 0, clock_timestamp())
|
|
181
|
+
ON CONFLICT (publisher_scope, tenant_scope, delivery_id) DO NOTHING`,
|
|
182
|
+
[
|
|
183
|
+
deliveryKey.publisherScope,
|
|
184
|
+
deliveryKey.tenantScope,
|
|
185
|
+
deliveryKey.deliveryId,
|
|
186
|
+
JSON.stringify(prepared.snapshot),
|
|
187
|
+
prepared.snapshotFingerprint,
|
|
188
|
+
prepared.storageFingerprint,
|
|
189
|
+
intentFingerprint
|
|
190
|
+
]
|
|
191
|
+
);
|
|
192
|
+
if ((write.rowCount ?? 0) !== 1) {
|
|
193
|
+
const raced = await readOutbox(client, outboxTable, deliveryKey);
|
|
194
|
+
if (!raced || raced.snapshot_fingerprint !== prepared.snapshotFingerprint) {
|
|
195
|
+
throw new TaskPushSettlementConfigurationError(
|
|
196
|
+
"Terminal webhook delivery identity is already bound to a conflicting route or payload"
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
delivery = deliveryState(raced);
|
|
200
|
+
} else {
|
|
201
|
+
inserted = true;
|
|
202
|
+
delivery = "durably_bound";
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
if (!TERMINAL.has(row.status)) {
|
|
206
|
+
const update = terminal.status === "completed" ? await client.query(
|
|
207
|
+
`UPDATE ${binding.tableName}
|
|
208
|
+
SET status = 'completed', result = $5::jsonb, error = NULL,
|
|
209
|
+
status_message = NULL, updated_at = clock_timestamp()
|
|
210
|
+
WHERE task_id = $1 AND registry_namespace = $2 AND account_id = $3 AND owner_scope = $4`,
|
|
211
|
+
[ref.taskId, binding.namespace, ref.accountId, ref.ownerScope, JSON.stringify(result)]
|
|
212
|
+
) : await client.query(
|
|
213
|
+
`UPDATE ${binding.tableName}
|
|
214
|
+
SET status = 'failed', result = $5::jsonb, error = $6::jsonb,
|
|
215
|
+
status_message = $7, updated_at = clock_timestamp()
|
|
216
|
+
WHERE task_id = $1 AND registry_namespace = $2 AND account_id = $3 AND owner_scope = $4`,
|
|
217
|
+
[
|
|
218
|
+
ref.taskId,
|
|
219
|
+
binding.namespace,
|
|
220
|
+
ref.accountId,
|
|
221
|
+
ref.ownerScope,
|
|
222
|
+
JSON.stringify(result),
|
|
223
|
+
JSON.stringify(error),
|
|
224
|
+
error.message
|
|
225
|
+
]
|
|
226
|
+
);
|
|
227
|
+
if ((update.rowCount ?? 0) !== 1) throw new Error("Task disappeared while holding its settlement lock");
|
|
228
|
+
await client.query("COMMIT");
|
|
229
|
+
return { outcome: "applied", delivery: "durably_bound" };
|
|
230
|
+
}
|
|
231
|
+
await client.query("COMMIT");
|
|
232
|
+
return {
|
|
233
|
+
outcome: "already_terminal",
|
|
234
|
+
status: row.status,
|
|
235
|
+
compatibility: "compatible",
|
|
236
|
+
delivery: inserted ? "durably_bound" : delivery ?? "recoverable"
|
|
237
|
+
};
|
|
238
|
+
} catch (cause) {
|
|
239
|
+
if (client) await rollbackQuietly(client);
|
|
240
|
+
if (cause instanceof TaskPushSettlementConfigurationError) throw cause;
|
|
241
|
+
throw new Error("PostgresTaskSettlementCoordinator.settle: transaction failed", { cause });
|
|
242
|
+
} finally {
|
|
243
|
+
client?.release();
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
async function completeScopedPushTask(coordinator, ref, push, result) {
|
|
249
|
+
return coordinator.settle(ref, { status: "completed", result }, push);
|
|
250
|
+
}
|
|
251
|
+
async function failScopedPushTask(coordinator, ref, push, error, result) {
|
|
252
|
+
return coordinator.settle(ref, { status: "failed", error, ...result !== void 0 && { result } }, push);
|
|
253
|
+
}
|
|
254
|
+
function terminalMatches(row, status, result, error) {
|
|
255
|
+
if (row.status !== status) return false;
|
|
256
|
+
return canonicalJsonSha256(row.result) === canonicalJsonSha256(result) && (status === "completed" || canonicalJsonSha256(row.error) === canonicalJsonSha256(error));
|
|
257
|
+
}
|
|
258
|
+
function stableScope(prefix, ref) {
|
|
259
|
+
const digest = createHash("sha256").update(JSON.stringify([ref.registryId, ref.accountId, ref.ownerScope, ref.taskId])).digest("hex");
|
|
260
|
+
return `${prefix}:${digest}`;
|
|
261
|
+
}
|
|
262
|
+
function stableRegistryScope(registryId, namespace) {
|
|
263
|
+
const digest = createHash("sha256").update(JSON.stringify([registryId, namespace])).digest("hex");
|
|
264
|
+
return `task-registry:${digest}`;
|
|
265
|
+
}
|
|
266
|
+
function taskPushIntentFingerprint(snapshot) {
|
|
267
|
+
const { timestamp: _generatedTimestamp, ...payload } = snapshot.payload;
|
|
268
|
+
return canonicalJsonSha256({
|
|
269
|
+
url: snapshot.url,
|
|
270
|
+
payload,
|
|
271
|
+
retries: snapshot.retries,
|
|
272
|
+
authentication: snapshot.authentication.kind === "none" ? { kind: "none" } : { kind: "protected", fingerprint: snapshot.authentication.fingerprint },
|
|
273
|
+
...snapshot.payloadToken && { payloadToken: { fingerprint: snapshot.payloadToken.fingerprint } }
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
function validatePush(push) {
|
|
277
|
+
if (!push || typeof push !== "object") {
|
|
278
|
+
throw new TaskPushSettlementConfigurationError("push settlement config is required");
|
|
279
|
+
}
|
|
280
|
+
const allowHttp = process.env.NODE_ENV === "test" || process.env.NODE_ENV === "development" || process.env.ADCP_DECISIONING_ALLOW_HTTP_WEBHOOKS === "1";
|
|
281
|
+
let parsedUrl;
|
|
282
|
+
try {
|
|
283
|
+
parsedUrl = typeof push.url === "string" ? new URL(push.url) : void 0;
|
|
284
|
+
} catch {
|
|
285
|
+
}
|
|
286
|
+
if (parsedUrl === void 0 || parsedUrl.hostname.length === 0 || parsedUrl.username.length > 0 || parsedUrl.password.length > 0 || parsedUrl.protocol !== "https:" && !(allowHttp && parsedUrl.protocol === "http:")) {
|
|
287
|
+
throw new TaskPushSettlementConfigurationError(
|
|
288
|
+
"push settlement url must be a request-validated HTTPS destination (HTTP requires the development allowlist)"
|
|
289
|
+
);
|
|
290
|
+
}
|
|
291
|
+
if (push.operationId !== void 0 && (typeof push.operationId !== "string" || !/^[A-Za-z0-9_.:-]{1,255}$/.test(push.operationId))) {
|
|
292
|
+
throw new TaskPushSettlementConfigurationError("push settlement operationId must match /^[A-Za-z0-9_.:-]{1,255}$/");
|
|
293
|
+
}
|
|
294
|
+
if (push.operationId === void 0 && (!isValidAdcpVersion(push.servedAdcpVersion) || isAdcpVersionAtLeast(push.servedAdcpVersion, "3.2.0-beta.5"))) {
|
|
295
|
+
throw new TaskPushSettlementConfigurationError(
|
|
296
|
+
"push settlement operationId is required unless servedAdcpVersion is an explicit valid pre-3.2.0-beta.5 version"
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
if (push.token !== void 0 && (typeof push.token !== "string" || push.token.length < 16 || push.token.length > 4096 || TOKEN_CONTROL_CHAR_RE.test(push.token))) {
|
|
300
|
+
throw new TaskPushSettlementConfigurationError(
|
|
301
|
+
"push settlement token must be a string from 16 through 4096 characters"
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
if (push.authentication !== void 0 && push.authentication !== null) {
|
|
305
|
+
const authentication = push.authentication;
|
|
306
|
+
const validBearer = authentication.type === "bearer" && typeof authentication.token === "string" && authentication.token.length >= 32;
|
|
307
|
+
const validHmac = authentication.type === "hmac_sha256" && typeof authentication.secret === "string" && authentication.secret.length >= 32;
|
|
308
|
+
if (!validBearer && !validHmac) {
|
|
309
|
+
throw new TaskPushSettlementConfigurationError(
|
|
310
|
+
"push settlement authentication must be a WebhookAuthentication value"
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
function resolveOperationId(push, tool, taskId) {
|
|
316
|
+
return push.operationId ?? `${tool}.${taskId}`;
|
|
317
|
+
}
|
|
318
|
+
function resolveRetries(retries) {
|
|
319
|
+
const resolved = {
|
|
320
|
+
maxAttempts: retries?.maxAttempts ?? 5,
|
|
321
|
+
initialDelayMs: retries?.initialDelayMs ?? 1e3,
|
|
322
|
+
maxDelayMs: retries?.maxDelayMs ?? 6e4,
|
|
323
|
+
jitter: retries?.jitter ?? 0.25
|
|
324
|
+
};
|
|
325
|
+
if (!Number.isSafeInteger(resolved.maxAttempts) || resolved.maxAttempts < 1) {
|
|
326
|
+
throw new TypeError("retries.maxAttempts must be an integer of at least 1");
|
|
327
|
+
}
|
|
328
|
+
for (const key of ["initialDelayMs", "maxDelayMs"]) {
|
|
329
|
+
if (!Number.isFinite(resolved[key]) || resolved[key] < 0) {
|
|
330
|
+
throw new TypeError(`retries.${key} must be a finite non-negative number`);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
if (!Number.isFinite(resolved.jitter) || resolved.jitter < 0 || resolved.jitter > 1) {
|
|
334
|
+
throw new TypeError("retries.jitter must be a finite number from 0 through 1");
|
|
335
|
+
}
|
|
336
|
+
return resolved;
|
|
337
|
+
}
|
|
338
|
+
function assertPayloadSize(result, error) {
|
|
339
|
+
const bytes = Buffer.byteLength(JSON.stringify({ result, error }), "utf8");
|
|
340
|
+
if (bytes > MAX_RESULT_BYTES) {
|
|
341
|
+
throw new TaskPushSettlementConfigurationError(`Task result/error JSON exceeds ${MAX_RESULT_BYTES} bytes`);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
async function readOutbox(client, table, key) {
|
|
345
|
+
const found = await client.query(
|
|
346
|
+
`SELECT snapshot, snapshot_fingerprint, intent_fingerprint, state, disposition
|
|
347
|
+
FROM ${table}
|
|
348
|
+
WHERE publisher_scope = $1 AND tenant_scope = $2 AND delivery_id = $3
|
|
349
|
+
FOR UPDATE`,
|
|
350
|
+
[key.publisherScope, key.tenantScope, key.deliveryId]
|
|
351
|
+
);
|
|
352
|
+
return found.rows[0];
|
|
353
|
+
}
|
|
354
|
+
function deliveryState(row) {
|
|
355
|
+
if (row.state !== "settled") return "recoverable";
|
|
356
|
+
return row.disposition === "delivered" ? "delivered" : "terminal";
|
|
357
|
+
}
|
|
358
|
+
async function rollbackQuietly(client) {
|
|
359
|
+
try {
|
|
360
|
+
await client.query("ROLLBACK");
|
|
361
|
+
} catch {
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
export {
|
|
365
|
+
TaskPushSettlementConfigurationError,
|
|
366
|
+
completeScopedPushTask,
|
|
367
|
+
createPostgresTaskSettlementCoordinator,
|
|
368
|
+
failScopedPushTask
|
|
369
|
+
};
|
|
@@ -114,6 +114,8 @@ export interface TaskRegistryListResult<TResult = unknown> {
|
|
|
114
114
|
export interface TaskRegistry {
|
|
115
115
|
/** Confirms that lifecycle methods use the account/principal-scoped v1 signatures. */
|
|
116
116
|
readonly scopeVersion: 1;
|
|
117
|
+
/** Whether stored rows can be reopened by a different process after restart. */
|
|
118
|
+
readonly durability?: 'durable' | 'process-local';
|
|
117
119
|
/**
|
|
118
120
|
* Identity bound into every durable task reference issued by this registry.
|
|
119
121
|
* It is stable for the lifetime of stored records and rotates when a
|
|
@@ -114,6 +114,8 @@ export interface TaskRegistryListResult<TResult = unknown> {
|
|
|
114
114
|
export interface TaskRegistry {
|
|
115
115
|
/** Confirms that lifecycle methods use the account/principal-scoped v1 signatures. */
|
|
116
116
|
readonly scopeVersion: 1;
|
|
117
|
+
/** Whether stored rows can be reopened by a different process after restart. */
|
|
118
|
+
readonly durability?: 'durable' | 'process-local';
|
|
117
119
|
/**
|
|
118
120
|
* Identity bound into every durable task reference issued by this registry.
|
|
119
121
|
* It is stable for the lifetime of stored records and rotates when a
|
|
@@ -107,6 +107,7 @@ function createInMemoryTaskRegistry() {
|
|
|
107
107
|
let registryId = `memory:${(0, import_node_crypto.randomUUID)()}`;
|
|
108
108
|
return {
|
|
109
109
|
scopeVersion: 1,
|
|
110
|
+
durability: "process-local",
|
|
110
111
|
get registryId() {
|
|
111
112
|
return registryId;
|
|
112
113
|
},
|
|
@@ -232,7 +233,7 @@ async function ensureWorkerSettlementIsSafe(registry, ref) {
|
|
|
232
233
|
if (record == null) return { outcome: "not_found_in_scope" };
|
|
233
234
|
if (record.hasWebhook) {
|
|
234
235
|
throw new Error(
|
|
235
|
-
"
|
|
236
|
+
"Registry-only scoped settlement is unavailable for tasks with push notifications. Use createPostgresTaskSettlementCoordinator() with completeScopedPushTask()/failScopedPushTask() for crash-safe PostgreSQL settlement."
|
|
236
237
|
);
|
|
237
238
|
}
|
|
238
239
|
return void 0;
|
|
@@ -77,6 +77,7 @@ function createInMemoryTaskRegistry() {
|
|
|
77
77
|
let registryId = `memory:${randomUUID()}`;
|
|
78
78
|
return {
|
|
79
79
|
scopeVersion: 1,
|
|
80
|
+
durability: "process-local",
|
|
80
81
|
get registryId() {
|
|
81
82
|
return registryId;
|
|
82
83
|
},
|
|
@@ -202,7 +203,7 @@ async function ensureWorkerSettlementIsSafe(registry, ref) {
|
|
|
202
203
|
if (record == null) return { outcome: "not_found_in_scope" };
|
|
203
204
|
if (record.hasWebhook) {
|
|
204
205
|
throw new Error(
|
|
205
|
-
"
|
|
206
|
+
"Registry-only scoped settlement is unavailable for tasks with push notifications. Use createPostgresTaskSettlementCoordinator() with completeScopedPushTask()/failScopedPushTask() for crash-safe PostgreSQL settlement."
|
|
206
207
|
);
|
|
207
208
|
}
|
|
208
209
|
return void 0;
|
|
@@ -61,6 +61,20 @@ function buildCtxMetadataAccessor(store, accountId) {
|
|
|
61
61
|
}
|
|
62
62
|
};
|
|
63
63
|
}
|
|
64
|
+
function createContextTaskHandoff(fn, options) {
|
|
65
|
+
if (options?.task_id !== void 0) {
|
|
66
|
+
if (typeof options.task_id !== "string" || options.task_id.length === 0) {
|
|
67
|
+
throw new Error("handoffToTask options.task_id must be a non-empty string");
|
|
68
|
+
}
|
|
69
|
+
if (options.task_id.length > 128) {
|
|
70
|
+
throw new Error("handoffToTask options.task_id must be \u2264 128 characters");
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (options != null && "settlement" in options && options.settlement !== "external") {
|
|
74
|
+
throw new Error("handoffToTask options.settlement must be 'external'");
|
|
75
|
+
}
|
|
76
|
+
return (0, import_async_outcome._createTaskHandoff)(fn, options);
|
|
77
|
+
}
|
|
64
78
|
function buildRequestContext(handlerCtx, ctxMetadataStore, input) {
|
|
65
79
|
const account = handlerCtx.account;
|
|
66
80
|
const stubResolver = (name) => async () => {
|
|
@@ -91,17 +105,7 @@ function buildRequestContext(handlerCtx, ctxMetadataStore, input) {
|
|
|
91
105
|
creativeFormat: stubResolver("creativeFormat")
|
|
92
106
|
},
|
|
93
107
|
ctxMetadata,
|
|
94
|
-
handoffToTask
|
|
95
|
-
if (options?.task_id !== void 0) {
|
|
96
|
-
if (typeof options.task_id !== "string" || options.task_id.length === 0) {
|
|
97
|
-
throw new Error("handoffToTask options.task_id must be a non-empty string");
|
|
98
|
-
}
|
|
99
|
-
if (options.task_id.length > 128) {
|
|
100
|
-
throw new Error("handoffToTask options.task_id must be \u2264 128 characters");
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
return (0, import_async_outcome._createTaskHandoff)(fn, options);
|
|
104
|
-
}
|
|
108
|
+
handoffToTask: createContextTaskHandoff
|
|
105
109
|
};
|
|
106
110
|
}
|
|
107
111
|
function buildHandoffContext(taskRegistry, taskRef) {
|
|
@@ -39,6 +39,20 @@ function buildCtxMetadataAccessor(store, accountId) {
|
|
|
39
39
|
}
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
|
+
function createContextTaskHandoff(fn, options) {
|
|
43
|
+
if (options?.task_id !== void 0) {
|
|
44
|
+
if (typeof options.task_id !== "string" || options.task_id.length === 0) {
|
|
45
|
+
throw new Error("handoffToTask options.task_id must be a non-empty string");
|
|
46
|
+
}
|
|
47
|
+
if (options.task_id.length > 128) {
|
|
48
|
+
throw new Error("handoffToTask options.task_id must be \u2264 128 characters");
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (options != null && "settlement" in options && options.settlement !== "external") {
|
|
52
|
+
throw new Error("handoffToTask options.settlement must be 'external'");
|
|
53
|
+
}
|
|
54
|
+
return _createTaskHandoff(fn, options);
|
|
55
|
+
}
|
|
42
56
|
function buildRequestContext(handlerCtx, ctxMetadataStore, input) {
|
|
43
57
|
const account = handlerCtx.account;
|
|
44
58
|
const stubResolver = (name) => async () => {
|
|
@@ -69,17 +83,7 @@ function buildRequestContext(handlerCtx, ctxMetadataStore, input) {
|
|
|
69
83
|
creativeFormat: stubResolver("creativeFormat")
|
|
70
84
|
},
|
|
71
85
|
ctxMetadata,
|
|
72
|
-
handoffToTask
|
|
73
|
-
if (options?.task_id !== void 0) {
|
|
74
|
-
if (typeof options.task_id !== "string" || options.task_id.length === 0) {
|
|
75
|
-
throw new Error("handoffToTask options.task_id must be a non-empty string");
|
|
76
|
-
}
|
|
77
|
-
if (options.task_id.length > 128) {
|
|
78
|
-
throw new Error("handoffToTask options.task_id must be \u2264 128 characters");
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
return _createTaskHandoff(fn, options);
|
|
82
|
-
}
|
|
86
|
+
handoffToTask: createContextTaskHandoff
|
|
83
87
|
};
|
|
84
88
|
}
|
|
85
89
|
function buildHandoffContext(taskRegistry, taskRef) {
|
|
@@ -65,8 +65,8 @@ export type { IdempotencyStore, IdempotencyStoreConfig, IdempotencyBackend, Idem
|
|
|
65
65
|
export { createA2AAdapter, A2AInvocationError } from './a2a-adapter.mjs';
|
|
66
66
|
export type { A2AAdapter, A2AAdapterOptions, A2AAgentCardOverrides, A2AAgentCapabilitiesOverride, A2AAgentSkillOverride, A2AMountOptions, ExpressAppLike, LegacyHttpSecurityScheme, LegacySecurityScheme, } from './a2a-adapter.mjs';
|
|
67
67
|
export { createWebhookEmitter, memoryWebhookDeliveryStore, memoryWebhookKeyStore } from './webhook-emitter.mjs';
|
|
68
|
-
export { pgWebhookDeliveryStore, pgWebhookDeliveryRecoveryBackend, redisWebhookDeliveryStore, redisWebhookDeliveryRecoveryBackend, getWebhookDeliveryMigration, getWebhookDeliveryRecoveryMigration, WEBHOOK_DELIVERY_MIGRATION, WEBHOOK_DELIVERY_RECOVERY_MIGRATION, createWebhookDeliveryRecovery, pollWebhookDeliveryRecovery, memoryWebhookDeliveryRecoveryBackend, WebhookDeliveryTerminalError, isWebhookDeliveryTerminalError, } from './webhook-delivery/index.mjs';
|
|
69
|
-
export type { PgWebhookDeliveryStoreOptions, PgWebhookDeliveryRecoveryOptions, RedisWebhookDeliveryStoreOptions, RedisWebhookDeliveryRecoveryOptions, ProtectedWebhookAuthentication, WebhookAuthenticationAdapter, WebhookAuthenticationContext, StoredWebhookDeliverySnapshot, WebhookRecoveryRecord, WebhookRecoveryLease, WebhookRecoveryCheckpointResult, WebhookRecoveryCheckpointOutcome, WebhookDeliveryRecoveryBackend, DurableWebhookDeliveryRecovery, CreateWebhookDeliveryRecoveryOptions, PollWebhookDeliveryRecoveryOptions, } from './webhook-delivery/index.mjs';
|
|
68
|
+
export { pgWebhookDeliveryStore, pgWebhookDeliveryRecoveryBackend, redisWebhookDeliveryStore, redisWebhookDeliveryRecoveryBackend, getWebhookDeliveryMigration, getWebhookDeliveryRecoveryMigration, WEBHOOK_DELIVERY_MIGRATION, WEBHOOK_DELIVERY_RECOVERY_MIGRATION, createWebhookDeliveryRecovery, pollWebhookDeliveryRecovery, memoryWebhookDeliveryRecoveryBackend, WebhookAuthenticationProtectionError, WebhookAuthenticationResolutionError, WebhookDeliveryTerminalError, isWebhookDeliveryTerminalError, } from './webhook-delivery/index.mjs';
|
|
69
|
+
export type { PgWebhookDeliveryStoreOptions, PgWebhookDeliveryRecoveryOptions, RedisWebhookDeliveryStoreOptions, RedisWebhookDeliveryRecoveryOptions, ProtectedWebhookAuthentication, WebhookAuthenticationAdapter, WebhookAuthenticationContext, StoredWebhookDeliverySnapshot, PreparedWebhookDeliverySnapshot, PrepareWebhookDeliveryOptions, WebhookRecoveryRecord, WebhookRecoveryLease, WebhookRecoveryCheckpointResult, WebhookRecoveryCheckpointOutcome, WebhookDeliveryRecoveryBackend, DurableWebhookDeliveryRecovery, CreateWebhookDeliveryRecoveryOptions, PollWebhookDeliveryRecoveryOptions, } from './webhook-delivery/index.mjs';
|
|
70
70
|
export type { WebhookEmitter, RecoverableWebhookEmitter, WebhookEmitterOptions, WebhookEmitParams, WebhookEmitResult, WebhookRecoveredDelivery, WebhookEmitAttempt, WebhookEmitAttemptResult, WebhookDeliveryBinding, WebhookDeliveryRetired, WebhookDeliveryRecord, WebhookDeliveryKey, WebhookDeliveryProposal, WebhookDeliverySnapshot, WebhookDeliveryRecovery, WebhookDeliveryRecoveryClaim, WebhookDeliveryStore, WebhookIdempotencyKeyStore, WebhookRetryOptions, WebhookAuthentication, } from './webhook-emitter.mjs';
|
|
71
71
|
export type { SigningProvider } from '../signing/provider.mjs';
|
|
72
72
|
export { createPinAndBindFetch, WEBHOOK_SSRF_POLICY, LOOPBACK_OK_WEBHOOK_SSRF_POLICY } from './pin-and-bind-fetch.mjs';
|
|
@@ -65,8 +65,8 @@ export type { IdempotencyStore, IdempotencyStoreConfig, IdempotencyBackend, Idem
|
|
|
65
65
|
export { createA2AAdapter, A2AInvocationError } from './a2a-adapter';
|
|
66
66
|
export type { A2AAdapter, A2AAdapterOptions, A2AAgentCardOverrides, A2AAgentCapabilitiesOverride, A2AAgentSkillOverride, A2AMountOptions, ExpressAppLike, LegacyHttpSecurityScheme, LegacySecurityScheme, } from './a2a-adapter';
|
|
67
67
|
export { createWebhookEmitter, memoryWebhookDeliveryStore, memoryWebhookKeyStore } from './webhook-emitter';
|
|
68
|
-
export { pgWebhookDeliveryStore, pgWebhookDeliveryRecoveryBackend, redisWebhookDeliveryStore, redisWebhookDeliveryRecoveryBackend, getWebhookDeliveryMigration, getWebhookDeliveryRecoveryMigration, WEBHOOK_DELIVERY_MIGRATION, WEBHOOK_DELIVERY_RECOVERY_MIGRATION, createWebhookDeliveryRecovery, pollWebhookDeliveryRecovery, memoryWebhookDeliveryRecoveryBackend, WebhookDeliveryTerminalError, isWebhookDeliveryTerminalError, } from './webhook-delivery';
|
|
69
|
-
export type { PgWebhookDeliveryStoreOptions, PgWebhookDeliveryRecoveryOptions, RedisWebhookDeliveryStoreOptions, RedisWebhookDeliveryRecoveryOptions, ProtectedWebhookAuthentication, WebhookAuthenticationAdapter, WebhookAuthenticationContext, StoredWebhookDeliverySnapshot, WebhookRecoveryRecord, WebhookRecoveryLease, WebhookRecoveryCheckpointResult, WebhookRecoveryCheckpointOutcome, WebhookDeliveryRecoveryBackend, DurableWebhookDeliveryRecovery, CreateWebhookDeliveryRecoveryOptions, PollWebhookDeliveryRecoveryOptions, } from './webhook-delivery';
|
|
68
|
+
export { pgWebhookDeliveryStore, pgWebhookDeliveryRecoveryBackend, redisWebhookDeliveryStore, redisWebhookDeliveryRecoveryBackend, getWebhookDeliveryMigration, getWebhookDeliveryRecoveryMigration, WEBHOOK_DELIVERY_MIGRATION, WEBHOOK_DELIVERY_RECOVERY_MIGRATION, createWebhookDeliveryRecovery, pollWebhookDeliveryRecovery, memoryWebhookDeliveryRecoveryBackend, WebhookAuthenticationProtectionError, WebhookAuthenticationResolutionError, WebhookDeliveryTerminalError, isWebhookDeliveryTerminalError, } from './webhook-delivery';
|
|
69
|
+
export type { PgWebhookDeliveryStoreOptions, PgWebhookDeliveryRecoveryOptions, RedisWebhookDeliveryStoreOptions, RedisWebhookDeliveryRecoveryOptions, ProtectedWebhookAuthentication, WebhookAuthenticationAdapter, WebhookAuthenticationContext, StoredWebhookDeliverySnapshot, PreparedWebhookDeliverySnapshot, PrepareWebhookDeliveryOptions, WebhookRecoveryRecord, WebhookRecoveryLease, WebhookRecoveryCheckpointResult, WebhookRecoveryCheckpointOutcome, WebhookDeliveryRecoveryBackend, DurableWebhookDeliveryRecovery, CreateWebhookDeliveryRecoveryOptions, PollWebhookDeliveryRecoveryOptions, } from './webhook-delivery';
|
|
70
70
|
export type { WebhookEmitter, RecoverableWebhookEmitter, WebhookEmitterOptions, WebhookEmitParams, WebhookEmitResult, WebhookRecoveredDelivery, WebhookEmitAttempt, WebhookEmitAttemptResult, WebhookDeliveryBinding, WebhookDeliveryRetired, WebhookDeliveryRecord, WebhookDeliveryKey, WebhookDeliveryProposal, WebhookDeliverySnapshot, WebhookDeliveryRecovery, WebhookDeliveryRecoveryClaim, WebhookDeliveryStore, WebhookIdempotencyKeyStore, WebhookRetryOptions, WebhookAuthentication, } from './webhook-emitter';
|
|
71
71
|
export type { SigningProvider } from '../signing/provider';
|
|
72
72
|
export { createPinAndBindFetch, WEBHOOK_SSRF_POLICY, LOOPBACK_OK_WEBHOOK_SSRF_POLICY } from './pin-and-bind-fetch';
|
package/dist/lib/server/index.js
CHANGED
|
@@ -77,6 +77,8 @@ __export(server_exports, {
|
|
|
77
77
|
WEBHOOK_SSRF_POLICY: () => import_pin_and_bind_fetch.WEBHOOK_SSRF_POLICY,
|
|
78
78
|
WIRE_SPEC_FIELDS: () => import_wire_safe.WIRE_SPEC_FIELDS,
|
|
79
79
|
WebSocketTransport: () => import_socket_mode.WebSocketTransport,
|
|
80
|
+
WebhookAuthenticationProtectionError: () => import_webhook_delivery.WebhookAuthenticationProtectionError,
|
|
81
|
+
WebhookAuthenticationResolutionError: () => import_webhook_delivery.WebhookAuthenticationResolutionError,
|
|
80
82
|
WebhookDeliveryTerminalError: () => import_webhook_delivery.WebhookDeliveryTerminalError,
|
|
81
83
|
adcpError: () => import_errors.adcpError,
|
|
82
84
|
anyOf: () => import_auth.anyOf,
|
|
@@ -373,6 +375,8 @@ var import_socket_mode = require('./socket-mode/index.js');
|
|
|
373
375
|
WEBHOOK_SSRF_POLICY,
|
|
374
376
|
WIRE_SPEC_FIELDS,
|
|
375
377
|
WebSocketTransport,
|
|
378
|
+
WebhookAuthenticationProtectionError,
|
|
379
|
+
WebhookAuthenticationResolutionError,
|
|
376
380
|
WebhookDeliveryTerminalError,
|
|
377
381
|
adcpError,
|
|
378
382
|
anyOf,
|
|
@@ -189,6 +189,8 @@ import {
|
|
|
189
189
|
createWebhookDeliveryRecovery,
|
|
190
190
|
pollWebhookDeliveryRecovery,
|
|
191
191
|
memoryWebhookDeliveryRecoveryBackend,
|
|
192
|
+
WebhookAuthenticationProtectionError,
|
|
193
|
+
WebhookAuthenticationResolutionError,
|
|
192
194
|
WebhookDeliveryTerminalError,
|
|
193
195
|
isWebhookDeliveryTerminalError
|
|
194
196
|
} from "./webhook-delivery/index.mjs";
|
|
@@ -322,6 +324,8 @@ export {
|
|
|
322
324
|
WEBHOOK_SSRF_POLICY,
|
|
323
325
|
WIRE_SPEC_FIELDS,
|
|
324
326
|
WebSocketTransport,
|
|
327
|
+
WebhookAuthenticationProtectionError,
|
|
328
|
+
WebhookAuthenticationResolutionError,
|
|
325
329
|
WebhookDeliveryTerminalError,
|
|
326
330
|
adcpError,
|
|
327
331
|
anyOf,
|
|
@@ -2,6 +2,6 @@ export { pgWebhookDeliveryStore, pgWebhookDeliveryRecoveryBackend, getWebhookDel
|
|
|
2
2
|
export type { PgWebhookDeliveryStoreOptions, PgWebhookDeliveryRecoveryOptions } from './pg.mjs';
|
|
3
3
|
export { redisWebhookDeliveryStore, redisWebhookDeliveryRecoveryBackend } from './redis.mjs';
|
|
4
4
|
export type { RedisWebhookDeliveryStoreOptions, RedisWebhookDeliveryRecoveryOptions } from './redis.mjs';
|
|
5
|
-
export { createWebhookDeliveryRecovery, pollWebhookDeliveryRecovery, memoryWebhookDeliveryRecoveryBackend, } from './recovery.mjs';
|
|
6
|
-
export type { ProtectedWebhookAuthentication, WebhookAuthenticationAdapter, WebhookAuthenticationContext, StoredWebhookDeliverySnapshot, WebhookRecoveryRecord, WebhookRecoveryLease, WebhookRecoveryCheckpointResult, WebhookRecoveryCheckpointOutcome, WebhookDeliveryRecoveryBackend, DurableWebhookDeliveryRecovery, CreateWebhookDeliveryRecoveryOptions, PollWebhookDeliveryRecoveryOptions, } from './recovery.mjs';
|
|
5
|
+
export { createWebhookDeliveryRecovery, pollWebhookDeliveryRecovery, memoryWebhookDeliveryRecoveryBackend, WebhookAuthenticationProtectionError, WebhookAuthenticationResolutionError, } from './recovery.mjs';
|
|
6
|
+
export type { ProtectedWebhookAuthentication, WebhookAuthenticationAdapter, WebhookAuthenticationContext, StoredWebhookDeliverySnapshot, PreparedWebhookDeliverySnapshot, PrepareWebhookDeliveryOptions, WebhookRecoveryRecord, WebhookRecoveryLease, WebhookRecoveryCheckpointResult, WebhookRecoveryCheckpointOutcome, WebhookDeliveryRecoveryBackend, DurableWebhookDeliveryRecovery, CreateWebhookDeliveryRecoveryOptions, PollWebhookDeliveryRecoveryOptions, } from './recovery.mjs';
|
|
7
7
|
export { WebhookDeliveryTerminalError, isWebhookDeliveryTerminalError } from './common.mjs';
|
|
@@ -2,6 +2,6 @@ export { pgWebhookDeliveryStore, pgWebhookDeliveryRecoveryBackend, getWebhookDel
|
|
|
2
2
|
export type { PgWebhookDeliveryStoreOptions, PgWebhookDeliveryRecoveryOptions } from './pg';
|
|
3
3
|
export { redisWebhookDeliveryStore, redisWebhookDeliveryRecoveryBackend } from './redis';
|
|
4
4
|
export type { RedisWebhookDeliveryStoreOptions, RedisWebhookDeliveryRecoveryOptions } from './redis';
|
|
5
|
-
export { createWebhookDeliveryRecovery, pollWebhookDeliveryRecovery, memoryWebhookDeliveryRecoveryBackend, } from './recovery';
|
|
6
|
-
export type { ProtectedWebhookAuthentication, WebhookAuthenticationAdapter, WebhookAuthenticationContext, StoredWebhookDeliverySnapshot, WebhookRecoveryRecord, WebhookRecoveryLease, WebhookRecoveryCheckpointResult, WebhookRecoveryCheckpointOutcome, WebhookDeliveryRecoveryBackend, DurableWebhookDeliveryRecovery, CreateWebhookDeliveryRecoveryOptions, PollWebhookDeliveryRecoveryOptions, } from './recovery';
|
|
5
|
+
export { createWebhookDeliveryRecovery, pollWebhookDeliveryRecovery, memoryWebhookDeliveryRecoveryBackend, WebhookAuthenticationProtectionError, WebhookAuthenticationResolutionError, } from './recovery';
|
|
6
|
+
export type { ProtectedWebhookAuthentication, WebhookAuthenticationAdapter, WebhookAuthenticationContext, StoredWebhookDeliverySnapshot, PreparedWebhookDeliverySnapshot, PrepareWebhookDeliveryOptions, WebhookRecoveryRecord, WebhookRecoveryLease, WebhookRecoveryCheckpointResult, WebhookRecoveryCheckpointOutcome, WebhookDeliveryRecoveryBackend, DurableWebhookDeliveryRecovery, CreateWebhookDeliveryRecoveryOptions, PollWebhookDeliveryRecoveryOptions, } from './recovery';
|
|
7
7
|
export { WebhookDeliveryTerminalError, isWebhookDeliveryTerminalError } from './common';
|
|
@@ -20,6 +20,8 @@ var webhook_delivery_exports = {};
|
|
|
20
20
|
__export(webhook_delivery_exports, {
|
|
21
21
|
WEBHOOK_DELIVERY_MIGRATION: () => import_pg.WEBHOOK_DELIVERY_MIGRATION,
|
|
22
22
|
WEBHOOK_DELIVERY_RECOVERY_MIGRATION: () => import_pg.WEBHOOK_DELIVERY_RECOVERY_MIGRATION,
|
|
23
|
+
WebhookAuthenticationProtectionError: () => import_recovery.WebhookAuthenticationProtectionError,
|
|
24
|
+
WebhookAuthenticationResolutionError: () => import_recovery.WebhookAuthenticationResolutionError,
|
|
23
25
|
WebhookDeliveryTerminalError: () => import_common.WebhookDeliveryTerminalError,
|
|
24
26
|
createWebhookDeliveryRecovery: () => import_recovery.createWebhookDeliveryRecovery,
|
|
25
27
|
getWebhookDeliveryMigration: () => import_pg.getWebhookDeliveryMigration,
|
|
@@ -41,6 +43,8 @@ var import_common = require('./common.js');
|
|
|
41
43
|
0 && (module.exports = {
|
|
42
44
|
WEBHOOK_DELIVERY_MIGRATION,
|
|
43
45
|
WEBHOOK_DELIVERY_RECOVERY_MIGRATION,
|
|
46
|
+
WebhookAuthenticationProtectionError,
|
|
47
|
+
WebhookAuthenticationResolutionError,
|
|
44
48
|
WebhookDeliveryTerminalError,
|
|
45
49
|
createWebhookDeliveryRecovery,
|
|
46
50
|
getWebhookDeliveryMigration,
|
|
@@ -10,12 +10,16 @@ import { redisWebhookDeliveryStore, redisWebhookDeliveryRecoveryBackend } from "
|
|
|
10
10
|
import {
|
|
11
11
|
createWebhookDeliveryRecovery,
|
|
12
12
|
pollWebhookDeliveryRecovery,
|
|
13
|
-
memoryWebhookDeliveryRecoveryBackend
|
|
13
|
+
memoryWebhookDeliveryRecoveryBackend,
|
|
14
|
+
WebhookAuthenticationProtectionError,
|
|
15
|
+
WebhookAuthenticationResolutionError
|
|
14
16
|
} from "./recovery.mjs";
|
|
15
17
|
import { WebhookDeliveryTerminalError, isWebhookDeliveryTerminalError } from "./common.mjs";
|
|
16
18
|
export {
|
|
17
19
|
WEBHOOK_DELIVERY_MIGRATION,
|
|
18
20
|
WEBHOOK_DELIVERY_RECOVERY_MIGRATION,
|
|
21
|
+
WebhookAuthenticationProtectionError,
|
|
22
|
+
WebhookAuthenticationResolutionError,
|
|
19
23
|
WebhookDeliveryTerminalError,
|
|
20
24
|
createWebhookDeliveryRecovery,
|
|
21
25
|
getWebhookDeliveryMigration,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { PgQueryable } from '../postgres-task-store.mjs';
|
|
2
|
-
import type { WebhookDeliveryStore } from '../webhook-emitter.mjs';
|
|
2
|
+
import type { WebhookDeliveryKey, WebhookDeliveryStore } from '../webhook-emitter.mjs';
|
|
3
3
|
import type { WebhookDeliveryRecoveryBackend } from './recovery.mjs';
|
|
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;
|