#!/usr/bin/env node // Lädt die Datenschutzerklärung (PDF und HTML) nach der Freigabe als neue Version in WOMS „Rechtliches“ hoch (Karte datenschutz, Bucket // legal-files, Collection legalVersions): neue Fassung "current", die bisherige gültige wird "superseded" mit validTo. Nur mit // --freigabe=JJJJ-MM-TT; dieser Tag muss der „Stand TT.MM.JJJJ“ in public/datenschutz.html entsprechen. Schon hochgeladene Stände (gleiche source, // also gleicher Commit) werden übersprungen. Den Ablauf teilt sich das Skript mit rechtliches-hochladen.mjs (Funktion hochladen). // Zwei Sperren gegen eine unfertige Fassung (vor dem Schreiben): (1) steht im Text noch eine „[OFFEN: …]“-Markierung (offene Tatsache im // Faktenblatt), (2) passt die Prüfsumme neben dem PDF (docs/WEBklar-Datenschutzerklaerung.pdf.sha256) nicht zur HTML, ist das PDF also nicht aus // dieser HTML gedruckt (scripts/build-legal-pdfs.sh datenschutz), dann Abbruch. // // node scripts/datenschutz-hochladen.mjs --probe nur lesen: Schlüssel, Bucket, Karte datenschutz und ihre Versionen // node scripts/datenschutz-hochladen.mjs --freigabe=JJJJ-MM-TT lädt die Datenschutzerklärung hoch (validFrom = Freigabedatum); ohne Karte, // ohne beide Dateien, mit nicht committetem Stand oder mit abweichendem // „Stand“ Abbruch vor dem Schreiben // // Schlüssel: kurzlebiger Appwrite-Schlüssel mit files.read/files.write/documents.read/documents.write in /root/.appwrite-rechtliches.key (chmod 600). // Der Import dieser Datei liest weder den Schlüssel noch nutzt er das Netz; beides geschieht nur in main (deps.schluessel, deps.fetch). // Dieses Skript wird nur geschrieben und mit Nachbau-deps getestet, nie von einem Agenten ausgeführt (auch nicht mit --probe). import { createHash } from 'node:crypto' import { readFileSync } from 'node:fs' import path from 'node:path' import { fileURLToPath } from 'node:url' import { BUCKET, KEY_DATEI, alleDokumente, client, ddmmjjjj, hochladen, istKalendertag, versionen } from './rechtliches-hochladen.mjs' const DOKUMENT_KEY = 'datenschutz' /** [PDF, HTML]: in dieser Reihenfolge hochgeladen. */ const DATEIEN = Object.freeze(['docs/WEBklar-Datenschutzerklaerung.pdf', 'public/datenschutz.html']) const QUELLE = 'public/datenschutz.html' /** Neben dem PDF: SHA-256 der HTML, aus der es gedruckt wurde (scripts/build-legal-pdfs.sh datenschutz). */ const PRUEFSUMME = 'docs/WEBklar-Datenschutzerklaerung.pdf.sha256' /** Für Kunden sichtbar (WOMS „Rechtliches“): darum weder „Workers“ noch „Hustler“. */ const AENDERUNG = 'Abschnitt 11 Interessenten (Antworten auf öffentliche Anfragen)' const USAGE = 'Aufruf: node scripts/datenschutz-hochladen.mjs --probe | --freigabe=JJJJ-MM-TT' /** * Kommandozeile prüfen: --probe allein oder genau eine --freigabe=JJJJ-MM-TT (ein echter Kalendertag). * @returns {{ modus: 'probe'|'hochladen', freigabe: string|null }} */ export function parseArgs(argv) { const fremde = argv.filter((a) => a !== '--probe' && !a.startsWith('--freigabe=')) if (fremde.length > 0) throw new Error(`${USAGE}\nUnbekanntes Argument: ${fremde[0].slice(0, 40)}`) const probe = argv.filter((a) => a === '--probe') const freigaben = argv.filter((a) => a.startsWith('--freigabe=')) if (probe.length > 0) { if (probe.length > 1 || freigaben.length > 0) throw new Error(`${USAGE}\n--probe steht allein.`) return { modus: 'probe', freigabe: null } } if (freigaben.length !== 1) throw new Error(`${USAGE}\nFreigabe fehlt: genau eine --freigabe=JJJJ-MM-TT ist beim Hochladen Pflicht.`) const freigabe = freigaben[0].slice('--freigabe='.length) if (!istKalendertag(freigabe)) throw new Error(`Freigabe ungültig (erwartet JJJJ-MM-TT, ein echter Kalendertag): ${freigabe.slice(0, 20)}`) return { modus: 'hochladen', freigabe } } /** Der Tag hinter „Stand“ in der Kopfzeile der HTML (TT.MM.JJJJ), sonst null. */ const standIn = (html) => /