'use server' import { revalidatePath } from 'next/cache' import { z } from 'zod' import { db } from '@/lib/db' import { requirePermissionForAction } from '@/lib/auth/current' import { writeAudit } from '@/lib/audit/write' import { de } from '@/lib/i18n/de' const schema = z.object({ entryEditPolicy: z.enum(['APPEND_ONLY', 'GRACE_WINDOW', 'OPEN']), entryEditGraceMinutes: z.coerce.number().int().min(0).max(1440), entryEditMarkGrace: z.boolean(), }) export type PolicyResult = { ok: true } | { ok: false; error: string } /** * Die Änderungsrichtlinie gilt für die ganze Abteilung und wird serverseitig * gelesen, nie aus dem Request. Deshalb ist das hier die einzige Stelle, an * der sie sich ändern lässt — mit Recht `admin` und mit Protokolleintrag. */ export async function savePolicy(input: unknown): Promise { const user = await requirePermissionForAction('admin') const parsed = schema.safeParse(input) if (!parsed.success) return { ok: false, error: de.actionErrors.default! } const before = await db.appSetting.findUnique({ where: { id: 1 } }) await db.$transaction(async (tx) => { await tx.appSetting.upsert({ where: { id: 1 }, create: { id: 1, ...parsed.data, updatedById: user.id }, update: { ...parsed.data, updatedById: user.id }, }) await writeAudit(tx, { actorId: user.id, action: 'roles.update', targetType: 'AppSetting', targetId: '1', clearanceAtTime: user.permissions.clearanceLevel, meta: { from: { policy: before?.entryEditPolicy, grace: before?.entryEditGraceMinutes, mark: before?.entryEditMarkGrace, }, to: parsed.data, }, }) }) revalidatePath('/admin/richtlinie') return { ok: true } }