From d57ad0c67f60d2e21298e8ab1930874ea1ed505c Mon Sep 17 00:00:00 2001 From: zzstoatzz Date: Fri, 7 Aug 2026 18:03:09 -0500 Subject: [PATCH] route com.atproto.space.getRepoState alongside getLatestCommit the atpint/bulleted stack requires getRepoState in the capability describe list; it takes the same space+repo params, so both names hit the signed-state handler while the permissioned-data draft settles. Co-Authored-By: Claude Fable 5 --- src/atproto/server.zig | 1 + src/atproto/space.zig | 3 +++ src/http/router.zig | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/atproto/server.zig b/src/atproto/server.zig index e8a012a..906da65 100644 --- a/src/atproto/server.zig +++ b/src/atproto/server.zig @@ -66,6 +66,7 @@ test "serviceDescribeBody reflects the permissioned-data flag" { try std.testing.expect(std.mem.indexOf(u8, with_spaces, "\"community.lexicon.service.describe\"") != null); try std.testing.expect(std.mem.indexOf(u8, without_spaces, "\"community.lexicon.service.describe\"") != null); try std.testing.expect(std.mem.indexOf(u8, with_spaces, "\"com.atproto.space.getSpace\"") != null); + try std.testing.expect(std.mem.indexOf(u8, with_spaces, "\"com.atproto.space.getRepoState\"") != null); try std.testing.expect(std.mem.indexOf(u8, without_spaces, "com.atproto.space.") == null); try std.testing.expect(std.mem.indexOf(u8, without_spaces, "com.atproto.simplespace.") == null); try std.testing.expect(std.mem.indexOf(u8, without_spaces, "_health") == null); diff --git a/src/atproto/space.zig b/src/atproto/space.zig index d56f7bb..401012e 100644 --- a/src/atproto/space.zig +++ b/src/atproto/space.zig @@ -44,6 +44,9 @@ pub fn dispatch(request: *http_api.Request) !void { if (std.mem.eql(u8, method, "com.atproto.space.listRecords")) return listRecords(request); if (std.mem.eql(u8, method, "com.atproto.space.getBlob")) return getBlob(request); if (std.mem.eql(u8, method, "com.atproto.space.getLatestCommit")) return getLatestCommit(request); + // newer name for the same operation in the atpint/bulleted stack; both + // stay routable while the draft settles on one. + if (std.mem.eql(u8, method, "com.atproto.space.getRepoState")) return getLatestCommit(request); if (std.mem.eql(u8, method, "com.atproto.space.getRepo")) return getRepo(request); if (std.mem.eql(u8, method, "com.atproto.space.listRepoOps")) return listRepoOps(request); if (std.mem.eql(u8, method, "com.atproto.space.registerNotify")) return registerNotify(request); diff --git a/src/http/router.zig b/src/http/router.zig index c96c595..67f8316 100644 --- a/src/http/router.zig +++ b/src/http/router.zig @@ -231,6 +231,7 @@ pub const endpoints = [_]Endpoint{ .{ .route = .permissioned_data, .method = "GET", .path = "/xrpc/com.atproto.space.listRecords", .group = "space", .auth = "experimental bearer or space credential", .summary = "List records in a permissioned data space. Values are included unless excludeValues=true.", .params = &.{ "space", "repo", "collection", "limit", "cursor", "reverse", "excludeValues" }, .notes = permissioned_data_note }, .{ .route = .permissioned_data, .method = "GET", .path = "/xrpc/com.atproto.space.getBlob", .group = "space", .auth = "experimental bearer or space credential", .summary = "Read a blob referenced from a permissioned data record.", .params = &.{ "space", "repo", "cid" }, .notes = permissioned_data_note }, .{ .route = .permissioned_data, .method = "GET", .path = "/xrpc/com.atproto.space.getLatestCommit", .group = "space", .auth = "experimental bearer or space credential", .summary = "Read the current signed commit for a writer repo in a space.", .params = &.{ "space", "repo" }, .notes = permissioned_data_note }, + .{ .route = .permissioned_data, .method = "GET", .path = "/xrpc/com.atproto.space.getRepoState", .group = "space", .auth = "experimental bearer or space credential", .summary = "Read the current signed state for a writer repo in a space (newer name for getLatestCommit).", .params = &.{ "space", "repo" }, .notes = permissioned_data_note }, .{ .route = .permissioned_data, .method = "GET", .path = "/xrpc/com.atproto.space.getRepo", .group = "space", .auth = "experimental bearer or space credential", .summary = "Download a full permissioned repo CAR for recovery.", .params = &.{ "space", "repo" }, .notes = permissioned_data_note }, .{ .route = .permissioned_data, .method = "GET", .path = "/xrpc/com.atproto.space.listRepoOps", .group = "space", .auth = "experimental bearer or space credential", .summary = "Read incremental record operations. Values are included unless excludeValues=true.", .params = &.{ "space", "repo", "since", "limit", "excludeValues" }, .notes = permissioned_data_note }, .{ .route = .permissioned_data, .method = "POST", .path = "/xrpc/com.atproto.space.registerNotify", .group = "space", .auth = "experimental space credential", .summary = "Register an expiring write-notification endpoint for a space or repo.", .body = &.{ "space", "repo", "endpoint" }, .notes = permissioned_data_note }, @@ -348,6 +349,7 @@ test "routes pds probes" { try std.testing.expectEqual(Route.sync_subscribe_repos, route(.GET, "/xrpc/com.atproto.sync.subscribeRepos?cursor=0")); try std.testing.expectEqual(Route.sync_request_crawl, route(.POST, "/xrpc/com.atproto.sync.requestCrawl")); try std.testing.expectEqual(Route.permissioned_data, route(.POST, "/xrpc/com.atproto.simplespace.createSpace")); + try std.testing.expectEqual(Route.permissioned_data, route(.GET, "/xrpc/com.atproto.space.getRepoState?space=x&repo=y")); try std.testing.expectEqual(Route.permissioned_data, route(.GET, "/xrpc/com.atproto.space.listRecords?space=at%3A%2F%2Fdid%3Aplc%3Aabc%2Fspace%2Fkey")); try std.testing.expectEqual(Route.not_found, route(.GET, "/xrpc/app.bsky.ageassurance.getState?countryCode=US")); try std.testing.expectEqual(Route.identity_resolve_handle, route(.GET, "/xrpc/com.atproto.identity.resolveHandle?handle=alice.test")); -- 2.51.2