From 5607aaf1ab6c2d99c430b12ba261c9a711b394ff Mon Sep 17 00:00:00 2001 From: Albrecht Degering Date: Tue, 7 Jul 2026 15:06:45 +0200 Subject: [PATCH] Sync wiki from project files --- Repo-docs-CATALOG-TRUST-AND-LICENSING.md | 191 +++++++++++++++++++++++ Repo-docs-MODULE-ARCHITECTURE.md | 32 +++- Repo-docs-RELEASE-DEPENDENCIES.md | 53 +++++-- 3 files changed, 264 insertions(+), 12 deletions(-) create mode 100644 Repo-docs-CATALOG-TRUST-AND-LICENSING.md diff --git a/Repo-docs-CATALOG-TRUST-AND-LICENSING.md b/Repo-docs-CATALOG-TRUST-AND-LICENSING.md new file mode 100644 index 0000000..3d189cb --- /dev/null +++ b/Repo-docs-CATALOG-TRUST-AND-LICENSING.md @@ -0,0 +1,191 @@ + + +> Mirrored from `/mnt/DATA/git/govoplan-core/docs/CATALOG_TRUST_AND_LICENSING.md`. +> Origin: `repository`. +> Active tasks and changing state belong in Gitea issues; this wiki page is durable project context. + +--- +# Module Catalog Trust And Licensing + +GovOPlaN module install and uninstall must remain operator-controlled. The +running server may plan and validate package changes, but package mutation is +performed by the separate installer daemon or an operator shell during +maintenance mode. + +## Roles + +`govoplan-web` is the public static distribution surface for official catalog +resources: + +- signed module package catalogs, grouped by release channel +- public catalog keyrings +- public license verification keyrings +- examples and operator-facing download paths + +`govoplan-core` is the verifier and orchestrator: + +- fetches a local or remote module catalog +- verifies catalog signatures against configured trusted keys +- enforces approved release channels +- rejects expired or not-yet-valid catalogs +- records accepted catalog sequence numbers for replay protection +- checks catalog entry license feature requirements before planning installs +- writes installer plans and request records + +Feature and platform modules own their package artifacts, manifests, migration +metadata, retirement providers, and optional lifecycle behavior. + +## Catalog Source + +Core accepts either a local catalog file or a remote URL: + +```bash +GOVOPLAN_MODULE_PACKAGE_CATALOG=/srv/govoplan/catalogs/stable.json +GOVOPLAN_MODULE_PACKAGE_CATALOG_URL=https://govoplan.example/catalogs/v1/channels/stable.json +GOVOPLAN_MODULE_PACKAGE_CATALOG_CACHE=/srv/govoplan/runtime/catalog-cache/stable.json +``` + +If both file and URL are set, the URL wins. The cache is used when a remote +fetch fails, so an operator can still inspect the last known catalog. A cached +catalog must still pass signature, freshness, channel, and replay validation. + +## Catalog Shape + +An official catalog is a JSON object with: + +- `catalog_version` +- `channel` +- `sequence` +- `generated_at` +- `not_before` when delayed activation is needed +- `expires_at` +- `modules` +- `signatures` + +Each module entry can declare: + +- backend package name and pinned install reference +- WebUI package name and pinned install reference +- display metadata and tags +- `license_features`, the feature entitlements required to plan that install + +The signature is Ed25519 over canonical JSON with both `signature` and +`signatures` removed. Core accepts the legacy single `signature` field and the +new `signatures` array. + +## Keyrings And Rotation + +Trusted catalog keys are configured locally: + +```bash +GOVOPLAN_MODULE_PACKAGE_CATALOG_TRUSTED_KEYS_FILE=/srv/govoplan/trust/catalog-keyring.json +GOVOPLAN_MODULE_PACKAGE_CATALOG_TRUSTED_KEYS='{"release-key-1":""}' +``` + +For development or tightly controlled deployments, a keyring can be read from a +URL and cached: + +```bash +GOVOPLAN_MODULE_PACKAGE_CATALOG_TRUSTED_KEYS_URL=https://govoplan.example/catalogs/v1/keyring.json +GOVOPLAN_MODULE_PACKAGE_CATALOG_TRUSTED_KEYS_CACHE=/srv/govoplan/runtime/catalog-cache/keyring.json +``` + +Production installations should pin the trusted keyring locally or ship it +through deployment configuration. Fetching trusted keys from the same public +origin as the catalog is convenient, but that origin must not become the only +trust root. + +Keyring entries support: + +- `key_id` +- `public_key` or `public_key_base64` +- `status`: `active`, `next`, `retired`, `revoked`, or `disabled` +- `not_before` +- `not_after` + +Rotation process: + +1. Add the next public key to the local trusted keyring with status `next`. +2. Publish catalogs signed by both current and next keys. +3. Upgrade installations so the next key is locally trusted. +4. Promote the next key to `active`. +5. Retire the old key only after every supported installation trusts the new + key. +6. Mark a compromised key `revoked` and publish a higher sequence catalog + signed by an uncompromised key. + +## Replay And Freshness + +Use replay state in production: + +```bash +GOVOPLAN_MODULE_PACKAGE_CATALOG_SEQUENCE_STATE=/srv/govoplan/runtime/catalog-sequences.json +GOVOPLAN_MODULE_PACKAGE_CATALOG_ENFORCE_SEQUENCE=true +``` + +Core records the accepted sequence per channel after a catalog entry is planned +from the admin interface. With strict sequence enforcement, a previously +accepted sequence is rejected; without strict enforcement, only older sequences +are rejected. + +Catalogs should always expire. Long-lived catalogs make rollback and key +compromise harder to reason about. + +## Release Channels + +Approved channels are deployment policy: + +```bash +GOVOPLAN_MODULE_PACKAGE_CATALOG_APPROVED_CHANNELS=stable,lts +GOVOPLAN_MODULE_PACKAGE_CATALOG_REQUIRE_SIGNATURE=true +``` + +The admin UI can display other catalog metadata, but core rejects catalogs from +unapproved channels when validation is configured. + +## Licensing + +Catalog entries can require license features: + +```json +"license_features": ["module.mail", "support.standard"] +``` + +Core checks those requirements against an offline license file before allowing +the entry into the install plan. + +```bash +GOVOPLAN_LICENSE_FILE=/srv/govoplan/license.json +GOVOPLAN_LICENSE_ENFORCEMENT=true +GOVOPLAN_LICENSE_TRUSTED_KEYS_FILE=/srv/govoplan/trust/license-keyring.json +``` + +License files are JSON objects with: + +- `license_id` +- `subject` +- `features` +- `valid_from` +- `valid_until` +- `signature` + +License enforcement can run in observe-only mode by leaving +`GOVOPLAN_LICENSE_ENFORCEMENT` unset. In that mode, missing or invalid license +data is surfaced as a warning but does not block planning. + +Licensing is intentionally separate from open-source code licensing. The +catalog/license mechanism can govern support channels, official release +eligibility, hosted update access, professional support, or commercial +entitlements without changing the source license of the repositories. + +## Production Gaps + +The current implementation validates signed catalog metadata and offline +license entitlements. Production-grade distribution still needs: + +- artifact digest verification for package archives or registry artifacts +- SBOM/provenance fields and verification workflow +- hardened catalog publishing pipeline in `govoplan-web` +- automated key rotation runbook and emergency revocation procedure +- license issuance and renewal tooling +- tests for remote catalog cache fallback and replay-state upgrades diff --git a/Repo-docs-MODULE-ARCHITECTURE.md b/Repo-docs-MODULE-ARCHITECTURE.md index 6a4f273..a00d8f0 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`. @@ -31,6 +31,7 @@ The kernel target owns: - the server entry point and platform configuration - module discovery, manifest validation, registry validation, route aggregation, and platform metadata APIs - database engine/session lifecycle and module migration orchestration +- module install-plan validation, signed catalog verification, license entitlement checks, and installer request orchestration - capability registry, command/event contracts, and lifecycle hooks - shared WebUI shell contracts, generic WebUI components, and module route/nav rendering - centralized mapping from serializable icon names to renderable frontend icons @@ -160,6 +161,7 @@ A module owns: - module migrations and migration metadata - module permissions and role templates - module-specific schemas, policies, and domain rules +- module package metadata and retirement providers used by install/uninstall preflight - WebUI pages, feature-specific components, API clients, route contributions, and navigation metadata A module should not own generic platform UI. If a component is useful outside one module, move it to `@govoplan/core-webui` and parameterize it there before reusing it. @@ -215,6 +217,34 @@ Rules: should compare the database heads to the configured script heads instead of assuming one linear revision when multiple modules are enabled. +## Install, Uninstall, And Catalogs + +Core owns the install plan, signed catalog validation, license entitlement +check, maintenance-mode guard, replay state, and installer request queue. +Package mutation is performed by `govoplan-module-installer` outside the +FastAPI request process. + +Official catalogs can be served as static JSON from `govoplan-web`, but core +does not trust the website by location alone. A catalog must pass the configured +signature, channel, freshness, and replay rules before a catalog entry can be +planned. Catalog entries may declare `license_features`; core checks those +against the configured offline license before adding the entry to the install +plan. + +Modules should provide: + +- pinned backend and WebUI package refs for official catalog entries +- compatibility metadata in the module manifest +- lifecycle hooks when a runtime enable/disable action needs module-specific + work +- uninstall guards for persistent data, active workers, schedulers, or external + bindings +- retirement providers when destructive uninstall can safely drop or retire + module-owned data + +Uninstall remains non-destructive unless the operator explicitly requests +`destroy_data` and the module provides a retirement provider that supports it. + ## WebUI Contract A WebUI module exports a `PlatformWebModule` from its package. The object contributes local/fallback metadata and route render functions. diff --git a/Repo-docs-RELEASE-DEPENDENCIES.md b/Repo-docs-RELEASE-DEPENDENCIES.md index 572d420..35b12d0 100644 --- a/Repo-docs-RELEASE-DEPENDENCIES.md +++ b/Repo-docs-RELEASE-DEPENDENCIES.md @@ -1,4 +1,4 @@ - + > Mirrored from `/mnt/DATA/git/govoplan-core/docs/RELEASE_DEPENDENCIES.md`. > Origin: `repository`. @@ -198,19 +198,30 @@ govoplan-module-installer --cancel-request --format json govoplan-module-installer --retry-request --format json ``` -Package catalogs are file-backed. Set `GOVOPLAN_MODULE_PACKAGE_CATALOG` to a -JSON file matching `docs/module-package-catalog.example.json`; the admin UI will -show those entries and can save them into the install plan. This keeps the -release approval decision outside the running server while avoiding hand-typed -package refs. Validate the catalog before handing it to operators: +Package catalogs can be local files or remote static resources, for example +served by `govoplan-web`. Set `GOVOPLAN_MODULE_PACKAGE_CATALOG` for a local file +or `GOVOPLAN_MODULE_PACKAGE_CATALOG_URL` for a remote catalog matching +`docs/module-package-catalog.example.json`; the admin UI will show those entries +and can save them into the install plan. This keeps the release approval +decision outside the running server while avoiding hand-typed package refs. +Remote catalogs can be cached for offline inspection: + +```bash +GOVOPLAN_MODULE_PACKAGE_CATALOG_URL=https://govoplan.example/catalogs/v1/channels/stable.json +GOVOPLAN_MODULE_PACKAGE_CATALOG_CACHE=/srv/govoplan/runtime/catalog-cache/stable.json +``` + +Validate the catalog before handing it to operators: ```bash govoplan-module-installer --validate-package-catalog docs/module-package-catalog.example.json --format json ``` -Release catalogs should be signed and channel-gated. The supported signing -format is an Ed25519 signature over the canonical catalog JSON object with the -`signature` field removed. Sign a catalog with: +Release catalogs should be signed, channel-gated, expiring, and sequence +tracked. The supported signing format is an Ed25519 signature over the +canonical catalog JSON object with the `signature` and `signatures` fields +removed. Core accepts the legacy single `signature` field and the newer +`signatures` array used during key rotation. Sign a catalog with: ```bash govoplan-module-installer \ @@ -238,10 +249,30 @@ GOVOPLAN_MODULE_PACKAGE_CATALOG=/path/to/catalog.json GOVOPLAN_MODULE_PACKAGE_CATALOG_REQUIRE_SIGNATURE=true GOVOPLAN_MODULE_PACKAGE_CATALOG_APPROVED_CHANNELS=stable GOVOPLAN_MODULE_PACKAGE_CATALOG_TRUSTED_KEYS='{"release-key-1":""}' +GOVOPLAN_MODULE_PACKAGE_CATALOG_SEQUENCE_STATE=/srv/govoplan/runtime/catalog-sequences.json +GOVOPLAN_MODULE_PACKAGE_CATALOG_ENFORCE_SEQUENCE=true ``` -Unsigned catalogs remain usable for local development when signature -enforcement is off, but the admin UI labels them as unsigned. +Trusted keys can also be loaded from +`GOVOPLAN_MODULE_PACKAGE_CATALOG_TRUSTED_KEYS_FILE`. A URL-backed keyring is +supported for development and tightly controlled deployments through +`GOVOPLAN_MODULE_PACKAGE_CATALOG_TRUSTED_KEYS_URL` plus +`GOVOPLAN_MODULE_PACKAGE_CATALOG_TRUSTED_KEYS_CACHE`, but production systems +should pin trusted keys locally. + +Catalog entries can declare `license_features`. If +`GOVOPLAN_LICENSE_ENFORCEMENT=true`, core blocks planning catalog installs +whose required features are not present in the configured offline license: + +```bash +GOVOPLAN_LICENSE_FILE=/srv/govoplan/license.json +GOVOPLAN_LICENSE_TRUSTED_KEYS_FILE=/srv/govoplan/trust/license-keyring.json +GOVOPLAN_LICENSE_ENFORCEMENT=true +``` + +See `docs/CATALOG_TRUST_AND_LICENSING.md` for key rotation, replay protection, +and licensing details. Unsigned catalogs remain usable for local development +when signature enforcement is off, but the admin UI labels them as unsigned. Install rows must use tagged package/git refs or registry packages, not local `file:` or workspace links. The installer daemon can run `npm install` and