feat(extensions): install independently distributed right-panel addons - #862
pascalandr wants to merge 1 commit into
Conversation
Allow users to inspect and install author-owned GitHub release ZIPs without rebuilding CodeNomad or touching the shared OpenCode daemon. Require an exact manifest/API contract and trust confirmation, start disabled, persist profile-wide or exact-folder grants, and revoke every activation when replacing code. Keep external HTML outside the primary renderer behind an opaque sandbox, restrictive CSP and per-mount context channel. Fence panel responses and author ports across session/project changes, disconnects, revocation and replacement; bind removal consent to the reviewed package digest so another window cannot redirect it to newer code. Document immutable GitHub release/checksum rules and public API compatibility with an independent starter. Add bounded ZIP/store/route regressions, real right-panel browser coverage, and an isolated Tauri/WebView2 native-command denial fixture with positive parent control. Keep the assets-history capability, marketplaces and automatic updates out of this distribution PR.
Gatekeeper review — pass 1I ran an independent review of the distribution, consent, scope and sandbox flows. I found no P1 issues and one P2: an open removal confirmation retained only the addon ID, so a replacement in another window could make it delete the new version. I fixed it in The reviewer independently ran 3/3 server checks, 3/3 original browser scenarios and the isolated native fixture. The native positive control executed from the parent; direct/raw child commands did not. The follow-up review is in progress; this is not yet the zero-finding sign-off. |
Gatekeeper review — pass 2I rechecked I verified that removal consent stays bound to the reviewed package digest and is cleared after replacement. The real-route race regression passes. I also rechecked authorization, ZIP bounds, installation/replacement consent, activation scopes, session/disconnect fences, sandboxing, customization and translations. Independent checks: 4/4 extension browser scenarios, 3/3 server checks, UI typecheck, and 4 tab-chrome browser checks passed. The native Electron scenario was skipped. The earlier isolated Windows Tauri fixture passed its parent-command positive control and direct/raw child-command denial checks. I did not access the shared daemon or user profiles. I have not qualified native Electron, macOS or Linux; these results do not claim process isolation or implement #801's gallery. |
Validation on
|
What changes
I add independently distributed right-panel UI extensions. An author can publish a self-contained ZIP in a separate GitHub repository, and users can inspect/install it without rebuilding CodeNomad or restarting OpenCode.
I show the manifest and exact archive SHA-256 before trust confirmation. Installation starts disabled; users enable it for all projects in the server profile or for the exact opened folder. Replacement requires the previous digest and revokes every activation grant. Removal is explicit. Packages and grants stay outside project/OpenCode storage.
I keep author code out of the main renderer. API 1 exposes only session ID, locale and appearance through a per-mount MessageChannel. It does not expose filesystem, transcript, images, credentials, native commands or the OpenCode proxy. Frames are sandboxed without same-origin access and receive a restrictive CSP; obsolete responses and ports are fenced on project/session changes, disconnects, revocation and replacement.
I document the package, permissions, API compatibility, scope, release/checksum and maintainer rules in
dev-docs/PANEL_EXTENSIONS.md, with a standalone starter inexamples/panel-extension/. GitHub's source ZIP is not an installable package. There is no marketplace, URL installer or automatic update.Scope and limits
I keep #801's assets gallery for a separate follow-up. It needs a bounded, authorized image/history capability rather than access to internal stores. This PR only establishes external distribution and a minimal context API.
Windows Tauri may inject native bridge objects into subframes: object presence is not a grant. My isolated WebView2 fixture proves parent command execution while direct/raw child calls do not reach it, and verifies context delivery plus DOM/network restrictions. A trusted hostile extension can still stall its renderer or attempt self-navigation; this is not process isolation or a universal offline guarantee. The installer warns users to trust the author.
I have not run a native Electron/macOS/Linux qualification or changed the shared daemon. The runtime implementation is shared between desktop hosts; native GUI validation here is Tauri only.
Validation
node scripts/test-panel-extension-native.mjson Windows, using the application's locked Tauri dependencies and an isolated browser profile: parent native call allowed; child native calls, parent DOM and network APIs blocked; session context delivered.--no-bundle) and packaged-resource smoke passed. Full browser suite results are recorded in the follow-up validation comment.Existing oversized files touched only for integration:
packages/server/src/api-types.ts(~735 lines),packages/server/src/index.ts(~713),packages/server/src/server/http-server.ts(~2,438).