Skip to main content

Crate plugin_host

Crate plugin_host 

Source
Expand description

wasmtime-бекенд wit/*.wit-контрактів (n7n:fix-deps@0.1.0) — спека 2026-08-17-n7n-harness-local-models.md, §3.12 пункт 16, ДРУГА половина (пункт 16а — контракти й in-process-бекенд, harness::registry — уже зроблений, без wasmtime; цей крейт додає ЄДИНУ нову залежність, яку той крок свідомо не чіпав).

§Чому окремий крейт, а не harness/llm-lib

wasmtime — найбільша залежність усього плану FixDeps-плагінів. harness тримає інваріант «нуль важких залежностей» (CI перевіряє cargo tree -p n7n-harness --all-features — там немає wasmtime); і n7n-llm-lib (featureless-ядро) щойно спеціально звужували (§3.1). Обидва інваріанти цей крейт не чіпає — він лише СПОЖИВАЄ обидва (n7n-harness за типами DetectFn/T0Fn/Violation/VerifyFn/ AstFactsFn з crate::registry/crate::pipeline, n7n-llm-lib з default-features = false за EditPlan/FileEditPlan/VerifyReport). Підключає його лише той споживач, що реально вантажить wasm-плагіни (rules-fix) — harness/llm-lib лишаються придатними для споживачів, яким wasm не потрібен, без жодного зайвого байта в графі.

§Що тут головне: чотири Wasm* — друга реалізація тих самих слотів

harness::registry::PluginRegistry уже спроєктований так, що бекенд компонента — друга реалізація T усередині Slot<T>, не окремий трейт-об’єкт (доккоментар registry.rs, “чому T, а не трейт”). Чотири типи нижче — WasmDetector, WasmVerify, WasmAstFacts, WasmT0 — виробляють РІВНО ті самі callable-типи, що in-process бекенд уже приймає (harness::pipeline::DetectFn, harness::registry::VerifyFn, harness::registry::AstFactsFn, harness::pipeline::T0Fn) — PluginRegistry::new/replace_* не відрізняє, звідки прийшло замикання: з Arc::new(|| ...) напряму чи з WasmDetector::into_detect_fn() нижче. Володіння (реєстр, Slot, generation, LIFO-аквайр) лишається рівно тим самим кодом (crates/harness/src/registry.rs) — цей крейт лише постачає ЩО саме кладеться в слот.

§Безпекова межа (§3.9) — де вона виражена в коді

  • Guest-и не отримують WASI-права запису взагалі. Єдине місце, де guest отримує (чи не отримує) права на диск — [wasi_ctx::read_only_repo_ctx]: FsPerms::ReadOnly, нуль ReadWrite в усьому крейті. Кожен із чотирьох Wasm*::call* нижче будує WasiCtx РІВНО через цю функцію — підміни в обхід неї немає, бо Store для guest-виклику ніде більше в крейті не конструюється.
  • T0 повертає edit-plan, хост застосовує. WasmT0::into_t0_fn виробляє лише harness::pipeline::T0Fn (порахувати план) — фаза застосування (PreparePlanFn/CommitPlanFn, write_guard) сюди НЕ входить: n7n-llm-lib тут узятий з default-features = false, тож write_guard (живе під фічею agents) цьому крейту недоступний за побудовою — той самий принцип, що вже застосовує harness::registry (доккоментар T0Step: “prepare/commit — цілком хостові… не частина контракту «порахувати план»”). Викликач збирає повний T0Step { plan: wasm_t0.into_t0_fn(), prepare: ..., commit: ... } сам, як і сьогодні для in-process T0.
  • Жодного спавну процесів у guest. Жоден із чотирьох wit/*.wit world-ів не імпортує нічого, що дало б guest-у спавнити процес (жодного wasi:cli/exec-подібного імпорту в жодному з detector-plugin/verify-plugin/ast-facts-plugin/t0-plugin), і WASI Preview 2 в принципі не має такого стандартного інтерфейсу — немає wasi-фічі, яку можна було б увімкнути, щоб це з’явилось.
  • Інстанс на спробу, без кешу. Кожен Wasm*::call* будує СВІЖИЙ Store+WasiCtx+Instance на КОЖЕН виклик (не лише на кожен checkout() реєстру) — суворіша гарантія, ніж вимагає §3.16 правило 3 (“інстанс на спробу”): жодного способу випадково закешувати Instance між викликами немає, бо для нього просто немає поля, яке пережило б виклик. Кешується лише СКОМПІЛЬОВАНИЙ wasmtime::component::ComponentEngine/Linker, які самі по собі не несуть стану guest-а) — те саме розрізнення “Component ≠ Instance”, яке задача явно вимагає.

§Тестовий guest

tests/guest/detector_fixture і tests/guest/t0_fixture — мінімальні wasm32-wasip2-компоненти для наскрізного тесту (tests/wasmtime_backend.rs). Компіляція гейтована наявністю wasm32-wasip2 в rustup target list --installed — де його немає (чи cargo build для guest-крейта впаде з іншої причини, напр. немає мережі до crates.io), тест друкує причину й виходить РАНО, не падаючи: середовище цієї задачі мало і target, і мережу (перевірено на старті), тож тут наскрізний прогін ДІЙСНО виконується, а не лише компілюється бекенд.

Structs§

WasmAstFacts
Wasm-бекенд одного ast-facts-компонента — доккоментар crate::detector::WasmDetector.
WasmDetector
Wasm-бекенд одного detector-компонента: скомпільований Component/Engine/Linker — кешовані (доккоментар crate-level “інстанс на спробу, без кешу” — кешується лише СКОМПІЛЬОВАНИЙ компонент, не Instance), плюс корінь репозиторію для read-only preopen-у.
WasmT0
Wasm-бекенд одного t0-компонента — доккоментар crate::detector::WasmDetector.
WasmVerify
Wasm-бекенд одного verify-компонента — доккоментар crate::detector::WasmDetector пояснює кешування Component/Engine/Linker проти “інстанс на спробу” для Instance.