import { createPrismaClient } from '../src/index.js' /** * Grundzustand der Anwendung. Alles hier ist Konfiguration, ohne die die App * nicht sinnvoll läuft, kein Testinhalt. * * Die vier Startvorlagen stehen hier, weil ohne Vorlage keine Akte angelegt * werden kann. Den Vorlagen-Editor und die übrigen Feldtypen baut Phase 3. */ const db = createPrismaClient() /** * Auslieferungszustand. Ab Stufe 3 ist die Existenz einer Akte für niedrigere * Stufen verborgen, darunter ist nur der Inhalt gesperrt. Der Leiter kann das * im Adminbereich ändern. * * Die Namen entsprechen den Zugangsrollen auf dem Discord und bleiben deshalb * englisch, siehe docs/13-entscheidungen.md. Stufe 0 hat keine eigene * Zugangsrolle: sie gilt für jedes AfiS-Mitglied ohne eine solche Rolle. */ const CLEARANCE_LEVELS = [ { level: 0, name: 'Unclassified', hiddenBelow: false, colorToken: 'stamp-0' }, { level: 1, name: 'Restricted Access', hiddenBelow: false, colorToken: 'stamp-1' }, { level: 2, name: 'Confidential Access', hiddenBelow: false, colorToken: 'stamp-2' }, { level: 3, name: 'Sensitive Access', hiddenBelow: true, colorToken: 'stamp-3' }, { level: 4, name: 'Critical Operations', hiddenBelow: true, colorToken: 'stamp-4' }, { level: 5, name: 'Executive Oversight', hiddenBelow: true, colorToken: 'stamp-5' }, ] /** * Startvorlagen nach docs/05-akten-und-vorlagen.md. Die Feldschlüssel sind * stabil und werden nie geändert — eine Akte merkt sich ihre Vorlage über * `templateId`, und eine neue Vorlagenversion lässt bestehende Akten unberührt. * * Der Zuschnitt der Felder ist bewusst schmal gehalten: den Vorlagen-Editor * mit allen Feldtypen baut Phase 3, hier steht nur, was eine Akte zum Laufen * braucht. */ const TEMPLATES: { key: string name: string description: string numberPrefix?: string numberPadding?: number }[] = [ { key: 'korruptionsverdacht', name: 'Korruptionsverdacht', description: 'Verdacht auf Vorteilsnahme, Bestechlichkeit oder Interessenkonflikt', }, { key: 'dienstvergehen', name: 'Dienstvergehen', description: 'Verstoß gegen Dienstpflichten oder interne Vorschriften', }, { key: 'sicherheitsvorfall', name: 'Sicherheitsvorfall', description: 'Containment-Bruch, Datenabfluss oder unbefugter Zugriff', }, { key: 'routinepruefung', name: 'Routineprüfung', description: 'Turnusmäßige Kontrolle ohne konkreten Anfangsverdacht', }, ] const TEMPLATE_FIELDS = [ { key: 'sachverhalt', label: 'Sachverhalt', type: 'longtext', required: true }, { key: 'beteiligte', label: 'Beteiligte Personen', type: 'longtext' }, { key: 'feststellungen', label: 'Feststellungen', type: 'longtext' }, { key: 'bewertung', label: 'Abschließende Bewertung', type: 'longtext', requiredToClose: true, help: 'Muss gefüllt sein, bevor der Fall abgeschlossen werden kann.', }, ] async function main(): Promise { for (const config of CLEARANCE_LEVELS) { await db.clearanceLevelConfig.upsert({ where: { level: config.level }, create: config, update: { name: config.name, colorToken: config.colorToken }, }) } console.log(`[seed] ${CLEARANCE_LEVELS.length} Freigabestufen`) // Änderungsrichtlinie im Auslieferungszustand: eigene Einträge sind 15 Minuten // frei änderbar, danach nur mit Recht. Eine Änderung in dieser Karenzzeit wird // versioniert und protokolliert, aber nicht sichtbar markiert. // Siehe docs/05-akten-und-vorlagen.md. await db.appSetting.upsert({ where: { id: 1 }, create: { id: 1 }, update: {}, }) console.log('[seed] Änderungsrichtlinie GRACE_WINDOW, 15 Minuten') for (const template of TEMPLATES) { await db.caseTemplate.upsert({ where: { key_version: { key: template.key, version: 1 } }, create: { ...template, numberPrefix: template.numberPrefix ?? 'AfiS', numberPadding: template.numberPadding ?? 4, version: 1, fields: TEMPLATE_FIELDS, isActive: true, }, // Muster und Felder bleiben unangetastet: was der Leiter im // Vorlagen-Editor eingestellt hat, überschreibt der Seed nicht. update: { name: template.name, description: template.description }, }) } console.log(`[seed] ${TEMPLATES.length} Startvorlagen`) // Ein Nummernkreis je Präfix und Jahr. Angelegt wird er beim ersten Fall // von selbst; hier steht er nur, damit ein frischer Bestand nachvollziehbar // bei null beginnt. const year = new Date().getFullYear() for (const prefix of [...new Set(TEMPLATES.map((t) => t.numberPrefix ?? 'AfiS'))]) { await db.caseCounter.upsert({ where: { prefix_year: { prefix, year } }, create: { prefix, year, lastNumber: 0 }, update: {}, }) } console.log(`[seed] Aktenzeichen-Zähler für ${year}`) // entry.edit_own, entry.edit_any und entry.retract sind bewusst keiner Rolle // zugeordnet. Der Leiter schaltet sie frei, wenn er sie will. // Siehe docs/03-auth-und-rechte.md. const mappings = await db.roleMapping.count() console.log(`[seed] ${mappings} Rollen-Zuordnungen vorhanden, keine angelegt`) } main() .then(() => db.$disconnect()) .catch(async (error: unknown) => { console.error('[seed] fehlgeschlagen', error) await db.$disconnect() process.exit(1) })