@adcp/sdk 14.0.0 → 14.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (185) hide show
  1. package/dist/lib/adapters/implicit-account-store.d.mts +12 -7
  2. package/dist/lib/adapters/implicit-account-store.d.ts +12 -7
  3. package/dist/lib/adapters/implicit-account-store.js +69 -15
  4. package/dist/lib/adapters/implicit-account-store.mjs +69 -15
  5. package/dist/lib/core/AgentClient.d.mts +1 -0
  6. package/dist/lib/core/AgentClient.d.ts +1 -0
  7. package/dist/lib/core/AgentClient.js +3 -0
  8. package/dist/lib/core/AgentClient.mjs +3 -0
  9. package/dist/lib/core/SingleAgentClient.d.mts +31 -1
  10. package/dist/lib/core/SingleAgentClient.d.ts +31 -1
  11. package/dist/lib/core/SingleAgentClient.js +355 -35
  12. package/dist/lib/core/SingleAgentClient.mjs +365 -37
  13. package/dist/lib/core/TaskExecutor.js +2 -1
  14. package/dist/lib/core/TaskExecutor.mjs +2 -1
  15. package/dist/lib/core/account-key.d.mts +3 -0
  16. package/dist/lib/core/account-key.d.ts +3 -0
  17. package/dist/lib/core/account-key.js +41 -0
  18. package/dist/lib/core/account-key.mjs +17 -0
  19. package/dist/lib/core/account-resolution.d.mts +2 -0
  20. package/dist/lib/core/account-resolution.d.ts +2 -0
  21. package/dist/lib/core/buyer-account-registry.d.mts +65 -0
  22. package/dist/lib/core/buyer-account-registry.d.ts +65 -0
  23. package/dist/lib/core/buyer-account-registry.js +518 -0
  24. package/dist/lib/core/buyer-account-registry.mjs +494 -0
  25. package/dist/lib/core/product-cache.d.mts +18 -0
  26. package/dist/lib/core/product-cache.d.ts +18 -0
  27. package/dist/lib/core/product-cache.js +137 -0
  28. package/dist/lib/core/product-cache.mjs +112 -0
  29. package/dist/lib/errors/index.d.mts +40 -1
  30. package/dist/lib/errors/index.d.ts +40 -1
  31. package/dist/lib/errors/index.js +69 -3
  32. package/dist/lib/errors/index.mjs +64 -3
  33. package/dist/lib/governance/authorization.d.mts +17 -1
  34. package/dist/lib/governance/authorization.d.ts +17 -1
  35. package/dist/lib/governance/authorization.js +55 -7
  36. package/dist/lib/governance/authorization.mjs +59 -7
  37. package/dist/lib/governance/index.d.mts +2 -2
  38. package/dist/lib/governance/index.d.ts +2 -2
  39. package/dist/lib/governance/index.js +2 -0
  40. package/dist/lib/governance/index.mjs +3 -1
  41. package/dist/lib/index.d.mts +5 -3
  42. package/dist/lib/index.d.ts +5 -3
  43. package/dist/lib/index.js +20 -0
  44. package/dist/lib/index.mjs +19 -0
  45. package/dist/lib/protocols/a2a.js +9 -1
  46. package/dist/lib/protocols/a2a.mjs +9 -1
  47. package/dist/lib/protocols/index.js +9 -2
  48. package/dist/lib/protocols/index.mjs +9 -2
  49. package/dist/lib/protocols/mcp-modern.js +2 -1
  50. package/dist/lib/protocols/mcp-modern.mjs +2 -1
  51. package/dist/lib/protocols/mcp.js +5 -2
  52. package/dist/lib/protocols/mcp.mjs +5 -2
  53. package/dist/lib/protocols/rawResponseCapture.d.mts +6 -0
  54. package/dist/lib/protocols/rawResponseCapture.d.ts +6 -0
  55. package/dist/lib/protocols/rawResponseCapture.js +41 -29
  56. package/dist/lib/protocols/rawResponseCapture.mjs +40 -29
  57. package/dist/lib/protocols/signedRequestRejection.d.mts +9 -0
  58. package/dist/lib/protocols/signedRequestRejection.d.ts +9 -0
  59. package/dist/lib/protocols/signedRequestRejection.js +209 -0
  60. package/dist/lib/protocols/signedRequestRejection.mjs +189 -0
  61. package/dist/lib/protocols/transportDiagnostics.d.mts +1 -0
  62. package/dist/lib/protocols/transportDiagnostics.d.ts +1 -0
  63. package/dist/lib/protocols/transportDiagnostics.js +2 -0
  64. package/dist/lib/protocols/transportDiagnostics.mjs +1 -0
  65. package/dist/lib/registry/types.generated.d.mts +112 -45
  66. package/dist/lib/registry/types.generated.d.ts +112 -45
  67. package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
  68. package/dist/lib/server/account-provisioning.d.mts +2 -0
  69. package/dist/lib/server/account-provisioning.d.ts +2 -0
  70. package/dist/lib/server/account-provisioning.js +30 -0
  71. package/dist/lib/server/account-provisioning.mjs +6 -0
  72. package/dist/lib/server/account-reference-warnings.d.mts +12 -0
  73. package/dist/lib/server/account-reference-warnings.d.ts +12 -0
  74. package/dist/lib/server/account-reference-warnings.js +48 -0
  75. package/dist/lib/server/account-reference-warnings.mjs +23 -0
  76. package/dist/lib/server/auth-signature.js +1 -0
  77. package/dist/lib/server/auth-signature.mjs +1 -0
  78. package/dist/lib/server/create-adcp-server.d.mts +34 -0
  79. package/dist/lib/server/create-adcp-server.d.ts +34 -0
  80. package/dist/lib/server/create-adcp-server.js +225 -14
  81. package/dist/lib/server/create-adcp-server.mjs +225 -14
  82. package/dist/lib/server/decisioning/account.d.mts +2 -0
  83. package/dist/lib/server/decisioning/account.d.ts +2 -0
  84. package/dist/lib/server/decisioning/runtime/from-platform.js +49 -10
  85. package/dist/lib/server/decisioning/runtime/from-platform.mjs +49 -10
  86. package/dist/lib/server/index.d.mts +2 -2
  87. package/dist/lib/server/index.d.ts +2 -2
  88. package/dist/lib/server/index.js +2 -0
  89. package/dist/lib/server/index.mjs +3 -1
  90. package/dist/lib/signing/agent-resolver/consistency.d.mts +6 -13
  91. package/dist/lib/signing/agent-resolver/consistency.d.ts +6 -13
  92. package/dist/lib/signing/agent-resolver/consistency.js +0 -1
  93. package/dist/lib/signing/agent-resolver/consistency.mjs +0 -1
  94. package/dist/lib/signing/agent-resolver/errors.d.mts +1 -1
  95. package/dist/lib/signing/agent-resolver/errors.d.ts +1 -1
  96. package/dist/lib/signing/agent-resolver/fetch-helpers.d.mts +2 -0
  97. package/dist/lib/signing/agent-resolver/fetch-helpers.d.ts +2 -0
  98. package/dist/lib/signing/agent-resolver/fetch-helpers.js +2 -1
  99. package/dist/lib/signing/agent-resolver/fetch-helpers.mjs +2 -1
  100. package/dist/lib/signing/agent-resolver/jwks-set.js +24 -3
  101. package/dist/lib/signing/agent-resolver/jwks-set.mjs +24 -3
  102. package/dist/lib/signing/agent-resolver/legacy-brand.d.mts +15 -0
  103. package/dist/lib/signing/agent-resolver/legacy-brand.d.ts +15 -0
  104. package/dist/lib/signing/agent-resolver/legacy-brand.js +60 -0
  105. package/dist/lib/signing/agent-resolver/legacy-brand.mjs +36 -0
  106. package/dist/lib/signing/agent-resolver/operator-authorization.d.mts +13 -0
  107. package/dist/lib/signing/agent-resolver/operator-authorization.d.ts +13 -0
  108. package/dist/lib/signing/agent-resolver/operator-authorization.js +108 -0
  109. package/dist/lib/signing/agent-resolver/operator-authorization.mjs +84 -0
  110. package/dist/lib/signing/agent-resolver/resolve-agent.d.mts +14 -4
  111. package/dist/lib/signing/agent-resolver/resolve-agent.d.ts +14 -4
  112. package/dist/lib/signing/agent-resolver/resolve-agent.js +101 -132
  113. package/dist/lib/signing/agent-resolver/resolve-agent.mjs +102 -133
  114. package/dist/lib/signing/agent-resolver/resolved-agent-jwks.d.mts +7 -1
  115. package/dist/lib/signing/agent-resolver/resolved-agent-jwks.d.ts +7 -1
  116. package/dist/lib/signing/agent-resolver/resolved-agent-jwks.js +50 -17
  117. package/dist/lib/signing/agent-resolver/resolved-agent-jwks.mjs +50 -17
  118. package/dist/lib/signing/agent-resolver/select-agent.d.mts +14 -15
  119. package/dist/lib/signing/agent-resolver/select-agent.d.ts +14 -15
  120. package/dist/lib/signing/agent-resolver/select-agent.js +98 -13
  121. package/dist/lib/signing/agent-resolver/select-agent.mjs +95 -13
  122. package/dist/lib/signing/brand-jwks.d.mts +27 -75
  123. package/dist/lib/signing/brand-jwks.d.ts +27 -75
  124. package/dist/lib/signing/brand-jwks.js +112 -182
  125. package/dist/lib/signing/brand-jwks.mjs +112 -182
  126. package/dist/lib/signing/errors.d.mts +3 -1
  127. package/dist/lib/signing/errors.d.ts +3 -1
  128. package/dist/lib/signing/errors.js +4 -1
  129. package/dist/lib/signing/errors.mjs +4 -1
  130. package/dist/lib/signing/jwks-https.d.mts +7 -0
  131. package/dist/lib/signing/jwks-https.d.ts +7 -0
  132. package/dist/lib/signing/jwks-https.js +31 -8
  133. package/dist/lib/signing/jwks-https.mjs +31 -8
  134. package/dist/lib/signing/jwks.d.mts +8 -0
  135. package/dist/lib/signing/jwks.d.ts +8 -0
  136. package/dist/lib/signing/middleware.js +2 -1
  137. package/dist/lib/signing/middleware.mjs +2 -1
  138. package/dist/lib/signing/publisher-pins.d.mts +11 -0
  139. package/dist/lib/signing/publisher-pins.d.ts +11 -0
  140. package/dist/lib/signing/publisher-pins.js +125 -0
  141. package/dist/lib/signing/publisher-pins.mjs +101 -0
  142. package/dist/lib/signing/server.d.mts +1 -0
  143. package/dist/lib/signing/server.d.ts +1 -0
  144. package/dist/lib/signing/types.d.mts +5 -0
  145. package/dist/lib/signing/types.d.ts +5 -0
  146. package/dist/lib/signing/verifier.js +49 -4
  147. package/dist/lib/signing/verifier.mjs +49 -4
  148. package/dist/lib/signing/webhook-verifier.d.mts +7 -2
  149. package/dist/lib/signing/webhook-verifier.d.ts +7 -2
  150. package/dist/lib/signing/webhook-verifier.js +42 -2
  151. package/dist/lib/signing/webhook-verifier.mjs +43 -3
  152. package/dist/lib/testing/storyboard/account-policy.d.mts +2 -0
  153. package/dist/lib/testing/storyboard/account-policy.d.ts +2 -0
  154. package/dist/lib/testing/storyboard/account-policy.js +35 -0
  155. package/dist/lib/testing/storyboard/account-policy.mjs +11 -0
  156. package/dist/lib/testing/storyboard/context.js +6 -0
  157. package/dist/lib/testing/storyboard/context.mjs +6 -0
  158. package/dist/lib/testing/storyboard/request-builder.js +12 -2
  159. package/dist/lib/testing/storyboard/request-builder.mjs +12 -2
  160. package/dist/lib/testing/storyboard/runner.js +3 -2
  161. package/dist/lib/testing/storyboard/runner.mjs +3 -2
  162. package/dist/lib/testing/storyboard/validations.d.mts +1 -1
  163. package/dist/lib/testing/storyboard/validations.d.ts +1 -1
  164. package/dist/lib/version.d.mts +3 -3
  165. package/dist/lib/version.d.ts +3 -3
  166. package/dist/lib/version.js +3 -3
  167. package/dist/lib/version.mjs +3 -3
  168. package/dist/lib/wholesale-feed-sync/sync.d.mts +1 -0
  169. package/dist/lib/wholesale-feed-sync/sync.d.ts +1 -0
  170. package/dist/lib/wholesale-feed-sync/sync.js +92 -21
  171. package/dist/lib/wholesale-feed-sync/sync.mjs +92 -21
  172. package/dist/lib/wholesale-feed-sync/types.d.mts +4 -3
  173. package/dist/lib/wholesale-feed-sync/types.d.ts +4 -3
  174. package/docs/TYPE-SUMMARY.md +2 -2
  175. package/docs/guides/BUILD-AN-AGENT.md +2 -2
  176. package/docs/guides/BUYER-QUICKSTART-3.2.md +2 -0
  177. package/docs/guides/FIRST-CALL-TO-A-SELLER.md +104 -0
  178. package/docs/guides/SIGNING-GUIDE.md +16 -7
  179. package/docs/guides/account-resolution.md +86 -0
  180. package/docs/llms.txt +3 -2
  181. package/docs/migration-14.x-rc-worksheet.md +4 -4
  182. package/docs/migration-4.x-to-5.x.md +1 -0
  183. package/docs/migration-agent-resolution-3.3.md +123 -0
  184. package/docs/recipes/verifying-inbound-webhooks.md +56 -15
  185. package/package.json +2 -2
