import React, { useEffect, useMemo, useState } from 'react'; import { Key, RefreshCw, ShieldAlert, CheckCircle2, AlertTriangle, Clock, Calendar, Building2, BadgeCheck, Sparkles, FileSignature, Copy, Check } from 'lucide-react'; interface LicensingEngineProps { tenants: any[]; metrics: { active_licenses?: number; expired_licenses?: number } | null; onRefresh?: () => void; } interface JwksKey { kty?: string; crv?: string; alg?: string; use?: string; kid?: string; pubKeyPem?: string; } function parseDate(d: any): Date | null { if (!d) return null; const dt = new Date(d); return isNaN(dt.getTime()) ? null : dt; } function fmtDate(d: any): string { const dt = parseDate(d); return dt ? dt.toLocaleDateString() : '—'; } function daysBetween(a: Date, b: Date): number { const ms = b.getTime() - a.getTime(); return Math.ceil(ms / (1000 * 60 * 60 * 24)); } function statusBadge(status: string | undefined, isExpired: boolean) { if (status === 'overridden') { return { label: 'OVERRIDDEN', cls: 'bg-amber-500/10 border-amber-500/20 text-amber-500', icon: ShieldAlert }; } if (isExpired) { return { label: 'EXPIRED', cls: 'bg-rose-500/10 border-rose-500/20 text-rose-500', icon: AlertTriangle }; } return { label: 'ACTIVE', cls: 'bg-emerald-500/10 border-emerald-500/20 text-emerald-500', icon: CheckCircle2 }; } export function LicensingEngine({ tenants, metrics, onRefresh }: LicensingEngineProps) { const now = useMemo(() => new Date(), []); const horizon30 = useMemo(() => new Date(now.getTime() + 30 * 24 * 60 * 60 * 1000), [now]); const [trustAnchor, setTrustAnchor] = useState<{ kid?: string; pubKeyPem?: string; error?: string } | null>(null); const [copied, setCopied] = useState(false); useEffect(() => { let cancelled = false; (async () => { try { const res = await fetch('/api/v1/auth/jwks'); if (!res.ok) throw new Error(`JWKS fetch failed: HTTP ${res.status}`); const data = await res.json(); const key: JwksKey | undefined = Array.isArray(data?.keys) ? data.keys[0] : undefined; if (cancelled) return; setTrustAnchor({ kid: key?.kid, pubKeyPem: key?.pubKeyPem }); } catch (err: any) { if (cancelled) return; setTrustAnchor({ error: err?.message || 'Failed to load JWKS' }); } })(); return () => { cancelled = true; }; }, []); const copyPublicKey = async () => { if (!trustAnchor?.pubKeyPem) return; try { await navigator.clipboard.writeText(trustAnchor.pubKeyPem); setCopied(true); setTimeout(() => setCopied(false), 2000); } catch { setCopied(false); } }; const counts = useMemo(() => { let active = 0, expired = 0, overridden = 0; for (const t of tenants) { if (t.license?.status === 'overridden') overridden += 1; else if (t.is_expired) expired += 1; else active += 1; } return { active: metrics?.active_licenses ?? active, expired: metrics?.expired_licenses ?? expired, overridden, }; }, [tenants, metrics]); const expiringSoon = useMemo(() => { return tenants .filter(t => { const end = parseDate(t.license?.end_date); const isOverridden = t.license?.status === 'overridden'; if (!end || isOverridden) return false; return end.getTime() >= now.getTime() && end.getTime() <= horizon30.getTime(); }) .sort((a, b) => { const ea = parseDate(a.license?.end_date)?.getTime() ?? 0; const eb = parseDate(b.license?.end_date)?.getTime() ?? 0; return ea - eb; }); }, [tenants, now, horizon30]); const recentlyIssued = useMemo(() => { return [...tenants] .filter(t => parseDate(t.license?.end_date)) .sort((a, b) => { const ea = parseDate(a.license?.end_date)?.getTime() ?? 0; const eb = parseDate(b.license?.end_date)?.getTime() ?? 0; return eb - ea; }) .slice(0, 10); }, [tenants]); const activeOverrides = useMemo(() => { return tenants.filter(t => t.license?.status === 'overridden'); }, [tenants]); return (
Asymmetric Ed25519 (EdDSA) term licenses issued by LicenseTokenGenerator; verifiable offline via tenant PUBLIC_KEY.
Valid signed tokens in field
In grace period or past end_date
Emergency overrides granted
Term licenses reaching end_date before {fmtDate(horizon30)}.
| School | Term | End Date | Days Remaining | Status |
|---|---|---|---|---|
|
|
{t.license?.term_name || 'Term 1'} | {fmtDate(t.license?.end_date)} | {daysLeft > 0 ? `${daysLeft}d` : 'today'} |
|
Top 10 most recently issued term licenses.
| School | Issued | Expires | Term | Status |
|---|---|---|---|---|
|
|
{fmtDate(t.license?.start_date)} | {fmtDate(t.license?.end_date)} | {t.license?.term_name || 'Term 1'} |
|
Emergency bypasses currently in effect.
| School | Override Reason | Override End Date | Granted |
|---|---|---|---|
|
|
{t.license?.override_reason || t.license?.reason || '—'} | {fmtDate(t.license?.override_end_date || t.license?.end_date)} |
|
Set SUPERADMIN_PUBLIC_KEY in server/.env to this value so the tenant middleware can verify Ed25519 signatures offline.
JWKS endpoint: GET /api/v1/auth/jwks (public, no auth)