Entwicklerdokumentation

Was DiPAgE speichert, was es von Ihnen annimmt und womit es spricht. Geschrieben für alle, die Importer, Exporter und Integrationen bauen.

Angular 22 · zoneless IndexedDB · kein Backend PWA · Offline-First

/ drücken für Suche · Esc zum Löschen

Wenn Sie Hilfe bei der Nutzung der App suchen, dann gehen Sie zur Benutzerdokumentation

Sie suchen den Datenstandard oder Beispiel-Exporte? Zu den Downloads

Zentrale Entwicklerressourcen

Feldreferenz des Datensatzes

Jedes Feld des PSM-Anwendungsdatensatzes — insgesamt 69 — mit Typ, Einschränkungen, Beispiel und dem Verhalten, das im Schema nicht sichtbar ist.

Zur Feldreferenz
Datenstandard & Beispieldateien

Das JSON-Schema, eine XSD-Variante sowie Beispiel-Exporte in CSV, JSON und XML — alles an einem Ort.

Zu den Downloads
Sie suchen die Anwenderhilfe?

App installieren, Anwendung erfassen, für eine Prüfung exportieren — die aufgabenorientierte Dokumentation hat ihre eigene Seite.

Zur Anwenderdokumentation
Hier anfangen

Fragen von Entwicklern.

Die Fragen, die beim ersten Integrationsversuch aufkommen — ungefähr in der Reihenfolge, in der sie aufkommen.

9 Fragen

Nein. DiPAgE hat kein eigenes Backend und keine serverseitige Datenbank — es gibt nichts, wogegen man sich authentifiziert, und keinen Endpunkt, der Datensätze zurückgibt. Jeder Datensatz liegt in der IndexedDB des Browsers, in dem er erfasst wurde. Integration läuft über Dateien: aus der App exportieren, in die App importieren. Die Formate sind unter „Import, Export und Austausch“ beschrieben, die Datensatzstruktur hat eine eigene Referenzseite. Code, der innerhalb der Seite läuft, ist ein anderer Fall — siehe die JavaScript-API im nächsten Eintrag.

Ja — genau dafür gibt es window.dipageApi. Die App friert beim Start ein kleines Objekt auf window fest (derzeit Version 1.1.0), damit Code in der Seite Datensätze über Methoden lesen und schreiben kann, statt sich durch die Oberfläche zu klicken; das ist der vorgesehene Weg für einen Agenten, der Daten erhebt oder erfasst. Bereitgestellt werden createRecord, openNewRecord, updateRecord, deleteRecord, getRecord, getRecords, searchPsm, searchCrops, getProfile, exportRecords und getTemplates. Die Aufrufe laufen über dieselbe Speicherschicht wie die Oberfläche und damit über denselben Schema-Sanitizer — die API kann also keine Datensatzform schreiben, die das Formular nicht erzeugen könnte. Es ist ausschließlich eine Oberfläche innerhalb der Seite: dahinter steht kein Netzwerk-Endpunkt, sie existiert nur in einem Browser-Tab mit geöffnetem DiPAgE und verschwindet mit ihm.

Die Validierungsgrenzen für geographische Koordinaten (WGS84) stellen sicher, dass eingegebene Punkte im mathematisch und geographisch gültigen Wertebereich liegen und fehlerhafte Eingaben abgewiesen werden. Im Datenmodell sind die Grenzwerte im JSON-Schema sowie synchron in der TypeScript-Validierungslogik hinterlegt. Bei projektbezogenen Anpassungen im Quellcode sollten stets beide Stellen im gleichen Schritt gepflegt werden, um eine konsistente Validierung über alle Schnittstellen hinweg zu gewährleisten.

Da das standardisierte Datensatzformat Notfallzulassungen über die allgemeinen Anwendungsnotizen abbildet, hinterlegt DiPAgE bei entsprechenden Mitteln standardisierte, sprachunabhängige Kennungscodes im Feld notizen (z. B. PPS_EA, PPS_NZ, ŚOR_ZN). Beim erneuten Einlesen und Bearbeiten wird dieser Kennzeichner automatisch ausgewertet, sodass die Einstufung über Exporte und Reimporte hinweg verlässlich erhalten bleibt. Für externe Schnittstellen und Werkzeuge empfiehlt es sich, vorhandene Einträge im Feld notizen beizubehalten. Beachten Sie zudem, dass Notfallzulassungen gemäß Zulassungsrecht ohne reguläre Zulassungsnummer geführt werden.

