From 3458306e04097870a94d4e1565d06ddaec8ee96d Mon Sep 17 00:00:00 2001 From: Albrecht Degering Date: Sun, 23 Aug 2026 20:11:47 +0200 Subject: [PATCH] docs(addresses): complete German reference coverage --- package.json | 2 +- pyproject.toml | 2 +- src/govoplan_addresses/backend/manifest.py | 161 +++++++++++++++++- .../test_interface_documentation_contract.py | 17 +- webui/package.json | 2 +- 5 files changed, 179 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 2c9d0d3..f895ae6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@govoplan/addresses-webui", - "version": "0.1.18", + "version": "0.1.19", "private": true, "type": "module", "main": "webui/src/index.ts", diff --git a/pyproject.toml b/pyproject.toml index 90ac56f..9b3dcd5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "govoplan-addresses" -version = "0.1.18" +version = "0.1.19" description = "GovOPlaN reusable address and recipient-source module." readme = "README.md" requires-python = ">=3.12" diff --git a/src/govoplan_addresses/backend/manifest.py b/src/govoplan_addresses/backend/manifest.py index b47d1cc..38df03e 100644 --- a/src/govoplan_addresses/backend/manifest.py +++ b/src/govoplan_addresses/backend/manifest.py @@ -26,6 +26,7 @@ from govoplan_core.core.people import CAPABILITY_ADDRESSES_PEOPLE_SEARCH from govoplan_core.core.distribution_lists import CAPABILITY_RECIPIENT_CHANNEL_FACTS from govoplan_core.core.modules import ( CapabilityDocumentation, + DocumentationCondition, DocumentationTopic, FrontendModule, FrontendRoute, @@ -434,7 +435,7 @@ LDAP_PROVIDER = ExternalProviderDeclaration( manifest = ModuleManifest( id="addresses", name="Addresses", - version="0.1.18", + version="0.1.19", required_capabilities=( CAPABILITY_AUTH_PRINCIPAL_RESOLVER, CAPABILITY_AUTH_PERMISSION_EVALUATOR, @@ -673,6 +674,29 @@ manifest = ModuleManifest( "records", ), order=29, + translations={ + "de": { + "title": "Addresses-Daten in einer Betroffenenanfrage prüfen", + "summary": ( + "Mandantenbezogene Kontaktdaten erfassen und dabei gemeinsame Adress-, Empfänger-, Synchronisations- und " + "Herkunftsnachweise bewahren." + ), + "body": ( + "Addresses durchsucht bestätigte E-Mail- und Kontoselektoren sowie namensraumgebundene Kontakt- und " + "Kontaktpunktverweise. Zu einem passenden Kontakt werden begrenzte Identitäts-, E-Mail-, Telefon- und Postwerte " + "einschließlich seiner Adresslistennutzung und minimierter Nachweise zu Governance, Qualität, Herkunft, Zusammenführung, " + "Weiterleitung und Synchronisation exportiert. Kontotreffer ergänzen nur minimierte Zuordnungen von Betriebspersonen zu " + "gesteuerter Konfiguration und Nachweisen. Ausgeschlossen sind rohe importierte oder synchronisierte Quelldaten, " + "Connector-Token und Revisionen mit Zugangsdatencharakter, undurchsichtige Metadaten, Anfrage- und Auflösungsnutzdaten " + "von Snapshots, Importpläne, Vorher-/Nachher-Daten von Zusammenführungen, unbeteiligte Kontakte und andere Mandanten. " + "Nachweise zu Qualität, Governance, Herkunft, Zusammenführung, Weiterleitung, Synchronisation, Import, Snapshot und " + "Betriebszuordnung werden mit ausdrücklicher Begründung aufbewahrt. Weil wiederverwendbare Kontakte geteilt, " + "synchronisiert, zusammengeführt oder von unveränderlichen Empfänger-Snapshots referenziert sein können, löscht der " + "DSAR-Provider sie niemals automatisch. Eine berechtigte Betriebsperson muss Abhängigkeiten prüfen und den regulären " + "Addresses-Ablauf für Korrektur, Archivierung, Quelle, Zusammenführung oder Governance verwenden." + ), + } + }, metadata={ "seed": True, "help_contexts": [ @@ -703,6 +727,20 @@ manifest = ModuleManifest( "postbox", ), order=30, + translations={ + "de": { + "title": "Zuständigkeit für wiederverwendbare Adressen", + "summary": ( + "Wiederverwendbare Personen-, Organisations-, Haushalts-, Post- und E-Mail-Empfängerquellen gehören dem " + "Addresses-Modul." + ), + "body": ( + "Campaigns darf unveränderliche campaignlokale Empfänger-Snapshots halten. Dauerhafte Adressverzeichnisse, " + "Empfängerquellendefinitionen, Einwilligungsmetadaten, Herkunft, Dublettenbereinigung sowie Import- und Exportabläufe " + "gehören jedoch govoplan-addresses." + ), + } + }, metadata={ "seed": True, "help_contexts": [ @@ -729,6 +767,18 @@ manifest = ModuleManifest( audience=("tenant_admin", "operator", "module_admin"), related_modules=("dist_lists", "campaigns", "policy", "templates"), order=31, + translations={ + "de": { + "title": "Kontaktpunktauflösung und Snapshots", + "summary": "Zweckbezogene Kanalziele auflösen und unveränderliche Empfängernachweise einfrieren.", + "body": ( + "Addresses stellt eine versionierte Kontaktpunktfähigkeit für E-Mail-, Post-, Hauspost- und Portalziele bereit. " + "Aufrufende können Wirksamkeitsdatum, Kommunikationszweck, Adresszweck, Rückfallregel, Spracheinstellung und Postformat " + "angeben. Begrenzte Vorschauen bleiben aktuell; eingefrorene Snapshots bewahren aufgelöste Werte, Ausschlüsse, Quellen- " + "und Governance-Revisionen, Herkunft und einen deterministischen Nachweishash auch nach späteren Kontaktänderungen." + ), + } + }, metadata={ "seed": True, "help_contexts": [ @@ -759,8 +809,45 @@ manifest = ModuleManifest( layer="configured", documentation_types=("admin", "user"), audience=("tenant_admin", "module_admin", "power_user"), + conditions=( + DocumentationCondition( + required_modules=("addresses",), + any_scopes=("addresses:contact:write", "addresses:sync:write"), + ), + ), related_modules=("connectors", "datasources", "dataflow", "files", "audit"), order=33, + translations={ + "de": { + "title": "Kontakte aus CSV, XLSX und LDIF importieren", + "summary": ( + "Wiederverwendbare, versionierte Kontaktzuordnungen vorprüfen und anwenden, ohne Zeilen oder Einträge " + "stillschweigend zu verlieren." + ), + "body": ( + "CSV-, XLSX- und LDIF-Dateien lassen sich mit bereichsgebundenen, wiederverwendbaren Profilversionen zuordnen. Jede " + "Vorschau prüft Überschriften oder Attribute, Kodierung, Quellschlüssel, Dubletten, Leerwerte, Formatgrenzen und " + "Kontaktidentität vor jeder Änderung. Der geprüfte Eingabe- und Planhash wird mit zeilenbezogenen Wirkungen und Diagnosen " + "aufbewahrt. Die Anwendung ist idempotent, verwirft seit der Vorschau geänderte Kontakte und zeichnet ausreichende " + "Nachweise für eine gesicherte Rücknahme auf. Ein gespeicherter Lauf kann nach Navigation oder Neuladen über seinen Link " + "erneut geöffnet werden; Vorschau-, Anwendungs-, Rücknahme-, Ablauf- und Nichtverfügbarkeitszustände bleiben eindeutig. " + "Anwendung und Rücknahme übermitteln den geprüften Planhash. Fehlende, abgelaufene, verborgene und mandantenfremde Läufe " + "legen keine Quelldaten offen. XLSX-Formeln, Makros und ältere Arbeitsmappenformate werden niemals ausgeführt oder " + "importiert. Gefaltete LDIF-Zeilen, UTF-8- und Base64-Text, wiederholte Attribute und Kommentare werden verarbeitet; " + "Binär- und URL-Werte werden weder projiziert noch abgerufen. Änderungsdatensätze gelten standardmäßig als abgelehnte " + "Diagnose und dürfen nur über eine ausdrückliche Profilrichtlinie ignoriert oder bei Add-Einträgen als statische Daten " + "behandelt werden." + ), + } + }, + metadata={ + "kind": "workflow", + "help_contexts": [ + "addresses.action.import", + "addresses.contacts", + "addresses.sources", + ], + }, ), DocumentationTopic( id="addresses.vcard-batches", @@ -782,6 +869,26 @@ manifest = ModuleManifest( audience=("tenant_admin", "operator", "module_admin", "power_user"), related_modules=("files", "audit", "connectors"), order=34, + translations={ + "de": { + "title": "vCard-Stapel selektiv importieren und exportieren", + "summary": ( + "Mehrere vCard-Dateien vorprüfen, die Wirkung jeder Karte wählen und deterministische bereichsgebundene Dateien exportieren." + ), + "body": ( + "Eine oder mehrere UTF-8-.vcf-Dateien werden in eine gespeicherte, nicht verändernde Vorschau mit begrenzten Diagnosen, " + "Dublettenhinweisen, Eingabehash, Parser-Version und deterministischem Planhash eingelesen. Betriebspersonen wählen " + "Anlegen, Aktualisieren oder Ignorieren nur dort, wo der geprüfte Plan es erlaubt. Die Anwendung verwirft veraltete " + "Kontaktziele und ist für dieselbe Auswahl idempotent; eine abweichende Wiederholung wird abgelehnt. Ausstehende Läufe " + "lassen sich neu laden oder abbrechen, ohne Kontakte zu verändern. Uploadgröße, Datei- und Kartenanzahl, Zeilenanzahl und " + "Länge entfalteter Zeilen sind begrenzt. Exporte können ein vollständiges Adressbuch, eine Adressliste oder ausgewählte " + "Kontakte umfassen; vCard 3.0 oder 4.0 wird ausdrücklich gewählt und Kontakte werden deterministisch nach Anzeigename und " + "stabiler Kennung sortiert. Export- und Importnachweise speichern Hashes und Anzahlen, während Diagnosen niemals rohe " + "Kontaktdaten offenlegen. Große Vorschauen bleiben gespeichert und geben ihren Stapelausführungsmodus an, sodass eine " + "Laufzeit-Jobfähigkeit sie bei Verfügbarkeit asynchron ausführen kann." + ), + } + }, metadata={ "seed": True, "help_contexts": [ @@ -807,6 +914,22 @@ manifest = ModuleManifest( audience=("tenant_admin", "operator", "module_admin"), related_modules=("connectors", "idm", "access", "policy", "audit"), order=35, + translations={ + "de": { + "title": "LDAP- und Active-Directory-Adressquellen", + "summary": ( + "Maßgebliche Verzeichniskontakte über eine begrenzte, schreibgeschützte Synchronisationsquelle projizieren." + ), + "body": ( + "LDAP-Quellen verwenden LDAPS oder StartTLS und wiederverwendbare Zugangsdatenhüllen. Die Ermittlung findet verfügbare " + "Basis-DNs; anschließend steuert das Quellprofil einen begrenzten seitenweisen Filter und eine ausdrückliche " + "Attributzuordnung. Die Vorschau verändert niemals Kontakte. Ein vollständiger erfolgreicher Lesevorgang darf lokale " + "Projektionen anlegen, aktualisieren oder als entfernt markieren; abgeschnittene oder fehlgeschlagene Lesevorgänge " + "unterdrücken Löschungen aufgrund von Abwesenheit und markieren die Quelle als veraltet. Stabile Quellschlüssel, " + "Revisionen, normalisierte Felder und Herkunft bleiben mit jedem erhaltenen Kontakt verbunden." + ), + } + }, ), DocumentationTopic( id="addresses.quality-and-merge", @@ -826,6 +949,21 @@ manifest = ModuleManifest( audience=("tenant_admin", "operator", "module_admin"), related_modules=("campaigns", "dist_lists", "policy", "audit"), order=32, + translations={ + "de": { + "title": "Kontaktqualität, Dubletten und umkehrbare Zusammenführungen", + "summary": "Adressqualität und Dublettenvorschläge prüfen, ohne Quellnachweise zu verlieren.", + "body": ( + "Addresses bewahrt ursprüngliche und normalisierte Kontaktpunktwerte, zeichnet die Herkunft je Feld auf und überführt " + "ungültige, zurückgesandte, veraltete oder unzustellbare Zustände mit stabilen Grundcodes in die Empfängerauflösung. " + "Dublettenvorschläge sind begrenzt und erklären ihre Übereinstimmungsmerkmale. Eine Betriebsperson kann die zu erhaltenden " + "Werte wählen, Kontaktpunkte zusammenführen und die Zusammenführung später rückgängig machen oder aufteilen, solange der " + "aufgezeichnete Nachweis nach der Zusammenführung noch übereinstimmt. Kontaktweiterleitungen halten gespeicherte Verweise " + "auflösbar, und Mitgliedschaften in Adresslisten werden transaktional repariert. Audit bleibt eine optionale Integration; " + "die Änderungsfolge und Zusammenführungsnachweise von Addresses werden stets aufbewahrt." + ), + } + }, ), DocumentationTopic( id="addresses.reference.fields-and-consequences", @@ -852,7 +990,28 @@ manifest = ModuleManifest( "audit", ), order=36, + translations={ + "de": { + "title": "Adressfelder, Geltungsbereiche und Folgen von Aktionen", + "summary": ( + "Geltungsbereich, Quellenhoheit, Kontaktpunkte, Listenmitgliedschaft sowie Folgen von Archivierung, Synchronisation und " + "Zusammenführung." + ), + "body": ( + "Adressbücher sind einer Person, Gruppe, einem Mandanten oder einem berechtigten Systemkontext zugeordnet. Geerbte und " + "extern maßgebliche Bücher können sichtbar, aber schreibgeschützt bleiben. Kontakte besitzen wiederverwendbare Angaben " + "zu Name, Organisation, elektronischen und telefonischen Kontaktpunkten, Postanschrift, Schlagwörtern, Notizen, Qualität " + "und Herkunft. Adresslisten verweisen auf Kontaktpunkte desselben Buchs und ersetzen keine Distribution Lists. Eine " + "Archivierung entfernt Buch, Liste oder Kontakt aus der gewöhnlichen Auswahl, bewahrt aber gesteuerte Historie und " + "Verweise. CardDAV- und LDAP-Quellen zeigen Richtung, Hoheit, Aktualität, Diagnosen, Konflikte und Verhalten bei " + "veraltetem Zustand. Import und Synchronisation erfordern vor jeder Änderung eine Vorschau. Kontaktzusammenführungen " + "wählen überlebenden Kontakt und Feldherkunft, reparieren Listenverweise transaktional und bewahren Weiterleitungen und " + "Nachweise, sodass eine passende Zusammenführung rückgängig gemacht oder aufgeteilt werden kann." + ), + } + }, metadata={ + "kind": "reference", "seed": True, "help_contexts": [ "addresses.field.book-scope", diff --git a/tests/test_interface_documentation_contract.py b/tests/test_interface_documentation_contract.py index 886161f..99d64e8 100644 --- a/tests/test_interface_documentation_contract.py +++ b/tests/test_interface_documentation_contract.py @@ -6,6 +6,18 @@ from govoplan_addresses.backend.manifest import manifest class AddressesInterfaceDocumentationContractTests(unittest.TestCase): + def test_all_static_topics_have_complete_german_content(self) -> None: + for topic in manifest.documentation: + german = (topic.translations or {}).get("de", {}) + self.assertEqual( + {"title", "summary", "body"}, + set(german), + topic.id, + ) + self.assertTrue( + all(str(value).strip() for value in german.values()), topic.id + ) + def test_route_and_surfaces_remain_declared(self) -> None: frontend = manifest.frontend self.assertIsNotNone(frontend) @@ -29,7 +41,10 @@ class AddressesInterfaceDocumentationContractTests(unittest.TestCase): reference = topics["addresses.reference.fields-and-consequences"] self.assertIn("addresses.state.read-only", boundary.metadata["help_contexts"]) - self.assertIn("addresses.field.communication-purpose", governance.metadata["help_contexts"]) + self.assertIn( + "addresses.field.communication-purpose", + governance.metadata["help_contexts"], + ) self.assertIn("addresses.action.sync", reference.metadata["help_contexts"]) self.assertIn("merge", reference.metadata["consequence_classes"]) self.assertIn("governance_fact", reference.metadata["consequence_classes"]) diff --git a/webui/package.json b/webui/package.json index e8508ae..ed56dfa 100644 --- a/webui/package.json +++ b/webui/package.json @@ -1,6 +1,6 @@ { "name": "@govoplan/addresses-webui", - "version": "0.1.18", + "version": "0.1.19", "private": true, "type": "module", "main": "src/index.ts",