Add relationshipLookup, bskyProfileIfExists, and BskyCDN read helpers - #58
Merged
germ-mark merged 1 commit intoSep 23, 2026
Merged
Conversation
Three additive helpers on Atproto.XRPC.BskyAppCallable: relationshipLookup(actor:others:) dedupes/chunks app.bsky.graph.getRelationships at the lexicon's 30-subject limit and reports not-found subjects rather than dropping them (not an account-existence check - the AppView returns a relationship entry for any well-formed DID); bskyProfileIfExists(actor:) maps getProfile's undeclared not-found shape (400 InvalidRequest, "Profile not found") to nil; and Atproto.BskyCDN.imageURL(_:did:blob:host:) builds CDN image URLs from a blob reference with explicit RFC 3986 path-segment encoding so a crafted DID/CID can't escape its segment. Also fixes GetRelationships.Parameters.init to accept exactly 30 others (the lexicon's own maxLength, previously rejected) and makes GetRelationships.Errors public, since it's already thrown by public API. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: 18c070d The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
germ-mark
merged commit Sep 23, 2026
1b4b358
into
llm/doh-wellknown-handle-resolvers
11 checks passed
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #57. Review and merge that first; this PR's diff is just the one commit on top.
relationshipLookup(actor:others:)dedupes, chunks at 30, and returns aGetRelationships.LookupwithfoundandnotFoundper requested DID. The existinggetRelationships(actor:subjects:)drops not-found subjects with acompactMap. The AppView returns a relationship entry for any well-formed DID, sofounddoesn't mean the account exists; usebskyProfileIfExistsfor that. If a response names a different actor, it throwsactorMismatchfrom the now-publicGetRelationships.Errors.GetRelationships.Parametersrejected exactly 30others, but the lexicon'sothers.maxLengthis 30.bskyProfileIfExists(actor:)returnsnilfor the AppView's400 InvalidRequest "Profile not found"(getProfile's lexicon declares no errors). Anything else, including deactivated or suspended accounts, still throws.Atproto.BskyCDN.imageURL(_:did:blob:host:)buildscdn.bsky.app/img/<avatar|banner>/plain/<did>/<cid>@jpegfrom a recordBlob. The DID and CID are percent-encoded as single path segments.Everything is additive except the
maxOthersfix and makingGetRelationships.Errorspublic.Testing: new tests cover chunking boundaries (30/31/60/61), the found/not-found split (including unrequested, omitted and handle-form entries), dedupe, the per-chunk actor check, the getProfile not-found parse path, and CDN path traversal and host handling. All were mutation-checked.
swift test --skip OnlineTests, strict lint and an Android cross-compile pass.🤖 Generated with Claude Code