@@ -50,6 +50,7 @@ var import_request_proposals_guard = require('./request-proposals-guard.js');
50
50
  var import_task_deadline = require('./task-deadline.js');
51
51
  var import_auth = require('../auth/index.js');
52
52
  var import_abort = require('../protocols/abort.js');
53
+ var import_signedRequestRejection = require('../protocols/signedRequestRejection.js');
53
54
  var import_protocols = require('../protocols/index.js');
54
55
  var import_errors = require('../errors/index.js');
55
56
  var import_net = require('../net/index.js');
@@ -69,6 +70,7 @@ var crypto = __toESM(require("crypto"));
69
70
  var import_abort2 = require('../protocols/abort.js');
70
71
  var import_capabilities = require('../utils/capabilities.js');
71
72
  var import_errors3 = require('../errors/index.js');
73
+ var import_buyer_account_registry = require('./buyer-account-registry.js');
72
74
  var import_account_resolution = require('./account-resolution.js');
73
75
  var import_request_normalizer = require('../utils/request-normalizer.js');
74
76
  var import_global_async_local_storage = require('../utils/global-async-local-storage.js');
@@ -83,6 +85,8 @@ var import_augment_response = require('../v2/projection/augment-response.js');
83
85
  var import_legacy_metadata = require('../v2/projection/legacy-metadata.js');
