@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
|
@@ -91,6 +91,8 @@ function hasIdempotencyClearAll(store) {
|
|
|
91
91
|
return typeof store.clearAll === "function";
|
|
92
92
|
}
|
|
93
93
|
const IDEMPOTENCY_CLAIM_RENEW_INTERVAL_MS = 6e4;
|
|
94
|
+
import { isAccountProvisioningTask } from "./account-provisioning.mjs";
|
|
95
|
+
import { warnAccountReferenceDeprecation } from "./account-reference-warnings.mjs";
|
|
94
96
|
import { isMutatingTask, requestUsesIdempotency, IDEMPOTENCY_KEY_PATTERN, MUTATING_TASKS } from "../utils/idempotency.mjs";
|
|
95
97
|
import { STATUS_FREE_SYNC_RESPONSE_TOOLS } from "../utils/envelope-status-compat.mjs";
|
|
96
98
|
import { validateRequest, validateResponse, formatIssues } from "../validation/schema-validator.mjs";
|
|
@@ -656,6 +658,98 @@ function shallowToolInputHintSchema(toolName) {
|
|
|
656
658
|
SHALLOW_HINT_SCHEMAS.set(toolName, schema);
|
|
657
659
|
return schema;
|
|
658
660
|
}
|
|
661
|
+
function isAccountNotificationEventIssue(issue) {
|
|
662
|
+
return issue.keyword === "enum" && /^\/accounts\/\d+\/notification_configs\/\d+\/event_types\/\d+$/.test(issue.pointer);
|
|
663
|
+
}
|
|
664
|
+
function rejectedSyncAccountRow(entry) {
|
|
665
|
+
const identity = entry.account !== void 0 ? { account: entry.account } : Object.fromEntries(
|
|
666
|
+
["brand", "operator", "operator_unit", "currency", "timezone", "sandbox"].filter((key) => entry[key] !== void 0).map((key) => [key, entry[key]])
|
|
667
|
+
);
|
|
668
|
+
return {
|
|
669
|
+
...identity,
|
|
670
|
+
action: "failed",
|
|
671
|
+
// Provisioning was declined. A failed settings update does not establish
|
|
672
|
+
// the existing account's lifecycle state, so leave that status unknown.
|
|
673
|
+
...entry.account === void 0 && { status: "rejected" },
|
|
674
|
+
errors: []
|
|
675
|
+
};
|
|
676
|
+
}
|
|
677
|
+
function accountNotificationFailureRows(accounts, issues, deleteMissing) {
|
|
678
|
+
const rows = /* @__PURE__ */ new Map();
|
|
679
|
+
for (const issue of issues) {
|
|
680
|
+
const [, accountIndex, configIndex, eventIndex] = issue.pointer.match(
|
|
681
|
+
/^\/accounts\/(\d+)\/notification_configs\/(\d+)\/event_types\/(\d+)$/
|
|
682
|
+
);
|
|
683
|
+
const index = Number(accountIndex);
|
|
684
|
+
const entry = accounts[index];
|
|
685
|
+
let row = rows.get(index);
|
|
686
|
+
if (row === void 0) {
|
|
687
|
+
row = rejectedSyncAccountRow(entry);
|
|
688
|
+
rows.set(index, row);
|
|
689
|
+
}
|
|
690
|
+
row.errors.push({
|
|
691
|
+
code: "VALIDATION_ERROR",
|
|
692
|
+
recovery: "correctable",
|
|
693
|
+
message: issue.message,
|
|
694
|
+
field: `notification_configs[${configIndex}].event_types[${eventIndex}]`
|
|
695
|
+
});
|
|
696
|
+
}
|
|
697
|
+
if (deleteMissing) {
|
|
698
|
+
for (const [index, entry] of accounts.entries()) {
|
|
699
|
+
if (rows.has(index)) continue;
|
|
700
|
+
rows.set(index, {
|
|
701
|
+
...rejectedSyncAccountRow(entry),
|
|
702
|
+
errors: [
|
|
703
|
+
{
|
|
704
|
+
code: "VALIDATION_ERROR",
|
|
705
|
+
recovery: "correctable",
|
|
706
|
+
message: "delete_missing cannot be applied while account notification event types are invalid. Correct the rejected entries and retry.",
|
|
707
|
+
field: "delete_missing"
|
|
708
|
+
}
|
|
709
|
+
]
|
|
710
|
+
});
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
return rows;
|
|
714
|
+
}
|
|
715
|
+
function restoreSyncAccountErrorIndices(row, acceptedIndices) {
|
|
716
|
+
if (!isPlainObject(row)) return row;
|
|
717
|
+
const restorePath = (path, pointer = false) => {
|
|
718
|
+
const match = pointer ? /^\/accounts\/(\d+)(?=\/|$)/.exec(path) : /^accounts\[(\d+)\](?=\.|\[|$)/.exec(path);
|
|
719
|
+
if (match === null) return path;
|
|
720
|
+
const originalIndex = acceptedIndices[Number(match[1])];
|
|
721
|
+
if (originalIndex === void 0) return path;
|
|
722
|
+
return `${pointer ? `/accounts/${originalIndex}` : `accounts[${originalIndex}]`}${path.slice(match[0].length)}`;
|
|
723
|
+
};
|
|
724
|
+
const restoreIssues = (issues) => issues.map(
|
|
725
|
+
(issue) => isPlainObject(issue) && typeof issue.pointer === "string" ? { ...issue, pointer: restorePath(issue.pointer, true) } : issue
|
|
726
|
+
);
|
|
727
|
+
const restoreField = (error) => {
|
|
728
|
+
if (!isPlainObject(error)) return error;
|
|
729
|
+
return {
|
|
730
|
+
...error,
|
|
731
|
+
...typeof error.field === "string" && { field: restorePath(error.field) },
|
|
732
|
+
...Array.isArray(error.issues) && { issues: restoreIssues(error.issues) },
|
|
733
|
+
...isPlainObject(error.details) && Array.isArray(error.details.issues) && {
|
|
734
|
+
details: { ...error.details, issues: restoreIssues(error.details.issues) }
|
|
735
|
+
}
|
|
736
|
+
};
|
|
737
|
+
};
|
|
738
|
+
return {
|
|
739
|
+
...row,
|
|
740
|
+
...Array.isArray(row.errors) && { errors: row.errors.map(restoreField) },
|
|
741
|
+
...isPlainObject(row.adcp_error) && { adcp_error: restoreField(row.adcp_error) }
|
|
742
|
+
};
|
|
743
|
+
}
|
|
744
|
+
function restoreSyncAccountEnvelopeErrorIndices(response, acceptedIndices) {
|
|
745
|
+
const body = response.structuredContent;
|
|
746
|
+
if (body === void 0 || !(Array.isArray(body.errors) || isPlainObject(body.adcp_error))) return response;
|
|
747
|
+
const restored = cloneFormattedResponse(response);
|
|
748
|
+
const mirrorsStructuredContent = contentTextMirrorsStructuredContent(restored, body);
|
|
749
|
+
restored.structuredContent = restoreSyncAccountErrorIndices(body, acceptedIndices);
|
|
750
|
+
syncContentJsonText(restored, restored.structuredContent, mirrorsStructuredContent);
|
|
751
|
+
return restored;
|
|
752
|
+
}
|
|
659
753
|
function validateFrameworkPayload(toolName, direction, payload, version, proposalCapabilities) {
|
|
660
754
|
if (toolName === "sync_reporting_status" && direction === "request") {
|
|
661
755
|
return validateSyncReportingStatusEnvelope(payload, version);
|
|
@@ -1852,6 +1946,7 @@ function createAdcpServer(config) {
|
|
|
1852
1946
|
defaultAdcpVersion: configuredDefaultAdcpVersion,
|
|
1853
1947
|
mcpToolProfile = "auto",
|
|
1854
1948
|
requireCompactMutationAccountScope = false,
|
|
1949
|
+
strictAccountReferences = false,
|
|
1855
1950
|
resolveAccount,
|
|
1856
1951
|
resolveAccountFromAuth,
|
|
1857
1952
|
resolveSessionKey,
|
|
@@ -2567,6 +2662,7 @@ function createAdcpServer(config) {
|
|
|
2567
2662
|
const wrap = meta?.wrap ?? ((data, summary) => genericResponse(toolName, data, summary));
|
|
2568
2663
|
const toolHandler = async (params, extra) => {
|
|
2569
2664
|
const callRequestValidationMode = effectiveRequestValidationMode(extra);
|
|
2665
|
+
let notificationFailureRows = /* @__PURE__ */ new Map();
|
|
2570
2666
|
const releaseSelection = selectServedAdcpRelease(params, capConfig, adcpVersion, defaultAdcpVersion);
|
|
2571
2667
|
let releaseError;
|
|
2572
2668
|
let requestRelease;
|
|
@@ -2814,7 +2910,25 @@ function createAdcpServer(config) {
|
|
|
2814
2910
|
})
|
|
2815
2911
|
);
|
|
2816
2912
|
}
|
|
2817
|
-
|
|
2913
|
+
let issues = idempotencyDisabled && requestIsStateChanging ? outcome.issues.filter((i) => !(i.keyword === "required" && i.pointer === "/idempotency_key")) : outcome.issues;
|
|
2914
|
+
if (toolName === "sync_accounts" && effectiveFrameworkRequestValidationMode === "strict") {
|
|
2915
|
+
const eventIssues = issues.filter(isAccountNotificationEventIssue);
|
|
2916
|
+
if (eventIssues.length > 0 && eventIssues.length === issues.length) {
|
|
2917
|
+
const failedRows = accountNotificationFailureRows(
|
|
2918
|
+
params.accounts,
|
|
2919
|
+
eventIssues,
|
|
2920
|
+
params.delete_missing === true
|
|
2921
|
+
);
|
|
2922
|
+
if (validateResponse(
|
|
2923
|
+
"sync_accounts",
|
|
2924
|
+
{ accounts: [...failedRows.values()] },
|
|
2925
|
+
requestRelease.validationVersion
|
|
2926
|
+
).valid) {
|
|
2927
|
+
notificationFailureRows = failedRows;
|
|
2928
|
+
issues = [];
|
|
2929
|
+
}
|
|
2930
|
+
}
|
|
2931
|
+
}
|
|
2818
2932
|
if (issues.length > 0) {
|
|
2819
2933
|
if (effectiveFrameworkRequestValidationMode === "strict") {
|
|
2820
2934
|
const payload = buildAdcpValidationErrorPayload(toolName, "request", issues, {
|
|
@@ -2833,13 +2947,24 @@ function createAdcpServer(config) {
|
|
|
2833
2947
|
}
|
|
2834
2948
|
}
|
|
2835
2949
|
}
|
|
2836
|
-
|
|
2950
|
+
let unresolvedAccountPassThrough = false;
|
|
2951
|
+
const suppliedAccountRef = hasAccount && params.account != null && !(strictAccountReferences && toolName === "list_accounts");
|
|
2952
|
+
if (suppliedAccountRef && toolName === "list_accounts") {
|
|
2953
|
+
warnAccountReferenceDeprecation(
|
|
2954
|
+
logger,
|
|
2955
|
+
"ADCP_LIST_ACCOUNTS_FILTER_RESOLVED",
|
|
2956
|
+
"[adcp/createAdcpServer] DEPRECATED: list_accounts.account is resolved as the request account (SDK 14.0 behavior). The next major release, or strictAccountReferences: true, treats it as a filter: resolveAccount is not called for it and ctx.account comes from resolveAccountFromAuth.",
|
|
2957
|
+
{ tool: toolName }
|
|
2958
|
+
);
|
|
2959
|
+
}
|
|
2960
|
+
if (suppliedAccountRef && resolveAccount) {
|
|
2837
2961
|
try {
|
|
2838
2962
|
const account = await resolveAccount(
|
|
2839
2963
|
params.account,
|
|
2840
2964
|
withImmutableServedAdcpVersion(
|
|
2841
2965
|
{
|
|
2842
2966
|
toolName,
|
|
2967
|
+
provisioning: isAccountProvisioningTask(toolName),
|
|
2843
2968
|
authInfo: ctx.authInfo,
|
|
2844
2969
|
...ctx.agent != null && { agent: ctx.agent },
|
|
2845
2970
|
input: params
|
|
@@ -2872,20 +2997,32 @@ function createAdcpServer(config) {
|
|
|
2872
2997
|
})
|
|
2873
2998
|
);
|
|
2874
2999
|
}
|
|
2875
|
-
} else if (
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
2882
|
-
|
|
2883
|
-
|
|
3000
|
+
} else if (suppliedAccountRef) {
|
|
3001
|
+
if (strictAccountReferences || toolName === "list_creative_formats") {
|
|
3002
|
+
return finalize(
|
|
3003
|
+
adcpError("ACCOUNT_NOT_FOUND", {
|
|
3004
|
+
message: "The specified account cannot be resolved",
|
|
3005
|
+
field: "account",
|
|
3006
|
+
suggestion: "The seller must configure resolveAccount to authorize supplied references; use list_accounts to discover an authorized account"
|
|
3007
|
+
})
|
|
3008
|
+
);
|
|
3009
|
+
}
|
|
3010
|
+
if (toolName !== "list_accounts") {
|
|
3011
|
+
warnAccountReferenceDeprecation(
|
|
3012
|
+
logger,
|
|
3013
|
+
"ADCP_UNRESOLVED_ACCOUNT_REFERENCE",
|
|
3014
|
+
"[adcp/createAdcpServer] DEPRECATED: a request carried a buyer-supplied account reference, but no resolveAccount is configured. The reference reached the handler unverified (ctx.account is undefined). The next major release refuses it with ACCOUNT_NOT_FOUND. Configure a reference-aware resolveAccount that returns null for unknown or unauthorized references, then set strictAccountReferences: true. See https://github.com/adcontextprotocol/adcp-client/blob/main/docs/guides/account-resolution.md",
|
|
3015
|
+
{ tool: toolName }
|
|
3016
|
+
);
|
|
3017
|
+
}
|
|
3018
|
+
unresolvedAccountPassThrough = true;
|
|
3019
|
+
} else if (!suppliedAccountRef && resolveAccountFromAuth) {
|
|
2884
3020
|
try {
|
|
2885
3021
|
const account = await resolveAccountFromAuth(
|
|
2886
3022
|
withImmutableServedAdcpVersion(
|
|
2887
3023
|
{
|
|
2888
3024
|
toolName,
|
|
3025
|
+
provisioning: isAccountProvisioningTask(toolName),
|
|
2889
3026
|
authInfo: ctx.authInfo,
|
|
2890
3027
|
...ctx.agent != null && { agent: ctx.agent },
|
|
2891
3028
|
input: params
|
|
@@ -2916,6 +3053,26 @@ function createAdcpServer(config) {
|
|
|
2916
3053
|
}
|
|
2917
3054
|
}
|
|
2918
3055
|
}
|
|
3056
|
+
if ((toolName === "get_products" || toolName === "list_products") && capConfig?.account?.requiredForProducts && ctx.account == null && // A supplied reference the compatibility pass-through handed to the
|
|
3057
|
+
// handler satisfies the seller's declared requirement.
|
|
3058
|
+
!unresolvedAccountPassThrough) {
|
|
3059
|
+
if (!strictAccountReferences) {
|
|
3060
|
+
warnAccountReferenceDeprecation(
|
|
3061
|
+
logger,
|
|
3062
|
+
"ADCP_REQUIRED_FOR_PRODUCTS_NOT_ENFORCED",
|
|
3063
|
+
`[adcp/createAdcpServer] DEPRECATED: this seller declares account.required_for_products, but ${toolName} ran without an account (SDK 14.0 behavior). The next major release, or strictAccountReferences: true, refuses it with ACCOUNT_REQUIRED.`,
|
|
3064
|
+
{ tool: toolName }
|
|
3065
|
+
);
|
|
3066
|
+
} else {
|
|
3067
|
+
return finalize(
|
|
3068
|
+
adcpError("ACCOUNT_REQUIRED", {
|
|
3069
|
+
message: "This seller requires an account for product discovery",
|
|
3070
|
+
field: "account",
|
|
3071
|
+
suggestion: "Provision an account with sync_accounts or discover one with list_accounts"
|
|
3072
|
+
})
|
|
3073
|
+
);
|
|
3074
|
+
}
|
|
3075
|
+
}
|
|
2919
3076
|
if (ctx.agent?.sandbox_only === true && ctx.account !== void 0 && ctx.account.sandbox !== true) {
|
|
2920
3077
|
return finalize(
|
|
2921
3078
|
adcpError("PERMISSION_DENIED", {
|
|
@@ -3177,13 +3334,23 @@ function createAdcpServer(config) {
|
|
|
3177
3334
|
if (typeof claimRenewalTimer === "object" && "unref" in claimRenewalTimer) claimRenewalTimer.unref();
|
|
3178
3335
|
}
|
|
3179
3336
|
let mutationHandlerCompleted = false;
|
|
3337
|
+
const acceptedAccountIndices = notificationFailureRows.size > 0 ? params.accounts.flatMap(
|
|
3338
|
+
(_entry, index) => notificationFailureRows.has(index) ? [] : [index]
|
|
3339
|
+
) : void 0;
|
|
3340
|
+
const restoreHandlerErrorIndices = (response) => acceptedAccountIndices === void 0 ? response : restoreSyncAccountEnvelopeErrorIndices(response, acceptedAccountIndices);
|
|
3180
3341
|
try {
|
|
3181
3342
|
if (webhookEmitter) {
|
|
3182
3343
|
const tenantScope = webhookTenantScopeForContext(ctx);
|
|
3183
3344
|
const scopedEmitter = tenantScope === void 0 ? configuredWebhookEmitter : webhookEmitter.forTenantScope(tenantScope);
|
|
3184
3345
|
ctx.emitWebhook = scopedEmitter.emit.bind(scopedEmitter);
|
|
3185
3346
|
}
|
|
3186
|
-
const
|
|
3347
|
+
const handlerParams = notificationFailureRows.size === 0 ? params : {
|
|
3348
|
+
...params,
|
|
3349
|
+
accounts: params.accounts.filter(
|
|
3350
|
+
(_entry, index) => !notificationFailureRows.has(index)
|
|
3351
|
+
)
|
|
3352
|
+
};
|
|
3353
|
+
const result = notificationFailureRows.size > 0 && handlerParams.accounts.length === 0 ? { accounts: [], ...params.dry_run === true && { dry_run: true } } : await handler(handlerParams, ctx);
|
|
3187
3354
|
mutationHandlerCompleted = true;
|
|
3188
3355
|
let formatted;
|
|
3189
3356
|
if (isFormattedResponse(result)) {
|
|
@@ -3220,6 +3387,42 @@ function createAdcpServer(config) {
|
|
|
3220
3387
|
} else {
|
|
3221
3388
|
formatted = wrap(result);
|
|
3222
3389
|
}
|
|
3390
|
+
formatted = restoreHandlerErrorIndices(formatted);
|
|
3391
|
+
if (notificationFailureRows.size > 0 && !isErrorResponse(formatted) && !(Array.isArray(formatted.structuredContent?.errors) && formatted.structuredContent?.accounts === void 0)) {
|
|
3392
|
+
formatted = cloneFormattedResponse(formatted);
|
|
3393
|
+
const body = formatted.structuredContent;
|
|
3394
|
+
const acceptedRows = Array.isArray(body.accounts) ? body.accounts.map((row) => restoreSyncAccountErrorIndices(row, acceptedAccountIndices)) : body.accounts;
|
|
3395
|
+
const submitted = isSubmittedEnvelope(body);
|
|
3396
|
+
let accounts;
|
|
3397
|
+
if (submitted) {
|
|
3398
|
+
if (acceptedRows !== void 0 && !Array.isArray(acceptedRows)) {
|
|
3399
|
+
throw new Error("sync_accounts submitted accounts must be an array when present");
|
|
3400
|
+
}
|
|
3401
|
+
accounts = [
|
|
3402
|
+
...Array.isArray(acceptedRows) ? acceptedRows : [],
|
|
3403
|
+
...[...notificationFailureRows.entries()].sort(([a], [b]) => a - b).map(([, row]) => row)
|
|
3404
|
+
];
|
|
3405
|
+
} else {
|
|
3406
|
+
if (!Array.isArray(acceptedRows) || acceptedRows.length !== handlerParams.accounts.length) {
|
|
3407
|
+
throw new Error("sync_accounts handler must return one result row for each accepted account entry");
|
|
3408
|
+
}
|
|
3409
|
+
let acceptedIndex = 0;
|
|
3410
|
+
accounts = params.accounts.map(
|
|
3411
|
+
(_entry, index) => notificationFailureRows.get(index) ?? acceptedRows[acceptedIndex++]
|
|
3412
|
+
);
|
|
3413
|
+
}
|
|
3414
|
+
const merged = { ...body, accounts };
|
|
3415
|
+
if (isFormattedResponse(result)) {
|
|
3416
|
+
const mirrorsStructuredContent = contentTextMirrorsStructuredContent(formatted, body);
|
|
3417
|
+
formatted = { ...formatted, structuredContent: wrap(merged).structuredContent };
|
|
3418
|
+
syncContentJsonText(formatted, formatted.structuredContent, mirrorsStructuredContent);
|
|
3419
|
+
} else {
|
|
3420
|
+
const rejected = accounts.filter((row) => row.action === "failed").length;
|
|
3421
|
+
const synced = accounts.length - rejected;
|
|
3422
|
+
const summary = submitted ? typeof body.message === "string" ? body.message : `Task ${body.task_id} submitted` : `Synced ${synced} account${synced === 1 ? "" : "s"}`;
|
|
3423
|
+
formatted = wrap(merged, `${summary}; ${rejected} account${rejected === 1 ? "" : "s"} rejected`);
|
|
3424
|
+
}
|
|
3425
|
+
}
|
|
3223
3426
|
if (testControllerBridge && !isErrorResponse(formatted) && isSandboxRequestForSeeding(params) && ctx.account !== void 0 && !isSandboxOrMockAccount(ctx.account)) {
|
|
3224
3427
|
const resolvedAccountId = typeof ctx.account === "object" && ctx.account !== null && typeof ctx.account.account_id === "string" ? ctx.account.account_id : void 0;
|
|
3225
3428
|
logger.debug(
|
|
@@ -3747,6 +3950,9 @@ function createAdcpServer(config) {
|
|
|
3747
3950
|
});
|
|
3748
3951
|
thrownTypedEnvelope = projectThrownAdcpError(err);
|
|
3749
3952
|
}
|
|
3953
|
+
if (thrownTypedEnvelope !== void 0) {
|
|
3954
|
+
thrownTypedEnvelope = restoreHandlerErrorIndices(thrownTypedEnvelope);
|
|
3955
|
+
}
|
|
3750
3956
|
const thrownRecovery = thrownTypedEnvelope ? thrownAdcpErrorRecovery(thrownTypedEnvelope) : void 0;
|
|
3751
3957
|
let stableTypedOutcome = !mutationHandlerCompleted && !!thrownTypedEnvelope && thrownRecovery !== "transient";
|
|
3752
3958
|
let replayEnvelope;
|
|
@@ -3841,7 +4047,7 @@ function createAdcpServer(config) {
|
|
|
3841
4047
|
message: env.message,
|
|
3842
4048
|
stack: err instanceof Error ? err.stack : void 0
|
|
3843
4049
|
});
|
|
3844
|
-
return finalize(err);
|
|
4050
|
+
return finalize(restoreHandlerErrorIndices(err));
|
|
3845
4051
|
}
|
|
3846
4052
|
if (err instanceof AdcpError) {
|
|
3847
4053
|
logger.warn("Handler threw an AdcpError", {
|
|
@@ -3851,7 +4057,7 @@ function createAdcpServer(config) {
|
|
|
3851
4057
|
message: err.message,
|
|
3852
4058
|
stack: err.stack
|
|
3853
4059
|
});
|
|
3854
|
-
return finalize(projectThrownAdcpError(err));
|
|
4060
|
+
return finalize(restoreHandlerErrorIndices(projectThrownAdcpError(err)));
|
|
3855
4061
|
}
|
|
3856
4062
|
const reason = err instanceof Error ? err.message : String(err);
|
|
3857
4063
|
logger.error("Handler failed", {
|
|
@@ -4154,6 +4360,11 @@ function createAdcpServer(config) {
|
|
|
4154
4360
|
}
|
|
4155
4361
|
}
|
|
4156
4362
|
checkCoherence(registeredToolNames, logger);
|
|
4363
|
+
if (!resolveAccount && process.env.NODE_ENV !== "production" && ["get_products", "get_signals", "request_proposals", "create_media_buy"].some((tool) => registeredToolNames.has(tool))) {
|
|
4364
|
+
logger.warn(
|
|
4365
|
+
strictAccountReferences ? "Account-carrying tools are registered without resolveAccount. Supplied references will fail with ACCOUNT_NOT_FOUND." : "Account-carrying tools are registered without resolveAccount. Supplied references reach handlers unverified; this is deprecated and they will fail with ACCOUNT_NOT_FOUND in the next major release. Configure a reference-aware resolveAccount and set strictAccountReferences: true."
|
|
4366
|
+
);
|
|
4367
|
+
}
|
|
4157
4368
|
const registeredMutatingTools = [...registeredToolNames].filter((t) => MUTATING_TASKS.has(t));
|
|
4158
4369
|
if (registeredToolNames.has("get_creative_features") && idempotency && idempotency.ttlSeconds < 86400) {
|
|
4159
4370
|
throw new TypeError(
|
|
@@ -305,6 +305,8 @@ export interface ResolvedAuthInfo {
|
|
|
305
305
|
extra?: Record<string, unknown>;
|
|
306
306
|
}
|
|
307
307
|
export interface ResolveContext {
|
|
308
|
+
/** True only for provisioning tasks. Discovery/negotiation MUST use lookup only. */
|
|
309
|
+
readonly provisioning?: boolean;
|
|
308
310
|
/** Authenticated principal extracted by `serve({ authenticate })`. Undefined when no `authenticate` is configured. */
|
|
309
311
|
authInfo?: ResolvedAuthInfo;
|
|
310
312
|
/** Tool the buyer is calling — useful for tool-aware tenant routing. */
|
|
@@ -305,6 +305,8 @@ export interface ResolvedAuthInfo {
|
|
|
305
305
|
extra?: Record<string, unknown>;
|
|
306
306
|
}
|
|
307
307
|
export interface ResolveContext {
|
|
308
|
+
/** True only for provisioning tasks. Discovery/negotiation MUST use lookup only. */
|
|
309
|
+
readonly provisioning?: boolean;
|
|
308
310
|
/** Authenticated principal extracted by `serve({ authenticate })`. Undefined when no `authenticate` is configured. */
|
|
309
311
|
authInfo?: ResolvedAuthInfo;
|
|
310
312
|
/** Tool the buyer is calling — useful for tool-aware tenant routing. */
|
|
@@ -26,6 +26,8 @@ __export(from_platform_exports, {
|
|
|
26
26
|
getHydratedLegacyFormatIds: () => getHydratedLegacyFormatIds
|
|
27
27
|
});
|
|
28
28
|
module.exports = __toCommonJS(from_platform_exports);
|
|
29
|
+
var import_account_provisioning = require('../../account-provisioning.js');
|
|
30
|
+
var import_account_reference_warnings = require('../../account-reference-warnings.js');
|
|
29
31
|
var import_node_crypto = require("node:crypto");
|
|
30
32
|
var import_types = require("@modelcontextprotocol/sdk/types.js");
|
|
31
33
|
var import_create_adcp_server = require('../../create-adcp-server.js');
|
|
@@ -1297,8 +1299,37 @@ function missingAccountError(toolName, resolution) {
|
|
|
1297
1299
|
suggestion: accountRequiredSuggestion(toolName, resolution)
|
|
1298
1300
|
});
|
|
1299
1301
|
}
|
|
1300
|
-
|
|
1302
|
+
const STRICT_IMPLICIT_IDENTITY_POLICY = Object.freeze({ strict: true });
|
|
1303
|
+
function implicitIdentityMismatch(identity, ref) {
|
|
1304
|
+
if (identity.brand && identity.brand.domain !== ref.brand.domain) return "brand.domain";
|
|
1305
|
+
if (identity.brand?.brand_id !== void 0 && ref.brand.brand_id !== void 0 && identity.brand.brand_id !== ref.brand.brand_id)
|
|
1306
|
+
return "brand.brand_id";
|
|
1307
|
+
if (identity.brand?.countries !== void 0 && ref.brand.countries !== void 0 && [...identity.brand.countries].sort().join("\0") !== [...ref.brand.countries].sort().join("\0"))
|
|
1308
|
+
return "brand.countries";
|
|
1309
|
+
if (identity.operator !== void 0 && identity.operator !== ref.operator) return "operator";
|
|
1310
|
+
if (identity.operator_unit !== void 0 && ref.operator_unit !== void 0 && identity.operator_unit.id !== ref.operator_unit.id)
|
|
1311
|
+
return "operator_unit";
|
|
1312
|
+
if (identity.currency !== void 0 && ref.currency !== void 0 && identity.currency !== ref.currency)
|
|
1313
|
+
return "currency";
|
|
1314
|
+
if (identity.timezone !== void 0 && ref.timezone !== void 0 && identity.timezone !== ref.timezone)
|
|
1315
|
+
return "timezone";
|
|
1316
|
+
if (identity.sandbox !== void 0 && identity.sandbox !== (ref.sandbox === true)) return "sandbox";
|
|
1317
|
+
return void 0;
|
|
1318
|
+
}
|
|
1319
|
+
function assertResolvedAccountMatchesRef(resolution, ref, account, logger, implicitIdentity = STRICT_IMPLICIT_IDENTITY_POLICY) {
|
|
1301
1320
|
if (account == null) return null;
|
|
1321
|
+
if ((0, import_account.normalizeAccountResolution)(resolution) === "implicit" && ref && "brand" in ref) {
|
|
1322
|
+
const field = implicitIdentityMismatch(account, ref);
|
|
1323
|
+
if (field === void 0) return account;
|
|
1324
|
+
if (implicitIdentity.strict) return null;
|
|
1325
|
+
(0, import_account_reference_warnings.warnAccountReferenceDeprecation)(
|
|
1326
|
+
logger,
|
|
1327
|
+
"ADCP_IMPLICIT_ACCOUNT_IDENTITY_MISMATCH",
|
|
1328
|
+
`[adcp/sdk] DEPRECATED: accounts.resolve returned an account whose ${field} does not match the supplied natural key on a resolution: 'implicit' platform. The account was accepted for compatibility; the next major release (or strictAccountReferences: true) refuses it with ACCOUNT_NOT_FOUND. Resolve by the complete natural key and return identity metadata that matches it.`,
|
|
1329
|
+
{ field, accountId: account.id }
|
|
1330
|
+
);
|
|
1331
|
+
return account;
|
|
1332
|
+
}
|
|
1302
1333
|
if ((0, import_account.normalizeAccountResolution)(resolution) !== "derived") return account;
|
|
1303
1334
|
const requestedId = (0, import_account.refAccountId)(ref);
|
|
1304
1335
|
if (requestedId === void 0 || account.id === requestedId) return account;
|
|
@@ -1329,6 +1360,7 @@ function createAdcpServerFromPlatform(platform, opts) {
|
|
|
1329
1360
|
signals: opts.legacyHandlers?.signals ?? runtimeLegacyOptions.signals
|
|
1330
1361
|
};
|
|
1331
1362
|
const runtimeOpts = opts;
|
|
1363
|
+
const implicitIdentityPolicy = { strict: runtimeOpts.strictAccountReferences === true };
|
|
1332
1364
|
const runtimeLegacyHandlers = legacyHandlers;
|
|
1333
1365
|
(0, import_validate_platform.validatePlatform)(platform, {
|
|
1334
1366
|
creative: legacyHandlers.creative,
|
|
@@ -1671,7 +1703,8 @@ function createAdcpServerFromPlatform(platform, opts) {
|
|
|
1671
1703
|
platform.accounts.resolution,
|
|
1672
1704
|
ref,
|
|
1673
1705
|
await platform.accounts.resolve(ref, toResolveCtx(ctx, ctx.toolName, ctx.input)),
|
|
1674
|
-
fwLogger
|
|
1706
|
+
fwLogger,
|
|
1707
|
+
implicitIdentityPolicy
|
|
1675
1708
|
);
|
|
1676
1709
|
resolved = account != null;
|
|
1677
1710
|
resolvedAccountId = account?.id;
|
|
@@ -1850,7 +1883,7 @@ function createAdcpServerFromPlatform(platform, opts) {
|
|
|
1850
1883
|
mergeOpts
|
|
1851
1884
|
),
|
|
1852
1885
|
accounts: (() => {
|
|
1853
|
-
const platformAccountHandlers = buildAccountHandlers(platform, ctxFor, fwLogger);
|
|
1886
|
+
const platformAccountHandlers = buildAccountHandlers(platform, ctxFor, fwLogger, implicitIdentityPolicy);
|
|
1854
1887
|
const merged = mergeHandlers(opts.accounts, platformAccountHandlers, "accounts", mergeOpts);
|
|
1855
1888
|
return guardDerivedSyncGovernance(
|
|
1856
1889
|
guardAdopterSyncAccounts(merged, platform, platformAccountHandlers, fwLogger),
|
|
@@ -1871,7 +1904,8 @@ function createAdcpServerFromPlatform(platform, opts) {
|
|
|
1871
1904
|
platform.agentRegistry,
|
|
1872
1905
|
fwLogger,
|
|
1873
1906
|
runtimeOpts.resolveSessionKey,
|
|
1874
|
-
opts.credentialPolicy
|
|
1907
|
+
opts.credentialPolicy,
|
|
1908
|
+
implicitIdentityPolicy
|
|
1875
1909
|
);
|
|
1876
1910
|
return {
|
|
1877
1911
|
...opts.customTools,
|
|
@@ -2093,7 +2127,8 @@ function createAdcpServerFromPlatform(platform, opts) {
|
|
|
2093
2127
|
platform.accounts.resolution,
|
|
2094
2128
|
accountRef,
|
|
2095
2129
|
resolvedAccount,
|
|
2096
|
-
fwLogger
|
|
2130
|
+
fwLogger,
|
|
2131
|
+
implicitIdentityPolicy
|
|
2097
2132
|
);
|
|
2098
2133
|
(0, import_observed_modes.recordResolvedAccountMode)(resolvedAccount);
|
|
2099
2134
|
const accountIsSandbox = resolvedAccount != null && (0, import_account_mode.isSandboxOrMockAccount)(resolvedAccount);
|
|
@@ -2235,7 +2270,7 @@ function createAdcpServerFromPlatform(platform, opts) {
|
|
|
2235
2270
|
statusChange: statusChangeBus
|
|
2236
2271
|
});
|
|
2237
2272
|
}
|
|
2238
|
-
function buildTasksGetTool(platform, taskRegistry, agentRegistry, logger, resolveSessionKey, credentialPolicy) {
|
|
2273
|
+
function buildTasksGetTool(platform, taskRegistry, agentRegistry, logger, resolveSessionKey, credentialPolicy, implicitIdentityPolicy) {
|
|
2239
2274
|
const credentialPolicyPatterns = credentialPolicy === void 0 || typeof credentialPolicy === "string" ? void 0 : credentialPolicy.patterns;
|
|
2240
2275
|
const credentialPolicyError = (args, extra) => {
|
|
2241
2276
|
if (credentialPolicy === void 0) return void 0;
|
|
@@ -2360,7 +2395,8 @@ function buildTasksGetTool(platform, taskRegistry, agentRegistry, logger, resolv
|
|
|
2360
2395
|
platform.accounts.resolution,
|
|
2361
2396
|
ref,
|
|
2362
2397
|
await platform.accounts.resolve(ref, resolveCtx),
|
|
2363
|
-
logger
|
|
2398
|
+
logger,
|
|
2399
|
+
implicitIdentityPolicy
|
|
2364
2400
|
);
|
|
2365
2401
|
if (resolved) {
|
|
2366
2402
|
resolvedAccountId = resolved.id;
|
|
@@ -3167,6 +3203,7 @@ function toResolveCtx(ctx, toolName, input) {
|
|
|
3167
3203
|
{
|
|
3168
3204
|
...ctx.authInfo !== void 0 && { authInfo: ctx.authInfo },
|
|
3169
3205
|
...toolName !== void 0 && { toolName },
|
|
3206
|
+
provisioning: (0, import_account_provisioning.isAccountProvisioningTask)(toolName),
|
|
3170
3207
|
...ctx.agent != null && { agent: ctx.agent },
|
|
3171
3208
|
...input != null && { input }
|
|
3172
3209
|
},
|
|
@@ -5375,7 +5412,7 @@ function enforceSyncAccountsCommercialPolicy(platform, params, resolveCtx) {
|
|
|
5375
5412
|
failedRows
|
|
5376
5413
|
};
|
|
5377
5414
|
}
|
|
5378
|
-
function buildAccountHandlers(platform, ctxFor, logger = DEFAULT_FRAMEWORK_LOGGER) {
|
|
5415
|
+
function buildAccountHandlers(platform, ctxFor, logger = DEFAULT_FRAMEWORK_LOGGER, implicitIdentityPolicy = STRICT_IMPLICIT_IDENTITY_POLICY) {
|
|
5379
5416
|
const accounts = platform.accounts;
|
|
5380
5417
|
const handlers = {};
|
|
5381
5418
|
if (accounts.upsert) {
|
|
@@ -5462,7 +5499,8 @@ function buildAccountHandlers(platform, ctxFor, logger = DEFAULT_FRAMEWORK_LOGGE
|
|
|
5462
5499
|
accounts.resolution,
|
|
5463
5500
|
accountRef,
|
|
5464
5501
|
await accounts.resolve(accountRef, resolveCtx),
|
|
5465
|
-
logger
|
|
5502
|
+
logger,
|
|
5503
|
+
implicitIdentityPolicy
|
|
5466
5504
|
);
|
|
5467
5505
|
if (!resolved) {
|
|
5468
5506
|
const suggestion = accountNotFoundSuggestion(accounts.resolution);
|
|
@@ -5499,7 +5537,8 @@ function buildAccountHandlers(platform, ctxFor, logger = DEFAULT_FRAMEWORK_LOGGE
|
|
|
5499
5537
|
accounts.resolution,
|
|
5500
5538
|
accountRef,
|
|
5501
5539
|
await accounts.resolve(accountRef, resolveCtx),
|
|
5502
|
-
logger
|
|
5540
|
+
logger,
|
|
5541
|
+
implicitIdentityPolicy
|
|
5503
5542
|
);
|
|
5504
5543
|
if (!resolved) {
|
|
5505
5544
|
const suggestion = accountNotFoundSuggestion(accounts.resolution);
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { isAccountProvisioningTask } from "../../account-provisioning.mjs";
|
|
2
|
+
import { warnAccountReferenceDeprecation } from "../../account-reference-warnings.mjs";
|
|
1
3
|
import { randomUUID } from "node:crypto";
|
|
2
4
|
import { ErrorCode, McpError } from "@modelcontextprotocol/sdk/types.js";
|
|
3
5
|
import {
|
|
@@ -1326,8 +1328,37 @@ function missingAccountError(toolName, resolution) {
|
|
|
1326
1328
|
suggestion: accountRequiredSuggestion(toolName, resolution)
|
|
1327
1329
|
});
|
|
1328
1330
|
}
|
|
1329
|
-
|
|
1331
|
+
const STRICT_IMPLICIT_IDENTITY_POLICY = Object.freeze({ strict: true });
|
|
1332
|
+
function implicitIdentityMismatch(identity, ref) {
|
|
1333
|
+
if (identity.brand && identity.brand.domain !== ref.brand.domain) return "brand.domain";
|
|
1334
|
+
if (identity.brand?.brand_id !== void 0 && ref.brand.brand_id !== void 0 && identity.brand.brand_id !== ref.brand.brand_id)
|
|
1335
|
+
return "brand.brand_id";
|
|
1336
|
+
if (identity.brand?.countries !== void 0 && ref.brand.countries !== void 0 && [...identity.brand.countries].sort().join("\0") !== [...ref.brand.countries].sort().join("\0"))
|
|
1337
|
+
return "brand.countries";
|
|
1338
|
+
if (identity.operator !== void 0 && identity.operator !== ref.operator) return "operator";
|
|
1339
|
+
if (identity.operator_unit !== void 0 && ref.operator_unit !== void 0 && identity.operator_unit.id !== ref.operator_unit.id)
|
|
1340
|
+
return "operator_unit";
|
|
1341
|
+
if (identity.currency !== void 0 && ref.currency !== void 0 && identity.currency !== ref.currency)
|
|
1342
|
+
return "currency";
|
|
1343
|
+
if (identity.timezone !== void 0 && ref.timezone !== void 0 && identity.timezone !== ref.timezone)
|
|
1344
|
+
return "timezone";
|
|
1345
|
+
if (identity.sandbox !== void 0 && identity.sandbox !== (ref.sandbox === true)) return "sandbox";
|
|
1346
|
+
return void 0;
|
|
1347
|
+
}
|
|
1348
|
+
function assertResolvedAccountMatchesRef(resolution, ref, account, logger, implicitIdentity = STRICT_IMPLICIT_IDENTITY_POLICY) {
|
|
1330
1349
|
if (account == null) return null;
|
|
1350
|
+
if (normalizeAccountResolution(resolution) === "implicit" && ref && "brand" in ref) {
|
|
1351
|
+
const field = implicitIdentityMismatch(account, ref);
|
|
1352
|
+
if (field === void 0) return account;
|
|
1353
|
+
if (implicitIdentity.strict) return null;
|
|
1354
|
+
warnAccountReferenceDeprecation(
|
|
1355
|
+
logger,
|
|
1356
|
+
"ADCP_IMPLICIT_ACCOUNT_IDENTITY_MISMATCH",
|
|
1357
|
+
`[adcp/sdk] DEPRECATED: accounts.resolve returned an account whose ${field} does not match the supplied natural key on a resolution: 'implicit' platform. The account was accepted for compatibility; the next major release (or strictAccountReferences: true) refuses it with ACCOUNT_NOT_FOUND. Resolve by the complete natural key and return identity metadata that matches it.`,
|
|
1358
|
+
{ field, accountId: account.id }
|
|
1359
|
+
);
|
|
1360
|
+
return account;
|
|
1361
|
+
}
|
|
1331
1362
|
if (normalizeAccountResolution(resolution) !== "derived") return account;
|
|
1332
1363
|
const requestedId = refAccountId(ref);
|
|
1333
1364
|
if (requestedId === void 0 || account.id === requestedId) return account;
|
|
@@ -1358,6 +1389,7 @@ function createAdcpServerFromPlatform(platform, opts) {
|
|
|
1358
1389
|
signals: opts.legacyHandlers?.signals ?? runtimeLegacyOptions.signals
|
|
1359
1390
|
};
|
|
1360
1391
|
const runtimeOpts = opts;
|
|
1392
|
+
const implicitIdentityPolicy = { strict: runtimeOpts.strictAccountReferences === true };
|
|
1361
1393
|
const runtimeLegacyHandlers = legacyHandlers;
|
|
1362
1394
|
validatePlatform(platform, {
|
|
1363
1395
|
creative: legacyHandlers.creative,
|
|
@@ -1700,7 +1732,8 @@ function createAdcpServerFromPlatform(platform, opts) {
|
|
|
1700
1732
|
platform.accounts.resolution,
|
|
1701
1733
|
ref,
|
|
1702
1734
|
await platform.accounts.resolve(ref, toResolveCtx(ctx, ctx.toolName, ctx.input)),
|
|
1703
|
-
fwLogger
|
|
1735
|
+
fwLogger,
|
|
1736
|
+
implicitIdentityPolicy
|
|
1704
1737
|
);
|
|
1705
1738
|
resolved = account != null;
|
|
1706
1739
|
resolvedAccountId = account?.id;
|
|
@@ -1879,7 +1912,7 @@ function createAdcpServerFromPlatform(platform, opts) {
|
|
|
1879
1912
|
mergeOpts
|
|
1880
1913
|
),
|
|
1881
1914
|
accounts: (() => {
|
|
1882
|
-
const platformAccountHandlers = buildAccountHandlers(platform, ctxFor, fwLogger);
|
|
1915
|
+
const platformAccountHandlers = buildAccountHandlers(platform, ctxFor, fwLogger, implicitIdentityPolicy);
|
|
1883
1916
|
const merged = mergeHandlers(opts.accounts, platformAccountHandlers, "accounts", mergeOpts);
|
|
1884
1917
|
return guardDerivedSyncGovernance(
|
|
1885
1918
|
guardAdopterSyncAccounts(merged, platform, platformAccountHandlers, fwLogger),
|
|
@@ -1900,7 +1933,8 @@ function createAdcpServerFromPlatform(platform, opts) {
|
|
|
1900
1933
|
platform.agentRegistry,
|
|
1901
1934
|
fwLogger,
|
|
1902
1935
|
runtimeOpts.resolveSessionKey,
|
|
1903
|
-
opts.credentialPolicy
|
|
1936
|
+
opts.credentialPolicy,
|
|
1937
|
+
implicitIdentityPolicy
|
|
1904
1938
|
);
|
|
1905
1939
|
return {
|
|
1906
1940
|
...opts.customTools,
|
|
@@ -2122,7 +2156,8 @@ function createAdcpServerFromPlatform(platform, opts) {
|
|
|
2122
2156
|
platform.accounts.resolution,
|
|
2123
2157
|
accountRef,
|
|
2124
2158
|
resolvedAccount,
|
|
2125
|
-
fwLogger
|
|
2159
|
+
fwLogger,
|
|
2160
|
+
implicitIdentityPolicy
|
|
2126
2161
|
);
|
|
2127
2162
|
recordResolvedAccountMode(resolvedAccount);
|
|
2128
2163
|
const accountIsSandbox = resolvedAccount != null && isSandboxOrMockAccount(resolvedAccount);
|
|
@@ -2264,7 +2299,7 @@ function createAdcpServerFromPlatform(platform, opts) {
|
|
|
2264
2299
|
statusChange: statusChangeBus
|
|
2265
2300
|
});
|
|
2266
2301
|
}
|
|
2267
|
-
function buildTasksGetTool(platform, taskRegistry, agentRegistry, logger, resolveSessionKey, credentialPolicy) {
|
|
2302
|
+
function buildTasksGetTool(platform, taskRegistry, agentRegistry, logger, resolveSessionKey, credentialPolicy, implicitIdentityPolicy) {
|
|
2268
2303
|
const credentialPolicyPatterns = credentialPolicy === void 0 || typeof credentialPolicy === "string" ? void 0 : credentialPolicy.patterns;
|
|
2269
2304
|
const credentialPolicyError = (args, extra) => {
|
|
2270
2305
|
if (credentialPolicy === void 0) return void 0;
|
|
@@ -2389,7 +2424,8 @@ function buildTasksGetTool(platform, taskRegistry, agentRegistry, logger, resolv
|
|
|
2389
2424
|
platform.accounts.resolution,
|
|
2390
2425
|
ref,
|
|
2391
2426
|
await platform.accounts.resolve(ref, resolveCtx),
|
|
2392
|
-
logger
|
|
2427
|
+
logger,
|
|
2428
|
+
implicitIdentityPolicy
|
|
2393
2429
|
);
|
|
2394
2430
|
if (resolved) {
|
|
2395
2431
|
resolvedAccountId = resolved.id;
|
|
@@ -3196,6 +3232,7 @@ function toResolveCtx(ctx, toolName, input) {
|
|
|
3196
3232
|
{
|
|
3197
3233
|
...ctx.authInfo !== void 0 && { authInfo: ctx.authInfo },
|
|
3198
3234
|
...toolName !== void 0 && { toolName },
|
|
3235
|
+
provisioning: isAccountProvisioningTask(toolName),
|
|
3199
3236
|
...ctx.agent != null && { agent: ctx.agent },
|
|
3200
3237
|
...input != null && { input }
|
|
3201
3238
|
},
|
|
@@ -5404,7 +5441,7 @@ function enforceSyncAccountsCommercialPolicy(platform, params, resolveCtx) {
|
|
|
5404
5441
|
failedRows
|
|
5405
5442
|
};
|
|
5406
5443
|
}
|
|
5407
|
-
function buildAccountHandlers(platform, ctxFor, logger = DEFAULT_FRAMEWORK_LOGGER) {
|
|
5444
|
+
function buildAccountHandlers(platform, ctxFor, logger = DEFAULT_FRAMEWORK_LOGGER, implicitIdentityPolicy = STRICT_IMPLICIT_IDENTITY_POLICY) {
|
|
5408
5445
|
const accounts = platform.accounts;
|
|
5409
5446
|
const handlers = {};
|
|
5410
5447
|
if (accounts.upsert) {
|
|
@@ -5491,7 +5528,8 @@ function buildAccountHandlers(platform, ctxFor, logger = DEFAULT_FRAMEWORK_LOGGE
|
|
|
5491
5528
|
accounts.resolution,
|
|
5492
5529
|
accountRef,
|
|
5493
5530
|
await accounts.resolve(accountRef, resolveCtx),
|
|
5494
|
-
logger
|
|
5531
|
+
logger,
|
|
5532
|
+
implicitIdentityPolicy
|
|
5495
5533
|
);
|
|
5496
5534
|
if (!resolved) {
|
|
5497
5535
|
const suggestion = accountNotFoundSuggestion(accounts.resolution);
|
|
@@ -5528,7 +5566,8 @@ function buildAccountHandlers(platform, ctxFor, logger = DEFAULT_FRAMEWORK_LOGGE
|
|
|
5528
5566
|
accounts.resolution,
|
|
5529
5567
|
accountRef,
|
|
5530
5568
|
await accounts.resolve(accountRef, resolveCtx),
|
|
5531
|
-
logger
|
|
5569
|
+
logger,
|
|
5570
|
+
implicitIdentityPolicy
|
|
5532
5571
|
);
|
|
5533
5572
|
if (!resolved) {
|
|
5534
5573
|
const suggestion = accountNotFoundSuggestion(accounts.resolution);
|