import { BarChart3, Loader2, Search, ShieldCheck, ShieldAlert } from 'lucide-react'; import { useEffect, useState } from 'react'; import type { AdminAnalyticsSummary, AdminAuditAction, AdminAuditLogItem, AdminSecurityPostureResponse, AdminSupportDiagnosticsResponse, ApplicationAdminSummary, BillingAdminWorkspaceDetail, BillingAdminWorkspaceSummary, } from '@/shared/types'; import { formatBillingStatusLabel, formatDateLabel } from '@/app/src/lib/billing-ui'; import { getAdminAnalyticsSummary, getAdminBillingWorkspaceDetail, getAdminSecurityPosture, getAdminSupportDiagnostics, listAdminAuditLogs, listAdminBillingWorkspaces, listApplicationAdmins, requestAdminBillingResync, updateApplicationAdminStatus, upsertApplicationAdmin, } from '../lib/admin'; import { Alert, Badge, Button, Card, FieldLabel, Input, LoadingState, PageContainer, PageShell, SectionHeader, Select } from '@/app/src/components/ui'; const MIN_SUMMARY_DAYS = 7; const MAX_SUMMARY_DAYS = 90; const DEFAULT_SUMMARY_DAYS = 30; const DEFAULT_AUDIT_PAGE_SIZE = 25; const DEFAULT_DIAGNOSTICS_WINDOW_DAYS = 7; const DEFAULT_STALE_THRESHOLD_HOURS = 24; const AUDIT_ACTION_OPTIONS: Array<{ value: AdminAuditAction; label: string }> = [ { value: 'admin_access_list', label: 'Admin access list' }, { value: 'admin_access_upsert', label: 'Admin access upsert' }, { value: 'admin_access_status_changed', label: 'Admin access status changed' }, { value: 'analytics_summary', label: 'Analytics summary' }, { value: 'billing_workspaces_list', label: 'Billing workspaces list' }, { value: 'billing_workspace_detail', label: 'Billing workspace detail' }, { value: 'bootstrap_admin_claimed', label: 'Bootstrap admin claimed' }, { value: 'admin_ops_audit_list', label: 'Admin ops audit list' }, { value: 'admin_ops_security_posture', label: 'Admin ops security posture' }, { value: 'admin_ops_diagnostics', label: 'Admin ops diagnostics' }, { value: 'admin_mutation_billing_resync_requested', label: 'Admin mutation billing resync requested' }, ]; function formatAuditActionLabel(action: AdminAuditAction) { const matched = AUDIT_ACTION_OPTIONS.find((option) => option.value === action); return matched?.label ?? action; } const clampSummaryDays = (value: number) => Math.min(MAX_SUMMARY_DAYS, Math.max(MIN_SUMMARY_DAYS, value)); function toIsoDateTime(value: string) { if (!value) { return undefined; } const parsed = new Date(value); if (Number.isNaN(parsed.getTime())) { return undefined; } return parsed.toISOString(); } export function AdminPage() { const [summaryDays, setSummaryDays] = useState(DEFAULT_SUMMARY_DAYS); const [analyticsSummary, setAnalyticsSummary] = useState(null); const [summaryLoading, setSummaryLoading] = useState(true); const [summaryError, setSummaryError] = useState(null); const [searchQuery, setSearchQuery] = useState(''); const [workspaces, setWorkspaces] = useState([]); const [selectedWorkspace, setSelectedWorkspace] = useState(null); const [workspacesLoading, setWorkspacesLoading] = useState(true); const [workspacesError, setWorkspacesError] = useState(null); const [detailLoading, setDetailLoading] = useState(false); const [admins, setAdmins] = useState([]); const [adminsLoading, setAdminsLoading] = useState(true); const [adminsError, setAdminsError] = useState(null); const [adminMutationFeedback, setAdminMutationFeedback] = useState(null); const [adminMutationError, setAdminMutationError] = useState(null); const [adminEmailInput, setAdminEmailInput] = useState(''); const [adminEmailSubmitting, setAdminEmailSubmitting] = useState(false); const [statusMutationAdminId, setStatusMutationAdminId] = useState(null); const [securityPosture, setSecurityPosture] = useState(null); const [securityLoading, setSecurityLoading] = useState(true); const [securityError, setSecurityError] = useState(null); const [diagnostics, setDiagnostics] = useState(null); const [diagnosticsLoading, setDiagnosticsLoading] = useState(true); const [diagnosticsError, setDiagnosticsError] = useState(null); const [auditItems, setAuditItems] = useState([]); const [auditLoading, setAuditLoading] = useState(true); const [auditError, setAuditError] = useState(null); const [auditPage, setAuditPage] = useState(1); const [auditTotal, setAuditTotal] = useState(0); const [auditActorEmail, setAuditActorEmail] = useState(''); const [auditAction, setAuditAction] = useState(''); const [auditWorkspaceId, setAuditWorkspaceId] = useState(''); const [auditFrom, setAuditFrom] = useState(''); const [auditTo, setAuditTo] = useState(''); const [mutationWorkspaceId, setMutationWorkspaceId] = useState(''); const [mutationReason, setMutationReason] = useState(''); const [mutationTicketRef, setMutationTicketRef] = useState(''); const [mutationConfirmation, setMutationConfirmation] = useState(''); const [mutationSubmitting, setMutationSubmitting] = useState(false); const [mutationFeedback, setMutationFeedback] = useState(null); const [mutationError, setMutationError] = useState(null); const loadAuditLogs = async ( page: number, overrides?: Partial<{ actorEmail: string; action: AdminAuditAction | ''; workspaceId: string; from: string; to: string }>, ) => { const actorEmail = overrides?.actorEmail ?? auditActorEmail; const action = overrides?.action ?? auditAction; const workspaceId = overrides?.workspaceId ?? auditWorkspaceId; const from = overrides?.from ?? auditFrom; const to = overrides?.to ?? auditTo; setAuditLoading(true); setAuditError(null); try { const response = await listAdminAuditLogs({ actorEmail: actorEmail.trim() || undefined, action: action || undefined, workspaceId: workspaceId.trim() || undefined, from: toIsoDateTime(from), to: toIsoDateTime(to), page, pageSize: DEFAULT_AUDIT_PAGE_SIZE, }); setAuditItems(response.items); setAuditTotal(response.total); setAuditPage(response.page); } catch (error) { setAuditError(error instanceof Error ? error.message : 'Failed to load admin audit logs.'); } finally { setAuditLoading(false); } }; const loadSecurityPosture = async () => { setSecurityLoading(true); setSecurityError(null); try { const response = await getAdminSecurityPosture(); setSecurityPosture(response); } catch (error) { setSecurityError(error instanceof Error ? error.message : 'Failed to load security posture.'); } finally { setSecurityLoading(false); } }; const loadDiagnostics = async () => { setDiagnosticsLoading(true); setDiagnosticsError(null); try { const response = await getAdminSupportDiagnostics({ windowDays: DEFAULT_DIAGNOSTICS_WINDOW_DAYS, staleSyncThresholdHours: DEFAULT_STALE_THRESHOLD_HOURS, sampleLimit: 10, }); setDiagnostics(response); } catch (error) { setDiagnosticsError(error instanceof Error ? error.message : 'Failed to load support diagnostics.'); } finally { setDiagnosticsLoading(false); } }; useEffect(() => { let isMounted = true; const loadAdminData = async () => { setSummaryLoading(true); setWorkspacesLoading(true); setAdminsLoading(true); setSummaryError(null); setWorkspacesError(null); setAdminsError(null); try { const [summary, workspaceResponse, adminResponse, securityResponse, diagnosticsResponse, auditResponse] = await Promise.all([ getAdminAnalyticsSummary(DEFAULT_SUMMARY_DAYS), listAdminBillingWorkspaces(), listApplicationAdmins(), getAdminSecurityPosture(), getAdminSupportDiagnostics({ windowDays: DEFAULT_DIAGNOSTICS_WINDOW_DAYS, staleSyncThresholdHours: DEFAULT_STALE_THRESHOLD_HOURS, sampleLimit: 10, }), listAdminAuditLogs({ page: 1, pageSize: DEFAULT_AUDIT_PAGE_SIZE }), ]); if (!isMounted) { return; } setAnalyticsSummary(summary); setWorkspaces(workspaceResponse.workspaces); setAdmins(adminResponse.admins); setSecurityPosture(securityResponse); setDiagnostics(diagnosticsResponse); setAuditItems(auditResponse.items); setAuditTotal(auditResponse.total); setAuditPage(auditResponse.page); } catch (error) { if (!isMounted) { return; } const message = error instanceof Error ? error.message : 'Failed to load admin console data.'; setSummaryError(message); setWorkspacesError(message); setAdminsError(message); setSecurityError(message); setDiagnosticsError(message); setAuditError(message); } finally { if (isMounted) { setSummaryLoading(false); setWorkspacesLoading(false); setAdminsLoading(false); setSecurityLoading(false); setDiagnosticsLoading(false); setAuditLoading(false); } } }; void loadAdminData(); return () => { isMounted = false; }; }, []); const handleRefreshSummary = async () => { setSummaryLoading(true); setSummaryError(null); try { const clampedDays = clampSummaryDays(summaryDays); if (clampedDays !== summaryDays) { setSummaryDays(clampedDays); } const summary = await getAdminAnalyticsSummary(clampedDays); setAnalyticsSummary(summary); } catch (error) { setSummaryError(error instanceof Error ? error.message : 'Failed to refresh analytics summary.'); } finally { setSummaryLoading(false); } }; const handleSearchWorkspaces = async () => { setWorkspacesLoading(true); setWorkspacesError(null); try { const response = await listAdminBillingWorkspaces(searchQuery); setWorkspaces(response.workspaces); setSelectedWorkspace(null); } catch (error) { setWorkspacesError(error instanceof Error ? error.message : 'Failed to search billing workspaces.'); } finally { setWorkspacesLoading(false); } }; const handleLoadWorkspaceDetail = async (workspaceId: string) => { setDetailLoading(true); setWorkspacesError(null); try { const response = await getAdminBillingWorkspaceDetail(workspaceId); setSelectedWorkspace(response.workspace); } catch (error) { setWorkspacesError(error instanceof Error ? error.message : 'Failed to load workspace detail.'); } finally { setDetailLoading(false); } }; const refreshAdmins = async () => { setAdminsLoading(true); setAdminsError(null); try { const response = await listApplicationAdmins(); setAdmins(response.admins); } catch (error) { setAdminsError(error instanceof Error ? error.message : 'Failed to load application admins.'); } finally { setAdminsLoading(false); } }; const handleUpsertAdmin = async () => { setAdminMutationFeedback(null); setAdminMutationError(null); setAdminEmailSubmitting(true); try { const response = await upsertApplicationAdmin(adminEmailInput); setAdminMutationFeedback(`Admin access is active for ${response.admin.email}.`); setAdminEmailInput(''); await refreshAdmins(); await loadSecurityPosture(); } catch (error) { setAdminMutationError(error instanceof Error ? error.message : 'Failed to add or reactivate admin.'); } finally { setAdminEmailSubmitting(false); } }; const handleSetAdminStatus = async (adminId: string, status: 'active' | 'disabled') => { setAdminMutationFeedback(null); setAdminMutationError(null); setStatusMutationAdminId(adminId); try { const response = await updateApplicationAdminStatus(adminId, status); setAdminMutationFeedback(`${response.admin.email} is now ${status}.`); await refreshAdmins(); await loadSecurityPosture(); } catch (error) { setAdminMutationError(error instanceof Error ? error.message : 'Failed to update admin status.'); } finally { setStatusMutationAdminId(null); } }; const handleRequestBillingResync = async () => { setMutationError(null); setMutationFeedback(null); setMutationSubmitting(true); try { const response = await requestAdminBillingResync({ workspaceId: mutationWorkspaceId.trim(), reason: mutationReason.trim(), confirmationText: mutationConfirmation.trim(), ticketRef: mutationTicketRef.trim() || undefined, }); setMutationFeedback(response.message); if (selectedWorkspace?.summary.workspaceId === mutationWorkspaceId.trim()) { await handleLoadWorkspaceDetail(mutationWorkspaceId.trim()); } await loadDiagnostics(); await loadAuditLogs(1); } catch (error) { setMutationError(error instanceof Error ? error.message : 'Failed to request billing resync.'); } finally { setMutationSubmitting(false); } }; const totalAuditPages = Math.max(1, Math.ceil(auditTotal / DEFAULT_AUDIT_PAGE_SIZE)); const canSubmitMutation = mutationWorkspaceId.trim().length > 0 && mutationReason.trim().length >= 10 && mutationConfirmation.trim() === 'RESYNC' && !mutationSubmitting; return (

Safe Mutations (Pilot)

Request billing resync for a workspace

This triggers a Stripe subscription re-sync for one workspace. It does not directly change plan pricing configuration.

Workspace ID setMutationWorkspaceId(event.target.value)} placeholder="Workspace UUID" />
Ticket reference (optional) setMutationTicketRef(event.target.value)} placeholder="SUP-1234" />
Reason (required) setMutationReason(event.target.value)} placeholder="Explain why this resync is needed." />
Type RESYNC to confirm setMutationConfirmation(event.target.value)} placeholder="RESYNC" />
{mutationError ? {mutationError} : null} {mutationFeedback ? {mutationFeedback} : null}
{selectedWorkspace ? ( ) : null}