84
86
  var import_types = require('../v2/projection/types.js');
85
87
  var import_jcs = require('../utils/jcs.js');
88
+ const SKIP_PRODUCT_CACHE = /* @__PURE__ */ Symbol("adcp.skipProductCache");
89
+ const SKIP_ACCOUNT_REGISTRY_OBSERVATION = /* @__PURE__ */ Symbol("adcp.skipAccountRegistryObservation");
86
90
  function presentedStaticTransportCredential(authToken, headers, authProvider) {
87
91
  if (authProvider) return false;
88
92
  if (authToken) return true;
@@ -765,6 +769,8 @@ class SingleAgentClient {
765
769
  };
766
770
  }
767
771
  this.normalizedAgent = this.normalizeAgentConfig(this.agent);
772
+ if (this.normalizedAgent.oauth_tokens && !this.normalizedAgent.oauth_client_credentials)
773
+ this.initialOAuthGrantMaterial = JSON.stringify(this.normalizedAgent.oauth_tokens);
768
774
  this.capabilityEvidenceAuthMaterial = this.currentCapabilityEvidenceAuthMaterial();
769
775
  this.executor = new import_TaskExecutor.TaskExecutor({
770
776
  workingTimeout: config.workingTimeout || 12e4,
@@ -833,6 +839,175 @@ class SingleAgentClient {
833
839
  }
834
840
  agent;
835
841
  config;
842
+ _accounts;
843
+ accountRegistryExplicitlyAccessed = false;
844
+ initialOAuthGrantMaterial;
845
+ accountCredentialMaterial;
846
+ accountCredentialScope;
847
+ credentialScope(material) {
848
+ if (this.accountCredentialMaterial !== material) {
849
+ this.accountCredentialScope = (0, import_node_crypto.scryptSync)(material, "adcp-sdk/account-registry-scope/v1", 32).toString("hex");
850
+ this.accountCredentialMaterial = material;
851
+ }
852
+ return this.accountCredentialScope;
853
+ }
854
+ accountScope() {
855
+ const agent = this.normalizedAgent ?? this.agent;
856
+ const cc = agent.oauth_client_credentials;
857
+ if (!cc && agent.oauth_tokens && !this.initialOAuthGrantMaterial)
858
+ this.initialOAuthGrantMaterial = JSON.stringify(agent.oauth_tokens);
859
+ const oauthIdentity = cc ? { client_id: cc.client_id, token_endpoint: cc.token_endpoint, scope: cc.scope, resource: cc.resource } : this.initialOAuthGrantMaterial;
860
+ const signing = agent.request_signing;
861
+ const signingIdentity = signing ? signing.kind === "provider" ? {
862
+ keyid: signing.provider.keyid,
863
+ algorithm: signing.provider.algorithm,
864
+ fingerprint: signing.provider.fingerprint,
865
+ purpose: signing.provider.adcpUse
866
+ } : { keyid: signing.kid, algorithm: signing.alg, key: signing.private_key } : void 0;
867
+ const credential = this.config.accountRegistryScope ?? this.credentialScope(
868
+ JSON.stringify({
869
+ token: agent.auth_token,
870
+ oauth: oauthIdentity,
871
+ oauthClient: agent.oauth_client?.client_id,
872
+ oauthResource: agent.oauth_resource,
873
+ headers: agent.headers,
874
+ signing: signingIdentity
875
+ })
876
+ );
877
+ return JSON.stringify([this.agent.agent_uri, this.agent.protocol, credential]);
878
+ }
879
+ get accounts() {
880
+ this.accountRegistryExplicitlyAccessed = true;
881
+ return this.getAccountRegistry();
882
+ }
883
+ getAccountRegistry() {
884
+ return this._accounts ??= new import_buyer_account_registry.BuyerAccountRegistry(
885
+ () => this.accountScope(),
886
+ async (account, options, taskOptions) => {
887
+ const caps = await this.getCapabilities(taskOptions);
888
+ const supported = caps.account?.supportedBilling ?? [];
889
+ const billing = options.billing ?? caps.account?.defaultBilling ?? (supported.length === 1 ? supported[0] : void 0);
890
+ if (!billing || supported.length && !supported.includes(billing)) {
891
+ throw new import_errors3.AccountRequiredError(
892
+ "implicit",
893
+ "sync_accounts",
894
+ "Choose a supported billing party before provisioning."
895
+ );
896
+ }
897
+ return this.syncAccounts(
898
+ {
899
+ accounts: [
900
+ {
901
+ ...account,
902
+ billing,
903
+ ...options.paymentTerms !== void 0 && { payment_terms: options.paymentTerms },
904
+ ...options.billingEntity !== void 0 && { billing_entity: options.billingEntity }
905
+ }
906
+ ]
907
+ },
908
+ void 0,
909
+ taskOptions
910
+ );
911
+ },
912
+ this.config.accountStorage,
913
+ async (accountId, options) => {
914
+ const rows = [];
915
+ const cursors = /* @__PURE__ */ new Set();
916
+ let cursor;
917
+ for (let page = 0; page < 100; page++) {
918
+ const result = await this.listAccounts(
919
+ { account: { account_id: accountId }, ...cursor && { pagination: { cursor } } },
920
+ void 0,
921
+ { ...options, [SKIP_ACCOUNT_REGISTRY_OBSERVATION]: true }
922
+ );
923
+ if (!result.success || result.status !== "completed" || !result.data || !("accounts" in result.data))
924
+ throw new Error("Account status reconciliation failed.");
925
+ rows.push(...result.data.accounts);
926
+ if (rows.some((row) => row.account_id === accountId) || !result.data.pagination?.has_more)
927
+ return rows.filter((row) => row.account_id === accountId);
928
+ const next = result.data.pagination.cursor;
929
+ if (!next || cursors.has(next)) break;
930
+ cursors.add(next);
931
+ cursor = next;
932
+ }
933
+ throw new Error("Account status reconciliation could not complete pagination.");
934
+ },
935
+ {
936
+ maxEntries: this.config.accountRegistryMaxEntries,
937
+ normalizeOptions: async (options, taskOptions) => {
938
+ if (options.billing) return options;
939
+ const caps = await this.getCapabilities(taskOptions);
940
+ const supported = caps.account?.supportedBilling ?? [];
941
+ const billing = caps.account?.defaultBilling ?? (supported.length === 1 ? supported[0] : void 0);
942
+ return { ...options, ...billing && { billing } };
943
+ }
944
+ }
945
+ );
946
+ }
947
+ /**
948
+ * The memoized registry backs `resolveAccount()` only when the caller opts
949
+ * in with an account policy or registry configuration. Otherwise
950
+ * `resolveAccount()` keeps the SDK 14.0 sync-on-every-call behavior.
951
+ */
952
+ accountRegistryOptedIn() {
953
+ return (this.config.accountPolicy ?? "off") !== "off" || this.config.accountStorage !== void 0 || this.config.accountRegistryScope !== void 0 || this.config.accountRegistryMaxEntries !== void 0;
954
+ }
955
+ accountRegistryContext(task, params, options) {
956
+ const knownOnly = !this.accountRegistryExplicitlyAccessed && (this.config.accountPolicy ?? "off") === "off" && !this.config.accountStorage;
957
+ if (knownOnly && !this._accounts) return void 0;
958
+ if (options?.[SKIP_ACCOUNT_REGISTRY_OBSERVATION])
959
+ return void 0;
960
+ if (task !== "sync_accounts" && task !== "list_accounts") return void 0;
961
+ return {
962
+ scope: this.accountScope(),
963
+ ...knownOnly && { knownOnly: true },
964
+ observationEpoch: this.getAccountRegistry().captureObservation(),
965
+ ...task === "list_accounts" && params.account && { refs: [params.account] },
966
+ ...task === "sync_accounts" && {
967
+ refs: Array.isArray(params.accounts) ? params.accounts.flatMap((value) => {
968
+ const ref = canonicalAccountRoutingSnapshot(value);
969
+ return ref ? [ref] : [];
970
+ }) : [],
971
+ dryRun: params.dry_run === true
972
+ }
973
+ };
974
+ }
975
+ async applyAccountPolicy(task, params, options) {
976
+ const policy = this.config.accountPolicy ?? "off";
977
+ const ref = params?.account ?? (typeof params?.account_id === "string" ? { account_id: params.account_id } : void 0);
978
+ if (policy === "off" || options?.skipAccountValidation || options?.preserveGovernedPayload || !ref || task === "list_accounts")
979
+ return params;
980
+ if (typeof ref !== "object" || ref === null || !("account_id" in ref) && (typeof ref.brand?.domain !== "string" || typeof ref.operator !== "string"))
981
+ return params;
982
+ const known = await this.getAccountRegistry().get(ref);
983
+ if (known && !["unknown", "provisioning", "failed_provisioning"].includes(known.status)) {
984
+ if (["create_media_buy", "buy_products", "accept_proposal", "activate_signal", "acquire_rights"].includes(task) && known.status !== "active") {
985
+ if (known.status === "pending_approval") throw new import_errors3.AccountPendingApprovalError(ref, known.account_id);
986
+ if (known.status === "payment_required") throw new import_errors3.AccountPaymentRequiredError();
987
+ throw new import_errors3.AccountSetupRequiredError(
988
+ `Account status is ${known.status}. Refresh it with client.accounts.applyStatusChange or complete seller setup.`
989
+ );
990
+ }
991
+ return params;
992
+ }
993
+ if (policy === "strict" || ![
994
+ "get_products",
995
+ "list_products",
996
+ "get_signals",
997
+ "request_proposals",
998
+ "refine_proposals",
999
+ "decline_proposals"
1000
+ ].includes(task)) {
1001
+ throw new import_errors3.AccountNotProvisionedError(ref, task);
1002
+ }
1003
+ const caps = await this.getCapabilities(options);
1004
+ if (caps._synthetic || ["get_products", "list_products"].includes(task) && caps.account?.requiredForProducts || params.push_notification_config || !(0, import_schema_loader.schemaAllowsTopLevelField)(task, "brand")) {
1005
+ throw new import_errors3.AccountNotProvisionedError(ref, task);
1006
+ }
1007
+ if (!("brand" in ref)) throw new import_errors3.AccountNotProvisionedError(ref, task);
1008
+ const { account, ...publicRequest } = params;
1009
+ return { ...publicRequest, brand: params.brand ?? ref.brand };
1010
+ }
836
1011
  executor;
837
1012
  asyncHandler;
838
1013
  normalizedAgent;
@@ -999,6 +1174,7 @@ class SingleAgentClient {
999
1174
  } = configuredResolverOptions ?? {};
1000
1175
  const resolver = new import_server.ResolvedAgentJwksResolver(registration.agentUrl, registration.protocol, {
1001
1176
  ...resolverOptionsWithoutOperatorContext,
1177
+ legacyWebhookFallback: configuredResolverOptions?.legacyWebhookFallback ?? true,
1002
1178
  ...delegatedOperatorAuthorization?.brand !== void 0 && {
1003
1179
  requiredOperatorBrand: delegatedOperatorAuthorization.brand
1004
1180
  },
@@ -1766,6 +1942,8 @@ class SingleAgentClient {
1766
1942
  }
1767
1943
  return { success: true };
1768
1944
  } catch (error) {
1945
+ const signedRejection = (0, import_signedRequestRejection.getSignedRequestRejection)(error);
1946
+ if (signedRejection) throw signedRejection;
1769
1947
  if ((0, import_abort.isAbortOrTimeoutError)(error)) {
1770
1948
  throw error;
1771
1949
  }
@@ -2078,6 +2256,8 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
2078
2256
  },
2079
2257
  {
2080
2258
  jwks: this.webhookJwksFor(registration),
2259
+ publisherPins: await this.config.webhookVerification?.publisherPins?.(registration),
2260
+ onKeyResolutionError: this.config.webhookVerification?.onKeyResolutionError,
2081
2261
  replayStore: this.webhookReplayStore,
2082
2262
  revocationStore: this.webhookRevocationStore,
2083
2263
  ...this.config.webhookVerification?.now && { now: this.config.webhookVerification.now },
@@ -2089,6 +2269,13 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
2089
2269
  );
2090
2270
  } catch (cause) {
2091
2271
  if (cause instanceof import_server.WebhookSignatureError) {
2272
+ if (cause.retryable)
2273
+ return {
2274
+ ok: false,
2275
+ code: "webhook_verification_unavailable",
2276
+ message: "Seller signing keys could not be resolved for webhook verification.",
2277
+ cause
2278
+ };
2092
2279
  return { ok: false, code: cause.code, message: cause.message, cause };
2093
2280
  }
2094
2281
  if (cause instanceof import_errors2.AgentResolverError && import_enums.RequestSigningErrorCodeMetadata[cause.code].recovery !== "transient") {
@@ -2910,6 +3097,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
2910
3097
  async executeAndHandleWithinDeadline(taskType, handlerName, params, inputHandler, options, transformCompletedResponse, legacyFormatConverter, canonicalRequest, projectionCatalogs) {
2911
3098
  (0, import_abort2.throwIfAborted)(options?.signal);
2912
3099
  const canonicalCreativeInvocation = CANONICAL_CREATIVE_ACTIVITY_TASKS.has(taskType) || canonicalRequest !== void 0;
3100
+ params = await this.applyAccountPolicy(taskType, params, options);
2913
3101
  let normalizedParams = options?.preserveGovernedPayload ? params : (0, import_request_normalizer.normalizeRequestParams)(taskType, params, {
2914
3102
  skipIdempotencyAutoInject: options?.skipIdempotencyAutoInject,
2915
3103
  skipAccountValidation: options?.skipAccountValidation
@@ -2993,6 +3181,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
2993
3181
  serverVersionSynthetic: capabilityDiscoveryContext.capabilities._synthetic
2994
3182
  },
2995
3183
  productPolicyRequest: productPolicyRequestSnapshot(normalizedParams),
3184
+ accountRegistry: this.accountRegistryContext(taskType, normalizedParams, effectiveOptions),
2996
3185
  ...projectionCatalogs !== void 0 && { projectionCatalogs },
2997
3186
  ...routingSnapshot !== void 0 && { routingSnapshot },
2998
3187
  ...effectiveOptions?.taskId !== void 0 && { optionTaskId: effectiveOptions.taskId },
@@ -3057,6 +3246,53 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
3057
3246
  const completionHandlerAlreadyPublished = (0, import_TaskExecutor.hasCompletionHandlerAlreadyPublished)(result);
3058
3247
  const settlementAcknowledger = result[import_TaskExecutor.DEFERRED_SETTLEMENT_ACK];
3059
3248
  const taskType = context.taskType;
3249
+ if (context.accountRegistry !== void 0 && context.accountRegistry.scope === this.accountScope() && result.success && result.status === "completed" && result.data && typeof result.data === "object" && "accounts" in result.data && Array.isArray(result.data.accounts)) {
3250
+ try {
3251
+ const registry = this.getAccountRegistry();
3252
+ let refs = context.accountRegistry.refs ?? [];
3253
+ let rows = result.data.accounts;
3254
+ if (context.accountRegistry.knownOnly) {
3255
+ refs = (await Promise.all(refs.map(async (ref) => await registry.get(ref) ? ref : void 0))).filter(
3256
+ (ref) => ref !== void 0
3257
+ );
3258
+ if (taskType === "list_accounts") {
3259
+ rows = (await Promise.all(
3260
+ result.data.accounts.map(async (row) => {
3261
+ const ref = canonicalAccountRoutingSnapshot(row);
3262
+ if (ref && await registry.get(ref)) return row;
3263
+ const natural = canonicalAccountRoutingSnapshot({ ...row, account_id: void 0 });
3264
+ return natural && await registry.get(natural) ? row : void 0;
3265
+ })
3266
+ )).filter((row) => row !== void 0);
3267
+ }
3268
+ }
3269
+ if (context.accountRegistry.scope !== this.accountScope()) return result;
3270
+ if (taskType === "sync_accounts")
3271
+ await registry.observeSync(
3272
+ refs,
3273
+ rows,
3274
+ context.accountRegistry.dryRun,
3275
+ context.accountRegistry.observationEpoch
3276
+ );
3277
+ if (taskType === "list_accounts") {
3278
+ const ref = refs[0];
3279
+ await registry.observeList(
3280
+ rows,
3281
+ ref && "account_id" in ref && (!result.data.pagination?.has_more || result.data.accounts.some((row) => row.account_id === ref.account_id)) ? ref.account_id : void 0,
3282
+ context.accountRegistry.observationEpoch
3283
+ );
3284
+ }
3285
+ } catch {
3286
+ result.debug_logs = [
3287
+ ...result.debug_logs ?? [],
3288
+ {
3289
+ level: "warn",
3290
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
3291
+ message: "Account registry observation failed. The seller operation completed; reconcile with listAccounts before relying on the registry."
3292
+ }
3293
+ ];
3294
+ }
3295
+ }
3060
3296
  const resumedOptions = {
3061
3297
  ...options ?? {},
3062
3298
  ...context.optionTaskId !== void 0 && { taskId: context.optionTaskId },
@@ -4076,7 +4312,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
4076
4312
  );
4077
4313
  return (0, import_task_deadline.withTaskDeadline)(snapshotTaskOptions(taskOptions), async (effectiveOptions) => {
4078
4314
  this.assertRequestSupportedByConfiguredVersion("get_products", params, effectiveOptions);
4079
- let request = params;
4315
+ let request = await this.applyAccountPolicy("get_products", params, effectiveOptions);
4080
4316
  const legacyAccountId = request.account_id;
4081
4317
  const accountReference = request.account ?? (typeof legacyAccountId === "string" && legacyAccountId ? { account_id: legacyAccountId } : void 0);
4082
4318
  if (!request.account && typeof legacyAccountId === "string" && legacyAccountId) {
@@ -4113,10 +4349,36 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
4113
4349
  request = { ...request, buying_mode: "wholesale" };
4114
4350
  }
4115
4351
  const account = canonicalAccountRoutingSnapshot(accountReference);
4116
- return this.executeAndHandle(
4352
+ const cache = !effectiveOptions.skipRequestValidation && !effectiveOptions.preserveGovernedPayload && !inputHandler && !request.push_notification_config && !this.config.webhookUrlTemplate && !this.config.handlers?.onGetProductsStatusChange ? this.config.productCache : void 0;
4353
+ const cacheScope = cache ? JSON.stringify([
4354
+ this.accountScope(),
4355
+ this.resolvedAdcpVersion,
4356
+ this.capabilityEvidenceScopeKey,
4357
+ effectiveOptions.contextId
4358
+ ]) : "";
4359
+ const cacheParams = request;
4360
+ const skipCacheRead = options?.[SKIP_PRODUCT_CACHE];
4361
+ if (cache && !skipCacheRead && cacheParams.if_wholesale_feed_version === void 0 && cacheParams.if_pricing_version === void 0) {
4362
+ const hit = cache.read(cacheScope, cacheParams);
4363
+ if (hit) {
4364
+ (0, import_abort2.throwIfAborted)(effectiveOptions.signal);
4365
+ if (hit.success && hit.status === "completed")
4366
+ this.rememberCanonicalProductRoutes(hit.data.products ?? [], account, hit.data.products ?? []);
4367
+ return (0, import_match.attachMatch)(
4368
+ await this.applyProductPropertyPolicy(
4369
+ hit,
4370
+ "get_products",
4371
+ productPolicyRequestSnapshot(request),
4372
+ effectiveOptions.signal
4373
+ )
4374
+ );
4375
+ }
4376
+ }
4377
+ const conditionalSnapshot = skipCacheRead ? void 0 : cache?.read(cacheScope, cacheParams, true);
4378
+ const result = await this.executeAndHandle(
4117
4379
  "get_products",
4118
4380
  "onGetProductsStatusChange",
4119
- request,
4381
+ cache && !skipCacheRead ? cache.conditionalParams(cacheScope, cacheParams) : request,
4120
4382
  inputHandler,
4121
4383
  effectiveOptions,
4122
4384
  (data) => {
@@ -4134,6 +4396,37 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
4134
4396
  void 0,
4135
4397
  projectionCatalogs
4136
4398
  );
4399
+ const finishCache = async (completed) => {
4400
+ if (!cache) return completed;
4401
+ const cachedResult = cache.write(cacheScope, cacheParams, completed, conditionalSnapshot);
4402
+ if (cachedResult.success && cachedResult.status === "completed") {
4403
+ if (!skipCacheRead && cacheParams.if_wholesale_feed_version === void 0 && cacheParams.if_pricing_version === void 0 && cachedResult.data.unchanged === true) {
4404
+ return this.getProducts(params, inputHandler, {
4405
+ ...options,
4406
+ ...effectiveOptions,
4407
+ [SKIP_PRODUCT_CACHE]: true
4408
+ });
4409
+ }
4410
+ this.rememberCanonicalProductRoutes(
4411
+ cachedResult.data.products ?? [],
4412
+ account,
4413
+ cachedResult.data.products ?? []
4414
+ );
4415
+ }
4416
+ if (cachedResult.submitted) {
4417
+ const submitted = cachedResult.submitted;
4418
+ cachedResult.submitted = {
4419
+ ...submitted,
4420
+ waitForCompletion: (interval, signal) => submitted.waitForCompletion(interval, signal).then(finishCache)
4421
+ };
4422
+ }
4423
+ if (cachedResult.deferred) {
4424
+ const deferred = cachedResult.deferred;
4425
+ cachedResult.deferred = { ...deferred, resume: (input) => deferred.resume(input).then(finishCache) };
4426
+ }
4427
+ return (0, import_match.attachMatch)(cachedResult);
4428
+ };
4429
+ return finishCache(result);
4137
4430
  });
4138
4431
  }
4139
4432
  /** Discover products through the compact AdCP 3.2 catalog task. */
@@ -4872,7 +5165,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
4872
5165
  const seenCursors = /* @__PURE__ */ new Set();
4873
5166
  let cursor;
4874
5167
  for (let page = 0; page < 100; page++) {
4875
- const result2 = await this.listAccounts(
5168
+ const result = await this.listAccounts(
4876
5169
  {
4877
5170
  status: "active",
4878
5171
  sandbox: hints.sandbox ?? false,
@@ -4881,13 +5174,13 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
4881
5174
  void 0,
4882
5175
  effectiveOptions
4883
5176
  );
4884
- onTaskResult?.(result2);
4885
- if (!result2.success || result2.status !== "completed" || !result2.data || !("accounts" in result2.data) || !Array.isArray(result2.data.accounts)) {
5177
+ onTaskResult?.(result);
5178
+ if (!result.success || result.status !== "completed" || !result.data || !("accounts" in result.data) || !Array.isArray(result.data.accounts)) {
4886
5179
  throw new Error("list_accounts did not return a completed account list.");
4887
5180
  }
4888
- accounts.push(...result2.data.accounts);
4889
- if (!result2.data.pagination?.has_more) return (0, import_account_resolution.selectListedAccount)(accounts, hints);
4890
- const nextCursor = result2.data.pagination.cursor;
5181
+ accounts.push(...result.data.accounts);
5182
+ if (!result.data.pagination?.has_more) return (0, import_account_resolution.selectListedAccount)(accounts, hints);
5183
+ const nextCursor = result.data.pagination.cursor;
4891
5184
  if (!nextCursor || seenCursors.has(nextCursor)) break;
4892
5185
  seenCursors.add(nextCursor);
4893
5186
  cursor = nextCursor;
@@ -4954,35 +5247,60 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
4954
5247
  `Choose a supported billing party for sync_accounts (seller supports: ${supportedBilling.join(", ") || "(none)"}).`
4955
5248
  );
4956
5249
  }
4957
- const result = await this.syncAccounts(
4958
- {
4959
- accounts: [
4960
- {
4961
- ...account,
4962
- billing
4963
- }
4964
- ]
4965
- },
4966
- void 0,
4967
- effectiveOptions
4968
- );
4969
- onTaskResult?.(result);
4970
- if (!result.success || result.status !== "completed" || !result.data || !("accounts" in result.data) || !Array.isArray(result.data.accounts)) {
4971
- throw new Error("sync_accounts did not return a completed account result.");
4972
- }
4973
- const synced = result.data.accounts.find(
4974
- (row) => row.brand?.domain === hints.brand.domain && row.operator === hints.operator && (!hints.brand.brand_id || row.brand.brand_id === hints.brand.brand_id) && (0, import_account_resolution.sameCountrySet)(hints.brand.countries, row.brand.countries) && (!hints.operatorUnit || row.operator_unit?.id === hints.operatorUnit.id) && (!hints.currency || row.currency === hints.currency) && (!hints.timezone || row.timezone === hints.timezone) && (row.sandbox === void 0 || row.sandbox === true === (hints.sandbox === true))
4975
- );
4976
- if (synced?.status === "pending_approval") {
4977
- throw new import_errors3.AccountPendingApprovalError(account, synced.account_id);
5250
+ if (!this.accountRegistryOptedIn()) {
5251
+ const result = await this.syncAccounts(
5252
+ {
5253
+ accounts: [
5254
+ {
5255
+ ...account,
5256
+ billing,
5257
+ ...hints.paymentTerms !== void 0 && { payment_terms: hints.paymentTerms },
5258
+ ...hints.billingEntity !== void 0 && { billing_entity: hints.billingEntity }
5259
+ }
5260
+ ]
5261
+ },
5262
+ void 0,
5263
+ effectiveOptions
5264
+ );
5265
+ onTaskResult?.(result);
5266
+ if (!result.success || result.status !== "completed" || !result.data || !("accounts" in result.data) || !Array.isArray(result.data.accounts)) {
5267
+ throw new Error("sync_accounts did not return a completed account result.");
5268
+ }
5269
+ const syncedRow = result.data.accounts.find(
5270
+ (row) => row.brand?.domain === hints.brand.domain && row.operator === hints.operator && (!hints.brand.brand_id || row.brand.brand_id === hints.brand.brand_id) && (0, import_account_resolution.sameCountrySet)(hints.brand.countries, row.brand.countries) && (!hints.operatorUnit || row.operator_unit?.id === hints.operatorUnit.id) && (!hints.currency || row.currency === hints.currency) && (!hints.timezone || row.timezone === hints.timezone) && (row.sandbox === void 0 || row.sandbox === true === (hints.sandbox === true))
5271
+ );
5272
+ if (syncedRow?.status === "pending_approval") {
5273
+ throw new import_errors3.AccountPendingApprovalError(account, syncedRow.account_id);
5274
+ }
5275
+ if (!syncedRow || syncedRow.action === "failed" || syncedRow.status !== "active") {
5276
+ throw new import_errors3.AccountRequiredError(
5277
+ "implicit",
5278
+ "resolveAccount",
5279
+ "sync_accounts did not establish an active account for the requested brand and operator."
5280
+ );
5281
+ }
5282
+ return account;
4978
5283
  }
4979
- if (!synced || synced.action === "failed" || synced.status !== "active") {
4980
- throw new import_errors3.AccountRequiredError(
4981
- "implicit",
4982
- "resolveAccount",
4983
- "sync_accounts did not establish an active account for the requested brand and operator."
5284
+ let synced;
5285
+ try {
5286
+ synced = await this.getAccountRegistry().ensure(
5287
+ account,
5288
+ {
5289
+ billing,
5290
+ paymentTerms: hints.paymentTerms,
5291
+ billingEntity: hints.billingEntity
5292
+ },
5293
+ effectiveOptions,
5294
+ onTaskResult
4984
5295
  );
5296
+ } catch (error) {
5297
+ if (error instanceof import_errors3.AccountNotFoundError)
5298
+ throw new import_errors3.AccountRequiredError("implicit", "resolveAccount", error.message);
5299
+ throw error;
4985
5300
  }
5301
+ if (synced.status === "pending_approval") throw new import_errors3.AccountPendingApprovalError(account, synced.account_id);
5302
+ if (synced.status !== "active")
5303
+ throw new import_errors3.AccountRequiredError("implicit", "resolveAccount", "The account is not active.");
4986
5304
  return account;
4987
5305
  });
4988
5306
  }
@@ -5253,6 +5571,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
5253
5571
  const startTime = Date.now();
5254
5572
  let detectedServerVersion;
5255
5573
  let detectedServerVersionSynthetic;
5574
+ params = await this.applyAccountPolicy(taskName, params, options);
5256
5575
  try {
5257
5576
  const normalizedParams = options?.preserveGovernedPayload ? params : (0, import_request_normalizer.normalizeRequestParams)(taskName, params, {
5258
5577
  skipIdempotencyAutoInject: options?.skipIdempotencyAutoInject,
@@ -5318,6 +5637,7 @@ Hint: this usually means agent_uri does not include the MCP endpoint path. The S
5318
5637
  serverVersionSynthetic: capabilityDiscoveryContext.capabilities._synthetic
5319
5638
  },
5320
5639
  productPolicyRequest: productPolicyRequestSnapshot(normalizedParams),
5640
+ accountRegistry: this.accountRegistryContext(taskName, normalizedParams, effectiveOptions),
5321
5641
  ...effectiveOptions?.taskId !== void 0 && { optionTaskId: effectiveOptions.taskId },
5322
5642
  ...effectiveOptions?.contextId !== void 0 && { optionContextId: effectiveOptions.contextId }
5323
5643
  };