User Story
As a team maintaining a project that consumes agent skills,
I want project-scope skill installs pinned in a committed lock file, cryptographically verified against the publisher's Sigstore identity, and safely upgradable,
So that every teammate and CI run restores the exact same reviewed skills, and tampered or re-signed artifacts are detected before they reach a developer's machine.
Context
RFC THV-0080 (stacklok/toolhive-rfcs#80) proposes a project-level skills lock file. PR #5715 implements a feasibility POC covering the full vertical slice:
- Lock file —
toolhive.lock.yaml pins source, resolvedReference, digest, and an on-disk contentDigest, with thv skill sync (--check/--adopt/--prune) and thv skill upgrade (--preview/--allow-ref-change)
- Sigstore v1 trust — verify on consume (install/sync/upgrade), sign on push (
--key, --no-sign), TOFU publisher identity pinned as provenance in the lock (or an explicit unsigned: true exception), offline bundle re-verification in sync --check, and a signer-change guard on upgrade (--allow-signer-change)
The POC validated feasibility (~6.6k lines / 74 files) but is intentionally not mergeable as one PR. This story tracks landing the work for production as 14 stacked PRs across two dependency chains (plan detailed in PR #5715):
Stack 1 — Lock file (6 PRs): lockfile package → SkillLockService split + storage → install/uninstall hooks → sync → upgrade → API/CLI surface
Stack 2 — Sigstore v1 (8 PRs, after Stack 1): provenance schema → verifier package → signer package → bundle storage + git signature plumbing → install verification → sync offline verify → upgrade signer guard → push signing + CLI/API flags
Each PR is independently buildable and testable (task test, task lint); this is a rewrite-by-file of the POC branch, not a cherry-pick of its commits.
Acceptance Criteria
Stack 1 — Lock file
Stack 2 — Sigstore v1
Delivery
Out of Scope (deferred from v1)
- Keyless OIDC push signing (E2E against Sigstore staging)
- Catalog-supplied expected identity (requires
Provenance on toolhive-core Skill types)
References
User Story
As a team maintaining a project that consumes agent skills,
I want project-scope skill installs pinned in a committed lock file, cryptographically verified against the publisher's Sigstore identity, and safely upgradable,
So that every teammate and CI run restores the exact same reviewed skills, and tampered or re-signed artifacts are detected before they reach a developer's machine.
Context
RFC THV-0080 (stacklok/toolhive-rfcs#80) proposes a project-level skills lock file. PR #5715 implements a feasibility POC covering the full vertical slice:
toolhive.lock.yamlpinssource,resolvedReference,digest, and an on-diskcontentDigest, withthv skill sync(--check/--adopt/--prune) andthv skill upgrade(--preview/--allow-ref-change)--key,--no-sign), TOFU publisher identity pinned asprovenancein the lock (or an explicitunsigned: trueexception), offline bundle re-verification insync --check, and a signer-change guard on upgrade (--allow-signer-change)The POC validated feasibility (~6.6k lines / 74 files) but is intentionally not mergeable as one PR. This story tracks landing the work for production as 14 stacked PRs across two dependency chains (plan detailed in PR #5715):
Stack 1 — Lock file (6 PRs): lockfile package →
SkillLockServicesplit + storage → install/uninstall hooks → sync → upgrade → API/CLI surfaceStack 2 — Sigstore v1 (8 PRs, after Stack 1): provenance schema → verifier package → signer package → bundle storage + git signature plumbing → install verification → sync offline verify → upgrade signer guard → push signing + CLI/API flags
Each PR is independently buildable and testable (
task test,task lint); this is a rewrite-by-file of the POC branch, not a cherry-pick of its commits.Acceptance Criteria
Stack 1 — Lock file
thv skill installwrites atoolhive.lock.yamlentry pinningsource,resolvedReference,digest, andcontentDigest;thv skill uninstallremoves it and cascade-removes orphaned dependencies (requiredBy/explicit)thv skill sync --checkdetects drift between the lock file and installed skills (missing, digest mismatch, on-disk tampering viacontentDigest) and exits with code 2 on failurethv skill sync --adoptrecords out-of-band installs into the lock;--pruneremoves lock entries for manually deleted skillsthv skill upgrade --previewshows the candidate change without applying; moving to a different resolved reference requires--allow-ref-changePOST /skills/syncandPOST /skills/upgradewith typed exit codes for CI (0 success / 2 check failure / 3 partial failure / 4 policy rejection)toolhive.requiresdependencies are materialized as lock entries withrequiredBytrackingStack 2 — Sigstore v1
--allow-unsignedis passed, which recordsunsigned: truein the lockprovenance.signerIdentity+certIssuer, TOFU); subsequent installs/syncs fail withsigner-mismatchif the identity divergesthv skill sync --checkre-verifies stored Sigstore bundles offline (no registry access) against the locked provenancethv skill upgradeblocks candidates whose signer identity or cert issuer changed, with--allow-signer-changeas the explicit overridethv skill pushsigns by default with a cosign key (--key,COSIGN_PASSWORD), attaching the signature as an OCI referrer;--no-signopts outprovenanceorunsigned: trueDelivery
docs/arch/12-skills-system.mddocuments the v1 trust model (cryptographic verification / TOFU identity / human lock-file review)Out of Scope (deferred from v1)
Provenanceon toolhive-coreSkilltypes)References