Publish complete signed module catalogs
Dependency Audit / dependency-audit (push) Successful in 1m46s
Deployment Installer / deployment-installer (push) Successful in 5s
Security Audit / security-audit (push) Successful in 11m49s

This commit is contained in:
2026-08-06 21:13:33 +02:00
parent f3cfd1bccc
commit 09046e6e62
17 changed files with 666 additions and 394 deletions
@@ -267,7 +267,7 @@ inspection is authorized.
The complete installation and lifecycle journey is specified in the
[System Administrator Lifecycle User Story](SYSTEM_ADMINISTRATOR_LIFECYCLE_USER_STORY.md):
one-command Core-only bootstrap, signed online module installation and updates,
one-command Core-baseline bootstrap, signed online module installation and updates,
stateless scale-out, versioned configuration transfer, undo, and reproducible
environment-promotion recipes.
@@ -977,7 +977,8 @@ Priorities:
1. Deliver the first slices of the
[System Administrator Lifecycle User Story](SYSTEM_ADMINISTRATOR_LIFECYCLE_USER_STORY.md):
a verified Core-only distribution, first-run control plane, read-only online
a verified full-package distribution with only the Core baseline active,
first-run control plane, read-only online
module directory, and durable plan/confirm/install progress.
2. Pin and publish a compatible Core/WebUI/module composition and first
reference configuration package.
+16
View File
@@ -38,6 +38,22 @@ The K3s VM lab has two modes over the same Kubernetes profile:
- `acceptance` requires independently controlled worker failure domains and can
contribute target evidence.
## Module composition and availability
Official immutable API and WebUI images carry the verified `full` package
profile. This is package availability, not runtime activation and not a license
or tenant entitlement. The signed distribution manifest records the complete
package composition; the desired module graph selects which installed modules
are active; tenant module policy applies unavailable/available/forced ceilings;
and Views/Policy control group and user presentation.
Local and single-host profiles may use the supervised installer to download a
signed catalog artifact into a private digest cache and mutate the local package
environment during maintenance. A multi-host/shared-state profile must never
change one replica in place. Its Admin install plan is a composition request:
publish and roll out a new signed image whose package lock contains the target,
then activate the module graph after all replicas report the same composition.
## Component Choices
The installer may manage a component where its bounded profile is appropriate,
+58 -13
View File
@@ -136,31 +136,38 @@ allow the same least-privilege credential to serve every module workflow.
## Exact release consumption
`tools/release/generate-release-package-set.py` translates the reviewed Git
source refs in `requirements-release.txt` into an exact registry package set.
It resolves each version tag to its commit and verifies the package metadata in
that tag.
`tools/release/generate-release-package-set.py` supports two explicit package
profiles. `base` translates the reviewed roots in `requirements-release.txt`;
`full` reads the exact `govoplan[full]` dependency set from the developer
meta-package. Both profiles resolve every version tag to its commit and verify
the package metadata from that exact Git tree. The official module directory
and immutable runtime distribution use `full`, so every publicly released
module can be discovered without rebuilding the application image.
`tools/release/resolve-package-artifacts.py` then downloads exactly those wheel
and WebUI versions from Gitea. It reads the identity embedded in every wheel and
npm tarball, rejects missing, duplicate, unexpected, or oversized artifacts,
and writes `package-artifacts.lock.json` with SHA-256 values and npm integrity
values. Credentials are accepted only through environment variables and are
and writes `package-artifacts.lock.json` with credential-free HTTPS download
URLs, SHA-256 values, and npm registry integrity values. The resolver verifies
that the bytes downloaded by `npm pack` match the registry's own integrity
record. Credentials are accepted only through environment variables and are
never written to the lock. Python resolution ignores ambient pip configuration
and extra indexes for GovOPlaN roots, preventing an internal package name from
being selected from an undeclared registry.
The runtime distribution workflow uses the verified wheelhouse directly and
installs module WebUI tarballs only after matching them to the lock. It publishes
the package set, package lock, and hash-locked requirements as release assets.
The runtime distribution workflow uses the verified full-profile wheelhouse
directly and installs every selected module WebUI tarball only after matching
it to the lock. It publishes the package set, package lock, and hash-locked
requirements as release assets.
The WebUI installer receives the absolute runtime-build interpreter path so its
directory changes cannot escape the isolated release environment.
Gitea 1.24 dispatches this workflow from a branch, but that branch is only the
workflow implementation. The job fetches and peels the protected `v<version>`
tag explicitly, then binds both the signed distribution source and the Gitea
release assets to that exact commit. A post-tag workflow repair can therefore
retry publication without relabelling the later branch commit as released
source.
tag explicitly and materializes both `requirements-release.txt` and the
developer meta-package from that Git tree. It then binds the signed distribution
source and Gitea release assets to the same exact commit. A post-tag workflow
repair can therefore retry publication without changing the released package
composition or relabelling the later branch commit as released source.
The package-lock SHA-256 is part of the signed distribution manifest. Runtime
finalization also requires the lock's package versions and hashes to match the
wheel composition embedded in the images. OCI assembly remains network-free
@@ -170,6 +177,44 @@ The source refs remain in the module catalog for source provenance and release
planning. Production installation consumes the signed runtime images rather
than invoking `pip`, `npm`, or Git on the target host.
## Public module directory
`tools/release/publish-release-catalog.sh` resolves the selected package set and
registry lock before it creates a catalog. Catalog entries are synthesized from
the exact tagged module manifests, never from a hand-maintained module list or
the current workspace. Each entry binds its Python wheel and optional WebUI
tarball to the registry URL, filename, size, SHA-256, package identity, source
tag, and source commit before the complete catalog is signed.
Official GovOPlaN modules are open-source directory entries and do not require
license entitlements. The generic `license_features` contract remains available
for third-party package directories, support/configuration packages, or future
deployment-specific presets. A catalog entry is gated only when that entry
explicitly declares such features.
Core carries the public stable catalog URL and its independently pinned trust
anchor. In the absence of an operator-configured catalog, Admin discovers the
official directory automatically. Selecting an entry creates a reviewed
install/update plan; the trusted installer downloads the exact signed artifacts
into a private digest cache, verifies size and hash, and installs only from that
cache. A saved plan is rejected if any package ref, artifact identity, catalog
channel, sequence, or signing-key identity differs from the currently validated
catalog.
Package lifecycle and availability are intentionally separate:
- install, update, and uninstall change the instance-wide package composition;
- enable and disable change the active instance runtime graph;
- tenant module entitlements define unavailable, available, and forced modules;
- group/user presentation is governed through Views and Policy; and
- enabling a capability module does not opt data into that capability.
Single-process or single-host installations may execute a supervised package
plan locally. Shared-state and Kubernetes profiles reject node-local package
mutation: operators compose and roll out a new signed full-profile runtime image
instead. This prevents replicas from drifting while retaining the same Admin
catalog and preflight experience.
## Developer meta-package
`packages/govoplan-meta` builds the optional `govoplan` package. Its default
@@ -4,7 +4,8 @@
> As a system administrator, I can execute one shell command that downloads a
> verified GovOPlaN distribution and starts a completely configured Core control
> plane without optional modules. In the WebUI I can browse compatible signed
> plane with the official package directory available but only the protected
> baseline active. In the WebUI I can browse compatible signed
> module releases, select the modules for this installation, and follow every
> download, validation, migration, installation, activation, and health-check
> step. When an update is available, I can review its impact and confirm it.
@@ -25,7 +26,8 @@ The canonical backlog item is
- **Core control plane:** the smallest bootable distribution: Core API, Core
WebUI, PostgreSQL, Redis, installer worker, migration runner, and durable
storage configuration. No optional GovOPlaN module package is installed.
storage configuration. An immutable image may carry the full verified package
profile, but optional modules are not active or tenant-entitled by implication.
- **Bootstrap administrator:** a single-use, time-limited installation identity
that may access only first-run and module-lifecycle functions. It is retired
when the selected identity/access configuration becomes healthy.
@@ -55,7 +57,9 @@ The canonical backlog item is
5. It prints the local URL and one-time bootstrap credential. Re-running the
command is idempotent and shows or repairs the existing installation rather
than creating another identity or database.
6. No optional module is installed or enabled at this point.
6. Only the protected baseline is enabled. Installed package availability does
not grant permissions, tenant entitlement, View visibility, or capability
opt-in.
### Module selection, installation, and update
@@ -160,19 +164,22 @@ Implementation status as of the current source tree:
ledger and deployment operation journal. Automatic database backup and broad
adoption by module-owned external effects remain open work.
1. **Reproducible Core-only distribution.** Publish pinned multi-architecture
images, signed distribution manifest, Core-only Compose profile, bootstrap
1. **Reproducible Core-baseline distribution.** Publish pinned multi-architecture
full-package images, signed distribution manifest, Core-baseline Compose profile, bootstrap
preflight, generated secrets, readiness, and idempotent rerun/repair.
2. **First-run control plane.** Add the restricted bootstrap administrator,
one-time enrollment, initial catalog/keyring configuration, and retirement
after durable administrator access is established.
3. **Read-only online module directory.** Move the existing catalog and module
directory contracts into the installed Core WebUI with compatibility,
provenance, release-note, and update-state presentation.
4. **Durable module plan and install.** Reuse the existing installer queue,
locks, signed-package validator, rollback drill, and run evidence behind a
plan/confirm/progress UI. Add initial catalog-entry synthesis and artifact
acquisition where the current release console still assumes local sources.
3. **Read-only online module directory (implemented foundation).** Admin falls
back to the signed public stable directory, presents installed/update state,
compatibility and provenance, and retains operator-configured catalogs as an
explicit override.
4. **Durable module plan and install (implemented local boundary).** Catalog
selection creates a reviewed plan; the installer queue, lock, preflight,
maintenance gate, digest-verified artifact cache, rollback drill, and run
evidence remain separate from the API process. Shared deployments convert
the same intent into a new immutable release composition instead of mutating
one replica.
5. **Safe module update.** Add drain/maintenance coordination, backup gate,
migration compatibility window, reconnectable progress, health verification,
retry/recovery, and update notification.
@@ -194,7 +201,8 @@ Implementation status as of the current source tree:
## Explicit non-goals for the first distribution slice
- Shipping optional modules in the Core image.
- Activating, tenant-entitling, or exposing optional modules merely because the
immutable image carries their verified packages.
- Exporting secrets or production business data with configuration.
- Pretending every schema migration can be reversed automatically.
- Building a proprietary orchestrator instead of supporting Compose and a