@inkeep/agents-core 0.41.2 → 0.43.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/api-client/base-client.d.ts +87 -8
- package/dist/api-client/base-client.js +174 -1
- package/dist/api-client/eval-api-client.d.ts +47 -0
- package/dist/api-client/eval-api-client.js +65 -0
- package/dist/api-client/index.d.ts +4 -0
- package/dist/api-client/index.js +5 -0
- package/dist/api-client/manage-api-client.d.ts +34 -0
- package/dist/api-client/manage-api-client.js +104 -0
- package/dist/auth/auth.d.ts +86 -20
- package/dist/auth/auth.js +60 -2
- package/dist/auth/authz/client.d.ts +87 -0
- package/dist/auth/authz/client.js +196 -0
- package/dist/auth/authz/config.d.ts +103 -0
- package/dist/auth/authz/config.js +93 -0
- package/dist/auth/authz/index.d.ts +5 -0
- package/dist/auth/authz/index.js +6 -0
- package/dist/auth/authz/permissions.d.ts +53 -0
- package/dist/auth/authz/permissions.js +83 -0
- package/dist/auth/authz/sync.d.ts +106 -0
- package/dist/auth/authz/sync.js +321 -0
- package/dist/auth/permissions.d.ts +13 -13
- package/dist/auth/permissions.js +2 -181
- package/dist/client-exports.d.ts +9 -3
- package/dist/client-exports.js +4 -2
- package/dist/constants/context-breakdown.d.ts +61 -0
- package/dist/constants/context-breakdown.js +124 -0
- package/dist/constants/execution-limits-shared/defaults.d.ts +1 -1
- package/dist/constants/execution-limits-shared/defaults.js +1 -1
- package/dist/constants/execution-limits-shared/index.d.ts +1 -1
- package/dist/constants/otel-attributes.d.ts +4 -0
- package/dist/constants/otel-attributes.js +4 -0
- package/dist/context/ContextConfig.d.ts +2 -2
- package/dist/context/ContextConfig.js +3 -3
- package/dist/context/TemplateEngine.d.ts +0 -6
- package/dist/context/TemplateEngine.js +4 -19
- package/dist/context/index.d.ts +1 -5
- package/dist/context/index.js +1 -5
- package/dist/credential-stores/keychain-store.d.ts +20 -8
- package/dist/credential-stores/keychain-store.js +107 -43
- package/dist/credential-stuffer/CredentialStuffer.d.ts +1 -1
- package/dist/data-access/index.d.ts +34 -26
- package/dist/data-access/index.js +34 -26
- package/dist/data-access/manage/agentFull.d.ts +36 -0
- package/dist/data-access/{agentFull.js → manage/agentFull.js} +209 -7
- package/dist/data-access/{agents.d.ts → manage/agents.d.ts} +64 -63
- package/dist/data-access/{agents.js → manage/agents.js} +80 -27
- package/dist/data-access/{artifactComponents.d.ts → manage/artifactComponents.d.ts} +33 -33
- package/dist/data-access/{artifactComponents.js → manage/artifactComponents.js} +5 -5
- package/dist/data-access/{contextConfigs.d.ts → manage/contextConfigs.d.ts} +26 -26
- package/dist/data-access/{contextConfigs.js → manage/contextConfigs.js} +3 -3
- package/dist/data-access/{credentialReferences.d.ts → manage/credentialReferences.d.ts} +17 -17
- package/dist/data-access/{credentialReferences.js → manage/credentialReferences.js} +2 -2
- package/dist/data-access/{dataComponents.d.ts → manage/dataComponents.d.ts} +26 -26
- package/dist/data-access/{dataComponents.js → manage/dataComponents.js} +7 -7
- package/dist/data-access/manage/evalConfig.d.ts +221 -0
- package/dist/data-access/manage/evalConfig.js +275 -0
- package/dist/data-access/{externalAgents.d.ts → manage/externalAgents.d.ts} +16 -16
- package/dist/data-access/{externalAgents.js → manage/externalAgents.js} +2 -2
- package/dist/data-access/manage/functionTools.d.ts +242 -0
- package/dist/data-access/{functionTools.js → manage/functionTools.js} +124 -30
- package/dist/data-access/{functions.d.ts → manage/functions.d.ts} +9 -9
- package/dist/data-access/{functions.js → manage/functions.js} +3 -3
- package/dist/data-access/manage/projectFull.d.ts +38 -0
- package/dist/data-access/{projectFull.js → manage/projectFull.js} +64 -65
- package/dist/data-access/manage/projectLifecycle.d.ts +119 -0
- package/dist/data-access/manage/projectLifecycle.js +234 -0
- package/dist/data-access/manage/projects.d.ts +75 -0
- package/dist/data-access/{projects.js → manage/projects.js} +15 -16
- package/dist/data-access/{subAgentExternalAgentRelations.d.ts → manage/subAgentExternalAgentRelations.d.ts} +43 -43
- package/dist/data-access/{subAgentExternalAgentRelations.js → manage/subAgentExternalAgentRelations.js} +2 -2
- package/dist/data-access/{subAgentRelations.d.ts → manage/subAgentRelations.d.ts} +65 -65
- package/dist/data-access/{subAgentRelations.js → manage/subAgentRelations.js} +3 -3
- package/dist/data-access/{subAgentTeamAgentRelations.d.ts → manage/subAgentTeamAgentRelations.d.ts} +43 -43
- package/dist/data-access/{subAgentTeamAgentRelations.js → manage/subAgentTeamAgentRelations.js} +2 -2
- package/dist/data-access/{subAgents.d.ts → manage/subAgents.d.ts} +28 -28
- package/dist/data-access/{subAgents.js → manage/subAgents.js} +4 -4
- package/dist/data-access/{tools.d.ts → manage/tools.d.ts} +65 -52
- package/dist/data-access/{tools.js → manage/tools.js} +109 -64
- package/dist/data-access/manage/triggers.d.ts +106 -0
- package/dist/data-access/manage/triggers.js +81 -0
- package/dist/data-access/{apiKeys.d.ts → runtime/apiKeys.d.ts} +37 -37
- package/dist/data-access/{apiKeys.js → runtime/apiKeys.js} +3 -3
- package/dist/data-access/runtime/cascade-delete.d.ts +77 -0
- package/dist/data-access/runtime/cascade-delete.js +111 -0
- package/dist/data-access/{contextCache.d.ts → runtime/contextCache.d.ts} +13 -13
- package/dist/data-access/{contextCache.js → runtime/contextCache.js} +5 -5
- package/dist/data-access/{conversations.d.ts → runtime/conversations.d.ts} +80 -31
- package/dist/data-access/{conversations.js → runtime/conversations.js} +13 -7
- package/dist/data-access/runtime/evalRuns.d.ts +120 -0
- package/dist/data-access/runtime/evalRuns.js +168 -0
- package/dist/data-access/{ledgerArtifacts.d.ts → runtime/ledgerArtifacts.d.ts} +13 -13
- package/dist/data-access/{ledgerArtifacts.js → runtime/ledgerArtifacts.js} +3 -3
- package/dist/data-access/{messages.d.ts → runtime/messages.d.ts} +24 -24
- package/dist/data-access/{messages.js → runtime/messages.js} +2 -2
- package/dist/data-access/{organizations.d.ts → runtime/organizations.d.ts} +16 -7
- package/dist/data-access/{organizations.js → runtime/organizations.js} +16 -4
- package/dist/data-access/runtime/projects.d.ts +62 -0
- package/dist/data-access/runtime/projects.js +90 -0
- package/dist/data-access/runtime/tasks.d.ts +55 -0
- package/dist/data-access/{tasks.js → runtime/tasks.js} +2 -2
- package/dist/data-access/runtime/triggerInvocations.d.ts +62 -0
- package/dist/data-access/runtime/triggerInvocations.js +54 -0
- package/dist/data-access/runtime/users.d.ts +19 -0
- package/dist/data-access/{users.js → runtime/users.js} +2 -2
- package/dist/data-access/validation.d.ts +4 -4
- package/dist/data-access/validation.js +1 -1
- package/dist/db/clean.d.ts +8 -4
- package/dist/db/clean.js +14 -105
- package/dist/db/delete.d.ts +1 -1
- package/dist/db/delete.js +7 -10
- package/dist/db/manage/dolt-cleanup.d.ts +51 -0
- package/dist/db/manage/dolt-cleanup.js +132 -0
- package/dist/db/manage/manage-client.d.ts +26 -0
- package/dist/db/manage/manage-client.js +68 -0
- package/dist/db/{schema.d.ts → manage/manage-schema.d.ts} +1257 -969
- package/dist/db/{schema.js → manage/manage-schema.js} +436 -334
- package/dist/db/manage/test-manage-client.d.ts +27 -0
- package/dist/db/manage/test-manage-client.js +68 -0
- package/dist/db/runtime/runtime-client.d.ts +20 -0
- package/dist/db/runtime/runtime-client.js +30 -0
- package/dist/db/runtime/runtime-schema.d.ts +2834 -0
- package/dist/db/runtime/runtime-schema.js +483 -0
- package/dist/db/runtime/test-runtime-client.d.ts +27 -0
- package/dist/db/{test-client.js → runtime/test-runtime-client.js} +11 -25
- package/dist/db/utils.d.ts +6 -0
- package/dist/db/utils.js +42 -0
- package/dist/dolt/branch.d.ts +62 -0
- package/dist/dolt/branch.js +82 -0
- package/dist/dolt/branches-api.d.ts +108 -0
- package/dist/dolt/branches-api.js +162 -0
- package/dist/dolt/commit.d.ts +94 -0
- package/dist/dolt/commit.js +103 -0
- package/dist/dolt/diff.d.ts +27 -0
- package/dist/dolt/diff.js +21 -0
- package/dist/dolt/index.d.ts +10 -0
- package/dist/dolt/index.js +11 -0
- package/dist/dolt/merge.d.ts +63 -0
- package/dist/dolt/merge.js +81 -0
- package/dist/dolt/migrate-all-branches.d.ts +4 -0
- package/dist/dolt/migrate-all-branches.js +83 -0
- package/dist/dolt/migrate-dolt.d.ts +1 -0
- package/dist/dolt/migrate-dolt.js +25 -0
- package/dist/dolt/ref-helpers.d.ts +19 -0
- package/dist/dolt/ref-helpers.js +65 -0
- package/dist/dolt/ref-middleware.d.ts +82 -0
- package/dist/dolt/ref-middleware.js +217 -0
- package/dist/dolt/ref-scope.d.ts +101 -0
- package/dist/dolt/ref-scope.js +231 -0
- package/dist/dolt/schema-sync.d.ts +135 -0
- package/dist/dolt/schema-sync.js +255 -0
- package/dist/env.d.ts +6 -4
- package/dist/env.js +3 -2
- package/dist/index.d.ts +73 -46
- package/dist/index.js +76 -49
- package/dist/types/@napi-rs__keyring/index.d.ts +14 -0
- package/dist/types/entities.d.ts +81 -2
- package/dist/types/index.d.ts +3 -3
- package/dist/types/utility.d.ts +46 -5
- package/dist/types/utility.js +2 -1
- package/dist/utils/JsonTransformer.d.ts +42 -0
- package/dist/utils/JsonTransformer.js +103 -0
- package/dist/utils/apiKeys.d.ts +5 -1
- package/dist/utils/apiKeys.js +11 -1
- package/dist/utils/colors.d.ts +34 -0
- package/dist/utils/colors.js +49 -0
- package/dist/utils/credential-store-utils.d.ts +1 -1
- package/dist/utils/format-messages.d.ts +1 -1
- package/dist/utils/index.d.ts +8 -4
- package/dist/utils/index.js +8 -4
- package/dist/utils/internal-service-auth.d.ts +79 -0
- package/dist/utils/internal-service-auth.js +140 -0
- package/dist/utils/jmespath-utils.d.ts +152 -0
- package/dist/utils/jmespath-utils.js +213 -0
- package/dist/utils/jwt-helpers.d.ts +56 -0
- package/dist/utils/jwt-helpers.js +90 -0
- package/dist/utils/mcp-client.d.ts +1 -1
- package/dist/utils/mcp-client.js +1 -1
- package/dist/utils/service-token-auth.d.ts +9 -27
- package/dist/utils/service-token-auth.js +48 -96
- package/dist/utils/signature-validation.d.ts +2 -0
- package/dist/utils/signature-validation.js +3 -0
- package/dist/utils/template-interpolation.d.ts +22 -0
- package/dist/utils/template-interpolation.js +62 -0
- package/dist/utils/third-party-mcp-servers/composio-client.d.ts +13 -1
- package/dist/utils/third-party-mcp-servers/composio-client.js +47 -29
- package/dist/utils/third-party-mcp-servers/index.d.ts +2 -2
- package/dist/utils/third-party-mcp-servers/index.js +2 -2
- package/dist/utils/trigger-auth.d.ts +85 -0
- package/dist/utils/trigger-auth.js +233 -0
- package/dist/validation/agentFull.js +2 -4
- package/dist/validation/dolt-schemas.d.ts +49 -0
- package/dist/validation/dolt-schemas.js +44 -0
- package/dist/validation/drizzle-schema-helpers.d.ts +4 -26
- package/dist/validation/drizzle-schema-helpers.js +5 -151
- package/dist/validation/index.d.ts +5 -4
- package/dist/validation/index.js +4 -3
- package/dist/validation/render-validation.js +19 -0
- package/dist/validation/schemas.d.ts +18223 -5148
- package/dist/validation/schemas.js +559 -12
- package/dist/validation/stream-event-schemas.d.ts +96 -1
- package/dist/validation/stream-event-schemas.js +67 -2
- package/drizzle/manage/0000_tearful_rhodey.sql +414 -0
- package/drizzle/manage/0001_broken_wendell_vaughn.sql +19 -0
- package/drizzle/manage/0002_bent_sunfire.sql +1 -0
- package/drizzle/manage/0003_tiny_captain_universe.sql +8 -0
- package/drizzle/manage/0004_curious_phil_sheldon.sql +2 -0
- package/drizzle/manage/0005_silent_shatterstar.sql +53 -0
- package/drizzle/manage/meta/0000_snapshot.json +2987 -0
- package/drizzle/manage/meta/0001_snapshot.json +3115 -0
- package/drizzle/manage/meta/0002_snapshot.json +3115 -0
- package/drizzle/manage/meta/0003_snapshot.json +3134 -0
- package/drizzle/manage/meta/0004_snapshot.json +3141 -0
- package/drizzle/manage/meta/0005_snapshot.json +3141 -0
- package/drizzle/manage/meta/_journal.json +48 -0
- package/drizzle/runtime/0008_silly_preak.sql +127 -0
- package/drizzle/runtime/0009_freezing_leo.sql +17 -0
- package/drizzle/runtime/meta/0008_snapshot.json +2263 -0
- package/drizzle/runtime/meta/0009_snapshot.json +2397 -0
- package/drizzle/{meta → runtime/meta}/_journal.json +14 -0
- package/package.json +56 -18
- package/spicedb/schema.zed +114 -0
- package/dist/context/ContextFetcher.d.ts +0 -73
- package/dist/context/ContextFetcher.js +0 -291
- package/dist/context/ContextResolver.d.ts +0 -60
- package/dist/context/ContextResolver.js +0 -278
- package/dist/context/context.d.ts +0 -27
- package/dist/context/context.js +0 -128
- package/dist/context/contextCache.d.ts +0 -58
- package/dist/context/contextCache.js +0 -177
- package/dist/data-access/agentFull.d.ts +0 -33
- package/dist/data-access/functionTools.d.ts +0 -169
- package/dist/data-access/projectFull.d.ts +0 -32
- package/dist/data-access/projects.d.ts +0 -71
- package/dist/data-access/tasks.d.ts +0 -45
- package/dist/data-access/users.d.ts +0 -19
- package/dist/db/client.d.ts +0 -20
- package/dist/db/client.js +0 -28
- package/dist/db/test-client.d.ts +0 -31
- package/dist/middleware/contextValidation.d.ts +0 -46
- package/dist/middleware/contextValidation.js +0 -280
- package/dist/middleware/index.d.ts +0 -2
- package/dist/middleware/index.js +0 -3
- package/dist/utils/execution.d.ts +0 -22
- package/dist/utils/execution.js +0 -25
- /package/drizzle/{0000_exotic_mysterio.sql → runtime/0000_exotic_mysterio.sql} +0 -0
- /package/drizzle/{0001_calm_sheva_callister.sql → runtime/0001_calm_sheva_callister.sql} +0 -0
- /package/drizzle/{0002_puzzling_goblin_queen.sql → runtime/0002_puzzling_goblin_queen.sql} +0 -0
- /package/drizzle/{0003_sweet_human_robot.sql → runtime/0003_sweet_human_robot.sql} +0 -0
- /package/drizzle/{0004_cuddly_shooting_star.sql → runtime/0004_cuddly_shooting_star.sql} +0 -0
- /package/drizzle/{0005_reflective_starfox.sql → runtime/0005_reflective_starfox.sql} +0 -0
- /package/drizzle/{0006_stale_thaddeus_ross.sql → runtime/0006_stale_thaddeus_ross.sql} +0 -0
- /package/drizzle/{0007_slim_karma.sql → runtime/0007_slim_karma.sql} +0 -0
- /package/drizzle/{meta → runtime/meta}/0000_snapshot.json +0 -0
- /package/drizzle/{meta → runtime/meta}/0001_snapshot.json +0 -0
- /package/drizzle/{meta → runtime/meta}/0003_snapshot.json +0 -0
- /package/drizzle/{meta → runtime/meta}/0005_snapshot.json +0 -0
- /package/drizzle/{meta → runtime/meta}/0006_snapshot.json +0 -0
- /package/drizzle/{meta → runtime/meta}/0007_snapshot.json +0 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { getLogger } from "./logger.js";
|
|
2
|
+
import { extractBearerToken, hasIssuer, signJwt, verifyJwt } from "./jwt-helpers.js";
|
|
3
|
+
|
|
4
|
+
//#region src/utils/internal-service-auth.ts
|
|
5
|
+
const logger = getLogger("internal-service-auth");
|
|
6
|
+
const ISSUER = "inkeep-agents-internal";
|
|
7
|
+
/**
|
|
8
|
+
* Known internal services that can authenticate
|
|
9
|
+
*/
|
|
10
|
+
const InternalServices = {
|
|
11
|
+
INKEEP_AGENTS_RUN_API: "inkeep-agents-run-api",
|
|
12
|
+
INKEEP_AGENTS_MANAGE_API: "inkeep-agents-manage-api",
|
|
13
|
+
INKEEP_AGENTS_EVAL_API: "inkeep-agents-eval-api"
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Generate an internal service token for service-to-service authentication
|
|
17
|
+
*/
|
|
18
|
+
async function generateInternalServiceToken(params) {
|
|
19
|
+
try {
|
|
20
|
+
const claims = {};
|
|
21
|
+
if (params.tenantId) claims.tenantId = params.tenantId;
|
|
22
|
+
if (params.projectId) claims.projectId = params.projectId;
|
|
23
|
+
if (params.userId) claims.userId = params.userId;
|
|
24
|
+
const token = await signJwt({
|
|
25
|
+
issuer: ISSUER,
|
|
26
|
+
subject: params.serviceId,
|
|
27
|
+
expiresIn: params.expiresIn || "5m",
|
|
28
|
+
claims
|
|
29
|
+
});
|
|
30
|
+
logger.debug({
|
|
31
|
+
serviceId: params.serviceId,
|
|
32
|
+
tenantId: params.tenantId,
|
|
33
|
+
projectId: params.projectId
|
|
34
|
+
}, "Generated internal service token");
|
|
35
|
+
return token;
|
|
36
|
+
} catch (error) {
|
|
37
|
+
logger.error({ error }, "Failed to generate internal service token");
|
|
38
|
+
throw new Error("Failed to generate internal service token");
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Verify and decode an internal service token
|
|
43
|
+
*/
|
|
44
|
+
async function verifyInternalServiceToken(token) {
|
|
45
|
+
const result = await verifyJwt(token, { issuer: ISSUER });
|
|
46
|
+
if (!result.valid || !result.payload) {
|
|
47
|
+
logger.warn({ error: result.error }, "Internal service token verification failed");
|
|
48
|
+
return {
|
|
49
|
+
valid: false,
|
|
50
|
+
error: result.error
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
const payload = result.payload;
|
|
54
|
+
if (typeof payload.sub !== "string") {
|
|
55
|
+
logger.warn({ payload }, "Invalid internal service token: missing subject");
|
|
56
|
+
return {
|
|
57
|
+
valid: false,
|
|
58
|
+
error: "Invalid token: missing service identifier"
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
if (!Object.values(InternalServices).includes(payload.sub)) {
|
|
62
|
+
logger.warn({ serviceId: payload.sub }, "Unknown service identifier in token");
|
|
63
|
+
return {
|
|
64
|
+
valid: false,
|
|
65
|
+
error: `Unknown service identifier: ${payload.sub}`
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
const validPayload = {
|
|
69
|
+
iss: payload.iss,
|
|
70
|
+
sub: payload.sub,
|
|
71
|
+
tenantId: payload.tenantId,
|
|
72
|
+
projectId: payload.projectId,
|
|
73
|
+
userId: payload.userId,
|
|
74
|
+
iat: payload.iat,
|
|
75
|
+
exp: payload.exp
|
|
76
|
+
};
|
|
77
|
+
logger.debug({
|
|
78
|
+
serviceId: validPayload.sub,
|
|
79
|
+
tenantId: validPayload.tenantId,
|
|
80
|
+
projectId: validPayload.projectId,
|
|
81
|
+
userId: validPayload.userId
|
|
82
|
+
}, "Successfully verified internal service token");
|
|
83
|
+
return {
|
|
84
|
+
valid: true,
|
|
85
|
+
payload: validPayload
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Extract and verify an internal service token from Authorization header
|
|
90
|
+
*/
|
|
91
|
+
async function verifyInternalServiceAuthHeader(authHeader) {
|
|
92
|
+
const extracted = extractBearerToken(authHeader);
|
|
93
|
+
if (!extracted.token) return {
|
|
94
|
+
valid: false,
|
|
95
|
+
error: extracted.error
|
|
96
|
+
};
|
|
97
|
+
return verifyInternalServiceToken(extracted.token);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Check if a token is an internal service token (vs user/agent token)
|
|
101
|
+
* by checking the issuer claim without full verification
|
|
102
|
+
*/
|
|
103
|
+
function isInternalServiceToken(token) {
|
|
104
|
+
return hasIssuer(token, ISSUER);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Validate that the token has access to the specified tenant.
|
|
108
|
+
* If token has no tenantId claim, it has access to all tenants (superuser service).
|
|
109
|
+
*/
|
|
110
|
+
function validateInternalServiceTenantAccess(payload, tenantId) {
|
|
111
|
+
if (!payload.tenantId) return true;
|
|
112
|
+
if (payload.tenantId !== tenantId) {
|
|
113
|
+
logger.warn({
|
|
114
|
+
tokenTenantId: payload.tenantId,
|
|
115
|
+
requestedTenantId: tenantId,
|
|
116
|
+
serviceId: payload.sub
|
|
117
|
+
}, "Internal service token tenant mismatch");
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Validate that the token has access to the specified project.
|
|
124
|
+
* If token has no projectId claim, it has access to all projects in the allowed tenant(s).
|
|
125
|
+
*/
|
|
126
|
+
function validateInternalServiceProjectAccess(payload, projectId) {
|
|
127
|
+
if (!payload.projectId) return true;
|
|
128
|
+
if (payload.projectId !== projectId) {
|
|
129
|
+
logger.warn({
|
|
130
|
+
tokenProjectId: payload.projectId,
|
|
131
|
+
requestedProjectId: projectId,
|
|
132
|
+
serviceId: payload.sub
|
|
133
|
+
}, "Internal service token project mismatch");
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
//#endregion
|
|
140
|
+
export { InternalServices, generateInternalServiceToken, isInternalServiceToken, validateInternalServiceProjectAccess, validateInternalServiceTenantAccess, verifyInternalServiceAuthHeader, verifyInternalServiceToken };
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { z } from "@hono/zod-openapi";
|
|
2
|
+
|
|
3
|
+
//#region src/utils/jmespath-utils.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Result of validating a JMESPath expression or regex pattern.
|
|
7
|
+
*/
|
|
8
|
+
interface ValidationResult {
|
|
9
|
+
valid: boolean;
|
|
10
|
+
error?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Maximum allowed length for JMESPath expressions.
|
|
14
|
+
*/
|
|
15
|
+
declare const MAX_EXPRESSION_LENGTH = 1000;
|
|
16
|
+
/**
|
|
17
|
+
* Validates a JMESPath expression by attempting to compile it.
|
|
18
|
+
* Uses the jmespath package which is already available in the codebase.
|
|
19
|
+
*
|
|
20
|
+
* @param expression - The JMESPath expression to validate
|
|
21
|
+
* @returns ValidationResult with valid flag and optional error message
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* ```typescript
|
|
25
|
+
* const result = validateJMESPath('body.user.id');
|
|
26
|
+
* if (!result.valid) {
|
|
27
|
+
* console.error(result.error);
|
|
28
|
+
* }
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
declare function validateJMESPath(expression: string): ValidationResult;
|
|
32
|
+
/**
|
|
33
|
+
* Validates a regex pattern by attempting to construct a RegExp object.
|
|
34
|
+
* Returns clear error messages for common regex issues.
|
|
35
|
+
*
|
|
36
|
+
* @param pattern - The regex pattern to validate (without delimiters)
|
|
37
|
+
* @returns ValidationResult with valid flag and optional error message
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* const result = validateRegex('v\\d+,(.+)');
|
|
42
|
+
* if (!result.valid) {
|
|
43
|
+
* console.error(result.error);
|
|
44
|
+
* }
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
declare function validateRegex(pattern: string): ValidationResult;
|
|
48
|
+
/**
|
|
49
|
+
* Compiles a JMESPath expression.
|
|
50
|
+
* Wrapper around jmespath.compile() with proper typing.
|
|
51
|
+
*
|
|
52
|
+
* @param expression - The JMESPath expression to compile
|
|
53
|
+
* @returns The compiled expression object
|
|
54
|
+
* @throws Error if the expression is invalid
|
|
55
|
+
*/
|
|
56
|
+
declare function compileJMESPath(expression: string): unknown;
|
|
57
|
+
/**
|
|
58
|
+
* Safely searches data using a JMESPath expression.
|
|
59
|
+
* Wrapper around jmespath.search() with proper typing.
|
|
60
|
+
*
|
|
61
|
+
* @param data - The object to search (e.g., template context, webhook body, tool result)
|
|
62
|
+
* @param expression - The JMESPath expression
|
|
63
|
+
* @returns The search result
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```typescript
|
|
67
|
+
* const data = { users: [{ name: 'Alice' }] };
|
|
68
|
+
* const name = searchJMESPath<string>(data, 'users[0].name');
|
|
69
|
+
* // name is 'Alice'
|
|
70
|
+
*
|
|
71
|
+
* // Common use cases:
|
|
72
|
+
* // - Template contexts: { headers: {...}, body: {...} }
|
|
73
|
+
* // - Webhook payloads: { event: "...", data: {...} }
|
|
74
|
+
* // - Tool results: { status: "success", result: {...} }
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
declare function searchJMESPath<T = unknown>(data: Record<string, unknown>, expression: string): T;
|
|
78
|
+
/**
|
|
79
|
+
* Normalize a JMESPath expression by wrapping property names with dashes in quotes.
|
|
80
|
+
* JMESPath requires identifiers with special characters (like dashes) to be quoted.
|
|
81
|
+
*
|
|
82
|
+
* @param path - The JMESPath expression to normalize
|
|
83
|
+
* @returns The normalized JMESPath expression
|
|
84
|
+
*
|
|
85
|
+
* @example
|
|
86
|
+
* ```typescript
|
|
87
|
+
* normalizeJMESPath('headers.x-tenant-id');
|
|
88
|
+
* // Returns: 'headers."x-tenant-id"'
|
|
89
|
+
*
|
|
90
|
+
* normalizeJMESPath('api-responses[0].response-code');
|
|
91
|
+
* // Returns: '"api-responses"[0]."response-code"'
|
|
92
|
+
*
|
|
93
|
+
* normalizeJMESPath('simple.path');
|
|
94
|
+
* // Returns: 'simple.path' (unchanged)
|
|
95
|
+
* ```
|
|
96
|
+
*/
|
|
97
|
+
declare function normalizeJMESPath(path: string): string;
|
|
98
|
+
/**
|
|
99
|
+
* Dangerous patterns that should not appear in JMESPath expressions.
|
|
100
|
+
* These patterns are checked during secure validation to prevent injection attacks.
|
|
101
|
+
*/
|
|
102
|
+
declare const DANGEROUS_PATTERNS: RegExp[];
|
|
103
|
+
/**
|
|
104
|
+
* Options for secure JMESPath validation.
|
|
105
|
+
*/
|
|
106
|
+
interface SecurityOptions {
|
|
107
|
+
maxLength?: number;
|
|
108
|
+
dangerousPatterns?: RegExp[];
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Validates a JMESPath expression with security checks.
|
|
112
|
+
* Performs checks in order of cost: length (O(1)), patterns (O(n)), compile (expensive).
|
|
113
|
+
*
|
|
114
|
+
* @param expression - The JMESPath expression to validate
|
|
115
|
+
* @param options - Optional security options
|
|
116
|
+
* @returns ValidationResult with valid flag and optional error message
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* ```typescript
|
|
120
|
+
* const result = validateJMESPathSecure('body.user.id');
|
|
121
|
+
* if (!result.valid) {
|
|
122
|
+
* console.error(result.error);
|
|
123
|
+
* }
|
|
124
|
+
*
|
|
125
|
+
* // With custom options
|
|
126
|
+
* const result2 = validateJMESPathSecure('expression', { maxLength: 500 });
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
declare function validateJMESPathSecure(expression: string, options?: SecurityOptions): ValidationResult;
|
|
130
|
+
/**
|
|
131
|
+
* Options for jmespathString Zod schema factory.
|
|
132
|
+
*/
|
|
133
|
+
interface JMESPathStringOptions {
|
|
134
|
+
maxLength?: number;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Creates a Zod string schema for JMESPath expressions with OpenAPI-visible constraints.
|
|
138
|
+
* Includes maxLength constraint and a description with valid/invalid examples.
|
|
139
|
+
*
|
|
140
|
+
* @param options - Optional configuration for the schema
|
|
141
|
+
* @returns A Zod string schema with maxLength and description
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```typescript
|
|
145
|
+
* const schema = z.object({
|
|
146
|
+
* transform: jmespathString().optional(),
|
|
147
|
+
* });
|
|
148
|
+
* ```
|
|
149
|
+
*/
|
|
150
|
+
declare function jmespathString(options?: JMESPathStringOptions): z.ZodString;
|
|
151
|
+
//#endregion
|
|
152
|
+
export { DANGEROUS_PATTERNS, JMESPathStringOptions, MAX_EXPRESSION_LENGTH, SecurityOptions, ValidationResult, compileJMESPath, jmespathString, normalizeJMESPath, searchJMESPath, validateJMESPath, validateJMESPathSecure, validateRegex };
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { z } from "@hono/zod-openapi";
|
|
2
|
+
import * as jmespath from "jmespath";
|
|
3
|
+
|
|
4
|
+
//#region src/utils/jmespath-utils.ts
|
|
5
|
+
const jmespathExt = jmespath;
|
|
6
|
+
/**
|
|
7
|
+
* Maximum allowed length for JMESPath expressions.
|
|
8
|
+
*/
|
|
9
|
+
const MAX_EXPRESSION_LENGTH = 1e3;
|
|
10
|
+
/**
|
|
11
|
+
* Validates a JMESPath expression by attempting to compile it.
|
|
12
|
+
* Uses the jmespath package which is already available in the codebase.
|
|
13
|
+
*
|
|
14
|
+
* @param expression - The JMESPath expression to validate
|
|
15
|
+
* @returns ValidationResult with valid flag and optional error message
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* const result = validateJMESPath('body.user.id');
|
|
20
|
+
* if (!result.valid) {
|
|
21
|
+
* console.error(result.error);
|
|
22
|
+
* }
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
function validateJMESPath(expression) {
|
|
26
|
+
if (!expression || typeof expression !== "string") return {
|
|
27
|
+
valid: false,
|
|
28
|
+
error: "JMESPath expression must be a non-empty string"
|
|
29
|
+
};
|
|
30
|
+
try {
|
|
31
|
+
jmespathExt.compile(expression);
|
|
32
|
+
return { valid: true };
|
|
33
|
+
} catch (error) {
|
|
34
|
+
return {
|
|
35
|
+
valid: false,
|
|
36
|
+
error: `Invalid JMESPath expression: ${error instanceof Error ? error.message : String(error)}`
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Validates a regex pattern by attempting to construct a RegExp object.
|
|
42
|
+
* Returns clear error messages for common regex issues.
|
|
43
|
+
*
|
|
44
|
+
* @param pattern - The regex pattern to validate (without delimiters)
|
|
45
|
+
* @returns ValidationResult with valid flag and optional error message
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* const result = validateRegex('v\\d+,(.+)');
|
|
50
|
+
* if (!result.valid) {
|
|
51
|
+
* console.error(result.error);
|
|
52
|
+
* }
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
function validateRegex(pattern) {
|
|
56
|
+
if (pattern === null || pattern === void 0) return {
|
|
57
|
+
valid: false,
|
|
58
|
+
error: "Regex pattern must be provided"
|
|
59
|
+
};
|
|
60
|
+
if (typeof pattern !== "string") return {
|
|
61
|
+
valid: false,
|
|
62
|
+
error: "Regex pattern must be a string"
|
|
63
|
+
};
|
|
64
|
+
if (pattern === "") return { valid: true };
|
|
65
|
+
try {
|
|
66
|
+
new RegExp(pattern);
|
|
67
|
+
return { valid: true };
|
|
68
|
+
} catch (error) {
|
|
69
|
+
return {
|
|
70
|
+
valid: false,
|
|
71
|
+
error: `Invalid regex pattern: ${error instanceof Error ? error.message : String(error)}`
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Compiles a JMESPath expression.
|
|
77
|
+
* Wrapper around jmespath.compile() with proper typing.
|
|
78
|
+
*
|
|
79
|
+
* @param expression - The JMESPath expression to compile
|
|
80
|
+
* @returns The compiled expression object
|
|
81
|
+
* @throws Error if the expression is invalid
|
|
82
|
+
*/
|
|
83
|
+
function compileJMESPath(expression) {
|
|
84
|
+
return jmespathExt.compile(expression);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Safely searches data using a JMESPath expression.
|
|
88
|
+
* Wrapper around jmespath.search() with proper typing.
|
|
89
|
+
*
|
|
90
|
+
* @param data - The object to search (e.g., template context, webhook body, tool result)
|
|
91
|
+
* @param expression - The JMESPath expression
|
|
92
|
+
* @returns The search result
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```typescript
|
|
96
|
+
* const data = { users: [{ name: 'Alice' }] };
|
|
97
|
+
* const name = searchJMESPath<string>(data, 'users[0].name');
|
|
98
|
+
* // name is 'Alice'
|
|
99
|
+
*
|
|
100
|
+
* // Common use cases:
|
|
101
|
+
* // - Template contexts: { headers: {...}, body: {...} }
|
|
102
|
+
* // - Webhook payloads: { event: "...", data: {...} }
|
|
103
|
+
* // - Tool results: { status: "success", result: {...} }
|
|
104
|
+
* ```
|
|
105
|
+
*/
|
|
106
|
+
function searchJMESPath(data, expression) {
|
|
107
|
+
return jmespath.search(data, expression);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Normalize a JMESPath expression by wrapping property names with dashes in quotes.
|
|
111
|
+
* JMESPath requires identifiers with special characters (like dashes) to be quoted.
|
|
112
|
+
*
|
|
113
|
+
* @param path - The JMESPath expression to normalize
|
|
114
|
+
* @returns The normalized JMESPath expression
|
|
115
|
+
*
|
|
116
|
+
* @example
|
|
117
|
+
* ```typescript
|
|
118
|
+
* normalizeJMESPath('headers.x-tenant-id');
|
|
119
|
+
* // Returns: 'headers."x-tenant-id"'
|
|
120
|
+
*
|
|
121
|
+
* normalizeJMESPath('api-responses[0].response-code');
|
|
122
|
+
* // Returns: '"api-responses"[0]."response-code"'
|
|
123
|
+
*
|
|
124
|
+
* normalizeJMESPath('simple.path');
|
|
125
|
+
* // Returns: 'simple.path' (unchanged)
|
|
126
|
+
* ```
|
|
127
|
+
*/
|
|
128
|
+
function normalizeJMESPath(path) {
|
|
129
|
+
return path.split(".").map((segment) => {
|
|
130
|
+
if (!segment.includes("-")) return segment;
|
|
131
|
+
if (segment.startsWith("\"") && segment.includes("\"")) return segment;
|
|
132
|
+
const bracketIndex = segment.indexOf("[");
|
|
133
|
+
if (bracketIndex !== -1) return `"${segment.substring(0, bracketIndex)}"${segment.substring(bracketIndex)}`;
|
|
134
|
+
return `"${segment}"`;
|
|
135
|
+
}).join(".");
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Dangerous patterns that should not appear in JMESPath expressions.
|
|
139
|
+
* These patterns are checked during secure validation to prevent injection attacks.
|
|
140
|
+
*/
|
|
141
|
+
const DANGEROUS_PATTERNS = [
|
|
142
|
+
/\$\{.*\}/,
|
|
143
|
+
/eval\s*\(/,
|
|
144
|
+
/function\s*\(/,
|
|
145
|
+
/constructor/,
|
|
146
|
+
/prototype/,
|
|
147
|
+
/__proto__/
|
|
148
|
+
];
|
|
149
|
+
/**
|
|
150
|
+
* Validates a JMESPath expression with security checks.
|
|
151
|
+
* Performs checks in order of cost: length (O(1)), patterns (O(n)), compile (expensive).
|
|
152
|
+
*
|
|
153
|
+
* @param expression - The JMESPath expression to validate
|
|
154
|
+
* @param options - Optional security options
|
|
155
|
+
* @returns ValidationResult with valid flag and optional error message
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* ```typescript
|
|
159
|
+
* const result = validateJMESPathSecure('body.user.id');
|
|
160
|
+
* if (!result.valid) {
|
|
161
|
+
* console.error(result.error);
|
|
162
|
+
* }
|
|
163
|
+
*
|
|
164
|
+
* // With custom options
|
|
165
|
+
* const result2 = validateJMESPathSecure('expression', { maxLength: 500 });
|
|
166
|
+
* ```
|
|
167
|
+
*/
|
|
168
|
+
function validateJMESPathSecure(expression, options) {
|
|
169
|
+
if (!expression || typeof expression !== "string") return {
|
|
170
|
+
valid: false,
|
|
171
|
+
error: "JMESPath expression must be a non-empty string"
|
|
172
|
+
};
|
|
173
|
+
const maxLength = options?.maxLength ?? MAX_EXPRESSION_LENGTH;
|
|
174
|
+
const patterns = options?.dangerousPatterns ?? DANGEROUS_PATTERNS;
|
|
175
|
+
if (expression.length > maxLength) return {
|
|
176
|
+
valid: false,
|
|
177
|
+
error: `JMESPath expression exceeds maximum length of ${maxLength} characters`
|
|
178
|
+
};
|
|
179
|
+
for (const pattern of patterns) if (pattern.test(expression)) return {
|
|
180
|
+
valid: false,
|
|
181
|
+
error: `JMESPath expression contains dangerous pattern: ${pattern.source}`
|
|
182
|
+
};
|
|
183
|
+
try {
|
|
184
|
+
jmespathExt.compile(expression);
|
|
185
|
+
return { valid: true };
|
|
186
|
+
} catch (error) {
|
|
187
|
+
return {
|
|
188
|
+
valid: false,
|
|
189
|
+
error: `Invalid JMESPath expression: ${error instanceof Error ? error.message : String(error)}`
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Creates a Zod string schema for JMESPath expressions with OpenAPI-visible constraints.
|
|
195
|
+
* Includes maxLength constraint and a description with valid/invalid examples.
|
|
196
|
+
*
|
|
197
|
+
* @param options - Optional configuration for the schema
|
|
198
|
+
* @returns A Zod string schema with maxLength and description
|
|
199
|
+
*
|
|
200
|
+
* @example
|
|
201
|
+
* ```typescript
|
|
202
|
+
* const schema = z.object({
|
|
203
|
+
* transform: jmespathString().optional(),
|
|
204
|
+
* });
|
|
205
|
+
* ```
|
|
206
|
+
*/
|
|
207
|
+
function jmespathString(options) {
|
|
208
|
+
const maxLen = options?.maxLength ?? MAX_EXPRESSION_LENGTH;
|
|
209
|
+
return z.string().max(maxLen).describe(`JMESPath expression (max ${maxLen} chars). Valid: "data.items[0].name", "results[?status=='active']", "keys(@)". Invalid: "\${...}" (template injection), "eval" calls, "constructor", "__proto__".`);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
//#endregion
|
|
213
|
+
export { DANGEROUS_PATTERNS, MAX_EXPRESSION_LENGTH, compileJMESPath, jmespathString, normalizeJMESPath, searchJMESPath, validateJMESPath, validateJMESPathSecure, validateRegex };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
//#region src/utils/jwt-helpers.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Get the JWT signing secret from environment variables.
|
|
4
|
+
* Falls back to an insecure default in non-production environments.
|
|
5
|
+
*/
|
|
6
|
+
declare function getJwtSecret(): Uint8Array;
|
|
7
|
+
/**
|
|
8
|
+
* Common verification result structure
|
|
9
|
+
*/
|
|
10
|
+
interface JwtVerifyResult<T> {
|
|
11
|
+
valid: boolean;
|
|
12
|
+
payload?: T;
|
|
13
|
+
error?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Options for signing a JWT
|
|
17
|
+
*/
|
|
18
|
+
interface SignJwtOptions {
|
|
19
|
+
issuer: string;
|
|
20
|
+
subject: string;
|
|
21
|
+
audience?: string;
|
|
22
|
+
expiresIn?: string;
|
|
23
|
+
claims?: Record<string, unknown>;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Sign a JWT with the shared secret
|
|
27
|
+
*/
|
|
28
|
+
declare function signJwt(options: SignJwtOptions): Promise<string>;
|
|
29
|
+
/**
|
|
30
|
+
* Options for verifying a JWT
|
|
31
|
+
*/
|
|
32
|
+
interface VerifyJwtOptions {
|
|
33
|
+
issuer: string;
|
|
34
|
+
audience?: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Verify a JWT and return the raw payload
|
|
38
|
+
*/
|
|
39
|
+
declare function verifyJwt(token: string, options: VerifyJwtOptions): Promise<JwtVerifyResult<Record<string, unknown>>>;
|
|
40
|
+
/**
|
|
41
|
+
* Extract bearer token from Authorization header
|
|
42
|
+
*/
|
|
43
|
+
declare function extractBearerToken(authHeader: string | undefined): {
|
|
44
|
+
token?: string;
|
|
45
|
+
error?: string;
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Decode JWT payload without verification (for checking issuer before full verify)
|
|
49
|
+
*/
|
|
50
|
+
declare function decodeJwtPayload(token: string): Record<string, unknown> | null;
|
|
51
|
+
/**
|
|
52
|
+
* Check if a token has a specific issuer (without full verification)
|
|
53
|
+
*/
|
|
54
|
+
declare function hasIssuer(token: string, issuer: string): boolean;
|
|
55
|
+
//#endregion
|
|
56
|
+
export { JwtVerifyResult, SignJwtOptions, VerifyJwtOptions, decodeJwtPayload, extractBearerToken, getJwtSecret, hasIssuer, signJwt, verifyJwt };
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { env } from "../env.js";
|
|
2
|
+
import { getLogger } from "./logger.js";
|
|
3
|
+
import { SignJWT, jwtVerify } from "jose";
|
|
4
|
+
|
|
5
|
+
//#region src/utils/jwt-helpers.ts
|
|
6
|
+
const logger = getLogger("jwt-helpers");
|
|
7
|
+
const DEV_SECRET = "insecure-dev-secret-change-in-production-min-32-chars";
|
|
8
|
+
/**
|
|
9
|
+
* Get the JWT signing secret from environment variables.
|
|
10
|
+
* Falls back to an insecure default in non-production environments.
|
|
11
|
+
*/
|
|
12
|
+
function getJwtSecret() {
|
|
13
|
+
const secret = env.INKEEP_AGENTS_JWT_SIGNING_SECRET;
|
|
14
|
+
if (!secret) {
|
|
15
|
+
if (env.ENVIRONMENT === "production") throw new Error("INKEEP_AGENTS_JWT_SIGNING_SECRET environment variable is required in production");
|
|
16
|
+
logger.warn({}, "INKEEP_AGENTS_JWT_SIGNING_SECRET not set, using insecure default. DO NOT USE IN PRODUCTION!");
|
|
17
|
+
return new TextEncoder().encode(DEV_SECRET);
|
|
18
|
+
}
|
|
19
|
+
return new TextEncoder().encode(secret);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Sign a JWT with the shared secret
|
|
23
|
+
*/
|
|
24
|
+
async function signJwt(options) {
|
|
25
|
+
const secret = getJwtSecret();
|
|
26
|
+
const builder = new SignJWT(options.claims || {}).setProtectedHeader({
|
|
27
|
+
alg: "HS256",
|
|
28
|
+
typ: "JWT"
|
|
29
|
+
}).setIssuer(options.issuer).setSubject(options.subject).setIssuedAt().setExpirationTime(options.expiresIn || "5m");
|
|
30
|
+
if (options.audience) builder.setAudience(options.audience);
|
|
31
|
+
return builder.sign(secret);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Verify a JWT and return the raw payload
|
|
35
|
+
*/
|
|
36
|
+
async function verifyJwt(token, options) {
|
|
37
|
+
const secret = getJwtSecret();
|
|
38
|
+
try {
|
|
39
|
+
const verifyOptions = {
|
|
40
|
+
issuer: options.issuer,
|
|
41
|
+
algorithms: ["HS256"]
|
|
42
|
+
};
|
|
43
|
+
if (options.audience) verifyOptions.audience = options.audience;
|
|
44
|
+
const { payload } = await jwtVerify(token, secret, verifyOptions);
|
|
45
|
+
return {
|
|
46
|
+
valid: true,
|
|
47
|
+
payload
|
|
48
|
+
};
|
|
49
|
+
} catch (error) {
|
|
50
|
+
if (error instanceof Error) return {
|
|
51
|
+
valid: false,
|
|
52
|
+
error: error.message
|
|
53
|
+
};
|
|
54
|
+
return {
|
|
55
|
+
valid: false,
|
|
56
|
+
error: "Token verification failed"
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Extract bearer token from Authorization header
|
|
62
|
+
*/
|
|
63
|
+
function extractBearerToken(authHeader) {
|
|
64
|
+
if (!authHeader) return { error: "Missing Authorization header" };
|
|
65
|
+
if (!authHeader.startsWith("Bearer ")) return { error: "Invalid Authorization header format. Expected: Bearer <token>" };
|
|
66
|
+
const token = authHeader.substring(7);
|
|
67
|
+
if (!token) return { error: "Empty token in Authorization header" };
|
|
68
|
+
return { token };
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Decode JWT payload without verification (for checking issuer before full verify)
|
|
72
|
+
*/
|
|
73
|
+
function decodeJwtPayload(token) {
|
|
74
|
+
try {
|
|
75
|
+
const parts = token.split(".");
|
|
76
|
+
if (parts.length !== 3) return null;
|
|
77
|
+
return JSON.parse(Buffer.from(parts[1], "base64url").toString());
|
|
78
|
+
} catch {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Check if a token has a specific issuer (without full verification)
|
|
84
|
+
*/
|
|
85
|
+
function hasIssuer(token, issuer) {
|
|
86
|
+
return decodeJwtPayload(token)?.iss === issuer;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
//#endregion
|
|
90
|
+
export { decodeJwtPayload, extractBearerToken, getJwtSecret, hasIssuer, signJwt, verifyJwt };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { MCPTransportType } from "../types/utility.js";
|
|
2
|
+
import { ClientCapabilities } from "@modelcontextprotocol/sdk/types.js";
|
|
2
3
|
import { SSEClientTransportOptions } from "@modelcontextprotocol/sdk/client/sse.js";
|
|
3
4
|
import { StreamableHTTPClientTransportOptions } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
4
|
-
import { ClientCapabilities } from "@modelcontextprotocol/sdk/types.js";
|
|
5
5
|
|
|
6
6
|
//#region src/utils/mcp-client.d.ts
|
|
7
7
|
interface SharedServerConfig {
|
package/dist/utils/mcp-client.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { MCPTransportType } from "../types/utility.js";
|
|
2
2
|
import { MCP_TOOL_CONNECTION_TIMEOUT_MS, MCP_TOOL_INITIAL_RECONNECTION_DELAY_MS, MCP_TOOL_MAX_RECONNECTION_DELAY_MS, MCP_TOOL_MAX_RETRIES, MCP_TOOL_RECONNECTION_DELAY_GROWTH_FACTOR } from "../constants/execution-limits-shared/index.js";
|
|
3
3
|
import { z } from "@hono/zod-openapi";
|
|
4
|
+
import { CallToolResultSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
4
5
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
5
6
|
import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
|
|
6
7
|
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
7
8
|
import { DEFAULT_REQUEST_TIMEOUT_MSEC } from "@modelcontextprotocol/sdk/shared/protocol.js";
|
|
8
|
-
import { CallToolResultSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
9
9
|
import { tool } from "ai";
|
|
10
10
|
import { asyncExitHook, gracefulExit } from "exit-hook";
|
|
11
11
|
import { match } from "ts-pattern";
|