@adcp/sdk 17.0.0-beta.2 → 17.0.0-beta.3

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 (60) hide show
  1. package/dist/lib/adapters/version/index.d.mts +9 -0
  2. package/dist/lib/adapters/version/index.d.ts +9 -0
  3. package/dist/lib/adapters/version/index.js +20 -6
  4. package/dist/lib/adapters/version/index.mjs +15 -2
  5. package/dist/lib/identity-3.3/trust.js +9 -2
  6. package/dist/lib/identity-3.3/trust.mjs +9 -2
  7. package/dist/lib/server/a2a-adapter.js +2 -1
  8. package/dist/lib/server/a2a-adapter.mjs +2 -1
  9. package/dist/lib/server/auth-signature.d.mts +2 -2
  10. package/dist/lib/server/auth-signature.d.ts +2 -2
  11. package/dist/lib/server/auth-signature.js +3 -0
  12. package/dist/lib/server/auth-signature.mjs +3 -0
  13. package/dist/lib/server/create-adcp-server.d.mts +2 -2
  14. package/dist/lib/server/create-adcp-server.d.ts +2 -2
  15. package/dist/lib/server/create-adcp-server.js +25 -3
  16. package/dist/lib/server/create-adcp-server.mjs +25 -3
  17. package/dist/lib/server/serve.js +3 -1
  18. package/dist/lib/server/serve.mjs +3 -1
  19. package/dist/lib/server/signed-request-transport.d.mts +1 -0
  20. package/dist/lib/server/signed-request-transport.d.ts +1 -0
  21. package/dist/lib/server/signed-request-transport.js +46 -0
  22. package/dist/lib/server/signed-request-transport.mjs +20 -0
  23. package/dist/lib/server/test-controller.d.mts +1 -0
  24. package/dist/lib/server/test-controller.d.ts +1 -0
  25. package/dist/lib/server/test-controller.js +5 -1
  26. package/dist/lib/server/test-controller.mjs +5 -1
  27. package/dist/lib/testing/index.d.mts +1 -0
  28. package/dist/lib/testing/index.d.ts +1 -0
  29. package/dist/lib/testing/index.js +3 -0
  30. package/dist/lib/testing/index.mjs +2 -0
  31. package/dist/lib/testing/storyboard/canonical-format-satisfaction.js +1 -15
  32. package/dist/lib/testing/storyboard/canonical-format-satisfaction.mjs +1 -15
  33. package/dist/lib/testing/storyboard/index.d.mts +1 -0
  34. package/dist/lib/testing/storyboard/index.d.ts +1 -0
  35. package/dist/lib/testing/storyboard/index.js +3 -0
  36. package/dist/lib/testing/storyboard/index.mjs +2 -0
  37. package/dist/lib/testing/storyboard/loader.js +7 -0
  38. package/dist/lib/testing/storyboard/loader.mjs +7 -0
  39. package/dist/lib/testing/storyboard/request-builder.js +9 -6
  40. package/dist/lib/testing/storyboard/request-builder.mjs +9 -6
  41. package/dist/lib/testing/storyboard/runner.js +59 -6
  42. package/dist/lib/testing/storyboard/runner.mjs +59 -6
  43. package/dist/lib/testing/storyboard/types.d.mts +18 -0
  44. package/dist/lib/testing/storyboard/types.d.ts +18 -0
  45. package/dist/lib/testing/storyboard/validations.d.mts +1 -1
  46. package/dist/lib/testing/storyboard/validations.d.ts +1 -1
  47. package/dist/lib/testing/storyboard/web-bot-auth.d.mts +10 -0
  48. package/dist/lib/testing/storyboard/web-bot-auth.d.ts +10 -0
  49. package/dist/lib/testing/storyboard/web-bot-auth.js +80 -0
  50. package/dist/lib/testing/storyboard/web-bot-auth.mjs +56 -0
  51. package/dist/lib/version.d.mts +3 -3
  52. package/dist/lib/version.d.ts +3 -3
  53. package/dist/lib/version.js +3 -3
  54. package/dist/lib/version.mjs +3 -3
  55. package/docs/TYPE-SUMMARY.md +2 -2
  56. package/docs/llms.txt +2 -2
  57. package/docs/migration-14.x-rc-worksheet.md +4 -4
  58. package/docs/migration-16-to-17.md +27 -0
  59. package/docs/migration-agent-identity-3.3.md +106 -4
  60. package/package.json +15 -2
@@ -88,3 +88,12 @@ export declare function downgradeResponse<T>(toolName: string, data: T, options:
88
88
  data: T;
89
89
  drifts: import('./types.mjs').VersionDrift[];
90
90
  };
91
+ /**
92
+ * Project a seller-owned webhook result with the same per-release conversion
93
+ * as framework responses. Pass the originating request's `ctx.servedAdcpVersion`;
94
+ * when the server uses another source release, pass it as `fromVersion`.
95
+ * Envelope construction, credential stripping and webhook signing remain the
96
+ * emitter's responsibility. The input is never mutated.
97
+ * Use `downgradeResponse` when translation diagnostics are also needed.
98
+ */
99
+ export declare function projectResponseForRelease<T>(toolName: string, payload: T, servedAdcpVersion: string, fromVersion?: string): T;
@@ -88,3 +88,12 @@ export declare function downgradeResponse<T>(toolName: string, data: T, options:
88
88
  data: T;
89
89
  drifts: import('./types').VersionDrift[];
90
90
  };
