diaryx_extism 1.3.0

Extism-based third-party plugin runtime for Diaryx
Documentation
# diaryx_extism

Extism-based third-party plugin runtime for Diaryx.

Loads WebAssembly plugin modules via the [Extism](https://extism.org/) runtime
and adapts them to `diaryx_core` plugin traits. Guest plugins communicate with
the host through a JSON protocol (`protocol.rs`).

## Plugin directory structure

```
~/.diaryx/plugins/
  my-plugin/
    plugin.wasm      # The WASM module
    manifest.json    # Cached guest manifest
    config.json      # Plugin config sidecar
```

## Guest-exported functions

| Function | Input | Output | When called |
|----------|-------|--------|-------------|
| `manifest` | `""` | `GuestManifest` JSON | At load time |
| `init` | `PluginContext` JSON | `""` | Plugin initialization |
| `on_event` | `GuestEvent` JSON | `""` | File/workspace events |
| `handle_command` | `CommandRequest` JSON | `CommandResponse` JSON | Command dispatch |
| `get_config` | `""` | config JSON | Config read |
| `set_config` | config JSON | `""` | Config write |

`GuestManifest` supports optional `requested_permissions`:

- `defaults` (`PluginPermissions`) for install-time defaults
- `reasons` (`HashMap<String, String>`) for permission rationale text

## Host functions available to guests

| Function | Description |
|----------|-------------|
| `host_log` | Plugin logging |
| `host_read_file` / `host_list_files` / `host_file_exists` | Workspace reads |
| `host_write_file` / `host_write_binary` | Workspace writes (create/edit split by file existence) |
| `host_delete_file` | Workspace deletes |
| `host_http_request` | HTTP request bridge (feature-gated, supports optional `timeout_ms`) |
| `host_storage_get` / `host_storage_set` | Plugin persistent storage |
| `host_run_wasi_module` | Execute a WASI module loaded from plugin storage (feature-gated) |
| `host_emit_event` / `host_ws_request` / `host_get_timestamp` | Eventing and utility functions |

## Permission enforcement

Permissions are checked in host functions via `HostContext.permission_checker`.

- If no checker is configured, host calls are denied.
- `HostContext::with_fs()` defaults to `DenyAllPermissionChecker`.
- Loader updates runtime `plugin_id` from the guest manifest `id`, so checks
  are keyed to the canonical plugin ID.

Provided checkers:

- `DenyAllPermissionChecker` — denies every request
- `FrontmatterPermissionChecker` — reads root frontmatter `plugins` config and
  delegates to `diaryx_core::plugin::permissions::check_permission`

Storage keys are plugin-scoped in host functions (`{plugin_id}:{key}`), so one
plugin cannot read another plugin's storage by key collision.