Harden source release preparation and record verified security follow-up
This commit is contained in:
@@ -263,11 +263,198 @@ python tools/release/generate-developer-meta-package.py
|
||||
python tools/release/generate-developer-meta-package.py --check
|
||||
```
|
||||
|
||||
The direct generator is a development synchronization tool, not a receipt-gated
|
||||
release executor. For release preparation, use the guarded out-of-run stage below.
|
||||
|
||||
`push-release-tag.sh` performs this synchronization before release commits and
|
||||
tags. The meta-package is for editable/developer setup and composition tests. It
|
||||
does not enable modules, apply migrations, provision services, or establish
|
||||
backup and recovery evidence.
|
||||
|
||||
### Shared source-tag contract and Meta composition
|
||||
|
||||
The shared version collector names Meta's real
|
||||
`packages/govoplan-meta/pyproject.toml` separately from root `pyproject.toml`.
|
||||
Only the registered `govoplan` system/meta repository with nested project name
|
||||
`govoplan` receives this contract. Missing, unknown, or misidentified metadata
|
||||
does not become a versionless exception. Version alignment compares the complete
|
||||
nested file with the canonical operator-tool generator output: its version must
|
||||
match Core, and dependencies and `full` composition must match the reviewed
|
||||
requirements and workspace package versions. Validation never executes a
|
||||
generator from a selected checkout. The shared trusted manifest checker can
|
||||
load reviewed application manifests; these checks are not a code sandbox.
|
||||
|
||||
Meta's complete generated file is recognized by shared version-mutation discovery,
|
||||
but the generic durable version executor deliberately cannot write it. A durable
|
||||
run freezes the release console's own Meta checkout as trusted runtime code;
|
||||
changing it in place would invalidate that run. The planner therefore places Meta
|
||||
after Core and exposes only non-executable support preparation/publication steps,
|
||||
not misleading automatic Meta version, commit, tag, or push actions. A missing or
|
||||
different Core target produces an actionable preparation prerequisite.
|
||||
|
||||
Prepare Core and the intended module inputs first, commit their reviewed state,
|
||||
then stop active durable runs for the target workspace. Use trusted operator tools
|
||||
against a separate registered, private source checkout, never the running operator
|
||||
Meta directory. Preview outside any selected source checkout, for example:
|
||||
|
||||
```sh
|
||||
python tools/release/prepare-developer-meta-package.py \
|
||||
--workspace /private/release-workspace --target-version X.Y.Z \
|
||||
> /private/operator/meta-preview.json
|
||||
python tools/release/prepare-developer-meta-package.py \
|
||||
--workspace /private/release-workspace --target-version X.Y.Z \
|
||||
--receipt /private/operator/meta-preview.json --apply --confirm-out-of-run
|
||||
```
|
||||
|
||||
The explicit confirmation attests that no durable run is active for that target
|
||||
workspace; the helper does not discover or stop other processes. Preview/apply
|
||||
requires registered clean main sources, matching origins and live-main ancestry,
|
||||
Core already aligned at the target, the exact nested identity, and no existing or
|
||||
unverifiable target Meta tag. Frozen receipts cover source HEADs/filesystem
|
||||
identities, release requirements, every discovered registered full-composition
|
||||
pyproject, the trusted generator snapshot, and the resulting full-file hash.
|
||||
Inputs are limited to 128 selected files, 2 MiB per file and 16 MiB aggregate.
|
||||
The canonical generator renders copied bounded data in a temporary directory;
|
||||
no generator from the selected checkout executes. Changed receipts block before
|
||||
the file effect. Apply writes only `packages/govoplan-meta/pyproject.toml`, then
|
||||
rechecks the other sources and exact output. A write or post-check failure that
|
||||
may have changed the file reports `needs-reconciliation` and leaves that bounded
|
||||
delta for explicit review; it never retries, rolls back, commits or publishes.
|
||||
|
||||
Review the complete generated composition and manually commit the resulting file.
|
||||
Complete matching Core publication before guarded Meta source tagging/publication,
|
||||
then start a fresh durable run from reviewed, clean, published operator tooling.
|
||||
Hot self-updating durable Meta release execution remains explicitly unsupported;
|
||||
this out-of-run preparation is the existing developer-meta support contract.
|
||||
|
||||
For every `tag_repositories` batch, strict checks apply to every selected
|
||||
repository before any tag creation, fetch, or push: registered checkout and
|
||||
origin/push URL, a clean `main` tracking `origin/main`, live remote-main ancestry,
|
||||
exact frozen HEADs, and immutable annotated local/remote tag objects. Git metadata
|
||||
must remain inside the operator's trusted workspace. Missing local knowledge of
|
||||
live remote main is a blocker; fetch and review it separately. Unknown repositories
|
||||
and non-registered remote aliases fail closed. If selected, Meta runs last.
|
||||
For Meta only, the matching annotated Core release must exist before its effect; Core may be
|
||||
an earlier selected repository, or an already tagged dependency. Publication
|
||||
requires that Core's exact tag and main commit are already remote.
|
||||
|
||||
Non-Meta selections do not acquire Meta's composition or Core-tag prerequisite.
|
||||
Local module-candidate tags still work before Core's final release lock or tag.
|
||||
The existing Core WebUI bundle gate still applies to module publication and
|
||||
batches selecting Core: relevant Core release-package and release-lock inputs
|
||||
must be operator-owned regular files, at most 16 MiB each, and their identities
|
||||
and content hashes are frozen before preflight and rechecked before every effect.
|
||||
When Core is unselected, this does not require its checkout to be clean or tagged;
|
||||
reviewed pending composition inputs retain their previous meaning. Backend-only
|
||||
selections never read irrelevant Core WebUI files.
|
||||
|
||||
Before even read-only Git commands, source ancestry must be owned by root or the
|
||||
current operator and must not be group/world writable. A sticky shared ancestor
|
||||
such as `/tmp` is permitted only above an owned, protected child; the workspace
|
||||
and checkouts receive no writable-directory exception. The current operator must
|
||||
own source inputs and actual Git/worktree/common metadata, which must be regular
|
||||
files/directories, non-symlinked, and non-writable by other users. Metadata walks
|
||||
are bounded to 500,000 entries and 128 levels, and tracked inputs to 100,000 paths
|
||||
and 16 MiB of listing text. Read-only Git targets, object alternates/grafts and
|
||||
hidden/sparse/unmerged index entries are blocked. Frozen receipts include actual
|
||||
checkout/Git directory paths, devices, inodes, owners and modes, so replacing Git
|
||||
metadata with the same HEAD is still detected. All selected version/composition
|
||||
inputs must be tracked, including root and WebUI package/lock metadata, discovered
|
||||
module manifests and package initializers, and Meta's nested package and release
|
||||
requirements; ignored working files cannot supply declarations absent from a tag.
|
||||
No chmod, ownership repair or
|
||||
global Git trust change is performed. A shared writable workspace must first be
|
||||
recreated or reviewed in the operator's protected release area by an explicitly
|
||||
authorized preparation workflow.
|
||||
|
||||
Preview is read-only. Local-tag mode creates only pinned annotated tags (or
|
||||
retrieves an identical published annotation); it does not publish main or tags.
|
||||
Publish mode atomically pushes the frozen main commit and annotation object,
|
||||
without force, retagging, fallback, or automatic retry. The complete source
|
||||
receipt is rechecked before every effect and afterward; remote main and the
|
||||
exact annotated tag must both match, not merely the Git exit status. Changes
|
||||
after preflight stop the remaining batch. Atomicity is per repository, not
|
||||
across repositories: earlier successful publications and a newly created local
|
||||
tag can remain after a later failure. Inspect reported receipts and obtain a new
|
||||
review before retrying; do not move immutable tags.
|
||||
|
||||
Whole-batch revalidation deliberately repeats source and live-remote checks around
|
||||
each repository effect; the number of checks can grow quadratically with batch
|
||||
size. Plan release time accordingly rather than bypassing trust checks. The
|
||||
shared internal preflight is read-only and exposes no legacy mutation path.
|
||||
The fixture suite covers Meta and non-Meta preview/local-tag/
|
||||
publication using temporary local bare remotes, including stale compositions,
|
||||
unsafe origins, divergent branches, damaged tag identity, changed receipts and
|
||||
false publication success. This is local tooling evidence, not a real release
|
||||
publication or production permission check.
|
||||
|
||||
Deutsch: Die gemeinsamen Helfer erkennen ausschließlich das registrierte
|
||||
Meta-Repository mit dem echten Paket `packages/govoplan-meta/pyproject.toml`
|
||||
(Projektname `govoplan`). Version und vollständige Zusammensetzung müssen dem
|
||||
kanonischen Generator, Core und den geprüften Anforderungen entsprechen; der
|
||||
Generator stammt niemals aus dem ausgewählten Checkout. Der gemeinsame
|
||||
Manifestprüfer kann geprüften Anwendungscode laden und ist keine Sandbox.
|
||||
Die gemeinsame Änderungsplanung erkennt die vollständig generierte Paketdatei,
|
||||
aber der dauerhafte Versionsausführer darf Meta nicht selbst verändern: sein
|
||||
eingefrorener Lauf bindet den Meta-Checkout als vertrauenswürdigen Programmstand.
|
||||
Meta erscheint deshalb nach Core ausschließlich mit nicht automatisch ausführbaren
|
||||
Vorbereitungs-/Veröffentlichungsschritten. Zuerst Core und Modulquellen vorbereiten
|
||||
und geprüft committen; bei abweichender Core-Zielversion nennt der Plan diese
|
||||
Voraussetzung ausdrücklich. Aktive dauerhafte Läufe des Ziel-Workspaces beenden.
|
||||
Mit `prepare-developer-meta-package.py` zunächst eine Vorschau außerhalb der
|
||||
Quell-Checkouts speichern, dann deren JSON über `--receipt` zusammen mit `--apply`
|
||||
und `--confirm-out-of-run` bestätigen. Das Ziel muss ein separater registrierter
|
||||
privater Checkout sein, niemals das laufende Operator-Meta. Die Bestätigung ist
|
||||
eine Betreibererklärung; der Helfer sucht oder beendet keine fremden Prozesse.
|
||||
Quell-HEADs, Pfadidentitäten, Anforderungen, alle registrierten vollständigen
|
||||
Paket-Eingaben, der vertrauenswürdige Generator und der vollständige Ausgabehash
|
||||
werden eingefroren. Es gelten höchstens 128 Quelldateien, 2 MiB je Datei und
|
||||
16 MiB insgesamt. Core muss bereits vollständig zur Zielversion passen; vorhandene
|
||||
oder nicht verifizierbare Meta-Zieltags sperren die Vorbereitung. Geänderte
|
||||
Nachweise stoppen vor dem Schreiben. Ausschließlich die verschachtelte Paketdatei
|
||||
wird vollständig generiert und danach geprüft; ein Fehler nach dem Schreiben
|
||||
meldet `needs-reconciliation` und erfordert die manuelle Prüfung dieser begrenzten
|
||||
Änderung, ohne automatisches Zurücksetzen. Kein automatischer
|
||||
Commit, Push oder Wiederholungsversuch findet statt. Zusammensetzung prüfen,
|
||||
manuell committen, Core zuerst veröffentlichen, dann die geschützte Meta-Tag-Route
|
||||
verwenden und einen neuen dauerhaften Lauf starten. Eine Selbstaktualisierung
|
||||
des aktiven dauerhaften Meta-Laufs bleibt ausdrücklich nicht unterstützt.
|
||||
Für jeden Tag-Stapel, auch ohne Meta, gelten
|
||||
Vertrauens-, Origin-, saubere Main- und Live-Abstammungsprüfungen für die gesamte
|
||||
Auswahl vor jeder Änderung. Unbekannte Repositories und nicht registrierte
|
||||
Remote-Aliase sind gesperrt. Nur bei ausgewähltem Meta gelten zusätzlich dessen
|
||||
Zusammensetzungsprüfung und der passende annotierte Core-Tag als Voraussetzung;
|
||||
Meta folgt zuletzt. Für Metas Veröffentlichung müssen Core-Tag und Main-Commit
|
||||
bereits auf dem Remote vorliegen. Lokale Modul-Kandidatentags bleiben vor Cores
|
||||
abschließendem Release-Lock und Tag möglich. Die vorhandene Core-WebUI-Bundleprüfung
|
||||
bleibt bei Modulveröffentlichung und Core-Auswahl erhalten. Relevante Core-Paket-
|
||||
und Lockdateien müssen eigene reguläre Dateien mit höchstens je 16 MiB sein;
|
||||
Identität und Inhaltshash werden eingefroren und vor jeder Aktion erneut geprüft.
|
||||
Nicht ausgewähltes Core benötigt dafür weder einen sauberen Checkout noch einen
|
||||
Tag. Reine Backend-Auswahlen lesen keine irrelevanten Core-WebUI-Dateien.
|
||||
Vor Git-Aufrufen werden Eigentümer, Schreibrechte, sichere
|
||||
Pfadabstammung und echte Git-/Worktree-Metadaten geprüft; veränderbare gemeinsame
|
||||
Verzeichnisse, fremde Eigentümer, Alternates, Grafts und versteckte Indexeinträge
|
||||
sind gesperrt. Ein Sticky-Bit-Vorfahr wie `/tmp` ist nur oberhalb eines eigenen
|
||||
geschützten Unterverzeichnisses zulässig. Es erfolgen weder Rechtereparaturen
|
||||
noch globale Git-Vertrauensänderungen. Ausgewählte Versions- und Zusammensetzungs-
|
||||
dateien müssen versioniert sein: Paket-/Lockdateien, Modulmanifeste und
|
||||
Paketinitialisierer sowie Metas verschachteltes Paket und Release-Anforderungen.
|
||||
Ignorierte Arbeitsdateien dürfen keine vom Tag abweichenden Angaben liefern.
|
||||
Die Vorschau schreibt nichts, lokale Tags veröffentlichen nichts,
|
||||
und die Veröffentlichung überträgt Main und den exakten annotierten Tag atomar
|
||||
je Repository. Unmittelbar vor und nach den Aktionen werden die eingefrorenen
|
||||
Quellnachweise erneut geprüft, einschließlich entferntem Main und Tag-Objekt.
|
||||
Bei Änderungen oder Fehlern stoppt der Rest des Stapels ohne automatischen
|
||||
Wiederholungsversuch. Frühere Veröffentlichungen und neu erzeugte lokale Tags
|
||||
können bestehen bleiben: vor einem neuen Versuch Nachweise prüfen und erneut
|
||||
freigeben, niemals unveränderliche Tags verschieben. Die vollständigen Quell- und
|
||||
Live-Remote-Prüfungen werden um jede Aktion wiederholt; bei großen Stapeln kann
|
||||
deren Anzahl quadratisch wachsen. Diese konservativen Prüfkosten gehören zur
|
||||
Release-Planung. Der interne Vorprüfer ist ausschließlich lesend und besitzt
|
||||
keinen alten Änderungspfad. Tests für Auswahlen mit und ohne Meta verwenden
|
||||
nur temporäre lokale Remotes und ersetzen keine echte Veröffentlichungsprüfung.
|
||||
|
||||
If the tag-triggered developer meta-package job fails before publication, rerun
|
||||
`publish-developer-meta-package.yml` with the existing protected version. The
|
||||
manual path validates that tag against `main`, checks out its exact commit, and
|
||||
|
||||
Reference in New Issue
Block a user