@adcp/sdk 14.1.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/core/SingleAgentClient.d.mts +4 -1
- package/dist/lib/core/SingleAgentClient.d.ts +4 -1
- package/dist/lib/core/SingleAgentClient.js +25 -4
- package/dist/lib/core/SingleAgentClient.mjs +25 -4
- package/dist/lib/core/TaskExecutor.d.mts +3 -1
- package/dist/lib/core/TaskExecutor.d.ts +3 -1
- package/dist/lib/core/TaskExecutor.js +15 -11
- package/dist/lib/core/TaskExecutor.mjs +15 -11
- package/dist/lib/core/buyer-account-registry.d.mts +30 -2
- package/dist/lib/core/buyer-account-registry.d.ts +30 -2
- package/dist/lib/core/buyer-account-registry.js +126 -42
- package/dist/lib/core/buyer-account-registry.mjs +127 -43
- package/dist/lib/index.d.mts +3 -2
- package/dist/lib/index.d.ts +3 -2
- package/dist/lib/index.js +9 -0
- package/dist/lib/index.mjs +12 -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/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/signing/agent-resolver/errors.d.mts +2 -0
- package/dist/lib/signing/agent-resolver/errors.d.ts +2 -0
- 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 +9 -0
- package/dist/lib/signing/agent-resolver/fetch-helpers.d.ts +9 -0
- package/dist/lib/signing/agent-resolver/fetch-helpers.js +35 -1
- package/dist/lib/signing/agent-resolver/fetch-helpers.mjs +38 -2
- package/dist/lib/signing/agent-resolver/legacy-brand.js +1 -1
- package/dist/lib/signing/agent-resolver/legacy-brand.mjs +2 -2
- package/dist/lib/signing/agent-resolver/resolve-agent.d.mts +1 -1
- package/dist/lib/signing/agent-resolver/resolve-agent.d.ts +1 -1
- package/dist/lib/signing/agent-resolver/resolve-agent.js +47 -5
- package/dist/lib/signing/agent-resolver/resolve-agent.mjs +55 -6
- package/dist/lib/signing/brand-jwks.d.mts +2 -0
- package/dist/lib/signing/brand-jwks.d.ts +2 -0
- package/dist/lib/signing/brand-jwks.js +10 -2
- package/dist/lib/signing/brand-jwks.mjs +10 -2
- package/dist/lib/signing/errors.d.mts +4 -2
- package/dist/lib/signing/errors.d.ts +4 -2
- package/dist/lib/signing/errors.js +3 -1
- package/dist/lib/signing/errors.mjs +3 -1
- package/dist/lib/signing/verifier.js +1 -1
- package/dist/lib/signing/verifier.mjs +1 -1
- package/dist/lib/signing/webhook-verifier.js +2 -2
- package/dist/lib/signing/webhook-verifier.mjs +3 -3
- 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 +12 -29
- package/dist/lib/wholesale-feed-sync/sync.d.ts +12 -29
- package/dist/lib/wholesale-feed-sync/sync.js +153 -297
- package/dist/lib/wholesale-feed-sync/sync.mjs +158 -297
- package/docs/README.md +6 -0
- package/docs/TYPE-SUMMARY.md +2 -2
- package/docs/guides/BUYER-STORAGE.md +3 -0
- package/docs/guides/FIRST-CALL-TO-A-SELLER.md +3 -1
- package/docs/guides/account-resolution.md +46 -10
- package/docs/llms.txt +2 -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-agent-resolution-3.3.md +5 -3
- package/docs/recipes/verifying-inbound-webhooks.md +4 -0
- package/package.json +2 -1
- 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
package/dist/lib/index.d.mts
CHANGED
|
@@ -237,7 +237,8 @@ export { resolvePreviewAuthority, type PlacementPreviewCandidate, type PreviewAu
|
|
|
237
237
|
export { isStatusCompleted, isStatusWorking, isStatusInputRequired, isStatusSubmitted, isStatusFailed, isStatusRejected, isGetProductsCompleted, isGetProductsWorking, isGetProductsInputRequired, isGetProductsSubmitted, isGetProductsFailed, isCreateMediaBuyCompleted, isCreateMediaBuyWorking, isCreateMediaBuyInputRequired, isCreateMediaBuySubmitted, isCreateMediaBuyFailed, isUpdateMediaBuyCompleted, isUpdateMediaBuyWorking, isUpdateMediaBuyInputRequired, isUpdateMediaBuySubmitted, isUpdateMediaBuyFailed, isSyncCreativesCompleted, isSyncCreativesWorking, isSyncCreativesInputRequired, isSyncCreativesSubmitted, isSyncCreativesFailed, } from './utils/typeGuards.mjs';
|
|
238
238
|
export { getAdcpVersion, getLibraryVersion, isCompatibleWith, getCompatibleVersions, parseAdcpMajorVersion, ADCP_VERSION, ADCP_MAJOR_VERSION, LIBRARY_VERSION, COMPATIBLE_ADCP_VERSIONS, VERSION_INFO, } from './version.mjs';
|
|
239
239
|
export type { AdcpVersion } from './version.mjs';
|
|
240
|
-
export { listBundledAdcpVersions, resolveAdcpVersion } from './utils/adcp-version-config.mjs';
|
|
240
|
+
export { listBundledAdcpVersions, resolveAdcpVersion, isAdcpVersionAtLeast, sellerAdvertises31, shouldOmit31Fields, } from './utils/adcp-version-config.mjs';
|
|
241
|
+
export { redactSecrets } from './utils/redact-secrets.mjs';
|
|
241
242
|
export { getTracer, isTracingEnabled, injectTraceHeaders, withSpan, addSpanAttributes, recordSpanException, } from './observability/index.mjs';
|
|
242
243
|
export { Agent as LegacyAgent, AgentCollection as LegacyAgentCollection } from './agents/index.generated.mjs';
|
|
243
244
|
export { LegacyContentStandardsAdapter, type LegacyIContentStandardsAdapter, type LegacyContentEvaluationResult, LegacyContentStandardsErrorCodes, isLegacyContentStandardsError, legacyDefaultContentStandardsAdapter, PropertyListAdapter, type IPropertyListAdapter, type ResolvedProperty, PropertyListErrorCodes, isPropertyListError, defaultPropertyListAdapter, SISessionManager, AISISessionManager, type ISISessionManager, type SISession, SIErrorCodes, defaultSISessionManager, GovernanceAdapter, defaultGovernanceAdapter, type IGovernanceAdapter, type GovernanceAdapterConfig, type GovernanceAdapterErrorCode, type CommittedCheckRequest, type LegacyCommittedCheckRequest, type ModernCommittedCheckRequest, GovernanceAdapterError, GovernanceAdapterErrorCodes, isGovernanceAdapterError, InMemoryImplicitAccountStore, defaultImplicitKeyFn, type ImplicitAccountStoreOptions, createOAuthPassthroughResolver, type OAuthPassthroughResolverOptions, createRosterAccountStore, type RosterAccountStoreOptions, createDerivedAccountStore, type DerivedAccountStoreOptions, type DerivedAccountStoreBaseOptions, type DerivedSingletonAccountStoreOptions, type DerivedRosterAccountStoreOptions, } from './adapters/index.mjs';
|
|
@@ -272,5 +273,5 @@ export { mediaBuyActionResolver } from './server/media-buy-action-resolver.mjs';
|
|
|
272
273
|
export type { SellerActionDecision, SellerActionResolutionOptions, SellerActionResolution, } from './server/media-buy-action-resolver.mjs';
|
|
273
274
|
export * from './supply-path/index.mjs';
|
|
274
275
|
export type { AuthorizationCollectionSelector, ProductCollectionSelector, CollectionDistribution, DiscoveryCollection, } from './discovery/types.mjs';
|
|
275
|
-
export { BuyerAccountRegistry, type AccountPolicy, type BuyerAccountStorage, type BuyerAccountRegistryOptions, type EnsureAccountOptions, type ProvisionedAccount, } from './core/buyer-account-registry.mjs';
|
|
276
|
+
export { BuyerAccountRegistry, type AccountPolicy, type BuyerAccountStorage, type BuyerAccountRegistryOptions, type BuyerAccountDispatch, type BuyerAccountProvisioningDispatch, type EnsureAccountOptions, type ProvisionedAccount, } from './core/buyer-account-registry.mjs';
|
|
276
277
|
export { createProductCache, ProductCache, type ProductCacheOptions } from './core/product-cache.mjs';
|
package/dist/lib/index.d.ts
CHANGED
|
@@ -237,7 +237,8 @@ export { resolvePreviewAuthority, type PlacementPreviewCandidate, type PreviewAu
|
|
|
237
237
|
export { isStatusCompleted, isStatusWorking, isStatusInputRequired, isStatusSubmitted, isStatusFailed, isStatusRejected, isGetProductsCompleted, isGetProductsWorking, isGetProductsInputRequired, isGetProductsSubmitted, isGetProductsFailed, isCreateMediaBuyCompleted, isCreateMediaBuyWorking, isCreateMediaBuyInputRequired, isCreateMediaBuySubmitted, isCreateMediaBuyFailed, isUpdateMediaBuyCompleted, isUpdateMediaBuyWorking, isUpdateMediaBuyInputRequired, isUpdateMediaBuySubmitted, isUpdateMediaBuyFailed, isSyncCreativesCompleted, isSyncCreativesWorking, isSyncCreativesInputRequired, isSyncCreativesSubmitted, isSyncCreativesFailed, } from './utils/typeGuards';
|
|
238
238
|
export { getAdcpVersion, getLibraryVersion, isCompatibleWith, getCompatibleVersions, parseAdcpMajorVersion, ADCP_VERSION, ADCP_MAJOR_VERSION, LIBRARY_VERSION, COMPATIBLE_ADCP_VERSIONS, VERSION_INFO, } from './version';
|
|
239
239
|
export type { AdcpVersion } from './version';
|
|
240
|
-
export { listBundledAdcpVersions, resolveAdcpVersion } from './utils/adcp-version-config';
|
|
240
|
+
export { listBundledAdcpVersions, resolveAdcpVersion, isAdcpVersionAtLeast, sellerAdvertises31, shouldOmit31Fields, } from './utils/adcp-version-config';
|
|
241
|
+
export { redactSecrets } from './utils/redact-secrets';
|
|
241
242
|
export { getTracer, isTracingEnabled, injectTraceHeaders, withSpan, addSpanAttributes, recordSpanException, } from './observability';
|
|
242
243
|
export { Agent as LegacyAgent, AgentCollection as LegacyAgentCollection } from './agents/index.generated';
|
|
243
244
|
export { LegacyContentStandardsAdapter, type LegacyIContentStandardsAdapter, type LegacyContentEvaluationResult, LegacyContentStandardsErrorCodes, isLegacyContentStandardsError, legacyDefaultContentStandardsAdapter, PropertyListAdapter, type IPropertyListAdapter, type ResolvedProperty, PropertyListErrorCodes, isPropertyListError, defaultPropertyListAdapter, SISessionManager, AISISessionManager, type ISISessionManager, type SISession, SIErrorCodes, defaultSISessionManager, GovernanceAdapter, defaultGovernanceAdapter, type IGovernanceAdapter, type GovernanceAdapterConfig, type GovernanceAdapterErrorCode, type CommittedCheckRequest, type LegacyCommittedCheckRequest, type ModernCommittedCheckRequest, GovernanceAdapterError, GovernanceAdapterErrorCodes, isGovernanceAdapterError, InMemoryImplicitAccountStore, defaultImplicitKeyFn, type ImplicitAccountStoreOptions, createOAuthPassthroughResolver, type OAuthPassthroughResolverOptions, createRosterAccountStore, type RosterAccountStoreOptions, createDerivedAccountStore, type DerivedAccountStoreOptions, type DerivedAccountStoreBaseOptions, type DerivedSingletonAccountStoreOptions, type DerivedRosterAccountStoreOptions, } from './adapters';
|
|
@@ -272,5 +273,5 @@ export { mediaBuyActionResolver } from './server/media-buy-action-resolver';
|
|
|
272
273
|
export type { SellerActionDecision, SellerActionResolutionOptions, SellerActionResolution, } from './server/media-buy-action-resolver';
|
|
273
274
|
export * from './supply-path';
|
|
274
275
|
export type { AuthorizationCollectionSelector, ProductCollectionSelector, CollectionDistribution, DiscoveryCollection, } from './discovery/types';
|
|
275
|
-
export { BuyerAccountRegistry, type AccountPolicy, type BuyerAccountStorage, type BuyerAccountRegistryOptions, type EnsureAccountOptions, type ProvisionedAccount, } from './core/buyer-account-registry';
|
|
276
|
+
export { BuyerAccountRegistry, type AccountPolicy, type BuyerAccountStorage, type BuyerAccountRegistryOptions, type BuyerAccountDispatch, type BuyerAccountProvisioningDispatch, type EnsureAccountOptions, type ProvisionedAccount, } from './core/buyer-account-registry';
|
|
276
277
|
export { createProductCache, ProductCache, type ProductCacheOptions } from './core/product-cache';
|
package/dist/lib/index.js
CHANGED
|
@@ -453,6 +453,7 @@ __export(index_exports, {
|
|
|
453
453
|
isADCPError: () => import_errors.isADCPError,
|
|
454
454
|
isAdcpError: () => import_utils.isAdcpError,
|
|
455
455
|
isAdcpSuccess: () => import_utils.isAdcpSuccess,
|
|
456
|
+
isAdcpVersionAtLeast: () => import_adcp_version_config.isAdcpVersionAtLeast,
|
|
456
457
|
isAgentCardPath: () => import_utils6.isAgentCardPath,
|
|
457
458
|
isAlwaysBlocked: () => import_net.isAlwaysBlocked,
|
|
458
459
|
isCPAPricing: () => import_utils7.isCPAPricing,
|
|
@@ -600,6 +601,7 @@ __export(index_exports, {
|
|
|
600
601
|
recordSpanException: () => import_observability.recordSpanException,
|
|
601
602
|
recoveryForModeMismatch: () => import_media_buy.recoveryForModeMismatch,
|
|
602
603
|
redactIdempotencyKey: () => import_idempotency.redactIdempotencyKey,
|
|
604
|
+
redactSecrets: () => import_redact_secrets.redactSecrets,
|
|
603
605
|
redisBackend: () => import_server.redisBackend,
|
|
604
606
|
redisWebhookRegistrationStore: () => import_redis_webhook_registration_store.redisWebhookRegistrationStore,
|
|
605
607
|
registerAdcpTaskTool: () => import_server.registerAdcpTaskTool,
|
|
@@ -638,7 +640,9 @@ __export(index_exports, {
|
|
|
638
640
|
scopedStore: () => import_server.scopedStore,
|
|
639
641
|
segmentIdActivationKey: () => import_activation_key_builders.segmentIdActivationKey,
|
|
640
642
|
selectLogoForSlot: () => import_brand.selectLogoForSlot,
|
|
643
|
+
sellerAdvertises31: () => import_adcp_version_config.sellerAdvertises31,
|
|
641
644
|
serve: () => import_server.serve,
|
|
645
|
+
shouldOmit31Fields: () => import_adcp_version_config.shouldOmit31Fields,
|
|
642
646
|
signalId: () => import_signal_id_builders.signalId,
|
|
643
647
|
singleBuildCreativeReturn: () => import_build_creative_return_builders.singleBuildCreativeReturn,
|
|
644
648
|
singleEnvelopedBuildCreativeReturn: () => import_build_creative_return_builders.singleEnvelopedBuildCreativeReturn,
|
|
@@ -825,6 +829,7 @@ var import_preview_authority = require('./utils/preview-authority.js');
|
|
|
825
829
|
var import_typeGuards = require('./utils/typeGuards.js');
|
|
826
830
|
var import_version = require('./version.js');
|
|
827
831
|
var import_adcp_version_config = require('./utils/adcp-version-config.js');
|
|
832
|
+
var import_redact_secrets = require('./utils/redact-secrets.js');
|
|
828
833
|
var import_observability = require('./observability/index.js');
|
|
829
834
|
var import_agents = require('./agents/index.generated.js');
|
|
830
835
|
var import_adapters = require('./adapters/index.js');
|
|
@@ -1288,6 +1293,7 @@ function createAdCPClientFromEnv() {
|
|
|
1288
1293
|
isADCPError,
|
|
1289
1294
|
isAdcpError,
|
|
1290
1295
|
isAdcpSuccess,
|
|
1296
|
+
isAdcpVersionAtLeast,
|
|
1291
1297
|
isAgentCardPath,
|
|
1292
1298
|
isAlwaysBlocked,
|
|
1293
1299
|
isCPAPricing,
|
|
@@ -1435,6 +1441,7 @@ function createAdCPClientFromEnv() {
|
|
|
1435
1441
|
recordSpanException,
|
|
1436
1442
|
recoveryForModeMismatch,
|
|
1437
1443
|
redactIdempotencyKey,
|
|
1444
|
+
redactSecrets,
|
|
1438
1445
|
redisBackend,
|
|
1439
1446
|
redisWebhookRegistrationStore,
|
|
1440
1447
|
registerAdcpTaskTool,
|
|
@@ -1473,7 +1480,9 @@ function createAdCPClientFromEnv() {
|
|
|
1473
1480
|
scopedStore,
|
|
1474
1481
|
segmentIdActivationKey,
|
|
1475
1482
|
selectLogoForSlot,
|
|
1483
|
+
sellerAdvertises31,
|
|
1476
1484
|
serve,
|
|
1485
|
+
shouldOmit31Fields,
|
|
1477
1486
|
signalId,
|
|
1478
1487
|
singleBuildCreativeReturn,
|
|
1479
1488
|
singleEnvelopedBuildCreativeReturn,
|
package/dist/lib/index.mjs
CHANGED
|
@@ -708,7 +708,14 @@ import {
|
|
|
708
708
|
COMPATIBLE_ADCP_VERSIONS,
|
|
709
709
|
VERSION_INFO
|
|
710
710
|
} from "./version.mjs";
|
|
711
|
-
import {
|
|
711
|
+
import {
|
|
712
|
+
listBundledAdcpVersions,
|
|
713
|
+
resolveAdcpVersion,
|
|
714
|
+
isAdcpVersionAtLeast,
|
|
715
|
+
sellerAdvertises31,
|
|
716
|
+
shouldOmit31Fields
|
|
717
|
+
} from "./utils/adcp-version-config.mjs";
|
|
718
|
+
import { redactSecrets } from "./utils/redact-secrets.mjs";
|
|
712
719
|
import {
|
|
713
720
|
getTracer,
|
|
714
721
|
isTracingEnabled,
|
|
@@ -1245,6 +1252,7 @@ export {
|
|
|
1245
1252
|
isADCPError,
|
|
1246
1253
|
isAdcpError,
|
|
1247
1254
|
isAdcpSuccess,
|
|
1255
|
+
isAdcpVersionAtLeast,
|
|
1248
1256
|
isAgentCardPath,
|
|
1249
1257
|
isAlwaysBlocked,
|
|
1250
1258
|
isCPAPricing,
|
|
@@ -1392,6 +1400,7 @@ export {
|
|
|
1392
1400
|
recordSpanException,
|
|
1393
1401
|
recoveryForModeMismatch,
|
|
1394
1402
|
redactIdempotencyKey,
|
|
1403
|
+
redactSecrets,
|
|
1395
1404
|
redisBackend,
|
|
1396
1405
|
redisWebhookRegistrationStore,
|
|
1397
1406
|
registerAdcpTaskTool,
|
|
@@ -1430,7 +1439,9 @@ export {
|
|
|
1430
1439
|
scopedStore,
|
|
1431
1440
|
segmentIdActivationKey,
|
|
1432
1441
|
selectLogoForSlot,
|
|
1442
|
+
sellerAdvertises31,
|
|
1433
1443
|
serve,
|
|
1444
|
+
shouldOmit31Fields,
|
|
1434
1445
|
signalId,
|
|
1435
1446
|
singleBuildCreativeReturn,
|
|
1436
1447
|
singleEnvelopedBuildCreativeReturn,
|
|
@@ -18,6 +18,7 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
18
18
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
19
|
var agent_transport_fetch_exports = {};
|
|
20
20
|
__export(agent_transport_fetch_exports, {
|
|
21
|
+
AgentTransportPolicyError: () => AgentTransportPolicyError,
|
|
21
22
|
createAgentTransportFetch: () => createAgentTransportFetch
|
|
22
23
|
});
|
|
23
24
|
module.exports = __toCommonJS(agent_transport_fetch_exports);
|
|
@@ -25,14 +26,21 @@ var import_promises = require("node:dns/promises");
|
|
|
25
26
|
var import_node_net = require("node:net");
|
|
26
27
|
var import_undici = require("undici");
|
|
27
28
|
var import_address_guards = require('./address-guards.js');
|
|
29
|
+
class AgentTransportPolicyError extends TypeError {
|
|
30
|
+
code = "agent_transport_policy_refused";
|
|
31
|
+
constructor(message) {
|
|
32
|
+
super(message);
|
|
33
|
+
this.name = "AgentTransportPolicyError";
|
|
34
|
+
}
|
|
35
|
+
}
|
|
28
36
|
const REDIRECT_STATUSES = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]);
|
|
29
37
|
const SENSITIVE_REDIRECT_HEADERS = ["authorization", "cookie", "proxy-authorization", "x-adcp-auth"];
|
|
30
38
|
function createAgentTransportFetch(agentUrl, options = {}) {
|
|
31
39
|
const lookup = options.lookup ?? ((hostname) => (0, import_promises.lookup)(hostname, { all: true }));
|
|
32
40
|
const maxRedirects = options.maxRedirects ?? 5;
|
|
33
41
|
const initialUrl = new URL(agentUrl);
|
|
34
|
-
const allowPrivateEverywhere = options.allowPrivateIp === true || process.env.ADCP_ALLOW_INTERNAL_PROBES === "1" || process.env.ADCP_ALLOW_PRIVATE_AGENT_URL === "1";
|
|
35
|
-
const allowPrivateInitialOrigin = (0, import_address_guards.isLikelyPrivateUrl)(initialUrl.toString());
|
|
42
|
+
const allowPrivateEverywhere = options.allowPrivateIp === true || options.allowPrivateInitialOrigin !== false && (process.env.ADCP_ALLOW_INTERNAL_PROBES === "1" || process.env.ADCP_ALLOW_PRIVATE_AGENT_URL === "1");
|
|
43
|
+
const allowPrivateInitialOrigin = options.allowPrivateInitialOrigin !== false && (0, import_address_guards.isLikelyPrivateUrl)(initialUrl.toString());
|
|
36
44
|
const dispatchers = /* @__PURE__ */ new Map();
|
|
37
45
|
const privateIpAllowedFor = (url) => allowPrivateEverywhere || allowPrivateInitialOrigin && url.origin === initialUrl.origin;
|
|
38
46
|
const dispatcherFor = (url) => {
|
|
@@ -57,6 +65,8 @@ function createAgentTransportFetch(agentUrl, options = {}) {
|
|
|
57
65
|
const redirectMode = init?.redirect ?? request?.redirect ?? "follow";
|
|
58
66
|
for (let redirects = 0; ; redirects++) {
|
|
59
67
|
assertTransportScheme(url);
|
|
68
|
+
if (options.requireHttps && url.protocol !== "https:" && !options.allowPrivateIp)
|
|
69
|
+
throw new AgentTransportPolicyError("Signing discovery requires HTTPS.");
|
|
60
70
|
const hostname = url.hostname.replace(/^\[|\]$/g, "");
|
|
61
71
|
if ((0, import_node_net.isIP)(hostname) !== 0) assertAgentAddressAllowed(hostname, hostname, privateIpAllowedFor(url), false);
|
|
62
72
|
const headerRecord = {};
|
|
@@ -124,19 +134,22 @@ async function resolveAndCreateDispatcher(url, lookup, allowPrivateIp) {
|
|
|
124
134
|
function assertAgentAddressAllowed(address, hostname, allowPrivateIp, resolved) {
|
|
125
135
|
const relationship = resolved ? "resolves to" : "is";
|
|
126
136
|
if ((0, import_address_guards.isAlwaysBlocked)(address)) {
|
|
127
|
-
throw new
|
|
137
|
+
throw new AgentTransportPolicyError(`Agent host ${hostname} ${relationship} an always-blocked address`);
|
|
128
138
|
}
|
|
129
139
|
if (!allowPrivateIp && (0, import_address_guards.isPrivateIp)(address)) {
|
|
130
140
|
const guidance = resolved ? "set transport.allowPrivateIp=true for an explicitly trusted private agent, or provide a trustedFetchFn that enforces its own hostname address policy" : "set transport.allowPrivateIp=true for an explicitly trusted private agent";
|
|
131
|
-
throw new
|
|
141
|
+
throw new AgentTransportPolicyError(
|
|
142
|
+
`Agent host ${hostname} ${relationship} a private or loopback address; ` + guidance
|
|
143
|
+
);
|
|
132
144
|
}
|
|
133
145
|
}
|
|
134
146
|
function assertTransportScheme(url) {
|
|
135
147
|
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
136
|
-
throw new
|
|
148
|
+
throw new AgentTransportPolicyError(`Agent transport does not allow ${url.protocol} URLs`);
|
|
137
149
|
}
|
|
138
150
|
}
|
|
139
151
|
// Annotate the CommonJS export names for ESM import in node:
|
|
140
152
|
0 && (module.exports = {
|
|
153
|
+
AgentTransportPolicyError,
|
|
141
154
|
createAgentTransportFetch
|
|
142
155
|
});
|
|
@@ -2,14 +2,21 @@ import { lookup as dnsLookup } from "node:dns/promises";
|
|
|
2
2
|
import { isIP } from "node:net";
|
|
3
3
|
import { Agent, fetch as undiciFetch } from "undici";
|
|
4
4
|
import { isAlwaysBlocked, isLikelyPrivateUrl, isPrivateIp } from "./address-guards.mjs";
|
|
5
|
+
class AgentTransportPolicyError extends TypeError {
|
|
6
|
+
code = "agent_transport_policy_refused";
|
|
7
|
+
constructor(message) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = "AgentTransportPolicyError";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
5
12
|
const REDIRECT_STATUSES = /* @__PURE__ */ new Set([301, 302, 303, 307, 308]);
|
|
6
13
|
const SENSITIVE_REDIRECT_HEADERS = ["authorization", "cookie", "proxy-authorization", "x-adcp-auth"];
|
|
7
14
|
function createAgentTransportFetch(agentUrl, options = {}) {
|
|
8
15
|
const lookup = options.lookup ?? ((hostname) => dnsLookup(hostname, { all: true }));
|
|
9
16
|
const maxRedirects = options.maxRedirects ?? 5;
|
|
10
17
|
const initialUrl = new URL(agentUrl);
|
|
11
|
-
const allowPrivateEverywhere = options.allowPrivateIp === true || process.env.ADCP_ALLOW_INTERNAL_PROBES === "1" || process.env.ADCP_ALLOW_PRIVATE_AGENT_URL === "1";
|
|
12
|
-
const allowPrivateInitialOrigin = isLikelyPrivateUrl(initialUrl.toString());
|
|
18
|
+
const allowPrivateEverywhere = options.allowPrivateIp === true || options.allowPrivateInitialOrigin !== false && (process.env.ADCP_ALLOW_INTERNAL_PROBES === "1" || process.env.ADCP_ALLOW_PRIVATE_AGENT_URL === "1");
|
|
19
|
+
const allowPrivateInitialOrigin = options.allowPrivateInitialOrigin !== false && isLikelyPrivateUrl(initialUrl.toString());
|
|
13
20
|
const dispatchers = /* @__PURE__ */ new Map();
|
|
14
21
|
const privateIpAllowedFor = (url) => allowPrivateEverywhere || allowPrivateInitialOrigin && url.origin === initialUrl.origin;
|
|
15
22
|
const dispatcherFor = (url) => {
|
|
@@ -34,6 +41,8 @@ function createAgentTransportFetch(agentUrl, options = {}) {
|
|
|
34
41
|
const redirectMode = init?.redirect ?? request?.redirect ?? "follow";
|
|
35
42
|
for (let redirects = 0; ; redirects++) {
|
|
36
43
|
assertTransportScheme(url);
|
|
44
|
+
if (options.requireHttps && url.protocol !== "https:" && !options.allowPrivateIp)
|
|
45
|
+
throw new AgentTransportPolicyError("Signing discovery requires HTTPS.");
|
|
37
46
|
const hostname = url.hostname.replace(/^\[|\]$/g, "");
|
|
38
47
|
if (isIP(hostname) !== 0) assertAgentAddressAllowed(hostname, hostname, privateIpAllowedFor(url), false);
|
|
39
48
|
const headerRecord = {};
|
|
@@ -101,18 +110,21 @@ async function resolveAndCreateDispatcher(url, lookup, allowPrivateIp) {
|
|
|
101
110
|
function assertAgentAddressAllowed(address, hostname, allowPrivateIp, resolved) {
|
|
102
111
|
const relationship = resolved ? "resolves to" : "is";
|
|
103
112
|
if (isAlwaysBlocked(address)) {
|
|
104
|
-
throw new
|
|
113
|
+
throw new AgentTransportPolicyError(`Agent host ${hostname} ${relationship} an always-blocked address`);
|
|
105
114
|
}
|
|
106
115
|
if (!allowPrivateIp && isPrivateIp(address)) {
|
|
107
116
|
const guidance = resolved ? "set transport.allowPrivateIp=true for an explicitly trusted private agent, or provide a trustedFetchFn that enforces its own hostname address policy" : "set transport.allowPrivateIp=true for an explicitly trusted private agent";
|
|
108
|
-
throw new
|
|
117
|
+
throw new AgentTransportPolicyError(
|
|
118
|
+
`Agent host ${hostname} ${relationship} a private or loopback address; ` + guidance
|
|
119
|
+
);
|
|
109
120
|
}
|
|
110
121
|
}
|
|
111
122
|
function assertTransportScheme(url) {
|
|
112
123
|
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
113
|
-
throw new
|
|
124
|
+
throw new AgentTransportPolicyError(`Agent transport does not allow ${url.protocol} URLs`);
|
|
114
125
|
}
|
|
115
126
|
}
|
|
116
127
|
export {
|
|
128
|
+
AgentTransportPolicyError,
|
|
117
129
|
createAgentTransportFetch
|
|
118
130
|
};
|
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
"source_sha": "4e553ad955f83b49c7d221ab5c3ff78237ad02e3",
|
|
5
5
|
"source_tarball_sha256": "580656d6466ef9f0d1119985e6726c2efea718dc671e2ad30957fcb2fd54af0f",
|
|
6
6
|
"upstream_adcp_version": "2.5.3",
|
|
7
|
-
"synced_at": "2026-10-
|
|
7
|
+
"synced_at": "2026-10-05T13:04:22.439Z"
|
|
8
8
|
}
|
|
@@ -46,6 +46,8 @@ export interface AgentResolverErrorDetail {
|
|
|
46
46
|
export declare class AgentResolverError extends Error {
|
|
47
47
|
readonly code: AgentResolverErrorCode;
|
|
48
48
|
readonly detail: AgentResolverErrorDetail;
|
|
49
|
+
/** Local, cause-aware recovery. Wire codes retain the protocol taxonomy. */
|
|
50
|
+
readonly recovery: 'transient' | 'correctable' | 'terminal';
|
|
49
51
|
readonly [ATTACKER_INFLUENCED]: ReadonlyArray<keyof AgentResolverErrorDetail>;
|
|
50
52
|
constructor(code: AgentResolverErrorCode, message: string, detail?: AgentResolverErrorDetail, attackerInfluencedFields?: ReadonlyArray<keyof AgentResolverErrorDetail>);
|
|
51
53
|
}
|
|
@@ -46,6 +46,8 @@ export interface AgentResolverErrorDetail {
|
|
|
46
46
|
export declare class AgentResolverError extends Error {
|
|
47
47
|
readonly code: AgentResolverErrorCode;
|
|
48
48
|
readonly detail: AgentResolverErrorDetail;
|
|
49
|
+
/** Local, cause-aware recovery. Wire codes retain the protocol taxonomy. */
|
|
50
|
+
readonly recovery: 'transient' | 'correctable' | 'terminal';
|
|
49
51
|
readonly [ATTACKER_INFLUENCED]: ReadonlyArray<keyof AgentResolverErrorDetail>;
|
|
50
52
|
constructor(code: AgentResolverErrorCode, message: string, detail?: AgentResolverErrorDetail, attackerInfluencedFields?: ReadonlyArray<keyof AgentResolverErrorDetail>);
|
|
51
53
|
}
|
|
@@ -23,16 +23,22 @@ __export(errors_exports, {
|
|
|
23
23
|
attackerInfluencedFields: () => attackerInfluencedFields
|
|
24
24
|
});
|
|
25
25
|
module.exports = __toCommonJS(errors_exports);
|
|
26
|
+
var import_fetch_helpers = require('./fetch-helpers.js');
|
|
27
|
+
var import_enums = require('../../types/enums.generated.js');
|
|
26
28
|
const ATTACKER_INFLUENCED = /* @__PURE__ */ Symbol.for("adcp.attacker-influenced");
|
|
27
29
|
class AgentResolverError extends Error {
|
|
28
30
|
code;
|
|
29
31
|
detail;
|
|
32
|
+
/** Local, cause-aware recovery. Wire codes retain the protocol taxonomy. */
|
|
33
|
+
recovery;
|
|
30
34
|
[ATTACKER_INFLUENCED];
|
|
31
35
|
constructor(code, message, detail = {}, attackerInfluencedFields2 = []) {
|
|
32
36
|
super(message);
|
|
33
37
|
this.name = "AgentResolverError";
|
|
34
38
|
this.code = code;
|
|
35
39
|
this.detail = detail;
|
|
40
|
+
const discovery = code === "request_signature_capabilities_unreachable" || code === "request_signature_brand_json_unreachable";
|
|
41
|
+
this.recovery = discovery && (0, import_fetch_helpers.isPermanentDiscoveryFailure)(detail) ? "terminal" : import_enums.RequestSigningErrorCodeMetadata[code].recovery;
|
|
36
42
|
this[ATTACKER_INFLUENCED] = attackerInfluencedFields2;
|
|
37
43
|
}
|
|
38
44
|
}
|
|
@@ -1,13 +1,19 @@
|
|
|
1
|
+
import { isPermanentDiscoveryFailure } from "./fetch-helpers.mjs";
|
|
2
|
+
import { RequestSigningErrorCodeMetadata } from "../../types/enums.generated.mjs";
|
|
1
3
|
const ATTACKER_INFLUENCED = /* @__PURE__ */ Symbol.for("adcp.attacker-influenced");
|
|
2
4
|
class AgentResolverError extends Error {
|
|
3
5
|
code;
|
|
4
6
|
detail;
|
|
7
|
+
/** Local, cause-aware recovery. Wire codes retain the protocol taxonomy. */
|
|
8
|
+
recovery;
|
|
5
9
|
[ATTACKER_INFLUENCED];
|
|
6
10
|
constructor(code, message, detail = {}, attackerInfluencedFields2 = []) {
|
|
7
11
|
super(message);
|
|
8
12
|
this.name = "AgentResolverError";
|
|
9
13
|
this.code = code;
|
|
10
14
|
this.detail = detail;
|
|
15
|
+
const discovery = code === "request_signature_capabilities_unreachable" || code === "request_signature_brand_json_unreachable";
|
|
16
|
+
this.recovery = discovery && isPermanentDiscoveryFailure(detail) ? "terminal" : RequestSigningErrorCodeMetadata[code].recovery;
|
|
11
17
|
this[ATTACKER_INFLUENCED] = attackerInfluencedFields2;
|
|
12
18
|
}
|
|
13
19
|
}
|
|
@@ -40,3 +40,12 @@ export declare function safeFetchJson(url: string, kind: FetchKind, options: {
|
|
|
40
40
|
maxBodyBytes: number;
|
|
41
41
|
lookup?: SsrfDnsLookup;
|
|
42
42
|
}): Promise<SafeFetchJsonResult>;
|
|
43
|
+
/** Coarse causes only: never expose messages, resolved addresses, or topology. */
|
|
44
|
+
export declare function classifyDiscoveryFailure(error: unknown): {
|
|
45
|
+
dns_error: SafeFetchError['transport'];
|
|
46
|
+
http_status?: number;
|
|
47
|
+
};
|
|
48
|
+
export declare function isPermanentDiscoveryFailure(detail: {
|
|
49
|
+
dns_error?: string;
|
|
50
|
+
http_status?: number;
|
|
51
|
+
}): boolean;
|
|
@@ -40,3 +40,12 @@ export declare function safeFetchJson(url: string, kind: FetchKind, options: {
|
|
|
40
40
|
maxBodyBytes: number;
|
|
41
41
|
lookup?: SsrfDnsLookup;
|
|
42
42
|
}): Promise<SafeFetchJsonResult>;
|
|
43
|
+
/** Coarse causes only: never expose messages, resolved addresses, or topology. */
|
|
44
|
+
export declare function classifyDiscoveryFailure(error: unknown): {
|
|
45
|
+
dns_error: SafeFetchError['transport'];
|
|
46
|
+
http_status?: number;
|
|
47
|
+
};
|
|
48
|
+
export declare function isPermanentDiscoveryFailure(detail: {
|
|
49
|
+
dns_error?: string;
|
|
50
|
+
http_status?: number;
|
|
51
|
+
}): boolean;
|
|
@@ -24,10 +24,13 @@ __export(fetch_helpers_exports, {
|
|
|
24
24
|
MAX_CAPABILITIES_BYTES: () => MAX_CAPABILITIES_BYTES,
|
|
25
25
|
MAX_JWKS_BYTES: () => MAX_JWKS_BYTES,
|
|
26
26
|
SafeFetchError: () => SafeFetchError,
|
|
27
|
+
classifyDiscoveryFailure: () => classifyDiscoveryFailure,
|
|
28
|
+
isPermanentDiscoveryFailure: () => isPermanentDiscoveryFailure,
|
|
27
29
|
safeFetchJson: () => safeFetchJson
|
|
28
30
|
});
|
|
29
31
|
module.exports = __toCommonJS(fetch_helpers_exports);
|
|
30
32
|
var import_net = require('../../net/index.js');
|
|
33
|
+
var import_agent_transport_fetch = require('../../net/agent-transport-fetch.js');
|
|
31
34
|
var import_strict_json = require('./strict-json.js');
|
|
32
35
|
const MAX_CAPABILITIES_BYTES = 65536;
|
|
33
36
|
const MAX_BRAND_JSON_BYTES = 262144;
|
|
@@ -60,7 +63,11 @@ async function safeFetchJson(url, kind, options) {
|
|
|
60
63
|
res = await (0, import_net.ssrfSafeFetch)(url, fetchOpts);
|
|
61
64
|
} catch (err) {
|
|
62
65
|
if (err instanceof import_net.SsrfRefusedError) {
|
|
63
|
-
throw new SafeFetchError(
|
|
66
|
+
throw new SafeFetchError(
|
|
67
|
+
kind,
|
|
68
|
+
import_net.SSRF_TRANSIENT_CODES.has(err.code) ? err.code === "body_exceeds_limit" ? "body_cap" : "dns_error" : "ssrf_refused",
|
|
69
|
+
`${kind} fetch refused: ${err.code}`
|
|
70
|
+
);
|
|
64
71
|
}
|
|
65
72
|
const message = err instanceof Error ? err.message : String(err);
|
|
66
73
|
if (/abort|timed?\s*out/i.test(message)) {
|
|
@@ -88,6 +95,31 @@ async function safeFetchJson(url, kind, options) {
|
|
|
88
95
|
fetchedAt: Math.floor(Date.now() / 1e3)
|
|
89
96
|
};
|
|
90
97
|
}
|
|
98
|
+
function classifyDiscoveryFailure(error) {
|
|
99
|
+
const seen = /* @__PURE__ */ new Set();
|
|
100
|
+
for (let depth = 0; error && typeof error === "object" && depth < 8 && !seen.has(error); depth++) {
|
|
101
|
+
seen.add(error);
|
|
102
|
+
if (error instanceof SafeFetchError)
|
|
103
|
+
return { dns_error: error.transport, ...error.httpStatus !== void 0 && { http_status: error.httpStatus } };
|
|
104
|
+
if (error instanceof import_agent_transport_fetch.AgentTransportPolicyError) return { dns_error: "ssrf_refused" };
|
|
105
|
+
if (error instanceof import_net.SsrfRefusedError)
|
|
106
|
+
return {
|
|
107
|
+
dns_error: import_net.SSRF_TRANSIENT_CODES.has(error.code) ? error.code === "body_exceeds_limit" ? "body_cap" : "dns_error" : "ssrf_refused"
|
|
108
|
+
};
|
|
109
|
+
const obj = error;
|
|
110
|
+
const status = obj.httpStatus ?? obj.status ?? obj.statusCode;
|
|
111
|
+
if (typeof status === "number" && status >= 400 && status <= 599)
|
|
112
|
+
return { dns_error: "fetch_failed", http_status: status };
|
|
113
|
+
if (obj.code === "ENOTFOUND" || obj.code === "EAI_AGAIN") return { dns_error: "dns_error" };
|
|
114
|
+
if (obj.name === "AbortError" || obj.name === "TimeoutError" || obj.code === "ETIMEDOUT" || typeof obj.code === "string" && obj.code.startsWith("UND_ERR_") && obj.code.endsWith("_TIMEOUT"))
|
|
115
|
+
return { dns_error: "timeout" };
|
|
116
|
+
error = obj.cause;
|
|
117
|
+
}
|
|
118
|
+
return { dns_error: "fetch_failed" };
|
|
119
|
+
}
|
|
120
|
+
function isPermanentDiscoveryFailure(detail) {
|
|
121
|
+
return detail.dns_error === "ssrf_refused" || detail.http_status !== void 0 && detail.http_status >= 400 && detail.http_status < 500;
|
|
122
|
+
}
|
|
91
123
|
// Annotate the CommonJS export names for ESM import in node:
|
|
92
124
|
0 && (module.exports = {
|
|
93
125
|
DEFAULT_CONNECT_TIMEOUT_MS,
|
|
@@ -96,5 +128,7 @@ async function safeFetchJson(url, kind, options) {
|
|
|
96
128
|
MAX_CAPABILITIES_BYTES,
|
|
97
129
|
MAX_JWKS_BYTES,
|
|
98
130
|
SafeFetchError,
|
|
131
|
+
classifyDiscoveryFailure,
|
|
132
|
+
isPermanentDiscoveryFailure,
|
|
99
133
|
safeFetchJson
|
|
100
134
|
});
|
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
ssrfSafeFetch,
|
|
3
|
+
SsrfRefusedError,
|
|
4
|
+
SSRF_TRANSIENT_CODES
|
|
5
|
+
} from "../../net/index.mjs";
|
|
6
|
+
import { AgentTransportPolicyError } from "../../net/agent-transport-fetch.mjs";
|
|
2
7
|
import { parseStrictJson, StrictJsonError } from "./strict-json.mjs";
|
|
3
8
|
const MAX_CAPABILITIES_BYTES = 65536;
|
|
4
9
|
const MAX_BRAND_JSON_BYTES = 262144;
|
|
@@ -31,7 +36,11 @@ async function safeFetchJson(url, kind, options) {
|
|
|
31
36
|
res = await ssrfSafeFetch(url, fetchOpts);
|
|
32
37
|
} catch (err) {
|
|
33
38
|
if (err instanceof SsrfRefusedError) {
|
|
34
|
-
throw new SafeFetchError(
|
|
39
|
+
throw new SafeFetchError(
|
|
40
|
+
kind,
|
|
41
|
+
SSRF_TRANSIENT_CODES.has(err.code) ? err.code === "body_exceeds_limit" ? "body_cap" : "dns_error" : "ssrf_refused",
|
|
42
|
+
`${kind} fetch refused: ${err.code}`
|
|
43
|
+
);
|
|
35
44
|
}
|
|
36
45
|
const message = err instanceof Error ? err.message : String(err);
|
|
37
46
|
if (/abort|timed?\s*out/i.test(message)) {
|
|
@@ -59,6 +68,31 @@ async function safeFetchJson(url, kind, options) {
|
|
|
59
68
|
fetchedAt: Math.floor(Date.now() / 1e3)
|
|
60
69
|
};
|
|
61
70
|
}
|
|
71
|
+
function classifyDiscoveryFailure(error) {
|
|
72
|
+
const seen = /* @__PURE__ */ new Set();
|
|
73
|
+
for (let depth = 0; error && typeof error === "object" && depth < 8 && !seen.has(error); depth++) {
|
|
74
|
+
seen.add(error);
|
|
75
|
+
if (error instanceof SafeFetchError)
|
|
76
|
+
return { dns_error: error.transport, ...error.httpStatus !== void 0 && { http_status: error.httpStatus } };
|
|
77
|
+
if (error instanceof AgentTransportPolicyError) return { dns_error: "ssrf_refused" };
|
|
78
|
+
if (error instanceof SsrfRefusedError)
|
|
79
|
+
return {
|
|
80
|
+
dns_error: SSRF_TRANSIENT_CODES.has(error.code) ? error.code === "body_exceeds_limit" ? "body_cap" : "dns_error" : "ssrf_refused"
|
|
81
|
+
};
|
|
82
|
+
const obj = error;
|
|
83
|
+
const status = obj.httpStatus ?? obj.status ?? obj.statusCode;
|
|
84
|
+
if (typeof status === "number" && status >= 400 && status <= 599)
|
|
85
|
+
return { dns_error: "fetch_failed", http_status: status };
|
|
86
|
+
if (obj.code === "ENOTFOUND" || obj.code === "EAI_AGAIN") return { dns_error: "dns_error" };
|
|
87
|
+
if (obj.name === "AbortError" || obj.name === "TimeoutError" || obj.code === "ETIMEDOUT" || typeof obj.code === "string" && obj.code.startsWith("UND_ERR_") && obj.code.endsWith("_TIMEOUT"))
|
|
88
|
+
return { dns_error: "timeout" };
|
|
89
|
+
error = obj.cause;
|
|
90
|
+
}
|
|
91
|
+
return { dns_error: "fetch_failed" };
|
|
92
|
+
}
|
|
93
|
+
function isPermanentDiscoveryFailure(detail) {
|
|
94
|
+
return detail.dns_error === "ssrf_refused" || detail.http_status !== void 0 && detail.http_status >= 400 && detail.http_status < 500;
|
|
95
|
+
}
|
|
62
96
|
export {
|
|
63
97
|
DEFAULT_CONNECT_TIMEOUT_MS,
|
|
64
98
|
DEFAULT_TOTAL_TIMEOUT_MS,
|
|
@@ -66,5 +100,7 @@ export {
|
|
|
66
100
|
MAX_CAPABILITIES_BYTES,
|
|
67
101
|
MAX_JWKS_BYTES,
|
|
68
102
|
SafeFetchError,
|
|
103
|
+
classifyDiscoveryFailure,
|
|
104
|
+
isPermanentDiscoveryFailure,
|
|
69
105
|
safeFetchJson
|
|
70
106
|
};
|
|
@@ -42,7 +42,7 @@ async function fetchLegacyBrandJson(agentUrl, options) {
|
|
|
42
42
|
} catch (err) {
|
|
43
43
|
throw new import_fetch_helpers.SafeFetchError(
|
|
44
44
|
"brand.json",
|
|
45
|
-
|
|
45
|
+
(0, import_fetch_helpers.classifyDiscoveryFailure)(err).dns_error,
|
|
46
46
|
err instanceof import_brand_jwks.BrandJsonResolverError && err.code === "invalid_body" ? "brand.json body failed strict-JSON parse" : "Legacy brand.json discovery failed",
|
|
47
47
|
err instanceof import_brand_jwks.BrandJsonResolverError ? err.httpStatus : void 0
|
|
48
48
|
);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { fetchBrandJson, BrandJsonResolverError } from "../brand-jwks.mjs";
|
|
2
2
|
import { eTldPlusOne } from "./etld.mjs";
|
|
3
|
-
import { SafeFetchError } from "./fetch-helpers.mjs";
|
|
3
|
+
import { SafeFetchError, classifyDiscoveryFailure } from "./fetch-helpers.mjs";
|
|
4
4
|
async function fetchLegacyBrandJson(agentUrl, options) {
|
|
5
5
|
const agent = new URL(agentUrl);
|
|
6
6
|
let startUrl = `${agent.origin}/.well-known/brand.json`;
|
|
@@ -19,7 +19,7 @@ async function fetchLegacyBrandJson(agentUrl, options) {
|
|
|
19
19
|
} catch (err) {
|
|
20
20
|
throw new SafeFetchError(
|
|
21
21
|
"brand.json",
|
|
22
|
-
|
|
22
|
+
classifyDiscoveryFailure(err).dns_error,
|
|
23
23
|
err instanceof BrandJsonResolverError && err.code === "invalid_body" ? "brand.json body failed strict-JSON parse" : "Legacy brand.json discovery failed",
|
|
24
24
|
err instanceof BrandJsonResolverError ? err.httpStatus : void 0
|
|
25
25
|
);
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
* `SsrfRefusedError` carries.
|
|
29
29
|
*/
|
|
30
30
|
import type { IdentityKeyOriginPurpose, IdentityPosture } from './capabilities-types.mjs';
|
|
31
|
-
import type
|
|
31
|
+
import { type SsrfDnsLookup } from '../../net/index.mjs';
|
|
32
32
|
import { type ConsistencyResult } from './consistency.mjs';
|
|
33
33
|
import { type AgentResolverErrorDetail } from './errors.mjs';
|
|
34
34
|
import { type AgentEntry } from './select-agent.mjs';
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
* `SsrfRefusedError` carries.
|
|
29
29
|
*/
|
|
30
30
|
import type { IdentityKeyOriginPurpose, IdentityPosture } from './capabilities-types';
|
|
31
|
-
import type
|
|
31
|
+
import { type SsrfDnsLookup } from '../../net';
|
|
32
32
|
import { type ConsistencyResult } from './consistency';
|
|
33
33
|
import { type AgentResolverErrorDetail } from './errors';
|
|
34
34
|
import { type AgentEntry } from './select-agent';
|