n7n-plugin-host 0.1.0

wasmtime-бекенд для crate::registry::PluginRegistry (n7n-harness) — друга (wasm-компонентна) реалізація слотів detector/verify/ast_facts/t0, поруч з in-process-бекендом §3.12 пункту 16а
//! ЄДИНЕ місце в крейті, де guest отримує (чи не отримує) права на диск —
//! §3.9: "читання — read-only preopen кореня репозиторію". Кожен із
//! чотирьох `Wasm*::call*` (`detector.rs`/`verify.rs`/`ast_facts.rs`/
//! `t0.rs`) будує `Store` для guest-виклику РІВНО через
//! [`read_only_repo_ctx`] — жодної іншої точки конструювання `WasiCtx` у
//! крейті немає, тож "мутуючий guest" не потребує домовленості чи ревʼю:
//! щоб він з'явився, хтось мусив би змінити ЦЮ функцію (видно в diff).

use std::path::Path;

use wasmtime_wasi::{DirPerms, FilePerms, WasiCtx, WasiCtxBuilder};

/// Read-only `WasiCtx` з одним preopen — коренем репозиторію спроби,
/// змонтованим у guest-і як `/`.
///
/// `DirPerms::READ`/`FilePerms::READ` — це ВЕСЬ бюджет прав, який
/// [`WasiCtxBuilder`] тут отримує; `DirPerms::MUTATE` ніде в цій функції
/// (і ніде більше в крейті) не згадується. Наслідок: guest, що намагається
/// писати чи створювати/видаляти файл через `wasi:filesystem` (а саме цим
/// шляхом іде звичайний `std::fs::write` у скомпільованому для
/// `wasm32-wasip2` guest-і — доккоментар `detector.rs`, тест
/// `write_attempt_is_denied_by_the_read_only_preopen`), отримує помилку від
/// самого wasmtime-wasi ще до того, як його код побачив би файлову систему
/// — заборона за побудовою, не за угодою застосунку.
///
/// Хостовий `host-fs.read-file` (`crate::host_state`) — ДРУГИЙ, вужчий
/// шлях читання (доккоментар `wit/host.wit`), який іде НЕ через цей
/// `WasiCtx`, а напряму host-side `std::fs`; він так само ніколи не пише
/// (сигнатура `host-fs` не має жодної функції запису), тож обидва шляхи
/// читання, які §3.9 називає, лишаються read-only незалежно один від
/// одного.
pub(crate) fn read_only_repo_ctx(repo_root: &Path) -> wasmtime::Result<WasiCtx> {
    let mut builder = WasiCtxBuilder::new();
    builder.preopened_dir(repo_root, "/", DirPerms::READ, FilePerms::READ)?;
    Ok(builder.build())
}

#[cfg(test)]
mod tests {
    //! Санітарний тест без `.wasm` (доккоментар `crate`-level "Тестовий
    //! guest", сценарій 2): підтверджує лише, що конструктор компілюється
    //! й повертає `Ok` на реальному каталозі — САМ доказ безпеки (guest не
    //! може писати) даний наскрізним тестом
    //! `tests/wasmtime_backend.rs::detector_end_to_end_denies_write_...`,
    //! бо перевірити ефект `DirPerms`/`FilePerms` можна лише реальним
    //! guest-викликом через `wasi:filesystem`, не інтроспекцією `WasiCtx`
    //! (тип не виставляє прав публічно).
    use super::*;

    #[test]
    fn read_only_repo_ctx_builds_successfully_on_a_real_directory() {
        let dir = tempfile::tempdir().expect("tempdir");
        if let Err(err) = read_only_repo_ctx(dir.path()) {
            panic!("{err}");
        }
    }
}