Skip to content

feat(dashboard): scoped path-token auth for plugin views and complete the views rename - #10415

Merged
Soulter merged 6 commits into
AstrBotDevs:masterfrom
Soulter:codex/plugin-views-path-token
Oct 6, 2026
Merged

Soulter merged 6 commits into
AstrBotDevs:masterfrom
Soulter:codex/plugin-views-path-token

Conversation

@Soulter

@Soulter Soulter commented Oct 6, 2026 •

Copy link
Copy Markdown
Member

Summary

Two related changes around plugin views:

1. Complete the Pages -> Views rename

The rename was left half-done: the plugin card "Open View" button crashed with No match for {"name":"PluginPage"}. This finishes it:

  • Plugin card and detail page now navigate to the renamed PluginView route
  • PluginPagePage.vue -> PluginViewPage.vue (plus internal identifiers and CSS classes)
  • openPluginWebui -> openPluginView, open-webui emit -> open-view, pluginPageTitle/Description -> pluginViewTitle/Description, isPluginPageRoute -> isPluginViewRoute
  • i18n keys renamed across en/zh/ja/ru (pluginWebui -> pluginView, openWebui -> openView, pluginPageType -> pluginViewType, related messages)
  • OpenAPI tag Plugin Pages -> Plugin Views

The postMessage bridge channel name (astrbot-plugin-page) is intentionally kept: it is part of the wire protocol shared with plugin_page_bridge.js.

2. Path-token authentication for view assets

Plugin view assets are now served from:

/api/v1/plugins/{plugin}/views/{page}/_t/{token}/{asset...}

The scoped token travels in the URL path, so relative URLs inside the view inherit it through normal path resolution. View assets are served raw — the server-side HTML/CSS/JS URL rewriting is removed entirely (only bridge SDK injection and theme handling remain for HTML).

  • Token TTL aligned with the dashboard session (7 days), with a page_session purpose claim; scoped to a single plugin and page
  • Auth is enforced by a FastAPI dependency because v1 paths bypass the dashboard auth middleware
  • The view entry content_path is serialized as the _t URL (with the asset_token query echoed for view scripts that read it from location.search)

3. Legacy surface removed

  • /api/plugin/page/content/...?asset_token=... route removed
  • Redundant authenticated asset routes (/plugins/page/assets, /plugins/view/assets, /plugins/{id}/(pages|views)/{page}/assets/...) removed — no callers outside the generated client
  • The regex-based HTML/CSS/JS rewriting helpers are gone
  • PluginPageAuth slimmed to the bridge SDK endpoint, the only non-v1 path still authenticating scoped query tokens

Old-to-new mapping

Old New
Route name PluginPage PluginView
/api/plugin/page/content/<plugin>/<page>/...?asset_token=<token> /api/v1/plugins/<plugin>/views/<page>/_t/<token>/...
`/api/v1/plugins/(page view)/assets?..., /api/v1/plugins//(pages
i18n pluginWebui / openWebui / pluginPageType pluginView / openView / pluginViewType

Impact on plugin authors

None: relative asset paths and the plugin_page_bridge JS APIs are unchanged. Only the dashboard-internal URLs and auth mechanism changed.

Testing

  • pytest tests/test_dashboard.py: 88 passed (path-token route: anonymous fetch OK, assets served raw, wrong-plugin token 401, missing token rejected, traversal blocked, legacy route 404)
  • ruff format --check / ruff check: clean
  • pnpm build: passes

Summary by Sourcery

Complete the plugin Pages-to-Views rename and replace rewritten query-token asset URLs with scoped path-token authentication for raw plugin view assets.

New Features:

  • Authenticate plugin view assets with long-lived JWTs embedded in plugin- and view-scoped URL paths.
  • Serve plugin view assets without rewriting relative HTML, CSS, or JavaScript URLs.

Bug Fixes:

  • Fix plugin view navigation to use the renamed PluginView route and prevent route-match failures.

Enhancements:

  • Complete the Pages-to-Views terminology rename across the dashboard, API, generated clients, localization, and OpenAPI definitions.
  • Remove legacy content and redundant authenticated asset routes while retaining deprecated pages aliases.
  • Update plugin view documentation and coverage for path-token authentication, raw assets, scoping, traversal protection, and legacy route removal.

Documentation:

  • Document path-token view asset URLs, session-scoped authentication, raw asset serving, and removal of the legacy content route.

Tests:

  • Expand dashboard tests to cover anonymous path-token access, token scope validation, raw relative assets, traversal protection, and removed legacy routes.

Finish the remaining Pages -> Views rename on the dashboard:

- Fix the plugin card "Open View" button crash by pointing
  openPluginWebui at the renamed PluginView route
- Rename PluginPagePage.vue to PluginViewPage.vue and update its
  internals (loadPluginView, pluginViewTitle, .plugin-view-* classes)
- Rename openPluginWebui -> openPluginView and the open-webui emit to
  open-view; pluginPageTitle/Description -> pluginViewTitle/Description;
  isPluginPageRoute -> isPluginViewRoute
- Rename i18n keys (pluginWebui -> pluginView, openWebui -> openView,
  pluginPageType -> pluginViewType, messages) across en/zh/ja/ru locales

The postMessage bridge channel name (astrbot-plugin-page) is kept
unchanged because it is part of the wire protocol shared with
plugin_page_bridge.js.
Serve plugin view assets from
/api/v1/plugins/{id}/views/{page}/_t/{token}/... so the scoped token
travels in the URL path. Relative URLs inside the view then inherit the
token through normal path resolution, which removes the need for
server-side HTML/CSS/JS URL rewriting on this route.

- Add the _t routes with a require_plugin_view_token dependency
  (v1 paths bypass the dashboard auth middleware)
- Extend the plugin page asset token to a session-length TTL (7 days,
  aligned with the dashboard session) with a page_session purpose claim,
  still scoped to a single plugin and page
- Serialize the view entry content_path as the _t URL, keeping the
  asset_token query for plugins that parse location.search
- Keep the legacy /api/plugin/page/content/...?asset_token= form working
  during the transition
- Rename the OpenAPI tag Plugin Pages -> Plugin Views, document the new
  route, regenerate the frontend API client, and update the zh/en
  plugin-pages docs

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've reviewed your changes and they look great!

Sourcery assessment

Needs a human reviewer. This changes how unauthenticated requests obtain plugin-view access and extends scoped JWT validity from 60 seconds to seven days, so a leaked path token can expose the corresponding view assets for much longer. Because the TTL and trust boundary are policy decisions, an overly permissive choice affects every issued token immediately, and reverting will not invalidate tokens already issued.


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

…URL rewriting

The path-token view route makes the compatibility surface unnecessary:

- Drop /api/plugin/page/content/... (query asset_token form)
- Drop the redundant authenticated asset routes /plugins/page/assets,
  /plugins/view/assets, and /plugins/{id}/(pages|views)/{page}/assets/...
  which had no callers outside the generated client
- Remove the HTML/CSS/JS URL rewriting helpers; view assets are always
  served raw and only HTML gets bridge SDK injection plus theme handling
- Slim PluginPageAuth down to the bridge SDK endpoint, the only
  non-v1 path still authenticating scoped query tokens
- serialize_plugin_page no longer falls back to the legacy content path
- Update the plugin-pages docs (zh/en) and the OpenAPI spec, and
  regenerate the frontend API client
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
astrbot-docs 475fe63 Commit Preview URL

Branch Preview URL
Oct 06 2026, 09:14 AM

Remove the page-named plugin view API aliases now that the views rename
is complete and legacy compatibility is intentionally dropped:

- DELETE /api/v1/plugins/page(s) and /plugins/{plugin_id}/pages{,/{page_name}}
  aliases; /plugins/view(s) and /plugins/{plugin_id}/views{,/{page_name}}
  are the only entry config routes
- Remove the unused /api/v1/plugins/page-bridge-sdk.js route; the live
  bridge SDK stays at /api/plugin/page/bridge-sdk.js
- Dashboard calls the view-named endpoints; regenerate the API client
  and the OpenAPI scopes docs
Restore the page-named plugin view routes removed in the previous commit
and keep them for a transition period, with view as the canonical API:

- /plugins/page(s) and /plugins/{plugin_id}/pages{,/{page_name}} serve as
  aliases of the corresponding /views routes (same handlers)
- The OpenAPI spec marks the page operations deprecated and points new
  clients at the view routes; the v1 page-bridge-sdk.js route is restored
- The dashboard keeps calling the view endpoints by default
The view entry and path-token asset routes now use {view_name} instead of
{page_name} in the OpenAPI-visible path, and the service layer renames its
internal page_name variables to match. Wire-compatible surfaces stay
unchanged: the page_name JWT claim, the pageName JSON field, query
parameters, and the deprecated /pages aliases. Error messages and the
plugin view docs (zh/en) complete the Page to View rename.
@Soulter
Soulter merged commit 8831d95 into AstrBotDevs:master Oct 6, 2026
23 checks passed
@Soulter
Soulter deleted the codex/plugin-views-path-token branch October 6, 2026 10:18
@C10H14N2O5 C10H14N2O5 mentioned this pull request Oct 6, 2026
5 tasks done
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.

1 participant