Skip to content

Tell whether prod has converged on main from the published artifact's signed provenance #3846

Closed

Description

@devantler

🤖 Generated by the Agentic Engineer

Part of #2838. Also resolves the race #2828 described, which was closed as its duplicate.

Evidence

Audience and impact

This affects the platform operator and every service on the cluster. After that interleaving, prod silently runs an older revision than main until some unrelated change triggers another deploy. Nothing reports it, so the platform's GitOps promise ("prod is what main says") is quietly false.

Smallest useful change

Build a read-only resolver. Given :latest's digest, it verifies the provenance against the platform's own deploy workflow identity, takes the source commit, and reports one verdict:

Verdict Meaning
CONVERGED the commit is main's tip, or an ancestor of it with no deploy-input change since
BEHIND an ancestor of main, but deploy inputs changed since (the #2838 state)
DIVERGED not reachable from main: an ejected merge-group artifact (the #2026 state the heal already handles)
UNKNOWN any read or verification failure; never reported as CONVERGED

Deploy inputs are the k8s path filter in the changes job of .github/workflows/ci.yaml. The resolver reads them from that file rather than copying the list, so the two cannot drift.

This child is not wired into any workflow and changes nothing in production. The follow-up child uses the verdict to run a convergence deploy after a merge.

Acceptance criteria

  • A test proves each verdict against a fixture repository, including ablations that fail when the ancestry check or the deploy-input check is removed.
  • A test proves that an unverifiable, unreadable, or wrong-identity attestation yields UNKNOWN.
  • Reading the deploy-input paths from ci.yaml fails closed (UNKNOWN) when the filter block cannot be found or is empty.
  • The one-command invocation is documented, and a read against the current :latest digest and main reports CONVERGED.

Size

S–M: one Go command under scripts/ with tests, no workflow wiring.

Activity

  1. added theissue type on Sep 15, 2026
  2. moved this to 📥 Backlog in 🌊 Project Boardon Sep 15, 2026
  3. added a commit that references this issue on Sep 15, 2026
  4. moved this from 📥 Backlog to 🏃🏻‍♂️ In Progress in 🌊 Project Boardon Sep 15, 2026
  5. devantler commented on Sep 15, 2026

    @devantler
    ContributorAuthor

    🤖 Generated by the Agentic Engineer

    Resolver merged in #3847 (merged at a3bbe487; its merge-group deploy to prod succeeded).

    Acceptance criterion State
    Each verdict proven on a fixture repository, with ablations that fail when the ancestry or deploy-input check is removed Met. Four overlay ablations each fail exactly the tests that guard them.
    An unverifiable, unreadable or wrong-identity attestation yields UNKNOWN Met, covered by tests. A live run on a host without registry access printed UNKNOWN and exited 2.
    An unreadable or empty deploy-input filter yields UNKNOWN Met. One test also reads the repository's own ci.yaml, so a filter change the resolver cannot parse fails CI.
    Invocation documented; a live read of the current :latest digest reports CONVERGED Documented. The live read needs a runner with packages: read, so it is proven by the wiring follow-up, #3848.

    Two findings from review changed what the verdicts mean, and the package documentation now says so:

    • Heal artifacts: a signing certificate names the run's triggering commit, so an artifact published by the merge-group heal reads as DIVERGED although it holds main. Redeploying main is still the correct remedy, and it converges prod in one deploy.
    • Repeated attestations: a digest re-attested by several runs is judged commit by commit, and the least converged verdict wins, rather than returning UNKNOWN.

    This issue stays open until #3848 records the live CONVERGED read.

  6. devantler commented on Sep 16, 2026

    @devantler
    ContributorAuthor

    🤖 Generated by the Agentic Engineer

    Live acceptance point met. #3864 merged as 5e3049c9. Its first 🧭 Observe Production Convergence run on main (run 35150608562, job 104977674658) ran the resolver against the real :latest digest with the Actions token. The run annotated CONVERGED prod runs main 5e3049c91ae599d5b215da404b20b0622cac4ae2. With that live read recorded, all four acceptance criteria are met.

  7. moved this from 🏃🏻‍♂️ In Progress to ✅ Done in 🌊 Project Boardon Sep 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Fields

    Priority

    None yet

    Effort

    None yet

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions