/** * Fehler, die bis in die Oberfläche durchgereicht werden. * * `code` ist ein Schlüssel in `de.actionErrors`, kein Text: die Meldung wird * erst am Rand übersetzt. Ein Fehler, den der Nutzer nicht sehen darf, kommt * gar nicht erst hier an — fehlender Zugriff endet in 404, nicht in 403. */ export class AccessError extends Error { constructor(readonly code: string) { super(code) this.name = 'AccessError' } } /** * Kein stilles Überschreiben: die fremde Fassung kommt mit zurück, damit der * Nutzer beide sieht und entscheidet. Siehe docs/05-akten-und-vorlagen.md. */ export class ConflictError extends Error { constructor( readonly current: { value: unknown; version: number; updatedById: string | null }, ) { super('conflict') this.name = 'ConflictError' } } export function must(check: { ok: boolean; reason?: string }): void { if (!check.ok) throw new AccessError(check.reason ?? 'denied') }