Im PSM-Datenstandard wird jede Produktanwendung als eigenständiger Datensatz geführt, um den gesetzlichen Aufzeichnungspflichten für jedes einzelne Pflanzenschutzmittel und dessen spezifische Aufwandmenge präzise zu entsprechen. Um gemeinsame Arbeitsgänge mit mehreren Mitteln dennoch strukturiert zusammenzufassen, verknüpft DiPAgE diese Datensätze über kohärente Kontextparameter: Behandlungsort, Anwendungsdatum sowie einen abgestimmten Erstellungszeitstempel. Dadurch bleibt die vollständige Konformität jedes einzelnen Datensatzes gewahrt, während die Anwendungsoberfläche die Datensätze übersichtlich als zusammenhängende Tankmischung darstellt und verwaltet.

Zwei verschiedene Dinge, beide kein Schemafeld. Ein Entwurf ist ein Datensatz, den die Nutzerin mit weicher Validierung gespeichert hat; er trägt in der IndexedDB status: „draft“, doch das Schema schließt status bewusst aus — der Sanitizer entfernt ihn bei jedem Lesen und Schreiben, und die Speicherschicht hängt ihn danach wieder an, damit ein Entwurf ein Neuladen übersteht. In einem Export erscheint status nie. „Unvollständig“ wird überhaupt nicht gespeichert, sondern berechnet, indem ein gespeicherter Datensatz erneut auf fehlende Pflichtfelder geprüft wird. Unvollständige Datensätze und Entwürfe weist die Exportprüfung mit einer Meldung ab; in vollständigen Backups bleiben beide erhalten. Die reinen UI-Felder indikation, anwendungszeitpunkt und notfallzulassung werden vom Sanitizer ebenfalls entfernt.

Für JSON ist der Vertrag das Schema — dagegen validieren, fertig. Für die tabellarischen Formate kommt eine Regel hinzu: CSV und die Excel-Arbeitsmappe tragen beide einen zweizeiligen Kopf. Zeile 1 enthält lokalisierte Beschriftungen für Menschen, Zeile 2 die maschinellen Feldpfade (etwa anwendung_zeitpunkt.datum), die Daten beginnen in Zeile 3. Der Importer sucht die Pfadzeile, statt eine Position anzunehmen — deshalb lässt sich eine auf Deutsch exportierte Datei korrekt in eine englische Oberfläche importieren. Schreiben Sie Zeile 2 korrekt, dann darf in Zeile 1 stehen, was Sie möchten.

Nur Nachschlagevorgänge, und nur zu in der Content-Security-Policy festgelegten Origins: synops.julius-kuehn.de für Mittel, Indikationen, Kulturen und Notfallzulassungen; nominatim.openstreetmap.org für die Postleitzahlensuche; sowie der JKI-GeoServer und OSM-/Esri-Kachelserver für die Karten- und Geometrieauswahl. Diese Origins sind in der Content-Security-Policy verankert, sodass nichts anderes kontaktiert werden kann, selbst wenn eine Abhängigkeit es versuchte. Es gibt keine Telemetrie und keine Analyse. Ihre Datensätze verlassen das Gerät nur, wenn Sie sie selbst exportieren.

Der .xml-Export von DiPAgE ist als XML-SpreadsheetML-2003-Arbeitsmappe strukturiert. Dieses XML-basierte Tabellenformat ermöglicht es, erfasste Daten direkt und ohne Konvertierungsschritt in Tabellenkalkulationsprogrammen wie Microsoft Excel zu öffnen — inklusive formatierter Kopfzeilen und einem integrierten Referenzblatt für alle zulässigen Einheitencodes. Gleichzeitig kann die erzeugte Datei nahtlos wieder in DiPAgE importiert werden, wodurch sie sich ideal als digitaler Vorlagen- und Austauschstandard für den betrieblichen Alltag eignet.

Technische Themen.

Jedes Thema steht für sich. Öffnen Sie das, was Sie brauchen; der Rest bleibt eingeklappt.

Der Zuschnitt

