import { z } from "zod"; export const accountStatuses = [ "active", "deactivated", "banned", "deleting", ] as const; export type AccountStatus = (typeof accountStatuses)[number]; export const accountReason = z.string().trim().min(10).max(2000); export const accountActionInput = z .object({ action: z.enum(["deactivate", "ban", "restore", "delete"]), reason: accountReason, confirmation: z.string().uuid().optional(), }) .strict(); export const accountAppealInput = z.object({ reason: accountReason }).strict(); export const accountAppealReviewInput = z .object({ decision: z.enum(["approve", "reject"]), reason: accountReason, }) .strict(); export function restrictionMessage(status: string) { return status === "banned" ? "Your account is banned. Visit /ban/appeal to read the reason and appeal." : status === "deleting" ? "Account deletion is pending. Visit /ban/appeal for account status." : "Your account is deactivated. Visit /ban/appeal for account status."; } /** Restricted accounts retain only the pages needed to understand/appeal access. */ export function restrictionPageAllowed(path: string) { return ( path === "/ban/appeal" || path === "/settings" || path === "/docs" || path === "/log-in" || path === "/auth/callback" || path === "/auth/reset-password" ); } export type ManagedAccount = { id: string; display_name: string; role: string; account_status: AccountStatus; account_reason: string | null; account_changed_at: string | null; status_version: number; }; export type AccountAppealRecord = { ban_reason?: string | null; id: string; owner_id: string; display_name: string; status_version: number; reason: string; state: "open" | "approved" | "rejected"; created_at: string; review_reason: string | null; reviewed_at: string | null; };