feat: support quota published by custom OAuth-login plugins - #883
Open
collegeming wants to merge 4 commits into
Open
collegeming wants to merge 4 commits into
collegeming wants to merge 4 commits into
Conversation
CPA exposes plugin quota generically: a plugin publishes a quota provider on /v0/management/quota/providers, binds its credentials through the quota_provider reported on /v0/management/auth-files, and answers labelled readings on /v0/management/plugins/:id/quota. The quota snapshot store only accepted the providers compiled into validProviders, so a plugin-owned credential could never keep quota evidence. The service now validates a provider against the built-in allowlist plus a runtime catalogue the caller registers from CPA's own answer, and WritePluginQuotaResult maps each labelled reading into the existing window model: the plugin's item key is the provider window id, its unit is the stored quota unit and a finite numeric reading is stored as the window amount. Plugin labels, formats and currencies are presentation hints CPA returns on every read, and the snapshot model deliberately persists no provider display strings. An unregistered plugin provider is ignored by WritePluginQuotaResult and stays rejected by the generic Write and Query entry points, so the built-in allowlist is unchanged.
Add a plugin quota source that is driven entirely by CPA's own contract: the provider catalogue, the credential binding and the item keys all arrive at runtime, so no provider name or channel is compiled into the panel. - internal/pluginquota is a transport-only client for /v0/management/quota/providers, /v0/management/plugins/:id/quota and the explicit /v0/management/quota/fetch action. It keeps a plugin's value shape (number, boolean or string) instead of coercing it into fake numeric evidence, and keeps CPA's plugin id verbatim for management URLs. - internal/service/pluginquota resolves one credential by CPA's auth index, writes what the plugin reports through the same quota snapshot service the panel and the collector already use, and reuses a short-lived provider catalogue so a panel refresh does not re-list providers per credential. - The panel reads and triggers it through /v0/management/plugin-quota/*, and a worker mirrors the Codex inspection worker: one pass at startup, then a periodic pass that only reads cached plugin quota. CPAMP_PLUGIN_QUOTA_ENABLED and CPAMP_PLUGIN_QUOTA_REFRESH_INTERVAL tune it. Unknown or removed plugins produce no rows and no error, and a summary without usable items is ignored rather than deactivating a credential that still owns quota.
A plugin quota is a set of labelled readings rather than the fixed windows the seven built-in providers expose, so the panel gains a 'plugin' quota type whose config is derived at runtime from the Manager Server's provider catalogue. - The provider catalogue is loaded once per connection and published through a subscribable store, so a credential is recognised by CPA's own quota_provider binding and an unknown plugin still resolves. - Each reading becomes a non-window display item that reuses the existing quota window pipeline: the accounts list 额度 column shows the plugin's own amount, and the detail 额度 tab renders the items under "other quota items" with the plugin's label, value, unit and format. - Plugin amounts render through their plugin format hint (number, currency, percent, boolean) without the panel interpreting a plugin unit, and a failed refresh keeps the previous items visible. - Adds plugin_quota strings for zh-CN, zh-TW, en and ru, and tests for the catalogue, the fetcher, the config state machine and the display windows.
Record that a plugin quota provider publishes its labelled items through CPA's quota.* management endpoints, that CPA names the provider and its credential binding, and that CPAMP renders each item verbatim instead of interpreting a plugin unit.
This branch has not been deployed
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
Custom plugins that implement OAuth login for other providers can only offer
their accounts to CPA, not to CPAMP: CPA already exposes each plugin's quota
over its management API and the plugins answer it, but the Manager Server has no
plugin quota source, so those credentials show no quota anywhere in the panel.
This adds a generic plugin quota source that consumes CPA's plugin quota
contract, and renders the items it returns in the places the panel already
shows quota.
Target branch:
dev.Scope
Changes
internal/pluginquotaclient for the generic pluginquota endpoints (
GET /v0/management/quota/providers,GET /v0/management/plugins/:id/quota?auth_index=…,POST /v0/management/quota/fetch), and aninternal/service/pluginquotaservice that resolves a credential by CPA's auth index, fetches what its
plugin reports and persists it through the quota snapshot service the panel
and the collector already use.
built-in provider allowlist still rejects every unknown provider; the plugin
catalogue is a runtime set, and a plugin provider is only accepted after CPA
named it on
/v0/management/quota/providers.WritePluginQuotaResultmaps each labelled item into theexisting window model, and
/v0/management/plugin-quota/{providers,credential,refresh}exposes the catalogue, the per-credential readings (the explicit refresh
action) and a periodic refresh worker modelled on the Codex inspection worker.
pluginquota type whose config is derived at runtime from thecatalogue, so a credential is recognised by the binding CPA reports
(
quota_provideron the auth file) or by the catalogue's supportedcredentials. Each reading becomes a non-window display item: the accounts
list 额度 column shows the plugin's own amount and the detail 额度 tab renders
the labelled items under "other quota items".
evidence source in both languages.
User Impact
A credential that belongs to a plugin with a quota provider now shows that
plugin's labelled readings instead of "no quota data": the credential list's
quota column, the credential detail quota tab and the persisted quota snapshot
history all show the same items. Built-in providers are unaffected. When a
plugin is missing or does not answer, nothing is shown and nothing breaks.
Compatibility / Runtime Notes
without a Manager Server connection keeps its previous behaviour and simply
has no plugin quota source.
CPAMP_PLUGIN_QUOTA_ENABLED(defaulton) and
CPAMP_PLUGIN_QUOTA_REFRESH_INTERVAL(default10m, accepting a Goduration or seconds). The periodic pass only reads the plugin's cached quota;
/v0/management/quota/fetchis called only when a caller explicitlyrequests a refresh.
A CPA build without these endpoints answers the catalogue with an empty list,
which is a valid "no plugin quota" answer.
name, provider name or item key is compiled into the panel, so a new plugin
works without a CPAMP change.
Data / Security Notes
(
window_kind=item,window_mode=non_window, the plugin's unit inquota_unitand a finite numeric reading as the window amount), keyed by thecredential identity the panel already uses (auth file +
auth_index).deliberately stores no provider display strings, and the panel renders them
from the live observation.
existing quota snapshot and monitoring routes and reuse CPA's Management Key
through the existing server-side connection, so no key is exposed to the
browser and no credential file is read or modified.
Risk / Rollback
Risk level: Low
Rollback notes: the change is additive and needs no migration. Revert the
commits, or disable the worker with
CPAMP_PLUGIN_QUOTA_ENABLED=falseto stopperiodic plugin quota reads; previously stored snapshots and every built-in
provider keep working either way.
Verification
Commands / evidence:
Live check against a running CPA with plugins that publish quota:
Manual check: with the built image running, the credential list quota column
shows the plugin's items and amounts, and the credential detail quota tab
renders the same items instead of the "no quota window" empty state; the
dashboard, monitoring, config, plugins and logs pages still load.
Screenshots / Recordings
Manual UI check screenshots (credential list quota column, credential detail
quota tab) were captured during the live check described above.
Docs
Docs decision:
apps/docs/manual/accounts.mdandapps/docs/en/manual/accounts.mdgained a plugin-provider row in the quotaevidence table. README does not enumerate quota sources per provider, and the
demo fixtures have no plugin credential, so neither needed a change.
Related
N/A