Skip to content

Track: Skills lock file + Sigstore signing (RFC THV-0080) #5899

Description

@samuv

Summary

Tracks the productionized implementation of RFC THV-0080: a project-level toolhive.lock.yaml that pins every project-scoped skill install (source, resolvedReference, digest, contentDigest, Sigstore provenance), plus thv skill sync / thv skill upgrade, signature verification on consume, and signing on push.

This replaces the original POC, PR #5715 (closed), which validated the approach but was too large to review/merge as one diff. The author's follow-up comment proposed a 14-PR split across two stacks; this issue tracks that split end-to-end.

The feature is gated behind TOOLHIVE_SKILLS_LOCK_ENABLED for the whole rollout — it stays inert on main until both stacks land, since the RFC treats reproducible pinning and Sigstore verification as one "v1" trust model, not two independently shippable halves.

Stack 1 — Lock file mechanics (✅ fully merged 2026-07-24)

Branch chain: skills-lock/01-lockfile → ... → skills-lock/06-cli-exitcodes, each PR targeting the previous one's branch.

Each PR includes its own tests (unit + E2E where applicable) and passes CI independently of the rest of the stack. A local review pass caught and fixed 6 correctness bugs across this stack before human review (digest-forgery via crafted paths, an unvalidated lock-file write path, an incomplete install rollback, inconsistent dependency-cycle keying, a sync-triggered field corruption, and a --fail-on-changes gate that mutated state before failing) — see each PR's commit history for details.

Stack 2 — Sigstore signing/verification (8 of 10 merged)

Branch chain: skills-sig/07-provenance-schema → ... → skills-sig/14-push-signing-ungate.

Current state: verification is fully implemented and released (v0.42.1), but the
feature remains gated on main — pkg/skills/feature_gate.go and six
LockFileFeatureEnabled() call sites are still present, so users see nothing unless
they set TOOLHIVE_SKILLS_LOCK_ENABLED. #6139 is what removes that, and it is still
open. #6139 is stacked on #6137's branch, so #6137 lands first.

Validated end-to-end

stacklok/toolhive-skills-lock-example exercises the merged half against the real
catalog: a dockyard-signed skill is installed, its keyless Sigstore signature verified,
the observed identity TOFU-pinned into toolhive.lock.yaml, and a scheduled workflow
detects upstream drift and opens a PR. Building it surfaced four bugs, all fixed and
released in v0.42.1 — #6211, #6212, #6213, plus the thv ai-plugin counterparts of the
first two.

Follow-ups (tracked separately once reached)

  • Keyless push signing + Sigstore-staging E2E
  • Catalog-supplied expected identity (needs toolhive-core Provenance on Skill types)
  • Move pkg/skills/signer into toolhive-core next to the verification exports, so all
    Sigstore code lives in one place (decided 2026-07-28, sequenced after PR14 because
    Sign pushes by default and remove the lock feature gate #6139 still modifies the package). The package imports nothing from toolhive, so the
    move is mechanical.
  • verifier: simple-signing payload digest binding is not independently validated toolhive-core#198 — the simple-signing payload digest binding is not
    independently validated; affects the verify path this stack depends on.
  • Record the certificate's source ref and runner environment in lock provenance. The
    recorded identity currently pins repository + workflow file but not the git ref, so a
    signature produced by that workflow on any branch satisfies the policy.

Definition of done

  • All Stack 1 PRs merged with CI green (including CodeQL).
  • toolhive-core#176 released and consumed via a go.mod bump.
  • All Stack 2 PRs merged.
  • TOOLHIVE_SKILLS_LOCK_ENABLED gate removed in PR14, documented as the user-facing change.

Activity

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

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestskillsSkills lifecycle management

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions