yoi/.yoi/tickets/00001KVMG8FTW/thread.md

26 KiB

作成

LocalTicketBackend によって作成されました。


State changed

Ticket を workspace-panel が queued にしました。


Decision

Routing decision: implementation_ready

Reason:

  • Ticket body は host_api.https 廃止、host_api.request 統一、manifest-declared URL/request target permissions、enablement grant 照合、runtime fail-closed、local/private target 明示 grant、broad/arbitrary URL 表示、docs/tests/diagnostics 更新まで具体化されている。
  • readiness: implementation_ready で、relations / orchestration plan に blocker はない。
  • Current active implementation 00001KVMFFYVX は Workspace web control plane bootstrap で、主対象は backend/frontend/store/Nix packaging。This Ticket の主対象は plugin manifest/pod runtime/plugin CLI/docs/tests で直接の semantic blocker はない。過去のユーザー指示「blocker無いなら並列に」に従い、並列実装可能と判断する。
  • Orchestrator worktree is clean on orchestration at f164483e で、対象 Ticket 用 worktree / branch は未作成。
  • Visible Pods に対象 Ticket の child Pod は存在しない。

Evidence checked:

  • Ticket body / thread / artifacts via TicketShow and direct item.md read。
  • TicketRelationQuery(00001KVMG8FTW): no relations / blockers。
  • TicketOrchestrationPlanQuery(00001KVMG8FTW): no records。
  • ListPods: active child is only yoi-coder-00001KVMFFYVX; no child for this Ticket。
  • Orchestrator git state / worktree list / branch list checked from /home/hare/Projects/yoi/.worktree/orchestration only。
  • Bounded code map:
    • crates/manifest/src/plugin.rs: PluginGrantConfig.https, PluginHttpsGrant, PluginHostApi::Https, permission/grant resolution/tests。
    • crates/pod/src/feature/plugin.rs: PluginHttps* runtime request path, yoi:host/https@1.0.0 / raw wasm yoi:https imports, URL validation, request bounds, credential header checks, public-IP guard, allowlist checks, plugin tests。
    • crates/yoi/src/plugin_cli.rs: inspection formatting for configured HTTPS grants。
    • docs/development/plugin-development.md: active host_api.https / grants.https docs。

IntentPacket:

Intent:

  • Replace public/model/config-facing host_api.https with URL-permission based one-shot host_api.request.
  • Keep existing safe outbound request behavior where applicable, but generalize schemes/targets so explicit manifest + enablement grants can authorize loopback/private/local targets.
  • Keep WebSocket / SSE / persistent connections out of request.

Binding decisions / invariants:

  • Do not add backward compatibility aliases for host_api.https, PluginHttps*, or grants.https in active APIs unless explicitly escalated and reapproved。
  • Model/config-facing naming must be request; internal names should also avoid PluginHttps* unless truly private transitional code is justified and not exposed。
  • Runtime authorization requires both manifest-declared request target permission and enablement grant for that target。
  • Grant-only without manifest request must fail closed or be explicitly diagnosed as unsafe/unused override; do not silently expand authority。
  • Requested-but-ungranted target must fail closed before network I/O。
  • Localhost/loopback/private/local targets are not ambient; they require manifest declaration and enablement grant。
  • Arbitrary URL / broad network access must be visibly distinguished from normal target grants in inspection/diagnostics。
  • Embedded credentials, credential-like headers, request/response bounds, external-content untrusted treatment, and no hidden context injection remain mandatory。
  • WebSocket URL / upgrade / persistent stream must be rejected or explicitly unsupported by request
  • Existing HTTPS request use cases must continue under host_api.request with explicit request permission/grant。

Requirements / acceptance criteria:

  • Active API naming uses host_api.request / request grant naming。
  • Plugin manifest statically declares request target permissions readable from manifest alone。
  • Enablement config grants request targets and is matched against manifest-declared targets。
  • Runtime checks method/scheme/host/port/path prefix against declared+granted URL permission。
  • http://localhost / loopback request can be allowed only with explicit declaration+grant。
  • Existing public HTTPS use case works as request。
  • Broad/arbitrary URL is supported only with clear broad display/diagnostic if implemented。
  • yoi plugin show / static inspection distinguishes requested, granted, denied/missing, and broad request permissions。
  • Docs/templates/tests/diagnostics are updated to request naming and WebSocket separate-capability policy。

