Parent: #452
Depends on: #456 (Account v3 wire fields)
JS source
6.7 changeset extend-v3-fallback.md and recipe #12 in migration guide.
Use case
For adapters wrapping a vendor OAuth + /me/adaccounts-shaped upstream (Meta, Snap, TikTok-shaped). Currently every adopter copies the same Shape B boilerplate: take the user's OAuth token, call /me/adaccounts, map each upstream record to an Account, return the one matching ref.
Proposed API
from adcp.decisioning import create_oauth_passthrough_resolver
resolve = create_oauth_passthrough_resolver(
http_client=upstream_client, # from #1
list_endpoint="/me/adaccounts",
id_field="id", # which field on each row identifies the account
to_account=lambda row, ctx: Account(...), # adapter's row→Account mapping
)
# Use as AccountStore.resolve
store = ExplicitAccounts(resolve=resolve)
Auto-handles OAuth refresh via dynamic_bearer.get_token from #1's auth modes.
Acceptance criteria
create_oauth_passthrough_resolver exported from adcp.decisioning.
- Tests cover: ref found, ref not found (returns None), upstream returns 401 (refresh path),
to_account raises (propagates).
Parent: #452
Depends on: #456 (Account v3 wire fields)
JS source
6.7 changeset
extend-v3-fallback.mdand recipe #12 in migration guide.Use case
For adapters wrapping a vendor OAuth +
/me/adaccounts-shaped upstream (Meta, Snap, TikTok-shaped). Currently every adopter copies the same Shape B boilerplate: take the user's OAuth token, call/me/adaccounts, map each upstream record to anAccount, return the one matchingref.Proposed API
Auto-handles OAuth refresh via
dynamic_bearer.get_tokenfrom #1's auth modes.Acceptance criteria
create_oauth_passthrough_resolverexported fromadcp.decisioning.to_accountraises (propagates).