CodeVetter · Repo Unpack · Data flow
tauri-apps/tauri
Configuration flows from tauri.conf.json (json/json5/toml, plus platform-specific overlay files) through tauri-build/tauri-codegen into a compiled `Context` carrying embedded assets, CSP hashes and resolved ACLs. At runtime the `AppManager` owns config, assets, plugins, state, listeners and the `RuntimeAuthority`; webview requests travel over postMessage or the `ipc://` custom protocol, get parsed into `InvokeRequest`s, authorized against the ACL and origin, then dispatched to plugin handlers or the app's `invoke_handler`, with responses returned via JS eval or a Channel. File access flows through the `asset:` protocol gated by FsScope, and dev-mode traffic can be proxied through the custom protocol on mobile.
- Config input boundary: tauri-utils accepts tauri.conf.json, tauri.conf.json5 and Tauri.toml plus per-platform overlays (tauri.macos.conf.json, Tauri.windows.toml, ...) listed in EXTENSIONS_SUPPORTED/platform file-name tables.
- At build time tauri-build's `build()` reads the config, writes ACL manifests (acl-manifests.json) and capabilities into OUT_DIR, copies sidecar binaries and resources, and emits cargo rerun-if-changed directives.
- tauri-codegen's `context_codegen` embeds frontendDist assets via EmbeddedAssets, injects CSP nonces and sha256 script hashes into HTML, resolves plugin manifests + capabilities into a `Resolved` ACL, and emits a `Context::new` token stream executed on a dedicated 8MiB-stack thread.
- Runtime state owner: `AppManager<R>` holds `runtime_authority: Mutex<RuntimeAuthority>`, window/webview/menu/tray sub-managers, `plugins: Mutex<PluginStore>`, `listeners: Listeners`, `state: Arc<StateManager>`, `config`, `assets`, `pattern`, `resources_table` and the per-run `invoke_key`.
- postMessage IPC path: `handle_ipc_message` deserializes a JSON Message {cmd, callback, error, payload, options, __TAURI_INVOKE_KEY__}, optionally decrypting an Isolation payload, builds an `InvokeRequest`, and calls `webview.on_message`.
- Custom-protocol IPC path: `ipc://localhost/<cmd>` POST requests carry the command in the URI path and callback/error/invoke-key/origin in headers (Tauri-Callback, Tauri-Error, Tauri-Invoke-Key, Origin); `parse_invoke_request` rejects requests missing any of them.
- Authorization: `Webview::on_message` first compares `request.invoke_key` to the manager's generated key (128-bit Z85 via `generate_invoke_key`), then calls `runtime_authority.resolve_access(cmd, window_label, webview_label, Origin::Local|Remote{url})` before dispatching.
- Dispatch: commands prefixed `plugin:` are split on `|` into (plugin, command) and routed to `manager.run_plugin_invoke_handler`; otherwise the app-level `invoke_handler: Box<InvokeHandler>` (built by `generate_handler!`) gets the `Invoke` with resolver + acl attached.
- Response boundary: InvokeResponse::Ok(Json|Raw)/Err is serialized by `ipc::format_callback` into a JS snippet executed with `webview.eval`, or — for non-Apple platforms when allowed — sent through a `Channel` keyed by the callback id; errors always go through eval.
- JS serialization boundary: `process-ipc-message-fn.js` JSON-stringifies payloads with a replacer that converts Map/Uint8Array/ArrayBuffer and invokes `__TAURI_TO_IPC_KEY__` on objects implementing it (e.g. Channel serializes to `__CHANNEL__:<id>`); binary bodies become application/octet-stream.
- Asset serving: `protocol::tauri::get` resolves `tauri://localhost/<path>` against `manager.get_asset` returning embedded bytes + mime + CSP header; under `cfg(all(dev, mobile))` the same handler proxies requests to the dev server with reqwest and a response cache.
- Event flow: Rust `emit` goes through `Listeners` (event/listener.rs) which serializes payloads to all matching webviews; JS `listen` registers via `plugin:event|listen` and unregisters through `window.__TAURI_EVENT_PLUGIN_INTERNALS__.unregisterListener` + `plugin:event|unlisten`.