Publish complete signed module catalogs
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user