fix(mcp-server): add missing jose + @fastify/cors deps; use ServiceError subclasses for 401/403; remove swagger option that crashed startup; add AbortSignal.timeout to platformFetch
This commit is contained in:
parent
eb5c3b1c66
commit
9a298d50ef
66
pnpm-lock.yaml
generated
66
pnpm-lock.yaml
generated
@ -92,6 +92,9 @@ importers:
|
|||||||
'@bytelyst/datastore':
|
'@bytelyst/datastore':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../packages/datastore
|
version: link:../../packages/datastore
|
||||||
|
'@bytelyst/design-tokens':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../packages/design-tokens
|
||||||
'@bytelyst/errors':
|
'@bytelyst/errors':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../../packages/errors
|
version: link:../../packages/errors
|
||||||
@ -347,6 +350,24 @@ importers:
|
|||||||
specifier: '>=4.0.0'
|
specifier: '>=4.0.0'
|
||||||
version: 4.9.1(@azure/core-client@1.10.1)
|
version: 4.9.1(@azure/core-client@1.10.1)
|
||||||
|
|
||||||
|
packages/dashboard-components:
|
||||||
|
devDependencies:
|
||||||
|
'@types/react':
|
||||||
|
specifier: ^19.0.0
|
||||||
|
version: 19.2.14
|
||||||
|
'@types/react-dom':
|
||||||
|
specifier: ^19.0.0
|
||||||
|
version: 19.2.3(@types/react@19.2.14)
|
||||||
|
react:
|
||||||
|
specifier: ^19.0.0
|
||||||
|
version: 19.2.4
|
||||||
|
react-dom:
|
||||||
|
specifier: ^19.0.0
|
||||||
|
version: 19.2.4(react@19.2.4)
|
||||||
|
typescript:
|
||||||
|
specifier: ^5.7.3
|
||||||
|
version: 5.9.3
|
||||||
|
|
||||||
packages/datastore:
|
packages/datastore:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@azure/cosmos':
|
'@azure/cosmos':
|
||||||
@ -627,6 +648,43 @@ importers:
|
|||||||
specifier: ^3.0.5
|
specifier: ^3.0.5
|
||||||
version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.11)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@28.0.0(@noble/hashes@1.8.0))(lightningcss@1.31.1)(msw@2.12.10(@types/node@22.19.11)(typescript@5.9.3))(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)
|
version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.11)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@28.0.0(@noble/hashes@1.8.0))(lightningcss@1.31.1)(msw@2.12.10(@types/node@22.19.11)(typescript@5.9.3))(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)
|
||||||
|
|
||||||
|
services/mcp-server:
|
||||||
|
dependencies:
|
||||||
|
'@bytelyst/config':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../packages/config
|
||||||
|
'@bytelyst/errors':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../packages/errors
|
||||||
|
'@bytelyst/fastify-core':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../packages/fastify-core
|
||||||
|
'@fastify/cors':
|
||||||
|
specifier: ^10.0.2
|
||||||
|
version: 10.1.0
|
||||||
|
fastify:
|
||||||
|
specifier: ^5.2.1
|
||||||
|
version: 5.7.4
|
||||||
|
jose:
|
||||||
|
specifier: ^5.9.6
|
||||||
|
version: 5.10.0
|
||||||
|
zod:
|
||||||
|
specifier: ^3.24.2
|
||||||
|
version: 3.25.76
|
||||||
|
devDependencies:
|
||||||
|
'@types/node':
|
||||||
|
specifier: ^22.12.0
|
||||||
|
version: 22.19.11
|
||||||
|
tsx:
|
||||||
|
specifier: ^4.19.2
|
||||||
|
version: 4.21.0
|
||||||
|
typescript:
|
||||||
|
specifier: ^5.7.3
|
||||||
|
version: 5.9.3
|
||||||
|
vitest:
|
||||||
|
specifier: ^3.0.5
|
||||||
|
version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.11)(happy-dom@18.0.1)(jiti@2.6.1)(jsdom@28.0.0(@noble/hashes@1.8.0))(lightningcss@1.31.1)(msw@2.12.10(@types/node@22.19.11)(typescript@5.9.3))(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)
|
||||||
|
|
||||||
services/monitoring:
|
services/monitoring:
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@bytelyst/monitoring':
|
'@bytelyst/monitoring':
|
||||||
@ -9465,6 +9523,12 @@ packages:
|
|||||||
}
|
}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
jose@5.10.0:
|
||||||
|
resolution:
|
||||||
|
{
|
||||||
|
integrity: sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==,
|
||||||
|
}
|
||||||
|
|
||||||
jose@6.1.3:
|
jose@6.1.3:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
@ -20412,6 +20476,8 @@ snapshots:
|
|||||||
|
|
||||||
jiti@2.6.1: {}
|
jiti@2.6.1: {}
|
||||||
|
|
||||||
|
jose@5.10.0: {}
|
||||||
|
|
||||||
jose@6.1.3: {}
|
jose@6.1.3: {}
|
||||||
|
|
||||||
js-tokens@10.0.0: {}
|
js-tokens@10.0.0: {}
|
||||||
|
|||||||
@ -16,7 +16,9 @@
|
|||||||
"@bytelyst/config": "workspace:*",
|
"@bytelyst/config": "workspace:*",
|
||||||
"@bytelyst/errors": "workspace:*",
|
"@bytelyst/errors": "workspace:*",
|
||||||
"@bytelyst/fastify-core": "workspace:*",
|
"@bytelyst/fastify-core": "workspace:*",
|
||||||
|
"@fastify/cors": "^10.0.2",
|
||||||
"fastify": "^5.2.1",
|
"fastify": "^5.2.1",
|
||||||
|
"jose": "^5.9.6",
|
||||||
"zod": "^3.24.2"
|
"zod": "^3.24.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import { jwtVerify } from 'jose';
|
import { jwtVerify } from 'jose';
|
||||||
|
import { UnauthorizedError, ForbiddenError } from '@bytelyst/errors';
|
||||||
import { config } from './config.js';
|
import { config } from './config.js';
|
||||||
|
|
||||||
export type Role = 'viewer' | 'admin' | 'super_admin';
|
export type Role = 'viewer' | 'admin' | 'super_admin';
|
||||||
@ -38,8 +39,7 @@ export async function parseJwt(req: FastifyRequest): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function requireAuth(req: AuthRequest): JwtPayload {
|
export function requireAuth(req: AuthRequest): JwtPayload {
|
||||||
if (!req.jwtPayload?.sub)
|
if (!req.jwtPayload?.sub) throw new UnauthorizedError('Authentication required');
|
||||||
throw Object.assign(new Error('Authentication required'), { statusCode: 401 });
|
|
||||||
return req.jwtPayload as JwtPayload;
|
return req.jwtPayload as JwtPayload;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -48,8 +48,6 @@ export function requireRole(req: AuthRequest, minRole: Role): JwtPayload {
|
|||||||
const order: Role[] = ['viewer', 'admin', 'super_admin'];
|
const order: Role[] = ['viewer', 'admin', 'super_admin'];
|
||||||
const userLevel = order.indexOf(payload.role ?? 'viewer');
|
const userLevel = order.indexOf(payload.role ?? 'viewer');
|
||||||
const requiredLevel = order.indexOf(minRole);
|
const requiredLevel = order.indexOf(minRole);
|
||||||
if (userLevel < requiredLevel) {
|
if (userLevel < requiredLevel) throw new ForbiddenError(`Role '${minRole}' required`);
|
||||||
throw Object.assign(new Error(`Role '${minRole}' required`), { statusCode: 403 });
|
|
||||||
}
|
|
||||||
return payload;
|
return payload;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,7 +21,11 @@ async function platformFetch<T>(
|
|||||||
...(opts.requestId ? { 'x-request-id': opts.requestId } : {}),
|
...(opts.requestId ? { 'x-request-id': opts.requestId } : {}),
|
||||||
...(opts.productId ? { 'x-product-id': opts.productId } : {}),
|
...(opts.productId ? { 'x-product-id': opts.productId } : {}),
|
||||||
};
|
};
|
||||||
const res = await fetch(url, { ...init, headers: { ...headers, ...(init.headers ?? {}) } });
|
const res = await fetch(url, {
|
||||||
|
...init,
|
||||||
|
headers: { ...headers, ...(init.headers ?? {}) },
|
||||||
|
signal: AbortSignal.timeout(10_000),
|
||||||
|
});
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
const body = await res.text().catch(() => '');
|
const body = await res.text().catch(() => '');
|
||||||
throw new Error(`platform-service ${init.method ?? 'GET'} ${path} → ${res.status}: ${body}`);
|
throw new Error(`platform-service ${init.method ?? 'GET'} ${path} → ${res.status}: ${body}`);
|
||||||
|
|||||||
@ -28,11 +28,6 @@ const app = await createServiceApp({
|
|||||||
description:
|
description:
|
||||||
'ByteLyst MCP Server — platform.telemetry.*, platform.diagnostics.*, extraction.*, support.*',
|
'ByteLyst MCP Server — platform.telemetry.*, platform.diagnostics.*, extraction.*, support.*',
|
||||||
corsOrigin: config.CORS_ORIGIN,
|
corsOrigin: config.CORS_ORIGIN,
|
||||||
swagger: {
|
|
||||||
title: 'ByteLyst MCP Server',
|
|
||||||
description: 'MCP tool execution endpoint for the ByteLyst platform',
|
|
||||||
port: config.PORT,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Parse JWT on every request (best-effort)
|
// Parse JWT on every request (best-effort)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user