Skip to content
This repository was archived by the owner on Jul 18, 2026. It is now read-only.

Fix published index: restore signatures on retained connector versions, gate unsigned publishes - #95

Merged
maciejwitowski merged 1 commit into
mainfrom
maciej/fix-retained-artifact-signatures
Jul 13, 2026
Merged

maciejwitowski merged 1 commit into
mainfrom
maciej/fix-retained-artifact-signatures

Conversation

@maciejwitowski

Copy link
Copy Markdown
Contributor

Problem

The 2026-07-13 05:13Z publish (first success since Jun 11, revived by #93) shipped a connector-index.json where 10 retained (superseded) connector versions have no artifactSignature. The installer hard-fails on missing Sigstore metadata, so every consumer install is broken: all unity-surfaces Vercel deploys and any fresh pnpm install die on

[resolve-connectors] ERROR: Connector artifact chatgpt-playwright@2.0.0 is missing Sigstore bundle metadata

(unity-surfaces pins 5 of the 10 affected versions; GH Actions only stay green because they set SKIP_CONNECTOR_FETCH=1.)

Root cause

Signatures are attached at publish time, and only along two paths: rebuilt current versions, and retained versions of a connector being bumped in that same publish (materializeRetainedArtifact). When a connector is not bumped, its retained versions are carried verbatim from the committed index — which never stores signatures. Today's publish took that path for all 10.

The bump-time materialization also hides a second landmine (very likely why the Jun 25/29 publish runs failed): retained tarballs aren't byte-reproducible, so the raw.githubusercontent copies no longer match the recorded artifactSha256. For github-playwright@1.2.0 the committed sha, the pinned raw bytes, and the signed June release bytes are three different values. Only the last published release assets are both signed and self-consistent.

Fix

  • connector-index.json — point the 9 restorable retained entries back at the connectors-3f944c668395 release (artifactUrl, artifactSha256, releaseId, sourceCommit/sourceTag, artifactSignature); all those assets are live (HTTP 200) and their sha256s verify. Drop github-playwright@1.4.0: added while publishing was broken, never in any successful release, no signature bundle exists anywhere for it (same precedent as Fix publish: drop retained claude-export 1.0.0 #87's drop of retained claude-export 1.0.0). Nothing pins it.
  • generate-connector-index.mjs — run retained versions through materializeRetainedArtifact on the preserved-current-version path too, making retention handling symmetric with the bump path (no-op in local/commit mode; inert for entries that already carry release URLs + signatures).
  • Signature gateassertConnectorIndexSigned (in connector-artifact-contract.mjs, called from the generator when CONNECTOR_ENABLE_SIGSTORE_METADATA=1): refuse to emit an index with unsigned entries. A future regression fails the publish loudly instead of shipping a broken index to every consumer.

Verification

  • node --test contract tests: 18/18 (2 new for the signature gate)
  • Local regeneration is byte-stable; --check + the full contract-guardrails battery pass locally
  • Publish simulation (CONNECTOR_USE_RELEASE_ASSETS=1 + CONNECTOR_ENABLE_SIGSTORE_METADATA=1): 26/26 entries signed, all 52 artifact+bundle URLs return 200
  • End-to-end: unity-surfaces' installer flow (loadConnectorIndexgenerateLockinstallFromLock) against the simulated published index resolves, downloads, and Sigstore-verifies all 13 pinned connectors

Notes / follow-ups

  • Merging this re-triggers the publish workflow, which unblocks unity-surfaces deploys immediately.
  • The rebuilt entries' releaseId comes out as github-<full-sha> (workflow sets release_id=github-${GITHUB_SHA}) while everything else uses connectors-<sha12> — intentional? Left untouched here.
  • Longer-term, consider re-uploading retained artifacts (fetched from their pinned release, not rebuilt) into each new immutable release so every release is self-contained.

🤖 Generated with Claude Code

…s, gate unsigned publishes

The 2026-07-13 05:13Z publish (first success since Jun 11) shipped a
connector-index.json where 10 retained (superseded) connector versions
carry no artifactSignature. The installer hard-fails on missing Sigstore
metadata, so every consumer install broke — all unity-surfaces Vercel
deploys and fresh `pnpm install`s die on
`chatgpt-playwright@2.0.0 is missing Sigstore bundle metadata`.

Mechanism: signatures are attached at publish time, and only along two
paths — rebuilt current versions, and retained versions of a connector
being bumped in that same publish (materializeRetainedArtifact). When a
connector is NOT bumped, its retained versions are carried verbatim from
the committed index, which never stores signatures. The Jun 25/29
publishes (which would have materialized the retained entries at bump
time) failed on a real checksum drift: retained tarballs are not
byte-reproducible, so the raw.githubusercontent copies no longer match
the recorded artifactSha256 (github-playwright@1.2.0: committed sha,
raw bytes, and signed release bytes are three different values). Only
the last published release assets are both signed and self-consistent.

Fix:
- connector-index.json: point the 9 restorable retained entries back at
  the connectors-3f944c668395 release (artifactUrl, artifactSha256,
  releaseId, sourceCommit/sourceTag, artifactSignature) — those assets
  are live and their sha256s verify. Drop github-playwright@1.4.0: it
  was added while publishing was broken, never appeared in a successful
  release, and no bundle exists anywhere for it (same precedent as #87).
- generate-connector-index.mjs: run retained versions through
  materializeRetainedArtifact on the preserved-current-version path too,
  so retention handling is symmetric with the bump path (no-op in local
  mode; inert for entries that already carry release URLs + signatures).
- generate-connector-index.mjs + connector-artifact-contract.mjs: refuse
  to emit an index with unsigned entries when sigstore metadata is
  enabled (assertConnectorIndexSigned). A future regression fails the
  publish loudly instead of shipping a broken index.

Verification:
- node --test contract tests: 18/18 (2 new for the signature gate).
- Local regen is byte-stable; `--check` and the full contract-guardrails
  battery pass.
- Publish simulation (CONNECTOR_USE_RELEASE_ASSETS=1 +
  CONNECTOR_ENABLE_SIGSTORE_METADATA=1): 26/26 entries signed; all 52
  artifact+bundle URLs return 200.
- End-to-end: unity-surfaces' installer-core flow (generateLock +
  installFromLock) against the simulated published index resolves,
  downloads, and Sigstore-verifies all 13 pinned connectors.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Schema Health Check — Non-blocking inherited issues

44/50 scopes consistent | 6 inherited Gateway gap(s) | no new blocking issues in this PR

@maciejwitowski
maciejwitowski merged commit 7945418 into main Jul 13, 2026
2 checks passed
@maciejwitowski
maciejwitowski deleted the maciej/fix-retained-artifact-signatures branch July 13, 2026 14:42
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant