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

55 lines
2.0 KiB
Markdown

---
id: task-03
title: plugin_state SQLite store
status: done
wave: 1
depends_on: []
plan: 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/requirements/plugins.md` → "`plugin_state` (SQLite)" and
"Plugin state API". Table:
```sql
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
with `CREATE TABLE IF NOT EXISTS`) and how repos take a `*sql.DB`/db handle.
Use the same db handle type the other stores use (`db.Pool` writer/reader or
`*sql.DB` — match sibling stores; inspect `internal/sentry/store.go`).
## Acceptance
1. `StateStore` with `initSchema()` creating `plugin_state` (idempotent).
2. 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)`.
3. `updated_at` set to RFC3339 UTC on write. NULL `scope_id` handled for instance scope.
## Files
- `apps/backend/internal/plugins/state/store.go`
- `apps/backend/internal/plugins/state/store_test.go` (in-memory or temp-file sqlite)
## Verification
- `go test ./internal/plugins/state/...` from `apps/backend`
- `make -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.