Admin Access Management

Application admin identities

Admin email setAdminEmailInput(event.target.value)} placeholder="name@company.com" type="email" />
{adminsError ? {adminsError} : null} {adminMutationError ? {adminMutationError} : null} {adminMutationFeedback ? {adminMutationFeedback} : null}
{adminsLoading && admins.length === 0 ? : null} {admins.map((admin) => { const isMutatingStatus = statusMutationAdminId === admin.id; const isActive = admin.status === 'active'; return (

{admin.email}

Created {formatDateLabel(admin.createdAt)}

{admin.status}
); })} {!adminsLoading && admins.length === 0 ? (

No application admins are configured.

) : null}

Security Posture

Bootstrap and admin-allowlist checks

{securityError ? {securityError} : null} {securityLoading && !securityPosture ? : null} {securityPosture ? (

Bootstrap Required

{securityPosture.bootstrapRequired ? 'Yes' : 'No'}

Bootstrap Enabled

{securityPosture.bootstrapEnabled ? 'Yes' : 'No'}

Active App Admins

{securityPosture.activeApplicationAdminCount}

{securityPosture.usingDeprecatedBillingAdminFallback ? (

Set `ADMIN_EMAILS` and stop relying on `BILLING_ADMIN_EMAILS` fallback.

) : null} {!securityPosture.adminAllowlistConfigured ? (

Configure `ADMIN_EMAILS` for emergency access and recovery playbooks.

) : null} {securityPosture.bootstrapEnabled ? (

After first-run setup, disable bootstrap and rotate `ADMIN_BOOTSTRAP_TOKEN`.

) : null}

Hardening checklist

  • - Disable bootstrap once initial admin setup is complete.
  • - Rotate the bootstrap token and store it in secrets management.
  • - Keep at least two active application admins to reduce lockout risk.
) : null}