DiPAgE ist eine Single-Page-Angular-Anwendung, die vollständig im Browser läuft. Es gibt keinen Anwendungsserver, keine bereitzustellende Datenbank und kein Kontosystem. Der einzige beteiligte Server liefert das statische Bundle aus, und damit endet seine Aufgabe. Alles, was die App weiß, liegt in der IndexedDB des Geräts, auf dem es erfasst wurde.

Technologieentscheidungen, die man kennen sollte

  • Angular 22 mit Standalone-Komponenten und durchgängig Signals. Change Detection ist zoneless, jede Komponente OnPush.
  • TypeScript im Strict-Modus einschließlich strictTemplates. Beachten Sie die Lücke: tsc prüft keine Templates, eine veraltete Bindung fällt erst beim AOT-Build auf.
  • Tailwind CSS 4 mit DaisyUI 5. Eigenes CSS nur dort, wo eine Utility-Klasse die Regel nicht ausdrücken kann.
  • UUIDv7 für jede erzeugte ID, damit Bezeichner nach Erstellungszeit sortieren.

Was zoneless kostet

Wer Tests gegen diese Codebasis schreibt, sollte eine Falle vorab kennen: unter zoneless Change Detection lässt sich eine im Konstruktor angelegte debounceTime- oder delay-Subscription in fakeAsync nicht mit tick() durchspülen. Die Zusicherung läuft dann durch, ohne die Entprellung überhaupt auszuführen. Legen Sie die Subscription stattdessen im Testkörper an.

Lokale Datenhaltung und Datensouveränität

Keine Synchronisation, kein Mehrgeräte-Abgleich, kein serverseitiges Backup. Daten zwischen Geräten zu bewegen ist ein ausdrücklicher Export und Import, und die zugehörige Konfliktlösung ist ein sichtbarer Ablauf statt eines Algorithmus im Hintergrund. Das ist der bewusste Preis dafür, ohne Verbindung zu arbeiten und keine personenbezogenen Daten zentral zu halten.

Die Speichereinheit

Gespeichert wird der PSM-Anwendungsdatensatz, gekennzeichnet als urn:psm:anwendung-datensatz:1.0.0 und definiert in record.schema.json (JSON Schema Draft 2020-12). Ein Datensatz beschreibt ein einmal angewandtes Mittel. Mehrere Mittel in einem Spritzgang oder mehrere behandelte Teile werden zu mehreren Datensätzen — das Formular multipliziert sie beim Speichern aus.

Wo die Komplexität wirklich sitzt

Der größte Teil des Schemas ist flach und unspektakulär. Die Ausnahme ist behandlungsort, ein Array, dessen standort_kennung_wert eine siebenfache Union ist, diskriminiert über standort_kennung_art: Koordinaten, Flurstückskennzeichen, InVeKoS-Referenz, Flächengeometrie, Gleisabschnitt, Forstadresse oder Weg. Eine davon — Wege — enthält ihrerseits eine weitere Union. Das Schema bildet das als if/then-Ketten unter allOf ab statt als benannte Varianten; ein generischer Validator kommt damit zurecht, eine handgeschriebene Prüfung muss die Verzweigung nachbauen.

Zwei Regeln, die nicht im Schema stehen

  1. Der Sanitizer ist die Formkontrolle. Jeder Lese- und Schreibvorgang wird gegen das Schema gefiltert. Ein Feld, das das Schema nicht kennt, wird stillschweigend verworfen — nicht laut abgelehnt. Wenn ein von Ihnen geschriebenes Feld danach fehlt, ist das der Grund.
  2. Manche Felder existieren im Modell, erscheinen aber in keinem Export. Beim Mittel indikation, anwendungszeitpunkt und notfallzulassung — reine UI-Felder, die auch nicht gespeichert werden. Die Ausnahme ist status am Datensatz: Der Sanitizer entfernt ihn zwar, die Speicherschicht hängt draft/saved danach aber wieder an, damit ein Entwurf ein Neuladen übersteht.

Feld für Feld

Jedes Feld mit Typ, Einschränkungen, einem einfügefertigen Beispiel und dem im Schema unsichtbaren Verhalten steht auf einer eigenen Seite — samt herunterladbarem Schema und einem vollständigen Beispieldatensatz, der alle sieben Ortsvarianten abdeckt.

Aufbau

