55 lines
2.0 KiB
Markdown
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.
|