35 KiB
Changelog
2026-07-09 — geo_reverse + Workflow karte-verorten
- geo_reverse — Reverse-Geocoding: Punkt (GeoJSON 25833 aus geo_erfassen oder ost/nord) → Ort, Ortsteil, PLZ, Straße. Transform via utm33ToWgs84 (require-route), Abfrage Nominatim/OSM. Der ALKIS-WFS liefert keine PLZ/Ortsteil.
- Workflow karte-verorten (Server, workflows/karte-verorten.xml): Punkt auf der Karte anklicken (geo_erfassen) → geo_reverse → Ort/Ortsteil/PLZ anzeigen. Start: start.php?xml=karte-verorten; auch als Kachel auf der Startseite.
2026-07-09 — personen_liste: anrede-Spalte
- personen_liste liefert zusätzlich
anrede(get_Anrede(false) = „Frau/Herr Nachname"). Genutzt im Posteingang-Workflow: die Select-Option trägtdata-anrede, JS schreibt sie ins Feldempfaenger_anrede→ E-Mail-Anrede „Hallo Frau Hielscher,". Mail neu strukturiert (HTML<br>, {{{BESCHREIBUNG}}} ist roh), Datei-Zeile entfernt. Neu:{{ICH.anrede}}in start.php.
2026-07-09 — personen_liste + Posteingang-Workflow + upload Drag&Drop
- personen_liste — Mitglieder einer Gruppe (Default VLN_MITARBEITER, rekursiv, nur aktive) als Liste {id,name,mail,funktion}; fuer -Optionen im html_form, Mail-Verteiler oder loop_foreach.
- upload — Dropzone nachgeruestet: Datei hineinziehen ODER klicken zum Auswaehlen (rueckwaertskompatibel).
- Workflow posteingang (Server, workflows/posteingang.xml): PDF hochladen -> Postnummer+Datum -> Posteingangsstempel positionieren+einbrennen (ohne Signatur) -> herunterladen ODER an VLN-Mitarbeiter weiterleiten (E-Mail "Neuer Posteingang" mit Anhang).
- posteingang / postausgang — PDF mit Eingangs-/Ausgangsstempel ("EINGANG/AUSGANG VLN Sachsen / Datum / Nr.") versehen. Der Stempel wird LOKAL per GD gezeichnet (1:1-Kopie der Generatoren 0_meinvln/posteingang|postausgang/stempel.php, kein mein.*-HTTP), interaktive Platzierung + Einbrennen von pdf_stamp_interactive geerbt. Config: file (Pflicht), nr, datum, breite_mm/hoehe_mm, output_var; assign_to Pflicht (interaktiv). Transparenter Hintergrund.
- pdf_ocr — gescannte PDF durchsuchbar machen (ocrmypdf/tesseract deu). Gemeinsamer Extraktor _DokumentText.php mit OCR-Fallback, jetzt auch in ki_auftrag, ki_dok_extrakt, rag_einpflegen. ki_auftrag bricht bei leerer Eingabedatei hart ab.
- rag_status — Chunk-Anzahl + distinkte Quellen im (gefilterten) Bereich; Idempotenz-Wächter vor rag_einpflegen.
- rag_loeschen — Quelle/Bereich aus dem Vektor-RAG entfernen (Filter Pflicht).
- bauakte_dateien — alle Dateien einer Bauakte/eines Ordners als Liste (loop_foreach → rag_einpflegen).
- ki_tabelle — mehrere Tabellenzeilen per KI extrahieren → Liste.
- ki_pruefliste — Dokument gegen N Kriterien: ja/nein/unklar + Begründung.
- ki_beleg_pruefung — Aussagen gegen Quelle prüfen (belegt/unbelegt/widerspruch).
- text_diff — zwei Texte/Dokumente deterministisch vergleichen (diff -u, ohne KI).
-
Fix: Mixed-Content bei
start.php-Start.start.phpbauteURL_WORKFLOWaus$_SERVER['HTTPS']— hinter Traefik (TLS am Proxy) nicht gesetzt ⇒http://. Das ES-Modulpdf.js/pdf-libinpdf_zeichnenwurde dadurch als Mixed-Content geblockt (Editor blieb bei „PDF wird geladen …").start.phpnutzt jetzt die kanonischeURL_WORKFLOW-Konstante (https, Fallback X-Forwarded-Proto);TaskPdfZeichnenhebt die pdflib-Basis zusätzlich defensiv auf https, wenn der Request https ist. Betraf nur den Browser-Start via start.php (MCP-Start war https). -
Neu: Task
bauakte_attribut— setzt/entfernt Metadaten imDATA_FILE.content-JSON einer Bauakte-Datei. Kurzform<signiert>true</signiert>setzt das Bauakte-signed-Flag (sperrt Bearbeiten; KEINE Krypto-Signatur), plus freie<attribute>(JSON) und<entfernen>. Nur Dateien in der angegebenen Bauakte, md5-validiert. Invergabe-angebot-pruefennach der Ablage eingebaut (markiert das geprüfte Dokument als signiert). DBV-Falle dokumentiert:DBV::getInstance()hat keinsqlSafe(das istDB/SecureDB) → in Taskssql/sqlA+escapenutzen. -
Neu: Task
rag_einpflegen— Dokument (PDF/TXT/MD/DOCX) oder Rohtext in den Vektor-RAG (Qdrantrag_docs, ollama bge-m3) einpflegen, getaggt mit<bereich>(+<typ>,<quelle>, freie<meta key>). Danach perrag_recherche <filter key="bereich">durchsuchbar; gesetzte Meta-Schlüssel werden als Qdrant-Index angelegt. Textextraktion via pdftotext/pandoc/soffice. Voraussetzung:php-workerim Netzqdrant_default(in manager/docker-compose.yaml persistiert). -
Fix:
is_signedin der Bauakte war unzuverlässig.DATA_FILE.content.signedwird nur gesetzt, wenn IN der Bauakte signiert wurde — extern signierte PDFs (z. B. „VLN Sachsen Autosign") standen auffalse. Folge: „Bearbeiten" und „Vergabe prüfen" wurden für signierte Dateien angeboten, undpdf-annot.phpliess sie per Direkt-URL bearbeiten (── „Drehung speichern" hätte das Original und damit die Signatur überschrieben). Neu zentral inrequire-bauakte.php:pdf_hat_signatur()(Tail-Scan der letzten 64 KB auf/ByteRange, 1,8 ms/Datei statt 23 ms fürpdfsig) undbauakte_datei_signiert()(Flag ODER echte Signatur). Genutzt inindex.php,pdf-annot.phpund derpdf_annot_save-Sperre inajax.php. Ergebnis deckte sich bei allen Stichproben mitpdfsig. -
bauakte_datei_waehlen: Begründung statt stiller Auswahl. Wird per Direkteinstieg eine Datei übergeben, die abgelehnt wird (signiert / falscher Ordner / andere Bauakte), nennt die GUI jetzt den Grund, statt kommentarlos die Dateiauswahl zu zeigen. start.php: Start-Parameter-Whitelist.?code=<md5>&file=<md5>&zurueck=bauaktelanden alsstart_bauakte_md5/start_file_md5(Praefix = ungeprueft) bzw. als serverseitig gemapptesrueck_url/rueck_nameim Kontext. Nur 32-hex bzw. bekanntes Kuerzel; keine Pfade/Dateinamen.bauakte_pick+bauakte_datei_waehlen: Direkteinstieg. Liegt die id schon im Kontext (start_bauakte_md5/start_file_md5), wird KEINE GUI gezeigt — die id wird gegen genau die rechtegefilterte Liste geprueft, die der Nutzer sonst saehe (Bauakte perget_meine(), Datei per Bauakte+Ordner+nur_unsigniert). Kein Treffer ⇒ normale GUI. Mit<start_var></start_var>abschaltbar.vergabe-angebot-pruefen: Abschluss-Schritt mit Rueckkehr. Popup ⇒postMessage(workflow_fertig)window.close()(weg 2); gleicher Tab mitrueck_url⇒ Button + Auto-Weiterleitung (weg 1); sonst normaler Fertig-Bildschirm. Werte ueber Data-Attribute (XSS-sicher), targetOrigin fest.
- Bauakte: Dropdown-Eintrag „Vergabe pruefen" pro PDF im Ordner Vergabe/Angebote (V/AA), oeffnet
den Workflow als Popup und laedt den Ordner nach dem Fertig-Signal neu. Kein iframe (SameSite=Lax,
cross-site). Doku:
direktstart.md. workflow_lintpräzisiert.ja¹-Zellen in der Doku markieren alternative Quellen (z. B.pdf_stamp_interactive:vorlage|stempel|stempel_text) und gelten nicht mehr als Pflichtparameter — das erzeugte Fehlalarme. Ein Task ohneidist jetzt eine Warnung; mehrere Tasks ohneidsind ein Fehler, weil sie sich den State-Key teilen (Abschluss-Marker vermischen sich).- MCP: drei weitere Werkzeuge.
workflow_getversteht jetztformat=struktur— nur der Task-Baum (Typ, id, assign_to, Verzweigung, output_var) statt der ganzen XML. Beibauakte-vergabe-pruefen: 1.772 statt 6.251 Zeichen (−72 %). Standard bleibtxml.workflow_vars— Variablen-Landkarte: welche Kontextvariablen erzeugt werden (mit Task und Herkunftsart:<output_var>,<var name>,<as>, Formularfeld, Task-id), welche gelesen werden und welche gelesen werden, ohne je gesetzt zu sein (Tippfehler).workflow_batch— mehrere Werkzeuge in einem Aufruf (z. B.create+lint+start). Jede Operation wird einzeln gegen die gewährten Scopes geprüft (einread-Key kann darüber keinworkflow_createausführen), Verschachtelung ist verboten, max. 20 Operationen; die Kette bricht standardmäßig beim ersten Fehler ab und meldet die restlichen als übersprungen.
pdf_stempel_oben: Schriftart wählbar. Neue Parameterschrift,schriftgroesse,schriftstil,abstand_oben_mm,auto_verkleinern. Neben den FPDF-Kern-Fonts stehtNATIONFD(NationalFirstFontDotted, gepunktet) zur Verfügung — dieselbe Schrift, diePDFER::stamper()für die Vergabe-Unterlagen nutzt. Unbekannte Schrift → Fehlermeldung mit Liste der verfügbaren. Eingebettete Schriften haben nur eine Schnittform, ein angeforderterschriftstilwird verworfen (sonst FPDF-Abbruch „Undefined font"). Zellhöhe bleibt fix bei 7 mm, damit große Schriften oben stehen bleiben. Vorgabe (Helvetica 12 pt fett) unverändert —pdf_anlagen_mergenutzt dieselbe Routine und bleibt unberührt.auto_verkleinern(Default an) schrumpft zu breiten Text, statt ihn über den Seitenrand laufen zu lassen.- Neu: Task
liste— Tabelle direkt im Editor pflegen (freie Spalten, z. B. name/mail/rolle). Ergebnis ist eine Liste aus Zeilen-Objekten:{{var}}(loop_foreach),{{var}}_json,{{var}}_anzahl,{{var}}_leerund je Spalte{{var}}_<spalte>_liste(fertiger Mail-Verteiler). Zellen dürfen Platzhalter enthalten. - Neu: Task
liste_filtern— Zeilen nach Bedingungen auswählen (ist,enthaelt,endet_auf,groesser,in, … ;und/oder). Quelle ist jede Liste (Taskliste,person_pick,json_transform, JSON-String oder Komma-Liste). Zusätzlich{{var}}_entfernt. - Editor: neuer Feldtyp
table— echtes Zeilenraster, feste oder dynamische Spalten (columnsFrom); Kopfzeile zieht nach, wennspaltengeändert wird. - MCP: vier neue Werkzeuge (token-sparsam entworfen):
task_list— alle Task-Typen mit Einzeiler, optional Volltextfilter;interaktiv=truemarkiert Tasks, die<assign_to>brauchen.task_doc— Doku zu MEHREREN Tasks in EINEM Aufruf;format=xml|kurz|md(≈1/10, 1/3, voll).task_search— findet den passenden Task zu einer Aufgabenbeschreibung.workflow_lint— statische Prüfung: unbekannte Task-Typen, doppelte ids, fehlende Pflichtparameter, interaktive Tasks ohne<assign_to>. Fängt ab, was sonst erst beim Start auffällt.
pdf_stamp_interactive: Stempelart zur Laufzeit wählbar. Neue Parameterstempel_auswahl(Komma-Liste oderalle) undstempel_default. Der Bearbeiter wählt die Art im Dropdown; Bild und Maße wechseln mit. Neue Ausgaben<id>_stempel_art/<id>_stempel_label.- Fix: Stempelgröße.
autorechnete Pixel mit 96 dpi um, diebau-Vorlage rendert aber mit 4 px/pt. Stempel waren dreimal zu groß (breiter als A4). Block-Stempel messen jetzt 84,7 × 22,9 mm (= die instempel-core.phpdokumentierten 85 × 23 mm). Gemerkte Skalierung invalidiert (localStorage-Schlüsselwf_stempel_scale2:). - Fix: Block-Stempel ohne
summe(frf,ga,v,f,ng) liefen in einen TypeError inzueuro().summewird jetzt übervoneuro()normalisiert,datumfällt auf heute zurück. Kein stiller HTTP-Fallback mehr — der echte Fehlergrund wird gemeldet. - Fix: Quelldateien außerhalb des Docroots. Neu
AbstractTask::browserFile(): liegt die PDF nicht unter dem Workflow-Docroot (z. B. Bauakte-Datei ausupload_neu), wird sie einmalig instemp_dirkopiert. Ohne das bekam der Browser einen Dateipfad statt einer URL und der Editor blieb leer — betrafpdf_zeichnenundpdf_stamp_interactive. bauakte_datei_waehlen: neuer Parameterordner(KurzcodeVoder KlarnameVergabe, Komma-Liste, exakter Treffer) sowie neue Ausgaben<prefix>_basis(Name ohne Endung) und<prefix>_endung.bauakte_datei_waehlen: Pfad-Filter und Signatur-Filter.<ordner>versteht jetzt Pfade (V/AA,Vergabe/Angebote, gemischtVergabe/AA); je Segment zaehlt Kurzcode oder Klarname. Neu<nur_unsigniert>true</nur_unsigniert>: digital signierte PDFs werden gar nicht erst angeboten (und beim Absenden serverseitig abgewiesen) — sie liessen sich ohnehin nicht bearbeiten. Erkennung perpdfsig; das Bauakte-FlagDATA_FILE.content.signedist nicht verlaesslich. Nebenbei:DATA_FOLDER.settingist PHP-serialisiert, nicht JSON.- Neuer Workflow
bauakte-vergabe-pruefen: Bauakte → PDF ausVergabe→ kommentieren → Summe → Prüfstempel platzieren → als<Name>_geprüft.pdfin denselben Ordner zurück. - Neu: Task
pdf_zeichnen— Freihand-Markierungen direkt auf der PDF (Stift, Linie, Pfeil, Rechteck, Ellipse, Text, Radierer ganz/Bereich), eigene Stifte inkl. Textmarker-Deckkraft, „Nur mit Stift“ (Apple Pencil / Palm Rejection), Zoom, Ansicht-Drehung, Undo/Redo, lokaler Entwurf. Gleiche Zeichenmaschine wie der Bauakte-PDF-Editor. Beim Abschluss brennt pdf-lib die Striche als Vektor-Ebene (OCG „Markierungen“) ins PDF. Signierte PDFs sind gesperrt (signiert=ablehnen). Doku:tasks/pdf_zeichnen.md. - Neue Option eigene_signatur=true (+ optional grund): die Platzier-GUI verlangt P12-Datei + Zertifikat-Passwort; das PDF wird kryptografisch signiert (pyHanko/PAdES-LTA via ltv-signer) mit dem Stempel als sichtbarer Signatur-Optik an der geklickten Position, statt das Bild nur einzubrennen.
- Sicherheit: is_uploaded_file, openssl_pkcs12_read gegen Passwort, P12 in 0600-Tempdatei + Cleanup, Passwort nie geloggt. P12/Passwort-Felder via form="posForm" (multipart); Confirm erst bei Position + Zertifikat+Passwort.
- QGIS-Kern komplettiert (10 Geo-Tasks): geo_aufloesen (Dissolve), geo_verorten (raeuml. Join), geo_zuschneiden (Clip), geo_konvexe_huelle, geo_vereinfachen (Simplify), geo_zusammenfuehren (Merge), geo_zaehlen_in_flaeche (Count in polygon), geo_reparieren (ogr2ogr -makevalid; MariaDB kann kein ST_MakeValid), geo_umschliessende_box (Envelope), geo_naechster (Nearest). Neuer Helfer geo_features().
- geo_wfs: nur_attribut/nur_wert (Client-Filter) + bbox_puffer (arithmetisch, KEIN ST_Buffer-Hang). geo_raeumliche_auswahl: toleranz (ST_Distance-Saum) + _bbox-Output. geo_visualisieren: legende an/aus (karte.php ?legende=0 + Umschalter).
- Cache: cache_lade (jetzt CONTAINER wie if: Kind-Tasks laufen nur bei Miss + Ergebnis wird auto-gecacht) + cache_schreiben; Datei-Cache MD5+TTL.
- Excel: excel_lesen/excel_schreiben (PhpSpreadsheet; Startzelle/Spalten/Bereich/Einzelzellen/Vorlage). Word: word_lesen/word_schreiben (PhpWord TemplateProcessor ${platzhalter}+Zeilen klonen; PDF via soffice). Zip: zip_erstellen/zip_entpacken (ZipArchive, Zip-Slip-sicher). Je eigener *-download.php (statisch geblockt).
- upload: interaktiver Datei-Upload ($_FILES) -> Serverpfad in Context; entsperrt excel_lesen/word_lesen/zip_entpacken.
- Workflow dokument-signatur-verband: upload PDF -> optionale Freigeber (sequenziell, approve_reject) -> Unterschrift Verband-Mitarbeiter (pdf_stamp_interactive). Als Start-Button Dokument digital freizeichnen in MeinVLN.
- Fixes: pdf_stamp_interactive vorlage=bau lokal statt HTTP (Container erreicht mein.*-URL nicht; stempel-core.php); Stempel-Picker Cursor ohne Bild ueber Kopfleiste; person_pick required=false erlaubt Absenden ohne Auswahl; Editor: XML-Kommentare editierbar + verschiebbar (mit Task oder einzeln).
- geo_raeumliche_auswahl: waehlt aus einer Kandidaten-Featuremenge alle Features nach raeumlicher Relation zu einer Referenz (intersects/touches/within/contains/overlaps/disjoint) -> liefert die Feature-Liste (nicht wie geo_verschneidung eine Geometrie, nicht wie geo_selektieren interaktiv).
- Anwendung: FB-Gemeinden (Gemeinden die das Verfahren schneiden) + anliegende Gemeinden (touches, mit Ausschluss der FBG). sammeln_var akkumuliert {name,art} ueber mehrere Aufrufe -> Ergebnistabelle. Editor-Schema + Palette (Geo-Operationen) ergaenzt.
- Backend MariaDB-Spatial (ST_Intersects/ST_Touches...). Verkettung: tg_pick -> geo_lade(umringe) -> geo_wfs(Gemeinden) -> geo_raeumliche_auswahl x2.
- Neue Option zertifizieren= an pdf_siegel (pyHanko-Weg): Autor-/Zertifizierungssignatur (blaues Band in Acrobat). endfassung=P1 keine Aenderung (LTA erzwungen AUS, da nachtraeglicher Dok-Zeitstempel P=1 bricht), zertifiziert=P2 (Inhalt gesperrt, LTA), mit_kommentaren=P3 (+Annotationen, LTA). Muss erste Signatur sein.
- ltv-signer /sign um certify-Parameter erweitert (MDPPerm NO_CHANGES/FILL_FORMS/ANNOTATE); pdfsign_ltv() + Task + Editor + Doku.
- Acrobat-Hinweis: Zertifizierungen brauchen im Trust der VLN-Root zusaetzlich den Haken 'Zertifizierte Dokumente'.
- pdf_siegel mit ltv=true kann jetzt eine SICHTBARE Signatur mit Stempelbild setzen (Bild-only). Neue Task-Felder bild/seite/x/y/breite/hoehe (Koordinaten oben-links, Points, Seite 1-basiert wie sign_an_position; leer/-1 = letzte Seite). LTA bleibt erhalten (Kette + Sperrinfos + Dok-Zeitstempel).
- ltv-signer-Container um pyHanko [image-support]/Pillow erweitert; rendert das Bild als StaticStampStyle-Hintergrund in einem sichtbaren Signaturfeld. pdfsign_ltv() um image/page/box-Parameter erweitert.
- Hinweis: SAPP-Funktionen sign_mit_bild/sign_an_position koennen ebenfalls Bilder, sind aber PAdES-T (kein LTA).
- Neuer Signierweg: pdf_siegel mit ltv=true erzeugt PAdES-LTA (langzeit-validierbar). Zertifikatskette + Sperrinfos (VLN-CRL + DigiCert-TSA-OCSP) + Dokument-Zeitstempel werden ins PDF (DSS) eingebettet. In Acrobat gruen OHNE 'Sperrung nicht geprueft' und OHNE 'nicht LTV-faehig' (bei importierter VLN-Stamm-CA).
- Neue VLN-CA-Sperrinfrastruktur (/daten/dockervorlagen/manager/pki): eigenes autosign_ltv.p12 (Leaf mit crlDistributionPoints + authorityInfoAccess/OCSP, EKU documentSigning), delegierter OCSP-Signer (EKU OCSPSigning + noCheck). Root unveraendert wiederverwendet.
- CRL + OCSP oeffentlich unter https://sign.flurneuordnung-sachsen.de/pki/ : statische CRL (taeglich per Cron, pki/renew_crl.sh) + OCSP-Responder-Container ocsp-responder (nginx-sign Proxy location /pki/ocsp).
- Signatur via Microservice-Container ltv-signer (pyHanko 0.35, Token-gesichert, www read-only + Sandbox 0_workflow/ltv). Neue Funktion pdfsign_ltv() in require-sign.php ruft ihn per HTTP.
- SAPP-Weg (pdfsign_tsa, PAdES-T, autosign.p12) bleibt Default; ltv=true schaltet auf den pyHanko-LTA-Weg.
- Neuer Task pdf_signaturen: liest alle Signaturen einer PDF (poppler pdfsig) als Array in Signier-Reihenfolge (sortiert nach Signierzeit). Je Eintrag: nr, unterzeichner (CN), dn, email, signiert_am/_iso, zeitstempel, feld, hash, abdeckung_gesamt, gueltig, zertifikat_status. Ausgabe {{signaturen}} (+ _json fuer loop_foreach, _anzahl, _letzter, _letzter_am).
- Neuer Task pdf_signatur_integritaet: prueft, ob NACH der letzten Signatur noch veraendert wurde (deckt die zeitlich letzte Signatur das ganze Dokument bis zum Dateiende?). Ausgabe {{integritaet_unveraendert}}/{{integritaet_veraendert}} (bool), _signiert, _letzter_unterzeichner, _letzter_am, _nachtraeglich_bytes, _meldung. Verzweigung per if auf {{integritaet_veraendert}}.
- Gemeinsamer Parser (public static in TaskPdfSignaturen) fuer beide Tasks. In den Editor eingepflegt (Palette PDF, Schema + Hilfe-Doku tasks/pdf_signaturen.md + tasks/pdf_signatur_integritaet.md).
- Verifiziert: 1-Sig unveraendert; 2-Sig korrekt in Reihenfolge (erste partial, letzte gesamt); +5 Byte angehaengt -> als 'VERAENDERT +5B' erkannt.
- Ursache: SAPP misst die Signaturlaenge mit einem TSA-Abruf und signiert dann mit einem zweiten; RFC-3161-Zeitstempel variieren um wenige Bytes, wodurch die reservierte /Contents-Laenge nicht zur echten Signatur passte. Folge: ByteRange um wenige Bytes verrechnet -> Acrobat 'SigDict /Contents illegal data' bzw. 'Digest Mismatch', Zeitstempel nicht erkannt. Trat intermittierend auf.
- Fix in vendor/ddn/sapp/PDFDoc.php: Reserve-Marge auf __SIGNATURE_MAX_LENGTH + /Contents wird auf die reservierte Laenge aufgefuellt (Trailing-Nullen liegen ausserhalb der ByteRange). 8/8 Wiederholungslaeufe jetzt gueltig (poppler: Signature is Valid / Total document signed).
- pdfsign_tsa() prueft nach dem Schreiben zusaetzlich die ByteRange-Konsistenz und wirft bei Abweichung eine Exception (keine still-kaputten Siegel).
- Hinweis: 'Identitaet nicht bestaetigt' bleibt normal (VLN-eigene CA, nicht in Acrobats Vertrauensliste); erst Import der VLN-Stamm-CA macht es voll gruen.
- Neuer Task pdf_siegel: siegelt eine PDF mit dem VLN-Org-Zertifikat (autosign.p12) als PAdES-T inkl. DigiCert-Zeitstempel (LTV) und optionalem Signatur-Grund (reason). In Acrobat sind Grund und Zeitstempel in den Unterschrifteneigenschaften sichtbar; langzeit-validierbar.
- Basis: neue Funktion pdfsign_tsa() in require-sign.php (SAPP set_tsa + set_metadata_props). Nur dieser Weg erzeugt einen echten RFC-3161-Zeitstempel; die tsa-Option des alten pdf_sign (TCPDF) ist wirkungslos.
- Config: file (Default {{latest_pdf_path}}), reason, name, ort, tsa (leer=kein Zeitstempel), output, output_var. In den Editor eingepflegt (Palette PDF, Feld reason konfigurierbar).
- Rechtlich = AES (Org-Soft-Zertifikat, keine QES). Server-seitig verifiziert: /Reason gesetzt, timeStampToken eingebettet.
- Externe Dritte (kein VLN-Login) koennen jetzt einen Workflow-Schritt bearbeiten. Neu: Tabelle WORKFLOW_EXTERN (Einmal-Token je Schritt+Mail, auditierbar), extern.php (login-loser Renderer eines einzelnen Schrittes + PDF-Stream, Vorbild 0_bauakte/extern.php), extern-lib.php.
- Neuer Task pdf_sign_extern: mailt der externen Person einen extern.php-Link; sie signiert per Zeichnen (Signaturseite wird angehaengt) ODER laedt eine unterschriebene PDF hoch. Engine: no_notify-Flag unterdrueckt die Standard-Assign-Mail (Task mailt selbst), WORKFLOW_ACCESS_TOKEN im Context.
- Workflow dokument-gegenzeichnen: Ersteller gibt Name/Mail/Freitext + PDF -> Person erhaelt Mail 'Bitte Dokument gegenzeichnen' mit Link -> signiert login-los -> Ersteller bekommt Mail 'Dokument wurde unterzeichnet' mit signierter PDF im Anhang.
- End-to-end verifiziert (Agentmail): Invite-Mail korrekt, login-loser Zugang, Signatur -> 2-seitige PDF, Einmal-Token verbraucht.
- Hinweis: gezeichnete/hochgeladene Unterschrift = EINFACHE E-Signatur (keine QES).
- pdf_split_interactive: neuer Button 'Visuell ansehen' zeigt einen waagerechten Streifen der Seiten-Vorschauen; zwischen zwei Seiten eine Schere -> Klick setzt/entfernt einen Schnitt, die Teile werden automatisch berechnet. Manuelle Seiteneingabe bleibt Default.
- Neuer Endpoint pdf-thumb.php: rendert eine Seite server-seitig per pdftoppm (token-gesichert, gecacht). Vorschauen werden lazy geladen (nur sichtbare Seiten) -> auch 400-MB/1366-Seiten-PDFs laufen fluessig, die grosse Datei wird nie in den Browser geladen. Seitenzahl jetzt via pdfinfo (schnell).
- Verifiziert an der 424-MB-Datei (Bauakte 2027): Seite in ~0.4s als 20-KB-JPEG, Streifen + Schere + Teileberechnung funktionieren.
- Fix: Starten-Button im Editor startet jetzt den aktuell geoeffneten Workflow (start.php?xml= in neuem Tab) statt nur die leere Startseite. Ohne offene Datei erscheint ein Hinweis.
- pdf_merge_interactive (neu, generisch): fuehrt mehrere PDFs zu einer zusammen. Eingabe = Array von Pfaden (files, z.B. {{teile}}); der Bearbeiter ordnet per Drag and Drop und waehlt ab/an; Merge per pdftk (Fallback pdfunite). Gegenstueck zu pdf_split_interactive. Setzt latest_pdf_path. End-to-end verifiziert (3+2 -> 5 Seiten).
- Editor: Suchfeld im Tab Bausteine filtert die Palette live (Name/Typ); leere Gruppen werden ausgeblendet.
- pdf_split_interactive (neu, generisch): teilt eine beliebige PDF interaktiv in Teile (Name + Seitenbereich, pdftk). Ergebnis-Array fuer loop_foreach.
- bauakte_datei_waehlen (neu, Bauakte-spezifisch): waehlt eine Datei aus dem Bauakte-Ordnerbaum; liefert lokalen Pfad + Quell-Ordner (folder_md5).
- bauakte_ablage: neuer Parameter folder_md5 (schreibt in exakt diesen Ordner; Vorrang vor ordner).
- Workflow bauakte-pdf-aufteilen: Bauakte waehlen, PDF waehlen, interaktiv aufteilen, Teile per loop_foreach in den Quell-Ordner zurueckschreiben. End-to-end verifiziert (49-Seiten-PDF, 2 Teile).
- Rechte Leiste (Baum/Diagramm/Fehler/Referenz) einklappbar per Chevron-Button; eingeklappt = schmaler Streifen (Center gewinnt Platz), Zustand in localStorage gemerkt.
- XML-Kommentare: innerhalb des Workflows werden im visuellen Editor als dezente Zeile (kursiv, Sprechblasen-Icon) ueber der jeweiligen Stelle angezeigt. Kommentare ueberleben Speichern (DOMParser + XMLSerializer erhalten sie).
- Task umverteilen -> sortieren umbenannt (Klasse TaskSortieren + Alias TaskUmverteilen fuer Altbestand; Palette/Schema/Doku/Workflow-XML angepasst).
- Editor-Hilfe: zentraler Hilfe-Button oben rechts (neben Dashboard) oeffnet ein Modal mit suchbarer, gruppierter Baustein-Liste + ausfuehrlicher Doku; zusaetzlich ein '?'-Icon auf jeder Task-Karte fuer direkte Baustein-Hilfe. Doku = tasks/*.md (jetzt auch auf dem Server) via neuen editor-api.php?action=taskdoc, gerendert mit marked.js.
- Fix: 'Speichern'-Button wurde beim Hovern weiss (weiss auf weiss) -> Hover-Hintergrund wieder gruen.
- Editor-Layout: linke Spalte hat jetzt zwei Reiter Workflows und Bausteine. Beim Öffnen/Neuerstellen eines Workflows schaltet sie automatisch auf Bausteine — die Drag-Drop-Palette füllt die ganze linke Spalte statt des gequetschten Kästchens im Mittelbereich. Reiter Workflows jederzeit für die Datei-Liste. Drag-Drop unverändert (Sortable-Gruppe wf-tasks).
- Alle Tasks haben jetzt eine Doku unter tasks/*.md (18 ergänzt).
- KI-Tasks verifiziert: ki_pruefung + recht_frage jetzt funktional getestet (echte KI-/RAG-Antworten).
- Bauakte-Tasks (5): bauakte_ablage (Datei in Bauakte, Ordner-Kurzcodes z.B. G/BG), bauakte_pick (Ziel waehlen), bauakte_neu (anlegen, Massnahme Pflicht), bauakte_benachrichtigung (Verteiler mailen), bauakte_toeb (raeumlich zustaendige ToeB zu einer Geometrie). Neue Palette-Gruppe 'Bauakte'.
- Demo-Workflow bauakt-genehmigung: bauakte_pick -> html_form (schreiben) -> pdf_from_template -> approve_reject -> if approved: bauakte_ablage (G/BG) + bauakte_benachrichtigung. End-to-end verifiziert (Ablehnungs-Pfad; Ablage separat unit-getestet).
- Offen: bauakte_inbox_freigabe (erst ajax.php inbox_approve in wiederverwendbare Funktion refactoren).
- Rechen-Tasks: geo_laenge, geo_puffer (ST_Buffer, z.B. Gewaesserrandstreifen), geo_abstand, geo_zentroid, geo_pruefung (topolog. Boolean fuer type=if: enthaelt/schneidet/innerhalb/...).
- Interaktiv: geo_messen (Strecke/Flaeche live), geo_grenze_verschieben (Modify + Vorher/Nachher-ha), geo_import (Upload Shape-zip/GPKG/GML/KML/DXF/DGN/GeoJSON -> ogr2ogr -> GeoJSON 25833). geo-editor.js: 5 Modi.
- KI: ki_pruefung (zentrale KI-Kette), recht_frage (Vektor-RAG FlurbG/AVLNO).
- PDF-Protokoll: pdf_from_template ist der einheitliche Mustache->PDF-Task (Arrays {{#gesamt}} ok). Freiwilliger-Landtausch endet jetzt mit PDF-Protokoll (template/landtausch-protokoll.mustache: Einlage je Teilnehmer + Umverteilung Vorher/Nachher) + Download-Seite. End-to-end verifiziert.
- geo_gemarkung: zweiter Waehlweg parallel zum Namen — beim Reinzoomen (Ausschnitt < 30 km) werden Gemarkungsgrenzen des aktuellen Kartenausschnitts als anklickbare graue Layer geladen; Klick waehlt die Gemarkung. gemarkung-geom.php liefert ohne Parameter s jetzt die ganze FeatureCollection im bbox.
- Hintergrund-Umschalter: Namen stehen jetzt in einer Zeile mit dem Radio (Bootstrap-.row-Konflikt behoben).
- geo_gemarkung (neuer Task): Gemarkung(en) aus ganz Sachsen (5340) per Suchfeld/Datalist waehlen statt Bereich einzuzeichnen; gewaehlte Gemarkung wird auf der Karte rot hervorgehoben (Highlight via /gemarkung-geom.php on-demand). Output gem_schluessel/gem_namen/gem_geojson/gem_bbox/gem_anzahl. Daten: data/gemarkungen_sn.json, ausgeliefert ueber gemarkung-list.php (PHP-FPM blockt direkte .json).
- geo_selektieren: neue Optionen filter_attribut/filter_werte (Komma-Liste) begrenzen die angezeigten Objekte serverseitig, z.B. gemaschl={{gem_schluessel}} (nur Flurstuecke der gewaehlten Gemarkung).
- Workflow freiwilliger-landtausch: Schritt 2 nutzt jetzt geo_gemarkung + gemaschl-Filter statt Polygon-Zeichnen (geo_erfassen->geo_wfs->geo_selektieren entfaellt). End-to-end verifiziert (Gohrisch: 721 Flurstuecke).
- geo-editor.js: dritter Modus 'gemarkung'. Editor-Schema + Palette ergaenzt.
- umverteilen überarbeitet: ganze Teilnehmer-Spalte ist Ablagezone (irgendwo loslassen → unten angehängt; an Position → dort einsortiert), größere Felder, Greif-Icon, „hierher ziehen"-Platzhalter, Ziel-Spalte-Hervorhebung beim Ziehen, Delta-Anzeige (+/− ha). emptyInsertThreshold für leichteres Treffen.
- geo_selektieren
<flurnummer_aus>: berechnetes Feldflurnummeraus Zaehler/Nenner (lesbare Flurstuecksnummer 5 / 3/109 / 7 a statt Roh-Kennzeichen). In freiwilliger-landtausch fuer die Flurstueck-Anzeige aktiviert. - Task
geo_tausch→umverteilenumbenannt (generischer Drag-&-Drop-Verteil-Task, nicht geodaten-spezifisch). Editor-Palette: von „Geo-Operationen" nach „Benutzer". Workflow freiwilliger-landtausch angepasst. - Neuer Task
geo_tausch: Drag-&-Drop-Board zur Umverteilung von Elementen zwischen Gruppen (Teilnehmern); je Gruppe Vorher-/Nachher-Flaeche (ha), Nachher dynamisch. Infreiwilliger-landtauschals Schritt 4 ergaenzt. End-to-end verifiziert. - geo_selektieren: Live-Tabelle (
<tabelle>), Flaechen-Summe (<flaeche_attribut>m²→ha), Akkumulation ueber Schleifen (<sammeln_var>/<sammeln_label>),_bbox/_summe_ha. geo_erfassen:_bbox-Output. Statisches geo-editor.js jetzt cache-gebustet. - Neuer Workflow
freiwilliger-landtausch: Teilnehmerzahl → je Teilnehmer Suchbereich/Gemarkung/Flurstuecke waehlen (ALKIS-WFS) mit dynamischer ha-Tabelle → Uebersicht je Teilnehmer mit Gesamtflaeche. End-to-end verifiziert. - Neue Tasks
geo_erfassen(Punkte/Linien/Polygone auf der Karte zeichnen; Typ + Anzahl steuerbar) undgeo_selektieren(dargestellte Objekte per Klick auswaehlen; liefert Features + ID-Liste). Gemeinsamer OpenLayers-Editor /geo-editor.js. End-to-end verifiziert. - Neuer Task
geo_export+ Endpointgeo-download.php: Download der Geodaten in GeoPackage/Shapefile/DXF/DGN/GML/KML/CSV/GeoJSON/FlatGeobuf (ogr2ogr, EPSG:25833; KML→WGS84). Formate beim Task-Erstellen steuerbar; ein Format = kein Auswahldialog. DWG-Hinweis: DXF (native DWG nur mit ODA-Konverter). In gewaesser-im-verfahren als Download-Schritt ergaenzt. - geo_visualisieren + Viewer: Erweiterte Signaturen. Neuer Layer-
typ="maske"(EQK-Inverse-Aufhellung: Flaeche ausserhalb des Polygons gedimmt, Rand=Umring). Attributgesteuerter<stil>-JSON: breite_nach (numerisch/kategorie), farbe_nach (kategorie/abstufung), label, punkt/icon; plus strich/deckkraft/z. turf.js im Viewer. - geo_wfs: Param
<version>— unterstuetzt jetzt auch WFS 1.1.0 (ArcGIS/Landesdienste, GML 3.1.1), inkl. LfULG-Gewaessernetz. geo_lade gibt zusaetzlich_bboxaus. - Neuer Workflow
gewaesser-im-verfahren: Verfahren waehlen → Umring laden → Fliessgewaesser-WFS → Verschneidung → Karte, die nur die Gewaesser im Verfahrensgebiet zeigt. - Neu: OAuth-2.1-Bruecke fuer den Workflow-MCP (claude.ai & Co.). Discovery + Dynamic Client Registration + authorize/token am Domain-Root; Login mit MCP-Key, Token traegt dessen Scopes. Dual-Auth (statischer Key ODER OAuth). Siehe mcp/README.md.
- Neu (Tasks):
geo_lade(Kartenobjekte in Kontext),geo_verschneidung(intersection/union/difference/symdifference, optional als Kartenobjekt speichern),geo_wfs(WFS-GetFeature mit GML-3.2-Fallback fuer ALKIS & Co.),geo_visualisieren(OpenLayers-Karten-Viewer mit Basemap.de/Luftbild-DOP/DTK/OSM + schaltbaren Layern, oeffentlicher Link karte.php?id=...). Editor-Palette-Gruppe Geo-Operationen erweitert. End-to-end getestet: ALKIS-WFS -> Verschneidung (56 ha) -> Karten-Link. - Neu: Workflow-MCP-Server unter /mcp (JSON-RPC). Gescopte API-Keys (read/author/interact) via Admin-Konsole im Dashboard. 10 Tools zum Erstellen/Bearbeiten/Starten von Workflows und Interagieren mit Instanzen. Siehe mcp/README.md.
- Neu (Visueller Editor): Persistente Baustein-Palette links neben dem Baum. Tasks werden per Drag-and-Drop aus der Palette in die Container (Sequenz/Parallel/then-else/Wurzel) gezogen. Ersetzt das bisherige, schwer auffindbare "+"-Einfügen (nur am Container-Ende). Touch-tauglich (SortableJS forceFallback) für Tablet-Nutzung. Umsortieren bestehender Karten unverändert.
- Fix (Engine):
stop-Task setzte den Gesamtstatus nicht aufCANCELLED. Der Persist-Block inrequire-workflow.phpbehandelte nursuccess/error/return/waiting— beistopfiel der Status auf den DefaultRUNNINGzurück und der Bearbeiter blieb zugewiesen. Folge: abgelehnte Workflows (z. B. Dienstreise nach Vorsitz-Ablehnung) blieben als offene Aufgabe hängen, cron-resume triggerte sie endlos, und der Bearbeiten-Link führte nur zur Sackgasse "Vorgang abgebrochen". Behoben: eigenerstop-Zweig →CANCELLED+current_assignee = NULL. Wirkt für alle stop-Quellen (approve_reject-Ablehnung, quorum, TaskStop). Verhalten entspricht jetzt der bereits korrekten Doku (README "Lebenszyklus und Status", tasks/stop.md). - Neu (Task):
geo_flaeche— Muster-Task der Geo-Reihe. Fläche von Polygon-Kartenobjekten (EPSG:25833) in m²/ha, per Inline-GeoJSON oder Layer+VKZ aus KARTE_OBJEKT. Rechen-Engine MariaDB ST_Area (SRID-0-planar). Siehe tasks/geo_flaeche.md. Editor-Schema + Palette-Gruppe 'Geo-Operationen' ergänzt.
2026-07-09 — posteingang + postausgang (Post-Stempel-Tasks)
2026-07-09 — 8 neue Tasks: OCR, RAG-Verwaltung, KI→Liste, Text-Vergleich
RAG-Klasse: neue Methoden count(), quellen(), loeschen(). Editor-Schemas + Palette ergänzt; MCP-Katalog erkennt alle 8 inkl. Pflichtparameter.