Alles liegt in einer einzigen IndexedDB-Datenbank, psm-application-db, derzeit auf DB_VERSION 13. Sechs Object Stores: records (Anwendungsdatensätze), partial_data (wiederverwendbare Stammdatenvorlagen, nach Typ indiziert), settings, crops (die synchronisierte Kulturliste), notfallzulassungen (synchronisierte Notfallzulassungen) und logs.

Der Sanitizer liegt auf jedem Pfad

Lesen und Schreiben laufen beide durch den Schema-Filter. Das hält fremde oder veraltete Felder aus dem Speicher heraus — und ist zugleich der Grund, warum direktes Schreiben in die IndexedDB kein unterstützter Integrationsweg ist: Ihre zusätzlichen Schlüssel überleben das nächste Lesen nicht. Zum Debuggen können Sie die Datenbank dennoch in jedem Browser-Devtools-Panel öffnen (Store records) — als reine Lesediagnose.

Persistenz und Speicherverwaltung des Browsers

Die Anwendung bittet den Browser beim Start über navigator.storage.persist() um dauerhafte Speicherung. Da die endgültige Speicherverwaltung jedoch den Richtlinien des jeweiligen Browsers und Betriebssystems unterliegt (insbesondere bei knappem Gerätespeicher), sollten Anwender regelmäßig die integrierte Datensicherungsfunktion (ZIP-Export) nutzen. DiPAgE stellt bewusst keine Cloud- oder Zentralspeicherdienste bereit; die Verantwortung für die Sicherung der gesetzlich vorgeschriebenen Aufzeichnungen liegt bei den Anwendern bzw. Betrieben.

Wenn Sie das Schema ändern

Es gibt drei unabhängige Versionsnummern, die man nicht verwechseln darf: datensatz_format_version ist im Schema als const auf „1.0.0“ eingefroren und beschreibt das Datensatzformat; ein informeller Zähler („v12“, „v13“) in Codekommentaren und Changelog zählt Schema-Überarbeitungen und steht in keinem Datensatz; DB_VERSION ist die IndexedDB-Upgradeversion und taucht in keiner Exportdatei auf. Eine Schemaänderung bewegt DB_VERSION nicht zwangsläufig. Die Versionsnummern sind an Stellen gekoppelt, die Sie durch Ausführen der Testsuite nicht finden: die End-to-End-Helfer und der Schema-Integritätstest halten DB_VERSION beide fest verdrahtet. Ändert man sie an einer Stelle und nicht an den anderen, entstehen einige hundert Fehlschläge, die nach Flakiness aussehen statt nach Versionskonflikt.

Exportformate

  • JSON — formatierte Datensätze, exakt in Schemaform. Das Format, gegen das man baut.
  • XML — strukturiert als SpreadsheetML-2003-Arbeitsmappe, die Tabellenkalkulationsprogramme wie Excel nativ öffnen: formatierte Kopfzeilen, fixierte Kopfzeile und ein integriertes Referenzblatt mit allen 284 zulässigen Einheitencodes. Eignet sich hervorragend als digital bearbeitbare Vorlage und für den reibungslosen Reimport.
  • CSV — flach, mit BOM, formelartige Werte gegen CSV-Injection entschärft.
  • PDF — ein abschnittsweiser, prüfungsorientierter Aufbau mit dem Betriebsimpressum. Flächengeometrie erscheint hier als Typ, Eckpunktzahl und Zentroid statt als Rohkoordinaten; jedes andere Format behält das vollständige Array.

Der zweizeilige Kopf

CSV und Arbeitsmappe teilen sich einen Vertrag, den man vor dem Schreiben eines Parsers verstehen sollte. Zeile 1 trägt lokalisierte Beschriftungen für Menschen. Zeile 2 trägt maschinelle Feldpfade — anwendung_zeitpunkt.datum, behandlungsort[0].bezeichnung. Die Daten beginnen in Zeile 3. Der Importer sucht die Pfadzeile, statt ihre Position anzunehmen, und kommt auch mit einer älteren einzeiligen Kopfzeile zurecht. Genau das lässt eine aus der deutschen Oberfläche exportierte Datei korrekt in der englischen importieren.

Import

