Goal: Stand up the plugin core service, validation, and storage in toolhive — build/push/validate plus the SQLite migration.
Deliverables:
pkg/plugins/ (template pkg/skills/): types.go, service.go (PluginService interface per RFC §API), parser.go (.claude-plugin/plugin.json; strict field types — keywords must be array), validator.go (reuse pkg/skills.Validator for bundled skills), options.go, project_root.go (reuse skills' git-root autodetect).
pkg/plugins/pluginsvc/ (template pkg/skills/skillsvc/): service.go, build.go (build + push), oci.go, local_build_marker.go, content.go, scope.go, pull_errors.go.
- Storage:
pkg/storage/sqlite/migrations/002_create_plugins.sql (installed_plugins + plugin_dependencies off existing entries; auto-discovered via //go:embed migrations/*.sql), pkg/storage/sqlite/plugin_store.go + storage.PluginStore, and a typed EntryType ("skill"/"plugin") replacing the stringly-typed entry_type = 'skill' literal.
- Risk: the
002_… migration must reuse entries.entry_type unique (entry_type, name), not redefine it.
Dependency/gate: depends on GATE-C2 (toolhive-core oci/plugins tagged + go.mod bumped). Nothing here compiles before C2.
Testing/exit gate: parser/validator units (type-mismatch + traversal-in-manifest-paths rejection); packager-determinism via the service; migration up/down; build→push round-trip vs. mock OCI registry.
Part of #5525
Refs RFC PR stacklok/toolhive-rfcs#77
Goal: Stand up the plugin core service, validation, and storage in
toolhive— build/push/validate plus the SQLite migration.Deliverables:
pkg/plugins/(templatepkg/skills/):types.go,service.go(PluginServiceinterface per RFC §API),parser.go(.claude-plugin/plugin.json; strict field types —keywordsmust be array),validator.go(reusepkg/skills.Validatorfor bundled skills),options.go,project_root.go(reuse skills' git-root autodetect).pkg/plugins/pluginsvc/(templatepkg/skills/skillsvc/):service.go,build.go(build + push),oci.go,local_build_marker.go,content.go,scope.go,pull_errors.go.pkg/storage/sqlite/migrations/002_create_plugins.sql(installed_plugins+plugin_dependenciesoff existingentries; auto-discovered via//go:embed migrations/*.sql),pkg/storage/sqlite/plugin_store.go+storage.PluginStore, and a typedEntryType("skill"/"plugin") replacing the stringly-typedentry_type = 'skill'literal.002_…migration must reuseentries.entry_typeunique(entry_type, name), not redefine it.Dependency/gate: depends on GATE-C2 (
toolhive-coreoci/pluginstagged +go.modbumped). Nothing here compiles before C2.Testing/exit gate: parser/validator units (type-mismatch + traversal-in-manifest-paths rejection); packager-determinism via the service; migration up/down; build→push round-trip vs. mock OCI registry.
Part of #5525
Refs RFC PR stacklok/toolhive-rfcs#77