diff --git a/package.json b/package.json index e2199f5..f46ff84 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@govoplan/admin-webui", - "version": "0.1.6", + "version": "0.1.7", "private": true, "type": "module", "main": "webui/src/index.ts", @@ -18,7 +18,7 @@ "LICENSE" ], "peerDependencies": { - "@govoplan/core-webui": "^0.1.6", + "@govoplan/core-webui": "^0.1.7", "lucide-react": "^1.23.0", "react": "^19.0.0", "react-dom": "^19.0.0", diff --git a/pyproject.toml b/pyproject.toml index fbf0d4d..385b899 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,14 +4,14 @@ build-backend = "setuptools.build_meta" [project] name = "govoplan-admin" -version = "0.1.6" +version = "0.1.7" description = "GovOPlaN generic administration module." readme = "README.md" requires-python = ">=3.12" authors = [{ name = "GovOPlaN" }] dependencies = [ - "govoplan-core>=0.1.6", - "govoplan-access>=0.1.6", + "govoplan-core>=0.1.7", + "govoplan-access>=0.1.7", ] [tool.setuptools.packages.find] diff --git a/src/govoplan_admin/backend/api/v1/routes.py b/src/govoplan_admin/backend/api/v1/routes.py index bae88e3..0819bca 100644 --- a/src/govoplan_admin/backend/api/v1/routes.py +++ b/src/govoplan_admin/backend/api/v1/routes.py @@ -31,6 +31,7 @@ from govoplan_core.core.configuration_control import ( ) from govoplan_core.core.module_management import ( PROTECTED_MODULES, + ModuleInstallPlan, ModuleInstallPlanItem, ModuleManagementError, configured_enabled_modules, @@ -49,6 +50,7 @@ from govoplan_core.core.module_installer import ( default_installer_runtime_dir, list_module_installer_runs, list_module_installer_requests, + module_install_catalog_companion_module_ids, module_installer_daemon_status, module_install_preflight, module_installer_lock_status, @@ -429,17 +431,27 @@ def _webui_root() -> Path | None: def _upsert_install_plan_item(session: Session, item: ModuleInstallPlanItem): + return _upsert_install_plan_items(session, [item]) + + +def _upsert_install_plan_items(session: Session, items: list[ModuleInstallPlanItem]): existing = saved_module_install_plan(session) + replacement_ids = {item.module_id for item in items if item.status == "planned"} retained = [ current for current in existing.items - if not (current.status == "planned" and current.module_id == item.module_id) + if not (current.status == "planned" and current.module_id in replacement_ids) ] - return save_module_install_plan(session, [*retained, item]) + return save_module_install_plan(session, [*retained, *items]) -def _catalog_plan_item(module_id: str, available_module_ids: set[str]) -> tuple[ModuleInstallPlanItem, dict[str, object]]: - result = validate_module_package_catalog() +def _catalog_plan_item( + module_id: str, + available_module_ids: set[str], + *, + validation: dict[str, object] | None = None, +) -> tuple[ModuleInstallPlanItem, dict[str, object]]: + result = validation or validate_module_package_catalog() if not result.get("valid"): raise HTTPException( status_code=status.HTTP_422_UNPROCESSABLE_CONTENT, @@ -801,7 +813,19 @@ def plan_module_install_from_catalog( lifecycle = getattr(request.app.state, "govoplan_lifecycle", None) available = dict(lifecycle.available_modules) if isinstance(lifecycle, ModuleLifecycleManager) else available_module_manifests(ignore_load_errors=True) item, validation = _catalog_plan_item(module_id, set(available)) - plan = _upsert_install_plan_item(session, item) + existing = saved_module_install_plan(session) + retained = [ + current + for current in existing.items + if not (current.status == "planned" and current.module_id == item.module_id) + ] + candidate_plan = ModuleInstallPlan(items=tuple([*retained, item])) + companion_ids = module_install_catalog_companion_module_ids(candidate_plan, available, validation=validation) + companion_items = [ + _catalog_plan_item(companion_id, set(available), validation=validation)[0] + for companion_id in companion_ids + ] + plan = _upsert_install_plan_items(session, [item, *companion_items]) record_module_package_catalog_acceptance(validation) except ModuleManagementError as exc: raise HTTPException(status_code=status.HTTP_422_UNPROCESSABLE_CONTENT, detail=str(exc)) from exc @@ -816,6 +840,7 @@ def plan_module_install_from_catalog( module_id=module_id, outcome="planned", items=[item.as_dict() for item in plan.items], + companion_module_ids=list(companion_ids), catalog_validation={ "valid": validation.get("valid"), "channel": validation.get("channel"), @@ -825,7 +850,10 @@ def plan_module_install_from_catalog( ) session.commit() planned_action = "update" if item.action == "update" else "install" - return _module_install_plan_response(session, request, notes=[f"Catalog {planned_action} entry planned for {module_id}."]) + notes = [f"Catalog {planned_action} entry planned for {module_id}."] + if companion_ids: + notes.append("Required companion catalog entries added: " + ", ".join(companion_ids)) + return _module_install_plan_response(session, request, notes=notes) @router.post("/system/modules/{module_id}/uninstall-plan", response_model=ModuleInstallPlanResponse) diff --git a/src/govoplan_admin/backend/api/v1/schemas.py b/src/govoplan_admin/backend/api/v1/schemas.py index 6fbb6f6..614472d 100644 --- a/src/govoplan_admin/backend/api/v1/schemas.py +++ b/src/govoplan_admin/backend/api/v1/schemas.py @@ -182,6 +182,7 @@ class ModuleInstallPlanItem(BaseModel): python_ref: str | None = Field(default=None, max_length=1000) webui_package: str | None = Field(default=None, max_length=200) webui_ref: str | None = Field(default=None, max_length=1000) + data_safety_acknowledged: bool = False destroy_data: bool = False status: Literal["planned", "applied", "blocked"] = "planned" notes: str | None = Field(default=None, max_length=1000) @@ -201,6 +202,63 @@ class ModuleInstallChecklistItem(BaseModel): detail: str | None = None +class ModuleInstallTargetItem(BaseModel): + module_id: str + action: Literal["install", "update", "uninstall"] + source: Literal["manual", "catalog"] + current_version: str | None = None + target_version: str | None = None + python_package: str | None = None + python_ref: str | None = None + webui_package: str | None = None + webui_ref: str | None = None + migration_safety: Literal["automatic", "requires_review", "forward_only", "destructive"] = "automatic" + migration_notes: str | None = None + current_version_min: str | None = None + current_version_max_exclusive: str | None = None + bridge_release: bool = False + bridge_notes: str | None = None + allow_downgrade: bool = False + allow_same_version: bool = False + recovery_tested: bool = False + recovery_notes: str | None = None + data_safety_acknowledged: bool = False + + +class ModuleMigrationPlanStep(BaseModel): + module_id: str + action: Literal["install", "update", "uninstall"] + phase: Literal["upgrade", "retirement"] + source: Literal["manifest", "catalog", "pending"] + has_migration_metadata: bool = False + metadata_pending: bool = False + migration_safety: Literal["automatic", "requires_review", "forward_only", "destructive"] = "automatic" + current_version: str | None = None + target_version: str | None = None + reason: str | None = None + + +class ModuleMigrationTaskPlanItem(BaseModel): + module_id: str + task_id: str + phase: Literal["pre_migration_check", "pre_migration_prepare", "post_migration_backfill", "post_migration_verify"] + summary: str + task_version: str = "1" + safety: Literal["automatic", "requires_review", "forward_only", "destructive"] = "automatic" + idempotent: bool = True + timeout_seconds: int | None = None + source: Literal["manifest", "catalog", "pending"] = "manifest" + has_executor: bool = False + metadata_pending: bool = False + + +class ModuleMigrationExecutionPlan(BaseModel): + enabled_modules: list[str] = Field(default_factory=list) + requires_database_migration: bool = False + steps: list[ModuleMigrationPlanStep] = Field(default_factory=list) + tasks: list[ModuleMigrationTaskPlanItem] = Field(default_factory=list) + + class ModuleInstallPreflightResponse(BaseModel): allowed: bool maintenance_mode: bool @@ -210,6 +268,8 @@ class ModuleInstallPreflightResponse(BaseModel): rollback_commands: list[str] = Field(default_factory=list) issues: list[ModuleInstallPreflightIssue] = Field(default_factory=list) checklist: list[ModuleInstallChecklistItem] = Field(default_factory=list) + target_plan: list[ModuleInstallTargetItem] = Field(default_factory=list) + migration_plan: ModuleMigrationExecutionPlan = Field(default_factory=ModuleMigrationExecutionPlan) class ModuleInstallPlanResponse(BaseModel): @@ -328,6 +388,20 @@ class ModulePackageCatalogItem(BaseModel): description: str | None = None version: str | None = None action: Literal["install", "update", "uninstall"] = "install" + dependencies: list[str] = Field(default_factory=list) + optional_dependencies: list[str] = Field(default_factory=list) + migration_safety: Literal["automatic", "requires_review", "forward_only", "destructive"] = "automatic" + migration_notes: str | None = None + migration_after: list[str] = Field(default_factory=list) + migration_before: list[str] = Field(default_factory=list) + current_version_min: str | None = None + current_version_max_exclusive: str | None = None + bridge_release: bool = False + bridge_notes: str | None = None + allow_downgrade: bool = False + allow_same_version: bool = False + recovery_tested: bool = False + recovery_notes: str | None = None python_package: str | None = None python_ref: str | None = None webui_package: str | None = None diff --git a/src/govoplan_admin/backend/manifest.py b/src/govoplan_admin/backend/manifest.py index c064170..c94362c 100644 --- a/src/govoplan_admin/backend/manifest.py +++ b/src/govoplan_admin/backend/manifest.py @@ -17,7 +17,7 @@ def _route_factory(context: ModuleContext): manifest = ModuleManifest( id="admin", name="Admin", - version="0.1.6", + version="0.1.7", required_capabilities=(CAPABILITY_AUTH_PRINCIPAL_RESOLVER, CAPABILITY_AUTH_PERMISSION_EVALUATOR), route_factory=_route_factory, migration_spec=MigrationSpec(module_id="admin", metadata=Base.metadata), diff --git a/webui/package.json b/webui/package.json index c5bc812..e9173c0 100644 --- a/webui/package.json +++ b/webui/package.json @@ -1,6 +1,6 @@ { "name": "@govoplan/admin-webui", - "version": "0.1.6", + "version": "0.1.7", "private": true, "type": "module", "main": "src/index.ts", @@ -13,7 +13,7 @@ } }, "peerDependencies": { - "@govoplan/core-webui": "^0.1.6", + "@govoplan/core-webui": "^0.1.7", "lucide-react": "^1.23.0", "react": "^19.0.0", "react-dom": "^19.0.0", diff --git a/webui/src/api/admin.ts b/webui/src/api/admin.ts index 36e588a..5ce4a91 100644 --- a/webui/src/api/admin.ts +++ b/webui/src/api/admin.ts @@ -249,13 +249,14 @@ export type ModuleCatalogResponse = { export type ModuleInstallPlanItem = { module_id: string; - action: "install" | "uninstall"; + action: "install" | "update" | "uninstall"; source: "manual" | "catalog"; catalog?: Record | null; python_package?: string | null; python_ref?: string | null; webui_package?: string | null; webui_ref?: string | null; + data_safety_acknowledged: boolean; destroy_data: boolean; status: "planned" | "applied" | "blocked"; notes?: string | null; @@ -275,6 +276,63 @@ export type ModuleInstallChecklistItem = { detail?: string | null; }; +export type ModuleInstallTargetItem = { + module_id: string; + action: "install" | "update" | "uninstall"; + source: "manual" | "catalog"; + current_version?: string | null; + target_version?: string | null; + python_package?: string | null; + python_ref?: string | null; + webui_package?: string | null; + webui_ref?: string | null; + migration_safety: "automatic" | "requires_review" | "forward_only" | "destructive"; + migration_notes?: string | null; + current_version_min?: string | null; + current_version_max_exclusive?: string | null; + bridge_release: boolean; + bridge_notes?: string | null; + allow_downgrade: boolean; + allow_same_version: boolean; + recovery_tested: boolean; + recovery_notes?: string | null; + data_safety_acknowledged: boolean; +}; + +export type ModuleMigrationPlanStep = { + module_id: string; + action: "install" | "update" | "uninstall"; + phase: "upgrade" | "retirement"; + source: "manifest" | "catalog" | "pending"; + has_migration_metadata: boolean; + metadata_pending: boolean; + migration_safety: "automatic" | "requires_review" | "forward_only" | "destructive"; + current_version?: string | null; + target_version?: string | null; + reason?: string | null; +}; + +export type ModuleMigrationTaskPlanItem = { + module_id: string; + task_id: string; + phase: "pre_migration_check" | "pre_migration_prepare" | "post_migration_backfill" | "post_migration_verify"; + summary: string; + task_version: string; + safety: "automatic" | "requires_review" | "forward_only" | "destructive"; + idempotent: boolean; + timeout_seconds?: number | null; + source: "manifest" | "catalog" | "pending"; + has_executor: boolean; + metadata_pending: boolean; +}; + +export type ModuleMigrationExecutionPlan = { + enabled_modules: string[]; + requires_database_migration: boolean; + steps: ModuleMigrationPlanStep[]; + tasks: ModuleMigrationTaskPlanItem[]; +}; + export type ModuleInstallPreflight = { allowed: boolean; maintenance_mode: boolean; @@ -284,6 +342,8 @@ export type ModuleInstallPreflight = { rollback_commands: string[]; issues: ModuleInstallPreflightIssue[]; checklist: ModuleInstallChecklistItem[]; + target_plan: ModuleInstallTargetItem[]; + migration_plan: ModuleMigrationExecutionPlan; }; export type ModuleInstallPlanResponse = { @@ -389,7 +449,21 @@ export type ModulePackageCatalogItem = { name: string; description?: string | null; version?: string | null; - action: "install" | "uninstall"; + action: "install" | "update" | "uninstall"; + dependencies: string[]; + optional_dependencies: string[]; + migration_safety: "automatic" | "requires_review" | "forward_only" | "destructive"; + migration_notes?: string | null; + migration_after: string[]; + migration_before: string[]; + current_version_min?: string | null; + current_version_max_exclusive?: string | null; + bridge_release: boolean; + bridge_notes?: string | null; + allow_downgrade: boolean; + allow_same_version: boolean; + recovery_tested: boolean; + recovery_notes?: string | null; python_package?: string | null; python_ref?: string | null; webui_package?: string | null; diff --git a/webui/src/features/admin/ModuleManagementPanel.tsx b/webui/src/features/admin/ModuleManagementPanel.tsx index 8503eff..1fe5b0e 100644 --- a/webui/src/features/admin/ModuleManagementPanel.tsx +++ b/webui/src/features/admin/ModuleManagementPanel.tsx @@ -26,6 +26,9 @@ import { type ModuleInstallerRunListResponse, type ModuleInstallPlanItem, type ModuleInstallPlanResponse, + type ModuleInstallTargetItem, + type ModuleMigrationPlanStep, + type ModuleMigrationTaskPlanItem, type ModuleLicenseDiagnostics, type ModulePackageCatalogResponse, type ModulePackageCatalogItem } from @@ -414,15 +417,25 @@ export default function ModuleManagementPanel({ settings, canWrite, canAccessMai {item.python_package && {item.python_package}} {item.webui_package && {item.webui_package}} {item.tags.length > 0 && {item.tags.join(", ")}} + {item.dependencies.length > 0 && i18n:govoplan-admin.dependencies.9f4f78d1 {item.dependencies.join(", ")}} + {item.migration_safety !== "automatic" && i18n:govoplan-admin.migration_safety.729bdb3c {migrationSafetyLabel(item.migration_safety)}} + {item.migration_after.length > 0 && i18n:govoplan-admin.after.695c89be {item.migration_after.join(", ")}} + {item.migration_before.length > 0 && i18n:govoplan-admin.before.a11cf31f {item.migration_before.join(", ")}} + {item.bridge_release && i18n:govoplan-admin.bridge_release.176cf241} + {(item.current_version_min || item.current_version_max_exclusive) && i18n:govoplan-admin.current_window.73e25c9f {currentWindowLabel(item)}} + {item.recovery_tested && i18n:govoplan-admin.recovery_tested.e831e2f1} {item.license_features.length > 0 && i18n:govoplan-admin.license.de13bf1a {item.license_features.join(", ")}} {item.license_missing_features.length > 0 && i18n:govoplan-admin.missing.feb2bbaa {item.license_missing_features.join(", ")}} {item.provides_interfaces.length > 0 && i18n:govoplan-admin.provides.221b70d9 {providedInterfacesLabel(item)}} {item.requires_interfaces.length > 0 && i18n:govoplan-admin.requires.a4fc9357 {requiredInterfacesLabel(item)}} {item.description &&

