@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
@@ -197,7 +197,7 @@ export interface UpstreamTrafficQueryResult {
197
197
  */
198
198
  export declare function runValidations(validations: StoryboardValidation[], context: ValidationContext): ValidationResult[];
199
199
  /** Capability semver emitted in run summaries and used for advisory expiry. */
200
- export declare const RUNNER_CAPABILITY_VERSION = "17.0.0-beta.2";
200
+ export declare const RUNNER_CAPABILITY_VERSION = "17.0.0-beta.3";
201
201
  /** True when a failed validation contributes to the owning step's grade. */
202
202
  export declare function validationFailsStep(result: ValidationResult): boolean;
203
203
  /**
@@ -0,0 +1,10 @@
1
+ import { type WebBotSigningKey, type WebBotSigningOptions } from '../../signing/web-bot-auth.mjs';
2
+ /** Sign the public HTTPS target while the official transport delivers to loopback. */
3
+ export declare function createStoryboardWebBotAuthFetch(upstream: typeof fetch, key: WebBotSigningKey, options: WebBotSigningOptions & {
4
+ /** Pin the destination origin for direct HTTPS delivery. */
5
+ agentUrl?: string;
6
+ target?: {
7
+ publicUrl: string;
8
+ loopbackUrl: string;
9
+ };
10
+ }): typeof fetch;
@@ -0,0 +1,10 @@
1
+ import { type WebBotSigningKey, type WebBotSigningOptions } from '../../signing/web-bot-auth';
2
+ /** Sign the public HTTPS target while the official transport delivers to loopback. */
3
+ export declare function createStoryboardWebBotAuthFetch(upstream: typeof fetch, key: WebBotSigningKey, options: WebBotSigningOptions & {
4
+ /** Pin the destination origin for direct HTTPS delivery. */
5
+ agentUrl?: string;
6
+ target?: {
7
+ publicUrl: string;
8
+ loopbackUrl: string;
9
+ };
10
+ }): typeof fetch;
@@ -0,0 +1,80 @@
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 web_bot_auth_exports = {};
20
+ __export(web_bot_auth_exports, {
21
+ createStoryboardWebBotAuthFetch: () => createStoryboardWebBotAuthFetch
22
+ });
23
+ module.exports = __toCommonJS(web_bot_auth_exports);
24
+ var import_web_bot_auth = require('../../signing/web-bot-auth.js');
25
+ function createStoryboardWebBotAuthFetch(upstream, key, options) {
26
+ const deliver = async (input, init) => {
27
+ const response = await upstream(input, { ...init, redirect: "manual" });
28
+ if ([301, 302, 303, 307, 308].includes(response.status) && response.headers.has("location")) {
29
+ await response.body?.cancel();
30
+ throw new TypeError("Web Bot Auth storyboard requests do not follow HTTP redirects");
31
+ }
32
+ return response;
33
+ };
34
+ if (!options.target) {
35
+ if (!options.agentUrl) throw new TypeError("Direct Web Bot Auth storyboard signing requires agentUrl");
36
+ const agentUrl = new URL(options.agentUrl);
37
+ if (agentUrl.protocol !== "https:" || agentUrl.username || agentUrl.password || agentUrl.hash)
38
+ throw new TypeError(
39
+ "Direct Web Bot Auth storyboard signing requires an HTTPS agentUrl without credentials or fragments"
40
+ );
41
+ const signed2 = (0, import_web_bot_auth.createWebBotAuthFetch)(deliver, key, options);
42
+ return (input, init) => {
43
+ const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
44
+ if (new URL(url).origin !== agentUrl.origin)
45
+ return Promise.reject(new TypeError("Web Bot Auth storyboard refused a different agent origin"));
46
+ return signed2(input, init);
47
+ };
48
+ }
49
+ const publicUrl = new URL(options.target.publicUrl);
50
+ const localUrl = new URL(options.target.loopbackUrl);
51
+ if (publicUrl.protocol !== "https:" || publicUrl.username || publicUrl.password || publicUrl.hash || publicUrl.search || !["http:", "https:"].includes(localUrl.protocol) || !["localhost", "127.0.0.1", "[::1]"].includes(localUrl.hostname) || localUrl.username || localUrl.password || localUrl.hash || localUrl.search)
52
+ throw new TypeError(
53
+ "Web Bot Auth test delivery requires a public HTTPS URL and a loopback URL without credentials, query or fragment"
54
+ );
55
+ const signed = (0, import_web_bot_auth.createWebBotAuthFetch)(
56
+ async (input, init) => {
57
+ const target = new URL(String(input));
58
+ if (target.origin !== publicUrl.origin || target.pathname !== publicUrl.pathname)
59
+ throw new TypeError("Web Bot Auth test delivery refused a different public endpoint");
60
+ const destination = new URL(localUrl);
61
+ destination.search = target.search;
62
+ return deliver(destination.href, init);
63
+ },
64
+ key,
65
+ options
66
+ );
67
+ return async (input, init) => {
68
+ if (input instanceof Request) throw new TypeError("Web Bot Auth test delivery requires a URL and init");
69
+ const source = new URL(String(input));
70
+ if (source.origin !== localUrl.origin || source.pathname !== localUrl.pathname)
71
+ throw new TypeError("Web Bot Auth test delivery refused a different loopback endpoint");
72
+ const target = new URL(publicUrl);
73
+ target.search = source.search;
74
+ return signed(target.href, init);
75
+ };
76
+ }
77
+ // Annotate the CommonJS export names for ESM import in node:
78
+ 0 && (module.exports = {
79
+ createStoryboardWebBotAuthFetch
80
+ });
@@ -0,0 +1,56 @@
1
+ import { createWebBotAuthFetch } from "../../signing/web-bot-auth.mjs";
2
+ function createStoryboardWebBotAuthFetch(upstream, key, options) {
3
+ const deliver = async (input, init) => {
4
+ const response = await upstream(input, { ...init, redirect: "manual" });
5
+ if ([301, 302, 303, 307, 308].includes(response.status) && response.headers.has("location")) {
6
+ await response.body?.cancel();
7
+ throw new TypeError("Web Bot Auth storyboard requests do not follow HTTP redirects");
8
+ }
9
+ return response;
10
+ };
11
+ if (!options.target) {
12
+ if (!options.agentUrl) throw new TypeError("Direct Web Bot Auth storyboard signing requires agentUrl");
13
+ const agentUrl = new URL(options.agentUrl);
14
+ if (agentUrl.protocol !== "https:" || agentUrl.username || agentUrl.password || agentUrl.hash)
15
+ throw new TypeError(
16
+ "Direct Web Bot Auth storyboard signing requires an HTTPS agentUrl without credentials or fragments"
17
+ );
18
+ const signed2 = createWebBotAuthFetch(deliver, key, options);
19
+ return (input, init) => {
20
+ const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
21
+ if (new URL(url).origin !== agentUrl.origin)
22
+ return Promise.reject(new TypeError("Web Bot Auth storyboard refused a different agent origin"));
23
+ return signed2(input, init);
24
+ };
25
+ }
26
+ const publicUrl = new URL(options.target.publicUrl);
27
+ const localUrl = new URL(options.target.loopbackUrl);
28
+ if (publicUrl.protocol !== "https:" || publicUrl.username || publicUrl.password || publicUrl.hash || publicUrl.search || !["http:", "https:"].includes(localUrl.protocol) || !["localhost", "127.0.0.1", "[::1]"].includes(localUrl.hostname) || localUrl.username || localUrl.password || localUrl.hash || localUrl.search)
29
+ throw new TypeError(
30
+ "Web Bot Auth test delivery requires a public HTTPS URL and a loopback URL without credentials, query or fragment"
31
+ );
32
+ const signed = createWebBotAuthFetch(
33
+ async (input, init) => {
34
+ const target = new URL(String(input));
35
+ if (target.origin !== publicUrl.origin || target.pathname !== publicUrl.pathname)
36
+ throw new TypeError("Web Bot Auth test delivery refused a different public endpoint");
37
+ const destination = new URL(localUrl);
38
+ destination.search = target.search;
39
+ return deliver(destination.href, init);
40
+ },
41
+ key,
42
+ options
43
+ );
44
+ return async (input, init) => {
45
+ if (input instanceof Request) throw new TypeError("Web Bot Auth test delivery requires a URL and init");
46
+ const source = new URL(String(input));
47
+ if (source.origin !== localUrl.origin || source.pathname !== localUrl.pathname)
48
+ throw new TypeError("Web Bot Auth test delivery refused a different loopback endpoint");
49
+ const target = new URL(publicUrl);
50
+ target.search = source.search;
51
+ return signed(target.href, init);
52
+ };
53
+ }
54
+ export {
55
+ createStoryboardWebBotAuthFetch
56
+ };
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * AdCP SDK library version
3
3
  */
4
- export declare const LIBRARY_VERSION = "17.0.0-beta.2";
4
+ export declare const LIBRARY_VERSION = "17.0.0-beta.3";
5
5
  /**
6
6
  * AdCP specification version this library is built for
7
7
  */
@@ -33,10 +33,10 @@ export type AdcpVersion = (typeof COMPATIBLE_ADCP_VERSIONS)[number];
33
33
  * Full version information
34
34
  */
35
35
  export declare const VERSION_INFO: {
36
- readonly library: "17.0.0-beta.2";
36
+ readonly library: "17.0.0-beta.3";
37
37
  readonly adcp: "3.3.0-beta.0";
38
38
  readonly compatibleVersions: readonly ["v3", "3.0.0", "3.0", "3.0.1", "3.0.2", "3.0.3", "3.0.4", "3.0.5", "3.0.6", "3.0.7", "3.0.8", "3.0.9", "3.0.10", "3.0.11", "3.0.12", "3.0.13", "3.0.14", "3.0.15", "3.0.16", "3.0.17", "3.0.18", "3.0.19", "3.0.20", "3.0.21", "3.0.22", "3.0.23", "3.0.24", "3.0.25", "3.1.0", "3.1", "3.1.1", "3.1.2", "3.1.3", "3.1.4", "3.1.5", "3.1.6", "3.1.7", "3.1.8", "3.1.9", "3.1.10", "3.1.11", "3.1.12", "3.1.13", "3.1.14", "3.1.15", "3.1.16", "3.1.17", "3.1.18", "3.1.19", "3.1.20", "3.1.21", "3.1.22", "3.1.23", "3.1.24", "3.1.25", "3.1.26", "3.1.27", "3.1.28", "3.1.29", "3.2.1", "3.2", "3.2.2", "3.2.3", "3.2.4", "3.2.5", "3.2.6", "3.2.7", "3.3.0-beta.0", "3.3-beta.0"];
39
- readonly generatedAt: "2026-10-27T06:33:58.733Z";
39
+ readonly generatedAt: "2026-10-28T13:03:53.360Z";
40
40
  };
41
41
  /**
42
42
  * Get the AdCP specification version this library is built for
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * AdCP SDK library version
3
3
  */
4
- export declare const LIBRARY_VERSION = "17.0.0-beta.2";
4
+ export declare const LIBRARY_VERSION = "17.0.0-beta.3";
5
5
  /**
6
6
  * AdCP specification version this library is built for
7
7
  */
@@ -33,10 +33,10 @@ export type AdcpVersion = (typeof COMPATIBLE_ADCP_VERSIONS)[number];
33
33
  * Full version information
34
34
  */
35
35
  export declare const VERSION_INFO: {
36
- readonly library: "17.0.0-beta.2";
36
+ readonly library: "17.0.0-beta.3";
37
37
  readonly adcp: "3.3.0-beta.0";
38
38
  readonly compatibleVersions: readonly ["v3", "3.0.0", "3.0", "3.0.1", "3.0.2", "3.0.3", "3.0.4", "3.0.5", "3.0.6", "3.0.7", "3.0.8", "3.0.9", "3.0.10", "3.0.11", "3.0.12", "3.0.13", "3.0.14", "3.0.15", "3.0.16", "3.0.17", "3.0.18", "3.0.19", "3.0.20", "3.0.21", "3.0.22", "3.0.23", "3.0.24", "3.0.25", "3.1.0", "3.1", "3.1.1", "3.1.2", "3.1.3", "3.1.4", "3.1.5", "3.1.6", "3.1.7", "3.1.8", "3.1.9", "3.1.10", "3.1.11", "3.1.12", "3.1.13", "3.1.14", "3.1.15", "3.1.16", "3.1.17", "3.1.18", "3.1.19", "3.1.20", "3.1.21", "3.1.22", "3.1.23", "3.1.24", "3.1.25", "3.1.26", "3.1.27", "3.1.28", "3.1.29", "3.2.1", "3.2", "3.2.2", "3.2.3", "3.2.4", "3.2.5", "3.2.6", "3.2.7", "3.3.0-beta.0", "3.3-beta.0"];
39
- readonly generatedAt: "2026-10-27T06:33:58.733Z";
39
+ readonly generatedAt: "2026-10-28T13:03:53.360Z";
40
40
  };
41
41
  /**
42
42
  * Get the AdCP specification version this library is built for
@@ -31,7 +31,7 @@ __export(version_exports, {
31
31
  toReleasePrecisionVersion: () => toReleasePrecisionVersion
32
32
  });
33
33
  module.exports = __toCommonJS(version_exports);
34
- const LIBRARY_VERSION = "17.0.0-beta.2";
34
+ const LIBRARY_VERSION = "17.0.0-beta.3";
35
35
  const ADCP_VERSION = "3.3.0-beta.0";
36
36
  const ADCP_MAJOR_VERSION = 3;
37
37
  const COMPATIBLE_ADCP_VERSIONS = [
@@ -106,10 +106,10 @@ const COMPATIBLE_ADCP_VERSIONS = [
106
106
  "3.3-beta.0"
107
107
  ];
108
108
  const VERSION_INFO = {
109
- library: "17.0.0-beta.2",
109
+ library: "17.0.0-beta.3",
110
110
  adcp: "3.3.0-beta.0",
111
111
  compatibleVersions: COMPATIBLE_ADCP_VERSIONS,
112
- generatedAt: "2026-10-27T06:33:58.733Z"
112
+ generatedAt: "2026-10-28T13:03:53.360Z"
113
113
  };
114
114
  function getAdcpVersion() {
115
115
  return ADCP_VERSION;
@@ -1,4 +1,4 @@
1
- const LIBRARY_VERSION = "17.0.0-beta.2";
1
+ const LIBRARY_VERSION = "17.0.0-beta.3";
2
2
  const ADCP_VERSION = "3.3.0-beta.0";
3
3
  const ADCP_MAJOR_VERSION = 3;
4
4
  const COMPATIBLE_ADCP_VERSIONS = [
@@ -73,10 +73,10 @@ const COMPATIBLE_ADCP_VERSIONS = [
73
73
  "3.3-beta.0"
74
74
  ];
75
75
  const VERSION_INFO = {
76
- library: "17.0.0-beta.2",
76
+ library: "17.0.0-beta.3",
77
77
  adcp: "3.3.0-beta.0",
78
78
  compatibleVersions: COMPATIBLE_ADCP_VERSIONS,
79
- generatedAt: "2026-10-27T06:33:58.733Z"
79
+ generatedAt: "2026-10-28T13:03:53.360Z"
80
80
  };
81
81
  function getAdcpVersion() {
82
82
  return ADCP_VERSION;
@@ -1,7 +1,7 @@
1
1
  # AdCP Type Summary
2
2
 
3
- > Generated at: 2026-10-27
4
- > @adcp/sdk v17.0.0-beta.2
3
+ > Generated at: 2026-10-28
4
+ > @adcp/sdk v17.0.0-beta.3
5
5
 
6
6
  Curated reference of the types that matter for using the AdCP client. For full generated types see `src/lib/types/tools.generated.ts` and `src/lib/types/core.generated.ts`.
7
7
 
package/docs/llms.txt CHANGED
@@ -1,7 +1,7 @@
1
1
  # Ad Context Protocol (AdCP)
2
2
 
3
- > Generated at: 2026-10-27
4
- > Library: @adcp/sdk v17.0.0-beta.2
3
+ > Generated at: 2026-10-28
4
+ > Library: @adcp/sdk v17.0.0-beta.3
5
5
  > AdCP major version: 3
6
6
  > Canonical URL: https://adcontextprotocol.github.io/adcp-client/llms.txt
7
7
  > Note: the `Library` stamp reflects the package.json version at doc-generation time. The narrative below describes the surface that lands on the next-published minor — including any 6.7 helpers documented here ahead of the release tag.
@@ -16,8 +16,8 @@ pin using `ADCP_VERSION` inside that tarball.
16
16
 
17
17
  | Fact | Value |
18
18
  | --- | --- |
19
- | Checkout `package.json` version | `@adcp/sdk@17.0.0-beta.2` |
20
- | npm integrity | registry-derived after publication; run `npm view @adcp/sdk@17.0.0-beta.2 dist.integrity` |
19
+ | Checkout `package.json` version | `@adcp/sdk@17.0.0-beta.3` |
20
+ | npm integrity | registry-derived after publication; run `npm view @adcp/sdk@17.0.0-beta.3 dist.integrity` |
21
21
  | Node.js runtime | `^20.19.0 || >=22.12.0` |
22
22
  | Default AdCP wire release | `3.3.0-beta.0` |
23
23
  | Maintained wire releases | `v3`, `3.0.0`, `3.0`, `3.0.1`, `3.0.2`, `3.0.3`, `3.0.4`, `3.0.5`, `3.0.6`, `3.0.7`, `3.0.8`, `3.0.9`, `3.0.10`, `3.0.11`, `3.0.12`, `3.0.13`, `3.0.14`, `3.0.15`, `3.0.16`, `3.0.17`, `3.0.18`, `3.0.19`, `3.0.20`, `3.0.21`, `3.0.22`, `3.0.23`, `3.0.24`, `3.0.25`, `3.1.0`, `3.1`, `3.1.1`, `3.1.2`, `3.1.3`, `3.1.4`, `3.1.5`, `3.1.6`, `3.1.7`, `3.1.8`, `3.1.9`, `3.1.10`, `3.1.11`, `3.1.12`, `3.1.13`, `3.1.14`, `3.1.15`, `3.1.16`, `3.1.17`, `3.1.18`, `3.1.19`, `3.1.20`, `3.1.21`, `3.1.22`, `3.1.23`, `3.1.24`, `3.1.25`, `3.1.26`, `3.1.27`, `3.1.28`, `3.1.29`, `3.2.1`, `3.2`, `3.2.2`, `3.2.3`, `3.2.4`, `3.2.5`, `3.2.6`, `3.2.7`, `3.3.0-beta.0`, `3.3-beta.0` |
@@ -26,8 +26,8 @@ pin using `ADCP_VERSION` inside that tarball.
26
26
  For a checkout at the published release commit, install the exact package version:
27
27
 
28
28
  ```bash
29
- npm install --save-exact '@adcp/sdk@17.0.0-beta.2'
30
- npm view '@adcp/sdk@17.0.0-beta.2' dist.integrity
29
+ npm install --save-exact '@adcp/sdk@17.0.0-beta.3'
30
+ npm view '@adcp/sdk@17.0.0-beta.3' dist.integrity
31
31
  ```
32
32
 
33
33
  ### Required and optional peers
@@ -151,6 +151,25 @@ server handlers are `mediaBuy.listCollections` and `mediaBuy.listProposals`,
151
151
  or optional methods on `MediaBuyLifecyclePlatform`. Their synchronous results
152
152
  use `outcome` and do not acquire a synthetic task `status` field.
153
153
 
154
+ ## Postgres replay store
155
+
156
+ `PostgresReplayStore` inserts through a table-specific guarded function
157
+ (`<table>_insert_guarded`) that keeps the replay check, the per-key cap and the
158
+ insert on one backend. A database created by an earlier SDK has the table but
159
+ not the function. Every insert then fails with "PostgresReplayStore database
160
+ migration is outdated", and signed requests answer 503 (Web Bot Auth) or are
161
+ refused. Rerun the migration for each replay table before deploying SDK 17:
162
+
163
+ ```ts
164
+ import { getReplayStoreMigration } from '@adcp/sdk/signing/server';
165
+
166
+ await pool.query(getReplayStoreMigration('adcp_replay_cache')); // your table name
167
+ ```
168
+
169
+ The migration is idempotent. If you manage schema with numbered migration
170
+ files, add a new file with the current `getReplayStoreMigration()` output; a
171
+ file copied from an older SDK does not create the function.
172
+
154
173
  ## Account resolution and optional declarations
155
174
 
156
175
  On a served AdCP 3.3 route, buyer-supplied account references require a
@@ -255,6 +274,14 @@ For AdCP 3.0 buyers, `create_media_buy` and `update_media_buy` responses move
255
274
  waiting on creatives therefore returns `status: 'pending_creatives'`; 3.1+
256
275
  responses keep task `status` separate from `media_buy_status`.
257
276
 
277
+ This projection applies to responses the framework emits. A webhook your
278
+ platform builds itself from a copy of the response, such as an inline completion
279
+ callback to a 3.0 buyer, does not pass through it. Apply the same mapping so the
280
+ webhook `result` matches the buyer-visible response: for a 3.0 buyer, carry the
281
+ media buy status as `status` and omit `media_buy_status`. A test comparing the
282
+ webhook `result` with the synchronous response catches drift. Exporting the
283
+ projection for seller-emitted webhooks is tracked in #3475.
284
+
258
285
  ## Receivers with their own delivery webhook verification
259
286
 
260
287
  `parseMediaBuyDeliveryWebhook` from `@adcp/sdk/webhooks` validates an already
@@ -3,10 +3,11 @@
3
3
  The experimental identity rollout is tracked in
4
4
  [adcp-client#3233](https://github.com/adcontextprotocol/adcp-client/issues/3233).
5
5
  This release implements the rollout behind explicit experimental configuration.
6
- The SDK's default `ADCP_VERSION` remains **3.2.5**. Experimental client/server
7
- instances select the 3.3 carrier and apply the pinned draft overlays to the
8
- released bundle; they do not regenerate or replace the public 3.2 types.
9
- Upstream PRs remain open, so the experiment can change before graduation.
6
+ SDK 17 beta pins `ADCP_VERSION` to **3.3.0-beta.0**; SDK 16 remains on 3.2.
7
+ The identity experiment can change before graduation. Setting `identity33`
8
+ selects the 3.3 schema scope for the entire server instance, including its
9
+ non-identity tools. To keep an existing 3.2 endpoint while evaluating identity,
10
+ create a separate server instance and mount it on another route.
10
11
 
11
12
  The dedicated API is `@adcp/sdk/identity-3.3`. Existing RFC configuration remains
12
13
  supported through 3.x and emits a one-time deprecation warning when used.
@@ -287,6 +288,99 @@ reassignment. Authorization runs before idempotency lookup and handler effects.
287
288
  Keep the normal buyer registry's suspension, blocking, sandbox and billing
288
289
  gates enabled; grants do not replace them.
289
290
 
291
+ ### Custom MCP hosts
292
+
293
+ `signedRequests` installs HTTP middleware through `ADCP_PRE_TRANSPORT`. `serve()`
294
+ and `createA2AAdapter()` consume it automatically. A host that calls
295
+ `server.connect(transport)` directly must mount that middleware before handing
296
+ requests to the MCP transport; the server refuses the connection when the hook has not been
297
+ consumed. Connecting the transport alone cannot verify HTTP signatures.
298
+ Reading the symbol acknowledges that the custom host mounts the middleware;
299
+ the framework cannot verify external middleware installation. Socket Mode and
300
+ in-memory transports cannot run this HTTP verifier; use a separate server
301
+ instance without `signedRequests` for those transports.
302
+ Framework-managed MCP connections are permitted per transport after middleware
303
+ accepts the request. Creating an A2A adapter does not acknowledge MCP middleware.
304
+
305
+ For a host with its own authentication layer, compose
306
+ `verifySignatureAsAuthenticator({ webBotAuth, ... })` instead. A Web Bot Auth-only
307
+ authenticator can omit `jwks`; legacy signatures are then refused. For example:
308
+
309
+ ```ts
310
+ import { createIdentity33PrincipalResolver } from '@adcp/sdk/identity-3.3';
311
+ import {
312
+ adcpOperationResolver,
313
+ requireSignatureWhenPresent,
314
+ verifySignatureAsAuthenticator,
315
+ } from '@adcp/sdk/server';
316
+
317
+ const signature = verifySignatureAsAuthenticator({
318
+ capability: {
319
+ supported: true,
320
+ profiles: ['web-bot-auth'],
321
+ covers_content_digest: 'required',
322
+ required_for: [],
323
+ },
324
+ replayStore, // Shared across requests and replicas.
325
+ resolveOperation: adcpOperationResolver,
326
+ // Trusted deployment config; never use caller-supplied forwarding headers.
327
+ getUrl: () => 'https://seller.example.com/mcp',
328
+ webBotAuth: {
329
+ directory,
330
+ resolvePrincipal: createIdentity33PrincipalResolver({ lifecycle, revocation: revocations }),
331
+ },
332
+ });
333
+ const authenticate = requireSignatureWhenPresent(signature, existingAuthenticator);
334
+ ```
335
+
336
+ Bind this authenticator to the configured `/mcp` route. The host must capture
337
+ the exact UTF-8 body in `req.rawBody` before JSON parsing,
338
+ run `authenticate` before `transport.handleRequest`, and propagate the returned
339
+ principal and authentication failures through its existing auth integration.
340
+ Hoist the authenticator and replay store outside request factories. If using
341
+ `serve()` with this authenticator, it captures the body automatically.
342
+
343
+ ### Signed storyboard steps against a local agent
344
+
345
+ Storyboard steps can select a named runtime identity:
346
+
347
+ ```yaml
348
+ auth: { type: web_bot_auth, identity: authorized_buyer }
349
+ ```
350
+
351
+ Pass keys separately from the YAML:
352
+
353
+ ```ts
354
+ import { runStoryboard } from '@adcp/sdk/testing';
355
+
356
+ await runStoryboard('http://127.0.0.1:3001/mcp', storyboard, {
357
+ protocol: 'mcp',
358
+ allow_http: true,
359
+ web_bot_auth: {
360
+ publicUrl: 'https://seller.example.com/mcp',
361
+ identities: {
362
+ authorized_buyer: { origin: 'https://buyer.agency.com', key: { privateKey: buyerJwk } },
363
+ impersonator: { origin: 'https://other.agency.com', key: { privateKey: otherJwk } },
364
+ },
365
+ },
366
+ });
367
+ ```
368
+
369
+ Loopback delivery supports MCP; A2A steps can sign directly to HTTPS. The
370
+ official MCP client signs the public HTTPS target and delivers to the exact
371
+ loopback endpoint. Configure the local verifier's trusted public URL to match,
372
+ and publish or inject the identities' directory, revocation and trust records.
373
+ Each overridden step uses a separate client and strips ambient bearer/API-key
374
+ credentials. An unknown identity fails the step before dispatch. These steps
375
+ support tool-response validations; HTTP probe assertions and session probes
376
+ require their existing authentication directives. The URL override accepts only
377
+ loopback delivery, keeps redirects disabled, and does not relax the production
378
+ signer's HTTPS requirement. Omit `publicUrl` for signing directly to HTTPS.
379
+ For custom official transport wiring, `createStoryboardWebBotAuthFetch` from
380
+ `@adcp/sdk/testing` exposes the same delivery helper.
381
+ For direct HTTPS use of the helper, pass `agentUrl` to pin the destination
382
+ origin. Redirects are refused before the transport can follow them.
383
+
290
384
  `bindPrincipal` requires seller audit evidence. Existing RFC mappings require
291
385
  explicit migration approval and an unambiguous origin. `sync_principal` may
292
386
  create only a new principal under declared open tiers; legacy-ledger lookup is
@@ -310,6 +404,14 @@ provided notification ID as the emitter's delivery ID. Call
310
404
 
311
405
  ## Trust, grants, and revocation
312
406
 
407
+ Identity authorization requires registrable domains from the pinned PSL.
408
+ Special-use names such as `brand.example`, `localhost`, and IP addresses cannot
409
+ establish trust or grants; invalid brand, account-operator, and resolved-house
410
+ domains receive coded `PERMISSION_DENIED` refusals. For tests, use registrable
411
+ fixture domains and inject `TrustEvaluator({ fetchOptions: { trustedFetchFn } })`
412
+ to serve their test trust records without relying on live DNS. This hook changes
413
+ record delivery, not domain validation or grant authorization.
414
+
313
415
  The operator is derived using the pinned ICANN+PRIVATE PSL, never a document
314
416
  field or authoritative hop host. Trust reads allow one document hop, zero HTTP
315
417
  redirects, 2 MiB, depth 32, and no duplicate JSON keys. Exactly one canonical
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adcp/sdk",
3
- "version": "17.0.0-beta.2",
3
+ "version": "17.0.0-beta.3",
4
4
  "description": "AdCP SDK — client, server, and compliance harnesses for the AdContext Protocol (MCP + A2A)",
5
5
  "workspaces": [
6
6
  ".",
@@ -51,6 +51,16 @@
51
51
  "default": "./dist/lib/compliance/index.js"
52
52
  }
53
53
  },
54
+ "./adapters/version": {
55
+ "import": {
56
+ "types": "./dist/lib/adapters/version/index.d.mts",
57
+ "default": "./dist/lib/adapters/version/index.mjs"
58
+ },
59
+ "require": {
60
+ "types": "./dist/lib/adapters/version/index.d.ts",
61
+ "default": "./dist/lib/adapters/version/index.js"
62
+ }
63
+ },
54
64
  "./advanced": {
55
65
  "import": {
56
66
  "types": "./dist/lib/advanced.d.mts",
@@ -432,6 +442,9 @@
432
442
  "compliance": [
433
443
  "dist/lib/compliance/index.d.ts"
434
444
  ],
445
+ "adapters/version": [
446
+ "dist/lib/adapters/version/index.d.ts"
447
+ ],
435
448
  "advanced": [
436
449
  "dist/lib/advanced.d.ts"
437
450
  ],
@@ -732,7 +745,7 @@
732
745
  "dependencies": {
733
746
  "@modelcontextprotocol/client": "2.3.1",
734
747
  "@modelcontextprotocol/ext-apps": "2.0.0",
735
- "@modelcontextprotocol/node": "2.0.0",
748
+ "@modelcontextprotocol/node": "2.1.1",
736
749
  "@modelcontextprotocol/server": "2.3.1",
737
750
  "@types/ws": "^8.18.1",
738
751
  "ajv": "^8.20.0",