docs(openspec): propose release-tools-image change with adversarial review #155

Merged
goern merged 0 commits from refs/pull/155/head into main 2026-05-25 14:01:07 +00:00
goern commented 2026-05-25 13:57:52 +00:00 (Migrated from codeberg.org)

Summary

Proposes a dedicated release-tools OCI image to replace the runtime-install pattern in the op1st Tekton release Tasks. Three live release attempts (v2.24.0/1/2) failed at distinct steps because tools were installed at Step runtime in stock images with mismatched assumptions (step-isolation, GOCACHE-in-workspace, distroless cosign).

Tracks bead forgejo-mcp-1b4 (P0). This PR is proposal-only — no Containerfile, no pipelines, no code yet. Implementation follows once design lands.

What's in this PR

  • openspec/changes/release-tools-image/proposal.md — the why and scope
  • openspec/changes/release-tools-image/design.md — base-image choice (Hummingbird), CEL gating, versioning policy, secrets, signing posture, registry path, isolation contract
  • openspec/changes/release-tools-image/tasks.md — task breakdown + acceptance criteria
  • openspec/changes/release-tools-image/specs/release-tools-image/spec.md — capability spec with scenarios
  • openspec/changes/release-tools-image/review.md — full adversarial review synthesis (see below)

openspec validate release-tools-image passes.

Key design decisions

  • Base: registry.access.redhat.com/hi/go:<ver>-builder (Project Hummingbird, Red Hat hardened images). Builder variant retains bash + dnf for layering syft / goreleaser / cosign / node / jq / curl.
  • Structural isolation: every introduced path lives under image/release-tools/ or .tekton/release-tools/. Lift-to-separate-repo = git mv of those two trees + the 5 operator actions enumerated in spec.md.
  • CEL gates: PR build fires on files.any.exists(p, p.matches("^(image/release-tools/|\\.tekton/release-tools/).*")); tag publish on target_branch.matches("^refs/tags/release-tools/v.*"). Tag scheme release-tools/vMAJOR.MINOR.PATCH won't collide with v* forgejo-mcp tags.
  • Versioning policy: image-API semver (MAJOR = base swap / removed tool / broken CLI; MINOR = added tool / Hummingbird bump / Go minor; PATCH = tool patches). Avoids Renovate treadmill.
  • Signing: cosign-sign by digest first, then promote tag (closes TOCTOU window). Image pipeline mounts cosign-signing-key with optional: false (fail-closed) — diverges intentionally from the release artifact pipeline's fail-open posture.
  • npm: committed package-lock.json + npm ci --ignore-scripts + SHA256 in VERSIONS.md. No live npm registry pull at build time.

Adversarial review applied

A team:debate pass (devils-advocate + supply-chain lens + proponent) produced 14 critiques. Defender response: 0 outright defends, 9 patches applied in-tree, 5 future-work items filed as blocked beads, 1 stalemate resolved as referee call.

Full synthesis: openspec/changes/release-tools-image/review.md.

Future-work beads (blocked on forgejo-mcp-1b4)

ID Origin Concern
forgejo-mcp-aun (P1) A6 + L6 Hummingbird base CVE response cadence + scheduled rescan
forgejo-mcp-3h2 (P1) L2 go install + curl installs lack SHA256 verify
forgejo-mcp-j52 (P1) L4 Shared cosign keypair — split image-signing from artifact-signing
forgejo-mcp-46j (P2) L5 SLSA provenance via Tekton Chains (deployed but unused)

Per the proposal's acceptance criteria, these MUST be filed before merge (done — all visible via bd blocked).

Out of scope (deferred to follow-up change release-pipeline-use-release-tools-image)

  • Rewriting .tekton/tasks/goreleaser-release.yaml, cosign-sign-release.yaml, mcpb-pack.yaml to reference the image
  • Dropping the /tmp GOCACHE workaround
  • Cutting a clean release as the first end-to-end-clean Tekton run

Open questions for reviewer

  • Final registry path: quay.io/operate-first/release-tools, ghcr.io/..., codeberg.org/...? Needs op1st-emea-b4mad maintainer decision before publish pipeline can land.
  • PaC controller version in op1st-pipelines ≥ 0.22.0 (required for files.any CEL)? Needs verification before merge — tasks.md item 3.3.