91
+ /**
92
+ * Project a seller-owned webhook result with the same per-release conversion
93
+ * as framework responses. Pass the originating request's `ctx.servedAdcpVersion`;
94
+ * when the server uses another source release, pass it as `fromVersion`.
95
+ * Envelope construction, credential stripping and webhook signing remain the
96
+ * emitter's responsibility. The input is never mutated.
97
+ * Use `downgradeResponse` when translation diagnostics are also needed.
98
+ */
99
+ export declare function projectResponseForRelease<T>(toolName: string, payload: T, servedAdcpVersion: string, fromVersion?: string): T;
@@ -18,16 +18,17 @@ var __copyProps = (to, from, except, desc) => {
18
18
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
19
  var version_exports = {};
20
20
  __export(version_exports, {
21
- adcpMinorLine: () => import_negotiate.adcpMinorLine,
22
- compareAdcpMinorLines: () => import_negotiate.compareAdcpMinorLines,
21
+ adcpMinorLine: () => import_negotiate2.adcpMinorLine,
22
+ compareAdcpMinorLines: () => import_negotiate2.compareAdcpMinorLines,
23
23
  convertRequest: () => convertRequest,
24
24
  convertResponse: () => convertResponse,
25
25
  downgradeResponse: () => downgradeResponse,
26
26
  getVersionAdapter: () => getVersionAdapter,
27
- isNegotiationFailure: () => import_negotiate.isNegotiationFailure,
27
+ isNegotiationFailure: () => import_negotiate2.isNegotiationFailure,
28
28
  listVersionAdapterTools: () => listVersionAdapterTools,
29
- negotiateAdcpRelease: () => import_negotiate.negotiateAdcpRelease,
30
- parseAdcpRelease: () => import_negotiate.parseAdcpRelease,
29
+ negotiateAdcpRelease: () => import_negotiate2.negotiateAdcpRelease,
30
+ parseAdcpRelease: () => import_negotiate2.parseAdcpRelease,
31
+ projectResponseForRelease: () => projectResponseForRelease,
31
32
  projectToolPayload: () => import_schema_projection.projectToolPayload,
32
33
  releaseDefinesTool: () => import_schema_projection.releaseDefinesTool,
33
34
  resolveAdapterKey: () => resolveAdapterKey,
@@ -36,12 +37,15 @@ __export(version_exports, {
36
37
  });
37
38
  module.exports = __toCommonJS(version_exports);
38
39
  var import_adcp_version_config = require('../../utils/adcp-version-config.js');
40
+ var import_version = require('../../version.js');
41
+ var import_negotiate = require('./negotiate.js');
42
+ var import_schema_loader = require('../../validation/schema-loader.js');
39
43
  var import_idempotency = require('../../utils/idempotency.js');
40
44
  var import__ = require('./3.0/index.js');
41
45
  var import__2 = require('./3.1/index.js');
42
46
  var import_translate = require('./translate.js');
43
47
  var import_translate2 = require('./translate.js');
44
- var import_negotiate = require('./negotiate.js');
48
+ var import_negotiate2 = require('./negotiate.js');
45
49
  var import_schema_projection = require('./schema-projection.js');
46
50
  const REGISTRY = /* @__PURE__ */ new Map();
47
51
  function register(version, adapters) {
@@ -77,6 +81,15 @@ function upgradeRequest(toolName, params, options) {
77
81
  function downgradeResponse(toolName, data, options) {
78
82
  return (0, import_translate.convertResponseToRelease)(toolName, data, { ...options, adapters: getVersionAdapter });
79
83
  }
84
+ function projectResponseForRelease(toolName, payload, servedAdcpVersion, fromVersion = import_version.ADCP_VERSION) {
85
+ const source = typeof fromVersion === "string" ? (0, import_negotiate.parseAdcpRelease)(fromVersion) : void 0;
86
+ const target = typeof servedAdcpVersion === "string" ? (0, import_negotiate.parseAdcpRelease)(servedAdcpVersion) : void 0;
87
+ if (!source || !target || source.major !== 3 || target.major !== 3 || target.minor > source.minor || source.minor === target.minor && source.prerelease !== target.prerelease || !(0, import_schema_loader.hasSchemaBundle)(fromVersion) || !(0, import_schema_loader.hasSchemaBundle)(servedAdcpVersion))
88
+ throw new TypeError(
89
+ "projectResponseForRelease requires valid AdCP 3 schema bundles, with the served minor line on or below the source and matching same-line previews"
90
+ );
91
+ return downgradeResponse(toolName, payload, { fromVersion, toVersion: servedAdcpVersion }).data;
92
+ }
80
93
  // Annotate the CommonJS export names for ESM import in node:
81
94
  0 && (module.exports = {
82
95
  adcpMinorLine,
@@ -89,6 +102,7 @@ function downgradeResponse(toolName, data, options) {
89
102
  listVersionAdapterTools,
90
103
  negotiateAdcpRelease,
91
104
  parseAdcpRelease,
105
+ projectResponseForRelease,
92
106
  projectToolPayload,
93
107
  releaseDefinesTool,
94
108
  resolveAdapterKey,
@@ -1,4 +1,7 @@
1
1
  import { shouldOmit31Fields } from "../../utils/adcp-version-config.mjs";
2
+ import { ADCP_VERSION } from "../../version.mjs";
3
+ import { parseAdcpRelease } from "./negotiate.mjs";
4
+ import { hasSchemaBundle } from "../../validation/schema-loader.mjs";
2
5
  import { isMutatingTask } from "../../utils/idempotency.mjs";
3
6
  import { v30Adapters } from "./3.0/index.mjs";
4
7
  import { v31Adapters } from "./3.1/index.mjs";
@@ -12,7 +15,7 @@ import { translationSteps } from "./translate.mjs";
12
15
  import {
13
16
  negotiateAdcpRelease,
14
17
  isNegotiationFailure,
15
- parseAdcpRelease,
18
+ parseAdcpRelease as parseAdcpRelease2,
16
19
  adcpMinorLine,
17
20
  compareAdcpMinorLines
18
21
  } from "./negotiate.mjs";
@@ -51,6 +54,15 @@ function upgradeRequest(toolName, params, options) {
51
54
  function downgradeResponse(toolName, data, options) {
52
55
  return convertResponseToRelease(toolName, data, { ...options, adapters: getVersionAdapter });
53
56
  }
57
+ function projectResponseForRelease(toolName, payload, servedAdcpVersion, fromVersion = ADCP_VERSION) {
58
+ const source = typeof fromVersion === "string" ? parseAdcpRelease(fromVersion) : void 0;
59
+ const target = typeof servedAdcpVersion === "string" ? parseAdcpRelease(servedAdcpVersion) : void 0;
60
+ if (!source || !target || source.major !== 3 || target.major !== 3 || target.minor > source.minor || source.minor === target.minor && source.prerelease !== target.prerelease || !hasSchemaBundle(fromVersion) || !hasSchemaBundle(servedAdcpVersion))
61
+ throw new TypeError(
62
+ "projectResponseForRelease requires valid AdCP 3 schema bundles, with the served minor line on or below the source and matching same-line previews"
63
+ );
64
+ return downgradeResponse(toolName, payload, { fromVersion, toVersion: servedAdcpVersion }).data;
65
+ }
54
66
  export {
55
67
  adcpMinorLine,
56
68
  compareAdcpMinorLines,
@@ -61,7 +73,8 @@ export {
61
73
  isNegotiationFailure,
62
74
  listVersionAdapterTools,
63
75
  negotiateAdcpRelease,
64
- parseAdcpRelease,
76
+ parseAdcpRelease2 as parseAdcpRelease,
77
+ projectResponseForRelease,
65
78
  projectToolPayload,
66
79
  releaseDefinesTool,
67
80
  resolveAdapterKey,
@@ -100,6 +100,13 @@ function failure(cause) {
100
100
  if (cause !== void 0) Object.defineProperty(error, "cause", { value: cause });
101
101
  throw error;
102
102
  }
103
+ function claimRegistrableDomain(domain) {
104
+ try {
105
+ return (0, import_etld.eTldPlusOne)(domain);
106
+ } catch (cause) {
107
+ return failure(cause);
108
+ }
109
+ }
103
110
  function validateTrustRecord(value) {
104
111
  if (!validateIdentity33Schema("trust/v1/trust", value)) failure();
105
112
  const record = value;
@@ -361,7 +368,7 @@ async function authorizeDemandGrant(claim, options) {
361
368
  const now = (options.now ?? (() => Date.now() / 1e3))();
362
369
  const signer = await options.evaluator.match(claim.signerOrigin, "adcp:buying", claim.brand.countries);
363
370
  if (signer.agent.countries && !claim.brand.countries?.length) failure();
364
- const brand = (0, import_etld.eTldPlusOne)(claim.brand.domain), account = (0, import_etld.eTldPlusOne)(claim.accountOperator), operator = signer.operator;
371
+ const brand = claimRegistrableDomain(claim.brand.domain), account = claimRegistrableDomain(claim.accountOperator), operator = signer.operator;
365
372
  const result = (source, chain, grants = []) => ({
366
373
  source,
367
374
  chain,
@@ -378,7 +385,7 @@ async function authorizeDemandGrant(claim, options) {
378
385
  throw cause;
379
386
  unavailable(cause);
380
387
  }
381
- const authoritativeBrand = house ? (0, import_etld.eTldPlusOne)(house.domain) : brand;
388
+ const authoritativeBrand = house ? claimRegistrableDomain(house.domain) : brand;
382
389
  const self = /* @__PURE__ */ new Set([brand, authoritativeBrand]);
383
390
  if (self.has(account) && self.has(operator)) return result("implicit", [.../* @__PURE__ */ new Set([brand, account, operator])]);
384
391
  const grantClaim = house ? { ...claim, brand: { ...claim.brand, brand_id: house.brand_id } } : claim;
@@ -59,6 +59,13 @@ function failure(cause) {
59
59
  if (cause !== void 0) Object.defineProperty(error, "cause", { value: cause });
60
60
  throw error;
61
61
  }
62
+ function claimRegistrableDomain(domain) {
63
+ try {
64
+ return eTldPlusOne(domain);
65
+ } catch (cause) {
66
+ return failure(cause);
67
+ }
68
+ }
62
69
  function validateTrustRecord(value) {
63
70
  if (!validateIdentity33Schema("trust/v1/trust", value)) failure();
64
71
  const record = value;
@@ -320,7 +327,7 @@ async function authorizeDemandGrant(claim, options) {
320
327
  const now = (options.now ?? (() => Date.now() / 1e3))();
321
328
  const signer = await options.evaluator.match(claim.signerOrigin, "adcp:buying", claim.brand.countries);
322
329
  if (signer.agent.countries && !claim.brand.countries?.length) failure();
323
- const brand = eTldPlusOne(claim.brand.domain), account = eTldPlusOne(claim.accountOperator), operator = signer.operator;
330
+ const brand = claimRegistrableDomain(claim.brand.domain), account = claimRegistrableDomain(claim.accountOperator), operator = signer.operator;
324
331
  const result = (source, chain, grants = []) => ({
325
332
  source,
326
333
  chain,
@@ -337,7 +344,7 @@ async function authorizeDemandGrant(claim, options) {
337
344
  throw cause;
338
345
  unavailable(cause);
339
346
  }
340
- const authoritativeBrand = house ? eTldPlusOne(house.domain) : brand;
347
+ const authoritativeBrand = house ? claimRegistrableDomain(house.domain) : brand;
341
348
  const self = /* @__PURE__ */ new Set([brand, authoritativeBrand]);
342
349
  if (self.has(account) && self.has(operator)) return result("implicit", [.../* @__PURE__ */ new Set([brand, account, operator])]);
343
350
  const grantClaim = house ? { ...claim, brand: { ...claim.brand, brand_id: house.brand_id } } : claim;
@@ -32,6 +32,7 @@ var import_operation_resolution = require('../signing/operation-resolution.js');
32
32
  var import_adcp_server = require('./adcp-server.js');
33
33
  var import_create_adcp_server = require('./create-adcp-server.js');
34
34
  var import_auth = require('./auth.js');
35
+ var import_signed_request_transport = require('./signed-request-transport.js');
35
36
  class RedactingA2ATaskStore {
36
37
  constructor(delegate) {
37
38
  this.delegate = delegate;
@@ -625,7 +626,7 @@ function captureRawBody(req, _res, buf) {
625
626
  }
626
627
  function resolveSignatureGate(options) {
627
628
  const symbols = options.server;
628
- const attached = symbols[import_create_adcp_server.ADCP_PRE_TRANSPORT];
629
+ const attached = (0, import_signed_request_transport.getSignedRequestPreTransport)(options.server) ?? symbols[import_create_adcp_server.ADCP_PRE_TRANSPORT];
629
630
  const gate = options.preTransport ?? (typeof attached === "function" ? attached : void 0);
630
631
  if (gate) return gate;
631
632
  const state = symbols[import_create_adcp_server.ADCP_SIGNED_REQUESTS_STATE];
@@ -25,6 +25,7 @@ import {
25
25
  ADCP_SIGNED_REQUESTS_STATE
26
26
  } from "./create-adcp-server.mjs";
27
27
  import { ADCP_SERVE_REQUEST_CONTEXT } from "./auth.mjs";
28
+ import { getSignedRequestPreTransport } from "./signed-request-transport.mjs";
28
29
  class RedactingA2ATaskStore {
29
30
  constructor(delegate) {
30
31
  this.delegate = delegate;
@@ -618,7 +619,7 @@ function captureRawBody(req, _res, buf) {
618
619
  }
619
620
  function resolveSignatureGate(options) {
620
621
  const symbols = options.server;
621
- const attached = symbols[ADCP_PRE_TRANSPORT];
622
+ const attached = getSignedRequestPreTransport(options.server) ?? symbols[ADCP_PRE_TRANSPORT];
622
623
  const gate = options.preTransport ?? (typeof attached === "function" ? attached : void 0);
623
624
  if (gate) return gate;
624
625
  const state = symbols[ADCP_SIGNED_REQUESTS_STATE];
@@ -64,8 +64,8 @@ export interface VerifySignatureAsAuthenticatorOptions {
64
64
  * requests fall through to the next authenticator — so set it to whatever
65
65
  * your `request_signing` capability claim advertises. */
66
66
  capability: VerifierCapability;
67
- /** Resolves verification keys by `keyid`. */
68
- jwks: JwksResolver;
67
+ /** Resolves legacy RFC 9421 keys. May be omitted for a Web Bot Auth-only endpoint. */
68
+ jwks?: JwksResolver;
69
69
  /**
70
70
  * Stores `(keyid, signature-bytes, expires)` tuples for replay detection.
71
71
  * Defaults to a fresh {@link InMemoryReplayStore} — fine for single-process
@@ -64,8 +64,8 @@ export interface VerifySignatureAsAuthenticatorOptions {
64
64
  * requests fall through to the next authenticator — so set it to whatever
65
65
  * your `request_signing` capability claim advertises. */
66
66
  capability: VerifierCapability;
67
- /** Resolves verification keys by `keyid`. */
68
- jwks: JwksResolver;
67
+ /** Resolves legacy RFC 9421 keys. May be omitted for a Web Bot Auth-only endpoint. */
68
+ jwks?: JwksResolver;
69
69
  /**
70
70
  * Stores `(keyid, signature-bytes, expires)` tuples for replay detection.
71
71
  * Defaults to a fresh {@link InMemoryReplayStore} — fine for single-process
@@ -36,6 +36,8 @@ var import_verifier = require('../signing/verifier.js');
36
36
  var import_buyer_agent = require('./decisioning/buyer-agent.js');
37
37
  var import_auth = require('./auth.js');
38
38
  function verifySignatureAsAuthenticator(options) {
39
+ if (!options.jwks && !options.webBotAuth)
40
+ throw new TypeError("verifySignatureAsAuthenticator requires jwks or webBotAuth");
39
41
  const replayStore = options.replayStore ?? new import_replay.InMemoryReplayStore();
40
42
  const legacyOriginGate = options.assertLegacyOriginAllowed ?? (0, import_web_bot_auth.getWebBotAuthLegacyOriginGate)(options.webBotAuth?.resolvePrincipal);
41
43
  if (options.webBotAuth && !legacyOriginGate)
@@ -102,6 +104,7 @@ function verifySignatureAsAuthenticator(options) {
102
104
  }
103
105
  };
104
106
  }
107
+ if (!options.jwks) throw new import_web_bot_auth2.WebBotAuthError(403, "profile_disabled");
105
108
  result = await (0, import_verifier.verifyRequestSignature)(requestLike, {
106
109
  capability: options.capability,
107
110
  jwks: options.jwks,
@@ -36,6 +36,8 @@ import {
36
36
  tagAuthenticatorPresenceGated
37
37
  } from "./auth.mjs";
38
38
  function verifySignatureAsAuthenticator(options) {
39
+ if (!options.jwks && !options.webBotAuth)
40
+ throw new TypeError("verifySignatureAsAuthenticator requires jwks or webBotAuth");
39
41
  const replayStore = options.replayStore ?? new InMemoryReplayStore();
40
42
  const legacyOriginGate = options.assertLegacyOriginAllowed ?? getWebBotAuthLegacyOriginGate(options.webBotAuth?.resolvePrincipal);
41
43
  if (options.webBotAuth && !legacyOriginGate)
@@ -102,6 +104,7 @@ function verifySignatureAsAuthenticator(options) {
102
104
  }
103
105
  };
104
106
  }
107
+ if (!options.jwks) throw new WebBotAuthError(403, "profile_disabled");
105
108
  result = await verifyRequestSignature(requestLike, {
106
109
  capability: options.capability,
107
110
  jwks: options.jwks,
@@ -946,8 +946,8 @@ export interface AdcpCapabilitiesOverrides {
946
946
  export interface SignedRequestsConfig {
947
947
  webBotAuth?: import('./auth-signature.mjs').VerifySignatureAsAuthenticatorOptions['webBotAuth'];
948
948
  assertLegacyOriginAllowed?: (agentUrl: string) => Promise<void>;
949
- /** Resolves verification keys by `keyid`. */
950
- jwks: JwksResolver;
949
+ /** Resolves legacy RFC 9421 keys. May be omitted for a Web Bot Auth-only endpoint. */
950
+ jwks?: JwksResolver;
951
951
  /** Stores `(keyid, signature-bytes, expires)` tuples for replay detection. */
952
952
  replayStore: ReplayStore;
953
953
  /** Consulted for revoked `kid` / `jti` before accepting a signature. */
@@ -946,8 +946,8 @@ export interface AdcpCapabilitiesOverrides {
946
946
  export interface SignedRequestsConfig {
947
947
  webBotAuth?: import('./auth-signature').VerifySignatureAsAuthenticatorOptions['webBotAuth'];
948
948
  assertLegacyOriginAllowed?: (agentUrl: string) => Promise<void>;
949
- /** Resolves verification keys by `keyid`. */
950
- jwks: JwksResolver;
949
+ /** Resolves legacy RFC 9421 keys. May be omitted for a Web Bot Auth-only endpoint. */
950
+ jwks?: JwksResolver;
951
951
  /** Stores `(keyid, signature-bytes, expires)` tuples for replay detection. */
952
952
  replayStore: ReplayStore;
953
953
  /** Consulted for revoked `kid` / `jti` before accepting a signature. */
@@ -81,6 +81,7 @@ var import_middleware = require('../signing/middleware.js');
81
81
  var import_operation_resolution = require('../signing/operation-resolution.js');
82
82
  var import_account_mode = require('./account-mode.js');
83
83
  var import_test_controller_bridge = require('./test-controller-bridge.js');
84
+ var import_signed_request_transport = require('./signed-request-transport.js');
84
85
  var import_version3 = require('../version.js');
85
86
  var import_schemas2 = require('../types/schemas.generated.js');
86
87
  var import_error_codes = require('../types/error-codes.js');
@@ -1466,6 +1467,8 @@ function resolveEffectiveSignedRequestPolicy(signedRequests, capabilityRequestSi
1466
1467
  };
1467
1468
  }
1468
1469
  function buildSignedRequestsPreTransport(signedRequests, effectiveRequestSigning, adcpVersion) {
1470
+ if (!signedRequests.jwks && !signedRequests.webBotAuth)
1471
+ throw new TypeError("signedRequests requires jwks or webBotAuth");
1469
1472
  const legacyOriginGate = signedRequests.assertLegacyOriginAllowed ?? (0, import_web_bot_auth.getWebBotAuthLegacyOriginGate)(signedRequests.webBotAuth?.resolvePrincipal);
1470
1473
  if (signedRequests.webBotAuth && !legacyOriginGate)
1471
1474
  throw new Error(
@@ -1485,7 +1488,7 @@ function buildSignedRequestsPreTransport(signedRequests, effectiveRequestSigning
1485
1488
  required_for: requiredFor,
1486
1489
  ...effectiveRequestSigning.protocol_methods_required_for ? { protocol_methods_required_for: effectiveRequestSigning.protocol_methods_required_for } : {}
1487
1490
  },
1488
- jwks: signedRequests.jwks,
1491
+ jwks: signedRequests.jwks ?? { resolve: async () => null },
1489
1492
  replayStore: signedRequests.replayStore,
1490
1493
  revocationStore: signedRequests.revocationStore,
1491
1494
  adcpVersion,
@@ -1558,6 +1561,12 @@ function buildSignedRequestsPreTransport(signedRequests, effectiveRequestSigning
1558
1561
  return true;
1559
1562
  }
1560
1563
  }
1564
+ if (!signedRequests.jwks && (req.headers["signature"] !== void 0 || req.headers["signature-input"] !== void 0)) {
1565
+ const refused = new import_web_bot_auth2.WebBotAuthError(403, "profile_disabled");
1566
+ res.writeHead(refused.status, { ...refused.headers, "Content-Type": "application/json" });
1567
+ res.end(JSON.stringify(refused.body));
1568
+ return true;
1569
+ }
1561
1570
  const reqShim = {
1562
1571
  method: req.method ?? "POST",
1563
1572
  url: req.url ?? "/mcp",
@@ -5121,12 +5130,25 @@ function createAdcpServer(config) {
5121
5130
  (0, import_adcp_server.setMcpAppResources)(wrapped, mcpAppResources);
5122
5131
  if (signedRequests) {
5123
5132
  const preTransport = buildSignedRequestsPreTransport(signedRequests, enforcedRequestSigningPolicy, adcpVersion);
5133
+ const transportPermitted = (0, import_signed_request_transport.registerSignedRequestTransportGuard)(wrapped, preTransport);
5134
+ let preTransportConsumed = false;
5124
5135
  Object.defineProperty(wrapped, ADCP_PRE_TRANSPORT, {
5125
- value: preTransport,
5136
+ get() {
5137
+ preTransportConsumed = true;
5138
+ return preTransport;
5139
+ },
5126
5140
  enumerable: false,
5127
- writable: false,
5128
5141
  configurable: true
5129
5142
  });
5143
+ const connect = wrapped.connect.bind(wrapped);
5144
+ wrapped.connect = async (transport) => {
5145
+ if (!preTransportConsumed && !transportPermitted(transport)) {
5146
+ throw new Error(
5147
+ "signedRequests verifier is not mounted: direct server.connect(transport) does not run HTTP middleware. Use serve(), createA2AAdapter(), or mount server[ADCP_PRE_TRANSPORT] before handling requests. For custom authentication, compose verifySignatureAsAuthenticator({ webBotAuth }) and capture rawBody."
5148
+ );
5149
+ }
5150
+ return connect(transport);
5151
+ };
5130
5152
  }
5131
5153
  const signedRequestsState = {
5132
5154
  autoWired: Boolean(signedRequests),
@@ -183,6 +183,7 @@ import {
183
183
  filterValidSeededRights,
184
184
  filterValidSeededSiOffering
185
185
  } from "./test-controller-bridge.mjs";
186
+ import { registerSignedRequestTransportGuard } from "./signed-request-transport.mjs";
186
187
  import { ADCP_VERSION, LIBRARY_VERSION } from "../version.mjs";
187
188
  import { AccountReferenceSchema } from "../types/schemas.generated.mjs";
188
189
  import {
@@ -1568,6 +1569,8 @@ function resolveEffectiveSignedRequestPolicy(signedRequests, capabilityRequestSi
1568
1569
  };
1569
1570
  }
1570
1571
  function buildSignedRequestsPreTransport(signedRequests, effectiveRequestSigning, adcpVersion) {
1572
+ if (!signedRequests.jwks && !signedRequests.webBotAuth)
1573
+ throw new TypeError("signedRequests requires jwks or webBotAuth");
1571
1574
  const legacyOriginGate = signedRequests.assertLegacyOriginAllowed ?? getWebBotAuthLegacyOriginGate(signedRequests.webBotAuth?.resolvePrincipal);
1572
1575
  if (signedRequests.webBotAuth && !legacyOriginGate)
1573
1576
  throw new Error(
@@ -1587,7 +1590,7 @@ function buildSignedRequestsPreTransport(signedRequests, effectiveRequestSigning
1587
1590
  required_for: requiredFor,
1588
1591
  ...effectiveRequestSigning.protocol_methods_required_for ? { protocol_methods_required_for: effectiveRequestSigning.protocol_methods_required_for } : {}
1589
1592
  },
1590
- jwks: signedRequests.jwks,
1593
+ jwks: signedRequests.jwks ?? { resolve: async () => null },
1591
1594
  replayStore: signedRequests.replayStore,
1592
1595
  revocationStore: signedRequests.revocationStore,
1593
1596
  adcpVersion,
@@ -1660,6 +1663,12 @@ function buildSignedRequestsPreTransport(signedRequests, effectiveRequestSigning
1660
1663
  return true;
1661
1664
  }
1662
1665
  }
1666
+ if (!signedRequests.jwks && (req.headers["signature"] !== void 0 || req.headers["signature-input"] !== void 0)) {
1667
+ const refused = new WebBotAuthError(403, "profile_disabled");
1668
+ res.writeHead(refused.status, { ...refused.headers, "Content-Type": "application/json" });
1669
+ res.end(JSON.stringify(refused.body));
1670
+ return true;
1671
+ }
1663
1672
  const reqShim = {
1664
1673
  method: req.method ?? "POST",
1665
1674
  url: req.url ?? "/mcp",
@@ -5223,12 +5232,25 @@ function createAdcpServer(config) {
5223
5232
  setMcpAppResources(wrapped, mcpAppResources);
5224
5233
  if (signedRequests) {
5225
5234
  const preTransport = buildSignedRequestsPreTransport(signedRequests, enforcedRequestSigningPolicy, adcpVersion);
5235
+ const transportPermitted = registerSignedRequestTransportGuard(wrapped, preTransport);
5236
+ let preTransportConsumed = false;
5226
5237
  Object.defineProperty(wrapped, ADCP_PRE_TRANSPORT, {
5227
- value: preTransport,
5238
+ get() {
5239
+ preTransportConsumed = true;
5240
+ return preTransport;
5241
+ },
5228
5242
  enumerable: false,
5229
- writable: false,
5230
5243
  configurable: true
5231
5244
  });
5245
+ const connect = wrapped.connect.bind(wrapped);
5246
+ wrapped.connect = async (transport) => {
5247
+ if (!preTransportConsumed && !transportPermitted(transport)) {
5248
+ throw new Error(
5249
+ "signedRequests verifier is not mounted: direct server.connect(transport) does not run HTTP middleware. Use serve(), createA2AAdapter(), or mount server[ADCP_PRE_TRANSPORT] before handling requests. For custom authentication, compose verifySignatureAsAuthenticator({ webBotAuth }) and capture rawBody."
5250
+ );
5251
+ }
5252
+ return connect(transport);
5253
+ };
5232
5254
  }
5233
5255
  const signedRequestsState = {
5234
5256
  autoWired: Boolean(signedRequests),
@@ -36,6 +36,7 @@ var import_create_adcp_server = require('./create-adcp-server.js');
36
36
  var import_tasks = require('./tasks.js');
37
37
  var import_adcp_server = require('./adcp-server.js');
38
38
  var import_mcp_modern_server = require('./mcp-modern-server.js');
39
+ var import_signed_request_transport = require('./signed-request-transport.js');
39
40
  class UnknownHostError extends Error {
40
41
  constructor(message = "Unknown host") {
41
42
  super(message);
@@ -407,7 +408,7 @@ function serve(createAgent, options) {
407
408
  return;
408
409
  }
409
410
  }
410
- const attached = agentServer[import_create_adcp_server.ADCP_PRE_TRANSPORT];
411
+ const attached = (0, import_signed_request_transport.getSignedRequestPreTransport)(agentServer) ?? agentServer[import_create_adcp_server.ADCP_PRE_TRANSPORT];
411
412
  const autoWiredPreTransport = typeof attached === "function" ? attached : void 0;
412
413
  const activePreTransport = explicitPreTransport ?? autoWiredPreTransport;
413
414
  if (activePreTransport) {
@@ -487,6 +488,7 @@ function serve(createAgent, options) {
487
488
  const transport = new import_streamableHttp.StreamableHTTPServerTransport({
488
489
  sessionIdGenerator: void 0
489
490
  });
491
+ (0, import_signed_request_transport.permitSignedRequestTransport)(agentServer, transport);
490
492
  await agentServer.connect(transport);
491
493
  if (parsedBody !== void 0) {
492
494
  await transport.handleRequest(req, res, parsedBody);
@@ -19,6 +19,7 @@ import {
19
19
  import { ADCP_TASK_MESSAGE_QUEUE } from "./tasks.mjs";
20
20
  import { getSdkServer, isAdcpServer } from "./adcp-server.mjs";
21
21
  import { createModernMcpServerAdapter } from "./mcp-modern-server.mjs";
22
+ import { getSignedRequestPreTransport, permitSignedRequestTransport } from "./signed-request-transport.mjs";
22
23
  class UnknownHostError extends Error {
23
24
  constructor(message = "Unknown host") {
24
25
  super(message);
@@ -390,7 +391,7 @@ function serve(createAgent, options) {
390
391
  return;
391
392
  }
392
393
  }
393
- const attached = agentServer[ADCP_PRE_TRANSPORT];
394
+ const attached = getSignedRequestPreTransport(agentServer) ?? agentServer[ADCP_PRE_TRANSPORT];
394
395
  const autoWiredPreTransport = typeof attached === "function" ? attached : void 0;
395
396
  const activePreTransport = explicitPreTransport ?? autoWiredPreTransport;
396
397
  if (activePreTransport) {
@@ -470,6 +471,7 @@ function serve(createAgent, options) {
470
471
  const transport = new StreamableHTTPServerTransport({
471
472
  sessionIdGenerator: void 0
472
473
  });
474
+ permitSignedRequestTransport(agentServer, transport);
473
475
  await agentServer.connect(transport);
474
476
  if (parsedBody !== void 0) {
475
477
  await transport.handleRequest(req, res, parsedBody);
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var signed_request_transport_exports = {};
20
+ __export(signed_request_transport_exports, {
21
+ getSignedRequestPreTransport: () => getSignedRequestPreTransport,
22
+ permitSignedRequestTransport: () => permitSignedRequestTransport,
23
+ registerSignedRequestTransportGuard: () => registerSignedRequestTransportGuard
24
+ });
25
+ module.exports = __toCommonJS(signed_request_transport_exports);
26
+ const GUARD = /* @__PURE__ */ Symbol.for("@adcp/client.signedRequestTransportGuard");
27
+ function guardFor(server) {
28
+ return server[GUARD];
29
+ }
30
+ function registerSignedRequestTransportGuard(server, preTransport) {
31
+ const entry = { preTransport, transports: /* @__PURE__ */ new WeakSet() };
32
+ Object.defineProperty(server, GUARD, { value: entry });
33
+ return (transport) => entry.transports.has(transport);
34
+ }
35
+ function getSignedRequestPreTransport(server) {
36
+ return guardFor(server)?.preTransport;
37
+ }
38
+ function permitSignedRequestTransport(server, transport) {
39
+ guardFor(server)?.transports.add(transport);
40
+ }
41
+ // Annotate the CommonJS export names for ESM import in node:
42
+ 0 && (module.exports = {
43
+ getSignedRequestPreTransport,
44
+ permitSignedRequestTransport,
45
+ registerSignedRequestTransportGuard
46
+ });
@@ -0,0 +1,20 @@
1
+ const GUARD = /* @__PURE__ */ Symbol.for("@adcp/client.signedRequestTransportGuard");
2
+ function guardFor(server) {
3
+ return server[GUARD];
4
+ }
5
+ function registerSignedRequestTransportGuard(server, preTransport) {
6
+ const entry = { preTransport, transports: /* @__PURE__ */ new WeakSet() };
7
+ Object.defineProperty(server, GUARD, { value: entry });
8
+ return (transport) => entry.transports.has(transport);
9
+ }
10
+ function getSignedRequestPreTransport(server) {
11
+ return guardFor(server)?.preTransport;
12
+ }
13
+ function permitSignedRequestTransport(server, transport) {
14
+ guardFor(server)?.transports.add(transport);
15
+ }
16
+ export {
17
+ getSignedRequestPreTransport,
18
+ permitSignedRequestTransport,
19
+ registerSignedRequestTransportGuard
20
+ };
@@ -367,6 +367,7 @@ export interface TestControllerStore {
367
367
  forceUpstreamUnavailable?(params: {
368
368
  tool: string;
369
369
  upstream_name?: string;
370
+ cache_age_seconds?: number;
370
371
  }): Promise<StateTransitionSuccess>;
371
372
  }
372
373
  /**
@@ -367,6 +367,7 @@ export interface TestControllerStore {
367
367
  forceUpstreamUnavailable?(params: {
368
368
  tool: string;
369
369
  upstream_name?: string;
370
+ cache_age_seconds?: number;
370
371
  }): Promise<StateTransitionSuccess>;
371
372
  }
372
373
  /**
@@ -764,10 +764,14 @@ async function handleTestControllerRequestImpl(storeOrFactory, input, options) {
764
764
  if (typeof forceParams.tool !== "string" || forceParams.tool.length === 0) {
765
765
  return controllerError("INVALID_PARAMS", "force_upstream_unavailable requires params.tool");
766
766
  }
767
+ if (forceParams.cache_age_seconds !== void 0 && (!Number.isInteger(forceParams.cache_age_seconds) || forceParams.cache_age_seconds < 0)) {
768
+ return controllerError("INVALID_PARAMS", "cache_age_seconds must be a non-negative integer");
769
+ }
767
770
  return wrapStoreSuccess(
768
771
  await store.forceUpstreamUnavailable({
769
772
  tool: forceParams.tool,
770
- upstream_name: typeof forceParams.upstream_name === "string" ? forceParams.upstream_name : void 0
773
+ upstream_name: typeof forceParams.upstream_name === "string" ? forceParams.upstream_name : void 0,
774
+ ...typeof forceParams.cache_age_seconds === "number" ? { cache_age_seconds: forceParams.cache_age_seconds } : {}
771
775
  })
772
776
  );
773
777
  }
@@ -736,10 +736,14 @@ async function handleTestControllerRequestImpl(storeOrFactory, input, options) {
736
736
  if (typeof forceParams.tool !== "string" || forceParams.tool.length === 0) {
737
737
  return controllerError("INVALID_PARAMS", "force_upstream_unavailable requires params.tool");
738
738
  }
739
+ if (forceParams.cache_age_seconds !== void 0 && (!Number.isInteger(forceParams.cache_age_seconds) || forceParams.cache_age_seconds < 0)) {
740
+ return controllerError("INVALID_PARAMS", "cache_age_seconds must be a non-negative integer");
741
+ }
739
742
  return wrapStoreSuccess(
740
743
  await store.forceUpstreamUnavailable({
741
744
  tool: forceParams.tool,
742
- upstream_name: typeof forceParams.upstream_name === "string" ? forceParams.upstream_name : void 0
745
+ upstream_name: typeof forceParams.upstream_name === "string" ? forceParams.upstream_name : void 0,
746
+ ...typeof forceParams.cache_age_seconds === "number" ? { cache_age_seconds: forceParams.cache_age_seconds } : {}
743
747
  })
744
748
  );
745
749
  }
@@ -23,3 +23,4 @@ export { COLLECTION_DIAGNOSTIC_LIMIT, COLLECTION_PAIR_LIMIT, COLLECTION_TARGETIN
23
23
  export type { CollectionNormalizationCode, CollectionNormalizationFailure, CollectionNormalizationResult, CrossPublisherCollectionRelation, CollectionPair, CollectionSelectionEvaluation, CollectionSelectionSelector, CollectionSelectionWitness, CollectionSelectorObject, CollectionWitnessKind, CollectionWitnessReadResult, FixtureContextOutput, NormalizedCollectionSelectors, PreparedFixtureBinding, PreparedFixtureSelection, PreparedFixturesAuthorizer, PreparedFixturesDecision, PreparedFixturesDisposition, PreparedFixturesLookup, PreparedFixturesPreparationLookup, PreparedFixturesPreparationAuthorizer, PreparedFixturesRefusal, PreparedFixturesRefusalCode, PreparedFixturesReference, PreparedSchemaArtifact, ProtectedContextViolationCode, ResolvedCollectionSelectionSelector, } from './storyboard/index.mjs';
24
24
  export { resolveCreativeBuildProbe, validateCreativeBuildProbeSpec } from './storyboard/index.mjs';
25
25
  export type { CreativeBuildProbeSpec, CreativeBuildProbeInputFixture, CreativeBuildProbeResolution, } from './storyboard/index.mjs';
26
+ export { createStoryboardWebBotAuthFetch } from './storyboard/web-bot-auth.mjs';