feat(configure): plugin OAuth account picker, multi-account hide, configured status (#336, #337, #338)#339
Merged
Conversation
…figured status Three configure-UI refinements for broker-OAuth plugin providers (design B, e.g. the Logly-managed Meta provider). OSS carries the mechanism; the plugin supplies the values/behaviour — mureo-pro needs no change. #336 — post-auth account picker. Add declarative `AccountOAuthConfig.accounts_field` (the field the picker fills) plus an optional provider hook `list_oauth_accounts(credentials) -> Sequence[Mapping]` discovered via `get_oauth_account_lister`. New backend `plugin_credentials.list_oauth_accounts()` loads the stored credentials section, invokes the hook (sync or async, bridged off the request thread), and normalises to `[{"id","name"}]` — the token never reaches logs and any hook failure (including a non-iterable return) collapses to a clean 502, never a raw 500. New GET `/api/credentials/plugins/<provider>/accounts` maps the typed errors to 404/409/502. The dashboard renders that field as a picker (Load -> radios -> dedicated Save) instead of free-text; picker radios are excluded from the OAuth Authenticate-is-save payload. #337 — multi-account hide. `multi_account_picker_scope()` returns, per OAuth provider, an allow-list excluding `accounts_field`; `_resolve_field_scope` merges it when a multi-account backend is active (an explicit backend scope wins). The per-account id is selected per-client at runtime, so pinning one at configure time is meaningless — this both hides the input and exempts it from required-validation, with no declaration needed from the agency backend. #338 — configured status. The OAuth target-field status row shows "Configured ✓" when the token is already stored (keyed off the injected `field.configured`), instead of always prompting to Authenticate. The input-suppression for the target field already shipped in #217. A typo'd `accounts_field` is rejected at the registry boundary (loud ValueError) so a wiring mistake can't silently disable the picker or the multi-account hide. Closes #336, #337, #338 Claude-Session: https://claude.ai/code/session_011rAu94b1o1xWYZhARk1VmL
This was referenced Jun 25, 2026
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.
Summary
Three configure-UI refinements for broker-OAuth plugin providers (design B — e.g. the Logly-managed Meta provider
meta_ads_logly). The OSS layer carries the mechanism; the plugin supplies the values/behaviour, so mureo-pro needs no change.#336 — post-auth account picker
AccountOAuthConfig.accounts_field(the field the picker fills) + optional provider hooklist_oauth_accounts(credentials) -> Sequence[Mapping], discovered defensively viaget_oauth_account_lister.plugin_credentials.list_oauth_accounts(): loads the stored credentials section, invokes the hook (sync or async, bridged off the request thread), normalises to[{"id","name"}]. The token never reaches logs; any hook failure — including a non-iterable return — collapses to a clean 502, never a raw 500.GET /api/credentials/plugins/<provider>/accountsmaps typed errors to 404 / 409 / 502.type="button"-safe and excluded from the OAuth Authenticate-is-save payload.#337 — hide
account_idwhen multi-account (agency) is activemulti_account_picker_scope()returns a per-provider allow-list excludingaccounts_field;_resolve_field_scopemerges it when a multi-account backend is active (an explicit backend scope wins).#338 — "Configured ✓" status
field.configured), instead of always prompting to Authenticate. (Input suppression for the target field already shipped in Plugin OAuth providers: replace Save with a single Authenticate-and-persist action — required target_field deadlocks first-time setup #217.)A typo'd
accounts_fieldis rejected at the registry boundary (loudValueError) so a wiring mistake can't silently disable the picker or the multi-account hide.Test plan
mureo.web.plugin_credentials—list_oauth_accounts(normalisation, async hook, async-from-running-loop, unknown provider, not-supported, not-authenticated, hook-failure-wrapped, non-iterable-return → 502, token-never-logged),multi_account_picker_scope, oauth-block surfacing.accounts_fieldvalidation (valid / typo→ValueError),get_oauth_account_lister(callable / absent / non-callable)._resolve_field_scopemulti-account fold-in (auto-hide, backend-override, single-account no-op).ruff+blackclean onmureo/;mypy --strictclean on changed files;node --checkondashboard.js.Closes #336, #337, #338
https://claude.ai/code/session_011rAu94b1o1xWYZhARk1VmL