[loader] Add Web/PWA plugin asset server #217

Closed
opened 2026-06-02 09:43:31 +00:00 by steve · 0 comments
Owner

Problem

Installed plugin files stored through vault adapters are not naturally URL-addressable in the browser, but dynamic import() requires module URLs for ESM plugins.

Goal

Define and implement the Web/PWA plugin asset serving path needed to import verified installed ESM plugin files from versioned same-origin URLs.

Scope

  • Add the shared PluginAssetServer interface.
  • Add a service-worker backed web implementation for /__lapis/plugins/[vault-id]/[plugin-id]/[version-or-hash]/[path].
  • Mirror verified plugin assets into Cache Storage as needed.
  • Serve correct MIME types for JavaScript, CSS, JSON, and WASM.
  • Add path traversal, installed-plugin, provenance, and hash verification checks.
  • Define a dev-only single-file Blob fallback policy if needed.

Non-goals

  • Do not serve arbitrary vault user files through plugin asset routes.
  • Do not allow untrusted remote plugin asset URLs.
  • Do not implement Electron custom protocol support in this issue.

Acceptance Criteria

  • Web can import /__lapis/plugins/.../main.mjs.
  • Relative ESM imports work once asset serving supports them.
  • Updated plugin versions use new module URLs.
  • Unsafe paths and missing or modified files fail safely.

Implementation Notes

  • Prefer version or content hash in URLs because browser ESM modules are cached for the document lifetime.
  • Use verified installed-plugin state when hashes or registry provenance are available.
  • Keep temporary Blob loading development-only and single-file only.

Active Implementation Plan

  • Keep the shared API helpers host-neutral and add a Web-host implementation that satisfies PluginAssetServer.
  • Use the active vault adapter plus DefaultPluginDistributionManager.getInstalled() to resolve installed plugin metadata, verify every mirrored file with the existing size/SHA-256 helper, and store versioned responses in Cache Storage under /__lapis/plugins/....
  • Add a generated-service-worker runtime route for /__lapis/plugins/ that serves only mirrored cache entries, so relative ESM imports resolve under the same same-origin URL space.
  • Register the Web implementation before workspace plugin loading by passing it into mountWorkspaceApp() from the web host entrypoint.
  • Cover cache mirroring, MIME headers, versioned URLs, and traversal/missing-file failures with focused tests.

Affected Packages and Files

  • packages/api/src/lib/plugin-asset-server.ts
  • packages/api/src/lib/__tests__/plugin-asset-server.test.ts
  • packages/web/src/main.ts
  • packages/web/src/plugin-asset-server.ts
  • packages/web/vite.config.ts
  • spec/src/20-packages/web/index.md
  • spec/src/30-cross-package-contracts/plugin-runtime.md

Suggested Files or Specs To Inspect

  • spec/src/20-packages/web/index.md
  • spec/src/30-cross-package-contracts/plugin-runtime.md
  • spec/src/30-cross-package-contracts/plugin-registry.md
  • packages/api/src/lib/plugin-distribution/
  • packages/web/src/

Validation Commands

  • pnpm --filter @lapis-notes/api check:all
  • pnpm --filter @lapis-notes/web check:all
  • pnpm check:all

Follow-up Tasks

Implementation Summary

Implemented a Web/PWA PluginAssetServer that verifies installed plugin metadata, mirrors supported assets into Cache Storage under versioned /__lapis/plugins URLs, registers the Workbox CacheOnly route, updates workspace host wiring, and documents/tests the behavior.

## Problem Installed plugin files stored through vault adapters are not naturally URL-addressable in the browser, but dynamic `import()` requires module URLs for ESM plugins. ## Goal Define and implement the Web/PWA plugin asset serving path needed to import verified installed ESM plugin files from versioned same-origin URLs. ## Scope - Add the shared `PluginAssetServer` interface. - Add a service-worker backed web implementation for `/__lapis/plugins/[vault-id]/[plugin-id]/[version-or-hash]/[path]`. - Mirror verified plugin assets into Cache Storage as needed. - Serve correct MIME types for JavaScript, CSS, JSON, and WASM. - Add path traversal, installed-plugin, provenance, and hash verification checks. - Define a dev-only single-file Blob fallback policy if needed. ## Non-goals - Do not serve arbitrary vault user files through plugin asset routes. - Do not allow untrusted remote plugin asset URLs. - Do not implement Electron custom protocol support in this issue. ## Acceptance Criteria - Web can import `/__lapis/plugins/.../main.mjs`. - Relative ESM imports work once asset serving supports them. - Updated plugin versions use new module URLs. - Unsafe paths and missing or modified files fail safely. ## Implementation Notes - Prefer version or content hash in URLs because browser ESM modules are cached for the document lifetime. - Use verified installed-plugin state when hashes or registry provenance are available. - Keep temporary Blob loading development-only and single-file only. ## Active Implementation Plan - Keep the shared API helpers host-neutral and add a Web-host implementation that satisfies `PluginAssetServer`. - Use the active vault adapter plus `DefaultPluginDistributionManager.getInstalled()` to resolve installed plugin metadata, verify every mirrored file with the existing size/SHA-256 helper, and store versioned responses in Cache Storage under `/__lapis/plugins/...`. - Add a generated-service-worker runtime route for `/__lapis/plugins/` that serves only mirrored cache entries, so relative ESM imports resolve under the same same-origin URL space. - Register the Web implementation before workspace plugin loading by passing it into `mountWorkspaceApp()` from the web host entrypoint. - Cover cache mirroring, MIME headers, versioned URLs, and traversal/missing-file failures with focused tests. ## Affected Packages and Files - `packages/api/src/lib/plugin-asset-server.ts` - `packages/api/src/lib/__tests__/plugin-asset-server.test.ts` - `packages/web/src/main.ts` - `packages/web/src/plugin-asset-server.ts` - `packages/web/vite.config.ts` - `spec/src/20-packages/web/index.md` - `spec/src/30-cross-package-contracts/plugin-runtime.md` ## Suggested Files or Specs To Inspect - `spec/src/20-packages/web/index.md` - `spec/src/30-cross-package-contracts/plugin-runtime.md` - `spec/src/30-cross-package-contracts/plugin-registry.md` - `packages/api/src/lib/plugin-distribution/` - `packages/web/src/` ## Validation Commands - `pnpm --filter @lapis-notes/api check:all` - `pnpm --filter @lapis-notes/web check:all` - `pnpm check:all` ## Related Issues ## Follow-up Tasks ## Implementation Summary Implemented a Web/PWA PluginAssetServer that verifies installed plugin metadata, mirrors supported assets into Cache Storage under versioned /__lapis/plugins URLs, registers the Workbox CacheOnly route, updates workspace host wiring, and documents/tests the behavior. <!-- backlog:task_id=TASK-PLUGIN-LOADER-005 source_spec=spec/src/30-cross-package-contracts/plugin-runtime.md -->
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lapis-notes/lapis#217
No description provided.