From 0d00de76c6e0a5626024ec5464f125df409b529e Mon Sep 17 00:00:00 2001 From: Evan Jarrett Date: Wed, 18 Feb 2026 21:52:21 -0600 Subject: [PATCH] implement HandleGetLatestCommit --- pkg/atproto/endpoints.go | 6 ++++++ pkg/hold/pds/xrpc.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/pkg/atproto/endpoints.go b/pkg/atproto/endpoints.go index 18bd594..79fd68e 100644 --- a/pkg/atproto/endpoints.go +++ b/pkg/atproto/endpoints.go @@ -135,6 +135,12 @@ const ( // Response: {"did": "...", "active": true, "rev": "..."} SyncGetRepoStatus = "/xrpc/com.atproto.sync.getRepoStatus" + // SyncGetLatestCommit gets the current commit CID and revision for a repository. + // Method: GET + // Query: did={did} + // Response: {"cid": "...", "rev": "..."} + SyncGetLatestCommit = "/xrpc/com.atproto.sync.getLatestCommit" + // SyncGetHostStatus gets the hosting/crawl status for a hostname on a relay. // Method: GET // Query: hostname={hostname} diff --git a/pkg/hold/pds/xrpc.go b/pkg/hold/pds/xrpc.go index 54b62a2..080b026 100644 --- a/pkg/hold/pds/xrpc.go +++ b/pkg/hold/pds/xrpc.go @@ -169,6 +169,7 @@ func (h *XRPCHandler) RegisterHandlers(r chi.Router) { r.Get(atproto.SyncGetRecord, h.HandleSyncGetRecord) r.Get(atproto.SyncGetRepo, h.HandleGetRepo) r.Get(atproto.SyncGetRepoStatus, h.HandleGetRepoStatus) + r.Get(atproto.SyncGetLatestCommit, h.HandleGetLatestCommit) r.Get(atproto.SyncSubscribeRepos, h.HandleSubscribeRepos) // DID document and handle resolution @@ -1294,6 +1295,38 @@ func (h *XRPCHandler) HandleGetRepoStatus(w http.ResponseWriter, r *http.Request }) } +// HandleGetLatestCommit returns the current commit CID and revision for a repository. +// Spec: https://docs.bsky.app/docs/api/com-atproto-sync-get-latest-commit +func (h *XRPCHandler) HandleGetLatestCommit(w http.ResponseWriter, r *http.Request) { + did := r.URL.Query().Get("did") + if did == "" { + http.Error(w, "missing required parameter: did", http.StatusBadRequest) + return + } + + if did != h.pds.DID() { + http.Error(w, "RepoNotFound", http.StatusNotFound) + return + } + + head, err := h.pds.repomgr.GetRepoRoot(r.Context(), h.pds.uid) + if err != nil { + http.Error(w, "RepoNotFound", http.StatusNotFound) + return + } + + rev, err := h.pds.repomgr.GetRepoRev(r.Context(), h.pds.uid) + if err != nil || rev == "" { + http.Error(w, "RepoNotFound", http.StatusNotFound) + return + } + + render.JSON(w, r, map[string]any{ + "cid": head.String(), + "rev": rev, + }) +} + // HandleDIDDocument returns the DID document func (h *XRPCHandler) HandleDIDDocument(w http.ResponseWriter, r *http.Request) { doc, err := h.pds.GenerateDIDDocument(h.pds.PublicURL)