Test plan

This is a proposal-only PR. No code to test. Validate via:

  • openspec validate release-tools-image (passes)
  • Reviewer reads proposal.mddesign.mdreview.mdspec.mdtasks.md in that order
  • All 4 future-work beads visible in bd blocked and depend on forgejo-mcp-1b4
  • Reviewer flags any A8-style stalemate they'd resolve differently
  • Registry path decision recorded (comment on this PR or in a separate ADR amendment) before implementation PR opens
## Summary Proposes a dedicated **release-tools** OCI image to replace the runtime-install pattern in the op1st Tekton release Tasks. Three live release attempts (`v2.24.0/1/2`) failed at distinct steps because tools were installed at Step runtime in stock images with mismatched assumptions (step-isolation, GOCACHE-in-workspace, distroless cosign). Tracks bead **`forgejo-mcp-1b4`** (P0). This PR is **proposal-only** — no Containerfile, no pipelines, no code yet. Implementation follows once design lands. ## What's in this PR - `openspec/changes/release-tools-image/proposal.md` — the why and scope - `openspec/changes/release-tools-image/design.md` — base-image choice (Hummingbird), CEL gating, versioning policy, secrets, signing posture, registry path, isolation contract - `openspec/changes/release-tools-image/tasks.md` — task breakdown + acceptance criteria - `openspec/changes/release-tools-image/specs/release-tools-image/spec.md` — capability spec with scenarios - `openspec/changes/release-tools-image/review.md` — full adversarial review synthesis (see below) `openspec validate release-tools-image` passes. ## Key design decisions - **Base**: `registry.access.redhat.com/hi/go:<ver>-builder` (Project Hummingbird, Red Hat hardened images). Builder variant retains bash + dnf for layering syft / goreleaser / cosign / node / jq / curl. - **Structural isolation**: every introduced path lives under `image/release-tools/` or `.tekton/release-tools/`. Lift-to-separate-repo = `git mv` of those two trees + the 5 operator actions enumerated in spec.md. - **CEL gates**: PR build fires on `files.any.exists(p, p.matches("^(image/release-tools/|\\.tekton/release-tools/).*"))`; tag publish on `target_branch.matches("^refs/tags/release-tools/v.*")`. Tag scheme `release-tools/vMAJOR.MINOR.PATCH` won't collide with `v*` forgejo-mcp tags. - **Versioning policy**: image-API semver (MAJOR = base swap / removed tool / broken CLI; MINOR = added tool / Hummingbird bump / Go minor; PATCH = tool patches). Avoids Renovate treadmill. - **Signing**: cosign-sign by digest first, then promote tag (closes TOCTOU window). Image pipeline mounts `cosign-signing-key` with `optional: false` (fail-closed) — diverges intentionally from the release artifact pipeline's fail-open posture. - **npm**: committed `package-lock.json` + `npm ci --ignore-scripts` + SHA256 in VERSIONS.md. No live npm registry pull at build time. ## Adversarial review applied A `team:debate` pass (devils-advocate + supply-chain lens + proponent) produced 14 critiques. Defender response: 0 outright defends, 9 patches applied in-tree, 5 future-work items filed as blocked beads, 1 stalemate resolved as referee call. Full synthesis: `openspec/changes/release-tools-image/review.md`. ### Future-work beads (blocked on `forgejo-mcp-1b4`) | ID | Origin | Concern | |---|---|---| | `forgejo-mcp-aun` (P1) | A6 + L6 | Hummingbird base CVE response cadence + scheduled rescan | | `forgejo-mcp-3h2` (P1) | L2 | `go install` + `curl` installs lack SHA256 verify | | `forgejo-mcp-j52` (P1) | L4 | Shared cosign keypair — split image-signing from artifact-signing | | `forgejo-mcp-46j` (P2) | L5 | SLSA provenance via Tekton Chains (deployed but unused) | Per the proposal's acceptance criteria, these MUST be filed before merge (done — all visible via `bd blocked`). ## Out of scope (deferred to follow-up change `release-pipeline-use-release-tools-image`) - Rewriting `.tekton/tasks/goreleaser-release.yaml`, `cosign-sign-release.yaml`, `mcpb-pack.yaml` to reference the image - Dropping the `/tmp` GOCACHE workaround - Cutting a clean release as the first end-to-end-clean Tekton run ## Open questions for reviewer - Final registry path: `quay.io/operate-first/release-tools`, `ghcr.io/...`, `codeberg.org/...`? Needs op1st-emea-b4mad maintainer decision before publish pipeline can land. - PaC controller version in `op1st-pipelines` ≥ 0.22.0 (required for `files.any` CEL)? Needs verification before merge — `tasks.md` item 3.3. ## Test plan This is a proposal-only PR. No code to test. Validate via: - [ ] `openspec validate release-tools-image` (passes) - [ ] Reviewer reads `proposal.md` → `design.md` → `review.md` → `spec.md` → `tasks.md` in that order - [ ] All 4 future-work beads visible in `bd blocked` and depend on `forgejo-mcp-1b4` - [ ] Reviewer flags any A8-style stalemate they'd resolve differently - [ ] Registry path decision recorded (comment on this PR or in a separate ADR amendment) before implementation PR opens
op1st-gitops commented 2026-05-25 13:57:58 +00:00 (Migrated from codeberg.org)

