"use client"; import { useEffect, useState } from "react"; /* An operator's own second factor. * * Three steps, the same as a coordinator's: set up (a secret and a QR, stored but not yet in * force), enable (prove one code from it works — only then does the password stop being enough), * and the recovery codes, shown exactly once. Turning it off or reissuing the codes asks for the * password, because both are privileged. * * The QR arrives from the server as SVG generated by the product's own QR library from a secret * that never has to reach client-side code; rendering it as markup is the same trust as rendering * any other server response. */ export const dynamic = "force-dynamic"; type Status = { enabled: boolean; recoveryLeft: number; viaSso: boolean }; export default function OpsSecurity() { const [st, setSt] = useState(null); const [qr, setQr] = useState(""); const [secret, setSecret] = useState(""); const [code, setCode] = useState(""); const [pw, setPw] = useState(""); const [codes, setCodes] = useState(null); const [err, setErr] = useState(""); const [busy, setBusy] = useState(false); async function load() { const r = await fetch("/api/ops/auth/totp").catch(() => null); const j = await r?.json().catch(() => null); if (j && typeof j.enabled === "boolean") setSt(j); } useEffect(() => { void load(); }, []); async function act(action: string, extra: Record = {}) { setBusy(true); setErr(""); try { const r = await fetch("/api/ops/auth/totp", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ action, ...extra }) }); const j = await r.json().catch(() => ({})); if (!r.ok) { setErr(j.error || "That didn’t work."); return null; } return j; } catch { setErr("No connection — check the network and try again."); return null; } finally { setBusy(false); } } const label: React.CSSProperties = { display: "block", fontSize: 11, fontWeight: 700, letterSpacing: "0.1em", textTransform: "uppercase", color: "var(--color-neutral-600)", margin: "14px 0 6px" }; const p: React.CSSProperties = { fontSize: 13.5, color: "var(--color-neutral-800)", lineHeight: 1.6, margin: "8px 0 0" }; return (
Operations console

Your sign-in

← Back

{!st &&

Loading…

} {st && !st.enabled && !qr && ( <>

The password door has no second factor yet. Until it does, a password alone opens this console — and that password has been typed into more places than it should have been.

)} {qr && !codes && ( <>

Scan this with your authenticator app, then enter the current code to switch it on.

{secret}

{ setCode(e.target.value); setErr(""); }} placeholder="000000" style={{ width: "100%" }} /> )} {codes && ( <>

Recovery codes. Each works once, for the day the phone is lost. They are shown now and never again — write them down somewhere that is not this screen.

{codes.join("\n")}
)} {st && st.enabled && !codes && ( <>

A second factor is on. {st.recoveryLeft} recovery {st.recoveryLeft === 1 ? "code" : "codes"} unused.{st.viaSso ? " This session came in by single sign-on." : ""}

{ setPw(e.target.value); setErr(""); }} style={{ width: "100%" }} />
)} {err &&
{err}
}
); }