Angenommen werden .json, .csv, .xml und .zip mit ebendiesen. Importe werden normalisiert (Punktpfade entflacht, Typen je Feld angeglichen, deutsche Dezimalkommata und TT.MM.JJJJ-Daten erkannt) und anschließend gegen das Schema geprüft. Datensätze, denen Pflichtfelder fehlen, landen in einem Prüfschritt, in dem die Nutzerin entscheidet, ob sie trotzdem übernommen werden; strukturell unbrauchbare Einträge werden gezählt und gemeldet. Die drei Systemfelder werden bei der Normalisierung ergänzt, wenn sie fehlen — eine handausgefüllte Vorlage mit leerer ID-Spalte importiert also trotzdem.

Konflikte

Ein Import mit gleicher ID und abweichendem Inhalt öffnet einen Versionsvergleich je Datensatz — importierte gegen aktuelle Fassung, mit der Option, beide zu behalten. Ein Treffer über den Inhalts-Fingerprint bei abweichenden IDs bildet eine eigene Konfliktklasse; das ist der Fall der zweimal importierten Vorlage. Der Fingerprint ist unabhängig von der Schlüsselreihenfolge, ignoriert ID, Erstellungszeitpunkt, Notizen und Status und reagiert auf Mittel, Aufwandmenge, Datum, Kultur, Ort und Anwender.

Backups

Ein vollständiges Backup ist ein ZIP mit records.json, master_data.json, profiles.json, settings.json und metadata.json. Die Wiederherstellung ist bewusst gestuft: erst eine ausdrückliche Bestätigung, dann Einlesen ohne Schreibvorgang, dann Konfliktklassifikation, dann Übernahme. Datensätze werden dabei so wiederhergestellt, wie sie gespeichert waren — auch Entwürfe und unvollständige —, denn die Schema-Konformität wird erst beim Export durchgesetzt. Schlagen Schreibvorgänge auf halbem Weg fehl, meldet die App eine Teilwiederherstellung, statt zu einem erneuten Versuch einzuladen, der doppelt anwenden würde.

Zwei Ebenen der Validierung

Die erste Ebene ist das JSON-Schema: Pflichtfelder, Typen, Enums, Formate, überall additionalProperties: false und die bedingten Einschränkungen als if/then-Ketten. Die zweite Ebene ist Anwendungscode und setzt fachliche Regeln durch, die das Schema nicht ausdrücken kann.

Regeln, die nur im Anwendungscode stehen

  • Die Verschachtelungstiefe der Geometrie muss zum Geometrietyp passen. Das Schema verlangt nur, dass koordinaten ein Array ist.
  • Die Aufwandmenge muss größer als null sein. Das Schema sagt number.
  • Die Uhrzeit wird zur Pflicht, wenn das gewählte Mittel eine Bienenschutzauflage trägt.
  • Feldprüfungen je Ortsart, über das hinaus, was die if/then-Kette abdeckt.

Formatierung von Zeit- und Zahlenwerten

Bei der Erfassung und Validierung von Zeitangaben (anwendung_zeitpunkt.uhrzeit) unterstützt DiPAgE sowohl vollständige Zeitstempel mit Zeitzonen-Offset als auch die vereinfachte lokale Uhrzeit (HH:mm:ss), um im praktischen Feldeinsatz maximale Flexibilität zu gewährleisten. Für Gleitkommawerte mit Dezimalstellen (wie Streckenkilometer) empfiehlt sich bei externen Prüfwerkzeugen die übliche Berücksichtigung von Rundungstoleranzen im Bruchteilbereich.

Hart und weich

Nicht jede Regel blockiert. Stammdatenvorlagen nutzen durchgehend weiche Validierung: Warnungen verhindern nie ein Speichern. Im Datensatzformular sind mehrere feldübergreifende Prüfungen reine Hinweise — ein Erntejahr, das nicht zum Anwendungsdatum passt, eine behandelte Größe über der Standortgröße, ein umgekehrter BBCH-Bereich. Sie erscheinen als Warnung und lassen das Speichern zu.

Unvollständige Datensätze

„Unvollständig“ wird berechnet, nicht gespeichert: ein gespeicherter Datensatz wird erneut auf fehlende Pflichtfelder geprüft und mit einer Liste des Fehlenden markiert. Unvollständige Datensätze stehen oben in der Liste und werden von der Exportprüfung mit einer Meldung abgewiesen, bleiben aber in vollständigen Backups erhalten, damit eine Wiederherstellung verlustfrei ist.

