import { type ReactNode, useState } from "react";
import type { ResourceAuthorityScope } from "@opengeni/sdk";
import {
CircleAlertIcon,
LaptopIcon,
MonitorIcon,
ScreenShareIcon,
ShieldAlertIcon,
TerminalIcon,
UsersIcon,
} from "lucide-react";
import { cn } from "../lib/cn";
import { useOpenGeniText } from "../messages/runtime";
/** The machine identity surfaced to the approver, from the device-flow start. */
export type EnrollmentConsentMachine = {
/** Human-friendly name (hostname by default). */
machineName: string;
os: string;
arch: string;
/** The agent can offer a display (a real screen / Xvfb is available). */
canOfferDisplay: boolean;
/** The agent requests screen control (computer-use). */
requestsScreenControl: boolean;
};
/** The phase of the approve page (drives the rendered panel). */
export type EnrollmentConsentPhase = "review" | "approving" | "approved" | "denied" | "error";
export type EnrollmentConsentProps = {
/** The short code the user typed / scanned (echoed back for confirmation). */
userCode: string;
machine: EnrollmentConsentMachine;
phase?: EnrollmentConsentPhase | undefined;
/** Whether this caller may publish the machine to the whole organization. */
allowOrganizationScope?: boolean | undefined;
/** Approve with the chosen screen-control consent and explicit access scope. */
onApprove?: ((allowScreenControl: boolean, scope: ResourceAuthorityScope) => void) | undefined;
onDeny?: (() => void) | undefined;
/** Error message when phase === "error". */
errorMessage?: string | undefined;
className?: string | undefined;
};
function Capability({ icon, title, body }: { icon: ReactNode; title: string; body: string }) {
return (
{icon}{title}{body}
);
}
/**
* The user-facing APPROVE page for the device-flow enrollment: a LOUD,
* un-minimised whole-machine consent. Approving grants the agent FULL access to
* this machine — exec, files, terminal — and (when toggled) live screen control.
* The danger framing is deliberate (§18 hardening: whole-machine = loud consent),
* never buried. Renders review / approving / approved / denied / error phases.
*/
export function EnrollmentConsent({
userCode,
machine,
phase = "review",
allowOrganizationScope = false,
onApprove,
onDeny,
errorMessage,
className,
}: EnrollmentConsentProps) {
const t = useOpenGeniText();
const [allowScreenControl, setAllowScreenControl] = useState(machine.requestsScreenControl);
const [scope, setScope] = useState("user");
const busy = phase === "approving";
const scopeCopy = {
user: {
label: t("enrollmentConsent.personal"),
body: t("enrollmentConsent.onlyYouCanUseThis"),
},
workspace: {
label: t("enrollmentConsent.workspace"),
body: t("enrollmentConsent.everyoneWithAccessToThis"),
},
organization: {
label: t("enrollmentConsent.organization"),
body: t("enrollmentConsent.membersOfThisOrganizationCan"),
},
} satisfies Record;
if (phase === "approved") {
return (
);
}
if (phase === "denied") {
return (
);
}
if (phase === "error") {
return (
);
}
return (