@kb-labs/gateway-app 2.96.0 → 2.100.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/index.js +52 -17
- package/dist/index.js.map +1 -1
- package/package.json +28 -28
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import { createServiceBootstrap, platform, getPlatformRoot, getProjectRoot, getA
|
|
|
4
4
|
import { makeAssemblyHook } from '@kb-labs/plugin-runtime';
|
|
5
5
|
import { createCorrelatedLogger, registerOpenAPI, createServiceReadyResponse, OperationMetricsTracker, createServiceObservabilityDescribe, createServiceObservabilityHealth } from '@kb-labs/shared-http';
|
|
6
6
|
import { HostStore, globalDispatcher, AdaptiveBuffer } from '@kb-labs/gateway-core';
|
|
7
|
-
import { UsersStore, CredentialsStore, MembershipsStore, SessionsStore, InvitesStore, loadIdentityProviders, createPasswordPolicy, createStubPDP, createTenantResolver, createUserAuthService, ensureBootstrapAdmin, createRateLimiter, OAuthStateStore, AuthService, verifyUserAccessToken, AuthError, getClientByHandle, issueCsrfToken, verifyCsrfToken, getClientByHostId } from '@kb-labs/gateway-auth';
|
|
7
|
+
import { UsersStore, CredentialsStore, MembershipsStore, SessionsStore, InvitesStore, loadIdentityProviders, createPasswordPolicy, createStubPDP, createTenantResolver, createUserAuthService, ensureBootstrapAdmin, createRateLimiter, OAuthStateStore, AuthService, ensureBootstrapCliCredentials, verifyUserAccessToken, AuthError, getClientByHandle, issueCsrfToken, verifyCsrfToken, getClientByHostId } from '@kb-labs/gateway-auth';
|
|
8
8
|
import { createRegistry, mergeOpenAPISpecs } from '@kb-labs/core-registry';
|
|
9
9
|
import { loadEffectiveConfig } from '@kb-labs/core-config';
|
|
10
10
|
import { GatewayConfigSchema, HostRegistrationSchema, RegisterRequestSchema, TokenRequestSchema, RefreshRequestSchema, ExecuteRequestSchema, ChatCompletionRequestSchema, TelemetryIngestRequestSchema, PlatformCallRequestSchema, HelloMessageSchema, SUPPORTED_PROTOCOL_VERSIONS, HostCapabilitySchema, AdapterCallMessageSchema, AdapterNameSchema, ClientHelloSchema, ClientCancelSchema, ClientUnsubscribeSchema, ClientSubscribeSchema, CLIENT_PROTOCOL_VERSION } from '@kb-labs/gateway-contracts';
|
|
@@ -68,6 +68,14 @@ var PUBLIC_ROUTES = /* @__PURE__ */ new Set([
|
|
|
68
68
|
"/health",
|
|
69
69
|
"/health/adapters",
|
|
70
70
|
"/ready",
|
|
71
|
+
// Studio SPA shell (index.html) — the login page itself. There is no
|
|
72
|
+
// session yet when a browser first hits this, so it can't be gated.
|
|
73
|
+
// Exact match only (not a prefix) so it doesn't swallow unrelated routes.
|
|
74
|
+
"/",
|
|
75
|
+
// Module Federation manifest — static, non-sensitive metadata describing
|
|
76
|
+
// available Studio remotes. The Studio SPA shell must be able to fetch
|
|
77
|
+
// this before a user has logged in (there is no session yet to gate on).
|
|
78
|
+
"/mf-manifest.json",
|
|
71
79
|
"/hosts/register",
|
|
72
80
|
// /hosts/connect and /clients/connect are handled at the HTTP upgrade level
|
|
73
81
|
// by gateway-ws.ts (raw ws) — they never reach Fastify routing.
|
|
@@ -99,6 +107,15 @@ function createAuthMiddleware(cache, jwtConfig, options = {}) {
|
|
|
99
107
|
if (routePath.startsWith("/auth/oauth/")) {
|
|
100
108
|
return;
|
|
101
109
|
}
|
|
110
|
+
if (routePath.startsWith("/webhooks/")) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
if (routePath.startsWith("/plugins/")) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
if (routePath.startsWith("/studio/")) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
102
119
|
const queryToken = request.query["access_token"];
|
|
103
120
|
const token = extractBearerToken(request.headers.authorization) ?? queryToken ?? null;
|
|
104
121
|
if (!token && request.userAuthContext) {
|
|
@@ -493,7 +510,12 @@ function registerUserAuthRoutes(app, deps) {
|
|
|
493
510
|
if (!auth) {
|
|
494
511
|
return reply.code(401).send({ error: "Unauthorized", message: "Not authenticated" });
|
|
495
512
|
}
|
|
496
|
-
return reply.send({
|
|
513
|
+
return reply.send({
|
|
514
|
+
userId: auth.userId,
|
|
515
|
+
namespaceId: auth.namespaceId,
|
|
516
|
+
email: auth.userId,
|
|
517
|
+
tenantId: auth.namespaceId
|
|
518
|
+
});
|
|
497
519
|
});
|
|
498
520
|
app.get("/auth/providers", {
|
|
499
521
|
schema: { tags: ["Auth"], summary: "List registered identity providers" }
|
|
@@ -1292,7 +1314,7 @@ async function resolveLLMForTier(tier) {
|
|
|
1292
1314
|
return llm;
|
|
1293
1315
|
}
|
|
1294
1316
|
function registerLLMGatewayRoutes(app, logger) {
|
|
1295
|
-
app.post("/
|
|
1317
|
+
app.post("/api/v1/llm/chat/completions", { schema: { tags: ["LLM"], summary: "OpenAI-compatible chat completions", hide: true } }, async (request, reply) => {
|
|
1296
1318
|
const auth = request.authContext;
|
|
1297
1319
|
if (!auth) {
|
|
1298
1320
|
return reply.code(401).send({ error: "Unauthorized" });
|
|
@@ -3782,6 +3804,20 @@ async function createServer(config, cache, logger, jwtConfig, registry, serviceT
|
|
|
3782
3804
|
statusCode: reply.statusCode
|
|
3783
3805
|
});
|
|
3784
3806
|
});
|
|
3807
|
+
if (userAuth) {
|
|
3808
|
+
app.addHook(
|
|
3809
|
+
"onRequest",
|
|
3810
|
+
createUserAuthMiddleware({
|
|
3811
|
+
users: userAuth.users,
|
|
3812
|
+
tenantResolver: userAuth.tenantResolver,
|
|
3813
|
+
jwtConfig
|
|
3814
|
+
})
|
|
3815
|
+
);
|
|
3816
|
+
}
|
|
3817
|
+
app.addHook(
|
|
3818
|
+
"onRequest",
|
|
3819
|
+
createAuthMiddleware(cache, jwtConfig, { authEnabled: config.auth?.enabled !== false })
|
|
3820
|
+
);
|
|
3785
3821
|
const socketWsUpstreams = [];
|
|
3786
3822
|
for (const [name, upstream] of Object.entries(config.upstreams)) {
|
|
3787
3823
|
const conn = serviceTransport.connectionInfo(upstream.serviceId);
|
|
@@ -3817,20 +3853,6 @@ async function createServer(config, cache, logger, jwtConfig, registry, serviceT
|
|
|
3817
3853
|
gatewayLogger.info(`Upstream registered: ${name} \u2192 ${connDesc} (${upstream.prefix}${wsDesc})`);
|
|
3818
3854
|
}
|
|
3819
3855
|
await app.register(async function gatewayRoutes(scope) {
|
|
3820
|
-
if (userAuth) {
|
|
3821
|
-
scope.addHook(
|
|
3822
|
-
"onRequest",
|
|
3823
|
-
createUserAuthMiddleware({
|
|
3824
|
-
users: userAuth.users,
|
|
3825
|
-
tenantResolver: userAuth.tenantResolver,
|
|
3826
|
-
jwtConfig
|
|
3827
|
-
})
|
|
3828
|
-
);
|
|
3829
|
-
}
|
|
3830
|
-
scope.addHook(
|
|
3831
|
-
"onRequest",
|
|
3832
|
-
createAuthMiddleware(cache, jwtConfig, { authEnabled: config.auth?.enabled !== false })
|
|
3833
|
-
);
|
|
3834
3856
|
if (config.pressure?.perTenant?.enabled === true && platform.hasResourceBroker) {
|
|
3835
3857
|
scope.addHook(
|
|
3836
3858
|
"preHandler",
|
|
@@ -4295,6 +4317,19 @@ async function bootstrap(repoRoot = process.cwd()) {
|
|
|
4295
4317
|
logger.warn("GATEWAY_JWT_SECRET not set \u2014 using insecure default (dev only, never use in production!)");
|
|
4296
4318
|
}
|
|
4297
4319
|
const jwtConfig = { secret: jwtSecret ?? DEV_JWT_SECRET };
|
|
4320
|
+
if (config.auth?.bootstrap?.provisionCliCredentials === true) {
|
|
4321
|
+
const bootstrapAuthService = new AuthService(cache, jwtConfig);
|
|
4322
|
+
await ensureBootstrapCliCredentials({
|
|
4323
|
+
enabled: true,
|
|
4324
|
+
authService: bootstrapAuthService,
|
|
4325
|
+
gatewayUrl: `http://127.0.0.1:${config.port}`,
|
|
4326
|
+
logger
|
|
4327
|
+
}).catch((err) => {
|
|
4328
|
+
logger.warn("Bootstrap CLI credentials provisioning failed (non-fatal)", {
|
|
4329
|
+
error: err instanceof Error ? err.message : String(err)
|
|
4330
|
+
});
|
|
4331
|
+
});
|
|
4332
|
+
}
|
|
4298
4333
|
if (platform.hasResourceBroker) {
|
|
4299
4334
|
registerPressureLimits(platform.resourceBroker, config.pressure, platform.logger);
|
|
4300
4335
|
} else {
|