Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Unreleased

- Breaking: the legacy app websocket is removed. It attached an app interface
that accepted any origin and injected a reusable, non-expiring token, and no
consumer still used it; windows reach the conductor over Tauri IPC only.
`WindowOptions::use_app_websocket` and the injected `__HC_LAUNCHER_ENV__` are
gone, and `holochain-conductor-runtime` drops `Runtime::ensure_app_websocket`,
`Runtime::setup_app` and `AppAuth`. Call `Runtime::install_app_if_missing`
where you called `setup_app`.
- The Makefile is gone; `npm run ci` is what CI runs (`fmt:check`, `lint`, `test`).
`npm run lint` now builds the example UI first, since `cargo clippy --workspace`
compiles the example app and Tauri resolves `frontendDist` at compile time. CI
Expand Down Expand Up @@ -48,6 +55,16 @@
with 100 there were no drops and a fresh phone agent synced in about 90 s.
`dev_network_url!()` reads `INTERNAL_IP`/`BOOTSTRAP_PORT` at run time on desktop
and at compile time on mobile.
- Windows from `main_window_builder` are confined to the origin they first
load from, recorded from the webview itself rather than predicted from the
config: navigation elsewhere is refused and logged (`blob:` URLs of the
origin excepted, so exports still work), and on desktop `window.open` and
`target="_blank"` open nothing. Tauri has no `on_new_window` on mobile: there
Android loads the target in the same webview, where the navigation check
applies, and iOS opens nothing. `HolochainPlugin::lock_navigation` applies
the policy to a window the app builds itself; `navigation_allowed`,
`origin_of` and `same_origin` are public. `on_new_window` arrived in Tauri
2.8; the workspace floor moves from 2.5.1 to 2.11, the version CI builds.
- Linux: `tauri-plugin-hc` grants WebKitGTK user-media permission requests on
every webview it sees, so a hApp UI can call `getUserMedia` (camera and
microphone) on Linux as it already could on Android. WebKitGTK denies these
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ url2 = "0.0.6"
lair_keystore_api = "0.7.1"
rustls = "0.23.25"

tauri = "2.5.1"
tauri = "2.11"
tauri-plugin = "2.2.0"
tauri-build = { version = "2.2.0", default-features = false }

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ your Tauri app → tauri-plugin-hc → holochain-conductor-runtime → conductor

| Crate | |
| --- | --- |
| [holochain-conductor-runtime](./crates/runtime) | Framework-free wrapper around the Holochain conductor. Two-phase boot (lair first, then the conductor on that same keystore), app install/enable/disable/uninstall, app websockets, zome-call and payload signing, key generation and seed import/export, hc-auth, network stats. Talks to the conductor through `AdminInterfaceApi`/`AppInterfaceApi` in-process — it never opens an admin websocket. |
| [holochain-conductor-runtime](./crates/runtime) | Framework-free wrapper around the Holochain conductor. Two-phase boot (lair first, then the conductor on that same keystore), app install/enable/disable/uninstall, zome-call and payload signing, key generation and seed import/export, hc-auth, network stats. Talks to the conductor through `AdminInterfaceApi`/`AppInterfaceApi` in-process — it never opens an admin websocket. |
| [tauri-plugin-hc](./crates/tauri-plugin-hc) | The Tauri integration, and the runtime's only consumer here. Boots the conductor, binds webview windows to installed apps, forwards signals, serves the App API over Tauri IPC, and signs zome calls for the UI. |

[create-holochain-tauri](./packages/create-holochain-tauri) adds a desktop and Android app built on the plugin to an existing hApp repository, such as one from `hc-scaffold`: `npm create holochain-tauri`.

[apps/holochain-runtime-example](./apps/holochain-runtime-example) is a working app for all three platforms: it boots a conductor, installs the bundled `forum.happ` fixture, and opens a window connected to it.

The plugin injects a `__HC_TAURI_HOLOCHAIN__` env into each window it opens. The UI reads it and connects with `@holochain/client` over Tauri IPC; the older loopback-app-websocket path is still selectable per window.
The plugin injects a `__HC_TAURI_HOLOCHAIN__` env into each window it opens. The UI reads it and connects with `@holochain/client` over Tauri IPC.

## Platform support

Expand Down
9 changes: 3 additions & 6 deletions apps/holochain-runtime-example/src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,7 @@ async fn open_main_window(handle: AppHandle) -> Result<(), Box<dyn Error>> {

// Install and enable the forum hApp on first run only. An app that is
// already installed is left in whatever state it is in, so one a user
// disabled stays disabled. This deliberately avoids `Runtime::setup_app`,
// which also attaches an app websocket interface: the window below reaches
// the conductor over Tauri IPC, so that port would sit open and unused.
// disabled stays disabled.
if !runtime.is_app_installed(APP_ID.into()).await? {
runtime
.install_app(InstallAppPayload {
Expand All @@ -125,9 +123,8 @@ async fn open_main_window(handle: AppHandle) -> Result<(), Box<dyn Error>> {
runtime.enable_app(APP_ID.into()).await?;
}

// Open a window bound to the app. With `use_app_websocket` left at its
// default (false), the plugin injects `__HC_TAURI_HOLOCHAIN__` and serves
// the App API and zome-call signing over Tauri IPC.
// Open a window bound to the app. The plugin injects `__HC_TAURI_HOLOCHAIN__`
// and serves the App API and zome-call signing over Tauri IPC.
plugin
.main_window_builder(
"main",
Expand Down
6 changes: 1 addition & 5 deletions apps/holochain-runtime-example/ui/src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,8 @@ const show = (id, text, ok) => {
if (ok !== undefined) report(id, ok, text);
};

// 1. Prove the plugin injected an env into this webview. Direct mode injects
// __HC_TAURI_HOLOCHAIN__ (no websocket); legacy mode injects __HC_LAUNCHER_ENV__.
// 1. Prove the plugin injected its __HC_TAURI_HOLOCHAIN__ env into this webview.
const tauriEnv = window.__HC_TAURI_HOLOCHAIN__;
const wsEnv = window.__HC_LAUNCHER_ENV__;
if (tauriEnv) {
show(
"env",
Expand All @@ -34,8 +32,6 @@ if (tauriEnv) {
!!tauriEnv.subscribeSignals,
true
);
} else if (wsEnv && wsEnv.APP_INTERFACE_PORT) {
show("env", "websocket — APP_INTERFACE_PORT=" + wsEnv.APP_INTERFACE_PORT, true);
} else {
show("env", "no holochain env injected", false);
}
Expand Down
2 changes: 1 addition & 1 deletion crates/runtime/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ It calls the conductor through `AdminInterfaceApi` and `AppInterfaceApi` in-proc
What it covers:

- **Two-phase boot.** Lair is spawned first, the hc-auth flow (if configured) signs a challenge against it and injects the resulting auth material into the `NetworkConfig`, and only then is the conductor built on that same keystore. This is what makes authenticated bootstrap and relay work on a first boot.
- **App lifecycle** — install, enable, disable, uninstall, list; `install_app_if_missing` for install-if-needed plus enable, and `setup_app`, which also attaches an app websocket.
- **App lifecycle** — install, enable, disable, uninstall, list; `install_app_if_missing` for install-if-needed plus enable.
- **Signing** — zome calls, and arbitrary payloads against a caller-chosen agent key.
- **Keys** — device key derivation, agent key generation, seed import and export.
- **App API and signals** — `handle_app_request` serves the full App API in-process; `subscribe_to_app_signals` yields an app's signal stream.
Expand Down
Loading
Loading