@adcp/sdk 14.0.0 → 14.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/adapters/implicit-account-store.d.mts +12 -7
- package/dist/lib/adapters/implicit-account-store.d.ts +12 -7
- package/dist/lib/adapters/implicit-account-store.js +69 -15
- package/dist/lib/adapters/implicit-account-store.mjs +69 -15
- package/dist/lib/core/AgentClient.d.mts +1 -0
- package/dist/lib/core/AgentClient.d.ts +1 -0
- package/dist/lib/core/AgentClient.js +3 -0
- package/dist/lib/core/AgentClient.mjs +3 -0
- package/dist/lib/core/SingleAgentClient.d.mts +35 -2
- package/dist/lib/core/SingleAgentClient.d.ts +35 -2
- package/dist/lib/core/SingleAgentClient.js +377 -36
- package/dist/lib/core/SingleAgentClient.mjs +387 -38
- package/dist/lib/core/TaskExecutor.d.mts +3 -1
- package/dist/lib/core/TaskExecutor.d.ts +3 -1
- package/dist/lib/core/TaskExecutor.js +17 -12
- package/dist/lib/core/TaskExecutor.mjs +17 -12
- package/dist/lib/core/account-key.d.mts +3 -0
- package/dist/lib/core/account-key.d.ts +3 -0
- package/dist/lib/core/account-key.js +41 -0
- package/dist/lib/core/account-key.mjs +17 -0
- package/dist/lib/core/account-resolution.d.mts +2 -0
- package/dist/lib/core/account-resolution.d.ts +2 -0
- package/dist/lib/core/buyer-account-registry.d.mts +93 -0
- package/dist/lib/core/buyer-account-registry.d.ts +93 -0
- package/dist/lib/core/buyer-account-registry.js +602 -0
- package/dist/lib/core/buyer-account-registry.mjs +578 -0
- package/dist/lib/core/product-cache.d.mts +18 -0
- package/dist/lib/core/product-cache.d.ts +18 -0
- package/dist/lib/core/product-cache.js +137 -0
- package/dist/lib/core/product-cache.mjs +112 -0
- package/dist/lib/errors/index.d.mts +40 -1
- package/dist/lib/errors/index.d.ts +40 -1
- package/dist/lib/errors/index.js +69 -3
- package/dist/lib/errors/index.mjs +64 -3
- package/dist/lib/governance/authorization.d.mts +17 -1
- package/dist/lib/governance/authorization.d.ts +17 -1
- package/dist/lib/governance/authorization.js +55 -7
- package/dist/lib/governance/authorization.mjs +59 -7
- package/dist/lib/governance/index.d.mts +2 -2
- package/dist/lib/governance/index.d.ts +2 -2
- package/dist/lib/governance/index.js +2 -0
- package/dist/lib/governance/index.mjs +3 -1
- package/dist/lib/index.d.mts +7 -4
- package/dist/lib/index.d.ts +7 -4
- package/dist/lib/index.js +29 -0
- package/dist/lib/index.mjs +31 -1
- package/dist/lib/net/agent-transport-fetch.d.mts +4 -0
- package/dist/lib/net/agent-transport-fetch.d.ts +4 -0
- package/dist/lib/net/agent-transport-fetch.js +18 -5
- package/dist/lib/net/agent-transport-fetch.mjs +17 -5
- package/dist/lib/protocols/a2a.js +9 -1
- package/dist/lib/protocols/a2a.mjs +9 -1
- package/dist/lib/protocols/index.js +9 -2
- package/dist/lib/protocols/index.mjs +9 -2
- package/dist/lib/protocols/mcp-modern.js +2 -1
- package/dist/lib/protocols/mcp-modern.mjs +2 -1
- package/dist/lib/protocols/mcp.js +5 -2
- package/dist/lib/protocols/mcp.mjs +5 -2
- package/dist/lib/protocols/rawResponseCapture.d.mts +6 -0
- package/dist/lib/protocols/rawResponseCapture.d.ts +6 -0
- package/dist/lib/protocols/rawResponseCapture.js +41 -29
- package/dist/lib/protocols/rawResponseCapture.mjs +40 -29
- package/dist/lib/protocols/signedRequestRejection.d.mts +9 -0
- package/dist/lib/protocols/signedRequestRejection.d.ts +9 -0
- package/dist/lib/protocols/signedRequestRejection.js +209 -0
- package/dist/lib/protocols/signedRequestRejection.mjs +189 -0
- package/dist/lib/protocols/transportDiagnostics.d.mts +1 -0
- package/dist/lib/protocols/transportDiagnostics.d.ts +1 -0
- package/dist/lib/protocols/transportDiagnostics.js +2 -0
- package/dist/lib/protocols/transportDiagnostics.mjs +1 -0
- package/dist/lib/registry/types.generated.d.mts +112 -45
- package/dist/lib/registry/types.generated.d.ts +112 -45
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/server/account-provisioning.d.mts +2 -0
- package/dist/lib/server/account-provisioning.d.ts +2 -0
- package/dist/lib/server/account-provisioning.js +30 -0
- package/dist/lib/server/account-provisioning.mjs +6 -0
- package/dist/lib/server/account-reference-warnings.d.mts +12 -0
- package/dist/lib/server/account-reference-warnings.d.ts +12 -0
- package/dist/lib/server/account-reference-warnings.js +48 -0
- package/dist/lib/server/account-reference-warnings.mjs +23 -0
- package/dist/lib/server/auth-signature.js +1 -0
- package/dist/lib/server/auth-signature.mjs +1 -0
- package/dist/lib/server/create-adcp-server.d.mts +34 -0
- package/dist/lib/server/create-adcp-server.d.ts +34 -0
- package/dist/lib/server/create-adcp-server.js +225 -14
- package/dist/lib/server/create-adcp-server.mjs +225 -14
- package/dist/lib/server/decisioning/account.d.mts +2 -0
- package/dist/lib/server/decisioning/account.d.ts +2 -0
- package/dist/lib/server/decisioning/runtime/from-platform.js +49 -10
- package/dist/lib/server/decisioning/runtime/from-platform.mjs +49 -10
- package/dist/lib/server/index.d.mts +2 -2
- package/dist/lib/server/index.d.ts +2 -2
- package/dist/lib/server/index.js +2 -0
- package/dist/lib/server/index.mjs +3 -1
- package/dist/lib/signing/agent-resolver/consistency.d.mts +6 -13
- package/dist/lib/signing/agent-resolver/consistency.d.ts +6 -13
- package/dist/lib/signing/agent-resolver/consistency.js +0 -1
- package/dist/lib/signing/agent-resolver/consistency.mjs +0 -1
- package/dist/lib/signing/agent-resolver/errors.d.mts +3 -1
- package/dist/lib/signing/agent-resolver/errors.d.ts +3 -1
- package/dist/lib/signing/agent-resolver/errors.js +6 -0
- package/dist/lib/signing/agent-resolver/errors.mjs +6 -0
- package/dist/lib/signing/agent-resolver/fetch-helpers.d.mts +11 -0
- package/dist/lib/signing/agent-resolver/fetch-helpers.d.ts +11 -0
- package/dist/lib/signing/agent-resolver/fetch-helpers.js +37 -2
- package/dist/lib/signing/agent-resolver/fetch-helpers.mjs +40 -3
- package/dist/lib/signing/agent-resolver/jwks-set.js +24 -3
- package/dist/lib/signing/agent-resolver/jwks-set.mjs +24 -3
- package/dist/lib/signing/agent-resolver/legacy-brand.d.mts +15 -0
- package/dist/lib/signing/agent-resolver/legacy-brand.d.ts +15 -0
- package/dist/lib/signing/agent-resolver/legacy-brand.js +60 -0
- package/dist/lib/signing/agent-resolver/legacy-brand.mjs +36 -0
- package/dist/lib/signing/agent-resolver/operator-authorization.d.mts +13 -0
- package/dist/lib/signing/agent-resolver/operator-authorization.d.ts +13 -0
- package/dist/lib/signing/agent-resolver/operator-authorization.js +108 -0
- package/dist/lib/signing/agent-resolver/operator-authorization.mjs +84 -0
- package/dist/lib/signing/agent-resolver/resolve-agent.d.mts +14 -4
- package/dist/lib/signing/agent-resolver/resolve-agent.d.ts +14 -4
- package/dist/lib/signing/agent-resolver/resolve-agent.js +148 -137
- package/dist/lib/signing/agent-resolver/resolve-agent.mjs +157 -139
- package/dist/lib/signing/agent-resolver/resolved-agent-jwks.d.mts +7 -1
- package/dist/lib/signing/agent-resolver/resolved-agent-jwks.d.ts +7 -1
- package/dist/lib/signing/agent-resolver/resolved-agent-jwks.js +50 -17
- package/dist/lib/signing/agent-resolver/resolved-agent-jwks.mjs +50 -17
- package/dist/lib/signing/agent-resolver/select-agent.d.mts +14 -15
- package/dist/lib/signing/agent-resolver/select-agent.d.ts +14 -15
- package/dist/lib/signing/agent-resolver/select-agent.js +98 -13
- package/dist/lib/signing/agent-resolver/select-agent.mjs +95 -13
- package/dist/lib/signing/brand-jwks.d.mts +29 -75
- package/dist/lib/signing/brand-jwks.d.ts +29 -75
- package/dist/lib/signing/brand-jwks.js +120 -182
- package/dist/lib/signing/brand-jwks.mjs +120 -182
- package/dist/lib/signing/errors.d.mts +7 -3
- package/dist/lib/signing/errors.d.ts +7 -3
- package/dist/lib/signing/errors.js +7 -2
- package/dist/lib/signing/errors.mjs +7 -2
- package/dist/lib/signing/jwks-https.d.mts +7 -0
- package/dist/lib/signing/jwks-https.d.ts +7 -0
- package/dist/lib/signing/jwks-https.js +31 -8
- package/dist/lib/signing/jwks-https.mjs +31 -8
- package/dist/lib/signing/jwks.d.mts +8 -0
- package/dist/lib/signing/jwks.d.ts +8 -0
- package/dist/lib/signing/middleware.js +2 -1
- package/dist/lib/signing/middleware.mjs +2 -1
- package/dist/lib/signing/publisher-pins.d.mts +11 -0
- package/dist/lib/signing/publisher-pins.d.ts +11 -0
- package/dist/lib/signing/publisher-pins.js +125 -0
- package/dist/lib/signing/publisher-pins.mjs +101 -0
- package/dist/lib/signing/server.d.mts +1 -0
- package/dist/lib/signing/server.d.ts +1 -0
- package/dist/lib/signing/types.d.mts +5 -0
- package/dist/lib/signing/types.d.ts +5 -0
- package/dist/lib/signing/verifier.js +50 -5
- package/dist/lib/signing/verifier.mjs +50 -5
- package/dist/lib/signing/webhook-verifier.d.mts +7 -2
- package/dist/lib/signing/webhook-verifier.d.ts +7 -2
- package/dist/lib/signing/webhook-verifier.js +42 -2
- package/dist/lib/signing/webhook-verifier.mjs +42 -2
- package/dist/lib/testing/storyboard/account-policy.d.mts +2 -0
- package/dist/lib/testing/storyboard/account-policy.d.ts +2 -0
- package/dist/lib/testing/storyboard/account-policy.js +35 -0
- package/dist/lib/testing/storyboard/account-policy.mjs +11 -0
- package/dist/lib/testing/storyboard/context.js +6 -0
- package/dist/lib/testing/storyboard/context.mjs +6 -0
- package/dist/lib/testing/storyboard/request-builder.js +12 -2
- package/dist/lib/testing/storyboard/request-builder.mjs +12 -2
- package/dist/lib/testing/storyboard/runner.js +3 -2
- package/dist/lib/testing/storyboard/runner.mjs +3 -2
- package/dist/lib/testing/storyboard/validations.d.mts +1 -1
- package/dist/lib/testing/storyboard/validations.d.ts +1 -1
- package/dist/lib/types/accept-proposal.d.ts +19 -1
- package/dist/lib/types/buy-products.d.ts +19 -1
- package/dist/lib/types/check-governance.d.ts +19 -1
- package/dist/lib/types/comply-test-controller.d.ts +19 -1
- package/dist/lib/types/control-media-buy.d.ts +19 -1
- package/dist/lib/types/core.generated.d.mts +14 -1
- package/dist/lib/types/core.generated.d.ts +14 -1
- package/dist/lib/types/create-media-buy.d.ts +14 -1
- package/dist/lib/types/get-media-buys.d.ts +14 -1
- package/dist/lib/types/get-products.d.ts +19 -1
- package/dist/lib/types/list-products.d.ts +19 -1
- package/dist/lib/types/refine-proposals.d.ts +19 -1
- package/dist/lib/types/request-proposals.d.ts +19 -1
- package/dist/lib/types/schemas.generated.d.ts +12 -3
- package/dist/lib/types/schemas.generated.js +4 -1
- package/dist/lib/types/schemas.generated.mjs +4 -1
- package/dist/lib/types/tools.generated.d.mts +14 -1
- package/dist/lib/types/tools.generated.d.ts +14 -1
- package/dist/lib/types/update-media-buy.d.ts +14 -1
- package/dist/lib/version.d.mts +3 -3
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.js +3 -3
- package/dist/lib/version.mjs +3 -3
- package/dist/lib/webhooks/index.d.mts +24 -0
- package/dist/lib/webhooks/index.d.ts +24 -0
- package/dist/lib/webhooks/index.js +50 -24
- package/dist/lib/webhooks/index.mjs +49 -24
- package/dist/lib/wholesale-feed-sync/index.d.mts +2 -0
- package/dist/lib/wholesale-feed-sync/index.d.ts +2 -0
- package/dist/lib/wholesale-feed-sync/index.js +7 -0
- package/dist/lib/wholesale-feed-sync/index.mjs +4 -0
- package/dist/lib/wholesale-feed-sync/mirror.d.mts +97 -0
- package/dist/lib/wholesale-feed-sync/mirror.d.ts +97 -0
- package/dist/lib/wholesale-feed-sync/mirror.js +350 -0
- package/dist/lib/wholesale-feed-sync/mirror.mjs +322 -0
- package/dist/lib/wholesale-feed-sync/sync.d.mts +13 -29
- package/dist/lib/wholesale-feed-sync/sync.d.ts +13 -29
- package/dist/lib/wholesale-feed-sync/sync.js +208 -281
- package/dist/lib/wholesale-feed-sync/sync.mjs +213 -281
- package/dist/lib/wholesale-feed-sync/types.d.mts +4 -3
- package/dist/lib/wholesale-feed-sync/types.d.ts +4 -3
- package/docs/README.md +6 -0
- package/docs/TYPE-SUMMARY.md +2 -2
- package/docs/guides/BUILD-AN-AGENT.md +2 -2
- package/docs/guides/BUYER-QUICKSTART-3.2.md +2 -0
- package/docs/guides/BUYER-STORAGE.md +3 -0
- package/docs/guides/FIRST-CALL-TO-A-SELLER.md +106 -0
- package/docs/guides/SIGNING-GUIDE.md +16 -7
- package/docs/guides/account-resolution.md +132 -10
- package/docs/llms.txt +3 -2
- package/docs/migration-14.0-to-14.1.md +85 -0
- package/docs/migration-14.x-rc-worksheet.md +4 -4
- package/docs/migration-4.x-to-5.x.md +1 -0
- package/docs/migration-agent-resolution-3.3.md +125 -0
- package/docs/recipes/verifying-inbound-webhooks.md +60 -15
- package/package.json +3 -2
- package/skills/adcp-brand.previous/SKILL.md +0 -200
- package/skills/adcp-creative.previous/SKILL.md +0 -305
- package/skills/adcp-governance.previous/SKILL.md +0 -566
- package/skills/adcp-measurement.previous/SKILL.md +0 -136
- package/skills/adcp-media-buy.previous/SKILL.md +0 -556
- package/skills/adcp-si.previous/SKILL.md +0 -206
- package/skills/adcp-signals.previous/SKILL.md +0 -204
|
@@ -22,7 +22,7 @@ export type WholesaleFeedSyncMode = 'manual' | 'auto-poll';
|
|
|
22
22
|
/**
|
|
23
23
|
* Lifecycle state of the sync engine.
|
|
24
24
|
*/
|
|
25
|
-
export type WholesaleFeedSyncState = 'idle' | 'bootstrapping' | 'syncing' | 'error';
|
|
25
|
+
export type WholesaleFeedSyncState = 'idle' | 'bootstrapping' | 'syncing' | 'degraded' | 'error';
|
|
26
26
|
/**
|
|
27
27
|
* Subset of `SingleAgentClient` that {@link WholesaleFeedSync} actually uses.
|
|
28
28
|
* Lets tests inject a minimal stub without constructing a full client.
|
|
@@ -178,8 +178,8 @@ export interface ResolvedCapabilities {
|
|
|
178
178
|
* picks a mode. Useful for UI mode badges.
|
|
179
179
|
* - `resyncing` — emitted before a `wholesale_feed.bulk_change` recovery
|
|
180
180
|
* re-bootstrap, webhook-version mismatch repair, or manual refresh.
|
|
181
|
-
* - `error` —
|
|
182
|
-
*
|
|
181
|
+
* - `error` — initial bootstrap, re-sync, or background probe failure.
|
|
182
|
+
* Failed refreshes preserve the last good mirror and retry on the next tick.
|
|
183
183
|
* - `stateChange` — fires on every {@link WholesaleFeedSyncState} transition.
|
|
184
184
|
*/
|
|
185
185
|
export interface WholesaleFeedSyncEvents {
|
|
@@ -200,6 +200,7 @@ export interface WholesaleFeedSyncEvents {
|
|
|
200
200
|
}];
|
|
201
201
|
error: [{
|
|
202
202
|
error: Error;
|
|
203
|
+
adcpError?: import('../core/ConversationTypes.mjs').AdcpErrorInfo;
|
|
203
204
|
}];
|
|
204
205
|
stateChange: [{
|
|
205
206
|
from: WholesaleFeedSyncState;
|
|
@@ -22,7 +22,7 @@ export type WholesaleFeedSyncMode = 'manual' | 'auto-poll';
|
|
|
22
22
|
/**
|
|
23
23
|
* Lifecycle state of the sync engine.
|
|
24
24
|
*/
|
|
25
|
-
export type WholesaleFeedSyncState = 'idle' | 'bootstrapping' | 'syncing' | 'error';
|
|
25
|
+
export type WholesaleFeedSyncState = 'idle' | 'bootstrapping' | 'syncing' | 'degraded' | 'error';
|
|
26
26
|
/**
|
|
27
27
|
* Subset of `SingleAgentClient` that {@link WholesaleFeedSync} actually uses.
|
|
28
28
|
* Lets tests inject a minimal stub without constructing a full client.
|
|
@@ -178,8 +178,8 @@ export interface ResolvedCapabilities {
|
|
|
178
178
|
* picks a mode. Useful for UI mode badges.
|
|
179
179
|
* - `resyncing` — emitted before a `wholesale_feed.bulk_change` recovery
|
|
180
180
|
* re-bootstrap, webhook-version mismatch repair, or manual refresh.
|
|
181
|
-
* - `error` —
|
|
182
|
-
*
|
|
181
|
+
* - `error` — initial bootstrap, re-sync, or background probe failure.
|
|
182
|
+
* Failed refreshes preserve the last good mirror and retry on the next tick.
|
|
183
183
|
* - `stateChange` — fires on every {@link WholesaleFeedSyncState} transition.
|
|
184
184
|
*/
|
|
185
185
|
export interface WholesaleFeedSyncEvents {
|
|
@@ -200,6 +200,7 @@ export interface WholesaleFeedSyncEvents {
|
|
|
200
200
|
}];
|
|
201
201
|
error: [{
|
|
202
202
|
error: Error;
|
|
203
|
+
adcpError?: import('../core/ConversationTypes').AdcpErrorInfo;
|
|
203
204
|
}];
|
|
204
205
|
stateChange: [{
|
|
205
206
|
from: WholesaleFeedSyncState;
|
package/docs/README.md
CHANGED
|
@@ -25,6 +25,12 @@ Use the [buyer quick start](./guides/BUYER-QUICKSTART-3.2.md). For the complete
|
|
|
25
25
|
tool and type inventory, use [llms.txt](./llms.txt) and the
|
|
26
26
|
[type summary](./TYPE-SUMMARY.md).
|
|
27
27
|
|
|
28
|
+
## Upgrade from SDK 14.0
|
|
29
|
+
|
|
30
|
+
Use the [14.0-to-14.1 upgrade checklist](./migration-14.0-to-14.1.md) for
|
|
31
|
+
required changes, opt-in features, and stricter signature verification. SDK
|
|
32
|
+
14.1.0 continues to use AdCP 3.2.1 on the wire.
|
|
33
|
+
|
|
28
34
|
## Upgrade from SDK 13
|
|
29
35
|
|
|
30
36
|
Start with the [release-bound upgrade worksheet](./migration-14.x-rc-worksheet.md),
|
package/docs/TYPE-SUMMARY.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# AdCP Type Summary
|
|
2
2
|
|
|
3
|
-
> Generated at: 2026-10-
|
|
4
|
-
> @adcp/sdk v14.
|
|
3
|
+
> Generated at: 2026-10-05
|
|
4
|
+
> @adcp/sdk v14.2.0
|
|
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
|
|
|
@@ -671,7 +671,7 @@ import {
|
|
|
671
671
|
requireAuthenticatedOrSigned,
|
|
672
672
|
mcpToolNameResolver,
|
|
673
673
|
} from '@adcp/sdk/server';
|
|
674
|
-
import {
|
|
674
|
+
import { ResolvedAgentJwksResolver } from '@adcp/sdk/signing/server';
|
|
675
675
|
|
|
676
676
|
serve(
|
|
677
677
|
() =>
|
|
@@ -692,7 +692,7 @@ serve(
|
|
|
692
692
|
authenticate: requireAuthenticatedOrSigned({
|
|
693
693
|
signature: verifySignatureAsAuthenticator({
|
|
694
694
|
capability: { supported: true, required_for: ['create_media_buy', 'update_media_buy'], covers_content_digest: 'either' },
|
|
695
|
-
jwks: new
|
|
695
|
+
jwks: new ResolvedAgentJwksResolver('https://buyer.example/mcp', 'mcp'),
|
|
696
696
|
resolveOperation: mcpToolNameResolver,
|
|
697
697
|
}),
|
|
698
698
|
fallback: verifyApiKey({ keys: { sk_live_abc: { principal: 'acct_42' } } }),
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Call a seller with AdCP 3.2
|
|
2
2
|
|
|
3
|
+
For a new seller, start with [account setup and public discovery](./FIRST-CALL-TO-A-SELLER.md).
|
|
4
|
+
|
|
3
5
|
For product possibility, accepted change rights, and current execution routes, use the [MediaBuy action assessment helpers](./MEDIA-BUY-ACTION-ASSESSMENT.md).
|
|
4
6
|
|
|
5
7
|
Requires Node.js `^20.19.0 || >=22.12.0`. Install SDK 14
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
# Buyer-owned storage and scheduling
|
|
2
|
+
|
|
3
|
+
See the [adapter contracts and recovery guide](https://github.com/adcontextprotocol/adcp-client/blob/main/docs/development/BUYER-STORAGE.md) for timer-free catalog mirrors, CAS provisioning, dispatch hooks, and caller-owned replay keys.
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# First call to a seller
|
|
2
|
+
|
|
3
|
+
An account reference selects a provisioned account at that seller. Discovery
|
|
4
|
+
does not provision it. Until setup is complete, send a top-level `brand` on
|
|
5
|
+
tools that support public discovery, and omit `account`.
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { AgentClient, createProductCache } from '@adcp/sdk';
|
|
9
|
+
|
|
10
|
+
const client = new AgentClient(sellerConfig, {
|
|
11
|
+
accountPolicy: 'auto',
|
|
12
|
+
productCache: createProductCache({ publicTtl: 60_000, accountTtl: 30_000 }),
|
|
13
|
+
});
|
|
14
|
+
const capabilities = await client.getCapabilities();
|
|
15
|
+
const brand = { domain: 'advertiser.example' };
|
|
16
|
+
const account = { brand, operator: 'agency.example' };
|
|
17
|
+
|
|
18
|
+
// Only use public discovery when the seller permits it.
|
|
19
|
+
if (!capabilities.account?.requiredForProducts) {
|
|
20
|
+
const publicCatalog = await client.getProducts({ brand, brief: 'Display inventory' });
|
|
21
|
+
if (!publicCatalog.success) console.error(publicCatalog.adcpError);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Choose billing terms before accepting them. This returns seller status and handle.
|
|
25
|
+
const setup = await client.accounts.ensure(account, {
|
|
26
|
+
billing: 'operator',
|
|
27
|
+
paymentTerms: 'net_30',
|
|
28
|
+
});
|
|
29
|
+
if (setup.status === 'active') {
|
|
30
|
+
const pricedCatalog = await client.getProducts({ account, brand, brief: 'Display inventory' });
|
|
31
|
+
if (!pricedCatalog.success) console.error(pricedCatalog.adcpError);
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
For agent-billed provisioning, pass `billingEntity` with the seller's required
|
|
36
|
+
business identity. `paymentTerms` and `billingEntity` are also accepted by
|
|
37
|
+
`resolveAccount()`. That helper keeps its existing pending-approval exception;
|
|
38
|
+
`accounts.ensure()` returns the status so callers can present the setup flow.
|
|
39
|
+
Non-active entries refresh through `list_accounts` when a seller handle is known.
|
|
40
|
+
An existing registry entry prevents repeated provisioning and silent acceptance
|
|
41
|
+
of new terms. To change terms, explicitly call `syncAccounts()`.
|
|
42
|
+
An explicit `ensure` with conflicting known setup terms refuses the change.
|
|
43
|
+
If the seller no longer lists an account, explicitly reestablish it with
|
|
44
|
+
`syncAccounts` after choosing terms; status repair never silently re-provisions it.
|
|
45
|
+
Caller cancellation stops waiting for setup; the single seller operation continues
|
|
46
|
+
so another caller cannot accidentally accept different terms concurrently.
|
|
47
|
+
Terminal setup failures permit an explicit retry. For interrupted async setup,
|
|
48
|
+
read `accounts.get(key).pendingTaskId`, reconcile that seller task, and pass its
|
|
49
|
+
completed rows to `accounts.observeSync([key], rows)` (or let the original
|
|
50
|
+
`syncAccounts` completion handle update the registry). Do not resubmit unresolved tasks.
|
|
51
|
+
|
|
52
|
+
For a seller that requires operator authentication, use `resolveAccount()` to
|
|
53
|
+
select an active account returned by `list_accounts`. An account ID echoed by
|
|
54
|
+
`sync_accounts` is a seller handle; implicit sellers still require the natural
|
|
55
|
+
key on subsequent calls. Do not replace it with `{ account_id }` automatically.
|
|
56
|
+
|
|
57
|
+
`accountPolicy` defaults to `'off'` to preserve existing requests. Opt-in
|
|
58
|
+
`'auto'` omits unknown accounts on public discovery tools that support `brand`;
|
|
59
|
+
it refuses required-account discovery, async discovery, and mutations until
|
|
60
|
+
the registry knows the key. `'strict'` refuses every unknown account-carrying
|
|
61
|
+
request. Both policies require an active account before spend commitments.
|
|
62
|
+
Explicit account filters on `list_accounts` remain filters.
|
|
63
|
+
Call `listAccounts` first when adopting these policies with existing opaque
|
|
64
|
+
account IDs so the registry knows those seller handles.
|
|
65
|
+
|
|
66
|
+
Provisioning is remembered per seller and caller. `syncAccounts()` and
|
|
67
|
+
`listAccounts()` update the registry on completed results; failed rows and dry
|
|
68
|
+
runs do not establish accounts. After verifying an `account.status_changed`
|
|
69
|
+
notification, call `client.accounts.applyStatusChange({ account_id })` to repair
|
|
70
|
+
from authoritative `list_accounts`. The notification's status is not trusted as
|
|
71
|
+
a snapshot, which avoids reordered deliveries overwriting current state.
|
|
72
|
+
|
|
73
|
+
The registry is in memory by default. Set `accountStorage` to an adapter with
|
|
74
|
+
`get(key)` and `set(key, entry)` for persistence. For multiple processes, add
|
|
75
|
+
revision-checked `compareAndSet` writes and dispatch ledger hooks; see
|
|
76
|
+
[buyer storage and scheduling](BUYER-STORAGE.md). Keys partition by seller URI,
|
|
77
|
+
protocol, and caller scope. Client-credentials OAuth uses the stable client ID, token endpoint, scopes, and resource. Authorization-code OAuth pins this client's initial grant fingerprint, keeping distinct user grants apart while automatic refreshes preserve its partition. Create a new client when switching users. Other credential modes fingerprint credentials;
|
|
78
|
+
for continuity across token rotations, supply `accountRegistryScope` from a
|
|
79
|
+
trusted stable principal identifier. Never share that scope between tenants.
|
|
80
|
+
Request-signing key identity is also part of the default fingerprint, so distinct
|
|
81
|
+
signers stay isolated. Key rotation requires reprovisioning or a trusted stable
|
|
82
|
+
`accountRegistryScope` for the same principal.
|
|
83
|
+
Registry memory and aliases per handle are bounded by `accountRegistryMaxEntries` (default 10,000); durable adapters allow entry eviction and reload. Without storage, reaching capacity throws a setup error; raise the limit or configure storage for large rosters. `resolveAccount()` uses the memoized registry only when you opt in with `accountPolicy: 'auto' | 'strict'`, `accountStorage`, `accountRegistryScope`, or `accountRegistryMaxEntries`; that internal use does not enable observations of unrelated rosters. Otherwise it keeps the 14.0 behavior: every call sends `sync_accounts` and reflects the seller's current status. Memoized entries require explicit `syncAccounts()` or authoritative status repair when seller linkage expires or is replaced externally. Stored entries contain account references, seller handles, status, optional pending task IDs, and hashes of explicitly chosen setup terms;
|
|
84
|
+
billing entities and tokens are not persisted. Manual feed mode recovers through
|
|
85
|
+
an explicit `refresh()`; auto-poll mode also retries initial failures.
|
|
86
|
+
|
|
87
|
+
Typed `AccountNotFoundError`, `AccountSetupRequiredError`, and
|
|
88
|
+
`AccountPaymentRequiredError` carry `fault: 'buyer_setup'`. Health trackers
|
|
89
|
+
should exclude them from seller-health failure counts. Failed task results still
|
|
90
|
+
expose the protocol code in `result.adcpError` and the typed exception in
|
|
91
|
+
`result.errorInstance`.
|
|
92
|
+
|
|
93
|
+
The optional product cache uses TTLs in milliseconds and keeps at most `maxEntries` entries (default 1,000). It keeps public and
|
|
94
|
+
account-scoped responses apart and stores the feed version and pricing version
|
|
95
|
+
with each snapshot. Missing `cache_scope` prevents caching. Stale entries are
|
|
96
|
+
conditionally revalidated using their own tokens; failures remain visible to
|
|
97
|
+
the caller and never erase the last valid entry. Caller-authored feed or pricing validators
|
|
98
|
+
retain their unchanged-response semantics. Caches are scoped to the client
|
|
99
|
+
instance so different local verification policies cannot share filtered results.
|
|
100
|
+
|
|
101
|
+
`WholesaleFeedSync` similarly keeps its last good product and signal mirrors on
|
|
102
|
+
a failed refresh. Its error event includes `adcpError`; a mirror becomes
|
|
103
|
+
`degraded` until a successful refresh restores `syncing`. Initial failure sets
|
|
104
|
+
`error`. Exhaustive state switches must handle the new `degraded` member.
|
|
105
|
+
|
|
106
|
+
Manual `WholesaleFeedSync.refresh()` and webhook repairs reject failed catalog reads, including failed task results. A failed webhook repair remains eligible for redelivery; acknowledge it only after repair succeeds. Bootstrap `start()` still reports failed task results through its state and error callback/event, and schedules recovery in auto-poll mode.
|
|
@@ -53,7 +53,7 @@ Your domain (e.g., agent.example.com)
|
|
|
53
53
|
-> /.well-known/jwks.json # JSON Web Key Set with public keys
|
|
54
54
|
```
|
|
55
55
|
|
|
56
|
-
`@adcp/sdk` provides `
|
|
56
|
+
`@adcp/sdk` provides `ResolvedAgentJwksResolver` which handles this entire chain automatically, with caching and refresh.
|
|
57
57
|
|
|
58
58
|
## Step 1: Generate a Signing Key
|
|
59
59
|
|
|
@@ -214,6 +214,12 @@ const signingFetch = buildAgentSigningFetch({
|
|
|
214
214
|
});
|
|
215
215
|
```
|
|
216
216
|
|
|
217
|
+
### Diagnosing a seller's rejection of a signed request
|
|
218
|
+
|
|
219
|
+
For SDK client calls over A2A or MCP, a signed HTTP 401 with a `Signature` challenge (or no challenge) produces an `AuthenticationRequiredError` with `requestSigned: true` and `status: 401`. Its `code` remains `AUTHENTICATION_REQUIRED` for compatibility; `signatureErrorCode` carries a recognized seller `request_signature_*` code, and the message includes the protocol's repair hint. Check the public discovery chain, `brand_json_url` → `agents[]` → `jwks_uri`, when the seller cannot resolve your key. Explicit Bearer or Basic gateway challenges retain their existing authentication recovery. For client-credentials agents, a bare 401 still permits one token refresh; a persistent signed rejection keeps its diagnostics. Other signed bare 401s bypass unsigned authentication probes and interactive OAuth recovery, so gateways requiring those flows should send an explicit Bearer challenge.
|
|
220
|
+
|
|
221
|
+
`error.responseBody` contains a bounded, redacted seller diagnostic when capture succeeds. It is non-enumerable and excluded from JSON error reports. Custom header values are conservatively treated as credentials; short values can mask matching diagnostic text. Treat it as untrusted operator diagnostic text; do not feed it to automated prompts or use it as recovery instructions. Failed `TaskResult` values preserve this error under `result.errorInstance`, so the diagnostic is available as `result.errorInstance.responseBody` after narrowing to `AuthenticationRequiredError`. Conformance raw capture uses the same bounded, redacted diagnostic rather than the original response bytes for these failures. Low-level signing fetch presets continue to return the original HTTP `Response`.
|
|
222
|
+
|
|
217
223
|
## Step 3.5: Production Key Storage — KMS / HSM / Vault
|
|
218
224
|
|
|
219
225
|
Holding a private JWK in process memory is fine for development and testing but it's not where you want production signing keys to live. A process compromise leaks the signing key, and the only remedy is rotation across every counterparty that's cached your public key (within their TTL). The AdCP spec recommends storing keys in a managed key store (HSM or KMS); the SDK supports this directly via the `SigningProvider` interface.
|
|
@@ -429,13 +435,13 @@ import {
|
|
|
429
435
|
requireAuthenticatedOrSigned,
|
|
430
436
|
mcpToolNameResolver,
|
|
431
437
|
} from '@adcp/sdk/server';
|
|
432
|
-
import {
|
|
438
|
+
import { ResolvedAgentJwksResolver } from '@adcp/sdk/signing/server';
|
|
433
439
|
|
|
434
440
|
serve(createAgent, {
|
|
435
441
|
authenticate: requireAuthenticatedOrSigned({
|
|
436
442
|
signature: verifySignatureAsAuthenticator({
|
|
437
443
|
capability: { supported: true, required_for: ['create_media_buy'], covers_content_digest: 'either' },
|
|
438
|
-
jwks: new
|
|
444
|
+
jwks: new ResolvedAgentJwksResolver(expectedBuyerAgentUrl, 'mcp'),
|
|
439
445
|
resolveOperation: mcpToolNameResolver,
|
|
440
446
|
}),
|
|
441
447
|
fallback: verifyApiKey({ keys: { 'sk_live_abc': { principal: 'acct_42' } } }),
|
|
@@ -453,7 +459,8 @@ Set `requiredFor` to the AdCP operations you want to gate behind signatures —
|
|
|
453
459
|
|---|---|
|
|
454
460
|
| `StaticJwksResolver` | Fixed set of known buyer keys. Good for dev/testing. |
|
|
455
461
|
| `HttpsJwksResolver` | Fetches JWKS from a URL with caching and refresh. |
|
|
456
|
-
| `
|
|
462
|
+
| `ResolvedAgentJwksResolver` | Capability-bound discovery from an expected agent URL. Production recommended. |
|
|
463
|
+
| `BrandJsonJwksResolver` | Confirms an operator mapping against capabilities; accepts an explicit `agentUrl` or infers a unique onboarding URL from existing configuration. |
|
|
457
464
|
|
|
458
465
|
## Step 5: Verify Inbound Webhooks (Buyer / Orchestrator)
|
|
459
466
|
|
|
@@ -462,16 +469,18 @@ When sellers send webhooks, verify the signature to confirm authenticity:
|
|
|
462
469
|
```typescript
|
|
463
470
|
import {
|
|
464
471
|
verifyWebhookSignature,
|
|
465
|
-
|
|
472
|
+
ResolvedAgentJwksResolver,
|
|
466
473
|
InMemoryReplayStore,
|
|
474
|
+
InMemoryRevocationStore,
|
|
467
475
|
} from '@adcp/sdk/signing/server';
|
|
468
476
|
|
|
469
|
-
const jwks = new
|
|
477
|
+
const jwks = new ResolvedAgentJwksResolver(expectedSellerAgentUrl, 'mcp', { legacyWebhookFallback: true });
|
|
470
478
|
const replayStore = new InMemoryReplayStore();
|
|
479
|
+
const revocationStore = new InMemoryRevocationStore();
|
|
471
480
|
|
|
472
481
|
app.post('/webhook', async (req, res) => {
|
|
473
482
|
try {
|
|
474
|
-
await verifyWebhookSignature(req, { jwks, replayStore });
|
|
483
|
+
await verifyWebhookSignature(req, { jwks, replayStore, revocationStore });
|
|
475
484
|
} catch (err) {
|
|
476
485
|
return res.status(401).json({ error: 'invalid webhook signature' });
|
|
477
486
|
}
|
|
@@ -24,6 +24,94 @@ accounts: {
|
|
|
24
24
|
}
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
+
For buyer setup and opt-in lifecycle management, see
|
|
28
|
+
[First call to a seller](./FIRST-CALL-TO-A-SELLER.md).
|
|
29
|
+
For upgrading an existing integration, use the
|
|
30
|
+
[14.0-to-14.1 checklist](../migration-14.0-to-14.1.md).
|
|
31
|
+
|
|
32
|
+
Account resolvers receive `ctx.provisioning`. It is false on discovery and
|
|
33
|
+
negotiation (`get_products`, `list_products`, `get_signals`, and proposal
|
|
34
|
+
request/refine/decline); these tasks MUST use lookup only. It is true on spend
|
|
35
|
+
commitments, `activate_signal`, and `sync_*` tasks. Lazy provisioning must be
|
|
36
|
+
explicitly gated:
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
resolve: async (ref, ctx) => {
|
|
40
|
+
const existing = await db.findAuthorizedAccount(ref, ctx?.authInfo);
|
|
41
|
+
if (existing || !ctx?.provisioning) return existing;
|
|
42
|
+
return await db.createAuthorizedAccount(ref, ctx?.authInfo);
|
|
43
|
+
},
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
When `resolveAccount` is configured, a supplied unknown reference returns
|
|
47
|
+
`ACCOUNT_NOT_FOUND`, even on optional account tools.
|
|
48
|
+
|
|
49
|
+
### Strict account references (`strictAccountReferences`)
|
|
50
|
+
|
|
51
|
+
SDK 14 keeps four compatibility behaviors that strict mode removes:
|
|
52
|
+
|
|
53
|
+
- A buyer-supplied `account` still reaches a raw handler-bag seller that has
|
|
54
|
+
no reference-aware `resolveAccount`: the handler sees `params.account` and
|
|
55
|
+
`ctx.account` is undefined. An auth-only `resolveAccountFromAuth` does not
|
|
56
|
+
authorize an arbitrary reference.
|
|
57
|
+
- A seller that declares `capabilities.account.requiredForProducts` still
|
|
58
|
+
serves `get_products` when the request carries no account and
|
|
59
|
+
authentication resolves none.
|
|
60
|
+
- `list_accounts.account` is resolved through `resolveAccount` as the
|
|
61
|
+
request's account (an unknown or unauthorized filter returns
|
|
62
|
+
`ACCOUNT_NOT_FOUND`). Strict mode treats it as a filter instead.
|
|
63
|
+
- On `createAdcpServerFromPlatform` with `resolution: 'implicit'`, an account
|
|
64
|
+
whose returned identity metadata disagrees with the supplied natural key is
|
|
65
|
+
still used.
|
|
66
|
+
|
|
67
|
+
Each logs a deprecation warning once per process per warning code (through
|
|
68
|
+
`logger.warn`, plus `process.emitWarning` outside `NODE_ENV=production`);
|
|
69
|
+
later occurrences log at debug level. Codes:
|
|
70
|
+
`ADCP_UNRESOLVED_ACCOUNT_REFERENCE`, `ADCP_REQUIRED_FOR_PRODUCTS_NOT_ENFORCED`,
|
|
71
|
+
`ADCP_LIST_ACCOUNTS_FILTER_RESOLVED`, and
|
|
72
|
+
`ADCP_IMPLICIT_ACCOUNT_IDENTITY_MISMATCH`.
|
|
73
|
+
|
|
74
|
+
**Strict mode becomes the default in the next major release.** Opt in now:
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
createAdcpServer({
|
|
78
|
+
name: 'Seller',
|
|
79
|
+
version: '1.0.0',
|
|
80
|
+
strictAccountReferences: true,
|
|
81
|
+
resolveAccount: (ref, ctx) => authorizedAccounts.find(ref, ctx.authInfo),
|
|
82
|
+
mediaBuy: {
|
|
83
|
+
getProducts: (params, ctx) => catalog.forAccount(ctx.account, params),
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
With `strictAccountReferences: true`:
|
|
89
|
+
|
|
90
|
+
- A supplied reference on a server without `resolveAccount` fails with
|
|
91
|
+
`ACCOUNT_NOT_FOUND` before the handler runs.
|
|
92
|
+
- A `requiredForProducts` seller refuses account-less `get_products` with
|
|
93
|
+
`ACCOUNT_REQUIRED`.
|
|
94
|
+
- `list_accounts.account` is a filter: `resolveAccount` is not called for it
|
|
95
|
+
and `ctx.account` comes from `resolveAccountFromAuth`.
|
|
96
|
+
- An implicit-mode account whose returned identity metadata (`brand`,
|
|
97
|
+
`operator`, `operator_unit`, `currency`, `timezone`, `sandbox`) disagrees
|
|
98
|
+
with the supplied natural key is refused with `ACCOUNT_NOT_FOUND`. Fields
|
|
99
|
+
your store does not return are not compared.
|
|
100
|
+
|
|
101
|
+
Migration for handler-bag sellers: move account authorization out of
|
|
102
|
+
individual handlers and into `resolveAccount`, then set the flag.
|
|
103
|
+
`authorizedAccounts.find` must return null on an unknown reference or a
|
|
104
|
+
reference owned by another principal. Public discovery may omit `account`;
|
|
105
|
+
resource creation and spend commitments need an authorized account. Implicit
|
|
106
|
+
stores should resolve by the complete natural key and return identity
|
|
107
|
+
metadata that echoes it, or omit the metadata.
|
|
108
|
+
|
|
109
|
+
`InMemoryImplicitAccountStore` matches supplied refs on the complete natural
|
|
110
|
+
key, including operator unit, currency, timezone, and sandbox. It retains its
|
|
111
|
+
24-hour TTL and replacement sync semantics. Set `mergeOnUpsert: true` for
|
|
112
|
+
additive batches and revoke individual refs with `remove(ref, ctx)`; passing
|
|
113
|
+
`delete_missing: true` in `sync_accounts` retains replacement semantics.
|
|
114
|
+
|
|
27
115
|
**Each mode has exactly one spelling.** `'derived'` keeps its name even
|
|
28
116
|
though [adcp#5062](https://github.com/adcontextprotocol/adcp/pull/5062)
|
|
29
117
|
calls the shape an *upstream-managed account-id namespace*: `resolution` is
|
|
@@ -47,29 +135,53 @@ construction, not a silent fallback.
|
|
|
47
135
|
|
|
48
136
|
### 1 · How it works
|
|
49
137
|
|
|
50
|
-
1. Buyer calls `sync_accounts` with
|
|
138
|
+
1. Buyer calls `sync_accounts` with natural-key provisioning entries.
|
|
51
139
|
2. Framework calls your `accounts.upsert()` — you create/find accounts and
|
|
52
140
|
store the `authPrincipal → accounts` mapping.
|
|
53
|
-
3.
|
|
54
|
-
|
|
55
|
-
|
|
141
|
+
3. On subsequent account-scoped calls, the buyer supplies top-level
|
|
142
|
+
`account: { brand, operator, ... }`. The framework calls
|
|
143
|
+
`accounts.resolve(ref, ctx)` with that natural key. Look it up within the
|
|
144
|
+
authenticated caller's synced roster; do not substitute another account.
|
|
145
|
+
4. When a request omits `account`, the framework instead calls
|
|
146
|
+
`accounts.resolve(undefined, ctx)`. This is a separate auth-derived lookup
|
|
147
|
+
path. A null result is allowed for account-optional tools and yields
|
|
148
|
+
`ACCOUNT_REQUIRED` for account-required operations.
|
|
149
|
+
|
|
150
|
+
Implicit sellers refuse the `{ account_id }` reference arm. A seller handle
|
|
151
|
+
returned by `sync_accounts` does not replace the natural key on later calls.
|
|
56
152
|
|
|
57
153
|
### 2 · Key derivation
|
|
58
154
|
|
|
59
155
|
Extract the principal key from `ctx.authInfo.credential`:
|
|
60
156
|
|
|
61
157
|
```ts
|
|
62
|
-
resolve: async (
|
|
158
|
+
resolve: async (ref, ctx) => {
|
|
63
159
|
const cred = ctx?.authInfo?.credential;
|
|
64
160
|
const key = cred?.kind === 'oauth' ? `oauth:${cred.client_id}`
|
|
65
161
|
: cred?.kind === 'api_key' ? `api_key:${cred.key_id}`
|
|
66
162
|
: cred?.kind === 'http_sig' ? `http_sig:${cred.agent_url}`
|
|
67
163
|
: undefined;
|
|
68
164
|
if (!key) return null;
|
|
165
|
+
if (ref !== undefined) {
|
|
166
|
+
// Match the full natural key within THIS principal's synced roster.
|
|
167
|
+
// An unknown or unauthorized ref returns null, without a fallback.
|
|
168
|
+
return await db.findSyncedAccountByNaturalKey(key, ref);
|
|
169
|
+
}
|
|
170
|
+
// Account omitted: use your existing auth-derived selection policy.
|
|
69
171
|
return await db.findAccountByPrincipalKey(key);
|
|
70
172
|
},
|
|
71
173
|
```
|
|
72
174
|
|
|
175
|
+
The `db` methods above are operations you implement in your own store.
|
|
176
|
+
`findSyncedAccountByNaturalKey` must compare the complete brand identity
|
|
177
|
+
(domain, optional brand ID and countries), operator, operator-unit ID,
|
|
178
|
+
currency, timezone, and sandbox within the principal's roster. Use consistent
|
|
179
|
+
normalization at sync and lookup, including country ordering and omitted/false
|
|
180
|
+
sandbox. It must not create an account or match on brand/operator alone.
|
|
181
|
+
`findAccountByPrincipalKey` handles only the omitted-reference path according
|
|
182
|
+
to your documented selection policy. The built-in `InMemoryImplicitAccountStore`
|
|
183
|
+
keeps its historical first-account selection for that path.
|
|
184
|
+
|
|
73
185
|
**Why `credential.client_id`, not `authInfo.sub`?**
|
|
74
186
|
|
|
75
187
|
`credential.client_id` is the OAuth *client* identity — stable across token
|
|
@@ -101,14 +213,24 @@ receiving auth errors will refresh credentials or escalate, not call
|
|
|
101
213
|
|
|
102
214
|
```ts
|
|
103
215
|
// ✓ Correct
|
|
104
|
-
resolve: async (
|
|
105
|
-
const
|
|
106
|
-
|
|
216
|
+
resolve: async (ref, ctx) => {
|
|
217
|
+
const key = extractKey(ctx?.authInfo);
|
|
218
|
+
if (!key) return null;
|
|
219
|
+
const account = ref === undefined
|
|
220
|
+
? await db.findAccountByPrincipalKey(key)
|
|
221
|
+
: await db.findSyncedAccountByNaturalKey(key, ref);
|
|
222
|
+
// Missing: supplied account → ACCOUNT_NOT_FOUND;
|
|
223
|
+
// omitted account on an account-required operation → ACCOUNT_REQUIRED.
|
|
224
|
+
return account ?? null;
|
|
107
225
|
},
|
|
108
226
|
|
|
109
227
|
// ✗ Wrong — misleads buyers about how to recover
|
|
110
|
-
resolve: async (
|
|
111
|
-
const
|
|
228
|
+
resolve: async (ref, ctx) => {
|
|
229
|
+
const key = extractKey(ctx?.authInfo);
|
|
230
|
+
if (!key) return null;
|
|
231
|
+
const account = ref === undefined
|
|
232
|
+
? await db.findAccountByPrincipalKey(key)
|
|
233
|
+
: await db.findSyncedAccountByNaturalKey(key, ref);
|
|
112
234
|
if (!account) throw new AdcpError('AUTH_MISSING', { message: 'call sync_accounts first' });
|
|
113
235
|
return account;
|
|
114
236
|
},
|
package/docs/llms.txt
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Ad Context Protocol (AdCP)
|
|
2
2
|
|
|
3
|
-
> Generated at: 2026-10-
|
|
4
|
-
> Library: @adcp/sdk v14.
|
|
3
|
+
> Generated at: 2026-10-05
|
|
4
|
+
> Library: @adcp/sdk v14.2.0
|
|
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.
|
|
@@ -19,6 +19,7 @@ SDK 14 is compact-lifecycle first: `list_products → buy_products → control_m
|
|
|
19
19
|
|
|
20
20
|
- **MediaBuy change rights:** use `assessMediaBuyAction` from `@adcp/sdk/media-buy/actions` for possible / promised / available-now assessment, and `mediaBuyActionResolver` from `@adcp/sdk/server` for explicit seller acceptance and current projection. See `docs/guides/MEDIA-BUY-ACTION-ASSESSMENT.md`.
|
|
21
21
|
- **Buyer** (calling a seller): read `docs/guides/BUYER-QUICKSTART-3.2.md` first.
|
|
22
|
+
- **Account setup and first discovery:** read `docs/guides/FIRST-CALL-TO-A-SELLER.md` for the provisioning registry, account policies, billing terms, and product cache.
|
|
22
23
|
- **Buyer Reliable Reporting**: import reconciliation, PostgreSQL persistence, and the worker from `@adcp/sdk/reporting/consumer`; see `docs/guides/REPORTING-RECONCILIATION.md`.
|
|
23
24
|
- **Before proposal acceptance:** use `verifyProposalCommercialTerms` from `@adcp/sdk/negotiation/verification` with a complete, independently reviewed snapshot and the seller-served schema version. Never use an unreviewed candidate as its own expected terms. See `docs/guides/PROPOSAL-TERMS-VERIFICATION.md`.
|
|
24
25
|
- **Seller** (implementing an agent that others call): read `docs/guides/SELLER-QUICKSTART-3.2.md` first, then `docs/guides/BUILD-AN-AGENT.md` for the complete framework surface.
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Migrating from SDK 14.0 to 14.1
|
|
2
|
+
|
|
3
|
+
SDK **14.1.0** still uses AdCP **3.2.1** on the wire. Its signature verification
|
|
4
|
+
adopts the AdCP 3.3 agent-resolution algorithm; this does not upgrade your wire
|
|
5
|
+
protocol or require enabling a new media-buy lifecycle.
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
npm install @adcp/sdk@14.1.0
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Account policies and strict account references keep their 14.0 defaults. Check
|
|
12
|
+
the applicable rows below before rolling out: some TypeScript types change,
|
|
13
|
+
and signature verification rejects identities or keys it cannot confirm.
|
|
14
|
+
|
|
15
|
+
## Required changes when applicable
|
|
16
|
+
|
|
17
|
+
| If your integration… | Change for 14.1 |
|
|
18
|
+
|---|---|
|
|
19
|
+
| Exhaustively switches over `WholesaleFeedSyncState` | Add a `degraded` case. A failed refresh preserves an existing mirror and marks it degraded; an initial failure still sets `error`. |
|
|
20
|
+
| Reads registry refresh fence fields as required values | Handle `undefined` on the deprecated fields in `AgentComplianceDetail.refresh_availability` and the `refreshAgent` 503 response. For example, use `refresh_availability.code ?? 'unknown'` for a local display label. The live registry no longer returns these fields; removal from SDK types is planned for the next major release. |
|
|
21
|
+
| Uses a standalone `BrandJsonJwksResolver` with A2A | Set `protocol: 'a2a'`. Capability discovery defaults to MCP; the onboarding record does not select the transport. |
|
|
22
|
+
| Supplies a natural-key account reference to an implicit seller | Resolve the complete key within the authenticated caller's synced roster. Include brand identity, operator, operator unit, currency, timezone, and sandbox. An unknown supplied reference must return `null`, never fall back to another account. See [account resolution](./guides/account-resolution.md#implicit-deep-dive). |
|
|
23
|
+
| Stores non-canonical issuer URLs in governance principal, replay, or revocation indexes | Migrate those keys to the canonical issuer identity before switching verification. Preserve replay and revocation history; use the [signature migration guide](./migration-agent-resolution-3.3.md) to check normalization rules. |
|
|
24
|
+
| Configures JWKS or operator discovery cache limits | Review the bounds in the [signature migration guide](./migration-agent-resolution-3.3.md). Brand discovery requires positive `maxAgeSeconds`; non-finite or negative cache options fail configuration validation. Expired mappings and keys are refused rather than reused. |
|
|
25
|
+
| Repairs wholesale mirrors from webhook deliveries | Acknowledge only after `refresh()` or repair succeeds. Failed catalog reads now reject, preserving the mirror and leaving the delivery eligible for retry. |
|
|
26
|
+
|
|
27
|
+
For the complete list of newly optional registry fields, see the
|
|
28
|
+
[14.1.0 changelog](https://github.com/adcontextprotocol/adcp-client/blob/main/CHANGELOG.md#1410).
|
|
29
|
+
|
|
30
|
+
## Security behavior to verify
|
|
31
|
+
|
|
32
|
+
Existing resolver constructor signatures remain supported, but accepting a key
|
|
33
|
+
now requires a confirmed canonical agent identity and the capabilities-selected
|
|
34
|
+
operator record. Ambiguous onboarding and unconfirmed cross-domain mappings
|
|
35
|
+
fail closed. Prefer supplying the expected `agentUrl` already recorded by your
|
|
36
|
+
integration.
|
|
37
|
+
|
|
38
|
+
Publisher-pinned webhook keys must also appear in the agent JWKS as the same
|
|
39
|
+
public key. Resolve pins from your persisted registration and media-buy record
|
|
40
|
+
for every affected publisher, rather than selecting publishers from the webhook
|
|
41
|
+
payload. Refresh callbacks must throw on fetch failure; `null` confirms removal
|
|
42
|
+
of a pin. Follow the [publisher-pin migration guidance](./migration-agent-resolution-3.3.md#publisher-pin-context).
|
|
43
|
+
|
|
44
|
+
`SingleAgentClient` and `BrandJsonJwksResolver` retain legacy 3.x webhook
|
|
45
|
+
fallback by default. A standalone `ResolvedAgentJwksResolver` requires explicit
|
|
46
|
+
opt-in. That fallback does not authorize request signatures.
|
|
47
|
+
|
|
48
|
+
Signed MCP and A2A HTTP 401 errors now retain signature diagnostics and repair
|
|
49
|
+
guidance. Explicit Signature-challenge rejections skip unsigned authentication
|
|
50
|
+
probes and credential refresh retries. Bare signed 401s retain the existing
|
|
51
|
+
single client-credentials refresh attempt.
|
|
52
|
+
|
|
53
|
+
## Optional adoption
|
|
54
|
+
|
|
55
|
+
| Feature | Default and adoption path |
|
|
56
|
+
|---|---|
|
|
57
|
+
| Buyer account registry | `accountPolicy` remains `'off'`. Set `'auto'` or `'strict'` to enforce setup, or configure registry storage/scope/capacity to opt into memoized `resolveAccount()`. Without opt-in, that helper still sends `sync_accounts` on each call. See [first call to a seller](./guides/FIRST-CALL-TO-A-SELLER.md). |
|
|
58
|
+
| Product cache | Opt in with `createProductCache`. Public and account-scoped responses stay separate; missing `cache_scope` prevents caching. See [buyer setup and caching](./guides/FIRST-CALL-TO-A-SELLER.md). |
|
|
59
|
+
| Strict seller account references | `strictAccountReferences` remains false; compatibility paths warn. Move reference authorization into `resolveAccount`, then set it to true. It becomes the default in the next major release. See [strict account references](./guides/account-resolution.md#strict-account-references-strictaccountreferences). |
|
|
60
|
+
| Additive implicit account sync | `InMemoryImplicitAccountStore` keeps replacement sync semantics and its 24-hour TTL. Set `mergeOnUpsert: true` for additive batches; `delete_missing: true` still requests replacement. Use `remove(ref, ctx)` for individual revocation. |
|
|
61
|
+
|
|
62
|
+
Account resolvers now receive `ctx.provisioning`. Discovery and negotiation
|
|
63
|
+
must remain lookup-only; gate any lazy account creation on this flag. The
|
|
64
|
+
[seller account guide](./guides/account-resolution.md) includes an example.
|
|
65
|
+
|
|
66
|
+
## Check your rollout
|
|
67
|
+
|
|
68
|
+
- Compile your application to catch the new state and optional registry fields.
|
|
69
|
+
- Exercise signed requests and webhooks against your actual agent/operator
|
|
70
|
+
records, including key rotation and any publisher pins.
|
|
71
|
+
- Check that supplied unknown or unauthorized account references are refused,
|
|
72
|
+
and that discovery does not create accounts.
|
|
73
|
+
- If you handle `sync_accounts` results, handle per-account notification
|
|
74
|
+
event-type failures. In strict request validation, valid siblings can proceed;
|
|
75
|
+
with `delete_missing: true`, the invalid batch is refused before writes.
|
|
76
|
+
Warn-mode validation remains advisory, as in 14.0.
|
|
77
|
+
- Exercise failed feed refreshes and webhook redelivery without losing the last
|
|
78
|
+
good mirror.
|
|
79
|
+
|
|
80
|
+
The published 14.1.0 artifact passed reporting core **4/4** and full lifecycle
|
|
81
|
+
**4/4** qualification, with integrity and provenance verified. This covers
|
|
82
|
+
Python producers and TypeScript consumers. It does not establish reverse-direction
|
|
83
|
+
parity or Python version-skew coverage; broader work remains in
|
|
84
|
+
[#3027](https://github.com/adcontextprotocol/adcp-client/issues/3027).
|
|
85
|
+
See the [published release and qualification evidence](https://github.com/adcontextprotocol/adcp-client/releases/tag/%40adcp/sdk%4014.1.0).
|
|
@@ -11,8 +11,8 @@ below as the publication/deployment gate.
|
|
|
11
11
|
|
|
12
12
|
| Fact | Value |
|
|
13
13
|
| --- | --- |
|
|
14
|
-
| Exact npm package | `@adcp/sdk@14.
|
|
15
|
-
| npm integrity | registry-derived after publication; run `npm view @adcp/sdk@14.
|
|
14
|
+
| Exact npm package | `@adcp/sdk@14.2.0` |
|
|
15
|
+
| npm integrity | registry-derived after publication; run `npm view @adcp/sdk@14.2.0 dist.integrity` |
|
|
16
16
|
| Node.js runtime | `^20.19.0 || >=22.12.0` |
|
|
17
17
|
| Default AdCP wire release | `3.2.1` |
|
|
18
18
|
| Maintained wire releases | `v2.5`, `v2.6`, `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.2.1`, `3.2` |
|
|
@@ -21,8 +21,8 @@ below as the publication/deployment gate.
|
|
|
21
21
|
Install exact production inputs rather than a moving range or dist-tag:
|
|
22
22
|
|
|
23
23
|
```bash
|
|
24
|
-
npm install --save-exact '@adcp/sdk@14.
|
|
25
|
-
npm view '@adcp/sdk@14.
|
|
24
|
+
npm install --save-exact '@adcp/sdk@14.2.0'
|
|
25
|
+
npm view '@adcp/sdk@14.2.0' dist.integrity
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
### Required and optional peers
|