Support Diagnostics

Webhook failures, sync health, and timeline anomalies

{diagnosticsError ? {diagnosticsError} : null} {diagnosticsLoading && !diagnostics ? : null} {diagnostics ? (

Failed webhook samples

{diagnostics.failedWebhooks.count} total
{diagnostics.failedWebhooks.items.length === 0 ?

No failed webhook events in window.

: null} {diagnostics.failedWebhooks.items.map((issue) => (

{issue.eventType}

{issue.workspaceName || 'Unknown workspace'} - {formatDateLabel(issue.receivedAt)}

{issue.errorMessage || 'No error message provided.'}

{issue.workspaceId ? ( ) : null}
))}

Stale sync samples

{diagnostics.staleBillingSync.count} total
{diagnostics.staleBillingSync.items.length === 0 ?

No stale sync accounts in window.

: null} {diagnostics.staleBillingSync.items.map((issue) => (

{issue.workspaceName}

{issue.planCode || 'No plan'} - {formatBillingStatusLabel(issue.status)}

Last sync: {formatDateLabel(issue.lastStripeSyncAt)}

))}

Timeline anomaly counters ({diagnostics.windowDays}-day window)

Repeated payment failures: {diagnostics.timelineAnomalies.repeatedPaymentFailedCount}
Pending plan past effective date: {diagnostics.timelineAnomalies.pendingPlanPastEffectiveCount}
Stale sync threshold breaches: {diagnostics.timelineAnomalies.staleSyncThresholdCount}
) : null}