Implementation latitude:

  • Exact Rust/TOML type names are up to Coder, but active names should be request-oriented, e.g. PluginRequestGrant, PluginRequestTarget, host_api.request.
  • Regex support is optional. If added, it must include review-readable normalized display/warning/label and tests for broad/opaque handling。
  • Request target schema may start with exact scheme/host/optional port/method/path prefix. Keep permission review human-readable。
  • Internal runtime can reuse/refactor existing HTTPS client/request code, but reviewer should see active API renaming and policy changes。
  • Raw wasm/component import migration may choose new import names with tests; if keeping an internal compatibility import is unavoidable, escalate before committing.

Escalate if:

  • Compatibility alias for old host_api.https / grants.https seems required。
  • Local/private target policy would open without both manifest declaration and grant。
  • Arbitrary URL access becomes visually indistinguishable from normal grants。
  • WebSocket/SSE/daemon lifecycle begins to enter request
  • Secret-bearing headers/env/config would flow from guest memory without explicit SecretRef/grant design。
  • Regex support becomes opaque or hard to review。
  • Parallel active 00001KVMFFYVX work creates unavoidable Cargo.lock / package.nix conflict; report rather than broad-rebasing alone。

Validation plan:

  • cargo fmt --check
  • Focused manifest plugin tests for request permission parsing/resolution and naming removal。
  • Focused pod plugin tests for grant allow/deny, requested-but-ungranted, granted-but-unrequested, loopback/local allow/deny, WebSocket/upgrade rejection, request/response bounds/credential-header safety。
  • Focused yoi plugin CLI tests for request permission/grant/broad/missing diagnostics。
  • Docs/template grep ensuring active host_api.https / grants.https / PluginHttps* naming is removed except historical Ticket text or explicitly justified migration notes。
  • cargo check for affected crates, git diff --check, yoi ticket doctor

Reviewer focus:

  • Breaking-change intent is real: no stale active docs/templates/CLI inspection still teaching host_api.https
  • Authorization must be two-stage: manifest request + grant。
  • Local/private network must not become ambient。
  • Old public HTTPS use case must still work under request naming。
  • External content and hidden context constraints remain intact。

State changed

Human authorized queue routing from Workspace Dashboard. Ticket has concrete acceptance criteria and no recorded blockers; active Workspace web control plane implementation is semantically separate enough for parallel implementation. Orchestrator accepts this Plugin host API refactor into implementation.


Implementation report

Implementation start report:

  • Created child implementation worktree:
    • /home/hare/Projects/yoi/.worktree/00001KVMG8FTW-plugin-request-host-api
  • Created branch:
    • impl/00001KVMG8FTW-plugin-request-host-api
  • Base commit:
    • 4cd4a06e ticket: route plugin request capabilities
  • Confirmed tracked Ticket project records are visible in the child worktree。
  • Confirmed .yoi/memory has no tracked/untracked entries in the child worktree check。
  • Spawned sibling Coder Pod:
    • yoi-coder-00001KVMG8FTW
  • Coder scope:
    • read: /home/hare/Projects/yoi
    • write: /home/hare/Projects/yoi/.worktree/00001KVMG8FTW-plugin-request-host-api

Parallelization note:

  • 00001KVMFFYVX remains in progress in a separate child worktree. Coder was instructed to avoid unnecessary Cargo.lock/package.nix churn and report if unavoidable conflicts appear。

Next action:

  • Wait for Coder implementation report, then spawn Reviewer read-only for the implementation diff. Orchestrator will not merge/close until reviewer approval and validation evidence are available。

Implementation report

Coder implementation report received from yoi-coder-00001KVMG8FTW.

Implementation commit:

  • 962b7699 plugin: replace https host api with request grants

