import { useEffect, useState } from 'react' import { useI18n } from '../i18n' import { Callout, Spinner } from './ui' import { federatedStatus, type FederatedStatus } from '../api/ai' /** Honest, non-authoritative view of the SIMULATED federated-learning demo (PR C3/C4). * Reports synthetic-server-simulation status, secure-aggregation DESIGN_ONLY, DP SIMULATED with an * exhausted-budget warning, and no payment authority. Never claims "data stays on your device". */ export function FederatedStatusCard({ detailed = false }: { detailed?: boolean }) { const { t } = useI18n() const [status, setStatus] = useState(null) const [loading, setLoading] = useState(true) const [err, setErr] = useState(false) useEffect(() => { const c = new AbortController() federatedStatus(c.signal) .then(setStatus) .catch(() => setErr(true)) .finally(() => setLoading(false)) return () => c.abort() }, []) if (loading) return if (err || !status) return {t('fed.unavailable')} const dp = status.differential_privacy_detail const rows: [string, string][] = [ ['client_type', status.client_type], ['federation', status.federation], ['secure_aggregation', status.secure_aggregation], ['differential_privacy', status.differential_privacy], ['real_device_training', status.real_device_training], ['native_local_only_training', status.native_local_only_training], ] return (
    {rows.map(([key, value]) => (
  • {t(`federated.label.${key}` as never)} {value}
  • ))}
{dp?.budget_exhausted && ( {t('fed.dp.exhausted')} )}

{t('federated.noAuthority')}

{detailed && ( <>

{t('fed.syntheticClients')}

{status.aggregators && status.aggregators.length > 0 && (

{t('fed.aggregators')}: {status.aggregators.join(', ')}

)}

{t('fed.candidate')}: {status.candidate_status} {' ยท '}{t('fed.notPromotable')}

{status.disclaimer}

)}
) }