Files
kandev/docs/specs/plugins/authoring-experience.md
T
2026-08-02 21:39:02 +01:00

127 lines
6.8 KiB
Markdown

---
status: draft
created: 2026-08-02
owner: kandev
---
# Plugin Authoring Experience
## Why
Plugin authors and coding agents cannot currently move from discovery to a
tested package without reconciling public tutorials, frozen contract notes,
frontend types, the Go SDK, the manifest implementation, packaging code, and
ADRs. Some of those references have drifted behind the shipped contract, which
makes otherwise copy-pasteable guidance unsafe.
## What
- `docs/public/plugins-authoring.md` is the canonical developer entry point and
is linked directly from the root, backend, and web `AGENTS.md` files.
- The entry point teaches one workflow: choose a supported recipe, edit
`manifest.yaml`, implement against the authoritative contract, run the
available validation, package, install, and smoke test.
- It explains the install-to-load lifecycle, package and per-plugin data layout,
backend/UI-focused/combined plugin shapes, capability boundary, and the rule
that plugins use Host APIs rather than Kandev databases or internal packages.
- A storage decision table distinguishes plugin-scoped Host state, the absence
of per-user `host.storage` in this branch, operator config and vault-backed
secrets, and files rooted under `KANDEV_PLUGIN_DATA_DIR`.
- A frontend matrix covers every registration and Host value currently exposed
by `apps/web/lib/plugins/types.ts` and `apps/web/lib/plugins/host-api.ts`. It
names every mounted component slot and records input, manifest requirement,
lifecycle/cleanup, and an example or authoritative source link.
- A backend matrix covers `Plugin.OnEvent`, `Plugin.HandleWebhook`, every
`pluginsdk.Host` method/resource accessor, the required capability, and the
relevant SDK/proto source.
- The guide explicitly says that `registerTaskPanel`, `registerTaskMenuAction`,
per-user `host.storage`, `RichTextEditor`, `RichTextReadOnly`, and direct
Kanban-card injection are not part of the current branch. It does not invent
future signatures.
- At least six current-contract recipes are runnable or link to maintained
source: a UI-focused plugin with the required no-op managed binary; a Go
backend using Host state; a `task-sidebar` contribution backed by task-scoped
Host state; a webhook receiver; an event subscriber; and a Kanban-aware route
that reads `host.store` without injecting into first-party cards.
- The reproducible workflow documents the exact checks already available in
the plugin template and monorepo, including their limits. Package creation
generates checksums; the install path performs manifest, checksum, archive,
extraction, and host-binary checks; the in-tree fixture package tests provide
the closest no-production-instance validation. This change does not add a
second validator or new runtime behavior.
- Existing plugin pages, contract notes, relevant README-style example docs,
and the `create-kandev-plugin` skill link back to the canonical entry point
instead of duplicating or contradicting the API.
- The plugin system remains marked experimental unless a separate product
stability decision changes the public status evidence.
## Authoritative contracts
This feature does not add plugin runtime hooks or Host RPCs. It documents the
current contract and points readers to:
- Frontend pair: `docs/plans/plugins/PLUGIN-API.md` and
`apps/web/lib/plugins/types.ts`.
- Concrete frontend Host exports: `apps/web/lib/plugins/host-api.ts`.
- Backend author API: `apps/backend/pkg/pluginsdk`.
- Wire API: `apps/backend/proto/kandev/plugin/v1/plugin.proto`.
- Manifest model and semantics: `apps/backend/internal/plugins/manifest`.
- Package integrity and install semantics:
`apps/backend/internal/plugins/pkgtar`.
The canonical guide summarizes those sources for discovery, but does not become
another type, proto, or schema definition.
## Permissions and storage
- Frontend bundles run in the Kandev origin and receive the current shared
React instance and curated host/store surface. Frontend registrations are not
individually capability-gated; `ui.bundle` and `ui.keybindings` declare the
relevant UI entry points.
- Host state requires `state`; secrets require `secrets`; reads require the
matching `api_read` resource; task/message writes require the matching
`api_write` resource; utility-agent invocation requires `agent_invoke`; and
event delivery requires a matching event subscription.
- `Host.GetConfig` and `Host.EmitEvent` are ungated. Webhook keys must be
declared. The external-auth response directive additionally requires `auth`.
- Plugins do not receive sanctioned direct database access. Domain reads and
writes go through typed Host RPCs and Kandev's service layer.
- Host state is plugin-scoped structured data and is not per-user browser
storage. Arbitrary plugin files belong below `KANDEV_PLUGIN_DATA_DIR`.
## Scenarios
- **GIVEN** an agent starts at a relevant `AGENTS.md`, **WHEN** it follows the
plugin-authoring link, **THEN** it reaches the canonical guide in one step and
sees the contract map and supported workflow.
- **GIVEN** a UI-focused plugin author, **WHEN** they follow the recipe, **THEN**
they include the no-op managed executable required by the current installer
and a native UI bundle without inventing unsupported backend behavior.
- **GIVEN** an author needs durable task-related state, **WHEN** they consult the
storage table and sidebar recipe, **THEN** they use task-scoped Host state and
do not mistake it for unavailable per-user `host.storage`.
- **GIVEN** a manifest declares `api_write: ["tasks"]`, **WHEN** an author reads
the capability matrix, **THEN** it documents `Tasks().Create/Update` as
implemented and links to the SDK/proto.
- **GIVEN** a package whose `ui.bundle` omits the leading slash, **WHEN** an
author follows the workflow, **THEN** the guide identifies that error before
install and explains which remaining checks happen during packaging and
install.
- **GIVEN** a disabled or uninstalled UI plugin, **WHEN** an author consults the
lifecycle matrix, **THEN** it explains `destroy`, bulk unregistration, modal
closure, stylesheet removal, and plugin-owned side-effect cleanup.
- **GIVEN** a request for a future task-panel, task-menu, per-user storage,
rich-text, or Kanban-card hook, **WHEN** an author checks the canonical page,
**THEN** it says the API is unavailable in this branch and points to the
closest supported recipe.
## Out of scope
- Adding a package checker or changing manifest, packaging, installation,
runtime supervision, capability enforcement, signing, or database behavior.
- Adding frontend hooks, per-user plugin storage, rich-text components, or
Kanban-card injection.
- Publishing or modifying external plugin repositories.
- Creating a second manifest, proto, TypeScript, or Go SDK definition in docs.
- Promoting the plugin system from experimental to stable.