gabriel / musehub public
feat BREAKING feat/57-version-tag-signing-server #1 / 1
AI Agent gabriel · 12 hours ago · Oct 21, 2026 · Diff

feat: server-side storage for signed version tags (muse#57 item 3)

Adds signer_public_key/signature columns to musehub_version_tags, completing the server half of muse's new `muse tag add --sign` / `muse tag verify` feature (an Ed25519 signature over (repo_id, tag, commit_id), mirroring the existing signed-commit pattern).

Migration 0079 adds both columns (nullable TEXT, empty-string default -- no backfill needed, every existing row is legitimately unsigned). MusehubVersionTag's ORM model, store_version_tags (both the insert and the on-conflict-update branches, so re-signing and re-pushing a tag correctly updates the stored signature), and list_version_tags (so the already-existing GET /{owner}/{slug}/version-tags endpoint returns them) all updated to pass the two fields through.

Also fixed test_migrations.py's _ALL_REVISIONS/_HEAD, which had silently drifted (stuck at "0074" while migrations 0075-0078 already existed on disk, added by earlier unrelated work this session) -- caught while adding migration 0079's own entry.

New tests/test_musehub_version_tags_service.py (service-level, no HTTP, matching this repo's existing test_musehub_sessions_service.py convention): unsigned tag round-trips with empty signature fields, a signed tag's signer_public_key/signature round-trip through store -> list, force-push re-signing updates the stored signature (not just commit_id), and a payload with no signature keys at all (older client) defaults to unsigned rather than raising. Confirmed genuine RED (4/4 failed with KeyError) before GREEN with the fix restored.

Live-verified end-to-end against the actual local musehub instance (not just the test suite): applied migration 0079, restarted both musehub and musehub_worker containers, confirmed clean boot, then from the muse side signed a tag locally, pushed it, deleted the local copy, and confirmed `muse tag list --remote local` (muse#57 item 4) retrieved it from this server with signed=true -- the full cross-repo wire round-trip, not just mocked unit tests on either side.

Targeted regression suite -- test_musehub_version_tags_service.py (4, new), test_migrations.py (53, including the drift fix), test_authz_wire_push.py (10, covers the version-tags push endpoint's write-authz guard) -- all pass, zero regressions.

Co-Authored-By: Claude Sonnet 5 <[email protected]>

sha256:e86c5be4cf41151c1b4a4b7ac3562c87948faca51a0aa9e533a1ce63e1c51754 sha
+22 ~5 symbols
5 changed · 1090 in snapshot files
sha256:76e00aec9069715c32e75f31be2f4c99a7e5aa16537751b9253006565351aa81 snapshot
+22
symbols added
~5
symbols modified
5
files changed
1090
files in snapshot
0
dead code introduced
Semantic Changes 27 symbols
+ branch_labels variable variable branch_labels L22–22
+ depends_on variable variable depends_on L23–23
+ down_revision variable variable down_revision L21–21
+ downgrade function function downgrade L37–39
+ Sequence import import Sequence L13–13
+ Union import import Union L13–13
+ annotations import import annotations L11–11
+ op import import op L15–15
+ sa import import sa L16–16
+ revision variable variable revision L20–20
+ upgrade function function upgrade L26–34
+ _tag_dict function function _tag_dict L18–33
+ AsyncSession import import AsyncSession L12–12
+ annotations import import annotations L8–8
+ create_repo import import create_repo L15–15
+ datetime import import datetime L10–10
+ timezone import import timezone L10–10
+ vtag_svc import import vtag_svc L14–14
+ test_missing_signature_fields_default_empty function async_function test_missing_signature_fields_default_empty L95–108
+ test_store_and_list_signed_tag_round_trips function async_function test_store_and_list_signed_tag_round_trips L51–65
+ test_store_and_list_unsigned_tag function async_function test_store_and_list_unsigned_tag L36–48
+ test_update_on_conflict_preserves_new_signature function async_function test_update_on_conflict_preserves_new_signature L68–92
~ tests/test_migrations.py .py 2 symbols modified
Files Changed
+2 ~3
1090 in snapshot
← Older Oldest on feat/57-version-tag-signing-server
All commits
Newer → Latest on feat/57-version-tag-signing-server

0 comments

No comments yet. Be the first to start the discussion.

To add a comment, use the Muse CLI: muse hub commit comment sha256:e86c5be4cf41151c1b4a4b7ac3562c87948faca51a0aa9e533a1ce63e1c51754 --body "your comment"