@kya-os/create-mcpi-app 1.10.2 → 1.10.4
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/.turbo/turbo-build.log +13 -13
- package/dist/bundles/blank.js +433 -77
- package/dist/bundles/ecommerce.js +433 -77
- package/dist/bundles/hardware-world.js +433 -77
- package/dist/bundles/manifest.json +11 -11
- package/dist/bundles/mix-station.js +433 -77
- package/dist/helpers/get-package-versions.js +2 -2
- package/package.json +4 -4
|
@@ -45834,6 +45834,18 @@ var require_oauth_config_service = __commonJS({
|
|
|
45834
45834
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45835
45835
|
exports.OAuthConfigService = void 0;
|
|
45836
45836
|
var oauth_config_cache_js_1 = require_oauth_config_cache();
|
|
45837
|
+
function mapProviderSecretMetadata(raw2) {
|
|
45838
|
+
if (!raw2 || typeof raw2 !== "object")
|
|
45839
|
+
return void 0;
|
|
45840
|
+
const m3 = raw2;
|
|
45841
|
+
const metadata = {
|
|
45842
|
+
clientSecretName: m3.clientSecretName ?? m3.client_secret_name,
|
|
45843
|
+
clientIdSecretName: m3.clientIdSecretName ?? m3.client_id_secret_name,
|
|
45844
|
+
apiKeySecretName: m3.apiKeySecretName ?? m3.api_key_secret_name,
|
|
45845
|
+
clientSecretVersion: m3.clientSecretVersion ?? m3.client_secret_version
|
|
45846
|
+
};
|
|
45847
|
+
return metadata;
|
|
45848
|
+
}
|
|
45837
45849
|
var OAuthConfigService2 = class {
|
|
45838
45850
|
config;
|
|
45839
45851
|
constructor(config4) {
|
|
@@ -45907,7 +45919,16 @@ var require_oauth_config_service = __commonJS({
|
|
|
45907
45919
|
customParams: p3.customParams ?? p3.custom_params,
|
|
45908
45920
|
tokenEndpointAuthMethod: p3.tokenEndpointAuthMethod ?? p3.token_endpoint_auth_method,
|
|
45909
45921
|
responseType: p3.responseType ?? p3.response_type,
|
|
45910
|
-
grantType: p3.grantType ?? p3.grant_type
|
|
45922
|
+
grantType: p3.grantType ?? p3.grant_type,
|
|
45923
|
+
// Provider-registry secret metadata (clientSecretName etc.). REQUIRED:
|
|
45924
|
+
// OAuthService.resolveClientSecret resolves a confidential provider's
|
|
45925
|
+
// client secret from secure storage via `metadata.clientSecretName`
|
|
45926
|
+
// (the AgentShield /providers response intentionally omits the plaintext
|
|
45927
|
+
// `clientSecret`). Without mapping this field here, `metadata` is
|
|
45928
|
+
// undefined, resolveClientSecret falls back to the (absent) inline
|
|
45929
|
+
// clientSecret, and the worker sends an empty secret — token exchange
|
|
45930
|
+
// then fails with "client_id and/or client_secret incorrect".
|
|
45931
|
+
metadata: mapProviderSecretMetadata(p3.metadata)
|
|
45911
45932
|
};
|
|
45912
45933
|
}
|
|
45913
45934
|
const configuredProvider = result.data.configuredProvider ?? result.data.configured_provider ?? null;
|
|
@@ -141492,6 +141513,21 @@ var INTERNAL_PICKUP_INFO = "/_internal/pickup/info";
|
|
|
141492
141513
|
|
|
141493
141514
|
// ../mcp-i-cloudflare/dist/delegation-http/anchor-do.js
|
|
141494
141515
|
init_storage_keys();
|
|
141516
|
+
function anchorSnapshot(rec) {
|
|
141517
|
+
return {
|
|
141518
|
+
sid: rec.sid,
|
|
141519
|
+
status: rec.status,
|
|
141520
|
+
requiredScopes: rec.requiredScopes,
|
|
141521
|
+
minAssurance: rec.minAssurance,
|
|
141522
|
+
expiresAt: rec.expiresAt,
|
|
141523
|
+
createdAt: rec.createdAt,
|
|
141524
|
+
registeredAtMs: rec.registeredAtMs,
|
|
141525
|
+
issuedAtMs: rec.issuedAtMs,
|
|
141526
|
+
agentDid: rec.agentDid,
|
|
141527
|
+
audience: rec.audience,
|
|
141528
|
+
serverDid: rec.serverDid
|
|
141529
|
+
};
|
|
141530
|
+
}
|
|
141495
141531
|
var pendingBody = () => ({ status: "pending" });
|
|
141496
141532
|
var pinnedErr = () => ({ error: KYAOS_ERRORS.pickupPinned });
|
|
141497
141533
|
var invalidSessionErr = () => ({ error: KYAOS_ERRORS.invalidSession });
|
|
@@ -141499,7 +141535,12 @@ var pickupExpiredErr = () => ({ error: KYAOS_ERRORS.pickupExpired });
|
|
|
141499
141535
|
function reduceCreate(rec, input, now2) {
|
|
141500
141536
|
const i2 = input;
|
|
141501
141537
|
if (rec && now2 <= rec.expiresAt) {
|
|
141502
|
-
return {
|
|
141538
|
+
return {
|
|
141539
|
+
response: {
|
|
141540
|
+
status: 201,
|
|
141541
|
+
body: { success: true, reused: true, anchor: anchorSnapshot(rec) }
|
|
141542
|
+
}
|
|
141543
|
+
};
|
|
141503
141544
|
}
|
|
141504
141545
|
const record4 = {
|
|
141505
141546
|
sid: i2.sid,
|
|
@@ -141512,6 +141553,8 @@ function reduceCreate(rec, input, now2) {
|
|
|
141512
141553
|
agentDid: typeof i2.agentDid === "string" ? i2.agentDid : void 0,
|
|
141513
141554
|
audience: typeof i2.audience === "string" ? i2.audience : void 0,
|
|
141514
141555
|
serverDid: typeof i2.serverDid === "string" ? i2.serverDid : void 0,
|
|
141556
|
+
registeredAtMs: typeof i2.registeredAtMs === "number" ? i2.registeredAtMs : void 0,
|
|
141557
|
+
issuedAtMs: now2,
|
|
141515
141558
|
pin: i2.pin ? {
|
|
141516
141559
|
type: i2.pin.type,
|
|
141517
141560
|
valueSha256: i2.pin.valueSha256,
|
|
@@ -141519,7 +141562,13 @@ function reduceCreate(rec, input, now2) {
|
|
|
141519
141562
|
source: "challenge"
|
|
141520
141563
|
} : void 0
|
|
141521
141564
|
};
|
|
141522
|
-
return {
|
|
141565
|
+
return {
|
|
141566
|
+
record: record4,
|
|
141567
|
+
response: {
|
|
141568
|
+
status: 201,
|
|
141569
|
+
body: { success: true, anchor: anchorSnapshot(record4) }
|
|
141570
|
+
}
|
|
141571
|
+
};
|
|
141523
141572
|
}
|
|
141524
141573
|
function reducePoll(rec, holder, now2) {
|
|
141525
141574
|
if (!rec) {
|
|
@@ -141663,7 +141712,7 @@ async function handlePickupInternal(ctx, request, now2) {
|
|
|
141663
141712
|
// ../mcp-i-cloudflare/package.json
|
|
141664
141713
|
var package_default = {
|
|
141665
141714
|
name: "@kya-os/mcp-i-cloudflare",
|
|
141666
|
-
version: "1.12.
|
|
141715
|
+
version: "1.12.2",
|
|
141667
141716
|
description: "Cloudflare Workers adapter for MCP-I framework",
|
|
141668
141717
|
main: "dist/index.js",
|
|
141669
141718
|
types: "dist/index.d.ts",
|
|
@@ -141692,9 +141741,9 @@ var package_default = {
|
|
|
141692
141741
|
},
|
|
141693
141742
|
dependencies: {
|
|
141694
141743
|
"@kya-os/consent": "^0.1.41",
|
|
141695
|
-
"@kya-os/contracts": "^1.9.
|
|
141744
|
+
"@kya-os/contracts": "^1.9.1",
|
|
141696
141745
|
"@kya-os/mcp": "^1.10.1",
|
|
141697
|
-
"@kya-os/mcp-i-core": "^1.8.
|
|
141746
|
+
"@kya-os/mcp-i-core": "^1.8.2",
|
|
141698
141747
|
"@kya-os/mcp-i-runtime": "^1.0.0",
|
|
141699
141748
|
"@kya-os/provider-registry": "^0.1.7",
|
|
141700
141749
|
"@modelcontextprotocol/sdk": "^1.25.2",
|
|
@@ -141881,6 +141930,16 @@ function registrationRateLimited(now2) {
|
|
|
141881
141930
|
|
|
141882
141931
|
// ../mcp-i-cloudflare/dist/delegation-http/anchor-registration-validate.js
|
|
141883
141932
|
var DID_RE = /^did:(key|web):.+$/;
|
|
141933
|
+
var SYNTHETIC_DETECTED_DID_PREFIX = "did:web:detected:";
|
|
141934
|
+
function didIssueMessage(value) {
|
|
141935
|
+
if (typeof value !== "string" || !DID_RE.test(value)) {
|
|
141936
|
+
return "Invalid DID format. Must be did:key: or did:web:";
|
|
141937
|
+
}
|
|
141938
|
+
if (value.startsWith(SYNTHETIC_DETECTED_DID_PREFIX)) {
|
|
141939
|
+
return "Synthetic detected DIDs are not valid KYA-OS identities";
|
|
141940
|
+
}
|
|
141941
|
+
return null;
|
|
141942
|
+
}
|
|
141884
141943
|
function isRecord2(value) {
|
|
141885
141944
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
141886
141945
|
}
|
|
@@ -141914,17 +141973,17 @@ function validateChallenge(issues, raw2) {
|
|
|
141914
141973
|
checkOptionalString(issues, "challenge.pep_surface", raw2.pep_surface, 64);
|
|
141915
141974
|
checkOptionalString(issues, "challenge.verdict", raw2.verdict, 64);
|
|
141916
141975
|
checkOptionalString(issues, "challenge.challenge_pin", raw2.challenge_pin, 512);
|
|
141917
|
-
if (raw2.detected_agent_did !== void 0
|
|
141918
|
-
|
|
141919
|
-
|
|
141920
|
-
|
|
141921
|
-
}
|
|
141976
|
+
if (raw2.detected_agent_did !== void 0) {
|
|
141977
|
+
const issue4 = didIssueMessage(raw2.detected_agent_did);
|
|
141978
|
+
if (issue4) {
|
|
141979
|
+
issues.push({ path: "challenge.detected_agent_did", message: issue4 });
|
|
141980
|
+
}
|
|
141922
141981
|
}
|
|
141923
|
-
if (raw2.audience !== void 0
|
|
141924
|
-
|
|
141925
|
-
|
|
141926
|
-
|
|
141927
|
-
}
|
|
141982
|
+
if (raw2.audience !== void 0) {
|
|
141983
|
+
const issue4 = didIssueMessage(raw2.audience);
|
|
141984
|
+
if (issue4) {
|
|
141985
|
+
issues.push({ path: "challenge.audience", message: issue4 });
|
|
141986
|
+
}
|
|
141928
141987
|
}
|
|
141929
141988
|
if (issues.length > issuesBefore)
|
|
141930
141989
|
return void 0;
|
|
@@ -141946,17 +142005,21 @@ function validateRegistrationBody(raw2) {
|
|
|
141946
142005
|
}
|
|
141947
142006
|
const issues = [];
|
|
141948
142007
|
checkString(issues, "session_id", raw2.session_id, 255);
|
|
141949
|
-
|
|
142008
|
+
{
|
|
142009
|
+
const issue4 = didIssueMessage(raw2.agent_did);
|
|
142010
|
+
if (issue4)
|
|
142011
|
+
issues.push({ path: "agent_did", message: issue4 });
|
|
142012
|
+
}
|
|
142013
|
+
if (typeof raw2.project_id !== "string" || raw2.project_id.length < 1) {
|
|
141950
142014
|
issues.push({
|
|
141951
|
-
path: "
|
|
141952
|
-
message: "
|
|
142015
|
+
path: "project_id",
|
|
142016
|
+
message: "project_id must be a non-empty string"
|
|
141953
142017
|
});
|
|
141954
142018
|
}
|
|
141955
|
-
|
|
141956
|
-
if (typeof raw2.created_at !== "number" || !Number.isInteger(raw2.created_at) || raw2.created_at <= 0) {
|
|
142019
|
+
if (typeof raw2.created_at !== "number" || !Number.isInteger(raw2.created_at) || raw2.created_at <= 0 || raw2.created_at > 864e13) {
|
|
141957
142020
|
issues.push({
|
|
141958
142021
|
path: "created_at",
|
|
141959
|
-
message: "created_at must be a positive unix-ms integer"
|
|
142022
|
+
message: "created_at must be a valid positive unix-ms integer"
|
|
141960
142023
|
});
|
|
141961
142024
|
}
|
|
141962
142025
|
const clientInfo = raw2.client_info;
|
|
@@ -141969,11 +142032,10 @@ function validateRegistrationBody(raw2) {
|
|
|
141969
142032
|
checkString(issues, "client_info.name", clientInfo.name, 255);
|
|
141970
142033
|
checkOptionalString(issues, "client_info.version", clientInfo.version, 50);
|
|
141971
142034
|
}
|
|
141972
|
-
if (raw2.server_did !== void 0
|
|
141973
|
-
|
|
141974
|
-
|
|
141975
|
-
|
|
141976
|
-
});
|
|
142035
|
+
if (raw2.server_did !== void 0) {
|
|
142036
|
+
const issue4 = didIssueMessage(raw2.server_did);
|
|
142037
|
+
if (issue4)
|
|
142038
|
+
issues.push({ path: "server_did", message: issue4 });
|
|
141977
142039
|
}
|
|
141978
142040
|
const challenge = validateChallenge(issues, raw2.challenge);
|
|
141979
142041
|
if (raw2.challenge !== void 0 && typeof raw2.session_id === "string" && raw2.session_id.length < 22) {
|
|
@@ -142002,7 +142064,10 @@ function validateRegistrationBody(raw2) {
|
|
|
142002
142064
|
// ../mcp-i-cloudflare/dist/delegation-http/anchor-registration.js
|
|
142003
142065
|
var DO_INTERNAL_ORIGIN = "https://do.internal";
|
|
142004
142066
|
function isAnchorRegistrationEnabled(cfg, env2) {
|
|
142005
|
-
return cfg !== null && cfg.remoteAnchorRegistration && typeof env2.AGENTSHIELD_API_KEY === "string" && env2.AGENTSHIELD_API_KEY.length > 0
|
|
142067
|
+
return cfg !== null && cfg.remoteAnchorRegistration && typeof env2.AGENTSHIELD_API_KEY === "string" && env2.AGENTSHIELD_API_KEY.length > 0 && // No anchor store, no registration surface: getAnchorStub throws on an
|
|
142068
|
+
// unbound MCP_OBJECT, so an unbound deployment must 404 like every other
|
|
142069
|
+
// unprovisioned state instead of 500ing per request.
|
|
142070
|
+
env2.MCP_OBJECT !== void 0;
|
|
142006
142071
|
}
|
|
142007
142072
|
function deriveRegistrationSid(sessionId) {
|
|
142008
142073
|
if (isAnchorSid(sessionId))
|
|
@@ -142032,41 +142097,37 @@ async function callAnchor(env2, deps, sid, internalPath, body) {
|
|
|
142032
142097
|
}
|
|
142033
142098
|
async function ensureAnchor(env2, cfg, deps, sid, challenge, session) {
|
|
142034
142099
|
const pin = challenge.challengePin && cfg.allowUnverifiedKeyidHolders ? { type: "keyid", valueSha256: sha256Hex(challenge.challengePin) } : void 0;
|
|
142035
|
-
const
|
|
142036
|
-
|
|
142037
|
-
|
|
142038
|
-
|
|
142039
|
-
|
|
142040
|
-
delegationExpiresInS: cfg.delegationExpiresInS,
|
|
142041
|
-
agentDid: challenge.detectedAgentDid ?? session.agentDid,
|
|
142042
|
-
// Cross-resource claim inputs (drive the minted VC's aud / server_did —
|
|
142043
|
-
// see consent-anchor-bridge's withCrossResourceClaims).
|
|
142044
|
-
...challenge.audience ? { audience: challenge.audience } : {},
|
|
142045
|
-
...session.serverDid ? { serverDid: session.serverDid } : {},
|
|
142046
|
-
...pin ? { pin } : {}
|
|
142047
|
-
});
|
|
142048
|
-
if (created.status !== 201) {
|
|
142049
|
-
return {
|
|
142050
|
-
error: errorResponse(502, "anchor_unavailable", "The anchor store did not accept the registration")
|
|
142051
|
-
};
|
|
142052
|
-
}
|
|
142053
|
-
let reused = false;
|
|
142100
|
+
const anchorUnavailable = {
|
|
142101
|
+
error: errorResponse(502, "anchor_unavailable", "The anchor store did not accept the registration")
|
|
142102
|
+
};
|
|
142103
|
+
let created;
|
|
142104
|
+
let body;
|
|
142054
142105
|
try {
|
|
142055
|
-
|
|
142056
|
-
|
|
142106
|
+
created = await callAnchor(env2, deps, sid, INTERNAL_PICKUP_CREATE, {
|
|
142107
|
+
sid,
|
|
142108
|
+
requiredScopes: challenge.requiredScopes,
|
|
142109
|
+
pollIntervalS: cfg.pollIntervalS,
|
|
142110
|
+
anchorTtlS: cfg.anchorTtlS,
|
|
142111
|
+
delegationExpiresInS: cfg.delegationExpiresInS,
|
|
142112
|
+
agentDid: challenge.detectedAgentDid ?? session.agentDid,
|
|
142113
|
+
registeredAtMs: session.registeredAtMs,
|
|
142114
|
+
// Cross-resource claim inputs (drive the minted VC's aud / server_did —
|
|
142115
|
+
// see consent-anchor-bridge's withCrossResourceClaims).
|
|
142116
|
+
...challenge.audience ? { audience: challenge.audience } : {},
|
|
142117
|
+
...session.serverDid ? { serverDid: session.serverDid } : {},
|
|
142118
|
+
...pin ? { pin } : {}
|
|
142119
|
+
});
|
|
142120
|
+
if (created.status !== 201)
|
|
142121
|
+
return anchorUnavailable;
|
|
142122
|
+
body = await created.json();
|
|
142123
|
+
} catch (error87) {
|
|
142124
|
+
console.warn(`[kya-http] anchor create failed (sid=${sid}):`, error87 instanceof Error ? error87.message : String(error87));
|
|
142125
|
+
return anchorUnavailable;
|
|
142057
142126
|
}
|
|
142058
|
-
|
|
142059
|
-
|
|
142060
|
-
});
|
|
142061
|
-
if (readBack.status !== 200) {
|
|
142062
|
-
return {
|
|
142063
|
-
error: errorResponse(502, "anchor_unavailable", "The registered anchor could not be read back")
|
|
142064
|
-
};
|
|
142127
|
+
if (!body.anchor || !Array.isArray(body.anchor.requiredScopes)) {
|
|
142128
|
+
return anchorUnavailable;
|
|
142065
142129
|
}
|
|
142066
|
-
return {
|
|
142067
|
-
isNew: !reused,
|
|
142068
|
-
snapshot: await readBack.json()
|
|
142069
|
-
};
|
|
142130
|
+
return { isNew: body.reused !== true, snapshot: body.anchor };
|
|
142070
142131
|
}
|
|
142071
142132
|
async function handleAnchorRegistration(c, env2, cfg, deps) {
|
|
142072
142133
|
if (!registrarAuthorized(env2, c.req.header("Authorization"))) {
|
|
@@ -142092,9 +142153,13 @@ async function handleAnchorRegistration(c, env2, cfg, deps) {
|
|
|
142092
142153
|
return errorResponse(401, "unauthorized", "This endpoint only accepts challenge registration");
|
|
142093
142154
|
}
|
|
142094
142155
|
const sid = deriveRegistrationSid(validated.input.sessionId);
|
|
142156
|
+
if (!challenge.audience) {
|
|
142157
|
+
console.warn(`[kya-http] external registration without challenge.audience (sid=${sid}): the minted credential will FAIL an org-pinned \xA74.3 audience gate; cross-resource use requires the registrar to send challenge.audience`);
|
|
142158
|
+
}
|
|
142095
142159
|
const anchor = await ensureAnchor(env2, cfg, deps, sid, challenge, {
|
|
142096
142160
|
agentDid: validated.input.agentDid,
|
|
142097
|
-
serverDid: validated.input.serverDid
|
|
142161
|
+
serverDid: validated.input.serverDid,
|
|
142162
|
+
registeredAtMs: validated.input.createdAt
|
|
142098
142163
|
});
|
|
142099
142164
|
if ("error" in anchor)
|
|
142100
142165
|
return anchor.error;
|
|
@@ -142118,17 +142183,24 @@ async function handleAnchorRegistration(c, env2, cfg, deps) {
|
|
|
142118
142183
|
console.warn(`[kya-http] registration challenge_proof signing failed (sid=${sid}):`, error87 instanceof Error ? error87.message : String(error87));
|
|
142119
142184
|
return errorResponse(502, "proof_unavailable", "The challenge proof could not be signed");
|
|
142120
142185
|
}
|
|
142186
|
+
const createdAtMs = anchor.snapshot.registeredAtMs ?? validated.input.createdAt;
|
|
142187
|
+
const issuedAtMs = anchor.snapshot.issuedAtMs ?? Date.now();
|
|
142121
142188
|
return new Response(JSON.stringify({
|
|
142122
142189
|
success: true,
|
|
142123
142190
|
data: {
|
|
142124
142191
|
session_id: sid,
|
|
142125
142192
|
registered: true,
|
|
142126
|
-
created_at: new Date(
|
|
142193
|
+
created_at: new Date(createdAtMs).toISOString(),
|
|
142127
142194
|
challenge: {
|
|
142128
142195
|
consent_uri: consentUri,
|
|
142129
142196
|
challenge_proof: challengeProof,
|
|
142130
142197
|
required_scopes: anchor.snapshot.requiredScopes,
|
|
142131
|
-
issued_at:
|
|
142198
|
+
issued_at: issuedAtMs,
|
|
142199
|
+
// ADDITIVE diagnostic (not in the frozen conformance key set, ignored
|
|
142200
|
+
// by both existing parsers): whether the minted credential will carry
|
|
142201
|
+
// the §4.3 cross-resource claims. False means no audience was
|
|
142202
|
+
// registered — the credential only self-verifies at this worker.
|
|
142203
|
+
cross_resource: typeof anchor.snapshot.audience === "string"
|
|
142132
142204
|
}
|
|
142133
142205
|
}
|
|
142134
142206
|
}), {
|
|
@@ -147376,6 +147448,190 @@ async function handlePickupGet(c, env2, cfg) {
|
|
|
147376
147448
|
init_dist2();
|
|
147377
147449
|
init_crypto();
|
|
147378
147450
|
init_storage();
|
|
147451
|
+
|
|
147452
|
+
// ../mcp-i-cloudflare/dist/delegation-http/credential-consent.js
|
|
147453
|
+
function readString(entry, camel, snake) {
|
|
147454
|
+
const value = entry[camel] ?? entry[snake];
|
|
147455
|
+
return typeof value === "string" ? value : void 0;
|
|
147456
|
+
}
|
|
147457
|
+
function readRecord(entry, camel, snake) {
|
|
147458
|
+
const value = entry[camel] ?? entry[snake];
|
|
147459
|
+
return value && typeof value === "object" ? value : void 0;
|
|
147460
|
+
}
|
|
147461
|
+
function isCredentialTyped(entry) {
|
|
147462
|
+
return !!entry && (entry.type === "password" || entry.type === "credential") && entry.configured !== false;
|
|
147463
|
+
}
|
|
147464
|
+
function buildSuccessCheck(raw2) {
|
|
147465
|
+
if (!raw2)
|
|
147466
|
+
return void 0;
|
|
147467
|
+
const path = typeof raw2.path === "string" ? raw2.path : void 0;
|
|
147468
|
+
const expectedValue = raw2.expectedValue ?? raw2.expected_value;
|
|
147469
|
+
if (!path || expectedValue === void 0)
|
|
147470
|
+
return void 0;
|
|
147471
|
+
if (typeof expectedValue !== "string" && typeof expectedValue !== "boolean" && typeof expectedValue !== "number") {
|
|
147472
|
+
return void 0;
|
|
147473
|
+
}
|
|
147474
|
+
return { path, expectedValue };
|
|
147475
|
+
}
|
|
147476
|
+
function buildCredentialConfig(entry) {
|
|
147477
|
+
const authEndpoint = readString(entry, "authEndpoint", "auth_endpoint");
|
|
147478
|
+
const requestBodyTemplate = readRecord(entry, "requestBodyTemplate", "request_body_template");
|
|
147479
|
+
const rawResponseFields = readRecord(entry, "responseFields", "response_fields");
|
|
147480
|
+
if (!authEndpoint || !requestBodyTemplate || !rawResponseFields)
|
|
147481
|
+
return null;
|
|
147482
|
+
const sessionToken = readString(rawResponseFields, "sessionToken", "session_token");
|
|
147483
|
+
if (!sessionToken)
|
|
147484
|
+
return null;
|
|
147485
|
+
const responseFields = {
|
|
147486
|
+
sessionToken,
|
|
147487
|
+
userId: readString(rawResponseFields, "userId", "user_id"),
|
|
147488
|
+
userEmail: readString(rawResponseFields, "userEmail", "user_email"),
|
|
147489
|
+
userDisplayName: readString(rawResponseFields, "userDisplayName", "user_display_name"),
|
|
147490
|
+
expiresIn: readString(rawResponseFields, "expiresIn", "expires_in")
|
|
147491
|
+
};
|
|
147492
|
+
const successCheck = buildSuccessCheck(readRecord(entry, "successCheck", "success_check"));
|
|
147493
|
+
const headers = readRecord(entry, "headers", "headers");
|
|
147494
|
+
const tokenUsage = readString(entry, "tokenUsage", "token_usage");
|
|
147495
|
+
const tokenHeader = readString(entry, "tokenHeader", "token_header");
|
|
147496
|
+
const cookieFormat = readString(entry, "cookieFormat", "cookie_format");
|
|
147497
|
+
return {
|
|
147498
|
+
// The handler ignores `type`, but the contract's discriminant is "credential".
|
|
147499
|
+
type: "credential",
|
|
147500
|
+
displayName: readString(entry, "displayName", "display_name"),
|
|
147501
|
+
authEndpoint,
|
|
147502
|
+
requestBodyTemplate,
|
|
147503
|
+
responseFields,
|
|
147504
|
+
...successCheck ? { successCheck } : {},
|
|
147505
|
+
...headers ? { headers } : {},
|
|
147506
|
+
...tokenUsage ? { tokenUsage } : {},
|
|
147507
|
+
...tokenHeader ? { tokenHeader } : {},
|
|
147508
|
+
...cookieFormat ? { cookieFormat } : {}
|
|
147509
|
+
};
|
|
147510
|
+
}
|
|
147511
|
+
async function resolveAnchorCredentialProvider(env2, _scopes) {
|
|
147512
|
+
const apiKey = env2.AGENTSHIELD_API_KEY;
|
|
147513
|
+
const projectId = env2.AGENTSHIELD_PROJECT_ID;
|
|
147514
|
+
if (!apiKey || !projectId)
|
|
147515
|
+
return { status: "none" };
|
|
147516
|
+
const agentShieldUrl = env2.AGENTSHIELD_API_URL || DEFAULT_AGENTSHIELD_URL;
|
|
147517
|
+
let providersMap;
|
|
147518
|
+
let configuredProvider;
|
|
147519
|
+
try {
|
|
147520
|
+
const response = await fetch(`${agentShieldUrl}/api/v1/bouncer/projects/${encodeURIComponent(projectId)}/providers`, {
|
|
147521
|
+
method: "GET",
|
|
147522
|
+
headers: {
|
|
147523
|
+
Authorization: `Bearer ${apiKey}`,
|
|
147524
|
+
"Content-Type": "application/json"
|
|
147525
|
+
}
|
|
147526
|
+
});
|
|
147527
|
+
if (!response.ok)
|
|
147528
|
+
return { status: "unavailable" };
|
|
147529
|
+
const body = await response.json();
|
|
147530
|
+
if (body.success !== true || !body.data || typeof body.data.providers !== "object" || body.data.providers === null) {
|
|
147531
|
+
return { status: "unavailable" };
|
|
147532
|
+
}
|
|
147533
|
+
providersMap = body.data.providers;
|
|
147534
|
+
configuredProvider = body.data.configuredProvider ?? body.data.configured_provider ?? null;
|
|
147535
|
+
} catch {
|
|
147536
|
+
return { status: "unavailable" };
|
|
147537
|
+
}
|
|
147538
|
+
const credentialIds = Object.keys(providersMap).filter((id) => isCredentialTyped(providersMap[id]));
|
|
147539
|
+
if (credentialIds.length === 0)
|
|
147540
|
+
return { status: "none" };
|
|
147541
|
+
const chosenId = configuredProvider && isCredentialTyped(providersMap[configuredProvider]) ? configuredProvider : credentialIds.length === 1 ? credentialIds[0] : null;
|
|
147542
|
+
if (!chosenId)
|
|
147543
|
+
return { status: "unavailable" };
|
|
147544
|
+
const config4 = buildCredentialConfig(providersMap[chosenId]);
|
|
147545
|
+
if (!config4)
|
|
147546
|
+
return { status: "unavailable" };
|
|
147547
|
+
return {
|
|
147548
|
+
status: "credential",
|
|
147549
|
+
provider: {
|
|
147550
|
+
providerId: chosenId,
|
|
147551
|
+
displayName: config4.displayName || chosenId,
|
|
147552
|
+
config: config4
|
|
147553
|
+
}
|
|
147554
|
+
};
|
|
147555
|
+
}
|
|
147556
|
+
async function resolveCredentialIdentity(env2, params) {
|
|
147557
|
+
const agentShieldUrl = env2.AGENTSHIELD_API_URL || DEFAULT_AGENTSHIELD_URL;
|
|
147558
|
+
const apiKey = env2.AGENTSHIELD_API_KEY;
|
|
147559
|
+
if (!apiKey)
|
|
147560
|
+
return { success: false };
|
|
147561
|
+
try {
|
|
147562
|
+
const response = await fetch(`${agentShieldUrl}/api/v1/bouncer/identity/resolve`, {
|
|
147563
|
+
method: "POST",
|
|
147564
|
+
headers: {
|
|
147565
|
+
"X-API-Key": apiKey,
|
|
147566
|
+
"Content-Type": "application/json"
|
|
147567
|
+
},
|
|
147568
|
+
body: JSON.stringify({
|
|
147569
|
+
project_id: params.projectId,
|
|
147570
|
+
credential_result: {
|
|
147571
|
+
provider: params.provider,
|
|
147572
|
+
user_id: params.userId,
|
|
147573
|
+
email: params.userEmail,
|
|
147574
|
+
name: params.userDisplayName
|
|
147575
|
+
}
|
|
147576
|
+
})
|
|
147577
|
+
});
|
|
147578
|
+
if (!response.ok)
|
|
147579
|
+
return { success: false };
|
|
147580
|
+
const data = await response.json();
|
|
147581
|
+
const userDid = data?.data?.user_did;
|
|
147582
|
+
return userDid ? { success: true, userDid } : { success: false };
|
|
147583
|
+
} catch {
|
|
147584
|
+
return { success: false };
|
|
147585
|
+
}
|
|
147586
|
+
}
|
|
147587
|
+
function sidToDelegationUuid(sid) {
|
|
147588
|
+
const h5 = sha256Hex(sid).slice(0, 32).split("");
|
|
147589
|
+
h5[12] = "4";
|
|
147590
|
+
h5[16] = (parseInt(h5[16], 16) & 3 | 8).toString(16);
|
|
147591
|
+
const s5 = h5.join("");
|
|
147592
|
+
return `${s5.slice(0, 8)}-${s5.slice(8, 12)}-${s5.slice(12, 16)}-${s5.slice(16, 20)}-${s5.slice(20, 32)}`;
|
|
147593
|
+
}
|
|
147594
|
+
async function notifyDelegation(env2, params) {
|
|
147595
|
+
const apiKey = env2.AGENTSHIELD_API_KEY;
|
|
147596
|
+
const projectId = env2.AGENTSHIELD_PROJECT_ID;
|
|
147597
|
+
if (!apiKey || !projectId)
|
|
147598
|
+
return;
|
|
147599
|
+
const agentShieldUrl = env2.AGENTSHIELD_API_URL || DEFAULT_AGENTSHIELD_URL;
|
|
147600
|
+
try {
|
|
147601
|
+
const response = await fetch(`${agentShieldUrl}/api/v1/bouncer/delegations/notify`, {
|
|
147602
|
+
method: "POST",
|
|
147603
|
+
headers: {
|
|
147604
|
+
"X-API-Key": apiKey,
|
|
147605
|
+
"Content-Type": "application/json"
|
|
147606
|
+
},
|
|
147607
|
+
body: JSON.stringify({
|
|
147608
|
+
delegation_id: sidToDelegationUuid(params.sid),
|
|
147609
|
+
agent_did: params.agentDid,
|
|
147610
|
+
agent_name: params.agentName || void 0,
|
|
147611
|
+
user_did: params.userDid,
|
|
147612
|
+
user_id: params.userId || void 0,
|
|
147613
|
+
user_identifier: params.userIdentifier || void 0,
|
|
147614
|
+
scopes: params.scopes,
|
|
147615
|
+
provider: params.provider,
|
|
147616
|
+
project_id: projectId,
|
|
147617
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
147618
|
+
expires_at: params.expiresAt || void 0,
|
|
147619
|
+
metadata: {
|
|
147620
|
+
source: "mcp-i-anchor-consent",
|
|
147621
|
+
sid: params.sid,
|
|
147622
|
+
...params.metadata
|
|
147623
|
+
}
|
|
147624
|
+
})
|
|
147625
|
+
});
|
|
147626
|
+
if (!response.ok) {
|
|
147627
|
+
console.warn(`[kya-http] delegation notify failed (non-blocking): ${response.status} sid=${params.sid}`);
|
|
147628
|
+
}
|
|
147629
|
+
} catch (error87) {
|
|
147630
|
+
console.warn(`[kya-http] delegation notify failed (non-blocking): ${error87 instanceof Error ? error87.message : String(error87)} sid=${params.sid}`);
|
|
147631
|
+
}
|
|
147632
|
+
}
|
|
147633
|
+
|
|
147634
|
+
// ../mcp-i-cloudflare/dist/delegation-http/consent-anchor-bridge.js
|
|
147379
147635
|
var DO_INTERNAL_ORIGIN2 = "https://do.internal";
|
|
147380
147636
|
async function callAnchor2(env2, sid, internalPath, body) {
|
|
147381
147637
|
const stub = getAnchorStub(env2, sid);
|
|
@@ -147445,6 +147701,36 @@ function approveFormPage(sid, info, csrfToken) {
|
|
|
147445
147701
|
</form>
|
|
147446
147702
|
</main>`);
|
|
147447
147703
|
}
|
|
147704
|
+
function credentialFieldNames(provider) {
|
|
147705
|
+
const names = [];
|
|
147706
|
+
for (const template of Object.values(provider.config.requestBodyTemplate)) {
|
|
147707
|
+
const match2 = /\{\{(\w+)\}\}/.exec(template);
|
|
147708
|
+
if (match2 && !names.includes(match2[1]))
|
|
147709
|
+
names.push(match2[1]);
|
|
147710
|
+
}
|
|
147711
|
+
return names.length > 0 ? names : ["email", "password"];
|
|
147712
|
+
}
|
|
147713
|
+
function credentialFormPage(sid, info, provider, csrfToken) {
|
|
147714
|
+
const scopeItems = info.requiredScopes.length > 0 ? info.requiredScopes.map((s5) => `<li class="kya-scope-item">${escapeHtml2(s5)}</li>`).join("") : `<li class="kya-scope-item">No specific permissions required.</li>`;
|
|
147715
|
+
const fieldInputs = credentialFieldNames(provider).map((name16) => {
|
|
147716
|
+
const isSecret = /pass|secret|token|pin/i.test(name16);
|
|
147717
|
+
const label = name16.charAt(0).toUpperCase() + name16.slice(1);
|
|
147718
|
+
return `<label class="kya-field-label" for="kya-field-${escapeHtml2(name16)}">${escapeHtml2(label)}</label>
|
|
147719
|
+
<input class="kya-field-input" id="kya-field-${escapeHtml2(name16)}" name="${escapeHtml2(name16)}" type="${isSecret ? "password" : "text"}" autocomplete="${isSecret ? "current-password" : "username"}" required>`;
|
|
147720
|
+
}).join("");
|
|
147721
|
+
return page("Permission Request", `<main class="kya-consent">
|
|
147722
|
+
<h1>Sign in to authorize</h1>
|
|
147723
|
+
<p class="kya-provider-name">${escapeHtml2(provider.displayName)}</p>
|
|
147724
|
+
<p class="kya-permissions-header">This request needs the following permissions:</p>
|
|
147725
|
+
<ul class="kya-permissions-list">${scopeItems}</ul>
|
|
147726
|
+
<form method="POST" action="/consent/approve?sid=${encodeURIComponent(sid)}">
|
|
147727
|
+
<input type="hidden" name="sid" value="${escapeHtml2(sid)}">
|
|
147728
|
+
<input type="hidden" name="csrf_token" value="${escapeHtml2(csrfToken)}">
|
|
147729
|
+
${fieldInputs}
|
|
147730
|
+
<button type="submit" class="kya-consent-allow">Sign in & allow</button>
|
|
147731
|
+
</form>
|
|
147732
|
+
</main>`);
|
|
147733
|
+
}
|
|
147448
147734
|
function base64UrlEncodeBytes(bytes) {
|
|
147449
147735
|
return btoa(String.fromCharCode(...bytes)).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
147450
147736
|
}
|
|
@@ -147549,7 +147835,11 @@ async function mintDelegationVcJwt(env2, sid, info, expiresInS) {
|
|
|
147549
147835
|
constraints: {
|
|
147550
147836
|
scopes: info.requiredScopes,
|
|
147551
147837
|
notBefore: nowS,
|
|
147552
|
-
notAfter: nowS + expiresInS
|
|
147838
|
+
notAfter: nowS + expiresInS,
|
|
147839
|
+
// §11.7 outer===inner audience invariant (checkpoint's own mints bind the
|
|
147840
|
+
// audience in BOTH the JWT aud and constraints.audience): set the inner
|
|
147841
|
+
// half for cross-resource anchors so verifiers reading either slot agree.
|
|
147842
|
+
...info.audience ? { audience: info.audience } : {}
|
|
147553
147843
|
},
|
|
147554
147844
|
signature: "",
|
|
147555
147845
|
status: "active",
|
|
@@ -147564,7 +147854,10 @@ async function mintDelegationVcJwt(env2, sid, info, expiresInS) {
|
|
|
147564
147854
|
const signingInput = withCrossResourceClaims(unsigned, info, sid);
|
|
147565
147855
|
const signatureBytes = await cryptoProvider.sign(new TextEncoder().encode(signingInput), signingPrivateKey);
|
|
147566
147856
|
const signature = base64urlEncodeFromBytes2(signatureBytes);
|
|
147567
|
-
return
|
|
147857
|
+
return {
|
|
147858
|
+
vcJwt: completeVCJWT2(signingInput, signature),
|
|
147859
|
+
subjectDid: agentDid
|
|
147860
|
+
};
|
|
147568
147861
|
}
|
|
147569
147862
|
async function handleAnchorConsentGet(c, sid, env2, _cfg) {
|
|
147570
147863
|
const infoResponse = await callAnchor2(env2, sid, INTERNAL_PICKUP_INFO, {
|
|
@@ -147579,12 +147872,16 @@ async function handleAnchorConsentGet(c, sid, env2, _cfg) {
|
|
|
147579
147872
|
}
|
|
147580
147873
|
const info = await infoResponse.json();
|
|
147581
147874
|
const csrfToken = await mintCsrfToken(env2, sid);
|
|
147875
|
+
const resolution = await resolveAnchorCredentialProvider(env2, info.requiredScopes);
|
|
147876
|
+
if (resolution.status === "credential") {
|
|
147877
|
+
return htmlResponse(credentialFormPage(sid, info, resolution.provider, csrfToken), 200);
|
|
147878
|
+
}
|
|
147582
147879
|
return htmlResponse(approveFormPage(sid, info, csrfToken), 200);
|
|
147583
147880
|
}
|
|
147584
147881
|
async function handleAnchorConsentApprove(c, sid, env2, cfg) {
|
|
147882
|
+
const bodyFields = await readBodyFields(c);
|
|
147585
147883
|
if (!isTestConsentMode(env2)) {
|
|
147586
|
-
const
|
|
147587
|
-
const valid = await validateCsrfToken(env2, sid, csrfToken);
|
|
147884
|
+
const valid = await validateCsrfToken(env2, sid, bodyFields.csrf_token);
|
|
147588
147885
|
if (!valid) {
|
|
147589
147886
|
return htmlResponse(page("Authorization failed", `<main class="kya-consent-failed"><h1>Authorization failed</h1><p>Invalid or missing security token. Please reload and try again.</p></main>`), 403);
|
|
147590
147887
|
}
|
|
@@ -147601,9 +147898,46 @@ async function handleAnchorConsentApprove(c, sid, env2, cfg) {
|
|
|
147601
147898
|
return approvalFailedPage("This authorization request could not be loaded. Please start over.", 502);
|
|
147602
147899
|
}
|
|
147603
147900
|
const info = await infoResponse.json();
|
|
147901
|
+
const resolution = await resolveAnchorCredentialProvider(env2, info.requiredScopes);
|
|
147902
|
+
if (resolution.status === "unavailable") {
|
|
147903
|
+
return approvalFailedPage("We could not verify the sign-in requirement for this request. Please try again.", 503);
|
|
147904
|
+
}
|
|
147905
|
+
const provider = resolution.status === "credential" ? resolution.provider : null;
|
|
147906
|
+
let authorizedUser = null;
|
|
147907
|
+
if (provider) {
|
|
147908
|
+
const credentials = {};
|
|
147909
|
+
for (const name16 of credentialFieldNames(provider)) {
|
|
147910
|
+
if (bodyFields[name16] !== void 0)
|
|
147911
|
+
credentials[name16] = bodyFields[name16];
|
|
147912
|
+
}
|
|
147913
|
+
const handler = createCredentialAuthHandler({
|
|
147914
|
+
fetch: (...args) => globalThis.fetch(...args),
|
|
147915
|
+
logger: (msg, data) => console.debug(`[kya-http] ${msg}`, data)
|
|
147916
|
+
});
|
|
147917
|
+
const authResult = await handler.authenticate(provider.config, credentials);
|
|
147918
|
+
if (!authResult.success) {
|
|
147919
|
+
return htmlResponse(page("Sign-in failed", `<main class="kya-consent-failed"><h1>Sign-in failed</h1><p>${escapeHtml2(authResult.error || "Those credentials were not accepted. Please try again.")}</p></main>`), 401);
|
|
147920
|
+
}
|
|
147921
|
+
const identity = await resolveCredentialIdentity(env2, {
|
|
147922
|
+
projectId: env2.AGENTSHIELD_PROJECT_ID || "",
|
|
147923
|
+
provider: provider.providerId,
|
|
147924
|
+
userId: authResult.userId || "unknown",
|
|
147925
|
+
userEmail: authResult.userEmail,
|
|
147926
|
+
userDisplayName: authResult.userDisplayName
|
|
147927
|
+
});
|
|
147928
|
+
if (!identity.success || !identity.userDid) {
|
|
147929
|
+
return approvalFailedPage("We signed you in but could not resolve your identity. Please start over.", 500);
|
|
147930
|
+
}
|
|
147931
|
+
authorizedUser = {
|
|
147932
|
+
userDid: identity.userDid,
|
|
147933
|
+
userId: authResult.userId,
|
|
147934
|
+
userEmail: authResult.userEmail
|
|
147935
|
+
};
|
|
147936
|
+
}
|
|
147604
147937
|
let vcJwt;
|
|
147938
|
+
let subjectDid;
|
|
147605
147939
|
try {
|
|
147606
|
-
vcJwt = await mintDelegationVcJwt(env2, sid, info, cfg.delegationExpiresInS);
|
|
147940
|
+
({ vcJwt, subjectDid } = await mintDelegationVcJwt(env2, sid, info, cfg.delegationExpiresInS));
|
|
147607
147941
|
} catch (error87) {
|
|
147608
147942
|
console.warn(`[kya-http] delegation mint failed (sid=${sid}):`, error87 instanceof Error ? error87.message : String(error87));
|
|
147609
147943
|
return approvalFailedPage("We could not complete the authorization. Please start over.", 500);
|
|
@@ -147621,24 +147955,46 @@ async function handleAnchorConsentApprove(c, sid, env2, cfg) {
|
|
|
147621
147955
|
if (!approveResponse.ok) {
|
|
147622
147956
|
return approvalFailedPage("We could not complete the authorization. Please start over.", 502);
|
|
147623
147957
|
}
|
|
147958
|
+
if (authorizedUser && provider) {
|
|
147959
|
+
const report = notifyDelegation(env2, {
|
|
147960
|
+
sid,
|
|
147961
|
+
agentDid: subjectDid,
|
|
147962
|
+
userDid: authorizedUser.userDid,
|
|
147963
|
+
userId: authorizedUser.userId,
|
|
147964
|
+
userIdentifier: authorizedUser.userEmail,
|
|
147965
|
+
scopes: info.requiredScopes,
|
|
147966
|
+
provider: provider.providerId,
|
|
147967
|
+
// Record the same expiry the VC was minted with, matching the OAuth path.
|
|
147968
|
+
expiresAt: new Date(Date.now() + cfg.delegationExpiresInS * 1e3).toISOString()
|
|
147969
|
+
});
|
|
147970
|
+
const execCtx = c.executionCtx;
|
|
147971
|
+
execCtx?.waitUntil?.(report);
|
|
147972
|
+
}
|
|
147624
147973
|
return successPage();
|
|
147625
147974
|
}
|
|
147626
|
-
async function
|
|
147975
|
+
async function readBodyFields(c) {
|
|
147976
|
+
const out = {};
|
|
147627
147977
|
const raw2 = c.req?.raw;
|
|
147628
147978
|
if (!raw2)
|
|
147629
|
-
return
|
|
147979
|
+
return out;
|
|
147630
147980
|
try {
|
|
147631
147981
|
const contentType2 = raw2.headers.get("Content-Type") || "";
|
|
147632
147982
|
if (contentType2.includes("application/json")) {
|
|
147633
|
-
const body = await raw2.
|
|
147634
|
-
const
|
|
147635
|
-
|
|
147983
|
+
const body = await raw2.json();
|
|
147984
|
+
for (const [key, value] of Object.entries(body)) {
|
|
147985
|
+
if (typeof value === "string")
|
|
147986
|
+
out[key] = value;
|
|
147987
|
+
}
|
|
147988
|
+
return out;
|
|
147636
147989
|
}
|
|
147637
|
-
const form = await raw2.
|
|
147638
|
-
|
|
147639
|
-
|
|
147990
|
+
const form = await raw2.formData();
|
|
147991
|
+
form.forEach((value, key) => {
|
|
147992
|
+
if (typeof value === "string")
|
|
147993
|
+
out[key] = value;
|
|
147994
|
+
});
|
|
147995
|
+
return out;
|
|
147640
147996
|
} catch {
|
|
147641
|
-
return
|
|
147997
|
+
return out;
|
|
147642
147998
|
}
|
|
147643
147999
|
}
|
|
147644
148000
|
|