From d5cdfdb2d72e955c2d1816099e96aa289a020bdc Mon Sep 17 00:00:00 2001 From: Albrecht Degering Date: Tue, 7 Jul 2026 12:04:22 +0200 Subject: [PATCH] Sync wiki from project files --- Repo-docs-MODULE-ARCHITECTURE.md | 58 +++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/Repo-docs-MODULE-ARCHITECTURE.md b/Repo-docs-MODULE-ARCHITECTURE.md index d190512..d6c65d4 100644 --- a/Repo-docs-MODULE-ARCHITECTURE.md +++ b/Repo-docs-MODULE-ARCHITECTURE.md @@ -1,4 +1,4 @@ - + > Mirrored from `/mnt/DATA/git/govoplan-core/docs/MODULE_ARCHITECTURE.md`. > Origin: `repository`. @@ -398,9 +398,14 @@ The package install-plan API records operator intent only: - `GET /api/v1/admin/system/modules/install-plan` reads the saved plan, renders shell commands, and returns installer preflight status. +- `GET /api/v1/admin/system/modules/install-runs` returns recent installer run + summaries and the current installer lock status. +- `GET /api/v1/admin/system/modules/install-runs/{run_id}` returns the raw run + record for diagnosis. - `PUT /api/v1/admin/system/modules/install-plan` saves planned install or uninstall rows. Install rows must use tagged package or git references, not - local `file:`/workspace paths. + local `file:`/workspace paths. Python install rows must also include the + distribution package name so rollback can uninstall newly added packages. - `DELETE /api/v1/admin/system/modules/install-plan` clears the plan. - `govoplan-module-install-plan --format shell` or `python -m govoplan_core.commands.module_install_plan --format shell` renders @@ -413,11 +418,13 @@ The package install-plan API records operator intent only: applied after success. - `govoplan-module-installer --supervise --migrate --health-url http://127.0.0.1:8000/health --restart-command ''` is the preferred disruptive-change path. It applies the plan, optionally runs - migrations in a fresh Python process, runs the restart command if provided, - polls health, and automatically rolls packages back from the run snapshot if - commands, migrations, restart, or health recovery fail. + migrations in a fresh Python process after a fresh-process manifest + verification, runs the restart command if provided, polls health, and + automatically rolls packages back from the run snapshot if commands, + migrations, restart, or health recovery fail. - `govoplan-module-installer --rollback ` restores the saved package - snapshots and reruns package installation from the previous freeze file. + snapshots, restores the captured SQLite database snapshot when present, and + reruns package installation from the previous freeze file. The installer preflight is intentionally conservative: @@ -428,9 +435,12 @@ The installer preflight is intentionally conservative: - uninstalling an active module is blocked; - uninstalling a module still present in desired startup state is blocked; - uninstalling a module with active/desired dependents is blocked; +- uninstalling a module that owns migrations is blocked until that module + explicitly supports migration retirement; - module-owned uninstall guard providers can veto data/migration/worker unsafe removals; - install refs must be exact versions or tagged git refs; +- Python install rows must include the package distribution name for rollback; - WebUI package changes require a WebUI root and trigger rebuild/reload status. The installer supervisor must run outside the FastAPI server process. A server @@ -438,10 +448,12 @@ request handler cannot reliably restart or roll back the process that is currently executing the request. The admin UI therefore remains an operator planning surface; the trusted daemon/CLI is the executor. -Automatic rollback covers Python and WebUI package state. It does not roll back -database migrations; production installs must take a database backup before -running `--migrate`, and module uninstall remains blocked until data and -migration-state retirement rules are satisfied. +Automatic rollback covers Python and WebUI package state. For `sqlite:///` +database URLs, `--migrate` also captures a SQLite backup and rollback restores +it before the supervisor restarts the server. Non-SQLite deployments still need +an external managed backup/restore path before running migrations, and module +uninstall remains blocked until data and migration-state retirement rules are +satisfied. The running FastAPI server still reports `package_mutation_supported=false` because dependency-manager operations are not executed inside request handlers. @@ -449,12 +461,26 @@ The trusted mutation boundary is the operator CLI. This keeps the interpreter, npm dependency graph, frontend bundle, migrations, and worker process set under process-supervisor control. -Frontend module loading currently uses the build-time package graph generated by -the core WebUI host. Therefore installing or uninstalling a WebUI package -requires `npm install` plus a WebUI rebuild/reload. True remote runtime bundle -loading would need signed asset manifests, version compatibility checks, CSP -rules, cache invalidation, and rollback at the asset-loader layer; it is a -future deployment hardening track, not the default module installer path. +Frontend module loading primarily uses the build-time package graph generated by +the core WebUI host. Installing or uninstalling a WebUI package therefore still +uses `npm install` plus a WebUI rebuild/reload by default. Core also exposes an +experimental hot remote-bundle path for modules that are enabled by the backend +but absent from the local WebUI package graph: + +- `FrontendModule.asset_manifest` points at a JSON remote asset manifest. +- `asset_manifest_integrity` is an SRI-style hash for that manifest. +- `asset_manifest_signature` and `asset_manifest_public_key_id` allow the shell + to verify the manifest when a trusted browser key is registered on + `window.__GOVOPLAN_REMOTE_MODULE_KEYS__`. +- The remote asset manifest contract version is `1` and contains `moduleId`, + `entry`, `entryIntegrity`, and optional `moduleExport`. +- The browser fetches and verifies the manifest, fetches and verifies the entry + bundle, imports it dynamically, and then applies backend metadata before + adding the module's routes/nav/capabilities. + +Unsigned/unhashed remote bundles are skipped. This keeps remote loading a +controlled deployment option rather than a replacement for release package +builds. ## Maintenance Mode