SynOPS — der inhaltliche Kern

synops.julius-kuehn.de liefert vier Dinge: die Mittelsuche nach Handelsname oder Zulassungsnummer, eingegrenzt auf die gewählte Kultur und nach Zulassungsstatus gruppiert; die Indikationen zu einer Mittel-Kultur-Kombination samt Gefahrencodes und Dosierungsvorschlägen, die die Aufwandmenge automatisch füllen; die Kulturliste, je Sprache in die IndexedDB synchronisiert, damit die Suche offline funktioniert; und die Notfallzulassungen, ebenfalls lokal synchronisiert. Mittel- und Indikationsabfragen laufen live und entprellt, veraltete Antworten werden verworfen. Kulturen und Notfallzulassungen sind synchronisierte Datenbestände mit Altersprüfung statt Abfragen pro Anfrage.

Geokodierung und Kartendaten

nominatim.openstreetmap.org löst Postleitzahlen für die Kartenauswahl auf. Der JKI-GeoServer bedient die Geometrieauswahl über WFS: amtliche Feldblöcke samt FLIK- und Schlagnummern für Nordrhein-Westfalen (inv:NRW_FB_<Jahr>) und Umrisse aus der Kulturartenerkennung ohne jede Feldidentität für das übrige Bundesgebiet (cora:CORA_<Jahr>); OSM- und Esri-Hosts liefern die Kacheln. Nach der Auswahl eines Polygons legt die Nutzerin per Häkchen fest, welche zusätzlichen Identitätseinträge (InVeKoS-Referenz und/oder Zentroid-Koordinaten) angelegt werden — vorausgewählt ist nichts. Mit dem Polygon verbunden sind sie nur über eine gemeinsame bezeichnung, weil das Schema kein Verknüpfungsfeld kennt.

Alles davon ist festgelegt

Jeder dieser Origins steht in der Content-Security-Policy. Nichts anderes kann kontaktiert werden; das ist der Mechanismus hinter der Aussage „keine Telemetrie“, kein bloßes Versprechen.

Degradation

Fehler und Offline-Zustand schalten ein globales Banner zwischen offline und eingeschränkt. Lokales bleibt unberührt: jedes Feld lässt sich weiterhin von Hand füllen, Datensätze speichern, Exporte laufen. Nur die Nachschlagevorgänge verstummen.

Wenn Sie integrieren

Dies sind die Vorsysteme der App, keine API-Oberfläche, die DiPAgE Ihnen anbietet. Es gibt keinen DiPAgE-Endpunkt zum Aufrufen — siehe den ersten FAQ-Eintrag.

Caching-Modell

Die Offline-Fähigkeit stammt vom Angular Service Worker, konfiguriert in ngsw-config.json. App-Shell und Assets werden vorab zwischengespeichert; die externen API-Origins bekommen eigene Data Groups. Nach dem ersten erfolgreichen Laden ist die App ohne Netz vollständig bedienbar — Erfassung, Validierung, Speicherung, Export und PDF-Erzeugung laufen lokal.

Synchronisierte Bestände gegen Live-Abfragen

Zwei verschiedene Mechanismen, leicht zu verwechseln. Kulturen, Notfallzulassungen und Bienenschutz-Gefahrencodes werden in die IndexedDB synchronisiert und von dort gelesen, mit einer Altersprüfung beim Start statt einer Abfrage je Suche — deshalb funktioniert die Kultur-Autovervollständigung ohne Empfang. Mittelsuche und Indikationen sind live und fallen offline aus.

Kartenkacheln umgehen den Service Worker

Jede Kachel-URL trägt einen konstanten ngsw-bypass-Parameter, Kacheln laufen also gar nicht über den Service Worker, und fehlgeschlagene Ladevorgänge werden über den Wiedereinstiegspunkt von OpenLayers wiederholt statt über die Cache-Schicht. Gut zu wissen, wenn Sie untersuchen, warum sich Kacheln anders verhalten als jede andere Anfrage.

Installation und Erkennung

Die App ist als PWA installierbar und erkennt den Standalone-Modus. Die Installierbarkeit unterscheidet sich je Plattform auf eine Weise, die eher eine Support- als eine Codefrage ist — die Anwenderdokumentation führt auf, welche Browser und Betriebssysteme sie erlauben.

