162 lines
6.1 KiB
Markdown
162 lines
6.1 KiB
Markdown
# Remote WebUI Bundle Loading
|
|
|
|
GovOPlaN WebUI modules normally ship through the core WebUI package graph:
|
|
install a tagged npm/git dependency, run `npm install`, rebuild the shell, and
|
|
restart or reload the served assets. Remote WebUI bundles are an experimental
|
|
future path for controlled deployments where a backend-enabled module is not in
|
|
the local WebUI package graph and the operator wants the shell to load its
|
|
frontend without rebuilding core.
|
|
|
|
This design defines the target guardrails. The current rebuild/reload path
|
|
remains the default production path.
|
|
|
|
## Current Rebuild Path
|
|
|
|
The supported release path is:
|
|
|
|
1. Install or remove backend and WebUI package dependencies through the trusted
|
|
installer CLI/daemon.
|
|
2. Snapshot package state before mutation.
|
|
3. Run `npm install` and optionally `npm run build`.
|
|
4. Restart or reload the served WebUI assets.
|
|
5. Use installer rollback if package apply, restart, or health checks fail.
|
|
|
|
Strengths:
|
|
|
|
- package manager and lockfile semantics stay conventional
|
|
- CSP can stay strict because all code is served as built assets
|
|
- rollback restores package files and lockfiles
|
|
- local development uses sibling workspace dependencies naturally
|
|
|
|
Costs:
|
|
|
|
- frontend changes require a rebuild/reload
|
|
- hot enabling a module with frontend code is not possible in the running shell
|
|
- failed rebuilds happen at install time, not at lazy module-load time
|
|
|
|
## Remote Bundle Path
|
|
|
|
Remote loading is only for modules that are enabled by the backend and absent
|
|
from `virtual:govoplan-installed-modules`. The backend manifest exposes:
|
|
|
|
- `FrontendModule.asset_manifest`
|
|
- `asset_manifest_integrity`
|
|
- `asset_manifest_signature`
|
|
- `asset_manifest_public_key_id`
|
|
- `asset_manifest_contract_version`
|
|
|
|
The WebUI shell fetches the asset manifest, verifies manifest integrity and/or
|
|
signature, validates the manifest contract, fetches the entry bundle, verifies
|
|
the entry integrity, imports the bundle, validates the exported
|
|
`PlatformWebModule`, and applies backend metadata before registering routes,
|
|
navigation, and UI capabilities.
|
|
|
|
Unsigned and unhashed manifests are skipped. Entries without integrity are
|
|
skipped. A module id mismatch is skipped.
|
|
|
|
## Asset Manifest Contract
|
|
|
|
Contract version `1`:
|
|
|
|
```json
|
|
{
|
|
"contractVersion": "1",
|
|
"moduleId": "files",
|
|
"entry": "./files-webui.remote.js",
|
|
"entryIntegrity": "SHA-256-<base64-or-hex-digest>",
|
|
"moduleExport": "default"
|
|
}
|
|
```
|
|
|
|
The backend manifest carries the manifest-level trust metadata. The remote
|
|
asset manifest carries the concrete entry URL and entry digest.
|
|
|
|
## Compatibility Checks
|
|
|
|
Before a remote bundle is accepted:
|
|
|
|
- backend module must be enabled
|
|
- local WebUI module with the same id must be absent
|
|
- manifest contract must be supported by the shell
|
|
- manifest `moduleId`, exported module `id`, and backend module id must match
|
|
- backend metadata remains authoritative for label, version, dependencies,
|
|
nav, and runtime UI capability exposure
|
|
- future contract versions must declare required shell capabilities so old
|
|
shells fail closed
|
|
|
|
Remote bundles must not broaden backend permissions. They can only contribute
|
|
routes/nav/capabilities that the backend metadata and existing permission
|
|
checks allow.
|
|
|
|
## CSP
|
|
|
|
The current implementation imports verified entry bytes through a blob URL. A
|
|
production CSP for this mode must explicitly allow:
|
|
|
|
- `connect-src` for the approved asset-manifest and bundle origins
|
|
- `script-src` for `blob:` only when remote loading is enabled
|
|
- no `unsafe-inline` requirement for remote modules
|
|
|
|
If an installation cannot allow `blob:` scripts, the follow-up implementation
|
|
should use signed same-origin module assets with static URLs instead of blob
|
|
imports. Remote loading must be disableable by configuration so strict-CSP
|
|
deployments can keep the rebuild path only.
|
|
|
|
## Cache Invalidation
|
|
|
|
The shell cache key is:
|
|
|
|
```text
|
|
<module-id>:<asset-manifest-url>:<backend-module-version>
|
|
```
|
|
|
|
Release catalogs should publish immutable manifest and entry URLs or change at
|
|
least one cache-key component on every release. Emergency rollback can point the
|
|
backend manifest at a previous immutable manifest URL or lower the enabled
|
|
module version after the backend package rollback.
|
|
|
|
Browsers may still cache remote responses. Approved asset servers should use:
|
|
|
|
- long cache lifetimes only for content-addressed immutable assets
|
|
- short cache lifetimes or explicit revalidation for channel/latest manifest
|
|
aliases
|
|
- `Cache-Control: no-store` for emergency override manifests
|
|
|
|
## Rollback
|
|
|
|
Remote WebUI rollback is metadata rollback, not package-manager rollback:
|
|
|
|
- if the backend package install rolls back, the previous backend frontend
|
|
metadata returns
|
|
- if only remote assets are bad, publish a new manifest URL or revert the
|
|
backend/frontend metadata to the last known good manifest
|
|
- failed remote loading must degrade by omitting the remote module frontend,
|
|
not by breaking the shell
|
|
|
|
Installer run records should eventually include remote asset manifest URLs,
|
|
integrity, signature key ids, and load-test results when a plan enables a
|
|
remote frontend.
|
|
|
|
## Local And Development Behavior
|
|
|
|
Local development should keep using workspace/file dependencies and Vite. Remote
|
|
loading is useful for integration testing release artifacts, not for day-to-day
|
|
module UI development.
|
|
|
|
Development deployments may use unsigned catalogs and local asset servers only
|
|
when signature/integrity enforcement is intentionally disabled. The remote
|
|
loader itself still requires an integrity hash or a verifiable signature.
|
|
|
|
## Follow-Up Slices
|
|
|
|
1. Add a server-side remote-bundle policy flag and surface whether remote
|
|
loading is enabled in platform metadata.
|
|
2. Add CSP documentation/config generation for strict rebuild-only mode versus
|
|
controlled remote-bundle mode.
|
|
3. Add an installer/catalog preflight that validates remote WebUI asset
|
|
manifests and records verified identity in installer run records.
|
|
4. Add Playwright coverage for a signed test remote bundle, failed digest, bad
|
|
module id, cache-key refresh, and fallback when the module is unavailable.
|
|
5. Add release tooling to emit immutable remote asset manifests with digest,
|
|
signature, key id, and rollback metadata.
|