Changed areas:

  • crates/manifest/src/plugin.rs
    • Replaced active host API/grant naming with request
    • Added manifest-declared [[request]] URL targets with scheme, host, optional port, methods, and path_prefixes
    • Added request grant parsing/labels/broad diagnostics and tests that legacy HTTPS-facing names are not accepted。
  • crates/pod/src/feature/plugin.rs
    • Renamed runtime path/imports to request-oriented naming。
    • Runtime now requires both manifest request target declaration and enabled request grant before network I/O。
    • Checks scheme/host/port/path/method, rejects embedded credentials, credential-like headers, WebSocket URLs/upgrades, and SSE/event-stream requests。
    • Allows loopback/local/private targets only when explicitly declared and granted。
    • Adds static inspection entries for requested/granted/missing/grant-only/broad request targets。
  • crates/yoi/src/plugin_cli.rs
    • Shows configured request grants and request target eligibility diagnostics, including broad/missing/grant-only states。
  • resources/plugin/wit/*
    • Updated WIT import/interface from HTTPS host API to yoi:host/request@1.0.0
  • docs/development/plugin-development.md
    • Rewrote host API docs for request, including manifest targets, enablement grants, loopback policy, broad target diagnostics, and WebSocket/SSE exclusion。
  • docs/design/plugin-component-model.md
    • Updated design wording/import references。
  • crates/pod/src/pod.rs
    • Updated test fixture initialization for the new manifest request target field。

Coder validation reported:

  • cargo fmt --check: passed
  • cargo test -p manifest request: passed
  • cargo test -p pod feature::plugin::tests --lib: passed
  • cargo test -p yoi plugin_cli::tests: passed
  • cargo check -p manifest -p pod -p yoi: passed
  • git diff --check: passed
  • Active naming grep for host_api.https|grants.https|PluginHttps|yoi:host/https|yoi:https under crates docs resources: no matches
  • target/debug/yoi ticket doctor: passed

Coder dependency/package report:

  • No Cargo.lock, package.nix, or flake changes。
  • No dependency/package churn。

Known deferrals:

  • Regex URL target matching was not added。
  • WebSocket/SSE/persistent connection support remains explicitly outside host_api.request

Orchestrator evidence checked:

  • Implementation worktree is clean on impl/00001KVMG8FTW-plugin-request-host-api
  • HEAD is 962b7699
  • Diff 4cd4a06e..HEAD touches 9 expected manifest/pod/plugin-doc/WIT files, about 768 insertions / 448 deletions。
  • Active stale naming grep under crates docs resources returned no matches。
  • git diff --check 4cd4a06e..HEAD produced no diagnostics。

Next action:

  • Route to read-only Reviewer Pod for acceptance review against the Ticket and IntentPacket。

Comment

Review routing:

Spawned read-only Reviewer Pod:

  • yoi-reviewer-00001KVMG8FTW-r1

Review target:

  • Worktree: /home/hare/Projects/yoi/.worktree/00001KVMG8FTW-plugin-request-host-api
  • Branch: impl/00001KVMG8FTW-plugin-request-host-api
  • Baseline: 4cd4a06e
  • Implementation commit: 962b7699 plugin: replace https host api with request grants
  • Diff: 4cd4a06e..962b7699

Reviewer scope:

  • read-only /home/hare/Projects/yoi

Reviewer focus:

  • Active API/docs/WIT/CLI naming uses request, not stale https names。
  • No compatibility alias remains for old host_api.https / grants.https unless explicitly justified。
  • Runtime authorization requires both manifest request target and enablement grant before network I/O。
  • Grant-only and missing-grant cases fail closed / diagnose clearly。
  • Local/private/loopback targets require explicit declaration and grant。
  • WebSocket/SSE/persistent stream behavior is rejected or explicitly unsupported by request
  • Broad/arbitrary URL grants are visibly distinguished。
  • Existing public HTTPS use case still works through request naming。

Orchestrator will wait for reviewer verdict before integration。


Review: request changes

Verdict: request_changes

確認範囲:

  • Ticket authority:
    • .yoi/tickets/00001KVMG8FTW/item.md
    • .yoi/tickets/00001KVMG8FTW/thread.md
  • Implementation diff 4cd4a06e..962b7699:
    • crates/manifest/src/plugin.rs
    • crates/pod/src/feature/plugin.rs
    • crates/pod/src/pod.rs
    • crates/yoi/src/plugin_cli.rs
    • docs/design/plugin-component-model.md
    • docs/development/plugin-development.md
    • resources/plugin/wit/deps/yoi-host/yoi-host-v1.wit
    • resources/plugin/wit/yoi-plugin-instance-v1.wit
    • resources/plugin/wit/yoi-plugin-tool-v1.wit

Blocking issue:

  1. Static inspection and runtime authorization disagree for broad / covering request grants。

Static inspection currently treats request target grants as matching only by exact equality:

  • crates/pod/src/feature/plugin.rs:420-425
    • let granted = record.grants.request.iter().any(|grant| grant == target);
  • crates/pod/src/feature/plugin.rs:440-455
    • grants without exact equality are reported as grant-only, eligible=false

Runtime authorization checks manifest targets and grants independently by URL coverage:

  • crates/pod/src/feature/plugin.rs:1397-1409
    • URL must be allowed by some manifest target and some enabled grant。
  • crates/pod/src/feature/plugin.rs:1420-1449
    • broad grants such as *://* or broader path/host scopes can cover a concrete URL even when not equal to the manifest target。

Concrete mismatch:

  • Manifest declares exact target: https://api.example.test ... /v1
  • Enablement grants broad target: *://* GET *
  • Inspection reports:
    • manifest target requested=true granted=false eligible=false
    • broad grant as grant-only ... eligible=false
  • Runtime still allows GET https://api.example.test/v1/data, because URL is covered by both manifest target and broad grant。

The added CLI test appears to codify this inconsistent reporting:

  • crates/yoi/src/plugin_cli.rs:1566-1574
    • expects broad grant display as grant-only
    • expects requested target as granted=false eligible=false

This violates the Ticket acceptance/invariants that inspection distinguish requested/granted/denied/broad request permissions accurately, and that grant-only / requested-but-ungranted cases do not silently diverge from runtime behavior。

Required fix:

  • Align static inspection and runtime semantics。
  • If broad / covering grants are valid authorization for declared manifest targets, inspection should report the manifest target as covered/granted, while visibly labeling the covering grant as broad。
  • If only exact target grants are intended to authorize, runtime should deny non-equal grant coverage before network I/O。
  • Apply same reasoning to the inverse shape: broad manifest request plus narrower exact grant can be runtime-allowed for URLs in the intersection while inspection currently reports both sides as ineligible/grant-only。

Non-blocking concern:

  • DNS/private-target semantics are now URL-permission based rather than resolved-address-category based。There is an explicit test allowing a declared/granted hostname to resolve to 127.0.0.1 (crates/pod/src/feature/plugin.rs:4841-4847)。This may be acceptable under the new model, but it should be documented/reconfirmed because the Ticket says local/private communication must not be ambient。The implementation interprets “explicit” as declared/granted URL host, not necessarily literal localhost / private IP grant。

Reviewer validation passed:

  • cargo fmt --check
  • git diff --check 4cd4a06e..HEAD
  • cargo test -p manifest request --quiet (7 passed)
  • cargo test -p pod feature::plugin::tests --lib --quiet (67 passed)
  • cargo test -p yoi plugin_cli::tests --quiet (18 passed)
  • cargo check -p manifest -p pod -p yoi --quiet
  • target/debug/yoi ticket doctor
  • Stale active naming grep under crates docs resources for host_api.https|grants.https|PluginHttps|yoi:host/https|yoi:https: no matches。

Worktree status:

  • Clean on impl/00001KVMG8FTW-plugin-request-host-api

Implementation report

Coder r1-fix report received from yoi-coder-00001KVMG8FTW.

New fix commit:

  • 0e14e7c1 plugin: align request grant inspection coverage

Branch commits now:

  • 962b7699 plugin: replace https host api with request grants
  • 0e14e7c1 plugin: align request grant inspection coverage

Fix summary:

  • crates/pod/src/feature/plugin.rs
    • Static inspection now uses request target coverage/intersection semantics instead of exact equality。
    • Broad/covering grants are reported as granted/eligible when they cover or intersect manifest targets in a way runtime can allow。
    • Broad manifest + narrower grant is also reported as eligible with partial-coverage diagnostics。
    • Truly grant-only/no-manifest-intersection grants remain ineligible。
    • Added focused static inspection tests for exact manifest target + broad grant and broad manifest target + narrower exact grant。
  • crates/yoi/src/plugin_cli.rs
    • Updated CLI/static inspection test expectations to match aligned broad grant semantics。
  • docs/development/plugin-development.md
    • Documented that explicit request authority is URL-host based, and a granted DNS hostname may resolve to loopback/private addresses if that hostname was intentionally declared/granted。

Coder validation reported:

  • cargo fmt --check: passed
  • git diff --check 4cd4a06e..HEAD: passed
  • cargo test -p manifest request --quiet: passed
  • cargo test -p pod feature::plugin::tests --lib --quiet: passed
  • cargo test -p yoi plugin_cli::tests --quiet: passed
  • cargo check -p manifest -p pod -p yoi --quiet: passed
  • target/debug/yoi ticket doctor: passed
  • stale active naming grep under crates docs resources for old HTTPS names: no matches

Orchestrator evidence checked:

  • Implementation worktree clean on impl/00001KVMG8FTW-plugin-request-host-api
  • HEAD is 0e14e7c1
  • r1-fix diff 962b7699..HEAD touches only crates/pod/src/feature/plugin.rs, crates/yoi/src/plugin_cli.rs, and docs/development/plugin-development.md
  • Active stale naming grep under crates docs resources returned no matches。
  • git diff --check 4cd4a06e..HEAD produced no diagnostics。

Next action:

  • Route back to Reviewer for r2 verification of static inspection/runtime coverage alignment and final acceptance。

Review: approve

Verdict: approve

確認範囲:

  • r1-fix diff 962b7699..0e14e7c1:
    • crates/pod/src/feature/plugin.rs
    • crates/yoi/src/plugin_cli.rs
    • docs/development/plugin-development.md
  • Overall changed-file set 4cd4a06e..0e14e7c1:
    • crates/manifest/src/plugin.rs
    • crates/pod/src/feature/plugin.rs
    • crates/pod/src/pod.rs
    • crates/yoi/src/plugin_cli.rs
    • docs/design/plugin-component-model.md
    • docs/development/plugin-development.md
    • resources/plugin/wit/deps/yoi-host/yoi-host-v1.wit
    • resources/plugin/wit/yoi-plugin-instance-v1.wit
    • resources/plugin/wit/yoi-plugin-tool-v1.wit

Previous blocker verification:

  • r1 blocker is resolved。
  • Static inspection now evaluates request grant coverage/intersection rather than exact equality。
  • Exact manifest target + broad grant is now reported as granted/eligible with broad diagnostics, not grant-only
  • Broad manifest target + narrower exact grant is now reported as runtime-eligible with partial-coverage diagnostics。
  • CLI/static inspection expectations were updated so broad grants are shown as usable grants, not ineligible grant-only。
  • DNS/private-target reviewer concern is documented in docs/development/plugin-development.md

Blocking issues:

  • None。

Non-blocking concerns:

  • None requiring changes before merge。

Overall Ticket satisfaction spot-check:

  • Active API/docs/WIT naming use request; stale active host_api.https / grants.https / PluginHttps* / old WIT names were not found under crates docs resources
  • No compatibility alias for old HTTPS naming was visible in active code/docs。
  • Runtime still requires both manifest host_api.request / request target declaration and enablement host_api.request / matching request grant。
  • Runtime URL checks remain method/scheme/host/port/path based。
  • WebSocket URLs, upgrade headers, and SSE/event-stream requests remain rejected。
  • Embedded URL credentials and credential-like headers remain rejected。
  • Local/private/loopback targets are not ambient; documented authority is URL-host declaration + grant。

Reviewer validation passed:

  • cargo fmt --check
  • git diff --check 4cd4a06e..HEAD
  • cargo test -p manifest request --quiet (7 passed)
  • cargo test -p pod feature::plugin::tests --lib --quiet (69 passed)
  • cargo test -p yoi plugin_cli::tests --quiet (18 passed)
  • cargo check -p manifest -p pod -p yoi --quiet
  • target/debug/yoi ticket doctor (doctor: ok)
  • Stale active naming grep under crates docs resources: no matches。

Worktree status:

  • Clean at HEAD 0e14e7c1 on impl/00001KVMG8FTW-plugin-request-host-api

Implementation report

Reviewer r2 approvalを受けて、実装ブランチを Orchestrator worktree の orchestration branch に統合した。

統合:

  • Merge commit: 8a15cca5 merge: plugin request host api
  • Merged branch: impl/00001KVMG8FTW-plugin-request-host-api
  • Implementation commits:
    • 962b7699 plugin: replace https host api with request grants
    • 0e14e7c1 plugin: align request grant inspection coverage

Orchestrator worktree validation:

  • cargo fmt --check: passed
  • git diff --check HEAD^1..HEAD: passed
  • cargo test -p manifest request --quiet: passed (7 passed)
  • cargo test -p pod feature::plugin::tests --lib --quiet: passed (69 passed)
  • cargo test -p yoi plugin_cli::tests --quiet: passed (18 passed)
  • cargo check -p manifest -p pod -p yoi --quiet: passed
  • Stale active naming grep: git grep -n -E 'host_api\.https|grants\.https|PluginHttps|yoi:host/https|yoi:https' -- crates docs resources: no matches
  • cargo run -p yoi -- ticket doctor: passed (doctor: ok)
  • nix build .#yoi --no-link: passed

Final Orchestrator worktree status after validation: clean on orchestration at 8a15cca5


State changed

Reviewer approval、Orchestrator worktree への統合、focused plugin request tests/checks、stale naming grep、Ticket doctor、Nix build が完了したため done に遷移する。


State changed

Ticket を closed にしました。


完了

Plugin host API の one-shot outbound request capability を host_api.https / grants.https から URL permission based host_api.request に置き換え、Orchestrator worktree の orchestration branch に統合した。

主な成果:

  • Active API / docs / WIT naming を request に移行。
  • Manifest に host_api.request[[request]] target declaration を追加。
  • Enablement grant を request target grant として扱うよう変更。
  • Runtime authorization を manifest-declared request target と enabled request grant の両方が URL/method/scheme/host/port/path coverage で許可する場合のみ network I/O に進む形にした。
  • Grant-only / missing-grant / broad / partial-coverage states を static inspection と yoi plugin show diagnostics で区別。
  • Broad/covering grant と broad manifest + narrower grant の intersection semantics を runtime と static inspection で一致させた。
  • Loopback/local/private target は ambient ではなく、URL host declaration + grant に基づく明示 authority として扱う方針を docs に記録。
  • Embedded credentials、credential-like headers、WebSocket URLs/upgrades、SSE/event-stream requests を reject/unsupported にした。
  • Old host_api.https / grants.https / PluginHttps* / old WIT names は active code/docs/resources から削除。
  • Focused manifest / pod / yoi plugin CLI tests を追加・更新。

統合・検証:

  • Merge commit: 8a15cca5 merge: plugin request host api
  • Implementation commits: 962b7699, 0e14e7c1
  • Reviewer final verdict: approve
  • Validation passed: cargo fmt --check, git diff --check HEAD^1..HEAD, cargo test -p manifest request --quiet, cargo test -p pod feature::plugin::tests --lib --quiet, cargo test -p yoi plugin_cli::tests --quiet, cargo check -p manifest -p pod -p yoi --quiet, stale active naming grep, cargo run -p yoi -- ticket doctor, and nix build .#yoi --no-link

範囲外:

  • Regex URL target matching は追加していない。
  • WebSocket/SSE/persistent connection support は host_api.request に含めていない。WebSocket は別 capability / design Ticket 側で扱う。