{item.description}

} + {item.migration_notes &&

{item.migration_notes}

} + {item.bridge_notes &&

{item.bridge_notes}

} + {item.recovery_notes &&

{item.recovery_notes}

} {item.license_reason &&

{item.license_reason}

} - + )} } @@ -450,6 +463,43 @@ export default function ModuleManagementPanel({ settings, canWrite, canAccessMai {installPlan.preflight.restart_required ? "i18n:govoplan-admin.restart_reload_required_after_package_changes.3a99cd63" : "i18n:govoplan-admin.no_package_restart_pending.efe6b8ce"} {installPlan.preflight.frontend_rebuild_required && i18n:govoplan-admin.webui_rebuild_required.010ce49f} + {installPlan.preflight.target_plan.length > 0 &&
+ i18n:govoplan-admin.target_plan.524ea0c8 + {installPlan.preflight.target_plan.map((target) => +
+ {target.module_id} - {target.action} + {targetVersionLabel(target)} +

{migrationSafetyLabel(target.migration_safety)}{target.data_safety_acknowledged ? " - i18n:govoplan-admin.acknowledged.d08d7c6d" : ""}

+ {target.bridge_release &&

i18n:govoplan-admin.bridge_release.176cf241

} + {target.recovery_tested &&

i18n:govoplan-admin.recovery_tested.e831e2f1

} + {target.python_ref &&

{target.python_ref}

} + {target.migration_notes &&

{target.migration_notes}

} + {target.bridge_notes &&

{target.bridge_notes}

} + {target.recovery_notes &&

{target.recovery_notes}

} +
+ )} +
} + {(installPlan.preflight.migration_plan.steps.length > 0 || installPlan.preflight.migration_plan.tasks.length > 0) &&
+ i18n:govoplan-admin.migration_plan.f42b9d90 + i18n:govoplan-admin.enabled_modules.3c38e9ff {installPlan.preflight.migration_plan.enabled_modules.join(", ")} + {installPlan.preflight.migration_plan.steps.map((step, index) => +
+ {index + 1}. {step.module_id} - {migrationPhaseLabel(step.phase)} + {migrationSourceLabel(step.source)}{step.metadata_pending ? " - i18n:govoplan-admin.metadata_pending.25190d87" : ""} +

{migrationSafetyLabel(step.migration_safety)}

+ {step.reason &&

{step.reason}

} +
+ )} + {installPlan.preflight.migration_plan.tasks.length > 0 && i18n:govoplan-admin.migration_tasks.a4410d3a} + {installPlan.preflight.migration_plan.tasks.map((task) => +
+ {task.module_id} - {migrationTaskPhaseLabel(task.phase)} + {task.summary} +

{migrationSourceLabel(task.source)}{task.metadata_pending ? " - i18n:govoplan-admin.executor_pending.7633225b" : ""}{task.has_executor ? " - i18n:govoplan-admin.executor_available.507de429" : ""}

+

{migrationSafetyLabel(task.safety)} - {task.idempotent ? "i18n:govoplan-admin.idempotent.47a0f2d6" : "i18n:govoplan-admin.not_idempotent.d3014c71"} - i18n:govoplan-admin.task_version.f0f26b92 {task.task_version}

+
+ )} +
} {installPlan.preflight.issues.length > 0 &&
{installPlan.preflight.issues.map((issue, index) =>
@@ -479,10 +529,11 @@ export default function ModuleManagementPanel({ settings, canWrite, canAccessMai {item.catalog?.sequence !== null && item.catalog?.sequence !== undefined && } {item.catalog?.key_id && }
- + updatePlanItem(index, { destroy_data: checked })} disabled={!canWrite || planBusy || item.action !== "uninstall"} /> + updatePlanItem(index, { data_safety_acknowledged: checked })} disabled={!canWrite || planBusy || item.action === "uninstall"} /> @@ -644,6 +695,65 @@ function requiredInterfacesLabel(item: ModulePackageCatalogItem): string { }).join(", "); } +function migrationSafetyLabel(value: ModulePackageCatalogItem["migration_safety"] | ModuleInstallTargetItem["migration_safety"]): string { + if (value === "requires_review") return "i18n:govoplan-admin.requires_review.8ba0b8c6"; + if (value === "forward_only") return "i18n:govoplan-admin.forward_only.6c107a46"; + if (value === "destructive") return "i18n:govoplan-admin.destructive.0051026c"; + return "i18n:govoplan-admin.automatic.d9a7260f"; +} + +function targetStatus(target: ModuleInstallTargetItem): "done" | "warning" | "blocked" { + if (target.migration_safety === "destructive" && !target.data_safety_acknowledged) return "blocked"; + if (target.migration_safety === "forward_only" && !target.data_safety_acknowledged) return "blocked"; + if (target.migration_safety !== "automatic") return "warning"; + return "done"; +} + +function targetVersionLabel(target: ModuleInstallTargetItem): string { + const current = target.current_version ?? "none"; + const next = target.action === "uninstall" ? "removed" : target.target_version ?? "unknown"; + return `${current} -> ${next}`; +} + +function migrationPhaseLabel(value: ModuleMigrationPlanStep["phase"]): string { + if (value === "retirement") return "i18n:govoplan-admin.retirement.6b680dd2"; + return "i18n:govoplan-admin.upgrade.12c5007d"; +} + +function migrationTaskPhaseLabel(value: ModuleMigrationTaskPlanItem["phase"]): string { + if (value === "pre_migration_check") return "i18n:govoplan-admin.pre_migration_check.f654164a"; + if (value === "pre_migration_prepare") return "i18n:govoplan-admin.pre_migration_prepare.d18fdd26"; + if (value === "post_migration_backfill") return "i18n:govoplan-admin.post_migration_backfill.21043d74"; + return "i18n:govoplan-admin.post_migration_verify.6af9f28b"; +} + +function migrationSourceLabel(value: ModuleMigrationPlanStep["source"] | ModuleMigrationTaskPlanItem["source"]): string { + if (value === "catalog") return "i18n:govoplan-admin.catalog_metadata.9b96c41a"; + if (value === "pending") return "i18n:govoplan-admin.pending_metadata.a24cfeb0"; + return "i18n:govoplan-admin.manifest_metadata.b9ae362a"; +} + +function migrationStepStatus(step: ModuleMigrationPlanStep): "done" | "pending" | "warning" | "blocked" { + if (step.metadata_pending) return "warning"; + if (step.migration_safety !== "automatic") return "warning"; + return "pending"; +} + +function migrationTaskStatus(task: ModuleMigrationTaskPlanItem): "done" | "pending" | "warning" | "blocked" { + if (!task.idempotent) return "blocked"; + if (!task.metadata_pending && !task.has_executor) return "blocked"; + if (task.safety === "forward_only" || task.safety === "destructive") return "warning"; + if (task.metadata_pending || task.safety === "requires_review") return "warning"; + return "pending"; +} + +function currentWindowLabel(item: Pick): string { + return [ + item.current_version_min ? `>=${item.current_version_min}` : "", + item.current_version_max_exclusive ? `<${item.current_version_max_exclusive}` : "", + ].filter(Boolean).join(" ") || "any"; +} + function ModuleStatus({ module, desiredEnabled }: {module: ModuleCatalogItem;desiredEnabled: boolean;}) { if (module.current_enabled && !desiredEnabled) return ; if (!module.current_enabled && desiredEnabled) return ; @@ -651,6 +761,12 @@ function ModuleStatus({ module, desiredEnabled }: {module: ModuleCatalogItem;des return ; } +function catalogPlanButtonLabel(item: ModulePackageCatalogItem, catalog: ModuleCatalogResponse | null): string { + if (item.action === "update") return "i18n:govoplan-admin.plan_update.86e6857a"; + const installed = catalog?.modules.some((module) => module.id === item.module_id && module.installed) ?? false; + return installed ? "i18n:govoplan-admin.plan_update.86e6857a" : "i18n:govoplan-admin.plan_install.e82bffe6"; +} + function sameSet(left: ReadonlySet, right: ReadonlySet) { if (left.size !== right.size) return false; for (const item of left) { @@ -669,6 +785,7 @@ function emptyPlanItem(): ModuleInstallPlanItem { python_ref: "", webui_package: "", webui_ref: "", + data_safety_acknowledged: false, destroy_data: false, status: "planned", notes: "" @@ -683,9 +800,10 @@ function normalizePlanItems(items: ModuleInstallPlanItem[]): ModuleInstallPlanIt source: item.source === "catalog" ? "catalog" : "manual", catalog: item.source === "catalog" ? item.catalog ?? null : null, python_package: cleanOptional(item.python_package), - python_ref: item.action === "install" ? cleanOptional(item.python_ref) : null, + python_ref: item.action !== "uninstall" ? cleanOptional(item.python_ref) : null, webui_package: cleanOptional(item.webui_package), - webui_ref: item.action === "install" ? cleanOptional(item.webui_ref) : null, + webui_ref: item.action !== "uninstall" ? cleanOptional(item.webui_ref) : null, + data_safety_acknowledged: item.action !== "uninstall" && Boolean(item.data_safety_acknowledged), destroy_data: item.action === "uninstall" && Boolean(item.destroy_data), status: item.status, notes: cleanOptional(item.notes) @@ -701,10 +819,10 @@ function cleanOptional(value?: string | null): string | null { function planValidationError(items: ModuleInstallPlanItem[]): string { for (const item of normalizePlanItems(items)) { if (!item.module_id) return "i18n:govoplan-admin.every_plan_item_needs_a_module_id.23a7f206"; - if (item.action === "install" && !item.python_ref) return i18nMessage("i18n:govoplan-admin.value_needs_a_python_package_reference.950b898e", { value0: item.module_id }); - if (item.action === "install" && item.python_ref && !item.python_package) return i18nMessage("i18n:govoplan-admin.value_needs_a_python_package_name_for_rollback.6c89ed75", { value0: item.module_id }); + if (item.action !== "uninstall" && !item.python_ref) return i18nMessage("i18n:govoplan-admin.value_needs_a_python_package_reference.950b898e", { value0: item.module_id }); + if (item.action !== "uninstall" && item.python_ref && !item.python_package) return i18nMessage("i18n:govoplan-admin.value_needs_a_python_package_name_for_rollback.6c89ed75", { value0: item.module_id }); if (item.action === "uninstall" && !item.python_package) return i18nMessage("i18n:govoplan-admin.value_needs_a_python_package_name_for_uninstall.004ba6fa", { value0: item.module_id }); - if (item.action === "install" && Boolean(item.webui_package) !== Boolean(item.webui_ref)) return i18nMessage("i18n:govoplan-admin.value_needs_both_webui_package_and_webui_referen.d2bab073", { value0: item.module_id }); + if (item.action !== "uninstall" && Boolean(item.webui_package) !== Boolean(item.webui_ref)) return i18nMessage("i18n:govoplan-admin.value_needs_both_webui_package_and_webui_referen.d2bab073", { value0: item.module_id }); if (item.action === "uninstall" && item.webui_ref && !item.webui_package) return i18nMessage("i18n:govoplan-admin.value_has_a_webui_reference_but_no_webui_package.18f44149", { value0: item.module_id }); } return ""; diff --git a/webui/src/i18n/generatedTranslations.ts b/webui/src/i18n/generatedTranslations.ts index a08300d..dbf8a43 100644 --- a/webui/src/i18n/generatedTranslations.ts +++ b/webui/src/i18n/generatedTranslations.ts @@ -6,10 +6,12 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.action.97c89a4d": "Action", "i18n:govoplan-admin.actions.c3cd636a": "Actions", "i18n:govoplan-admin.activate_installs.731d22a1": "Activate installs", + "i18n:govoplan-admin.acknowledged.d08d7c6d": "Acknowledged", "i18n:govoplan-admin.active_and_total_memberships.c0c20f10": "Active and total memberships.", "i18n:govoplan-admin.active_tenant_automation_credentials.240c659e": "Active tenant automation credentials.", "i18n:govoplan-admin.active_tenant.dfadf0aa": "Active tenant:", "i18n:govoplan-admin.active.a733b809": "Active", + "i18n:govoplan-admin.after.695c89be": "After:", "i18n:govoplan-admin.add_group_template.b74d8f0f": "Add group template", "i18n:govoplan-admin.add_plan_item.fa55f028": "Add plan item", "i18n:govoplan-admin.add_tenant_role.fcd904ea": "Add tenant role", @@ -34,9 +36,12 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.audit.fa1703dd": "Audit", "i18n:govoplan-admin.available.7c62a142": "Available", "i18n:govoplan-admin.blocked.99613c74": "Blocked", + "i18n:govoplan-admin.before.a11cf31f": "Before:", + "i18n:govoplan-admin.bridge_release.176cf241": "Bridge release", "i18n:govoplan-admin.build_webui.ed5ef1fd": " --build-webui", "i18n:govoplan-admin.build_webui.fe8ccad7": "Build WebUI", "i18n:govoplan-admin.bypass_allowed.4e347c27": "Bypass allowed", + "i18n:govoplan-admin.catalog_metadata.9b96c41a": "Catalog metadata", "i18n:govoplan-admin.bypass_denied.ab987400": "Bypass denied", "i18n:govoplan-admin.cached_from.d73c5b2a": "· cached from", "i18n:govoplan-admin.cancel.77dfd213": "Cancel", @@ -73,7 +78,10 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.create_tenant_role.f58db104": "Create tenant role", "i18n:govoplan-admin.created.0c78dab1": "Created:", "i18n:govoplan-admin.created.accf40c8": "Created", + "i18n:govoplan-admin.current_window.73e25c9f": "Current window:", + "i18n:govoplan-admin.automatic.d9a7260f": "Automatic", "i18n:govoplan-admin.daemon_execution.cc0fad8d": "Daemon execution", + "i18n:govoplan-admin.data_safety_reviewed.b4774edc": "Data safety reviewed", "i18n:govoplan-admin.daemon_offline.314f19a4": "Daemon offline", "i18n:govoplan-admin.daemon_value.e54f5a31": "Daemon: {value0}", "i18n:govoplan-admin.db_backup_command.5bded3ac": "DB backup command", @@ -95,8 +103,10 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.delete_tenant_role.4efa0813": "Delete tenant role", "i18n:govoplan-admin.delete_value_removal_is_blocked_while_a_material.d4eba73d": "Delete {value0}? Removal is blocked while a materialized tenant definition still has members or assignments.", "i18n:govoplan-admin.delete_value.4d18989e": "Delete {value0}", + "i18n:govoplan-admin.dependencies.9f4f78d1": "Dependencies:", "i18n:govoplan-admin.dependents.072665c4": "Dependents:", "i18n:govoplan-admin.description.55f8ebc8": "Description", + "i18n:govoplan-admin.destructive.0051026c": "Destructive", "i18n:govoplan-admin.destroy_data.34557c3c": "Destroy data", "i18n:govoplan-admin.disabled.f4f4473d": "Disabled", "i18n:govoplan-admin.discovered_packages.660902de": "Discovered packages", @@ -108,6 +118,9 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.edit_tenant_role.c15a260d": "Edit tenant role", "i18n:govoplan-admin.edit_value.fad75899": "Edit {value0}", "i18n:govoplan-admin.enable_maintenance_mode.75f98d57": "Enable maintenance mode", + "i18n:govoplan-admin.enabled_modules.3c38e9ff": "Enabled modules:", + "i18n:govoplan-admin.executor_available.507de429": "Executor available", + "i18n:govoplan-admin.executor_pending.7633225b": "Executor pending", "i18n:govoplan-admin.enabled.df174a3f": "Enabled", "i18n:govoplan-admin.enabling_maintenance_mode_requires_system_mainte.062d3968": "Enabling maintenance mode requires system:maintenance:access.", "i18n:govoplan-admin.enabling.2b8e03e6": "Enabling...", @@ -121,6 +134,7 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.exported_tenant_access_configuration.9122c85c": "Exported tenant access configuration", "i18n:govoplan-admin.features.5df81ffa": "Features:", "i18n:govoplan-admin.file_connections.1e362326": "File connections", + "i18n:govoplan-admin.forward_only.6c107a46": "Forward-only", "i18n:govoplan-admin.finished.4b52fe3f": "Finished:", "i18n:govoplan-admin.fragment.3f19d616": "Fragment", "i18n:govoplan-admin.front_office.d9dcfee1": "Front office", @@ -142,6 +156,7 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.history.90ccd649": "History", "i18n:govoplan-admin.id.474ae526": "Id", "i18n:govoplan-admin.import_preflight_approve_apply_and_export_module.29aec929": "Import, preflight, approve, apply and export module-owned configuration packages.", + "i18n:govoplan-admin.idempotent.47a0f2d6": "Idempotent", "i18n:govoplan-admin.inactive.09af574c": "Inactive", "i18n:govoplan-admin.inspect_value.9d5d1071": "Inspect {value0}", "i18n:govoplan-admin.install.fd6c3ebf": "Install", @@ -169,6 +184,7 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.license.de13bf1a": "License:", "i18n:govoplan-admin.locked.a798882f": "Locked", "i18n:govoplan-admin.mail_servers.d627326a": "Mail servers", + "i18n:govoplan-admin.manifest_metadata.b9ae362a": "Manifest metadata", "i18n:govoplan-admin.maintenance_message.ca62571f": "Maintenance message", "i18n:govoplan-admin.maintenance_mode_enabled_apply_the_module_state_.dda13e5c": "Maintenance mode enabled. Apply the module-state request when ready.", "i18n:govoplan-admin.maintenance_mode_is_off_package_changes_should_b.1d262629": "Maintenance mode is off. Package changes should be applied only after enabling maintenance mode.", @@ -177,6 +193,10 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.maintenance.94de303b": "Maintenance", "i18n:govoplan-admin.membership_status_groups_and_direct_roles_in_the.ab6c10b6": "Membership status, groups and direct roles in the active tenant.", "i18n:govoplan-admin.message.68f4145f": "Message", + "i18n:govoplan-admin.metadata_pending.25190d87": "Metadata pending", + "i18n:govoplan-admin.migration_plan.f42b9d90": "Migration plan", + "i18n:govoplan-admin.migration_safety.729bdb3c": "Migration safety:", + "i18n:govoplan-admin.migration_tasks.a4410d3a": "Migration tasks", "i18n:govoplan-admin.minimal_office_access.af48f49a": "Minimal office access", "i18n:govoplan-admin.missing_entitlement.0cafa611": "Missing entitlement", "i18n:govoplan-admin.missing.feb2bbaa": "Missing:", @@ -204,6 +224,7 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.none.6eef6648": "None", "i18n:govoplan-admin.not_available.d1a17af1": "Not available", "i18n:govoplan-admin.not_configured.811931bb": "Not configured", + "i18n:govoplan-admin.not_idempotent.d3014c71": "Not idempotent", "i18n:govoplan-admin.not_recorded.9925ee3c": "not recorded", "i18n:govoplan-admin.notes.70440046": "Notes", "i18n:govoplan-admin.object.2883f191": "Object", @@ -223,8 +244,14 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.package.7431e3df": "Package", "i18n:govoplan-admin.packages.0a999012": "Packages", "i18n:govoplan-admin.pending.c515ec74": " pending", + "i18n:govoplan-admin.pending_metadata.a24cfeb0": "Pending metadata", "i18n:govoplan-admin.permissions.d06d5557": "Permissions", "i18n:govoplan-admin.plan_install.e82bffe6": "Plan install", + "i18n:govoplan-admin.plan_update.86e6857a": "Plan update", + "i18n:govoplan-admin.post_migration_backfill.21043d74": "Post-migration backfill", + "i18n:govoplan-admin.post_migration_verify.6af9f28b": "Post-migration verify", + "i18n:govoplan-admin.pre_migration_check.f654164a": "Pre-migration check", + "i18n:govoplan-admin.pre_migration_prepare.d18fdd26": "Pre-migration prepare", "i18n:govoplan-admin.plan_package_installs_and_removals_here_then_app.4aeb03bf": "Plan package installs and removals here, then apply the rendered commands from an operator shell during maintenance mode.", "i18n:govoplan-admin.plan_uninstall.e62804ab": "Plan uninstall", "i18n:govoplan-admin.plan.ae2f98a0": "Plan", @@ -241,6 +268,7 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.queued_daemon_handoffs_created_from_the_admin_ui.d7ae7914": "Queued daemon handoffs created from the admin UI or CLI.", "i18n:govoplan-admin.queueing_installer_requests_requires_maintenance.ae81f9ac": "Queueing installer requests requires maintenance access.", "i18n:govoplan-admin.recent_supervised_installer_records_and_the_curr.29860245": "Recent supervised installer records and the current package-install lock.", + "i18n:govoplan-admin.recovery_tested.e831e2f1": "Recovery tested", "i18n:govoplan-admin.registered_tenant_spaces.61e17d70": "Registered tenant spaces.", "i18n:govoplan-admin.reload.cce71553": "Reload", "i18n:govoplan-admin.remove.e963907d": "Remove", @@ -253,10 +281,12 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.required.d5793988": "Required:", "i18n:govoplan-admin.required.eed6bfb4": "Required", "i18n:govoplan-admin.requires.a4fc9357": "Requires:", + "i18n:govoplan-admin.requires_review.8ba0b8c6": "Review required", "i18n:govoplan-admin.restart_commands.035997f9": "Restart commands", "i18n:govoplan-admin.restart_reload_required_after_package_changes.3a99cd63": "Restart/reload required after package changes", "i18n:govoplan-admin.restrict_authenticated_api_access_to_maintenance.2bc47195": "Restrict authenticated API access to maintenance operators", "i18n:govoplan-admin.retention.c7199d9e": "Retention", + "i18n:govoplan-admin.retirement.6b680dd2": "Retirement", "i18n:govoplan-admin.retry_of.3a6bb304": "Retry of:", "i18n:govoplan-admin.retry.9f5cd8a2": "Retry", "i18n:govoplan-admin.reusable_encrypted_smtp_imap_profiles_and_mail_p.31f150d1": "Reusable encrypted SMTP/IMAP profiles and mail policy.", @@ -302,6 +332,8 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.system_settings_saved.dac4f17b": "System settings saved.", "i18n:govoplan-admin.system_wide_governance_and_tenant_local_access_m.cda72499": "System-wide governance and tenant-local access management, separated by scope and enforced by the backend.", "i18n:govoplan-admin.system.bc0792d8": "System", + "i18n:govoplan-admin.target_plan.524ea0c8": "Target plan", + "i18n:govoplan-admin.task_version.f0f26b92": "Task version", "i18n:govoplan-admin.target.61ad50a9": "Target", "i18n:govoplan-admin.template_details.d5d75e4d": "Template details", "i18n:govoplan-admin.tenant_administration_capabilities.5d265972": "Tenant administration capabilities", @@ -328,6 +360,8 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.unlocked.b3da7025": "Unlocked", "i18n:govoplan-admin.unsigned.e91344ea": "Unsigned", "i18n:govoplan-admin.untrusted.cdc7838a": "Untrusted", + "i18n:govoplan-admin.upgrade.12c5007d": "Upgrade", + "i18n:govoplan-admin.update.503a059f": "Update", "i18n:govoplan-admin.update_enabled_modules.9b7ae790": "Update enabled modules", "i18n:govoplan-admin.updated.f2f8570d": "Updated", "i18n:govoplan-admin.user_file_connector_policy_limits": "File connector policy limits for user-owned spaces.", @@ -361,10 +395,12 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.action.97c89a4d": "Action", "i18n:govoplan-admin.actions.c3cd636a": "Aktionen", "i18n:govoplan-admin.activate_installs.731d22a1": "Installationen aktivieren", + "i18n:govoplan-admin.acknowledged.d08d7c6d": "Bestaetigt", "i18n:govoplan-admin.active_and_total_memberships.c0c20f10": "Active and total memberships.", "i18n:govoplan-admin.active_tenant_automation_credentials.240c659e": "Active tenant automation credentials.", "i18n:govoplan-admin.active_tenant.dfadf0aa": "Active tenant:", "i18n:govoplan-admin.active.a733b809": "Aktiv", + "i18n:govoplan-admin.after.695c89be": "Nach:", "i18n:govoplan-admin.add_group_template.b74d8f0f": "Add group template", "i18n:govoplan-admin.add_plan_item.fa55f028": "Add plan item", "i18n:govoplan-admin.add_tenant_role.fcd904ea": "Add tenant role", @@ -389,9 +425,12 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.audit.fa1703dd": "Audit", "i18n:govoplan-admin.available.7c62a142": "Verfügbar", "i18n:govoplan-admin.blocked.99613c74": "Blockiert", + "i18n:govoplan-admin.before.a11cf31f": "Vor:", + "i18n:govoplan-admin.bridge_release.176cf241": "Brueckenrelease", "i18n:govoplan-admin.build_webui.ed5ef1fd": " --build-webui", "i18n:govoplan-admin.build_webui.fe8ccad7": "WebUI bauen", "i18n:govoplan-admin.bypass_allowed.4e347c27": "Bypass allowed", + "i18n:govoplan-admin.catalog_metadata.9b96c41a": "Katalogmetadaten", "i18n:govoplan-admin.bypass_denied.ab987400": "Bypass denied", "i18n:govoplan-admin.cached_from.d73c5b2a": "· cached from", "i18n:govoplan-admin.cancel.77dfd213": "Abbrechen", @@ -428,7 +467,10 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.create_tenant_role.f58db104": "Create tenant role", "i18n:govoplan-admin.created.0c78dab1": "Created:", "i18n:govoplan-admin.created.accf40c8": "Erstellt", + "i18n:govoplan-admin.current_window.73e25c9f": "Aktuelles Fenster:", + "i18n:govoplan-admin.automatic.d9a7260f": "Automatisch", "i18n:govoplan-admin.daemon_execution.cc0fad8d": "Daemon-Ausführung", + "i18n:govoplan-admin.data_safety_reviewed.b4774edc": "Datensicherheit geprueft", "i18n:govoplan-admin.daemon_offline.314f19a4": "Daemon offline", "i18n:govoplan-admin.daemon_value.e54f5a31": "Daemon: {value0}", "i18n:govoplan-admin.db_backup_command.5bded3ac": "DB-Backup-Befehl", @@ -450,8 +492,10 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.delete_tenant_role.4efa0813": "Delete tenant role", "i18n:govoplan-admin.delete_value_removal_is_blocked_while_a_material.d4eba73d": "Delete {value0}? Removal is blocked while a materialized tenant definition still has members or assignments.", "i18n:govoplan-admin.delete_value.4d18989e": "Delete {value0}", + "i18n:govoplan-admin.dependencies.9f4f78d1": "Abhaengigkeiten:", "i18n:govoplan-admin.dependents.072665c4": "Dependents:", "i18n:govoplan-admin.description.55f8ebc8": "Beschreibung", + "i18n:govoplan-admin.destructive.0051026c": "Destruktiv", "i18n:govoplan-admin.destroy_data.34557c3c": "Daten zerstören", "i18n:govoplan-admin.disabled.f4f4473d": "Disabled", "i18n:govoplan-admin.discovered_packages.660902de": "Discovered packages", @@ -463,6 +507,9 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.edit_tenant_role.c15a260d": "Edit tenant role", "i18n:govoplan-admin.edit_value.fad75899": "Edit {value0}", "i18n:govoplan-admin.enable_maintenance_mode.75f98d57": "Enable maintenance mode", + "i18n:govoplan-admin.enabled_modules.3c38e9ff": "Aktive Module:", + "i18n:govoplan-admin.executor_available.507de429": "Ausfuehrer verfuegbar", + "i18n:govoplan-admin.executor_pending.7633225b": "Ausfuehrer ausstehend", "i18n:govoplan-admin.enabled.df174a3f": "Aktiviert", "i18n:govoplan-admin.enabling_maintenance_mode_requires_system_mainte.062d3968": "Enabling maintenance mode requires system:maintenance:access.", "i18n:govoplan-admin.enabling.2b8e03e6": "Enabling...", @@ -476,6 +523,7 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.exported_tenant_access_configuration.9122c85c": "Exported tenant access configuration", "i18n:govoplan-admin.features.5df81ffa": "Features:", "i18n:govoplan-admin.file_connections.1e362326": "Dateiverbindungen", + "i18n:govoplan-admin.forward_only.6c107a46": "Nur vorwaerts", "i18n:govoplan-admin.finished.4b52fe3f": "Finished:", "i18n:govoplan-admin.fragment.3f19d616": "Fragment", "i18n:govoplan-admin.front_office.d9dcfee1": "Front office", @@ -497,6 +545,7 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.history.90ccd649": "History", "i18n:govoplan-admin.id.474ae526": "Id", "i18n:govoplan-admin.import_preflight_approve_apply_and_export_module.29aec929": "Modul-eigene Konfigurationspakete importieren, prüfen, freigeben, anwenden und exportieren.", + "i18n:govoplan-admin.idempotent.47a0f2d6": "Idempotent", "i18n:govoplan-admin.inactive.09af574c": "Inaktiv", "i18n:govoplan-admin.inspect_value.9d5d1071": "Inspect {value0}", "i18n:govoplan-admin.install.fd6c3ebf": "Installieren", @@ -524,6 +573,7 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.license.de13bf1a": "License:", "i18n:govoplan-admin.locked.a798882f": "Gesperrt", "i18n:govoplan-admin.mail_servers.d627326a": "Mail servers", + "i18n:govoplan-admin.manifest_metadata.b9ae362a": "Manifestmetadaten", "i18n:govoplan-admin.maintenance_message.ca62571f": "Wartungsmeldung", "i18n:govoplan-admin.maintenance_mode_enabled_apply_the_module_state_.dda13e5c": "Maintenance mode enabled. Apply the module-state request when ready.", "i18n:govoplan-admin.maintenance_mode_is_off_package_changes_should_b.1d262629": "Maintenance mode is off. Package changes should be applied only after enabling maintenance mode.", @@ -532,6 +582,10 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.maintenance.94de303b": "Wartung", "i18n:govoplan-admin.membership_status_groups_and_direct_roles_in_the.ab6c10b6": "Membership status, groups and direct roles in the active tenant.", "i18n:govoplan-admin.message.68f4145f": "Nachricht", + "i18n:govoplan-admin.metadata_pending.25190d87": "Metadaten ausstehend", + "i18n:govoplan-admin.migration_plan.f42b9d90": "Migrationsplan", + "i18n:govoplan-admin.migration_safety.729bdb3c": "Migrationssicherheit:", + "i18n:govoplan-admin.migration_tasks.a4410d3a": "Migrationsaufgaben", "i18n:govoplan-admin.minimal_office_access.af48f49a": "Minimal office access", "i18n:govoplan-admin.missing_entitlement.0cafa611": "Missing entitlement", "i18n:govoplan-admin.missing.feb2bbaa": "Missing:", @@ -559,6 +613,7 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.none.6eef6648": "Keine", "i18n:govoplan-admin.not_available.d1a17af1": "Not available", "i18n:govoplan-admin.not_configured.811931bb": "Nicht konfiguriert", + "i18n:govoplan-admin.not_idempotent.d3014c71": "Nicht idempotent", "i18n:govoplan-admin.not_recorded.9925ee3c": "not recorded", "i18n:govoplan-admin.notes.70440046": "Notes", "i18n:govoplan-admin.object.2883f191": "Object", @@ -578,8 +633,14 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.package.7431e3df": "Package", "i18n:govoplan-admin.packages.0a999012": "Pakete", "i18n:govoplan-admin.pending.c515ec74": " pending", + "i18n:govoplan-admin.pending_metadata.a24cfeb0": "Ausstehende Metadaten", "i18n:govoplan-admin.permissions.d06d5557": "Berechtigungen", "i18n:govoplan-admin.plan_install.e82bffe6": "Plan install", + "i18n:govoplan-admin.plan_update.86e6857a": "Aktualisierung planen", + "i18n:govoplan-admin.post_migration_backfill.21043d74": "Nach-Migration Backfill", + "i18n:govoplan-admin.post_migration_verify.6af9f28b": "Nach-Migration Pruefung", + "i18n:govoplan-admin.pre_migration_check.f654164a": "Vor-Migration Check", + "i18n:govoplan-admin.pre_migration_prepare.d18fdd26": "Vor-Migration Vorbereitung", "i18n:govoplan-admin.plan_package_installs_and_removals_here_then_app.4aeb03bf": "Plan package installs and removals here, then apply the rendered commands from an operator shell during maintenance mode.", "i18n:govoplan-admin.plan_uninstall.e62804ab": "Plan uninstall", "i18n:govoplan-admin.plan.ae2f98a0": "Plan", @@ -596,6 +657,7 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.queued_daemon_handoffs_created_from_the_admin_ui.d7ae7914": "Queued daemon handoffs created from the admin UI or CLI.", "i18n:govoplan-admin.queueing_installer_requests_requires_maintenance.ae81f9ac": "Das Einreihen von Installer-Anfragen erfordert Wartungszugriff.", "i18n:govoplan-admin.recent_supervised_installer_records_and_the_curr.29860245": "Aktuelle überwachte Installer-Datensätze und die aktuelle Paketinstallationssperre.", + "i18n:govoplan-admin.recovery_tested.e831e2f1": "Recovery getestet", "i18n:govoplan-admin.registered_tenant_spaces.61e17d70": "Registered tenant spaces.", "i18n:govoplan-admin.reload.cce71553": "Neu laden", "i18n:govoplan-admin.remove.e963907d": "Entfernen", @@ -608,10 +670,12 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.required.d5793988": "Required:", "i18n:govoplan-admin.required.eed6bfb4": "Required", "i18n:govoplan-admin.requires.a4fc9357": "Requires:", + "i18n:govoplan-admin.requires_review.8ba0b8c6": "Pruefung erforderlich", "i18n:govoplan-admin.restart_commands.035997f9": "Neustartbefehle", "i18n:govoplan-admin.restart_reload_required_after_package_changes.3a99cd63": "Restart/reload required after package changes", "i18n:govoplan-admin.restrict_authenticated_api_access_to_maintenance.2bc47195": "Authentifizierten API-Zugriff auf Wartungsoperatoren beschränken", "i18n:govoplan-admin.retention.c7199d9e": "Retention", + "i18n:govoplan-admin.retirement.6b680dd2": "Stilllegung", "i18n:govoplan-admin.retry_of.3a6bb304": "Retry of:", "i18n:govoplan-admin.retry.9f5cd8a2": "Erneut versuchen", "i18n:govoplan-admin.reusable_encrypted_smtp_imap_profiles_and_mail_p.31f150d1": "Reusable encrypted SMTP/IMAP profiles and mail policy.", @@ -657,6 +721,8 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.system_settings_saved.dac4f17b": "Systemeinstellungen gespeichert.", "i18n:govoplan-admin.system_wide_governance_and_tenant_local_access_m.cda72499": "System-wide governance and tenant-local access management, separated by scope and enforced by the backend.", "i18n:govoplan-admin.system.bc0792d8": "System", + "i18n:govoplan-admin.target_plan.524ea0c8": "Zielplan", + "i18n:govoplan-admin.task_version.f0f26b92": "Aufgabenversion", "i18n:govoplan-admin.target.61ad50a9": "Target", "i18n:govoplan-admin.template_details.d5d75e4d": "Template details", "i18n:govoplan-admin.tenant_administration_capabilities.5d265972": "Tenant administration capabilities", @@ -683,6 +749,8 @@ export const generatedTranslations: PlatformTranslations = { "i18n:govoplan-admin.unlocked.b3da7025": "Entsperrt", "i18n:govoplan-admin.unsigned.e91344ea": "Unsigniert", "i18n:govoplan-admin.untrusted.cdc7838a": "Nicht vertrauenswürdig", + "i18n:govoplan-admin.upgrade.12c5007d": "Upgrade", + "i18n:govoplan-admin.update.503a059f": "Aktualisieren", "i18n:govoplan-admin.update_enabled_modules.9b7ae790": "Update enabled modules", "i18n:govoplan-admin.updated.f2f8570d": "Aktualisiert", "i18n:govoplan-admin.user_file_connector_policy_limits": "Dateiverbindungsrichtlinien fuer benutzereigene Bereiche.",