Skip to content

fix(ci): prove publisher lineage with the central Dagger function (draft: pinned at ci#50 head) - #78

Draft
hseshadr wants to merge 3 commits into
mainfrom
fix/publish-lineage-module
Draft

hseshadr wants to merge 3 commits into
mainfrom
fix/publish-lineage-module

Conversation

@hseshadr

Copy link
Copy Markdown
Owner

Reopened from #75, which GitHub closed when its stacked base (#74, now squash-merged) was deleted. Same branch.

TL;DR

Draft on purpose. Pinned to hseshadr/ci#50 head 3de1c4b. That commit is not on ci main until #50 merges. Re-pin to the ci merge SHA after ci merges, then mark ready.

Stacked on #74 (fix/release-tag-injection), which already moves event values in publish.yml into env:. Base is #74's branch; GitHub retargets to main once #74 merges.

Both publish jobs (publish-python, publish-npm) now start with portfolio-foundation's release-lineage, exactly the step ci#50's fleet policy accepts. The job if (head_branch == default_branch) also passes for a workflow_dispatch on a tag named main. The lineage call proves from GitHub's run records that the candidate run is a successful release-candidate.yml dispatch here for exactly HEAD_SHA, and that main contains it, before any artifact is downloaded.

Claim touched: "a publisher only publishes bytes whose candidate run came from main".

Contract changes (called out on purpose)

  • Both jobs gain contents: read: the lineage proof reads compare/ and branches/main. test_workflow_security and test_release_contract pinned {actions: read, id-token: write}; they now pin the three-key set the fleet policy allows (same as edgeproc-core#60 / privacy-core#49).
  • test_should_reduce_the_total_dagger_and_workflow_surface budget: 700 → 720 lines, for the two required lineage steps. No repository logic added.
  • Step-list tests now expect the lineage step first.

Evidence

Check Result
New lineage tests before the workflow change red: 5 failed (2 new lineage tests + 3 shape/permission tests)
After the workflow change green: 29 passed (test_workflow_security.py, test_workflow_contract.py)
Mutation: drop --publish-run-id red: 2 failed; ci#50 policy reports 2 publisher-lineage
Mutation: paste ${{ github.event.workflow_run.head_sha }} into lineage args red: 3 failed
Mutation: delete the npm job's lineage step red: 2 failed (ci#50 policy still 0: lineage is optional there until feat/require-publish-lineage)
ci#50 validate_workflow on all four workflows 0 findings (0 on base too)
poe lint, fmt-check, typecheck, complexity, workflow-security (zizmor), workflow-lint (actionlint) green
poe test locally 94.3% coverage; only failures are local pnpm/corepack toolchain ones that fail identically on the base branch
git merge-tree vs main, #74, #73 clean

Merge order

  1. feat(fleet): enforce per-module required-minimum pin floors ci#47 → feat: add protected release mirror #48 → fix: create recovery release from verified tag #50.
  2. assay#74, then re-pin this PR's module: SHA to ci#50's merge SHA and mark ready.
  3. Merge this before hseshadr/ci feat/require-publish-lineage (which makes the lineage step required).

Not verified

  • A real publish. That needs a release dispatch, which this PR does not do.

🤖 Generated with Claude Code

https://claude.ai/code/session_015oBArfm762nN1r4F4Fst5a

hseshadr and others added 3 commits September 25, 2026 09:02
release-candidate.yml pasted `${{ inputs.tag }}` straight into the
dagger-for-github `args`, which the action splices into bash. A crafted tag
could inject arguments or commands. The tag now reaches the step only as the
TAG environment variable and the args hold only double-quoted variables, the
same shape as edge-proc#76. publish.yml gets the same treatment for the
workflow_run head SHA.

The workflow test that asserted `--tag=${{ inputs.tag }}` in the args is
inverted: it asserted the defect as the contract.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015oBArfm762nN1r4F4Fst5a
Debian published libjq1 1.7.1-6+deb13u4, so the u3 jq pin can no longer be
installed and the Dagger base image fails with exit 100. This is the same
one-line bump as #73, so the two branches merge cleanly in either order.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015oBArfm762nN1r4F4Fst5a
Both publish jobs (PyPI and npm) now start with portfolio-foundation's
release-lineage, pinned at hseshadr/ci#50 head 3de1c4b. The job `if`
(head_branch == default_branch) also passes for a dispatch on a tag named
`main`; the lineage call proves from GitHub's run records that the candidate
is a successful release-candidate.yml dispatch for exactly HEAD_SHA and that
main contains it, before any artifact is downloaded.

Jobs gain contents:read (compare/ and branches/main). Contract tests that
pinned the old two-permission set and step lists are updated; the
surface budget moves 700 -> 720 for the two required lineage steps.

Draft: re-pin to the ci merge SHA after hseshadr/ci#50 merges.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015oBArfm762nN1r4F4Fst5a

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant