Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2e46a623fb | ||
|
|
489d44d18d |
+2
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@govoplan/ops-webui",
|
||||
"version": "0.1.21",
|
||||
"version": "0.1.22",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"main": "webui/src/index.ts",
|
||||
@@ -17,7 +17,7 @@
|
||||
"README.md"
|
||||
],
|
||||
"peerDependencies": {
|
||||
"@govoplan/core-webui": "^0.1.18",
|
||||
"@govoplan/core-webui": "^0.1.45",
|
||||
"lucide-react": "^1.23.0",
|
||||
"react": ">=19.2.7 <20",
|
||||
"react-dom": ">=19.2.7 <20",
|
||||
|
||||
+2
-2
@@ -4,13 +4,13 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "govoplan-ops"
|
||||
version = "0.1.21"
|
||||
version = "0.1.22"
|
||||
description = "GovOPlaN operations module for health, deployment profile, and sizing visibility."
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
authors = [{ name = "GovOPlaN" }]
|
||||
dependencies = [
|
||||
"govoplan-core>=0.1.42",
|
||||
"govoplan-core>=0.1.45",
|
||||
"govoplan-access>=0.1.18",
|
||||
]
|
||||
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
__all__ = ["__version__"]
|
||||
|
||||
__version__ = "0.1.21"
|
||||
__version__ = "0.1.22"
|
||||
|
||||
@@ -100,7 +100,7 @@ def _route_factory(context: ModuleContext):
|
||||
manifest = ModuleManifest(
|
||||
id="ops",
|
||||
name="Ops",
|
||||
version="0.1.21",
|
||||
version="0.1.22",
|
||||
required_capabilities=(
|
||||
CAPABILITY_AUTH_PRINCIPAL_RESOLVER,
|
||||
CAPABILITY_AUTH_PERMISSION_EVALUATOR,
|
||||
@@ -152,7 +152,10 @@ manifest = ModuleManifest(
|
||||
id="ops.health-governance-and-sizing",
|
||||
title="Inspect platform health and deployment posture",
|
||||
summary="Ops combines module-owned health checks with deployment profile, governance inventory, worker assumptions, and sizing guidance.",
|
||||
body="Read-only status distinguishes configured capabilities from healthy integrations. Worker and queue providers use a Core runtime-status contract, so Ops never imports a provider backend. The surface distinguishes intentionally disabled, unconfigured, starting, healthy with unsupported queue depth, measured idle, busy, degraded, stale, and unreachable states. It shows enabled/configured state, backend, workers, heartbeat age and stale threshold, queue depth, active/reserved work, and failures only when each value is actually reported; unavailable values are never rendered as zero or healthy. Local development treats intentionally disabled workers as expected, while production profiles require an enabled, configured, reachable provider before queue-backed work is accepted. Polling is bounded to one request, pauses while the page is hidden, and refreshes on return. When the deployment mounts a signed or locally generated non-secret infrastructure capability receipt, Ops shows whether PostgreSQL, Redis, SMTP, file storage, load balancing, and ingress are configured, externally supplied, available but unconfigured, or unavailable. Secret values never cross this boundary; only stable environment or credential-envelope references may be disclosed. Pending post-install tasks remain visible with a stable resume key. The separately authorized infrastructure-dependency endpoint asks enabled module providers for their current persisted configuration and data dependencies. Each provider returns only stable references, states, scopes, numeric metrics, and required migration actions; one failed provider marks the entire fresh inventory incomplete so the host deployer blocks a capability change. Authorized operators can run bounded probes; a probe must not perform unbounded business work or silently repair data. Use readiness and worker results when diagnosing a node, and use the deployment profile and sizing assumptions when planning horizontal capacity.",
|
||||
body="Documentation books sit immediately beside the visible heading or contextual label for Ops "
|
||||
"and health information, not among operational action buttons. Field help remains beside its "
|
||||
"label. "
|
||||
"Read-only status distinguishes configured capabilities from healthy integrations. Worker and queue providers use a Core runtime-status contract, so Ops never imports a provider backend. The surface distinguishes intentionally disabled, unconfigured, starting, healthy with unsupported queue depth, measured idle, busy, degraded, stale, and unreachable states. It shows enabled/configured state, backend, workers, heartbeat age and stale threshold, queue depth, active/reserved work, and failures only when each value is actually reported; unavailable values are never rendered as zero or healthy. Local development treats intentionally disabled workers as expected, while production profiles require an enabled, configured, reachable provider before queue-backed work is accepted. Polling is bounded to one request, pauses while the page is hidden, and refreshes on return. When the deployment mounts a signed or locally generated non-secret infrastructure capability receipt, Ops shows whether PostgreSQL, Redis, SMTP, file storage, load balancing, and ingress are configured, externally supplied, available but unconfigured, or unavailable. Secret values never cross this boundary; only stable environment or credential-envelope references may be disclosed. Pending post-install tasks remain visible with a stable resume key. The separately authorized infrastructure-dependency endpoint asks enabled module providers for their current persisted configuration and data dependencies. Each provider returns only stable references, states, scopes, numeric metrics, and required migration actions; one failed provider marks the entire fresh inventory incomplete so the host deployer blocks a capability change. Authorized operators can run bounded probes; a probe must not perform unbounded business work or silently repair data. Use readiness and worker results when diagnosing a node, and use the deployment profile and sizing assumptions when planning horizontal capacity.",
|
||||
documentation_types=("admin", "user"),
|
||||
audience=("operator", "system_admin"),
|
||||
related_modules=("audit", "docs", "notifications"),
|
||||
@@ -173,6 +176,9 @@ manifest = ModuleManifest(
|
||||
"title": "Plattformzustand und Bereitstellungsprofil prüfen",
|
||||
"summary": "Ops führt modulbezogene Zustandsprüfungen mit Bereitstellungsprofil, Governance-Inventar, Worker-Annahmen und Dimensionierungshinweisen zusammen.",
|
||||
"body": (
|
||||
"Dokumentationsbücher stehen unmittelbar neben der sichtbaren Überschrift oder "
|
||||
"Kontextbezeichnung für Betriebs- und Zustandsinformationen, nicht zwischen ausführbaren "
|
||||
"Aktionsschaltflächen. Feldhilfe bleibt neben der Feldbezeichnung. "
|
||||
"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. "
|
||||
@@ -209,7 +215,7 @@ manifest = ModuleManifest(
|
||||
DocumentationTopic(
|
||||
id="ops.runtime-coordination-and-recovery",
|
||||
title="Drain runtime nodes and inspect recovery evidence",
|
||||
summary="Ops projects shared runtime heartbeats, replica gaps, drain controls, and recovery states that require operator attention.",
|
||||
summary="Ops projects shared runtime heartbeats, replica gaps, drain controls, and recovery states that require operator attention. Node controls remain pinned at the right edge of horizontally scrolled runtime tables.",
|
||||
body="Use the runtime table to identify stale or composition-skewed API and worker replicas. Drain before replacement so API readiness closes and workers stop taking new queue work; cancellation is available while the node is still draining. The recovery table reports durable Core recovery operations. A rejected operation is a verified provider rejection and needs no recovery; outcome-unknown and recovery-required operations still require reconciliation through the owning module. Core module-lifecycle entries block every later install or live graph change: use the installer run id to verify package, backup, migration, and health evidence before rollback or forward repair. Mail SMTP and IMAP APPEND entries use stable attempt identifiers and digest-only evidence: reconcile the Mail command from provider evidence, never by replaying the original effect from Ops. Files blob writes, hard purge, reference-checked garbage collection, and conditional S3 connector writes record Core recovery evidence. For a Files connector outcome, inspect the provider request/content markers and revision before allowing another write to the fenced path; for blob GC, recheck FileVersion references and exact object absence. Development SQLite can show only handled-rollback reconstruction for caller-transaction blob uploads; after a hard SQLite process loss, run the owning Files integrity scan because an orphan may have no Ops ledger row. Dataflow database-only runs are atomic, while published-output runs use forward recovery: reconcile the recorded output digest and sink idempotency key before allowing another publication. Backup status separately projects only the sanitized deployment verification receipt: a verified status identifies a coordinated recovery point and isolated restore drill, while absent, expired, or invalid evidence blocks a release-changing migration.",
|
||||
documentation_types=("admin", "user"),
|
||||
audience=("operator", "system_admin"),
|
||||
@@ -223,7 +229,7 @@ manifest = ModuleManifest(
|
||||
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.",
|
||||
"summary": "Ops projiziert gemeinsame Laufzeit-Heartbeats, Replikatlücken, Leerungssteuerung und Wiederherstellungszustände, die betriebliche Aufmerksamkeit erfordern. Die Knotensteuerung bleibt am rechten Rand horizontal gescrollter Laufzeittabellen angeheftet.",
|
||||
"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. "
|
||||
|
||||
@@ -76,7 +76,9 @@ class OpsInterfaceDocumentationContractTests(unittest.TestCase):
|
||||
"TableActionGroup",
|
||||
):
|
||||
self.assertIn(component, page)
|
||||
self.assertIn("DocumentationHelpLink", widget)
|
||||
contribution = (REPO_ROOT / "webui/src/module.ts").read_text(encoding="utf-8")
|
||||
self.assertIn("documentation: OPS_DOCUMENTATION", contribution)
|
||||
self.assertNotIn("DocumentationHelpLink", widget)
|
||||
self.assertIn("LoadingFrame", widget)
|
||||
|
||||
|
||||
|
||||
+3
-2
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@govoplan/ops-webui",
|
||||
"version": "0.1.21",
|
||||
"version": "0.1.22",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"main": "src/index.ts",
|
||||
@@ -13,10 +13,11 @@
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"test:action-layout": "node scripts/test-action-layout.mjs",
|
||||
"test:runtime-status": "rm -rf .runtime-status-test-build && mkdir -p .runtime-status-test-build && printf '{\"type\":\"commonjs\"}\\n' > .runtime-status-test-build/package.json && ../../govoplan-core/webui/node_modules/.bin/tsc -p tsconfig.runtime-status-tests.json && node .runtime-status-test-build/tests/runtime-status.test.js"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@govoplan/core-webui": "^0.1.18",
|
||||
"@govoplan/core-webui": "^0.1.45",
|
||||
"lucide-react": "^1.23.0",
|
||||
"react": ">=19.2.7 <20",
|
||||
"react-dom": ">=19.2.7 <20",
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { readFileSync } from "node:fs";
|
||||
|
||||
const page = readFileSync(new URL("../src/features/ops/OpsPage.tsx", import.meta.url), "utf8");
|
||||
assert.match(page, /id: "actions",\s*header: "",\s*width: 72,\s*sticky: "end",\s*resizable: false,\s*align: "right"/);
|
||||
assert.match(page, /<TableActionGroup\s*minimumSlots=\{1\}/);
|
||||
console.log("Runtime node controls use the shared pinned action layout.");
|
||||
@@ -3,7 +3,6 @@ import { MetricGrid } from "@govoplan/core-webui";
|
||||
import { useEffect, useState } from "react";
|
||||
import {
|
||||
DismissibleAlert,
|
||||
DocumentationHelpLink,
|
||||
LoadingFrame,
|
||||
MetricCard,
|
||||
StatusBadge,
|
||||
@@ -11,7 +10,6 @@ import {
|
||||
type ApiSettings
|
||||
} from "@govoplan/core-webui";
|
||||
import { fetchOpsStatus, type OpsStatus } from "../../api/ops";
|
||||
import { OPS_DOCUMENTATION } from "./interfacePatterns";
|
||||
import { knownMetric, knownQueueDepthTotal, runtimeWorkTone } from "./runtimeStatus";
|
||||
|
||||
export default function OpsHealthWidget({ settings, refreshKey }: { settings: ApiSettings; refreshKey: number }) {
|
||||
@@ -42,9 +40,6 @@ export default function OpsHealthWidget({ settings, refreshKey }: { settings: Ap
|
||||
return (
|
||||
<LoadingFrame loading={loading} label="Loading operations status">
|
||||
{error && <DismissibleAlert tone="warning" resetKey={error}>{error}</DismissibleAlert>}
|
||||
<div className="button-row compact-actions">
|
||||
<DocumentationHelpLink reference={OPS_DOCUMENTATION} />
|
||||
</div>
|
||||
<MetricGrid columns={3} spacing="none">
|
||||
<MetricCard label="Readiness" value={ready ? "ready" : "blocked"} tone={ready ? "good" : "danger"} detail={status?.readiness.profile ?? "-"} />
|
||||
<MetricCard label="Workers" value={knownMetric(workerMetrics?.workers)} tone={runtimeWorkTone(workerMetrics?.state ?? "unreachable")} detail={workerMetrics?.state ?? "unavailable"} />
|
||||
|
||||
@@ -173,14 +173,14 @@ export default function OpsPage({ settings, auth }: {settings: ApiSettings;auth:
|
||||
return (
|
||||
<PageLayout
|
||||
archetype="overview"
|
||||
title="i18n:govoplan-ops.ops.907a54c2"
|
||||
title="i18n:govoplan-ops.ops.907a54c2" titleHelp={<DocumentationHelpLink reference={OPS_DOCUMENTATION} />}
|
||||
description="i18n:govoplan-ops.runtime_health_deployment_profile_worker_split_a.55340156"
|
||||
error={error}
|
||||
actions={<PageActionBar
|
||||
variant="overview"
|
||||
refreshable
|
||||
reloadAction={{ onReload: () => void load(), loading, disabledReason: loading ? OPS_I18N.loading : undefined }}
|
||||
helpAction={<DocumentationHelpLink reference={OPS_DOCUMENTATION} />}
|
||||
|
||||
primaryActions={<Button variant="primary" onClick={() => void runChecks()} disabled={Boolean(runProbesDisabledReason)} disabledReason={runProbesDisabledReason}>i18n:govoplan-ops.surface.run_probes</Button>}
|
||||
/>}
|
||||
>
|
||||
@@ -399,7 +399,10 @@ function RuntimeNodeTable({
|
||||
{
|
||||
id: "actions",
|
||||
header: "",
|
||||
width: 56,
|
||||
width: 72,
|
||||
sticky: "end",
|
||||
resizable: false,
|
||||
align: "right",
|
||||
value: (node) => node.state,
|
||||
render: (node) => {
|
||||
const busy = busyNodeId === node.node_id;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { createElement, lazy } from "react";
|
||||
import type { DashboardWidgetsUiCapability, PlatformWebModule } from "@govoplan/core-webui";
|
||||
import OpsHealthWidget from "./features/ops/OpsHealthWidget";
|
||||
import { OPS_DOCUMENTATION } from "./features/ops/interfacePatterns";
|
||||
import { generatedTranslations } from "./i18n/generatedTranslations";
|
||||
|
||||
const OpsPage = lazy(() => import("./features/ops/OpsPage"));
|
||||
@@ -16,6 +17,7 @@ const dashboardWidgets: DashboardWidgetsUiCapability = {
|
||||
id: "ops.health",
|
||||
surfaceId: "ops.widget.health",
|
||||
title: "Operations health",
|
||||
documentation: OPS_DOCUMENTATION,
|
||||
description: "Readiness, worker mode, and current warning count.",
|
||||
moduleId: "ops",
|
||||
category: "Operations",
|
||||
|
||||
Reference in New Issue
Block a user