diff --git a/package.json b/package.json index b792ab7..77eecb0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@govoplan/ops-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 de66e17..3b75b0e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "govoplan-ops" -version = "0.1.18" +version = "0.1.19" description = "GovOPlaN operations module for health, deployment profile, and sizing visibility." readme = "README.md" requires-python = ">=3.12" diff --git a/src/govoplan_ops/__init__.py b/src/govoplan_ops/__init__.py index fb97446..c708a18 100644 --- a/src/govoplan_ops/__init__.py +++ b/src/govoplan_ops/__init__.py @@ -2,4 +2,4 @@ __all__ = ["__version__"] -__version__ = "0.1.18" +__version__ = "0.1.19" diff --git a/src/govoplan_ops/backend/manifest.py b/src/govoplan_ops/backend/manifest.py index 89cd055..9990f33 100644 --- a/src/govoplan_ops/backend/manifest.py +++ b/src/govoplan_ops/backend/manifest.py @@ -92,7 +92,7 @@ def _route_factory(context: ModuleContext): manifest = ModuleManifest( id="ops", name="Ops", - version="0.1.18", + version="0.1.19", required_capabilities=( CAPABILITY_AUTH_PRINCIPAL_RESOLVER, CAPABILITY_AUTH_PERMISSION_EVALUATOR, @@ -143,6 +143,24 @@ manifest = ModuleManifest( documentation_types=("admin", "user"), audience=("operator", "system_admin"), related_modules=("audit", "docs", "notifications"), + translations={ + "de": { + "title": "Plattformzustand und Bereitstellungsprofil prüfen", + "summary": "Ops führt modulbezogene Zustandsprüfungen mit Bereitstellungsprofil, Governance-Inventar, Worker-Annahmen und Dimensionierungshinweisen zusammen.", + "body": ( + "Der schreibgeschützte Status unterscheidet konfigurierte Fähigkeiten von funktionsfähigen Integrationen. " + "Worker- und Warteschlangenanbieter verwenden einen Core-Vertrag für den Laufzeitstatus, sodass Ops niemals ein Anbieter-Backend importiert. " + "Die Oberfläche unterscheidet bewusst deaktivierte, nicht konfigurierte, startende, gesunde, untätige, ausgelastete, beeinträchtigte, veraltete und nicht erreichbare Zustände; eine nicht unterstützte Warteschlangentiefe wird ausdrücklich ausgewiesen. " + "Aktivierung, Konfiguration, Backend, Worker, Alter und Grenzwert des Heartbeats, Warteschlangentiefe, aktive oder reservierte Arbeit sowie Fehler werden nur angezeigt, wenn der Anbieter den jeweiligen Wert tatsächlich meldet; fehlende Werte erscheinen niemals als null oder gesund. " + "In der lokalen Entwicklung sind bewusst deaktivierte Worker zulässig, während Produktionsprofile einen aktivierten, konfigurierten und erreichbaren Anbieter verlangen, bevor warteschlangengestützte Arbeit angenommen wird. " + "Die Abfrage bleibt auf eine Anfrage je Intervall begrenzt, pausiert bei ausgeblendeter Seite und wird bei der Rückkehr fortgesetzt. " + "Ist ein signierter oder lokal erzeugter Infrastrukturbeleg ohne Geheimwerte eingebunden, zeigt Ops für PostgreSQL, Redis, SMTP, Dateispeicher, Lastverteilung und Ingress, ob die Fähigkeit konfiguriert, extern bereitgestellt, verfügbar aber nicht konfiguriert oder nicht verfügbar ist. " + "Geheimwerte überschreiten diese Grenze nie; offengelegt werden dürfen nur stabile Umgebungs- oder Credential-Envelope-Referenzen. " + "Ausstehende Aufgaben nach einer Installation bleiben mit einem stabilen Fortsetzungsschlüssel sichtbar. Autorisierte Betriebsverantwortliche dürfen begrenzte Prüfungen ausführen; eine Prüfung darf weder unbegrenzte Facharbeit auslösen noch Daten stillschweigend reparieren. " + "Nutzen Sie Bereitschafts- und Worker-Ergebnisse zur Diagnose eines Knotens sowie Bereitstellungsprofil und Dimensionierungsannahmen zur Planung horizontaler Kapazität." + ), + } + }, metadata={ "kind": "reference", "help_contexts": [ @@ -175,6 +193,23 @@ manifest = ModuleManifest( ), ), related_modules=("audit", "files", "notifications"), + translations={ + "de": { + "title": "Laufzeitknoten leeren und Wiederherstellungsnachweise prüfen", + "summary": "Ops projiziert gemeinsame Laufzeit-Heartbeats, Replikatlücken, Leerungssteuerung und Wiederherstellungszustände, die betriebliche Aufmerksamkeit erfordern.", + "body": ( + "Verwenden Sie die Laufzeittabelle, um veraltete API- und Worker-Replikate oder Replikate mit abweichender Modulzusammensetzung zu erkennen. " + "Leeren Sie einen Knoten vor dem Austausch, damit seine API-Bereitschaft geschlossen wird und Worker keine neue Warteschlangenarbeit annehmen; solange der Knoten noch geleert wird, kann der Vorgang abgebrochen werden. " + "Die Wiederherstellungstabelle zeigt dauerhafte Core-Wiederherstellungsvorgänge. Eine abgelehnte Operation ist eine bestätigte Ablehnung des Anbieters und benötigt keine Wiederherstellung; Vorgänge mit unbekanntem Ergebnis oder erforderlicher Wiederherstellung müssen weiterhin im besitzenden Modul abgeglichen werden. " + "Core-Einträge zum Modullebenszyklus sperren jede spätere Installation oder Änderung des laufenden Modulgraphen: Prüfen Sie anhand der Installer-Lauf-ID Paket-, Sicherungs-, Migrations- und Zustandsnachweise, bevor Sie zurückrollen oder vorwärts reparieren. " + "SMTP- und IMAP-APPEND-Einträge von Mail verwenden stabile Versuchskennungen und ausschließlich Digest-Nachweise; gleichen Sie den Mail-Befehl mit Anbieternachweisen ab und wiederholen Sie niemals die ursprüngliche Wirkung aus Ops. " + "Files erfasst Core-Wiederherstellungsnachweise für Blob-Schreibvorgänge, genehmigte harte Löschung, referenzgeprüfte Speicherbereinigung und bedingte S3-Connector-Schreibvorgänge. Prüfen Sie bei einem Files-Connector-Ergebnis Anbieteranfrage, Inhaltsmerkmale und Revision, bevor ein weiterer Schreibvorgang auf den gesperrten Pfad zugelassen wird; prüfen Sie bei der Blob-Bereinigung erneut FileVersion-Referenzen und die genaue Abwesenheit des Objekts. " + "SQLite für die Entwicklung kann bei Blob-Uploads innerhalb einer aufrufenden Transaktion nur die Rekonstruktion behandelter Rollbacks zeigen; nach einem harten Prozessverlust muss die Files-Integritätsprüfung ausgeführt werden, weil ein verwaistes Objekt ohne Ops-Ledger-Eintrag existieren kann. " + "Reine Datenbankläufe von Dataflow sind atomar, während Läufe mit veröffentlichten Ausgaben vorwärts repariert werden: Gleichen Sie den erfassten Ausgabedigest und den Idempotenzschlüssel des Ziels ab, bevor eine weitere Veröffentlichung erlaubt wird. " + "Der Sicherungsstatus projiziert getrennt nur den bereinigten Bereitstellungsbeleg: Ein verifizierter Status weist einen koordinierten Wiederherstellungspunkt und eine isolierte Wiederherstellungsprobe nach; fehlende, abgelaufene oder ungültige Nachweise sperren eine migrationsbedingte Release-Änderung." + ), + } + }, metadata={ "kind": "workflow", "route": "/ops", diff --git a/tests/test_interface_documentation_contract.py b/tests/test_interface_documentation_contract.py index bc633ee..a1ba1a9 100644 --- a/tests/test_interface_documentation_contract.py +++ b/tests/test_interface_documentation_contract.py @@ -54,6 +54,14 @@ class OpsInterfaceDocumentationContractTests(unittest.TestCase): self.assertIn("cancel_node_drain", recovery.metadata["consequence_classes"]) self.assertIn("inspect_recovery", recovery.metadata["consequence_classes"]) + def test_public_documentation_has_complete_german_baseline(self) -> None: + for topic in get_manifest().documentation: + german = topic.translations.get("de", {}) + self.assertTrue( + all(german.get(field) for field in ("title", "summary", "body")), + topic.id, + ) + def test_webui_uses_shared_operational_patterns(self) -> None: page = (REPO_ROOT / "webui/src/features/ops/OpsPage.tsx").read_text(encoding="utf-8") widget = (REPO_ROOT / "webui/src/features/ops/OpsHealthWidget.tsx").read_text(encoding="utf-8") diff --git a/webui/package.json b/webui/package.json index 96ee268..98f30bc 100644 --- a/webui/package.json +++ b/webui/package.json @@ -1,6 +1,6 @@ { "name": "@govoplan/ops-webui", - "version": "0.1.18", + "version": "0.1.19", "private": true, "type": "module", "main": "src/index.ts",