Wo das Risiko tatsächlich liegt

Es gibt keinen Server, keine Sitzung und keine Mandantenfähigkeit, damit entfällt die übliche Web-Angriffsfläche zum größten Teil. Was bleibt: die App verarbeitet Dateien, die ihr die Nutzerin übergibt — JSON, CSV, XML, ZIP — aus Quellen, für die sie nicht bürgen kann. Um diese Grenze herum ist die Härtung gebaut.

Härtung beim Import

  • ZIP: Positivliste für Eintragsnamen, Größen- und Anzahlgrenzen, Obergrenze für die entpackte Größe je Eintrag. Vollständige Backup-Archive weist der Datensatz-Import strukturell ab, bevor ein einziger Eintrag geparst wird.
  • XML: <!DOCTYPE> wird rundweg abgelehnt, dazu eine Obergrenze von 2 MB.
  • Prototype Pollution: jede Iteration über nicht vertrauenswürdige Schlüssel ist abgesichert. Das wiegt hier schwerer als sonst, weil das Entflachen von Punktpfaden schon konstruktionsbedingt über angreiferseitig gelieferte Schlüsselpfade läuft.
  • Backup-Wiederherstellung: Datensätze werden so wiederhergestellt, wie sie gespeichert waren (übersprungen werden nur Einträge, die keine Objekte sind), und durchlaufen bei jedem Lesen den Sanitizer; Vorlagen werden gegen ihre Form, Profile über eine Feld-Positivliste geprüft. Abgewiesenes wird gezählt und gemeldet statt still verworfen.

Härtung beim Export

CSV-Injection wird beim Export entschärft: ein formelartiger Wert wird so maskiert, dass er beim Öffnen in einer Tabellenkalkulation nicht ausgeführt wird. Im Arbeitsmappen-Pfad bleiben formelartige Werte dennoch wortgetreu erhalten, damit der Rundlauf keine Daten beschädigt.

Content-Security-Policy

Die CSP verankert die unter „Externe APIs“ genannten Origins. Sie steht im Meta-Tag der index.html und im Antwort-Header des ausliefernden Servers — beide werden getrennt durchgesetzt und müssen übereinstimmen; frame-ancestors gibt es nur im Header, weil eine Meta-CSP das nicht ausdrücken kann. Daneben: X-Frame-Options, nosniff, eine Referrer-Policy und ein Path-Traversal-Schutz im statischen Server.

Einwilligung vor Speicherung

Der Router-Outlet rendert erst nach erteilter Speichereinwilligung, es wird also nichts geschrieben, bevor zugestimmt wurde. Wer Tests schreibt, die die Einwilligung direkt in die IndexedDB setzen, muss danach neu laden — die App liest die Einwilligung nicht reaktiv, und das Auslassen dieses Neuladens hat schon ganze Suiten zerlegt.

Wo CSP und visuelle Tests auseinandergehen

Eine Falle sei benannt: eine per CSP blockierte Ressource rendert gleichbleibend kaputt, ein visueller Schnappschuss davon passt also weiterhin zu einer gleichbleibend kaputten Referenz. Ein neuer externer Origin muss in einem ausgelieferten Build geprüft werden; grüne End-to-End-Tests belegen nicht, dass er funktioniert.

Übersetzung

Drei Sprachen — de (Standard), en und pl — bei vollständiger Schlüsselparität, mit Punktnotation und {param}-Interpolation. Lokalisierte Formatierung umfasst Datum, Uhrzeit und erzeugte Dateinamen. Die Spracheinstellung liegt in der IndexedDB und ist von der Gerätesprache unabhängig.

Zwei Regeln, die den Code prägen

  1. Keine rohen Zeichenketten in der Oberfläche. Selbst Fehlermeldungen erscheinen als übersetzte Schlüssel; das Detail geht stattdessen in den Log-Store.
  2. translate() gibt bei einem Fehltreffer den Schlüssel zurück, nie einen leeren Wert. Eine fehlende Übersetzung zeigt sich also als sichtbarer Schlüssel statt als leeres Element — Absicht, denn eine leere Beschriftung übersieht man in der Durchsicht viel leichter.

Barrierefreiheit

