import { useState } from "react"; import { Link, useSearchParams } from "react-router"; import { api, ApiError, type AuditEvent, type Health, type Job, type Metrics } from "../api"; import { useFetch, ago, fmtBytes, fmtDate, num } from "../hooks"; import { Badge, Bool, Empty, ErrorBox, JobStatus, JsonTree, KV, Loading, Tabs, Td } from "../components/ui"; import { Breakdown, Sparkline } from "../components/charts"; import { useMe } from "../App"; export default function Operations() { const { me } = useMe(); const [sp] = useSearchParams(); const [tab, setTab] = useState(sp.get("job") ? "Jobs" : "Health"); const health = useFetch("ops/health"); const metrics = useFetch(tab === "Metrics" ? "ops/metrics" : null); const backups = useFetch<{ dir: string; remote: string; files: { name: string; bytes: number; mtime: string }[]; runs: { ts: string; details: Record }[] }>(tab === "Backups" ? "ops/backups" : null); const [jobState, setJobState] = useState(""); const jobs = useFetch<{ jobs: Job[]; stats: Health["jobs"] }>(tab === "Jobs" ? `jobs?limit=100${jobState ? `&state=${jobState}` : ""}` : null); const focusJob = useFetch(sp.get("job") ? `jobs/${sp.get("job")}` : null); const [auditOffset, setAuditOffset] = useState(0); const audit = useFetch<{ events: AuditEvent[]; total: number }>(tab === "Audit" ? `audit?limit=50&offset=${auditOffset}` : null); const docs = useFetch<{ documents: string[] }>(tab === "Docs" ? "/docs/index" : null); const [doc, setDoc] = useState<{ name: string; text: string } | null>(null); const [verify, setVerify] = useState<{ ok: boolean; checked: number; head?: string; broken_at_seq?: number } | null>(null); const [backupJob, setBackupJob] = useState(null); const [err, setErr] = useState(null); const h = health.data; return (

Operations

{h && {h.status} · {h.host} · up {Math.round(h.uptime_s / 60)} min}
{tab === "Health" && (health.loading ? : health.error ? : h && (

Service

{h.db.latency_ms} ms · {fmtBytes(h.db.size_bytes)}], ["Migrations", h.db.migrations.map((m) => m.name).join(", ")], ["Egress proxy", 127.0.0.1:{h.proxy.port}], ["sandbox-exec", ], ["Data dir", h.data_dir], ["Disk", h.disk ? `${fmtBytes(h.disk.free_bytes)} free of ${fmtBytes(h.disk.total_bytes)}` : "—"]]} />

Workers ({h.live_workers} live)

{h.workers.length ? h.workers.map((w) =>
{w.name} pid {w.pid} · v{w.version}{w.current_job ? `job ${w.current_job.slice(0, 8)}` : "idle"} · {ago(w.last_seen)}
) :
No worker heartbeat.
}

Queue

queued {h.jobs.queued}running {h.jobs.running}dead {h.jobs.dead}
({ label: k, n: v }))} />
))} {tab === "Metrics" && (metrics.loading ? : metrics.error ? : metrics.data && (

Execution latency (24 h, n={num(metrics.data.executions_24h.n)})

p50
{metrics.data.executions_24h.p50 === null ? "—" : `${Math.round(metrics.data.executions_24h.p50)} ms`}
p95
{metrics.data.executions_24h.p95 === null ? "—" : `${Math.round(metrics.data.executions_24h.p95)} ms`}
max
{metrics.data.executions_24h.max ?? "—"}
jobs done / dead
{metrics.data.jobs_24h.done}/{metrics.data.jobs_24h.dead}

Executions per hour (48 h)

({ x: p.hour, y: p.n }))} />

Egress decisions (24 h)

{metrics.data.egress_24h.length ? ({ label: e.decision, n: e.n, tone: e.decision === "block" ? "s8" : "s1" }))} /> : no proxy traffic}

By API (7 d)

{metrics.data.by_api_7d.length ? {metrics.data.by_api_7d.map((a) => )}
APICallsOKAvg ms
{a.name}{a.n}{a.ok}{a.avg_ms === null ? "—" : Math.round(a.avg_ms)}
: No executions in 7 days.}
))} {tab === "Jobs" && (
{focusJob.data &&

Job {focusJob.data.id}

}
{jobs.loading && } {jobs.data && jobs.data.jobs.length === 0 && No jobs.} {jobs.data && jobs.data.jobs.length > 0 && {jobs.data.jobs.map((j) => )}
JobKindStateAttemptsCreatedFinishedError / result
setTab("Jobs")}>{j.id.slice(0, 8)}{j.kind}{j.attempts}/{j.max_attempts ?? "?"}{fmtDate(j.created_at)}{fmtDate(j.finished_at)}{j.error ? {j.error.split("\n")[0].slice(0, 160)} : j.result ? {JSON.stringify(j.result).slice(0, 160)} : "—"}{(j.state === "dead" || j.state === "failed") && (me?.role === "admin" || me?.role === "operator") && }
}
)} {tab === "Backups" && (

Backups

{me?.role === "admin" && }
backups.reload()} /> {backups.loading && } {backups.data && <> {backups.data.files.length ? {backups.data.files.map((f) => )}
FileSizeModified
{f.name}{fmtBytes(f.bytes)}{fmtDate(f.mtime)}
: No backup files yet.}

Backup runs

{backups.data.runs.length ? backups.data.runs.map((r, i) =>
{fmtDate(r.ts)} · return code {String(r.details.returncode)}
{String(r.details.stdout ?? "")}{String(r.details.stderr ?? "")}
) : none recorded}}
)} {tab === "Audit" && (

Audit log (append-only, hash-chained)

{verify &&
{verify.ok ? `Chain intact: ${verify.checked} events verified, head ${verify.head?.slice(0, 16)}…` : `Chain BROKEN at seq ${verify.broken_at_seq} after ${verify.checked} valid events`}
} {audit.loading && } {audit.data && <>{audit.data.events.map((a) => )}
#WhenActorActionTargetDetails
{a.seq}{fmtDate(a.ts)}{a.actor_type}:{a.actor_id?.slice(0, 8)}{a.action}{a.target_type ? `${a.target_type}:${a.target_id?.slice(0, 8)}` : "—"}
{JSON.stringify(a.details).slice(0, 80)}
hash {a.hash.slice(0, 20)}… prev {a.prev_hash?.slice(0, 20) ?? "∅"}
{audit.data.total} events
}
)} {tab === "Docs" && (

Documentation

Interactive API reference (/docs)

{docs.loading && }{docs.data?.documents.map((d) =>
)}

{doc?.name ?? "Viewer"}

{doc ?
{doc.text}
:
Select a document.
}
)}
); }