Admin Audit Explorer

Route and support action history

Actor email setAuditActorEmail(event.target.value)} placeholder="ops@company.com" />
Action
Workspace ID setAuditWorkspaceId(event.target.value)} placeholder="uuid" />
From setAuditFrom(event.target.value)} />
To setAuditTo(event.target.value)} />
{auditError ? {auditError} : null}
{auditLoading && auditItems.length === 0 ? : null} {!auditLoading && auditItems.length === 0 ? (

No audit entries found for the selected filters.

) : null} {auditItems.length > 0 ? ( {auditItems.map((item) => ( ))}
Occurred Actor Action Route Workspace
{formatDateLabel(item.occurredAt)} {item.actorEmail || 'Unknown actor'} {formatAuditActionLabel(item.action)} {item.route} {item.targetWorkspaceName || item.targetWorkspaceId || 'N/A'}
) : null}

Showing page {auditPage} of {totalAuditPages} ({auditTotal} total entries)

Analytics Summary

Admin metrics overview

Days { const numericValue = Number(event.target.value); const normalizedValue = Number.isFinite(numericValue) ? numericValue : DEFAULT_SUMMARY_DAYS; setSummaryDays(clampSummaryDays(normalizedValue)); }} className="w-24" />
{summaryError ? {summaryError} : null} {summaryLoading && !analyticsSummary ? : null} {analyticsSummary ? (
) : null}

