Sync wiki from project files
191
Repo-docs-CATALOG-TRUST-AND-LICENSING.md
Normal file
191
Repo-docs-CATALOG-TRUST-AND-LICENSING.md
Normal file
@@ -0,0 +1,191 @@
|
||||
<!-- codex-wiki-sync:36e407f77dd59c0601fa5063 -->
|
||||
|
||||
> 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":"<base64 public key>"}'
|
||||
```
|
||||
|
||||
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
|
||||
@@ -1,4 +1,4 @@
|
||||
<!-- codex-wiki-sync:97f252ae80996d8ee236fd44 -->
|
||||
<!-- codex-wiki-sync:24b67ceb3231203599e59944 -->
|
||||
|
||||
> 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.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<!-- codex-wiki-sync:874f18ab843f9c893d212d76 -->
|
||||
<!-- codex-wiki-sync:e178a363f47dd4c65d49cb2c -->
|
||||
|
||||
> Mirrored from `/mnt/DATA/git/govoplan-core/docs/RELEASE_DEPENDENCIES.md`.
|
||||
> Origin: `repository`.
|
||||
@@ -198,19 +198,30 @@ govoplan-module-installer --cancel-request <request-id> --format json
|
||||
govoplan-module-installer --retry-request <request-id> --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":"<base64-ed25519-public-key>"}'
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user