@hivemagnus/hive-router 1.0.1 → 1.0.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/dist/src/admin/app.js
CHANGED
|
@@ -574,9 +574,12 @@ async function probeHiveService(key, name, role, internalUrl, publicUrl, healthP
|
|
|
574
574
|
};
|
|
575
575
|
}
|
|
576
576
|
}
|
|
577
|
-
async function buildHiveStatus(env, requestId) {
|
|
577
|
+
export async function buildHiveStatus(env, requestId) {
|
|
578
578
|
const tlsCertificate = inspectTlsCertificate({ publicUrl: env.PUBLIC_ADMIN_URL, ...(env.TLS_CERT_PATH ? { certPath: env.TLS_CERT_PATH } : {}) });
|
|
579
579
|
const securityExporterJwks = getSecurityExporterJwksStatus(env.HIVE_ROUTER_IAM_JWKS_MAX_AGE_MS);
|
|
580
|
+
// Exporter keys load on demand; an unused cache is expected on a fresh install.
|
|
581
|
+
const exporterKeysDegraded = securityExporterJwks.state !== 'healthy'
|
|
582
|
+
&& securityExporterJwks.state !== 'uninitialized';
|
|
580
583
|
const [providerCount, enabledProviders, routeRuleCount, traceCount, failureCount, failoverCount] = await Promise.all([
|
|
581
584
|
prisma.provider.count(),
|
|
582
585
|
prisma.provider.count({ where: { enabled: true } }),
|
|
@@ -589,7 +592,7 @@ async function buildHiveStatus(env, requestId) {
|
|
|
589
592
|
key: 'router',
|
|
590
593
|
name: 'Hive Router',
|
|
591
594
|
role: 'traffic routing and OpenAI-compatible gateway',
|
|
592
|
-
status: failureCount > 0 || tlsCertificate.status !== 'pass' ||
|
|
595
|
+
status: failureCount > 0 || tlsCertificate.status !== 'pass' || exporterKeysDegraded ? 'degraded' : 'online',
|
|
593
596
|
summary: `${enabledProviders}/${providerCount} providers enabled`,
|
|
594
597
|
internalUrl: env.PUBLIC_ADMIN_URL,
|
|
595
598
|
publicUrl: env.PUBLIC_API_URL,
|
|
@@ -603,7 +606,7 @@ async function buildHiveStatus(env, requestId) {
|
|
|
603
606
|
name: 'security-exporter-jwks',
|
|
604
607
|
status: securityExporterJwks.state === 'healthy' ? 'pass' : securityExporterJwks.state === 'expired' ? 'fail' : 'warn',
|
|
605
608
|
message: securityExporterJwks.state === 'uninitialized'
|
|
606
|
-
? 'not cached yet'
|
|
609
|
+
? 'not cached yet; first exporter request will load IAM keys'
|
|
607
610
|
: `${Math.ceil(securityExporterJwks.remainingMs / 1_000)}s remaining (${securityExporterJwks.state})`,
|
|
608
611
|
},
|
|
609
612
|
],
|
|
@@ -19,6 +19,12 @@ export async function requireApiKey(context, next) {
|
|
|
19
19
|
return context.json({ error: 'Invalid API key' }, 401);
|
|
20
20
|
}
|
|
21
21
|
const metadata = safeJsonParse(match.metadataJson, {});
|
|
22
|
+
if (metadata.expiresAt !== undefined) {
|
|
23
|
+
const expiresAt = typeof metadata.expiresAt === 'string' ? Date.parse(metadata.expiresAt) : NaN;
|
|
24
|
+
if (!Number.isFinite(expiresAt) || expiresAt <= Date.now()) {
|
|
25
|
+
return context.json({ error: 'Invalid API key' }, 401);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
22
28
|
const permission = context.req.method === 'GET' ? 'models:read' : 'inference:write';
|
|
23
29
|
if (Array.isArray(metadata.scopes) && !metadata.scopes.includes('*') && !metadata.scopes.includes(permission))
|
|
24
30
|
return context.json({ error: 'Client key does not permit this operation' }, 403);
|
package/package.json
CHANGED