Control bridge access
Vidra separates what the native host implements from what the WebView may use.
Registering a module makes it available to the host; access remains denied until
vidra.config.ts grants the generated method or event token.
This default-deny policy limits the damage a compromised web bundle can cause.
It applies equally to generated proxies and calls through vidra.unsafe.
Host-initiated JavaScript contracts are outside this policy.
Grant native methods
Built-in method tokens come from @vidra-dev/sdk/config:
import { defineConfig, native } from "@vidra-dev/sdk/config";
export default defineConfig({
bridge: {
allow: [
native.app.getInfo,
native.clipboard.getText,
native.notifications.show,
],
},
});
For an application contract, import its generated access catalog:
import { defineConfig } from "@vidra-dev/sdk/config";
import { native } from "./ui/src/generated/access.js";
export default defineConfig({
bridge: {
allow: [native.greeting.greet],
},
});
The generated tokens provide autocomplete and fail TypeScript checking when a contract or member is renamed. String contract names are not accepted here.
Grant events
An event must be registered by the native host and granted before Vidra sends it to the WebView:
import { defineConfig, events } from "@vidra-dev/sdk/config";
export default defineConfig({
bridge: {
events: [
events.appWindow.resized,
events.connectivity.changed,
],
},
});
Use events from ./ui/src/generated/access.js for application-defined event
contracts.
Scope filesystem methods
Filesystem methods cannot be added to the general allow list. Pair each
method with a symbolic native root:
import {
defineConfig,
filesystemRoots,
native,
within,
} from "@vidra-dev/sdk/config";
export default defineConfig({
bridge: {
filesystem: [
{
root: within(filesystemRoots.documents, "MyApp"),
allow: [
native.filesystem.readText,
native.filesystem.writeText,
native.filesystem.listDirectory,
],
},
],
},
});
Available roots are appData, cache, documents, and downloads.
within(root, relativePath) narrows a root; .. traversal is rejected while
loading the config.
Filesystem calls still pass fully qualified OS paths. The host resolves the symbolic root on the user’s machine and rejects paths outside it, including existing symbolic links that escape the configured scope.
Build-time policy
vidra build and vidra dev execute vidra.config.ts in the CLI, validate it,
and write a normalized policy into the native application. The WebView cannot
change that policy at runtime.
The config may also be a callback:
import { defineConfig, native } from "@vidra-dev/sdk/config";
export default defineConfig(({ mode, target }) => ({
bridge: {
allow: [
native.app.getInfo,
...(mode === "development" ? [native.clipboard.getText] : []),
...(target === "windows" ? [native.appWindow.setTitle] : []),
],
},
}));
Changing grants during vidra dev rebuilds and relaunches the host because the
installed policy is immutable.
Compatibility and updates
The generated frontend records the policy fingerprint it expects. Startup fails before bridge traffic if it does not match the native host.
Web-bundle update entries carry the same fingerprint, so a bundle is considered only when its required access exactly matches the installed policy. Increasing or reducing access therefore requires a native release before a web-only bundle can depend on the new policy.
vidra.capabilities() reports only methods and events that are both registered
and granted. Use it for runtime feature detection, not as a replacement for
declaring the policy.