diff --git a/package.json b/package.json index 460b48b..27300a8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@govoplan/encryption", - "version": "0.1.18", + "version": "0.1.19", "private": true, "description": "GovOPlaN encryption platform module scaffold.", "type": "module", diff --git a/pyproject.toml b/pyproject.toml index b3a164e..f985f0a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "govoplan-encryption" -version = "0.1.18" +version = "0.1.19" description = "Optional key-vault and content-protection capabilities for GovOPlaN." readme = "README.md" requires-python = ">=3.12" diff --git a/src/govoplan_encryption/backend/manifest.py b/src/govoplan_encryption/backend/manifest.py index 661fbc2..41d1c4c 100644 --- a/src/govoplan_encryption/backend/manifest.py +++ b/src/govoplan_encryption/backend/manifest.py @@ -17,6 +17,7 @@ from govoplan_core.core.module_guards import ( ) from govoplan_core.core.modules import ( CapabilityDocumentation, + DocumentationCondition, DocumentationLink, DocumentationTopic, FrontendModule, @@ -45,7 +46,7 @@ from govoplan_encryption.backend.service import SqlEncryptionService MODULE_ID = "encryption" MODULE_NAME = "Encryption" -MODULE_VERSION = "0.1.18" +MODULE_VERSION = "0.1.19" USE_SCOPE = "encryption:vault:use" ADMIN_SCOPE = "encryption:vault:admin" @@ -367,6 +368,7 @@ manifest = ModuleManifest( related_modules=("core", "identity_trust", "audit", "policy"), order=95, metadata={ + "kind": "reference", "help_contexts": [ "encryption.admin.operations", "privacy.data-subject-requests", @@ -383,6 +385,35 @@ manifest = ModuleManifest( ), }, }, + translations={ + "de": { + "title": "Datenschutzanfragen zur Verschlüsselung", + "summary": ( + "Mitwirkung an kryptografischer Verwahrung ausgeben, ohne geschützte Inhalte oder Schlüsselmaterial offenzulegen." + ), + "body": ( + "Encryption gleicht ausschließlich eine exakte Mandantenkontokennung ab und kann eine bereits verifizierte " + "Suche auf einen Tresor, Schlüsselvorgang, Umschlag, eine Migration oder Wiederherstellungszeremonie " + "einschränken. Die Ausgabe meldet minimierte Tresoradministration, Schlüsselvorgangsanfragen, " + "Schutzregistrierungen, Migrationen und Wiederherstellungsmitwirkung. Sie enthält niemals Anbieter- oder " + "öffentliche Schlüsselverweise, umhüllte Schlüssel, Nonces, Chiffratorte, Ressourcenkennungen, Prüfsummen, " + "Anfrageinhalte, Zusicherungs- und Regelverweise, Wiederherstellungsgründe, Idempotenzschlüssel oder Provenienz. " + "Fachmodule bleiben für die Ausgabe der Klartextsemantik ihrer geschützten Ressourcen verantwortlich. " + "Zuordnungen des kryptografischen Lebenszyklus und der Verwahrung bleiben unveränderliche Sicherheitsnachweise " + "und werden nicht automatisch gelöscht." + ), + } + }, + structured_translation_version="1", + structured_translations={ + "de": { + "consequence_classes": { + "export_custody_attribution": "Gibt minimierte Lebenszyklusaktivität für das exakte Konto zurück.", + "exclude_cryptographic_secrets": "Gibt niemals Schlüsselmaterial, Chiffratverweise, Nonces oder geschützte Nachweise zurück.", + "retain_cryptographic_evidence": "Bewahrt unveränderliche Verantwortungsnachweise zu Verwahrung und Wiederherstellung.", + } + } + }, ), DocumentationTopic( id="encryption.boundary", @@ -419,6 +450,23 @@ manifest = ModuleManifest( kind="repository", ), ), + metadata={"kind": "reference"}, + translations={ + "de": { + "title": "Abgrenzung von Verschlüsselung und Schlüsselverwahrung", + "summary": ( + "Optionale Fähigkeiten für Tresore, Inhaltsschutz, Rotation, Wiederherstellung und Deaktivierungsnachweise." + ), + "body": ( + "Encryption schützt fachmoduleigene Inhalte, ohne deren fachliche Eigentümerschaft zu übernehmen. Die " + "Wiederherstellung von Ressourceneigentum gewährt niemals stillschweigend kryptografische Schlüssel. " + "Lebenszyklusaktionen mit hohem Risiko erfordern eine aktuelle Identity-Trust-Zusicherung. Die Deaktivierung " + "bleibt gesperrt, bis jeder Umschlag migriert, entschlüsselt, ausdrücklich exportiert oder kryptografisch " + "vernichtet wurde. Der mitgelieferte lokale AES-GCM-Anbieter ist serverseitig lesbar und erfordert den " + "Deployment-Hauptschlüssel; er begründet keine Ende-zu-Ende-Verschlüsselung." + ), + } + }, ), DocumentationTopic( id="encryption.administration", @@ -442,6 +490,23 @@ manifest = ModuleManifest( audience=("administrator", "security_officer", "auditor"), related_modules=OPTIONAL_DEPENDENCIES, order=110, + metadata={"kind": "reference"}, + translations={ + "de": { + "title": "Verschlüsselungsvorgänge administrieren", + "summary": ( + "Sichere Tresor- und Umschlagmetadaten prüfen, den Schlüssellebenszyklus steuern, Migrationen koordinieren und Deaktivierungsbereitschaft nachweisen." + ), + "body": ( + "Die Encryption-Administration zeigt begrenzte Mandantenmetadaten, aber niemals Anbieterschlüsselverweise, " + "umhüllte Schlüssel, Chiffratorte oder Klartext. Rotation erzeugt eine neue aktuelle Version, während " + "bestehende Umschläge an ihre Version gebunden bleiben. Widerruf und Vernichtung können bereits erlangtes " + "Material nicht zurückrufen und Inhalte unzugänglich machen. Migrationen bleiben zweiphasig: Das " + "Eigentümermodul führt den dauerhaften Inhaltsvorgang aus und hält vor Erfolg Nachweise fest. Die " + "Deaktivierungsvorprüfung sperrt, bis jeder Umschlag einen endgültigen Verbleib hat." + ), + } + }, ), DocumentationTopic( id="encryption.recovery", @@ -461,8 +526,27 @@ manifest = ModuleManifest( layer="available", documentation_types=("admin", "user"), audience=("administrator", "security_officer", "auditor"), + conditions=( + DocumentationCondition(required_scopes=(RECOVERY_SCOPE,)), + ), related_modules=("identity_trust", "access", "audit", "policy"), order=120, + metadata={"kind": "workflow"}, + translations={ + "de": { + "title": "Wiederherstellungszeremonie für Verschlüsselung durchführen", + "summary": ( + "Zeitlich begrenzte Wiederherstellung mit hoher Zusicherung und Quorum unterschiedlicher Verwahrender beantragen und entscheiden." + ), + "body": ( + "Die antragstellende Person legt Regel und aktuellen Nachweis hoher Zusicherung vor und darf dieselbe " + "Zeremonie nicht genehmigen. Jede verwahrende Person kann genau einmal entscheiden; eine Ablehnung beendet " + "den Antrag und Genehmigungen müssen das Tresorquorum vor Ablauf erreichen. Die Genehmigung autorisiert einen " + "späteren Anbietervorgang. Sie gibt kein Schlüsselmaterial frei, überträgt kein Ressourceneigentum und beweist " + "nicht, dass die Wiederherstellung erfolgreich ausgeführt wurde." + ), + } + }, ), ), architecture=declared_module_architecture( diff --git a/tests/test_documentation.py b/tests/test_documentation.py new file mode 100644 index 0000000..08410b7 --- /dev/null +++ b/tests/test_documentation.py @@ -0,0 +1,34 @@ +from __future__ import annotations + +import unittest + +from govoplan_core.core.modules import ( + documentation_structured_translation_issues, + localizable_documentation_metadata_keys, +) +from govoplan_encryption.backend.manifest import get_manifest + + +class EncryptionDocumentationTests(unittest.TestCase): + def test_german_reference_documentation_is_complete(self) -> None: + topics = get_manifest().documentation + self.assertEqual(4, len(topics)) + for topic in topics: + translation = topic.translations.get("de", {}) + self.assertTrue(translation.get("title"), topic.id) + self.assertTrue(translation.get("summary"), topic.id) + self.assertTrue(translation.get("body"), topic.id) + if localizable_documentation_metadata_keys(topic): + self.assertEqual("1", topic.structured_translation_version, topic.id) + self.assertIn("de", topic.structured_translations, topic.id) + self.assertEqual((), documentation_structured_translation_issues(topic)) + + kinds = {topic.metadata.get("kind") for topic in topics} + self.assertIn("workflow", kinds) + self.assertIn("reference", kinds) + workflow = next(topic for topic in topics if topic.metadata.get("kind") == "workflow") + self.assertTrue(workflow.conditions) + + +if __name__ == "__main__": + unittest.main() diff --git a/webui/package.json b/webui/package.json index 80dc17d..2168815 100644 --- a/webui/package.json +++ b/webui/package.json @@ -1,6 +1,6 @@ { "name": "@govoplan/encryption-webui", - "version": "0.1.18", + "version": "0.1.19", "private": true, "type": "module", "main": "src/index.ts",