Files
kandev/docs/plans/plugins/task-08-proxies.md
T
2026-08-24 11:09:03 +00:00

54 lines
2.3 KiB
Markdown

---
id: task-08
title: Tool invocation client + webhook & UI reverse proxies
status: pending
wave: 2
depends_on: [task-05]
plan: docs/plans/plugins/plan.md
---
# Tool invocation client + webhook & UI reverse proxies
## Title
Outbound HTTP to plugins: tool invocation client (kandev→plugin), external webhook
reverse proxy, and iframe UI page reverse proxy with header stripping.
## Inputs
- Spec `docs/specs/plugins/requirements/plugins.md` → "Agent tool invocation" (POST
`{base_url}/tools/{name}`, 30s timeout, `{tool_call_id, input, context}` →
`{output}`), "External webhook proxy" (forward body+headers, add
`X-Plugin-Id`,`X-Webhook-Key`), and the NEW UI proxy section (GET/POST
`{base_url}{ui.page.path}`; strip `X-Frame-Options` and frame-restricting CSP
from the plugin response so kandev can iframe it; inject nothing else).
- Header-stripping precedent: read `apps/backend/internal/agentctl/server/api/AGENTS.md`
and the reverse-proxy code there (Accept-Encoding handling + iframe-blocking
header removal) and mirror the approach with `httputil.ReverseProxy` +
`ModifyResponse`.
## Acceptance
1. `internal/plugins/client.go`: `Client.InvokeTool(ctx, record, toolName, input, callCtx) (json.RawMessage, error)`,
30s timeout, non-2xx → typed error. `Client.Health(ctx, record) error` (used by task-07).
2. `internal/plugins/proxy.go`: `WebhookProxy(record, webhookKey) http.Handler`
forwarding to `{base_url}{endpoints.webhooks templated with key}`, adding
`X-Plugin-Id`/`X-Webhook-Key`, preserving method/body/query.
3. `UIProxy(record, page) http.Handler` reverse-proxying to `{base_url}{page.path}`,
`ModifyResponse` strips `X-Frame-Options` and removes `frame-ancestors` from CSP;
rewrites relative redirects under the kandev proxy path.
4. Both proxies 404/503 when record is nil / not active (the handler layer task-09
passes only valid records; still guard).
## Files
- `apps/backend/internal/plugins/client.go` + `client_test.go`
- `apps/backend/internal/plugins/proxy.go` + `proxy_test.go` (httptest upstream)
## Verification
- `go test ./internal/plugins/...` from `apps/backend`
- `make -C apps/backend lint`
## Output contract
Report: tool-call request/response shapes, exact headers stripped on UI proxy,
redirect-rewrite behavior. Import task-05 types only; do not edit other tasks' files.
## Dependencies
task-05.