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':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/datastore
|
||||
'@bytelyst/design-tokens':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/design-tokens
|
||||
'@bytelyst/errors':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/errors
|
||||
@ -347,6 +350,24 @@ importers:
|
||||
specifier: '>=4.0.0'
|
||||
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:
|
||||
dependencies:
|
||||
'@azure/cosmos':
|
||||
@ -627,6 +648,43 @@ importers:
|
||||
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/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:
|
||||
devDependencies:
|
||||
'@bytelyst/monitoring':
|
||||
@ -9465,6 +9523,12 @@ packages:
|
||||
}
|
||||
hasBin: true
|
||||
|
||||
jose@5.10.0:
|
||||
resolution:
|
||||
{
|
||||
integrity: sha512-s+3Al/p9g32Iq+oqXxkW//7jk2Vig6FF1CFqzVXoTUXt2qz89YWbL+OwS17NFYEvxC35n0FKeGO2LGYSxeM2Gg==,
|
||||
}
|
||||
|
||||
jose@6.1.3:
|
||||
resolution:
|
||||
{
|
||||
@ -20412,6 +20476,8 @@ snapshots:
|
||||
|
||||
jiti@2.6.1: {}
|
||||
|
||||
jose@5.10.0: {}
|
||||
|
||||
jose@6.1.3: {}
|
||||
|
||||
js-tokens@10.0.0: {}
|
||||
|
||||
@ -16,7 +16,9 @@
|
||||
"@bytelyst/config": "workspace:*",
|
||||
"@bytelyst/errors": "workspace:*",
|
||||
"@bytelyst/fastify-core": "workspace:*",
|
||||
"@fastify/cors": "^10.0.2",
|
||||
"fastify": "^5.2.1",
|
||||
"jose": "^5.9.6",
|
||||
"zod": "^3.24.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import { jwtVerify } from 'jose';
|
||||
import { UnauthorizedError, ForbiddenError } from '@bytelyst/errors';
|
||||
import { config } from './config.js';
|
||||
|
||||
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 {
|
||||
if (!req.jwtPayload?.sub)
|
||||
throw Object.assign(new Error('Authentication required'), { statusCode: 401 });
|
||||
if (!req.jwtPayload?.sub) throw new UnauthorizedError('Authentication required');
|
||||
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 userLevel = order.indexOf(payload.role ?? 'viewer');
|
||||
const requiredLevel = order.indexOf(minRole);
|
||||
if (userLevel < requiredLevel) {
|
||||
throw Object.assign(new Error(`Role '${minRole}' required`), { statusCode: 403 });
|
||||
}
|
||||
if (userLevel < requiredLevel) throw new ForbiddenError(`Role '${minRole}' required`);
|
||||
return payload;
|
||||
}
|
||||
|
||||
@ -21,7 +21,11 @@ async function platformFetch<T>(
|
||||
...(opts.requestId ? { 'x-request-id': opts.requestId } : {}),
|
||||
...(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) {
|
||||
const body = await res.text().catch(() => '');
|
||||
throw new Error(`platform-service ${init.method ?? 'GET'} ${path} → ${res.status}: ${body}`);
|
||||
|
||||
@ -28,11 +28,6 @@ const app = await createServiceApp({
|
||||
description:
|
||||
'ByteLyst MCP Server — platform.telemetry.*, platform.diagnostics.*, extraction.*, support.*',
|
||||
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)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user