Skip to content

Write the k6 Hub specification #6253

Description

@szkiba

Summary

Write an OpenSpec change for the k6 Hub, starting from the merged feature brief. Follow the layout of openspec/changes/archive/2026-06-11-add-feature-flags/.

This issue is about the spec only. No Hub code, no resolver, no catalog repo. The output is proposal.md, design.md, tasks.md and the capability spec.md files, so the work can be reviewed and planned.

Proposed for the next core-team cycle.

Why now

The feature brief (docs/features/001-k6-hub.md, added in #6197) covers the problem, the desired state and what is out of scope, and per docs/features/README.md a merged brief is final. It says what changes for the user and why. It does not say how the catalog is modelled, how imports resolve, or what ships first.

Until that part is written down we can't estimate the work, split it across cycles, or decide what belongs in grafana/k6 and what belongs in a catalog repo. Feature flags went the same way: brief, then OpenSpec change, then implementation. The spec is where the tasks came from.

Scope

Create an OpenSpec change directory (working name openspec/changes/add-k6-hub/) with:

  • proposal.md - Why / What Changes / Capabilities (new and modified) / Impact / References.
  • design.md - context, goals and non-goals, domain model, numbered decisions including what each one was chosen over, risks and trade-offs.
  • specs/<capability>/spec.md - requirements in the ### Requirement: and #### Scenario: GIVEN/WHEN/THEN format the repo already uses. Testable, no implementation detail.
  • tasks.md - implementation split into chunks that fit a cycle.

Three things to work out while writing it, not before:

  • How to split the capabilities. The Hub is too big for one. Catalog data model and governance / import resolution / distribution and serving is one option, but whichever split we take needs an argument behind it. Feature flags was a single capability; this is larger.
  • Which side each requirement sits on. k6 side is the k6: URI, resolution, caching and failure modes. Catalog side is the schema, index generation, CODEOWNERS governance and the publishing flow. Decide whether both go in this change or only the k6 side.
  • What ships first. The brief describes the end state. The spec should say where the first delivery stops.

Out of scope

  • Implementation, prototypes, catalog content.
  • Reopening the brief. It is merged, so it is final. A change of direction means a new brief.
  • What the brief already excluded: removing the existing import syntaxes, bit-for-bit extension binary reproducibility, agent-facing tooling such as an MCP server or skills, and unifying how modules are authored across kinds.

Source material

Read in this order.

1. Feature brief - authoritative

Feature Brief (docs/features/001-k6-hub.md), once #6197 lands. Start here. Everything in the spec should trace back to it. Attached to this issue.

2 and 3. Historical documents - context only

A Product DNA and a Technical Spec, both written before the brief and never reviewed as a PR. Attached to this issue.

They are worth reading. There is a catalog schema, a resolution algorithm, a governance model and a hosting plan in there, and redoing all of that from scratch would be a waste. They are still not a spec to copy.

How to use them:

  • The brief supersedes them. It came out of reconsidering these two documents, so where they differ the call has already been made. What the brief dropped, such as private catalogs and npm/JSR packages, is out. What the brief added is in.
  • Treat their design decisions as options, not answers. Anything carried into design.md needs its own argument there, including what it beat.
  • They are older than the brief and say nothing about two of its requirements: reproducibility and machine-readable metadata.

What the brief leaves open

Not everything in the historical documents is still live, as above. What follows is the rest: points the brief states as a requirement without saying how, or does not mention at all. Each one needs a decision in design.md, or an open question written down.

# Topic What's open
1 Relationship to registry.k6.io The brief has the Hub take over from today's extension catalog for provisioning. It does not say how we get there: whether registry.k6.io keeps serving during a transition, whether we generate a compatibility file for the current provisioning system (the Technical Spec generates extension-catalog.json), and when we switch.
2 Reproducibility and provenance The brief wants each module version to map to an immutable commit that can be checked by digest, so a re-publish can't change a pinned or archived run. Nothing designs this yet. The historical documents rely on versions being immutable and on GPG-signed commits, which is a weaker promise. Needs a model: what gets digested, who checks it, and when.
3 Machine-readable metadata The brief treats a queryable API as a core requirement: kind, versions, k6 compatibility, ownership, provenance. It needs defining - the shape, what we promise not to break, how it is served. The Technical Spec's @index.json is a start, but it is a build artifact for search rather than something callers can depend on.
4 Resolution mechanism The brief describes behaviour, not mechanism. The Technical Spec picks esbuild for parse-time resolution based on an old reading of the JS runtime, so check that against Sobek as it is today. Either way the spec should describe what happens, not which library does it.
5 builtin version semantics The brief settles the semantics: the version is whatever the binary ships, a constraint is matched against it, and a constraint that can't be met fails at load instead of quietly resolving to something else. How to model it is open. The Technical Spec uses a provides map on a core k6:@grafana/k6 module, and asks without answering whether that module is virtual.
6 Failure modes None of the three documents cover these: Hub unreachable, constraints that can't all be satisfied, transitive imports that conflict, import cycles. The Product DNA says the resolver "must rigorously address" the last two, which is a requirement to write, not a design that exists.
7 package.json constraints The brief does not mention manifests. Both historical documents let the manifest override import attributes (package.json > import attributes > latest) as a governance lever. Decide whether that is in the first spec.

Definition of done

  • The change directory exists with proposal.md, design.md, tasks.md and capability spec.md files, in the same format as the archived feature-flags change.
  • It passes whatever the OpenSpec tooling checks (openspec validate --strict if we use the CLI).
  • Every requirement traces back to the brief or to a decision recorded in design.md.
  • Every open point above is either decided in design.md or written down as an open question with an owner.
  • tasks.md is detailed enough to schedule across cycles and shows where the first delivery ends.
  • Opened as a PR and reviewed by the team.

Related issues and PRs


Attachments

All three documents are attached to this issue.

  1. 001-k6-hub.md - the feature brief. Authoritative; lands in the repo at docs/features/001-k6-hub.md when docs: add feature brief for k6 Hub unified module catalog #6197 merges.
  2. Product-DNA-k6-hub.md - historical, Google Drive export. Context only - not a specification, never PR-reviewed, superseded by the brief wherever they disagree.
  3. Technical-Spec-k6-hub.md - historical, Google Drive export. Context only - its schema, resolution algorithm and governance model are options to re-argue in design.md, not decisions to adopt as-is.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions