c53f699714
- go plugin backends ship as release tarballs (per-platform binaries, checksums) that kandev installs from url/upload or filesystem sideload+sync, then spawns and supervises via hashicorp/go-plugin (unix socket / loopback tcp+automtls) - strict typed grpc contract (kandev.plugin.v1): DeliverEvent/InvokeTool/HandleWebhook plus a capability-gated host service (state, secrets, emit); author sdk in pkg/pluginsdk; packaging cli in cmd/plugin-pack - native frontend bundles: window.registerKandevPlugin + registry/host loader with dynamic routes, nav items, slots and ws handlers; plugins settings page with install dialog, sync button and enable/disable/uninstall - gated behind the plugins feature flag (prod off, dev/e2e on); covered by unit and integration tests plus playwright e2e against a real packaged fixture plugin Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2.0 KiB
2.0 KiB
id, title, status, wave, depends_on, plan
| id | title | status | wave | depends_on | plan |
|---|---|---|---|---|---|
| task-03 | plugin_state SQLite store | done | 1 | docs/plans/plugins/plan.md |
plugin_state SQLite store
Title
SQLite-backed plugin-scoped KV state store following the per-package
initSchema() convention.
Inputs
- Spec
docs/specs/plugins/spec.md→ "plugin_state(SQLite)" and "Plugin state API". Table:CREATE TABLE plugin_state ( id TEXT PRIMARY KEY, plugin_id TEXT NOT NULL, scope TEXT NOT NULL DEFAULT 'instance', scope_id TEXT, state_key TEXT NOT NULL, value_json TEXT NOT NULL, updated_at TEXT NOT NULL, UNIQUE (plugin_id, scope, scope_id, state_key)); - Scopes: instance | workspace | task | agent. Plugins cannot read others' state (enforced by always filtering on plugin_id — the API layer passes it, task-09).
- Pattern reference:
internal/task/repository/sqlite/base_schema.go(initSchema withCREATE TABLE IF NOT EXISTS) and how repos take a*sql.DB/db handle. Use the same db handle type the other stores use (db.Poolwriter/reader or*sql.DB— match sibling stores; inspectinternal/sentry/store.go).
Acceptance
StateStorewithinitSchema()creatingplugin_state(idempotent).- Methods:
Get(ctx, pluginID, scope, scopeID, key) (json.RawMessage, bool, error),Set(ctx, pluginID, scope, scopeID, key, value)(upsert on the UNIQUE key),Delete(ctx, pluginID, scope, scopeID, key),List(ctx, pluginID, scope, scopeID) ([]StateEntry, error). updated_atset to RFC3339 UTC on write. NULLscope_idhandled for instance scope.
Files
apps/backend/internal/plugins/state/store.goapps/backend/internal/plugins/state/store_test.go(in-memory or temp-file sqlite)
Verification
go test ./internal/plugins/state/...fromapps/backendmake -C apps/backend lint
Output contract
Report: db handle type chosen (match siblings), upsert approach, scope_id NULL
handling. Stay within internal/plugins/state/.
Dependencies
None.