activity-core/docs/release-broker.md
tegwick 22935955cc
All checks were successful
CI Smoke / host-smoke (push) Successful in 1s
CI Smoke / container-smoke (push) Successful in 3s
Build and Publish Container Image / build-and-push (push) Successful in 1m32s
Implement signed release admission and durable rollback coordinator
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a0e241-8285-7a63-8c0c-51c9cb824dc3
2026-09-27 16:39:29 +02:00

4.6 KiB

Image-only release broker core

ACTIVITY-WP-0041-T03 owns this implementation. Not activated in production. The new modules are not wired to an API, worker, schedule or credential source. Construction requires admitted=True from trusted deployment configuration; that switch is a local guard, not proof that an identity has actually been admitted. The current deployed revision is unchanged, so this code does not restart soak.

Implemented boundary

activity_core.release_broker.Receipts checks Ed25519 signatures against a locally configured key-to-principal/role registry. Requests cannot introduce trusted keys. Build, independent review, health and retention attestations must all name the same fixed repository/application, full candidate and rollback commits, and exact before/after manifest hashes. Evidence expires within five minutes. Build and review require different principals and keys. Build evidence must cover exact candidate image digests and all three mandatory CI contexts. Retention must cover both live and rollback images. Health must attest continuous healthy observation of the prior revision for at least 24 hours. The trusted issuers must verify these facts against their authorities; signatures alone cannot make assertions true.

gitops_policy is the shared image-only validator used by both broker and the existing CLI. It forbids non-image deployment changes and resource-set changes. release_operations constructs a one-field update of the validated platform child Application and fixed selective root/child sync payloads. No arbitrary command, repository path, application, prune flag or override is exposed by these builders.

Durable recovery

A local SQLite ledger stores signed receipts, their hashes, the release binding, phase and transition history. One active row and an immediate transaction serialize all releases and adapter calls on that ledger. The database must reside on durable, operator-owned local storage, shared by all instances handling this application; this is not a distributed lock across independent databases or network filesystems.

Phases are planned → publish_pending → published → synced → complete. Publication intent is committed before calling the adapter. Lost responses therefore cannot turn a possibly published change into an assumed cancellation. A release that expires before any attempt is cancelled; after intent, timeout or failed health enters rollback_planned → rollback_published → rollback_synced → rolled_back. Failed rollback retains the active slot. Retried publication/sync must be idempotent, using compare-and-swap and accepting already-at-target as success. The adapter must refuse any unexpected third revision rather than overwriting it.

Tests use generated fixture keys and an in-memory adapter. They prove policy and state-machine behavior, including restart and failed-health rollback; they are not proof of production Git/ArgoCD rollback or admitted authority.

Still required before activation

  1. Implement and verify an authenticated transport adapter that resolves exact source commits, compares rendered manifests to the signed hashes, publishes only the platform child revision field, and runs the fixed selective syncs. Every network operation needs a bounded timeout; health must wait within that bound for the exact revision and verify deployments, report sink and schedules. It must persist/recover the platform commit across lost responses and serialize with other writers. A generic repository-write token is not path enforcement.
  2. Admit the dedicated principal and credential custody through the owner lane. ArgoCD Core has no API-server token lane. Kubernetes Application patch RBAC alone cannot restrict fields: keep it behind the reviewed broker boundary. Publish negative access tests and revocation behavior; no broad operator key.
  3. Supply independent trusted build/review/health/retention issuers and their key custody/rotation. The observer must measure continuous health; it must not manufacture a 24-hour interval from two snapshots. Preserve signing public keys for audit and protect the ledger from producer writes.
  4. Connect the durable dispatcher through activity-core/Temporal and sanitized evidence sinks. Prove authenticated transport failure, concurrency with other publishers, restart, denial and rollback in an isolated deployment environment. Then finish the production observation gate and enable the bounded scope.

Platform enforcement contract: railiance-platform/docs/activity-core-release-admission.md. These requirements remain live work in ACTIVITY-WP-0041-T03 and RPF-WP-0048-T02.