op1st Pipelines as Code/code-scans-zvldq is running.

Starting Pipelinerun code-scans-zvldq in namespace op1st-pipelines

You can monitor the execution using the op1st Pipelines as Code PipelineRun viewer or through the command line by
using the tkn CLI with the following command:

tkn pr logs -n op1st-pipelines code-scans-zvldq -f

op1st Pipelines as Code/code-scans-zvldq is running. Starting Pipelinerun <b>[code-scans-zvldq](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/code-scans-zvldq)</b> in namespace <b>op1st-pipelines</b> You can monitor the execution using the [op1st Pipelines as Code](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/code-scans-zvldq) PipelineRun viewer or through the command line by using the [tkn](https://tekton.dev/docs/cli/#installation) CLI with the following command: <code>tkn pr logs -n op1st-pipelines code-scans-zvldq -f</code>
op1st-gitops commented 2026-05-25 13:57:58 +00:00 (Migrated from codeberg.org)

op1st Pipelines as Code/on-pull-request-v8q7k is running.

Starting Pipelinerun on-pull-request-v8q7k in namespace op1st-pipelines

You can monitor the execution using the op1st Pipelines as Code PipelineRun viewer or through the command line by
using the tkn CLI with the following command:

tkn pr logs -n op1st-pipelines on-pull-request-v8q7k -f

op1st Pipelines as Code/on-pull-request-v8q7k is running. Starting Pipelinerun <b>[on-pull-request-v8q7k](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/on-pull-request-v8q7k)</b> in namespace <b>op1st-pipelines</b> You can monitor the execution using the [op1st Pipelines as Code](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/on-pull-request-v8q7k) PipelineRun viewer or through the command line by using the [tkn](https://tekton.dev/docs/cli/#installation) CLI with the following command: <code>tkn pr logs -n op1st-pipelines on-pull-request-v8q7k -f</code>
op1st-gitops commented 2026-05-25 13:57:58 +00:00 (Migrated from codeberg.org)

op1st Pipelines as Code/openspec-validate-pr-wpq9v is running.

Starting Pipelinerun openspec-validate-pr-wpq9v in namespace op1st-pipelines

You can monitor the execution using the op1st Pipelines as Code PipelineRun viewer or through the command line by
using the tkn CLI with the following command:

tkn pr logs -n op1st-pipelines openspec-validate-pr-wpq9v -f

op1st Pipelines as Code/openspec-validate-pr-wpq9v is running. Starting Pipelinerun <b>[openspec-validate-pr-wpq9v](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/openspec-validate-pr-wpq9v)</b> in namespace <b>op1st-pipelines</b> You can monitor the execution using the [op1st Pipelines as Code](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/openspec-validate-pr-wpq9v) PipelineRun viewer or through the command line by using the [tkn](https://tekton.dev/docs/cli/#installation) CLI with the following command: <code>tkn pr logs -n op1st-pipelines openspec-validate-pr-wpq9v -f</code>
op1st-gitops commented 2026-05-25 13:58:21 +00:00 (Migrated from codeberg.org)

op1st Pipelines as Code/code-scans-zvldq has successfully validated your commit.


Task Statuses:

StatusDurationName
Succeeded 14 seconds

fetch-source

Succeeded 11 seconds

gitleaks-version

Succeeded 9 seconds

gitleaks

op1st Pipelines as Code/code-scans-zvldq has <b>successfully</b> validated your commit. <ul> <li><b>Namespace</b>: <a href="https://detailurl.setting.custom-console-url-namespace.is.not.configured">op1st-pipelines</a></li> <li><b>PipelineRun:</b> <a href="https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/code-scans-zvldq">code-scans-zvldq</a></li> </ul> <hr> <h4>Task Statuses:</h4> <table> <tr><th>Status</th><th>Duration</th><th>Name</th></tr> <tr> <td>Succeeded</td> <td>14 seconds</td><td> [fetch-source](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/code-scans-zvldq/logs/fetch-source) </td></tr> <tr> <td>Succeeded</td> <td>11 seconds</td><td> [gitleaks-version](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/code-scans-zvldq/logs/gitleaks-version) </td></tr> <tr> <td>Succeeded</td> <td>9 seconds</td><td> [gitleaks](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/code-scans-zvldq/logs/gitleaks) </td></tr> </table>
op1st-gitops commented 2026-05-25 13:58:29 +00:00 (Migrated from codeberg.org)

op1st Pipelines as Code/openspec-validate-pr-wpq9v has successfully validated your commit.


Task Statuses:

StatusDurationName
Succeeded 12 seconds

fetch-source

Succeeded 18 seconds

validate

op1st Pipelines as Code/openspec-validate-pr-wpq9v has <b>successfully</b> validated your commit. <ul> <li><b>Namespace</b>: <a href="https://detailurl.setting.custom-console-url-namespace.is.not.configured">op1st-pipelines</a></li> <li><b>PipelineRun:</b> <a href="https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/openspec-validate-pr-wpq9v">openspec-validate-pr-wpq9v</a></li> </ul> <hr> <h4>Task Statuses:</h4> <table> <tr><th>Status</th><th>Duration</th><th>Name</th></tr> <tr> <td>Succeeded</td> <td>12 seconds</td><td> [fetch-source](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/openspec-validate-pr-wpq9v/logs/fetch-source) </td></tr> <tr> <td>Succeeded</td> <td>18 seconds</td><td> [validate](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/openspec-validate-pr-wpq9v/logs/validate) </td></tr> </table>
goern commented 2026-05-25 13:58:45 +00:00 (Migrated from codeberg.org)

Tracking issue: #156

Tracking issue: #156
op1st-gitops commented 2026-05-25 13:59:33 +00:00 (Migrated from codeberg.org)

op1st Pipelines as Code/on-pull-request-v8q7k has successfully validated your commit.


Task Statuses:

StatusDurationName
Succeeded 12 seconds

fetch-source

Succeeded 1 minute

build-and-test

op1st Pipelines as Code/on-pull-request-v8q7k has <b>successfully</b> validated your commit. <ul> <li><b>Namespace</b>: <a href="https://detailurl.setting.custom-console-url-namespace.is.not.configured">op1st-pipelines</a></li> <li><b>PipelineRun:</b> <a href="https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/on-pull-request-v8q7k">on-pull-request-v8q7k</a></li> </ul> <hr> <h4>Task Statuses:</h4> <table> <tr><th>Status</th><th>Duration</th><th>Name</th></tr> <tr> <td>Succeeded</td> <td>12 seconds</td><td> [fetch-source](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/on-pull-request-v8q7k/logs/fetch-source) </td></tr> <tr> <td>Succeeded</td> <td>1 minute</td><td> [build-and-test](https://console-openshift-console.apps.nostromo.erdgeschoss.b4mad.emea.operate-first.cloud/k8s/ns/op1st-pipelines/tekton.dev~v1~PipelineRun/on-pull-request-v8q7k/logs/build-and-test) </td></tr> </table>
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
agentic-forges/forgejo-mcp!155
No description provided.