Billing Support Visibility

Workspace lookup and detail

{detailLoading ? : null}
setSearchQuery(event.target.value)} placeholder="Search workspace, customer ref, or subscription ref" />
{workspacesError ? {workspacesError} : null}
{workspacesLoading && workspaces.length === 0 ? : null} {workspaces.map((workspace) => ( ))} {!workspacesLoading && workspaces.length === 0 ? (

No workspaces found for this search.

) : null}
{!selectedWorkspace ? (

Select a workspace to review billing state, pending plan fields, and recent timeline events.

) : (

{selectedWorkspace.summary.workspaceName}

{selectedWorkspace.summary.planCode || 'No plan'} - {formatBillingStatusLabel(selectedWorkspace.summary.status)}

Period ends: {formatDateLabel(selectedWorkspace.billing.currentPeriodEndsAt)}
Grace period ends: {formatDateLabel(selectedWorkspace.billing.gracePeriodEndsAt)}
Pending plan code: {selectedWorkspace.billing.pendingPlanCode || 'None'}
Pending effective at: {formatDateLabel(selectedWorkspace.billing.pendingPlanEffectiveAt)}
External customer ref: {selectedWorkspace.summary.externalCustomerRef || 'Not set'}
External subscription ref: {selectedWorkspace.summary.externalSubscriptionRef || 'Not set'}
Usage period id: {selectedWorkspace.usagePeriodId || 'Not active'}

Recent timeline summary

{selectedWorkspace.timeline.slice(0, 10).map((entry) => (
{entry.eventType} {formatDateLabel(entry.occurredAt)}
))} {selectedWorkspace.timeline.length === 0 ?

No timeline events recorded.

: null}
)}
); } function DiagnosticsMetricCard({ title, value }: { title: string; value: number }) { return (

{title}

{value}

); } function MetricBucketCard({ title, buckets }: { title: string; buckets: Array<{ key: string; count: number }> }) { return (

{title}

{buckets.reduce((sum, bucket) => sum + bucket.count, 0)} total
{buckets.length === 0 ?

No data for this window.

: null} {buckets.slice(0, 6).map((bucket) => (
{bucket.key} {bucket.count}
))}
); }