@adcp/sdk 14.0.0 → 14.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/adapters/implicit-account-store.d.mts +12 -7
- package/dist/lib/adapters/implicit-account-store.d.ts +12 -7
- package/dist/lib/adapters/implicit-account-store.js +69 -15
- package/dist/lib/adapters/implicit-account-store.mjs +69 -15
- package/dist/lib/core/AgentClient.d.mts +1 -0
- package/dist/lib/core/AgentClient.d.ts +1 -0
- package/dist/lib/core/AgentClient.js +3 -0
- package/dist/lib/core/AgentClient.mjs +3 -0
- package/dist/lib/core/SingleAgentClient.d.mts +35 -2
- package/dist/lib/core/SingleAgentClient.d.ts +35 -2
- package/dist/lib/core/SingleAgentClient.js +377 -36
- package/dist/lib/core/SingleAgentClient.mjs +387 -38
- package/dist/lib/core/TaskExecutor.d.mts +3 -1
- package/dist/lib/core/TaskExecutor.d.ts +3 -1
- package/dist/lib/core/TaskExecutor.js +17 -12
- package/dist/lib/core/TaskExecutor.mjs +17 -12
- package/dist/lib/core/account-key.d.mts +3 -0
- package/dist/lib/core/account-key.d.ts +3 -0
- package/dist/lib/core/account-key.js +41 -0
- package/dist/lib/core/account-key.mjs +17 -0
- package/dist/lib/core/account-resolution.d.mts +2 -0
- package/dist/lib/core/account-resolution.d.ts +2 -0
- package/dist/lib/core/buyer-account-registry.d.mts +93 -0
- package/dist/lib/core/buyer-account-registry.d.ts +93 -0
- package/dist/lib/core/buyer-account-registry.js +602 -0
- package/dist/lib/core/buyer-account-registry.mjs +578 -0
- package/dist/lib/core/product-cache.d.mts +18 -0
- package/dist/lib/core/product-cache.d.ts +18 -0
- package/dist/lib/core/product-cache.js +137 -0
- package/dist/lib/core/product-cache.mjs +112 -0
- package/dist/lib/errors/index.d.mts +40 -1
- package/dist/lib/errors/index.d.ts +40 -1
- package/dist/lib/errors/index.js +69 -3
- package/dist/lib/errors/index.mjs +64 -3
- package/dist/lib/governance/authorization.d.mts +17 -1
- package/dist/lib/governance/authorization.d.ts +17 -1
- package/dist/lib/governance/authorization.js +55 -7
- package/dist/lib/governance/authorization.mjs +59 -7
- package/dist/lib/governance/index.d.mts +2 -2
- package/dist/lib/governance/index.d.ts +2 -2
- package/dist/lib/governance/index.js +2 -0
- package/dist/lib/governance/index.mjs +3 -1
- package/dist/lib/index.d.mts +7 -4
- package/dist/lib/index.d.ts +7 -4
- package/dist/lib/index.js +29 -0
- package/dist/lib/index.mjs +31 -1
- package/dist/lib/net/agent-transport-fetch.d.mts +4 -0
- package/dist/lib/net/agent-transport-fetch.d.ts +4 -0
- package/dist/lib/net/agent-transport-fetch.js +18 -5
- package/dist/lib/net/agent-transport-fetch.mjs +17 -5
- package/dist/lib/protocols/a2a.js +9 -1
- package/dist/lib/protocols/a2a.mjs +9 -1
- package/dist/lib/protocols/index.js +9 -2
- package/dist/lib/protocols/index.mjs +9 -2
- package/dist/lib/protocols/mcp-modern.js +2 -1
- package/dist/lib/protocols/mcp-modern.mjs +2 -1
- package/dist/lib/protocols/mcp.js +5 -2
- package/dist/lib/protocols/mcp.mjs +5 -2
- package/dist/lib/protocols/rawResponseCapture.d.mts +6 -0
- package/dist/lib/protocols/rawResponseCapture.d.ts +6 -0
- package/dist/lib/protocols/rawResponseCapture.js +41 -29
- package/dist/lib/protocols/rawResponseCapture.mjs +40 -29
- package/dist/lib/protocols/signedRequestRejection.d.mts +9 -0
- package/dist/lib/protocols/signedRequestRejection.d.ts +9 -0
- package/dist/lib/protocols/signedRequestRejection.js +209 -0
- package/dist/lib/protocols/signedRequestRejection.mjs +189 -0
- package/dist/lib/protocols/transportDiagnostics.d.mts +1 -0
- package/dist/lib/protocols/transportDiagnostics.d.ts +1 -0
- package/dist/lib/protocols/transportDiagnostics.js +2 -0
- package/dist/lib/protocols/transportDiagnostics.mjs +1 -0
- package/dist/lib/registry/types.generated.d.mts +112 -45
- package/dist/lib/registry/types.generated.d.ts +112 -45
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/server/account-provisioning.d.mts +2 -0
- package/dist/lib/server/account-provisioning.d.ts +2 -0
- package/dist/lib/server/account-provisioning.js +30 -0
- package/dist/lib/server/account-provisioning.mjs +6 -0
- package/dist/lib/server/account-reference-warnings.d.mts +12 -0
- package/dist/lib/server/account-reference-warnings.d.ts +12 -0
- package/dist/lib/server/account-reference-warnings.js +48 -0
- package/dist/lib/server/account-reference-warnings.mjs +23 -0
- package/dist/lib/server/auth-signature.js +1 -0
- package/dist/lib/server/auth-signature.mjs +1 -0
- package/dist/lib/server/create-adcp-server.d.mts +34 -0
- package/dist/lib/server/create-adcp-server.d.ts +34 -0
- package/dist/lib/server/create-adcp-server.js +225 -14
- package/dist/lib/server/create-adcp-server.mjs +225 -14
- package/dist/lib/server/decisioning/account.d.mts +2 -0
- package/dist/lib/server/decisioning/account.d.ts +2 -0
- package/dist/lib/server/decisioning/runtime/from-platform.js +49 -10
- package/dist/lib/server/decisioning/runtime/from-platform.mjs +49 -10
- package/dist/lib/server/index.d.mts +2 -2
- package/dist/lib/server/index.d.ts +2 -2
- package/dist/lib/server/index.js +2 -0
- package/dist/lib/server/index.mjs +3 -1
- package/dist/lib/signing/agent-resolver/consistency.d.mts +6 -13
- package/dist/lib/signing/agent-resolver/consistency.d.ts +6 -13
- package/dist/lib/signing/agent-resolver/consistency.js +0 -1
- package/dist/lib/signing/agent-resolver/consistency.mjs +0 -1
- package/dist/lib/signing/agent-resolver/errors.d.mts +3 -1
- package/dist/lib/signing/agent-resolver/errors.d.ts +3 -1
- package/dist/lib/signing/agent-resolver/errors.js +6 -0
- package/dist/lib/signing/agent-resolver/errors.mjs +6 -0
- package/dist/lib/signing/agent-resolver/fetch-helpers.d.mts +11 -0
- package/dist/lib/signing/agent-resolver/fetch-helpers.d.ts +11 -0
- package/dist/lib/signing/agent-resolver/fetch-helpers.js +37 -2
- package/dist/lib/signing/agent-resolver/fetch-helpers.mjs +40 -3
- package/dist/lib/signing/agent-resolver/jwks-set.js +24 -3
- package/dist/lib/signing/agent-resolver/jwks-set.mjs +24 -3
- package/dist/lib/signing/agent-resolver/legacy-brand.d.mts +15 -0
- package/dist/lib/signing/agent-resolver/legacy-brand.d.ts +15 -0
- package/dist/lib/signing/agent-resolver/legacy-brand.js +60 -0
- package/dist/lib/signing/agent-resolver/legacy-brand.mjs +36 -0
- package/dist/lib/signing/agent-resolver/operator-authorization.d.mts +13 -0
- package/dist/lib/signing/agent-resolver/operator-authorization.d.ts +13 -0
- package/dist/lib/signing/agent-resolver/operator-authorization.js +108 -0
- package/dist/lib/signing/agent-resolver/operator-authorization.mjs +84 -0
- package/dist/lib/signing/agent-resolver/resolve-agent.d.mts +14 -4
- package/dist/lib/signing/agent-resolver/resolve-agent.d.ts +14 -4
- package/dist/lib/signing/agent-resolver/resolve-agent.js +148 -137
- package/dist/lib/signing/agent-resolver/resolve-agent.mjs +157 -139
- package/dist/lib/signing/agent-resolver/resolved-agent-jwks.d.mts +7 -1
- package/dist/lib/signing/agent-resolver/resolved-agent-jwks.d.ts +7 -1
- package/dist/lib/signing/agent-resolver/resolved-agent-jwks.js +50 -17
- package/dist/lib/signing/agent-resolver/resolved-agent-jwks.mjs +50 -17
- package/dist/lib/signing/agent-resolver/select-agent.d.mts +14 -15
- package/dist/lib/signing/agent-resolver/select-agent.d.ts +14 -15
- package/dist/lib/signing/agent-resolver/select-agent.js +98 -13
- package/dist/lib/signing/agent-resolver/select-agent.mjs +95 -13
- package/dist/lib/signing/brand-jwks.d.mts +29 -75
- package/dist/lib/signing/brand-jwks.d.ts +29 -75
- package/dist/lib/signing/brand-jwks.js +120 -182
- package/dist/lib/signing/brand-jwks.mjs +120 -182
- package/dist/lib/signing/errors.d.mts +7 -3
- package/dist/lib/signing/errors.d.ts +7 -3
- package/dist/lib/signing/errors.js +7 -2
- package/dist/lib/signing/errors.mjs +7 -2
- package/dist/lib/signing/jwks-https.d.mts +7 -0
- package/dist/lib/signing/jwks-https.d.ts +7 -0
- package/dist/lib/signing/jwks-https.js +31 -8
- package/dist/lib/signing/jwks-https.mjs +31 -8
- package/dist/lib/signing/jwks.d.mts +8 -0
- package/dist/lib/signing/jwks.d.ts +8 -0
- package/dist/lib/signing/middleware.js +2 -1
- package/dist/lib/signing/middleware.mjs +2 -1
- package/dist/lib/signing/publisher-pins.d.mts +11 -0
- package/dist/lib/signing/publisher-pins.d.ts +11 -0
- package/dist/lib/signing/publisher-pins.js +125 -0
- package/dist/lib/signing/publisher-pins.mjs +101 -0
- package/dist/lib/signing/server.d.mts +1 -0
- package/dist/lib/signing/server.d.ts +1 -0
- package/dist/lib/signing/types.d.mts +5 -0
- package/dist/lib/signing/types.d.ts +5 -0
- package/dist/lib/signing/verifier.js +50 -5
- package/dist/lib/signing/verifier.mjs +50 -5
- package/dist/lib/signing/webhook-verifier.d.mts +7 -2
- package/dist/lib/signing/webhook-verifier.d.ts +7 -2
- package/dist/lib/signing/webhook-verifier.js +42 -2
- package/dist/lib/signing/webhook-verifier.mjs +42 -2
- package/dist/lib/testing/storyboard/account-policy.d.mts +2 -0
- package/dist/lib/testing/storyboard/account-policy.d.ts +2 -0
- package/dist/lib/testing/storyboard/account-policy.js +35 -0
- package/dist/lib/testing/storyboard/account-policy.mjs +11 -0
- package/dist/lib/testing/storyboard/context.js +6 -0
- package/dist/lib/testing/storyboard/context.mjs +6 -0
- package/dist/lib/testing/storyboard/request-builder.js +12 -2
- package/dist/lib/testing/storyboard/request-builder.mjs +12 -2
- package/dist/lib/testing/storyboard/runner.js +3 -2
- package/dist/lib/testing/storyboard/runner.mjs +3 -2
- package/dist/lib/testing/storyboard/validations.d.mts +1 -1
- package/dist/lib/testing/storyboard/validations.d.ts +1 -1
- package/dist/lib/types/accept-proposal.d.ts +19 -1
- package/dist/lib/types/buy-products.d.ts +19 -1
- package/dist/lib/types/check-governance.d.ts +19 -1
- package/dist/lib/types/comply-test-controller.d.ts +19 -1
- package/dist/lib/types/control-media-buy.d.ts +19 -1
- package/dist/lib/types/core.generated.d.mts +14 -1
- package/dist/lib/types/core.generated.d.ts +14 -1
- package/dist/lib/types/create-media-buy.d.ts +14 -1
- package/dist/lib/types/get-media-buys.d.ts +14 -1
- package/dist/lib/types/get-products.d.ts +19 -1
- package/dist/lib/types/list-products.d.ts +19 -1
- package/dist/lib/types/refine-proposals.d.ts +19 -1
- package/dist/lib/types/request-proposals.d.ts +19 -1
- package/dist/lib/types/schemas.generated.d.ts +12 -3
- package/dist/lib/types/schemas.generated.js +4 -1
- package/dist/lib/types/schemas.generated.mjs +4 -1
- package/dist/lib/types/tools.generated.d.mts +14 -1
- package/dist/lib/types/tools.generated.d.ts +14 -1
- package/dist/lib/types/update-media-buy.d.ts +14 -1
- 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/dist/lib/webhooks/index.d.mts +24 -0
- package/dist/lib/webhooks/index.d.ts +24 -0
- package/dist/lib/webhooks/index.js +50 -24
- package/dist/lib/webhooks/index.mjs +49 -24
- package/dist/lib/wholesale-feed-sync/index.d.mts +2 -0
- package/dist/lib/wholesale-feed-sync/index.d.ts +2 -0
- package/dist/lib/wholesale-feed-sync/index.js +7 -0
- package/dist/lib/wholesale-feed-sync/index.mjs +4 -0
- package/dist/lib/wholesale-feed-sync/mirror.d.mts +97 -0
- package/dist/lib/wholesale-feed-sync/mirror.d.ts +97 -0
- package/dist/lib/wholesale-feed-sync/mirror.js +350 -0
- package/dist/lib/wholesale-feed-sync/mirror.mjs +322 -0
- package/dist/lib/wholesale-feed-sync/sync.d.mts +13 -29
- package/dist/lib/wholesale-feed-sync/sync.d.ts +13 -29
- package/dist/lib/wholesale-feed-sync/sync.js +208 -281
- package/dist/lib/wholesale-feed-sync/sync.mjs +213 -281
- package/dist/lib/wholesale-feed-sync/types.d.mts +4 -3
- package/dist/lib/wholesale-feed-sync/types.d.ts +4 -3
- package/docs/README.md +6 -0
- package/docs/TYPE-SUMMARY.md +2 -2
- package/docs/guides/BUILD-AN-AGENT.md +2 -2
- package/docs/guides/BUYER-QUICKSTART-3.2.md +2 -0
- package/docs/guides/BUYER-STORAGE.md +3 -0
- package/docs/guides/FIRST-CALL-TO-A-SELLER.md +106 -0
- package/docs/guides/SIGNING-GUIDE.md +16 -7
- package/docs/guides/account-resolution.md +132 -10
- package/docs/llms.txt +3 -2
- package/docs/migration-14.0-to-14.1.md +85 -0
- package/docs/migration-14.x-rc-worksheet.md +4 -4
- package/docs/migration-4.x-to-5.x.md +1 -0
- package/docs/migration-agent-resolution-3.3.md +125 -0
- package/docs/recipes/verifying-inbound-webhooks.md +60 -15
- package/package.json +3 -2
- package/skills/adcp-brand.previous/SKILL.md +0 -200
- package/skills/adcp-creative.previous/SKILL.md +0 -305
- package/skills/adcp-governance.previous/SKILL.md +0 -566
- package/skills/adcp-measurement.previous/SKILL.md +0 -136
- package/skills/adcp-media-buy.previous/SKILL.md +0 -556
- package/skills/adcp-si.previous/SKILL.md +0 -206
- package/skills/adcp-signals.previous/SKILL.md +0 -204
|
@@ -22,6 +22,7 @@ __export(webhooks_exports, {
|
|
|
22
22
|
WholesaleFeedWebhookNotificationError: () => import_webhook_notification.WholesaleFeedWebhookNotificationError,
|
|
23
23
|
normalizeWholesaleFeedWebhookNotification: () => import_webhook_notification.normalizeWholesaleFeedWebhookNotification,
|
|
24
24
|
parseWholesaleFeedWebhookNotification: () => import_webhook_notification.parseWholesaleFeedWebhookNotification,
|
|
25
|
+
preflightWebhookRequest: () => preflightWebhookRequest,
|
|
25
26
|
verifyWebhookRequest: () => verifyWebhookRequest
|
|
26
27
|
});
|
|
27
28
|
module.exports = __toCommonJS(webhooks_exports);
|
|
@@ -29,49 +30,73 @@ var import_crypto = require("crypto");
|
|
|
29
30
|
__reExport(webhooks_exports, require('../notifications/account-change-recorded.js'), module.exports);
|
|
30
31
|
var import_webhook_notification = require('../wholesale-feed-sync/webhook-notification.js');
|
|
31
32
|
function verifyWebhookRequest(options) {
|
|
33
|
+
const preflight = preflightWebhookRequest(options, {
|
|
34
|
+
now: options.now,
|
|
35
|
+
maxSkewSeconds: options.maxSkewSeconds ?? options.skewSeconds
|
|
36
|
+
});
|
|
37
|
+
if (!preflight.ok) return preflight;
|
|
32
38
|
const secret = options.secret ?? options.globalSecret;
|
|
33
39
|
if (!secret) {
|
|
34
40
|
return fail("missing_secret", "A webhook HMAC secret is required.");
|
|
35
41
|
}
|
|
36
|
-
const
|
|
37
|
-
if (signature.reason) return fail(signature.reason, signature.message);
|
|
38
|
-
const timestamp = resolveHeader("x-adcp-timestamp", options.timestamp, options.headers);
|
|
39
|
-
if (timestamp.reason) return fail(timestamp.reason, timestamp.message);
|
|
40
|
-
if (!signature.value || !timestamp.value) {
|
|
41
|
-
return fail("missing_headers", "Webhook is missing x-adcp-signature or x-adcp-timestamp.");
|
|
42
|
-
}
|
|
43
|
-
const parsedTimestamp = parseTimestamp(timestamp.value);
|
|
44
|
-
if (parsedTimestamp === void 0) {
|
|
45
|
-
return fail("invalid_timestamp", "x-adcp-timestamp must be an integer unix timestamp in seconds.");
|
|
46
|
-
}
|
|
47
|
-
const now = options.now ? Math.floor(options.now()) : Math.floor(Date.now() / 1e3);
|
|
48
|
-
const skewSeconds = options.skewSeconds ?? 300;
|
|
49
|
-
if (!Number.isFinite(skewSeconds) || skewSeconds < 0) {
|
|
50
|
-
return fail("invalid_timestamp", "skewSeconds must be a non-negative number.");
|
|
51
|
-
}
|
|
52
|
-
if (Math.abs(now - parsedTimestamp) > skewSeconds) {
|
|
53
|
-
return fail("stale_timestamp", `Webhook timestamp is outside the allowed ${skewSeconds}s skew window.`);
|
|
54
|
-
}
|
|
55
|
-
if (!/^sha256=[a-f0-9]{64}$/.test(signature.value)) {
|
|
56
|
-
return fail("malformed_signature", "x-adcp-signature must match sha256=<64 lowercase hex chars>.");
|
|
57
|
-
}
|
|
42
|
+
const { signature, timestamp: parsedTimestamp, checkedAt: now } = preflight;
|
|
58
43
|
const hmac = (0, import_crypto.createHmac)("sha256", secret);
|
|
59
44
|
hmac.update(String(parsedTimestamp), "utf8");
|
|
60
45
|
hmac.update(".", "utf8");
|
|
61
46
|
hmac.update(toBodyBytes(options.rawBody));
|
|
62
47
|
const expected = `sha256=${hmac.digest("hex")}`;
|
|
63
48
|
const expectedBytes = Buffer.from(expected, "utf8");
|
|
64
|
-
const actualBytes = Buffer.from(signature
|
|
49
|
+
const actualBytes = Buffer.from(signature, "utf8");
|
|
65
50
|
if (actualBytes.length !== expectedBytes.length || !(0, import_crypto.timingSafeEqual)(actualBytes, expectedBytes)) {
|
|
66
51
|
return fail("bad_signature", "Webhook HMAC signature does not match the request body and timestamp.");
|
|
67
52
|
}
|
|
68
53
|
return {
|
|
69
54
|
ok: true,
|
|
70
|
-
signature
|
|
55
|
+
signature,
|
|
71
56
|
timestamp: parsedTimestamp,
|
|
72
57
|
verifiedAt: now
|
|
73
58
|
};
|
|
74
59
|
}
|
|
60
|
+
function preflightWebhookRequest(request, options = {}) {
|
|
61
|
+
const signature = resolveHeader("x-adcp-signature", request.signature, request.headers);
|
|
62
|
+
if (signature.reason) return { ok: false, reason: signature.reason, message: signature.message };
|
|
63
|
+
const timestamp = resolveHeader("x-adcp-timestamp", request.timestamp, request.headers);
|
|
64
|
+
if (timestamp.reason) return { ok: false, reason: timestamp.reason, message: timestamp.message };
|
|
65
|
+
if (!signature.value || !timestamp.value)
|
|
66
|
+
return {
|
|
67
|
+
ok: false,
|
|
68
|
+
reason: "missing_headers",
|
|
69
|
+
message: "Webhook is missing x-adcp-signature or x-adcp-timestamp."
|
|
70
|
+
};
|
|
71
|
+
const parsedTimestamp = parseTimestamp(timestamp.value);
|
|
72
|
+
if (parsedTimestamp === void 0)
|
|
73
|
+
return {
|
|
74
|
+
ok: false,
|
|
75
|
+
reason: "invalid_timestamp",
|
|
76
|
+
message: "x-adcp-timestamp must be an integer unix timestamp in seconds."
|
|
77
|
+
};
|
|
78
|
+
const now = Math.floor(options.now ? options.now() : Date.now() / 1e3);
|
|
79
|
+
const skewSeconds = options.maxSkewSeconds ?? options.skewSeconds ?? 300;
|
|
80
|
+
if (!Number.isFinite(now) || !Number.isFinite(skewSeconds) || skewSeconds < 0)
|
|
81
|
+
return {
|
|
82
|
+
ok: false,
|
|
83
|
+
reason: "invalid_timestamp",
|
|
84
|
+
message: "Clock and skew must be finite; skew must be non-negative."
|
|
85
|
+
};
|
|
86
|
+
if (Math.abs(now - parsedTimestamp) > skewSeconds)
|
|
87
|
+
return {
|
|
88
|
+
ok: false,
|
|
89
|
+
reason: "stale_timestamp",
|
|
90
|
+
message: `Webhook timestamp is outside the allowed ${skewSeconds}s skew window.`
|
|
91
|
+
};
|
|
92
|
+
if (!/^sha256=[a-f0-9]{64}$/.test(signature.value))
|
|
93
|
+
return {
|
|
94
|
+
ok: false,
|
|
95
|
+
reason: "malformed_signature",
|
|
96
|
+
message: "x-adcp-signature must match sha256=<64 lowercase hex chars>."
|
|
97
|
+
};
|
|
98
|
+
return { ok: true, signature: signature.value, timestamp: parsedTimestamp, checkedAt: now };
|
|
99
|
+
}
|
|
75
100
|
function fail(reason, message) {
|
|
76
101
|
return { ok: false, reason, message };
|
|
77
102
|
}
|
|
@@ -148,6 +173,7 @@ function isHeaders(headers) {
|
|
|
148
173
|
WholesaleFeedWebhookNotificationError,
|
|
149
174
|
normalizeWholesaleFeedWebhookNotification,
|
|
150
175
|
parseWholesaleFeedWebhookNotification,
|
|
176
|
+
preflightWebhookRequest,
|
|
151
177
|
verifyWebhookRequest,
|
|
152
178
|
...require('../notifications/account-change-recorded.js')
|
|
153
179
|
});
|
|
@@ -6,49 +6,73 @@ import {
|
|
|
6
6
|
WholesaleFeedWebhookNotificationError
|
|
7
7
|
} from "../wholesale-feed-sync/webhook-notification.mjs";
|
|
8
8
|
function verifyWebhookRequest(options) {
|
|
9
|
+
const preflight = preflightWebhookRequest(options, {
|
|
10
|
+
now: options.now,
|
|
11
|
+
maxSkewSeconds: options.maxSkewSeconds ?? options.skewSeconds
|
|
12
|
+
});
|
|
13
|
+
if (!preflight.ok) return preflight;
|
|
9
14
|
const secret = options.secret ?? options.globalSecret;
|
|
10
15
|
if (!secret) {
|
|
11
16
|
return fail("missing_secret", "A webhook HMAC secret is required.");
|
|
12
17
|
}
|
|
13
|
-
const
|
|
14
|
-
if (signature.reason) return fail(signature.reason, signature.message);
|
|
15
|
-
const timestamp = resolveHeader("x-adcp-timestamp", options.timestamp, options.headers);
|
|
16
|
-
if (timestamp.reason) return fail(timestamp.reason, timestamp.message);
|
|
17
|
-
if (!signature.value || !timestamp.value) {
|
|
18
|
-
return fail("missing_headers", "Webhook is missing x-adcp-signature or x-adcp-timestamp.");
|
|
19
|
-
}
|
|
20
|
-
const parsedTimestamp = parseTimestamp(timestamp.value);
|
|
21
|
-
if (parsedTimestamp === void 0) {
|
|
22
|
-
return fail("invalid_timestamp", "x-adcp-timestamp must be an integer unix timestamp in seconds.");
|
|
23
|
-
}
|
|
24
|
-
const now = options.now ? Math.floor(options.now()) : Math.floor(Date.now() / 1e3);
|
|
25
|
-
const skewSeconds = options.skewSeconds ?? 300;
|
|
26
|
-
if (!Number.isFinite(skewSeconds) || skewSeconds < 0) {
|
|
27
|
-
return fail("invalid_timestamp", "skewSeconds must be a non-negative number.");
|
|
28
|
-
}
|
|
29
|
-
if (Math.abs(now - parsedTimestamp) > skewSeconds) {
|
|
30
|
-
return fail("stale_timestamp", `Webhook timestamp is outside the allowed ${skewSeconds}s skew window.`);
|
|
31
|
-
}
|
|
32
|
-
if (!/^sha256=[a-f0-9]{64}$/.test(signature.value)) {
|
|
33
|
-
return fail("malformed_signature", "x-adcp-signature must match sha256=<64 lowercase hex chars>.");
|
|
34
|
-
}
|
|
18
|
+
const { signature, timestamp: parsedTimestamp, checkedAt: now } = preflight;
|
|
35
19
|
const hmac = createHmac("sha256", secret);
|
|
36
20
|
hmac.update(String(parsedTimestamp), "utf8");
|
|
37
21
|
hmac.update(".", "utf8");
|
|
38
22
|
hmac.update(toBodyBytes(options.rawBody));
|
|
39
23
|
const expected = `sha256=${hmac.digest("hex")}`;
|
|
40
24
|
const expectedBytes = Buffer.from(expected, "utf8");
|
|
41
|
-
const actualBytes = Buffer.from(signature
|
|
25
|
+
const actualBytes = Buffer.from(signature, "utf8");
|
|
42
26
|
if (actualBytes.length !== expectedBytes.length || !timingSafeEqual(actualBytes, expectedBytes)) {
|
|
43
27
|
return fail("bad_signature", "Webhook HMAC signature does not match the request body and timestamp.");
|
|
44
28
|
}
|
|
45
29
|
return {
|
|
46
30
|
ok: true,
|
|
47
|
-
signature
|
|
31
|
+
signature,
|
|
48
32
|
timestamp: parsedTimestamp,
|
|
49
33
|
verifiedAt: now
|
|
50
34
|
};
|
|
51
35
|
}
|
|
36
|
+
function preflightWebhookRequest(request, options = {}) {
|
|
37
|
+
const signature = resolveHeader("x-adcp-signature", request.signature, request.headers);
|
|
38
|
+
if (signature.reason) return { ok: false, reason: signature.reason, message: signature.message };
|
|
39
|
+
const timestamp = resolveHeader("x-adcp-timestamp", request.timestamp, request.headers);
|
|
40
|
+
if (timestamp.reason) return { ok: false, reason: timestamp.reason, message: timestamp.message };
|
|
41
|
+
if (!signature.value || !timestamp.value)
|
|
42
|
+
return {
|
|
43
|
+
ok: false,
|
|
44
|
+
reason: "missing_headers",
|
|
45
|
+
message: "Webhook is missing x-adcp-signature or x-adcp-timestamp."
|
|
46
|
+
};
|
|
47
|
+
const parsedTimestamp = parseTimestamp(timestamp.value);
|
|
48
|
+
if (parsedTimestamp === void 0)
|
|
49
|
+
return {
|
|
50
|
+
ok: false,
|
|
51
|
+
reason: "invalid_timestamp",
|
|
52
|
+
message: "x-adcp-timestamp must be an integer unix timestamp in seconds."
|
|
53
|
+
};
|
|
54
|
+
const now = Math.floor(options.now ? options.now() : Date.now() / 1e3);
|
|
55
|
+
const skewSeconds = options.maxSkewSeconds ?? options.skewSeconds ?? 300;
|
|
56
|
+
if (!Number.isFinite(now) || !Number.isFinite(skewSeconds) || skewSeconds < 0)
|
|
57
|
+
return {
|
|
58
|
+
ok: false,
|
|
59
|
+
reason: "invalid_timestamp",
|
|
60
|
+
message: "Clock and skew must be finite; skew must be non-negative."
|
|
61
|
+
};
|
|
62
|
+
if (Math.abs(now - parsedTimestamp) > skewSeconds)
|
|
63
|
+
return {
|
|
64
|
+
ok: false,
|
|
65
|
+
reason: "stale_timestamp",
|
|
66
|
+
message: `Webhook timestamp is outside the allowed ${skewSeconds}s skew window.`
|
|
67
|
+
};
|
|
68
|
+
if (!/^sha256=[a-f0-9]{64}$/.test(signature.value))
|
|
69
|
+
return {
|
|
70
|
+
ok: false,
|
|
71
|
+
reason: "malformed_signature",
|
|
72
|
+
message: "x-adcp-signature must match sha256=<64 lowercase hex chars>."
|
|
73
|
+
};
|
|
74
|
+
return { ok: true, signature: signature.value, timestamp: parsedTimestamp, checkedAt: now };
|
|
75
|
+
}
|
|
52
76
|
function fail(reason, message) {
|
|
53
77
|
return { ok: false, reason, message };
|
|
54
78
|
}
|
|
@@ -124,5 +148,6 @@ export {
|
|
|
124
148
|
WholesaleFeedWebhookNotificationError,
|
|
125
149
|
normalizeWholesaleFeedWebhookNotification,
|
|
126
150
|
parseWholesaleFeedWebhookNotification,
|
|
151
|
+
preflightWebhookRequest,
|
|
127
152
|
verifyWebhookRequest
|
|
128
153
|
};
|
|
@@ -5,3 +5,5 @@ export { normalizeWholesaleFeedWebhookNotification, parseWholesaleFeedWebhookNot
|
|
|
5
5
|
export type { WholesaleFeedSyncClient, WholesaleFeedSyncConfig, WholesaleFeedSyncEvents, WholesaleFeedSyncMode, WholesaleFeedSyncPersistedState, WholesaleFeedSyncPersistenceHooks, WholesaleFeedSyncState, ProductFilter, ResolvedCapabilities, SignalFilter, } from './types.mjs';
|
|
6
6
|
export type { NormalizedWholesaleFeedWebhookNotification, WholesaleFeedWebhookAffectedEntityType, WholesaleFeedWebhookCacheScope, WholesaleFeedWebhookNotificationErrorCode, WholesaleFeedWebhookNotificationErrorDetails, WholesaleFeedWebhookNotificationType, } from './webhook-notification.mjs';
|
|
7
7
|
export type { LegacyWholesaleFeedEvent, LegacyWholesaleFeedWebhook, LegacyWholesaleProduct, LegacyWholesaleSignal, } from './protocol-types.mjs';
|
|
8
|
+
export { refreshWholesaleFeed, applyWholesaleFeedWebhook, InMemoryWholesaleFeedMirrorStore } from './mirror.mjs';
|
|
9
|
+
export type { WholesaleFeedMirrorStore, WholesaleFeedMirrorScope, WholesaleFeedMirrorItem, WholesaleFeedMirrorSnapshot, WholesaleFeedMirrorCommit, WholesaleFeedRefreshOutcome, RefreshWholesaleFeedOptions, ApplyWholesaleFeedWebhookOptions, } from './mirror.mjs';
|
|
@@ -5,3 +5,5 @@ export { normalizeWholesaleFeedWebhookNotification, parseWholesaleFeedWebhookNot
|
|
|
5
5
|
export type { WholesaleFeedSyncClient, WholesaleFeedSyncConfig, WholesaleFeedSyncEvents, WholesaleFeedSyncMode, WholesaleFeedSyncPersistedState, WholesaleFeedSyncPersistenceHooks, WholesaleFeedSyncState, ProductFilter, ResolvedCapabilities, SignalFilter, } from './types';
|
|
6
6
|
export type { NormalizedWholesaleFeedWebhookNotification, WholesaleFeedWebhookAffectedEntityType, WholesaleFeedWebhookCacheScope, WholesaleFeedWebhookNotificationErrorCode, WholesaleFeedWebhookNotificationErrorDetails, WholesaleFeedWebhookNotificationType, } from './webhook-notification';
|
|
7
7
|
export type { LegacyWholesaleFeedEvent, LegacyWholesaleFeedWebhook, LegacyWholesaleProduct, LegacyWholesaleSignal, } from './protocol-types';
|
|
8
|
+
export { refreshWholesaleFeed, applyWholesaleFeedWebhook, InMemoryWholesaleFeedMirrorStore } from './mirror';
|
|
9
|
+
export type { WholesaleFeedMirrorStore, WholesaleFeedMirrorScope, WholesaleFeedMirrorItem, WholesaleFeedMirrorSnapshot, WholesaleFeedMirrorCommit, WholesaleFeedRefreshOutcome, RefreshWholesaleFeedOptions, ApplyWholesaleFeedWebhookOptions, } from './mirror';
|
|
@@ -18,23 +18,30 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var wholesale_feed_sync_exports = {};
|
|
20
20
|
__export(wholesale_feed_sync_exports, {
|
|
21
|
+
InMemoryWholesaleFeedMirrorStore: () => import_mirror.InMemoryWholesaleFeedMirrorStore,
|
|
21
22
|
WholesaleFeedSync: () => import_sync.WholesaleFeedSync,
|
|
22
23
|
WholesaleFeedWebhookNotificationError: () => import_webhook_notification.WholesaleFeedWebhookNotificationError,
|
|
23
24
|
WholesaleFeedWebhookRegistrationError: () => import_register.WholesaleFeedWebhookRegistrationError,
|
|
25
|
+
applyWholesaleFeedWebhook: () => import_mirror.applyWholesaleFeedWebhook,
|
|
24
26
|
normalizeWholesaleFeedWebhookNotification: () => import_webhook_notification.normalizeWholesaleFeedWebhookNotification,
|
|
25
27
|
parseWholesaleFeedWebhookNotification: () => import_webhook_notification.parseWholesaleFeedWebhookNotification,
|
|
28
|
+
refreshWholesaleFeed: () => import_mirror.refreshWholesaleFeed,
|
|
26
29
|
registerWholesaleFeedWebhooks: () => import_register.registerWholesaleFeedWebhooks
|
|
27
30
|
});
|
|
28
31
|
module.exports = __toCommonJS(wholesale_feed_sync_exports);
|
|
29
32
|
var import_sync = require('./sync.js');
|
|
30
33
|
var import_register = require('./register.js');
|
|
31
34
|
var import_webhook_notification = require('./webhook-notification.js');
|
|
35
|
+
var import_mirror = require('./mirror.js');
|
|
32
36
|
// Annotate the CommonJS export names for ESM import in node:
|
|
33
37
|
0 && (module.exports = {
|
|
38
|
+
InMemoryWholesaleFeedMirrorStore,
|
|
34
39
|
WholesaleFeedSync,
|
|
35
40
|
WholesaleFeedWebhookNotificationError,
|
|
36
41
|
WholesaleFeedWebhookRegistrationError,
|
|
42
|
+
applyWholesaleFeedWebhook,
|
|
37
43
|
normalizeWholesaleFeedWebhookNotification,
|
|
38
44
|
parseWholesaleFeedWebhookNotification,
|
|
45
|
+
refreshWholesaleFeed,
|
|
39
46
|
registerWholesaleFeedWebhooks
|
|
40
47
|
});
|
|
@@ -5,11 +5,15 @@ import {
|
|
|
5
5
|
parseWholesaleFeedWebhookNotification,
|
|
6
6
|
WholesaleFeedWebhookNotificationError
|
|
7
7
|
} from "./webhook-notification.mjs";
|
|
8
|
+
import { refreshWholesaleFeed, applyWholesaleFeedWebhook, InMemoryWholesaleFeedMirrorStore } from "./mirror.mjs";
|
|
8
9
|
export {
|
|
10
|
+
InMemoryWholesaleFeedMirrorStore,
|
|
9
11
|
WholesaleFeedSync,
|
|
10
12
|
WholesaleFeedWebhookNotificationError,
|
|
11
13
|
WholesaleFeedWebhookRegistrationError,
|
|
14
|
+
applyWholesaleFeedWebhook,
|
|
12
15
|
normalizeWholesaleFeedWebhookNotification,
|
|
13
16
|
parseWholesaleFeedWebhookNotification,
|
|
17
|
+
refreshWholesaleFeed,
|
|
14
18
|
registerWholesaleFeedWebhooks
|
|
15
19
|
};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { AccountReference } from '../types/index.mjs';
|
|
2
|
+
import type { AdcpErrorInfo } from '../core/ConversationTypes.mjs';
|
|
3
|
+
import type { WholesaleFeedSyncClient } from './types.mjs';
|
|
4
|
+
import type { LegacyWholesaleFeedEvent, LegacyWholesaleFeedWebhook, LegacyWholesaleProduct, LegacyWholesaleSignal } from './protocol-types.mjs';
|
|
5
|
+
export type WholesaleFeedMirrorItem = LegacyWholesaleProduct | LegacyWholesaleSignal;
|
|
6
|
+
/** accountKey must include the caller/principal and account overlay, even for public catalogs. */
|
|
7
|
+
export interface WholesaleFeedMirrorScope {
|
|
8
|
+
agentUrl: string;
|
|
9
|
+
accountKey: string;
|
|
10
|
+
entity: 'product' | 'signal';
|
|
11
|
+
}
|
|
12
|
+
export interface WholesaleFeedMirrorSnapshot {
|
|
13
|
+
revision: number;
|
|
14
|
+
items: WholesaleFeedMirrorItem[];
|
|
15
|
+
wholesaleFeedVersion?: string;
|
|
16
|
+
pricingVersion?: string;
|
|
17
|
+
cacheScope: 'public' | 'account';
|
|
18
|
+
lastSyncedAt?: string;
|
|
19
|
+
lastWebhookEventId?: string;
|
|
20
|
+
lastWebhookIdempotencyKey?: string;
|
|
21
|
+
error?: AdcpErrorInfo;
|
|
22
|
+
}
|
|
23
|
+
export interface WholesaleFeedMirrorCommit {
|
|
24
|
+
upserts: WholesaleFeedMirrorItem[];
|
|
25
|
+
deletes: string[];
|
|
26
|
+
wholesaleFeedVersion?: string;
|
|
27
|
+
pricingVersion?: string;
|
|
28
|
+
cacheScope: 'public' | 'account';
|
|
29
|
+
lastSyncedAt: string;
|
|
30
|
+
lastWebhookEventId?: string;
|
|
31
|
+
lastWebhookIdempotencyKey?: string;
|
|
32
|
+
/** Persist this delivery receipt atomically with the row/token commit. */
|
|
33
|
+
webhookReceipt?: {
|
|
34
|
+
eventId: string;
|
|
35
|
+
idempotencyKey: string;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/** Consistent reads; atomically check/increment revisions with rows, tokens, and receipts. */
|
|
39
|
+
export interface WholesaleFeedMirrorStore {
|
|
40
|
+
read(scope: WholesaleFeedMirrorScope): Promise<WholesaleFeedMirrorSnapshot>;
|
|
41
|
+
hasWebhookReceipt(scope: WholesaleFeedMirrorScope, idempotencyKey: string): Promise<boolean>;
|
|
42
|
+
commit(scope: WholesaleFeedMirrorScope, expectedRevision: number, change: WholesaleFeedMirrorCommit): Promise<boolean>;
|
|
43
|
+
recordError(scope: WholesaleFeedMirrorScope, expectedRevision: number, error: AdcpErrorInfo): Promise<boolean>;
|
|
44
|
+
}
|
|
45
|
+
export type WholesaleFeedRefreshOutcome = {
|
|
46
|
+
outcome: 'unchanged';
|
|
47
|
+
snapshot: WholesaleFeedMirrorSnapshot;
|
|
48
|
+
} | {
|
|
49
|
+
outcome: 'applied';
|
|
50
|
+
snapshot: WholesaleFeedMirrorSnapshot;
|
|
51
|
+
diff: LegacyWholesaleFeedEvent[];
|
|
52
|
+
} | {
|
|
53
|
+
outcome: 'degraded';
|
|
54
|
+
error: AdcpErrorInfo;
|
|
55
|
+
cause: Error;
|
|
56
|
+
} | {
|
|
57
|
+
outcome: 'superseded';
|
|
58
|
+
};
|
|
59
|
+
export interface RefreshWholesaleFeedOptions {
|
|
60
|
+
client: WholesaleFeedSyncClient;
|
|
61
|
+
store: WholesaleFeedMirrorStore;
|
|
62
|
+
scope: WholesaleFeedMirrorScope;
|
|
63
|
+
account?: AccountReference;
|
|
64
|
+
/** Disable against sellers that do not advertise wholesale-feed versioning. Defaults to true. */
|
|
65
|
+
conditional?: boolean;
|
|
66
|
+
/** Local cancellation fence; no timer is started by the core. */
|
|
67
|
+
isCurrent?: () => boolean;
|
|
68
|
+
}
|
|
69
|
+
export declare class InMemoryWholesaleFeedMirrorStore implements WholesaleFeedMirrorStore {
|
|
70
|
+
private readonly maxWebhookReceipts;
|
|
71
|
+
private readonly records;
|
|
72
|
+
private readonly receipts;
|
|
73
|
+
private receiptCount;
|
|
74
|
+
/** Fail closed at capacity rather than evicting receipts inside the delivery retry window. */
|
|
75
|
+
constructor(maxWebhookReceipts?: number);
|
|
76
|
+
hasWebhookReceipt(scope: WholesaleFeedMirrorScope, idempotencyKey: string): Promise<boolean>;
|
|
77
|
+
private key;
|
|
78
|
+
read(scope: WholesaleFeedMirrorScope): Promise<WholesaleFeedMirrorSnapshot>;
|
|
79
|
+
/** Seed a detached record when restoring a shell snapshot. */
|
|
80
|
+
restore(scope: WholesaleFeedMirrorScope, snapshot: WholesaleFeedMirrorSnapshot): void;
|
|
81
|
+
commit(scope: WholesaleFeedMirrorScope, expectedRevision: number, change: WholesaleFeedMirrorCommit): Promise<boolean>;
|
|
82
|
+
recordError(scope: WholesaleFeedMirrorScope, expectedRevision: number, error: AdcpErrorInfo): Promise<boolean>;
|
|
83
|
+
}
|
|
84
|
+
/** Refresh one legacy get_products/get_signals feed without owning scheduling or storage. */
|
|
85
|
+
export declare function refreshWholesaleFeed(options: RefreshWholesaleFeedOptions): Promise<WholesaleFeedRefreshOutcome>;
|
|
86
|
+
export interface ApplyWholesaleFeedWebhookOptions extends RefreshWholesaleFeedOptions {
|
|
87
|
+
webhook: LegacyWholesaleFeedWebhook;
|
|
88
|
+
/** Expected subscription route, supplied after authentication by the receiver. */
|
|
89
|
+
webhookScope?: {
|
|
90
|
+
accountId?: string;
|
|
91
|
+
subscriberId?: string;
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/** Apply an authenticated legacy delta, or repair from the seller on bulk change/order/version mismatch. */
|
|
95
|
+
export declare function applyWholesaleFeedWebhook(options: ApplyWholesaleFeedWebhookOptions): Promise<WholesaleFeedRefreshOutcome>;
|
|
96
|
+
export declare function applyWholesaleFeedEvent(entity: WholesaleFeedMirrorScope['entity'], previous: WholesaleFeedMirrorItem[], event: LegacyWholesaleFeedEvent): WholesaleFeedMirrorItem[] | undefined;
|
|
97
|
+
export declare function diffWholesaleFeed(entity: WholesaleFeedMirrorScope['entity'], previous: WholesaleFeedMirrorItem[], next: WholesaleFeedMirrorItem[], cacheScope: 'public' | 'account', includeAllChanges?: boolean): LegacyWholesaleFeedEvent[];
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import type { AccountReference } from '../types';
|
|
2
|
+
import type { AdcpErrorInfo } from '../core/ConversationTypes';
|
|
3
|
+
import type { WholesaleFeedSyncClient } from './types';
|
|
4
|
+
import type { LegacyWholesaleFeedEvent, LegacyWholesaleFeedWebhook, LegacyWholesaleProduct, LegacyWholesaleSignal } from './protocol-types';
|
|
5
|
+
export type WholesaleFeedMirrorItem = LegacyWholesaleProduct | LegacyWholesaleSignal;
|
|
6
|
+
/** accountKey must include the caller/principal and account overlay, even for public catalogs. */
|
|
7
|
+
export interface WholesaleFeedMirrorScope {
|
|
8
|
+
agentUrl: string;
|
|
9
|
+
accountKey: string;
|
|
10
|
+
entity: 'product' | 'signal';
|
|
11
|
+
}
|
|
12
|
+
export interface WholesaleFeedMirrorSnapshot {
|
|
13
|
+
revision: number;
|
|
14
|
+
items: WholesaleFeedMirrorItem[];
|
|
15
|
+
wholesaleFeedVersion?: string;
|
|
16
|
+
pricingVersion?: string;
|
|
17
|
+
cacheScope: 'public' | 'account';
|
|
18
|
+
lastSyncedAt?: string;
|
|
19
|
+
lastWebhookEventId?: string;
|
|
20
|
+
lastWebhookIdempotencyKey?: string;
|
|
21
|
+
error?: AdcpErrorInfo;
|
|
22
|
+
}
|
|
23
|
+
export interface WholesaleFeedMirrorCommit {
|
|
24
|
+
upserts: WholesaleFeedMirrorItem[];
|
|
25
|
+
deletes: string[];
|
|
26
|
+
wholesaleFeedVersion?: string;
|
|
27
|
+
pricingVersion?: string;
|
|
28
|
+
cacheScope: 'public' | 'account';
|
|
29
|
+
lastSyncedAt: string;
|
|
30
|
+
lastWebhookEventId?: string;
|
|
31
|
+
lastWebhookIdempotencyKey?: string;
|
|
32
|
+
/** Persist this delivery receipt atomically with the row/token commit. */
|
|
33
|
+
webhookReceipt?: {
|
|
34
|
+
eventId: string;
|
|
35
|
+
idempotencyKey: string;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/** Consistent reads; atomically check/increment revisions with rows, tokens, and receipts. */
|
|
39
|
+
export interface WholesaleFeedMirrorStore {
|
|
40
|
+
read(scope: WholesaleFeedMirrorScope): Promise<WholesaleFeedMirrorSnapshot>;
|
|
41
|
+
hasWebhookReceipt(scope: WholesaleFeedMirrorScope, idempotencyKey: string): Promise<boolean>;
|
|
42
|
+
commit(scope: WholesaleFeedMirrorScope, expectedRevision: number, change: WholesaleFeedMirrorCommit): Promise<boolean>;
|
|
43
|
+
recordError(scope: WholesaleFeedMirrorScope, expectedRevision: number, error: AdcpErrorInfo): Promise<boolean>;
|
|
44
|
+
}
|
|
45
|
+
export type WholesaleFeedRefreshOutcome = {
|
|
46
|
+
outcome: 'unchanged';
|
|
47
|
+
snapshot: WholesaleFeedMirrorSnapshot;
|
|
48
|
+
} | {
|
|
49
|
+
outcome: 'applied';
|
|
50
|
+
snapshot: WholesaleFeedMirrorSnapshot;
|
|
51
|
+
diff: LegacyWholesaleFeedEvent[];
|
|
52
|
+
} | {
|
|
53
|
+
outcome: 'degraded';
|
|
54
|
+
error: AdcpErrorInfo;
|
|
55
|
+
cause: Error;
|
|
56
|
+
} | {
|
|
57
|
+
outcome: 'superseded';
|
|
58
|
+
};
|
|
59
|
+
export interface RefreshWholesaleFeedOptions {
|
|
60
|
+
client: WholesaleFeedSyncClient;
|
|
61
|
+
store: WholesaleFeedMirrorStore;
|
|
62
|
+
scope: WholesaleFeedMirrorScope;
|
|
63
|
+
account?: AccountReference;
|
|
64
|
+
/** Disable against sellers that do not advertise wholesale-feed versioning. Defaults to true. */
|
|
65
|
+
conditional?: boolean;
|
|
66
|
+
/** Local cancellation fence; no timer is started by the core. */
|
|
67
|
+
isCurrent?: () => boolean;
|
|
68
|
+
}
|
|
69
|
+
export declare class InMemoryWholesaleFeedMirrorStore implements WholesaleFeedMirrorStore {
|
|
70
|
+
private readonly maxWebhookReceipts;
|
|
71
|
+
private readonly records;
|
|
72
|
+
private readonly receipts;
|
|
73
|
+
private receiptCount;
|
|
74
|
+
/** Fail closed at capacity rather than evicting receipts inside the delivery retry window. */
|
|
75
|
+
constructor(maxWebhookReceipts?: number);
|
|
76
|
+
hasWebhookReceipt(scope: WholesaleFeedMirrorScope, idempotencyKey: string): Promise<boolean>;
|
|
77
|
+
private key;
|
|
78
|
+
read(scope: WholesaleFeedMirrorScope): Promise<WholesaleFeedMirrorSnapshot>;
|
|
79
|
+
/** Seed a detached record when restoring a shell snapshot. */
|
|
80
|
+
restore(scope: WholesaleFeedMirrorScope, snapshot: WholesaleFeedMirrorSnapshot): void;
|
|
81
|
+
commit(scope: WholesaleFeedMirrorScope, expectedRevision: number, change: WholesaleFeedMirrorCommit): Promise<boolean>;
|
|
82
|
+
recordError(scope: WholesaleFeedMirrorScope, expectedRevision: number, error: AdcpErrorInfo): Promise<boolean>;
|
|
83
|
+
}
|
|
84
|
+
/** Refresh one legacy get_products/get_signals feed without owning scheduling or storage. */
|
|
85
|
+
export declare function refreshWholesaleFeed(options: RefreshWholesaleFeedOptions): Promise<WholesaleFeedRefreshOutcome>;
|
|
86
|
+
export interface ApplyWholesaleFeedWebhookOptions extends RefreshWholesaleFeedOptions {
|
|
87
|
+
webhook: LegacyWholesaleFeedWebhook;
|
|
88
|
+
/** Expected subscription route, supplied after authentication by the receiver. */
|
|
89
|
+
webhookScope?: {
|
|
90
|
+
accountId?: string;
|
|
91
|
+
subscriberId?: string;
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
/** Apply an authenticated legacy delta, or repair from the seller on bulk change/order/version mismatch. */
|
|
95
|
+
export declare function applyWholesaleFeedWebhook(options: ApplyWholesaleFeedWebhookOptions): Promise<WholesaleFeedRefreshOutcome>;
|
|
96
|
+
export declare function applyWholesaleFeedEvent(entity: WholesaleFeedMirrorScope['entity'], previous: WholesaleFeedMirrorItem[], event: LegacyWholesaleFeedEvent): WholesaleFeedMirrorItem[] | undefined;
|
|
97
|
+
export declare function diffWholesaleFeed(entity: WholesaleFeedMirrorScope['entity'], previous: WholesaleFeedMirrorItem[], next: WholesaleFeedMirrorItem[], cacheScope: 'public' | 'account', includeAllChanges?: boolean): LegacyWholesaleFeedEvent[];
|