ticket: refine plugin feature layering
This commit is contained in:
@@ -1,82 +1,88 @@
|
||||
---
|
||||
title: "Plugin: define extension surface for hooks and tools"
|
||||
state: "planning"
|
||||
created_at: "2026-05-31T01:00:05Z"
|
||||
updated_at: "2026-06-03T12:25:05Z"
|
||||
title: 'Plugin: define extension surface for hooks and tools'
|
||||
state: 'planning'
|
||||
created_at: '2026-05-31T01:00:05Z'
|
||||
updated_at: '2026-06-13T15:29:21Z'
|
||||
assignee: null
|
||||
---
|
||||
|
||||
## Goal
|
||||
|
||||
Design Yoi's Plugin surface as the user-facing package/config/runtime layer built on top of `pod::feature`.
|
||||
|
||||
`pod::feature` is the internal API substrate for contribution registration: Tools, Hooks, BackgroundTasks, Services, diagnostics, and lifecycle integration. Plugin is the layer that makes that substrate usable by users and workspaces through package metadata, enablement config, runtime choices, provenance, and Plugin-layer permissions.
|
||||
|
||||
MCP is not the Plugin model and should not be treated as a Plugin permission backend. MCP is a separate protocol-backed integration layer that also uses the feature API and owns its own MCP-specific enablement/trust policy.
|
||||
|
||||
## Background
|
||||
|
||||
insomnia currently has internal Hook / Tool concepts, plus a separate planned MCP integration ticket (`mcp-integration`). The next design step is to define the project-level Plugin surface: how user/project-provided extensions can contribute Tools and Hooks without weakening scope, permission, history, or prompt-context invariants.
|
||||
Yoi already has internal extension-like surfaces:
|
||||
|
||||
The plugin surface should not be a grab bag of arbitrary code execution. Candidate extension mechanisms have different trust and protocol properties:
|
||||
- Tools via `llm_worker::ToolRegistry` / `ToolDefinition`
|
||||
- Hooks via `HookRegistry` / `HookEvent` / `HookAction`
|
||||
- Feature contribution declarations in `pod::feature`
|
||||
- Built-in features such as task and ticket tools
|
||||
|
||||
- MCP: protocol-bound external tool/resource/prompt provider surface.
|
||||
- TOML/config-only hooks: declarative configuration for simple hook behavior without arbitrary code.
|
||||
- WASM: planned first programmable plugin runtime for Hooks and Tools, with explicit capability imports and sandboxing.
|
||||
- General scripting languages: considered, but not the initial direction because arbitrary script execution broadens the trust/runtime surface too quickly.
|
||||
The Plugin surface should expose extension points without letting external packages bypass Worker history, prompt/context invariants, scoped tool permissions, or role/profile configuration.
|
||||
|
||||
## Related work
|
||||
|
||||
- `work-items/open/20260529-161928-mcp-integration/` — MCP integration as one plugin backend / external capability bridge.
|
||||
- `work-items/open/20260603-122317-plugin-feature-contribution-registry/` — implementation-oriented runtime registry split-out for built-in and external feature contributions.
|
||||
- `work-items/open/20260603-122317-hook-public-surface-hardening/` — prerequisite hardening for public Hook contribution safety.
|
||||
- Existing internal hooks/tools code: `crates/pod`, `crates/tools`, `crates/llm-worker`.
|
||||
- Manifest permission policy and scope enforcement must remain authoritative for plugin-provided tools.
|
||||
Prior Hook hardening work constrains model-visible context mutation so Plugin exposure can stay safe. Plugin design should reuse those safe surfaces rather than creating a parallel tool/hook runtime.
|
||||
|
||||
## Requirements
|
||||
|
||||
- Define a Plugin surface that can provide:
|
||||
- Tools callable by the LLM through the normal ToolRegistry / permission / scope path;
|
||||
- Hooks observing or influencing Pod/Worker lifecycle through the existing Hook boundary, not by directly mutating worker history/context.
|
||||
- Separate plugin description/registration from plugin runtime implementation.
|
||||
- A plugin manifest should declare provided tools/hooks, required capabilities, configuration schema or config values, and trust/runtime type.
|
||||
- Runtime implementations can include MCP, declarative config hooks, and WASM in separate phases.
|
||||
- Keep MCP as a related backend, not the whole plugin model.
|
||||
- MCP servers remain untrusted external capability providers bridged through allowlists, bounded output, scope/permission policy, and explicit resource/prompt use.
|
||||
- Define a declarative hook path for simple TOML/config-only behavior where code execution is unnecessary.
|
||||
- Define a WASM plugin direction for programmable Hooks/Tools.
|
||||
- WASM modules must receive explicit host imports/capabilities only.
|
||||
- File/network/process access must not be ambient; all external effects go through host-provided capability APIs and existing policy checks.
|
||||
- Tool outputs must be bounded and recorded through normal history/tool-result paths.
|
||||
- Preserve LLM context/history invariants.
|
||||
- Plugins must not inject cross-turn invisible context.
|
||||
- If plugin output becomes model-visible, it must enter through durable history/tool/hook paths according to existing rules.
|
||||
- Preserve scope and permission invariants.
|
||||
- Plugin-provided tools must not bypass `ScopedFs`, manifest tool permission policy, child scope delegation, or web/network policy.
|
||||
- Clarify trust model and lifecycle.
|
||||
- Builtin vs project vs user plugins.
|
||||
- Discovery/enablement through manifest/profile/config.
|
||||
- Versioning / compatibility boundaries.
|
||||
- Diagnostics when a plugin cannot load or asks for unavailable capabilities.
|
||||
|
||||
## Non-goals
|
||||
|
||||
- Implementing the full WASM runtime in the first design step.
|
||||
- Implementing MCP itself beyond referencing the existing MCP integration ticket.
|
||||
- Supporting arbitrary host scripting languages as a first-class plugin runtime.
|
||||
- Allowing plugins to mutate session history, memory, prompt context, or scope outside approved APIs.
|
||||
- Adding UI plugin systems or TUI rendering extensions.
|
||||
|
||||
## Suggested phases
|
||||
|
||||
1. **Design / architecture note**
|
||||
- Define Plugin, PluginManifest, PluginRuntimeKind, Tool contribution, Hook contribution, capability request, and trust/source model.
|
||||
- Map MCP, declarative hooks, and WASM onto that model.
|
||||
2. **Internal registry boundary**
|
||||
- Detailed implementation is split to `plugin-feature-contribution-registry` so this ticket can stay focused on the architecture surface and invariants.
|
||||
3. **Declarative hooks MVP**
|
||||
- Add a non-code configuration path for simple hook behavior if an immediate use case exists.
|
||||
4. **WASM spike**
|
||||
- Evaluate runtime (`wasmtime` or alternative), host imports, resource limits, serialization, and Nix/package impact.
|
||||
5. **MCP bridge alignment**
|
||||
- Ensure `mcp-integration` plugs into the same Tool/permission/output boundary rather than becoming a parallel extension path.
|
||||
- Define Plugin as a user-facing layer over `pod::feature`, not as the feature API itself.
|
||||
- Plugin package/config/runtime code eventually contributes through `pod::feature`.
|
||||
- `pod::feature` remains responsible for contribution declarations, lifecycle, diagnostics, and registration plumbing.
|
||||
- Plugin remains responsible for package enablement, provenance, runtime selection, and Plugin-layer permission/trust policy.
|
||||
- Define supported contribution categories.
|
||||
- Tools
|
||||
- Hooks
|
||||
- Background tasks / services, if included in the initial model
|
||||
- Future extensions must remain explicit contribution categories, not arbitrary host access.
|
||||
- Define Plugin-layer permission and trust model separately from `pod::feature`.
|
||||
- Do not rely on feature-level `HostAuthority` / authority grants for Plugin permissions.
|
||||
- Plugin grants should be tied to package identity/runtime/user or workspace config, not to feature install reports.
|
||||
- Plugin policy must decide which contribution categories and host APIs a Plugin runtime can use.
|
||||
- Define runtime families separately.
|
||||
- Declarative/config-only Plugins
|
||||
- WASM or another sandboxed runtime, if/when selected
|
||||
- External process/plugin bridge, if/when selected
|
||||
- MCP remains a separate feature-backed protocol integration, not the Plugin permission model.
|
||||
- Hook Plugins must use the hardened public Hook surface.
|
||||
- no raw hidden `Item` injection
|
||||
- no prompt/context mutation outside durable history-aware paths
|
||||
- explicit supported `HookAction` subset only
|
||||
- Tool Plugins must register ordinary Yoi tools.
|
||||
- normal tool schema exposure
|
||||
- normal PreToolCall permission path
|
||||
- normal tool-result history path
|
||||
- bounded result serialization
|
||||
- Plugin metadata and package content are untrusted input.
|
||||
- Plugin enablement must be explicit.
|
||||
- package presence/discovery alone cannot enable or execute Plugin code
|
||||
- workspace/user config must opt in to package/runtime/contribution activation
|
||||
- The design must document the boundary among Plugin, MCP, and built-in Features.
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- The repository has a documented plugin architecture proposal covering Tools, Hooks, runtimes, capability model, trust model, and discovery/enablement.
|
||||
- MCP is positioned as one plugin backend / bridge and linked to `mcp-integration`, not treated as the only extension mechanism.
|
||||
- The proposal explicitly explains why arbitrary scripting languages are deferred and why WASM is the initial programmable runtime direction.
|
||||
- The design preserves existing scope, permission, history, and prompt-context invariants.
|
||||
- Follow-up implementation tickets can be cut independently for declarative hooks, WASM runtime, and MCP bridge integration.
|
||||
- Any code changes in this ticket, if taken beyond design docs, are limited to safe internal boundaries and have focused tests.
|
||||
- A design note or Ticket plan defines Plugin as a user-facing layer over `pod::feature`.
|
||||
- The plan states that Plugin permissions are Plugin-layer policy and are not implemented by `pod::feature` `HostAuthority` grants.
|
||||
- The plan states that MCP is a separate feature-backed integration with MCP-specific enablement/trust policy.
|
||||
- Contribution categories and runtime families are named with explicit in/out of scope decisions for the first implementation slice.
|
||||
- The public Hook safety invariants from `00001KT6Q08R8` remain intact.
|
||||
- Tool Plugins are required to use ordinary ToolRegistry / permission / history / bounded-result paths.
|
||||
- No design path allows Plugin package presence alone to execute code or mutate context.
|
||||
- The design identifies which follow-up Tickets own package format, runtime implementation, and Plugin permission details.
|
||||
|
||||
## Suggested decomposition
|
||||
|
||||
1. Public Hook surface hardening. Completed by `00001KT6Q08R8`.
|
||||
2. Feature contribution API substrate. Completed initial slice by `00001KT6Q08R9`; dynamic provider work continues in `00001KTR81P9X`.
|
||||
3. Plugin package/discovery format. Tracked by `00001KT0Z4BK8`.
|
||||
4. Plugin permission/runtime policy Ticket. Create or refine after runtime family is selected; do not put this policy into `pod::feature`.
|
||||
5. MCP local stdio integration. Tracked separately by `00001KTR82RB7`; it uses feature API but is not Plugin permission work.
|
||||
|
||||
## Notes
|
||||
|
||||
- This Ticket is a design coordination Ticket; implementation should be split into concrete Tickets rather than landing a broad Plugin platform in one change.
|
||||
- Keep Plugin permission terms distinct from `HostAuthority`. If `HostAuthority` remains in code, it is not the Plugin policy surface.
|
||||
- Avoid adding support for arbitrary scripting languages until package identity, runtime sandbox/trust, and permission policy are explicit.
|
||||
|
||||
@@ -39,4 +39,22 @@ Two implementation-oriented prerequisite tickets are split out:
|
||||
This preserves the desired detachable shape: feature state remains in the feature/extension module, while Pod interaction happens through existing durable host surfaces. WorkItem management should be implemented as a built-in feature contribution once the registry boundary is in place, rather than as a special Pod context-injection path.
|
||||
|
||||
|
||||
---
|
||||
|
||||
<!-- event: decision author: hare at: 2026-06-13T15:29:21Z -->
|
||||
|
||||
## Decision
|
||||
|
||||
決定:
|
||||
- `pod::feature` は API / contribution substrate として扱い、Plugin や MCP の権限管理を担わせない。
|
||||
- Plugin は `pod::feature` をユーザー向け package/config/runtime 形式で使わせる層であり、Plugin permission / trust policy は Plugin layer で定義する。
|
||||
- MCP は `pod::feature` 上に protocol-backed integration layer を構築するが、MCP server enablement / command-env-secret policy / trust boundary / MCP-specific permission は MCP layer が独自に持つ。
|
||||
- MCP local stdio server の OS-level side effects は Yoi feature authority では制御できないため、feature-layer authority / grant を MCP や Plugin の permission model に流用しない。
|
||||
|
||||
反映:
|
||||
- `00001KTR81P9X` は authority ではなく provider lifecycle / dynamic contribution / normal ToolRegistry path / untrusted normalization に絞る。
|
||||
- `00001KTR82RB7` は MCP 固有の explicit config と trust model を持つ。
|
||||
- `00001KSXRQ4G8` と `00001KT0Z4BK8` は Plugin permission を Plugin layer として扱い、MCP を初期 Plugin packaging/runtime から分離する。
|
||||
|
||||
|
||||
---
|
||||
|
||||
Reference in New Issue
Block a user