Ziel ist WCAG 2.2, abgesichert aus drei Richtungen: ESLint-Regeln für Barrierefreiheit auf Templates, axe-core-Durchläufe end-to-end in beiden Themes und ein Tastatur-Durchlauf. Screenreader-Ansagen laufen über zwei ARIA-Live-Regionen, eine höfliche und eine bestimmte, verwaltet von einem einzigen Dienst. Routenwechsel, Theme-, Sprach- und Schriftgrößenwechsel sowie erscheinende Dialoge werden angesagt.

Themes und Skalierung

Zwei Themes, jkiLight und jkiDark, über data-theme gesetzt und gespeichert. Die Schriftskalierung beträgt 100, 150 oder 200 Prozent, angewandt auf die Wurzel-Schriftgröße, ebenfalls gespeichert. Wer eine Komponente ergänzt, muss sie bei 200 Prozent in beiden Themes tragfähig halten — an dieser Kombination bricht das Layout zuerst.

Die Stufen

  • Lint — Stil und Barrierefreiheitsregeln auf Templates.
  • Typprüfung — TypeScript in .ts-Dateien. Nicht in Templates.
  • Invarianten — ein dateiübergreifendes Konsistenzskript: das DB_VERSION-Tripel, das CSP-Paar aus Meta und Header, die Data Groups des Service Workers, die Geo-Grenzen in TypeScript gegen das Schema, die Maximallänge von notizen, der Gleichstand des generierten Schema-Validators, additionalProperties: false an jedem Objekt, i18n-Parität und verwaiste Schlüssel sowie eine Mindestwartezeit für neue pnpm-Pakete.
  • Unit — über 3.400 Karma/Jasmine-Tests, etwa 92 % Statement- und 85 % Branch-Abdeckung. Ein Schwellwert ist nicht konfiguriert — das ist also eine Messung, keine Schranke.
  • Build (AOT) — die einzige Stufe, die eine veraltete Template-Bindung abfängt.
  • End-to-End — echte Abläufe plus visuelle Schnappschüsse über Desktop, mobiles Chrome und mobiles Safari.
  • Barrierefreiheit — axe-core in beiden Themes plus ein Tastatur-Durchlauf.
  • Serversicherheit — Abweisung von Path Traversal und die Sicherheits-Header.

Wo ein grüner Lauf lügt

Wert, verinnerlicht zu werden, bevor Sie einer bestandenen Pipeline vertrauen:

  1. Eine grüne Typprüfung heißt nicht, dass eine Umbenennung angekommen ist — Templates werden erst beim AOT-Build geprüft.
  2. Vom Compiler stillgelegte Fixtures (as unknown as-Casts auf Datensatzformen) laufen nach einer Feldänderung gegen ein veraltetes Schema weiter durch.
  3. Eine Spy-Liste ohne eine neu ergänzte Methode liefert undefined und erzeugt ein irreführendes „nie aufgerufen“.
  4. Eine per CSP blockierte Ressource passt weiterhin zu ihrer kaputten Referenz; visuelle Tests belegen also nicht, dass ein neuer Origin funktioniert.

Schnappschuss-Politik

Visuelle Referenzbilder werden von Menschen aktualisiert, nie automatisch und nie von der CI. Die Abweichung ist das Prüfsignal; sie bei einem Fehlschlag neu zu erzeugen wirft genau das weg, was der Test gemessen hat.

Sie suchen ein bestimmtes Feld? Zur Feldreferenz des Datensatzes

Direkt starten

DiPAgE direkt im Browser nutzen. Ohne Anmeldung und kostenlos.

Öffnen Sie die Anwendung und beginnen Sie direkt mit der Dokumentation Ihrer Pflanzenschutzmittelanwendungen. Eine Installation ist nicht erforderlich, auf unterstützten Geräten kann DiPAgE dennoch zusätzlich installiert und offline genutzt werden.

Direkt im Browser
Keine Installation erforderlich. Anwendung öffnen und direkt beginnen.
Keine Anmeldung
DiPAgE kann ohne Benutzerkonto oder Registrierung genutzt werden.
Daten lokal gespeichert
Ihre Dokumentationsdaten verbleiben auf dem verwendeten Gerät.
Offline nutzbar
Auf unterstützten Geräten kann DiPAgE installiert und ohne Internetverbindung verwendet werden.