"use server"; import { revalidatePath } from "next/cache"; import type { ContentMutationSnapshot } from "@/features/housekeeping/domains/content/services/mutations"; import { createCorrelationId } from "@/features/housekeeping/foundation/contracts"; import { requirePermission, type StaffUser } from "@/lib/admin/guard"; import { PERMS } from "@/lib/permissions"; const MAX_SIZE = 2 * 1024 * 1024; const ALLOWED = [ "image/png", "image/jpeg", "image/gif", "image/webp", "image/x-icon", "image/svg+xml", ]; async function executeAuditedFaviconMutation( staff: StaffUser, operation: "favicon.save" | "favicon.delete", input: unknown, ): Promise { const [ { contentProductionMutationAdapter }, { getHousekeepingCapabilityContext }, ] = await Promise.all([ import( "@/features/housekeeping/domains/content/services/mutations-production" ), import("@/features/housekeeping/foundation/server-capability-context"), ]); const capability = await getHousekeepingCapabilityContext(); if (capability.actor.id !== staff.id) throw new Error("Authenticated staff changed during favicon mutation"); return contentProductionMutationAdapter.execute(operation, input, { capability, correlationId: createCorrelationId(), legacy: true, }); } export async function saveFavicon( formData: FormData, ): Promise<{ success: boolean; url?: string; error?: string }> { const staff = await requirePermission(PERMS.SETTINGS_VIEW); try { const file = formData.get("file") as File | null; if (!file || file.size === 0) return { success: false, error: "No file provided" }; if (file.size > MAX_SIZE) return { success: false, error: "File too large (max 2MB)" }; if (!ALLOWED.includes(file.type)) return { success: false, error: "Invalid file type. Allowed: PNG, JPEG, GIF, WebP, ICO, SVG", }; const result = await executeAuditedFaviconMutation(staff, "favicon.save", { file, }); siteRevalidate(); return { success: true, ...(typeof result.output?.url === "string" ? { url: result.output.url } : {}), }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : "Unknown error", }; } } export async function deleteFavicon(): Promise<{ success: boolean; error?: string; }> { const staff = await requirePermission(PERMS.SETTINGS_VIEW); try { await executeAuditedFaviconMutation(staff, "favicon.delete", {}); siteRevalidate(); return { success: true }; } catch (error) { return { success: false, error: error instanceof Error ? error.message : "Unknown error", }; } } function siteRevalidate(): void { revalidatePath("/", "layout"); revalidatePath("/admin/favicon"); }