Sign pushes by default and remove the lock feature gate - #6139
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## skills-sig/13b-provenance-display #6139 +/- ##
==================================================================
Coverage 72.81% 72.82%
==================================================================
Files 743 742 -1
Lines 77674 77708 +34
==================================================================
+ Hits 56558 56589 +31
- Misses 17146 17150 +4
+ Partials 3970 3969 -1 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
64ff0fa to
3afb9eb
Compare
3afb9eb to
71a473b
Compare
71a473b to
762881c
Compare
762881c to
caa6620
Compare
dbf984a to
454442d
Compare
454442d to
1c3289a
Compare
The final RFC THV-0080 piece: thv skill push signs the pushed artifact with the provided cosign key (attaching the signature manifest next to it, so installs can verify), and pushing unsigned requires an explicit --no-sign — a failed signing fails the push rather than silently publishing unsigned. With signing on publish and verification on consume both in place, the TOOLHIVE_SKILLS_LOCK_ENABLED gate comes out: the lock file, sync, upgrade, dependency materialization, and signature verification are now standard behavior for project-scoped skills. The architecture document's trust-model section graduates from the drift-detection honesty note to the verified model — TOFU semantics, the explicit allow_unsigned / allow_signer_change escape hatches, the provisional git marker, and what deliberately remains trusted on faith. Closes #5899. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-by-default pushes turned every E2E push into a 400: the suite has no signing infrastructure, so its pushes carry the explicit no_sign decision — matching the allow_unsigned exceptions its project-scoped installs already record. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
thv skill push --key could not read any key produced by the cosign CLI. It failed with an opaque ASN.1 error, and no test caught it: the fixtures built keys with cryptoutils, which writes PKCS#8 standard encryption under the same "ENCRYPTED SIGSTORE PRIVATE KEY" label that cosign uses for a payload sealed with scrypt and nacl/secretbox. Same label, different bytes. Decrypt the cosign sealing when the label says so, falling back to the PKCS#8 form, and report a wrong password as such rather than as a parse failure. Also document where COSIGN_PASSWORD is read: signing happens in the API server, so the variable belongs in that process's environment, not the shell running the CLI.
1c3289a to
1c8d470
Compare
|
Rebased onto the updated #6137 branch and marked ready. The gate removal verifies clean: A shipping blocker this PR hadThe plan for this stack promised one manual check that was never run: "signing round-trip interop —
The cause is a collision of formats behind one label. The tests missed it because the fixtures were built with Fixed by decrypting the cosign sealing when the label indicates it, falling back to the PKCS#8 form so both keep working, and reporting a wrong password as a password problem instead of an ASN.1 parse failure. Interop now provenVerified with both an empty-password key and a password-protected one, against a real registry, using the stock cosign CLI. New regression tests build fixtures with One behaviour worth documenting, not fixing
Related: stacklok/toolhive-core#230 carries the same fix, since that PR moves this package into core. |
Note
Stack 2 of RFC THV-0080 — final PR (stack #6128, on top of #6137). Closes #5899 when it lands.
Summary
The last piece: signing on publish, and the feature gate comes out.
thv skill pushsigns by default:--keysigns the pushed artifact with a cosign private key (the signature manifest is attached at the.sigtag, so project-scoped installs verify it; the flow the signer/verifier PRs round-trip in tests). Pushing unsigned requires an explicit--no-sign, and a failed signing fails the push — an artifact is never silently published unsigned. Threaded through CLI, client, and API.TOOLHIVE_SKILLS_LOCK_ENABLEDis removed: with verification on consume (installs, sync, upgrade) and signing on publish both in place, the lock file graduates from experimental. The gate, its env var, the "(experimental)" command markers, and every gated test-server setup are gone; the lock file,toolhive.requiresmaterialization,sync,upgrade, and signature verification are now standard behavior for project-scoped skills. This is THE user-facing change of the stack.docs/arch/12-skills-system.md): the "drift detection over a repository-editable file" honesty note graduates to the verified model — TOFU semantics with the identity displayed,--allow-unsigned/--allow-signer-changeescape hatches, theprovisional:git marker, and an explicit list of what deliberately remains trusted on faith (unsigned exceptions, the lock file as reviewable policy, the first-use anchor).Type of change
Test plan
task test, full suite with -race)task lint-fix, 0 issues)task docsregenerated.Does this introduce a user-facing change?
Yes. The skills lock file feature is no longer gated: project-scoped installs write
toolhive.lock.yaml, verify signatures (unsigned installs need--allow-unsigned), andthv skill sync/upgradework withoutTOOLHIVE_SKILLS_LOCK_ENABLED.thv skill pushnow requires--keyor an explicit--no-sign.Special notes for reviewers
cosign verify --keyaccepts our attached signature) is covered by the signer package's unit tests plus toolhive-core's key-signed retrieval tests; a manual cosign-CLI check against a real registry is worth doing once before release.provisional:), keyless/OIDC signing, catalog-supplied expected identity, and movingpkg/skills/signerto toolhive-core.Generated with Claude Code