import { useCallback, useEffect, useState } from 'react' import { ShieldCheck, RefreshCw, Loader2, Lock, Unlock, Check, X, FileCheck2, AlertTriangle } from 'lucide-react' import { cn } from '../../lib/utils' type Check = { name: string; ok: boolean; value: unknown; target: unknown } type Pii = { pii_count: number; all_masked: boolean; masked: number; unmasked: number } type Alert = { type: string; severity: string; message: string } type Posture = { key: string; label: string; engine: string; color: string; table: string owner?: string | null; steward?: string | null; tier?: string | null pii: Pii; dq_score?: number | null; issues: string[]; alerts: Alert[] contract: Record; checks: Check[]; compliant: boolean } type Resp = { ok: boolean; datasets: Posture[]; summary: { total: number; compliant: number; non_compliant: number } } export function GovernanceAccessView() { const [data, setData] = useState(null) const [loading, setLoading] = useState(true) const load = useCallback(async () => { setLoading(true) try { const r = await fetch('/api/governance/posture') if (r.ok) setData(await r.json()) } catch { /* */ } finally { setLoading(false) } }, []) useEffect(() => { load() }, [load]) useEffect(() => { const t = setInterval(load, 12000); return () => clearInterval(t) }, [load]) const sev = (s: string) => (s === 'critical' ? 'text-rose-400' : s === 'warning' ? 'text-amber-400' : 'text-sky-400') return (
Governance posture = ownership + PII masking + live DQ + observability alerts vs each data contract
{(data?.datasets || []).map((d) => (
{d.label} {d.compliant ? : } {d.compliant ? 'Compliant' : 'Action needed'}
{d.checks.map((c) => (
{c.ok ? : } {c.name} {String(c.value)}
))}
Owner: {d.owner || '—'} · Tier: {d.tier || '—'} · {d.pii.unmasked === 0 ? <> {d.pii.masked}/{d.pii.pii_count} PII masked : <> {d.pii.unmasked} PII visible}
{d.alerts.length > 0 && (
{d.alerts.map((a, i) => (

{a.message}

))}
)}

Contract: DQ ≥ {d.contract.min_score} · completeness ≥ {d.contract.min_completeness}% · freshness ≤ {d.contract.min_freshness_min}m · crit alerts ≤ {d.contract.max_critical_alerts}

))}
) } function Kpi({ icon: Icon, label, value, accent }: { icon: typeof ShieldCheck; label: string; value: string; accent: string }) { return (

{label}

{value}

) }