Skip to content

Add fyi.atstore.directory.getListingAuth - #59

Open
chris-pardy wants to merge 1 commit into
ATProtocol-Community:mainfrom
chris-pardy:listing-oauth-client-metadata
Open

chris-pardy wants to merge 1 commit into
ATProtocol-Community:mainfrom
chris-pardy:listing-oauth-client-metadata

Conversation

@chris-pardy

Copy link
Copy Markdown
Contributor

What

A new public XRPC query, fyi.atstore.directory.getListingAuth?uri=<listing.detail AT URI>, that says how a listing's app signs users in:

{
  "uri": "at://…/fyi.atstore.listing.detail/…",
  "authMethod": "oauth",              // oauth | app_password | unsupported_mobile | unknown
  "clientMetadataUrl": "https://…/oauth-client-metadata.json",  // the app's client_id, or null
  "scope": "atproto include:…",       // scope line last probed from that metadata, or null
  "checkedAt": "2026-10-28T…Z"        // when it was probed, or null
}

Errors: InvalidParams (400), ListingNotFound (404; same public-listing rules as getListing).

Why

AT Store already does the hard part of finding each app's OAuth client metadata: well-known probes, the Playwright pass, and manual triage in store_listing_oauth_discovery. None of that reaches other atproto services today. I'm building scoped app passwords on a PDS: you pick an app from AT Store, and the password gets only the permissions the app asks for in OAuth. Without this endpoint the PDS has to re-probe each app's website. Against a handful of popular listings, that only found metadata for one in five, while AT Store already knows most of them.

How

  • clientMetadataUrl is taken from store_listing_oauth_discovery.client_metadata_url first, then from store_listing_oauth_probes.successful_client_metadata_url.
  • authMethod is the discovery classification. With no discovery row, it is oauth if a probe found metadata, otherwise unknown.
  • scope is the probe's client_scope_raw_line. It is only returned when the probe's URL matches the URL being returned, so a manually triaged client never gets another client's scope. It may be stale, and consumers should fetch clientMetadataUrl for the authoritative scope.
  • The probe data was already public on product pages. The discovery data is URLs to public metadata documents plus a coarse classification.

Changes: the lexicon (lexicons/fyi/atstore/directory/getListingAuth.json, added to lex:gen and regenerated), the NSID and method registry (so server.describe lists it), the handler, and a row on /developers/atproto.

Testing

  • pnpm typecheck, oxlint, oxfmt --check and pnpm test (128 passing).
  • Ran the handler against a migrated Postgres with seeded listings: discovery and probe agreeing, app_password only, probe only, discovery and probe disagreeing (scope dropped), an unverified listing (404), an unknown URI (404), and bad or missing uri (400).

🤖 Generated with Claude Code

https://claude.ai/code/session_019AnbyLhXS4koGFdgrG9YST

A public query for how a listing's app signs in: authMethod, its OAuth
client metadata URL (client_id) when known, and the scope last probed
from that metadata. client_metadata_url from store_listing_oauth_discovery
(well-known, Playwright or manual triage) wins over the periodic probe's
successful_client_metadata_url; the probed scope is only returned when it
came from the same client.

Lets a PDS or client find the permissions an app asks for (e.g. to make a
scoped app password) without re-probing the app's site.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019AnbyLhXS4koGFdgrG9YST

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants