Repository navigation
Conversation
Discover trusted package manifests at runtime and reuse ConsoleModule for menus, routes and overview cards. Share host React and shell providers without adding plugin management UI. Fixes #113
9 tasks done
Resolve built-in and remote modules through one startup navigation tree. Preserve sibling order, nested folders and existing page permissions; reject invalid declarations and mount collisions before executing remote entries. Refs #113
huskcass
reviewed
Nov 10, 2026
Collaborator
There was a problem hiding this comment.
Blockers (design scope / existing UI behavior):
- Built-ins now depend on plugin discovery.
main.tsxwaits for/plugins/index.jsonbefore the first render, login included. Inplugins.ts, a failed discovery returnsmodules: []. A remotemenu.paththat equals a built-in base path passes Go validation.validateFrontendPathsthen throws in the outertryand drops every module, not just the bad remote; I checked this locally. On main, the five built-ins always render. Keep built-ins from the compiled registry no matter what happens to discovery. Reject built-in base paths in Go at startup. Let a failure affect only the remote that caused it. - The vendored SDK is much larger than its one consumer needs. The canary frontend uses
createPlugin,getBusiness().console,./buildand./dev. These parts have no caller and no backend in Console:cluster-resource-api(/oapis/resources.theriseunion.io)scope-filterandcluster-display-namecreate-instance- the SDK
i18nchannel and locales, andtesting - slots, the event bus and the
navstub incore.ts, plus most oftypes.ts
That is roughly 2.5k lines of source and tests. Host extras that only mirror that surface can go too:ScopeContext,getScope,get("auth"),apiClient,formatDate, and the__GLOBAL_SDK__/__RISE_SDK__aliases. Keeping the SDK in a separate pnpm lockfile and CI job, beside the npm web project, doubles the toolchain for a private package. Trim it to the used surface and build it with the existing web job.
- The config tree has more modes than any current need.
pluginsdoesn't exist on main, so the "legacy unmarked remote list" mode supports a format that was never released. Its browser branch is also dead, because Go stamps every leaf with asource.default-plugins.yamlduplicatesmodules/index.ts.source: builtinselection and nested folders have no requester today. Simpler: leavepluginsunset for the compiled modules, and have each entry be a remote appended after them. Add folders or built-in selection when someone actually needs them.
Non-blocking:
- The menu is declared twice. The plugin's
createPlugin({ menus })is ignored by the host, while the YAML has to repeat title, label, path and component. Pick one source. - Development mode (WebSocket hijack, Host/Origin forwarding) sits in the production proxy behind a values flag. The console Vite dev server could proxy
/plugins/<id>straight to the plugin's Vite server instead. If it stays, keepdevelopment: trueout of production values. - Each asset load waits up to 15s, one after another, before first paint. An unreachable plugin service delays the whole console.
- The asset proxy forwards any relative path to the configured upstream, not only the declared entry and styles. That's fine for a static image, but worth restricting.
Verified at cc29e7a: go build, go vet and go test ./... pass, and web tsc -b and vitest pass (511 tests).
Verdict: loading one trusted remote frontend is justified, but trim to that before merge.
— Review Golden
20 tasks
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.
What type of PR is this?
What this PR does and why
Console now loads enabled built-in modules and separately delivered SDK frontends from one startup YAML tree. Operators control module order and nested menu directories through configuration. Built-ins resolve against the compiled registry; remote entries register their actual pages through the ModelSphere SDK. Permission filtering hides empty folders, active detail routes open their ancestors, and collapsed navigation retains descendant links.
Maintain the reusable SDK in
web/packages/plugin-sdkas@modelsphere/plugin-sdk, with source attribution and compatible host-global aliases. The host shares its actual React, Router, Query, UI, locale and authenticated API transport. Plugin development uses Vite, the same-origin WebSocket proxy and the host React Refresh runtime; compatible component edits and new shared imports preserve local state. Production serves built JavaScript/CSS from a static-resource image.The embedded YAML provides default built-in navigation. Explicit trees select only their listed modules;
plugins: []disables modules, and omitted/null configuration uses defaults. Legacy unmarked remote declarations retain default built-ins followed by remotes. Configuration changes require a backend restart and browser refresh; changing menu position or folders does not require rebuilding the plugin image.Which issue(s) this PR fixes
Fixes #113
How it was tested
Browser component checks used
web/test/plugin-runtime.html; authenticated business endpoints returned 401 in the anonymous test session. Screenshots and local environment configuration remain outside the repository.Checks
go test ./...,go vet ./..., and changed Go files formattedhelm lint --strict helm/consoleNotes for reviewers
Start with
docs/development/plugins.mdand the SDK/configured-navigation proposals indocs/plans/.internal/config/default-plugins.yamlandnavigation.go: default/legacy/explicit tree semantics and validation.internal/server/plugin_service.go: tree discovery and resource-only proxying of remote leaves.web/src/shell/plugin-tree.ts,plugins.ts,Sidebar.tsx: preflight mount collision checks, ordered loading and nested directories.web/packages/plugin-sdk/src/dev.tsanddev-shared.ts: host runtime sharing and Vite Fast Refresh.Discovery failures keep only the shell rather than enabling unconfigured modules. Remote load failures preserve other valid configured modules. Folder metadata changes neither page permissions nor business API authorization.
Release note
GitHub verification
Latest head:
cc29e7a(includes navigation commit4745dbc). CI 42247317988 and publish 42247318085 passed. PR #114 is conflict-free and awaiting an Approver review.