Add atomic runtime tuple promotion gate

This commit is contained in:
2026-07-18 14:14:41 -07:00
parent b84432f989
commit a640f44972
7 changed files with 995 additions and 5 deletions

View File

@@ -25,6 +25,63 @@ Promotion is a reviewed manifest change that moves the old `current` tuple to
merged and deployed separately. Workflows in this repository have no deploy
credentials or deploy steps.
Use the repository promotion command; do not hand-edit the three tuple slots.
It binds evidence to a canonical SHA-256 of the complete tuple, requires full
consumer and gem commits, rejects mutable runtime image coordinates, and writes
the manifest with a same-filesystem atomic rename. The command only changes
`manifests/runtime-tuples.json`; it cannot deploy a consumer.
First inspect the fingerprints for both the candidate and rollback tuple:
```sh
ruby scripts/promote_runtime_tuple.rb fingerprint \
--consumer travelwolf \
--consumer-commit FULL_40_CHARACTER_CONSUMER_COMMIT
```
Commit one or more JSON evidence documents under `evidence/`. Each document
must explicitly contain values matching the promotion:
```json
{
"schema_version": 1,
"consumer": "travelwolf",
"profile": "rails-persisted-turn",
"consumer_commit": "FULL_40_CHARACTER_CONSUMER_COMMIT",
"status": "pass",
"certified_at": "2026-07-18T12:00:00Z",
"tuple_sha256": "sha256:FULL_64_CHARACTER_FINGERPRINT"
}
```
Preview the exact manifest transition with `--dry-run`, then repeat without it
to write the manifest:
```sh
ruby scripts/promote_runtime_tuple.rb promote \
--consumer travelwolf \
--consumer-commit FULL_40_CHARACTER_CONSUMER_COMMIT \
--status pass \
--certified-at 2026-07-18T12:00:00Z \
--evidence evidence/travelwolf-candidate.json \
--previous-status pass \
--previous-certified-at 2026-07-17T12:00:00Z \
--previous-evidence evidence/travelwolf-rollback.json \
--dry-run
```
The `--previous-*` arguments are required while the old `current` tuple lacks a
valid certification record. Later promotions reuse and revalidate that record.
Both candidate and previous evidence must match the printed tuple fingerprint,
consumer, full consumer commit, timestamp, and `pass` status. A tag may be kept
only in a `tag_provenance` field; `image`, `registry_ref`, and base image fields
must use `image@sha256:...`, while a private local artifact may use an exact
`docker_image_id`.
The command clears `candidate` after promotion. It sets the repository-wide
`migration_state` to `certified` only after every consumer has certified
`current` and `previous` tuples and no pending candidate.
## Rollback
Rollback restores the whole `previous` tuple. Do not roll back only the gem or