# Release Catalog Workflow GovOPlaN release catalogs are published by `govoplan-web` as static JSON and verified by `govoplan-core` before installer plans are accepted. Private signing keys must stay outside all git repositories. Public keyrings are published with the website. ## One-Time Key Setup Create the first catalog signing key on the release machine: ```bash cd /mnt/DATA/git/govoplan-core KEY_DIR="$HOME/.config/govoplan/release-keys" mkdir -p "$KEY_DIR" ./.venv/bin/python scripts/generate-catalog-keypair.py \ --key-id release-key-1 \ --private-key "$KEY_DIR/release-key-1.pem" \ --public-key "$KEY_DIR/release-key-1.pub" \ --keyring "$KEY_DIR/catalog-keyring.json" ``` Keep `release-key-1.pem` private. The generated keyring contains only public material. ## Publish Current Release Catalog Generate the signed catalog into `govoplan-web`: ```bash cd /mnt/DATA/git/govoplan-core KEY_DIR="$HOME/.config/govoplan/release-keys" scripts/publish-release-catalog.sh \ --version 0.1.4 \ --sequence 202607071340 \ --catalog-signing-key "release-key-1=$KEY_DIR/release-key-1.pem" \ --build-web ``` This writes: - `/mnt/DATA/git/govoplan-web/public/catalogs/v1/channels/stable.json` - `/mnt/DATA/git/govoplan-web/public/catalogs/v1/keyring.json` The wrapper validates the catalog with core using the generated public keyring. ## Publish After A New Release For normal module/core releases, first tag and push the module/core repos. Then publish the website catalog: ```bash cd /mnt/DATA/git/govoplan-core KEY_DIR="$HOME/.config/govoplan/release-keys" scripts/publish-release-catalog.sh \ --version \ --catalog-signing-key "release-key-1=$KEY_DIR/release-key-1.pem" \ --build-web \ --commit \ --tag \ --push ``` The website tag is `catalog-v`. The public URL is: ```text https://govoplan.add-ideas.de/catalogs/v1/channels/stable.json ``` The public keyring URL is: ```text https://govoplan.add-ideas.de/catalogs/v1/keyring.json ``` ## Integrated Release Script `scripts/push-release-tag.sh` can publish the web catalog after module and core tags have been pushed: ```bash cd /mnt/DATA/git/govoplan-core KEY_DIR="$HOME/.config/govoplan/release-keys" scripts/push-release-tag.sh \ --bump subversion \ --publish-web-catalog \ --catalog-signing-key "release-key-1=$KEY_DIR/release-key-1.pem" \ --build-web-catalog ``` Use `--catalog-signing-key` more than once during a key rotation window. The catalog will contain multiple signatures and the public keyring will include the corresponding public keys. ## Consumer Configuration On a GovOPlaN installation that should consume the official stable catalog: ```bash GOVOPLAN_MODULE_PACKAGE_CATALOG_URL=https://govoplan.add-ideas.de/catalogs/v1/channels/stable.json GOVOPLAN_MODULE_PACKAGE_CATALOG_CACHE=/srv/govoplan/runtime/catalog-cache/stable.json GOVOPLAN_MODULE_PACKAGE_CATALOG_REQUIRE_SIGNATURE=true GOVOPLAN_MODULE_PACKAGE_CATALOG_APPROVED_CHANNELS=stable GOVOPLAN_MODULE_PACKAGE_CATALOG_TRUSTED_KEYS_FILE=/srv/govoplan/trust/catalog-keyring.json GOVOPLAN_MODULE_PACKAGE_CATALOG_SEQUENCE_STATE=/srv/govoplan/runtime/catalog-sequences.json GOVOPLAN_MODULE_PACKAGE_CATALOG_ENFORCE_SEQUENCE=true ``` For production, copy the public keyring into deployment configuration and pin it locally. Do not rely on a URL-fetched keyring as the only trust root. ## Core Updates `stable.json` includes a top-level `core_release` section for operator/update tooling. Core is intentionally not listed as a normal module entry, because it must not be added to saved enabled-module state. Core upgrades should remain an operator-supervised package update with restart and health checks. ## Key Rotation 1. Generate the next private key outside git. 2. Run `publish-release-catalog.sh` with both signing keys. 3. Publish the web catalog/keyring. 4. Roll the new public keyring into installations. 5. Stop signing with the old key after the supported fleet trusts the new key. 6. Mark compromised keys as revoked in the public keyring and publish a higher sequence catalog signed by a trusted uncompromised key.