Skip to content

feat(extensions): install independently distributed right-panel addons - #862

Open
pascalandr wants to merge 1 commit into
devfrom
feat/external-panel-extensions
Open

pascalandr wants to merge 1 commit into
devfrom
feat/external-panel-extensions

Conversation

@pascalandr

Copy link
Copy Markdown
Contributor

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 in examples/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

  • UI and server typechecks.
  • 14 focused server/registry/manifest tests.
  • Real right-panel browser tests for ZIP consent, activation scopes, replacement, revocation, context changes, stale reads and frame isolation.
  • node scripts/test-panel-extension-native.mjs on 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.
  • UI build, Windows Tauri release build (--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).

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.
@pascalandr

Copy link
Copy Markdown
Contributor Author

Gatekeeper review — pass 1

I 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 df8b10ef: the confirmation captures the exact { id, digest }, is invalidated when that package changes, and sends only that captured digest. I added the real-route browser reproduction; all four extension browser scenarios pass.

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.

@pascalandr

Copy link
Copy Markdown
Contributor Author

Gatekeeper review — pass 2

I rechecked df8b10ef independently against dev: zero remaining actionable P1/P2 findings.

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.

@pascalandr

Copy link
Copy Markdown
Contributor Author

Validation on df8b10ef

I passed both typechecks, 14 focused server/registry/manifest tests, all 4 extension browser scenarios, and the shared tab-chrome browser checks. I rebuilt the final Windows Tauri release after the consent fix; packaged server/Node/dependency/static-asset checks passed. I also ran the isolated WebView2 fixture using the workspace lock: context delivered, parent DOM/network blocked, parent native command allowed, direct/raw child commands denied.

I started the full npm run test:browser --workspace @codenomad/ui suite. It is not green: existing native Electron fixtures fail because this isolated checkout has no installed Electron executable (Electron failed to install correctly). The remaining Chromium scenarios are still running. I am not installing or launching Electron to bypass the Tauri-only GUI validation requirement; I have not changed those fixtures or the shared daemon.

I published both independent gatekeeper passes above: the one reproduced P2 is fixed and the final review has zero remaining actionable P1/P2 findings. Native Electron/macOS/Linux qualification and #801's gallery remain outside these results. I am making this PR ready for review, not merging it or claiming green CI.

@pascalandr
pascalandr marked this pull request as ready for review October 6, 2026 10:14
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