stacklok / stacklok/toolhive-registry-server

Skill/plugin package ordering is not preserved or deterministic

Open
#882 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement needs-triage
Dominant language
Go
Stars
27
Forks
15
Avg merge
2d 1h
Merged PRs (30d)
16

Description

Split out of #861 (finding 6) because it needs a product decision before any schema work, unlike the mechanical fixes remaining in that issue.

Current behaviour

A skill/plugin's packages array is stored across two tables with no ordinal column, and reassembled by concatenation:

  • skill_oci_package / skill_git_package (000012_add_skills.up.sql:33-56) and plugin_oci_package / plugin_git_package (000022_add_plugins.up.sql:38-61) — neither has an ordinal/position column.
  • Fetch always appends OCI before Git, regardless of manifest order: internal/service/db/impl_skills.go:135-139, :255-260, :391-395, and identically impl_plugins.go:136-140, :256-261, :392-396.

So a manifest declaring [git, oci] round-trips as [oci, git]. A consumer following a "first package wins" convention gets a different artifact than the publisher declared.

Two separable problems

1. Non-determinism within each group (no decision needed). ListSkillOciPackages / ListSkillGitPackages (database/queries/skills.sql) and the plugin equivalents have no ORDER BY at all. Row order is whatever Postgres happens to return, so it can change after an update or vacuum with no data change — the same GET can return packages in a different order on successive calls. That's worth fixing regardless of the decision below; ordering by id (UUIDv7-ish, monotonic per insert batch) or by identifier would make output stable.

2. Manifest order not preserved (needs a decision). Fixing this properly means adding an ordinal column to all four package tables, populating it during sync, and merging the two result sets by ordinal on fetch.

The question

Is the order of packages in a skill/plugin manifest semantically meaningful — i.e. is it a publisher-expressed preference that consumers are entitled to rely on?

  • If yes: add the ordinal column to all four tables, preserve order through sync and fetch, and document the guarantee.
  • If no: fix (1) for stable output only, and document that packages order is not significant so consumers select by type/identifier rather than position.

Worth answering before anyone writes the migration — (2) is four tables plus sync and fetch changes across both types, and is wasted work if the answer is "no".

Split from #861
Refs #859

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with database/queries/skills.sql, 000012_add_skills.up.sql, 000022_add_plugins.up.sql, internal/service/db/impl_skills.go, and impl_plugins.go. Determine whether manifest package order is semantically meaningful before choosing between stable per-group ordering and ordinal preservation. Done means the product decision is documented and the resulting schema, sync, fetch, and ordering work is specified.

Written by the indexing model from the issue text.

Assessment

Tech stack
go, postgresql
Domain
backend, databases
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.