@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.
@@ -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' || securityExporterJwks.state !== 'healthy' ? 'degraded' : 'online',
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hivemagnus/hive-router",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Hive Router: OpenAI-compatible model gateway with routing, failover, quotas and traces, plus the admin API and the unified Hive console",
5
5
  "keywords": [
6
6
  "hive",