@astrasyncai/verification-gateway 2.1.0 → 2.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +64 -30
- package/dist/adapter-interface/interface.d.mts +2 -2
- package/dist/adapter-interface/interface.d.ts +2 -2
- package/dist/adapters/express.d.mts +2 -2
- package/dist/adapters/express.d.ts +2 -2
- package/dist/adapters/express.js +74 -95
- package/dist/adapters/express.js.map +1 -1
- package/dist/adapters/express.mjs +74 -95
- package/dist/adapters/express.mjs.map +1 -1
- package/dist/adapters/nextjs.d.mts +2 -2
- package/dist/adapters/nextjs.d.ts +2 -2
- package/dist/adapters/nextjs.js +74 -115
- package/dist/adapters/nextjs.js.map +1 -1
- package/dist/adapters/nextjs.mjs +74 -115
- package/dist/adapters/nextjs.mjs.map +1 -1
- package/dist/adapters/sdk.d.mts +2 -2
- package/dist/adapters/sdk.d.ts +2 -2
- package/dist/adapters/sdk.js +56 -55
- package/dist/adapters/sdk.js.map +1 -1
- package/dist/adapters/sdk.mjs +56 -55
- package/dist/adapters/sdk.mjs.map +1 -1
- package/dist/agent/index.d.mts +2 -2
- package/dist/agent/index.d.ts +2 -2
- package/dist/agent/index.js +68 -2
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/index.mjs +66 -2
- package/dist/agent/index.mjs.map +1 -1
- package/dist/browser/background.js +56 -55
- package/dist/browser/background.js.map +1 -1
- package/dist/browser/background.mjs +56 -55
- package/dist/browser/background.mjs.map +1 -1
- package/dist/browser/browser-adapter.d.mts +2 -2
- package/dist/browser/browser-adapter.d.ts +2 -2
- package/dist/cli/index.d.mts +2 -2
- package/dist/cli/index.d.ts +2 -2
- package/dist/cursor/cursor-adapter.d.mts +2 -2
- package/dist/cursor/cursor-adapter.d.ts +2 -2
- package/dist/cursor/extension.d.mts +2 -2
- package/dist/cursor/extension.d.ts +2 -2
- package/dist/cursor/extension.js +56 -55
- package/dist/cursor/extension.js.map +1 -1
- package/dist/cursor/extension.mjs +56 -55
- package/dist/cursor/extension.mjs.map +1 -1
- package/dist/{express-Bcl-uBUE.d.ts → express-BtKlLI8U.d.ts} +2 -2
- package/dist/{express-CtwDIZyF.d.mts → express-DgwpS8Ha.d.mts} +2 -2
- package/dist/gateway/gateway.d.mts +2 -2
- package/dist/gateway/gateway.d.ts +2 -2
- package/dist/gateway/gateway.js +56 -55
- package/dist/gateway/gateway.js.map +1 -1
- package/dist/gateway/gateway.mjs +56 -55
- package/dist/gateway/gateway.mjs.map +1 -1
- package/dist/git-trigger/git-hooks.d.mts +2 -2
- package/dist/git-trigger/git-hooks.d.ts +2 -2
- package/dist/{index-BY8yQ8N8.d.mts → index-AzhK20t0.d.mts} +46 -3
- package/dist/{index-CME6r4uH.d.ts → index-Ba0Lvsjo.d.ts} +1 -1
- package/dist/{index-3NRaBNvp.d.mts → index-BaxpmTGA.d.mts} +1 -1
- package/dist/{index-CtYSYwn3.d.ts → index-DpJS1JEI.d.ts} +46 -3
- package/dist/index.d.mts +7 -7
- package/dist/index.d.ts +7 -7
- package/dist/index.js +158 -117
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +158 -117
- package/dist/index.mjs.map +1 -1
- package/dist/local-evaluator/evaluator.d.mts +2 -2
- package/dist/local-evaluator/evaluator.d.ts +2 -2
- package/dist/{nextjs-CEldnIJ9.d.ts → nextjs-B2kg19c1.d.ts} +1 -1
- package/dist/{nextjs-BQyMCSx_.d.mts → nextjs-ZymQ8jDh.d.mts} +1 -1
- package/dist/{sdk-BhvuJSrH.d.mts → sdk-B7id0VFS.d.mts} +2 -2
- package/dist/{sdk-BlyVSC_S.d.ts → sdk-Bso0FSI0.d.ts} +2 -2
- package/dist/transport/index.d.mts +2 -2
- package/dist/transport/index.d.ts +2 -2
- package/dist/{types-79qS7aON.d.ts → types-BYKAY6Cc.d.ts} +1 -1
- package/dist/{types-jJnPXStc.d.mts → types-CgXPKUwi.d.mts} +1 -1
- package/dist/{types-CxQwJKbd.d.mts → types-DOrqNMgy.d.mts} +79 -13
- package/dist/{types-CxQwJKbd.d.ts → types-DOrqNMgy.d.ts} +79 -13
- package/dist/ui/index.d.mts +1 -1
- package/dist/ui/index.d.ts +1 -1
- package/dist/webhooks.d.mts +59 -0
- package/dist/webhooks.d.ts +59 -0
- package/dist/webhooks.js +81 -0
- package/dist/webhooks.js.map +1 -0
- package/dist/webhooks.mjs +55 -0
- package/dist/webhooks.mjs.map +1 -0
- package/package.json +8 -3
package/dist/index.js
CHANGED
|
@@ -179,14 +179,36 @@ function getCapabilities(accessLevel) {
|
|
|
179
179
|
|
|
180
180
|
// src/verify.ts
|
|
181
181
|
var DEFAULT_CONFIG = {
|
|
182
|
-
apiBaseUrl: "https://
|
|
182
|
+
apiBaseUrl: "https://astrasync.ai/api",
|
|
183
183
|
defaultAccessLevel: "guidance",
|
|
184
|
-
minTrustScore
|
|
185
|
-
minTrustScoreForFull: 70,
|
|
184
|
+
// minTrustScore + minTrustScoreForFull deprecated in v2.3.0 — server decides.
|
|
186
185
|
cacheTtl: 300,
|
|
187
186
|
// 5 minutes
|
|
188
187
|
debug: false
|
|
189
188
|
};
|
|
189
|
+
var initCheckPerformed = false;
|
|
190
|
+
var deprecationWarningShown = false;
|
|
191
|
+
async function performInitCheck(apiBaseUrl, debug) {
|
|
192
|
+
initCheckPerformed = true;
|
|
193
|
+
try {
|
|
194
|
+
const probeUrl = `${apiBaseUrl}/agents/verify-access`;
|
|
195
|
+
const response = await fetch(probeUrl, { method: "HEAD" });
|
|
196
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
197
|
+
if (contentType.startsWith("text/html")) {
|
|
198
|
+
console.warn(
|
|
199
|
+
`[VerificationGateway] apiBaseUrl '${apiBaseUrl}' returned HTML (content-type: ${contentType}). This usually means apiBaseUrl is pointing at a marketing site instead of the API. Expected: 'https://astrasync.ai/api' (prod) or 'https://staging.astrasync.ai/api' (staging). Set disableInitChecks: true on GatewayConfig to silence this warning.`
|
|
200
|
+
);
|
|
201
|
+
} else if (debug) {
|
|
202
|
+
console.log(
|
|
203
|
+
`[VerificationGateway] init check passed for ${apiBaseUrl} (content-type: ${contentType})`
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
} catch (err) {
|
|
207
|
+
if (debug) {
|
|
208
|
+
console.log(`[VerificationGateway] init check failed (non-blocking): ${String(err)}`);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
190
212
|
var verificationCache = /* @__PURE__ */ new Map();
|
|
191
213
|
function getCacheKey(credentials) {
|
|
192
214
|
return `${credentials.astraId || ""}-${credentials.apiKey || ""}-${credentials.jwt || ""}`;
|
|
@@ -214,7 +236,7 @@ function clearCache() {
|
|
|
214
236
|
}
|
|
215
237
|
function extractCredentials(headers, query) {
|
|
216
238
|
const credentials = {};
|
|
217
|
-
const astraIdHeader = headers["x-astra-id"] || headers["X-Astra-Id"] || headers["X-ASTRA-ID"];
|
|
239
|
+
const astraIdHeader = headers["x-astra-id"] || headers["X-Astra-Id"] || headers["X-ASTRA-ID"] || headers["x-astra-agentid"] || headers["X-Astra-AgentId"] || headers["x-astra-agent-id"] || headers["X-Astra-Agent-Id"] || headers["X-ASTRA-AGENT-ID"];
|
|
218
240
|
if (astraIdHeader) {
|
|
219
241
|
credentials.astraId = Array.isArray(astraIdHeader) ? astraIdHeader[0] : astraIdHeader;
|
|
220
242
|
}
|
|
@@ -266,7 +288,7 @@ function createGuidanceResponse(config, reason) {
|
|
|
266
288
|
async function callVerifyAccessAPI(config, request) {
|
|
267
289
|
const { credentials, ...requestData } = request;
|
|
268
290
|
const body = {
|
|
269
|
-
agentId: credentials.astraId,
|
|
291
|
+
...credentials.astraId && { agentId: credentials.astraId },
|
|
270
292
|
purpose: requestData.purpose || "general"
|
|
271
293
|
};
|
|
272
294
|
if (requestData.action) body.action = requestData.action;
|
|
@@ -278,21 +300,34 @@ async function callVerifyAccessAPI(config, request) {
|
|
|
278
300
|
if (requestData.isSubAgentRequest) body.isSubAgentRequest = requestData.isSubAgentRequest;
|
|
279
301
|
if (requestData.parentAgentId) body.parentAgentId = requestData.parentAgentId;
|
|
280
302
|
if (requestData.subAgentDepth !== void 0) body.subAgentDepth = requestData.subAgentDepth;
|
|
281
|
-
if (requestData.enableRuntimeChallenge)
|
|
303
|
+
if (requestData.enableRuntimeChallenge)
|
|
304
|
+
body.enableRuntimeChallenge = requestData.enableRuntimeChallenge;
|
|
282
305
|
if (requestData.createSession) body.createSession = requestData.createSession;
|
|
283
306
|
if (requestData.durationRequired) body.durationRequired = requestData.durationRequired;
|
|
284
307
|
if (requestData.counterpartyType) body.counterpartyType = requestData.counterpartyType;
|
|
285
308
|
if (requestData.counterpartyUrl) body.counterpartyUrl = requestData.counterpartyUrl;
|
|
286
|
-
if (
|
|
309
|
+
if (config.counterpartyId) body.counterpartyId = config.counterpartyId;
|
|
310
|
+
if (requestData.runtimeChallengeOptions)
|
|
311
|
+
body.runtimeChallengeOptions = requestData.runtimeChallengeOptions;
|
|
312
|
+
if (requestData.callerMetadata || requestData.clientIp || requestData.userAgent) {
|
|
313
|
+
const meta = {
|
|
314
|
+
...requestData.clientIp && { sourceIp: requestData.clientIp },
|
|
315
|
+
...requestData.userAgent && { userAgent: requestData.userAgent },
|
|
316
|
+
...requestData.callerMetadata
|
|
317
|
+
};
|
|
318
|
+
if (Object.keys(meta).length > 0) body.callerMetadata = meta;
|
|
319
|
+
}
|
|
287
320
|
const headers = {
|
|
288
321
|
"Content-Type": "application/json",
|
|
289
322
|
...config.customHeaders
|
|
290
323
|
};
|
|
291
|
-
if (config.apiKey) {
|
|
292
|
-
headers["X-API-Key"] = config.apiKey;
|
|
293
|
-
}
|
|
294
324
|
if (credentials.authorizationHeader) {
|
|
295
325
|
headers["Authorization"] = credentials.authorizationHeader;
|
|
326
|
+
} else if (config.apiKey) {
|
|
327
|
+
headers["Authorization"] = `Bearer ${config.apiKey}`;
|
|
328
|
+
}
|
|
329
|
+
if (config.apiKey) {
|
|
330
|
+
headers["X-API-Key"] = config.apiKey;
|
|
296
331
|
}
|
|
297
332
|
try {
|
|
298
333
|
const response = await fetch(`${config.apiBaseUrl}/agents/verify-access`, {
|
|
@@ -318,8 +353,14 @@ async function callVerifyAccessAPI(config, request) {
|
|
|
318
353
|
}
|
|
319
354
|
async function verify(config, request) {
|
|
320
355
|
const mergedConfig = { ...DEFAULT_CONFIG, ...config };
|
|
321
|
-
if (!
|
|
322
|
-
|
|
356
|
+
if (!initCheckPerformed && !mergedConfig.disableInitChecks && mergedConfig.apiBaseUrl) {
|
|
357
|
+
void performInitCheck(mergedConfig.apiBaseUrl, mergedConfig.debug);
|
|
358
|
+
}
|
|
359
|
+
if (!deprecationWarningShown && (config.minTrustScore !== void 0 || config.minTrustScoreForFull !== void 0)) {
|
|
360
|
+
deprecationWarningShown = true;
|
|
361
|
+
console.warn(
|
|
362
|
+
"[VerificationGateway] minTrustScore / minTrustScoreForFull are deprecated in v2.3.0 and have no effect. Server is now the single source of truth for access-level decisions (the SDK reads access.accessLevel from the verify-access response). To gate access to an endpoint, configure the endpoint's trust_score_requirement server-side."
|
|
363
|
+
);
|
|
323
364
|
}
|
|
324
365
|
if (mergedConfig.cacheTtl && mergedConfig.cacheTtl > 0) {
|
|
325
366
|
const cached = getCachedResult(request.credentials);
|
|
@@ -391,18 +432,7 @@ async function verify(config, request) {
|
|
|
391
432
|
selfInstantiationAllowed: apiResponse.access.pdlss.selfInstantiationAllowed,
|
|
392
433
|
appliedPolicy: apiResponse.access.appliedPolicy
|
|
393
434
|
} : void 0;
|
|
394
|
-
const
|
|
395
|
-
const isOrgMember = false;
|
|
396
|
-
const accessLevel = determineAccessLevel(
|
|
397
|
-
true,
|
|
398
|
-
trustScore,
|
|
399
|
-
isOrgMember,
|
|
400
|
-
{
|
|
401
|
-
"read-only": 20,
|
|
402
|
-
standard: mergedConfig.minTrustScore || 40,
|
|
403
|
-
full: mergedConfig.minTrustScoreForFull || 70
|
|
404
|
-
}
|
|
405
|
-
);
|
|
435
|
+
const accessLevel = apiResponse.access?.accessLevel ?? "standard";
|
|
406
436
|
const result = {
|
|
407
437
|
verified: true,
|
|
408
438
|
accessLevel,
|
|
@@ -424,7 +454,9 @@ async function verify(config, request) {
|
|
|
424
454
|
if (result.recommendation === "deny") {
|
|
425
455
|
result.verified = false;
|
|
426
456
|
result.accessLevel = "none";
|
|
427
|
-
result.denialReasons = result.recommendationReasons || [
|
|
457
|
+
result.denialReasons = result.recommendationReasons || [
|
|
458
|
+
"Access denied by AstraSync recommendation"
|
|
459
|
+
];
|
|
428
460
|
if (result.runtimeChallenge) {
|
|
429
461
|
result.guidance = {
|
|
430
462
|
message: `Verification failed: ${result.runtimeChallenge.reason || "runtime challenge failed"}`,
|
|
@@ -446,7 +478,10 @@ async function verify(config, request) {
|
|
|
446
478
|
}
|
|
447
479
|
async function recordDecision(config, sessionId, decision, reason) {
|
|
448
480
|
const headers = { "Content-Type": "application/json" };
|
|
449
|
-
if (config.apiKey)
|
|
481
|
+
if (config.apiKey) {
|
|
482
|
+
headers["Authorization"] = `Bearer ${config.apiKey}`;
|
|
483
|
+
headers["X-API-Key"] = config.apiKey;
|
|
484
|
+
}
|
|
450
485
|
await fetch(`${config.apiBaseUrl}/agents/verify-access/${sessionId}/decision`, {
|
|
451
486
|
method: "POST",
|
|
452
487
|
headers,
|
|
@@ -454,15 +489,6 @@ async function recordDecision(config, sessionId, decision, reason) {
|
|
|
454
489
|
}).catch(() => {
|
|
455
490
|
});
|
|
456
491
|
}
|
|
457
|
-
async function reportUnregisteredAttempt(config, data) {
|
|
458
|
-
const apiBaseUrl = config.apiBaseUrl || DEFAULT_CONFIG.apiBaseUrl;
|
|
459
|
-
await fetch(`${apiBaseUrl}/verification-activity/unregistered-attempt`, {
|
|
460
|
-
method: "POST",
|
|
461
|
-
headers: { "Content-Type": "application/json" },
|
|
462
|
-
body: JSON.stringify(data)
|
|
463
|
-
}).catch(() => {
|
|
464
|
-
});
|
|
465
|
-
}
|
|
466
492
|
async function reportCounterpartyPreCheckFailure(config, data) {
|
|
467
493
|
const apiBaseUrl = config.apiBaseUrl || DEFAULT_CONFIG.apiBaseUrl;
|
|
468
494
|
await fetch(`${apiBaseUrl}/verification-activity/counterparty-pre-check-failure`, {
|
|
@@ -688,32 +714,6 @@ function createMiddleware(options) {
|
|
|
688
714
|
return next();
|
|
689
715
|
}
|
|
690
716
|
const credentials = customExtractCredentials ? customExtractCredentials(req) : defaultExtractCredentials(req);
|
|
691
|
-
if (!hasCredentials(credentials) && routeConfig.minAccessLevel !== "guidance") {
|
|
692
|
-
const counterpartyUrl2 = config.counterpartyUrl || `${req.protocol}://${req.get("host")}`;
|
|
693
|
-
reportUnregisteredAttempt(config, {
|
|
694
|
-
counterpartyUrl: counterpartyUrl2,
|
|
695
|
-
counterpartyType: config.counterpartyType || "api",
|
|
696
|
-
sourceIp: req.ip,
|
|
697
|
-
userAgent: req.headers["user-agent"],
|
|
698
|
-
requestPath: req.path,
|
|
699
|
-
requestMethod: req.method
|
|
700
|
-
}).catch(() => {
|
|
701
|
-
});
|
|
702
|
-
const result2 = {
|
|
703
|
-
verified: false,
|
|
704
|
-
accessLevel: "none",
|
|
705
|
-
denialReasons: ["No agent credentials provided"],
|
|
706
|
-
guidance: {
|
|
707
|
-
message: "This endpoint requires agent verification. Please provide your ASTRA-ID.",
|
|
708
|
-
registrationUrl: `${config.apiBaseUrl?.replace("/api", "")}/register`,
|
|
709
|
-
documentationUrl: `${config.apiBaseUrl?.replace("/api", "")}/docs/agent-access`
|
|
710
|
-
},
|
|
711
|
-
verifiedAt: /* @__PURE__ */ new Date()
|
|
712
|
-
};
|
|
713
|
-
req.agentVerification = result2;
|
|
714
|
-
onDenied(result2, req, res);
|
|
715
|
-
return;
|
|
716
|
-
}
|
|
717
717
|
const purpose = customExtractPurpose ? customExtractPurpose(req) : defaultExtractPurpose(req);
|
|
718
718
|
const astraCreds = extractAstraSyncCredentials(req);
|
|
719
719
|
const counterpartyUrl = config.counterpartyUrl || `${req.protocol}://${req.get("host")}`;
|
|
@@ -744,18 +744,28 @@ function createMiddleware(options) {
|
|
|
744
744
|
return;
|
|
745
745
|
}
|
|
746
746
|
const shouldRecordDecisions = recordDecisions !== false;
|
|
747
|
+
const forwardedFor = req.headers["x-forwarded-for"];
|
|
748
|
+
const forwardedForStr = Array.isArray(forwardedFor) ? forwardedFor.join(", ") : forwardedFor;
|
|
749
|
+
const originalClientIp = forwardedForStr ? forwardedForStr.split(",")[0].trim() : req.ip;
|
|
750
|
+
const agentCardUrl = typeof req.headers["x-astrasync-agent-card"] === "string" ? req.headers["x-astrasync-agent-card"] : void 0;
|
|
747
751
|
const result = await verify(config, {
|
|
748
752
|
credentials,
|
|
749
753
|
purpose,
|
|
750
754
|
action: req.method.toLowerCase(),
|
|
751
755
|
resource: req.path,
|
|
752
|
-
clientIp: req.ip,
|
|
753
|
-
userAgent: req.headers["user-agent"],
|
|
754
756
|
createSession: shouldRecordDecisions,
|
|
755
757
|
counterpartyUrl,
|
|
756
758
|
counterpartyType: config.counterpartyType || "api",
|
|
757
759
|
enableRuntimeChallenge,
|
|
758
|
-
durationRequired: astraCreds?.pdlss?.duration?.maxSessionDuration
|
|
760
|
+
durationRequired: astraCreds?.pdlss?.duration?.maxSessionDuration,
|
|
761
|
+
callerMetadata: {
|
|
762
|
+
sourceIp: originalClientIp,
|
|
763
|
+
userAgent: req.headers["user-agent"],
|
|
764
|
+
referer: req.headers.referer,
|
|
765
|
+
host: req.headers.host,
|
|
766
|
+
forwardedFor: forwardedForStr,
|
|
767
|
+
agentCardUrl
|
|
768
|
+
}
|
|
759
769
|
});
|
|
760
770
|
req.agentVerification = result;
|
|
761
771
|
const sessionId = result.sessionId;
|
|
@@ -1027,7 +1037,13 @@ function generateCommerceShieldHtml(result, options) {
|
|
|
1027
1037
|
`.trim();
|
|
1028
1038
|
}
|
|
1029
1039
|
function createMiddleware2(options) {
|
|
1030
|
-
const {
|
|
1040
|
+
const {
|
|
1041
|
+
routes = [],
|
|
1042
|
+
skipPaths = [],
|
|
1043
|
+
showCommerceShield = true,
|
|
1044
|
+
enableRuntimeChallenge = true,
|
|
1045
|
+
...config
|
|
1046
|
+
} = options;
|
|
1031
1047
|
return async function middleware(request) {
|
|
1032
1048
|
const { NextResponse } = await import("next/server");
|
|
1033
1049
|
const pathname = request.nextUrl.pathname;
|
|
@@ -1043,53 +1059,6 @@ function createMiddleware2(options) {
|
|
|
1043
1059
|
return NextResponse.next();
|
|
1044
1060
|
}
|
|
1045
1061
|
const credentials = extractCredentialsFromNextRequest(request);
|
|
1046
|
-
if (!hasCredentials(credentials) && routeConfig.minAccessLevel !== "guidance") {
|
|
1047
|
-
const counterpartyUrl2 = config.counterpartyUrl || request.nextUrl.origin;
|
|
1048
|
-
reportUnregisteredAttempt(config, {
|
|
1049
|
-
counterpartyUrl: counterpartyUrl2,
|
|
1050
|
-
counterpartyType: config.counterpartyType || "website",
|
|
1051
|
-
sourceIp: request.headers.get("x-forwarded-for") || request.headers.get("x-real-ip") || void 0,
|
|
1052
|
-
userAgent: request.headers.get("user-agent") || void 0,
|
|
1053
|
-
requestPath: pathname,
|
|
1054
|
-
requestMethod: request.method
|
|
1055
|
-
}).catch(() => {
|
|
1056
|
-
});
|
|
1057
|
-
const result2 = {
|
|
1058
|
-
verified: false,
|
|
1059
|
-
accessLevel: "none",
|
|
1060
|
-
denialReasons: ["No agent credentials provided"],
|
|
1061
|
-
guidance: {
|
|
1062
|
-
message: "This page requires agent verification.",
|
|
1063
|
-
registrationUrl: `${config.apiBaseUrl?.replace("/api", "")}/register`,
|
|
1064
|
-
documentationUrl: `${config.apiBaseUrl?.replace("/api", "")}/docs/agent-access`
|
|
1065
|
-
},
|
|
1066
|
-
verifiedAt: /* @__PURE__ */ new Date()
|
|
1067
|
-
};
|
|
1068
|
-
if (pathname.startsWith("/api/")) {
|
|
1069
|
-
return NextResponse.json(
|
|
1070
|
-
{
|
|
1071
|
-
success: false,
|
|
1072
|
-
error: {
|
|
1073
|
-
code: "UNAUTHORIZED",
|
|
1074
|
-
message: "No agent credentials provided",
|
|
1075
|
-
guidance: result2.guidance
|
|
1076
|
-
}
|
|
1077
|
-
},
|
|
1078
|
-
{ status: 401 }
|
|
1079
|
-
);
|
|
1080
|
-
}
|
|
1081
|
-
if (showCommerceShield) {
|
|
1082
|
-
return new NextResponse(generateCommerceShieldHtml(result2, options), {
|
|
1083
|
-
status: 200,
|
|
1084
|
-
headers: {
|
|
1085
|
-
"Content-Type": "text/html",
|
|
1086
|
-
"X-AstraSync-Verification": "commerce-shield"
|
|
1087
|
-
}
|
|
1088
|
-
});
|
|
1089
|
-
}
|
|
1090
|
-
const registerUrl = result2.guidance?.registrationUrl || "/register";
|
|
1091
|
-
return NextResponse.redirect(new URL(registerUrl, request.url));
|
|
1092
|
-
}
|
|
1093
1062
|
const counterpartyUrl = config.counterpartyUrl || request.nextUrl.origin;
|
|
1094
1063
|
const purpose = extractPurpose(request);
|
|
1095
1064
|
const astraCreds = extractAstraSyncCredentialsFromNextRequest(request);
|
|
@@ -1139,17 +1108,25 @@ function createMiddleware2(options) {
|
|
|
1139
1108
|
}
|
|
1140
1109
|
return NextResponse.redirect(new URL("/unauthorized", request.url));
|
|
1141
1110
|
}
|
|
1111
|
+
const forwardedFor = request.headers.get("x-forwarded-for") || void 0;
|
|
1112
|
+
const originalClientIp = forwardedFor?.split(",")[0]?.trim();
|
|
1142
1113
|
const result = await verify(config, {
|
|
1143
1114
|
credentials,
|
|
1144
1115
|
purpose,
|
|
1145
1116
|
action: request.method.toLowerCase(),
|
|
1146
1117
|
resource: pathname,
|
|
1147
|
-
clientIp: request.headers.get("x-forwarded-for")?.split(",")[0]?.trim() || void 0,
|
|
1148
|
-
userAgent: request.headers.get("user-agent") || void 0,
|
|
1149
1118
|
counterpartyUrl,
|
|
1150
1119
|
counterpartyType: config.counterpartyType || "website",
|
|
1151
1120
|
enableRuntimeChallenge,
|
|
1152
|
-
durationRequired: astraCreds?.pdlss?.duration?.maxSessionDuration
|
|
1121
|
+
durationRequired: astraCreds?.pdlss?.duration?.maxSessionDuration,
|
|
1122
|
+
callerMetadata: {
|
|
1123
|
+
sourceIp: originalClientIp,
|
|
1124
|
+
userAgent: request.headers.get("user-agent") || void 0,
|
|
1125
|
+
referer: request.headers.get("referer") || void 0,
|
|
1126
|
+
host: request.headers.get("host") || void 0,
|
|
1127
|
+
forwardedFor,
|
|
1128
|
+
agentCardUrl: request.headers.get("x-astrasync-agent-card") || void 0
|
|
1129
|
+
}
|
|
1153
1130
|
});
|
|
1154
1131
|
if (!hasMinimumAccess(result.accessLevel, routeConfig.minAccessLevel)) {
|
|
1155
1132
|
if (pathname.startsWith("/api/")) {
|
|
@@ -3771,21 +3748,85 @@ function extractCredentialsFromProtocol(protocol, context) {
|
|
|
3771
3748
|
var agent_exports = {};
|
|
3772
3749
|
__export(agent_exports, {
|
|
3773
3750
|
AgentClient: () => AgentClient,
|
|
3751
|
+
AstraSyncSdkError: () => AstraSyncSdkError,
|
|
3774
3752
|
ChallengeHandler: () => ChallengeHandler,
|
|
3753
|
+
OwnershipMismatchError: () => OwnershipMismatchError,
|
|
3775
3754
|
formatPDLSSForTransport: () => formatPDLSSForTransport,
|
|
3776
3755
|
parsePDLSSFromTransport: () => parsePDLSSFromTransport,
|
|
3777
3756
|
recordDecision: () => recordDecision2
|
|
3778
3757
|
});
|
|
3779
3758
|
|
|
3759
|
+
// src/agent/errors.ts
|
|
3760
|
+
var AstraSyncSdkError = class extends Error {
|
|
3761
|
+
constructor(code, message) {
|
|
3762
|
+
super(message);
|
|
3763
|
+
this.name = "AstraSyncSdkError";
|
|
3764
|
+
this.code = code;
|
|
3765
|
+
}
|
|
3766
|
+
};
|
|
3767
|
+
var OwnershipMismatchError = class extends AstraSyncSdkError {
|
|
3768
|
+
constructor(astraId) {
|
|
3769
|
+
super(
|
|
3770
|
+
"ownership_mismatch",
|
|
3771
|
+
`The configured API key does not own agent ${astraId}. Refusing to initialise.`
|
|
3772
|
+
);
|
|
3773
|
+
this.name = "OwnershipMismatchError";
|
|
3774
|
+
this.astraId = astraId;
|
|
3775
|
+
}
|
|
3776
|
+
};
|
|
3777
|
+
|
|
3780
3778
|
// src/agent/client.ts
|
|
3781
|
-
var AgentClient = class {
|
|
3779
|
+
var AgentClient = class _AgentClient {
|
|
3782
3780
|
constructor(config) {
|
|
3783
3781
|
this.credentials = {
|
|
3784
3782
|
agentId: config.agentId,
|
|
3785
|
-
verifyUrl: config.verifyUrl ?? "https://
|
|
3783
|
+
verifyUrl: config.verifyUrl ?? "https://astrasync.ai/api/agents/verify-access",
|
|
3786
3784
|
challengeUrl: config.challengeUrl,
|
|
3787
3785
|
pdlss: config.pdlss
|
|
3788
3786
|
};
|
|
3787
|
+
this.apiBaseUrl = config.apiBaseUrl ?? "https://astrasync.ai/api";
|
|
3788
|
+
this.apiKey = config.apiKey;
|
|
3789
|
+
}
|
|
3790
|
+
/**
|
|
3791
|
+
* Async factory that validates the API key's account owns the configured
|
|
3792
|
+
* ASTRA-id before returning a usable client. Refuses to initialise on
|
|
3793
|
+
* mismatch so a stolen ASTRA-id cannot be paired with a valid (different)
|
|
3794
|
+
* API key.
|
|
3795
|
+
*
|
|
3796
|
+
* Set env `ASTRASYNC_SKIP_OWNERSHIP_CHECK=true` to bypass — intended for
|
|
3797
|
+
* test environments only.
|
|
3798
|
+
*/
|
|
3799
|
+
static async create(config) {
|
|
3800
|
+
const client = new _AgentClient(config);
|
|
3801
|
+
const skip = typeof process !== "undefined" && process.env?.ASTRASYNC_SKIP_OWNERSHIP_CHECK === "true";
|
|
3802
|
+
if (skip) return client;
|
|
3803
|
+
if (!config.apiKey) {
|
|
3804
|
+
throw new OwnershipMismatchError(config.agentId);
|
|
3805
|
+
}
|
|
3806
|
+
const owned = await client.verifyOwnership();
|
|
3807
|
+
if (!owned) throw new OwnershipMismatchError(config.agentId);
|
|
3808
|
+
return client;
|
|
3809
|
+
}
|
|
3810
|
+
/**
|
|
3811
|
+
* Calls GET /api/agents/:astraId/ownership with the configured API key.
|
|
3812
|
+
* Returns true only when the backend confirms this API key's account
|
|
3813
|
+
* owns the configured agent.
|
|
3814
|
+
*/
|
|
3815
|
+
async verifyOwnership() {
|
|
3816
|
+
if (!this.apiKey) return false;
|
|
3817
|
+
const url = `${this.apiBaseUrl.replace(/\/+$/, "")}/api/agents/${encodeURIComponent(
|
|
3818
|
+
this.credentials.agentId
|
|
3819
|
+
)}/ownership`;
|
|
3820
|
+
const resp = await fetch(url, {
|
|
3821
|
+
method: "GET",
|
|
3822
|
+
headers: {
|
|
3823
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
3824
|
+
"Content-Type": "application/json"
|
|
3825
|
+
}
|
|
3826
|
+
});
|
|
3827
|
+
if (!resp.ok) return false;
|
|
3828
|
+
const body = await resp.json().catch(() => null);
|
|
3829
|
+
return Boolean(body?.data?.owned);
|
|
3789
3830
|
}
|
|
3790
3831
|
/**
|
|
3791
3832
|
* Make an HTTP request with AstraSync headers automatically injected.
|