repo.delete leaves stale repo_aliases rows, orphans bare repo on recreate-with-same-name

did:plc:r2whjvupgfw55mllpksnombn opened this 1d ago 0 comments
did:plc:r2whjvupgfw55mllpksnombn opened 1d ago

Summary

sh.tangled.repo.delete removes the row from repo_keys but leaves the matching row in repo_aliases in place. Because the subsequent sh.tangled.repo.create uses INSERT INTO repo_aliases ... ON CONFLICT(owner_did, rkey) DO NOTHING, recreating a repo with the same name leaves the new bare repo orphaned — the on-disk dir at scanPath/<new-repoDid> is correctly populated, but the alias still points at the deleted DID, so HTTP routing returns "repository not found" for all clone URLs.

Reproduction

  1. sh.tangled.repo.create for name=foo → returns repoDid=D1. Bare repo at scanPath/D1 is created.
  2. sh.tangled.repo.delete for the same (owner, name) — succeeds, but repo_aliases (owner_did, rkey="foo", repo_did=D1) remains.
  3. sh.tangled.repo.create for name=foo again — mints repoDid=D2 and bare-clones (or init-bares) at scanPath/D2. repo_keys has the new row. repo_aliases is unchanged (still pointing at D1).
  4. Any clone URL that resolves to D2 fails: ResolveRepoDIDOnDisk(D2) calls GetRepoKeyOwner(D2) which queries repo_aliases WHERE repo_did=D2 and finds nothing → "unknown repo DID".

Hit this from CCotw (Anthropic's web Claude container, which has no port 22 egress) while validating that sh.tangled.repo.create's source parameter lets us populate a Tangled repo server-side from a GitHub mirror — that feature works perfectly, but the alias bug forced us to use a different name (claude-tangled-spoke-mirror instead of claude-tangled-spoke).

Suggested fix

In knotserver/xrpc/delete_repo.go, after DeleteRepoKey(repoDid), also DELETE FROM repo_aliases WHERE repo_did = ?. Or, in storeRepoKeyRow, change the alias upsert from ON CONFLICT DO NOTHING to an UPDATE that replaces the old repo_did. The delete-side cleanup is the more conservative fix.

Source pointers

  • knotserver/xrpc/delete_repo.go:97DeleteRepoKey(repoDid) is the only DB-side cleanup
  • knotserver/db/db.go:188-225storeRepoKeyRow has the ON CONFLICT DO NOTHING
  • knotserver/db/db.go:267-286ResolveRepoDIDOnDisk is what then can't find the repo

Filed from the CLI we built for the integration: https://github.com/oaustegard/claude-tangled-spoke

No activity yet.

cospan · schematic version control on atproto built on AT Protocol