Skip to content

feat: indicate whether an extension pack/dependency reference is available - #2108

Draft
netomi wants to merge 2 commits into
mainfrom
fix/extension-pack-reference-availability
Draft

feat: indicate whether an extension pack/dependency reference is available#2108
netomi wants to merge 2 commits into
mainfrom
fix/extension-pack-reference-availability

Conversation

@netomi

@netomi netomi commented Aug 27, 2026

Copy link
Copy Markdown
Contributor

Closes #224.

What

Extension packs have not required their bundled extensions to already exist in the registry for some time now: bundledExtensions is stored as a plain list of namespace.extension strings, and publish-time validation only checks the format, not resolvability - unlike extensionDependencies, which does still check resolvability. So the core ask in #224 (publish a pack referencing extensions that aren't yet published here) has worked for a while.

What was still missing, per the later discussion on that issue: the API handed back a URL for every bundled-extension/dependency reference whether or not it actually resolved, and the extension detail page linked to all of them uniformly - following a reference to an unpublished (or since-removed) extension led to a bare 404 with no indication beforehand.

Changes

  • Server: ExtensionReferenceJson gains an available boolean. LocalRegistryService.resolveExtensionReferences (renamed from setExtensionReferenceUrls, made package-private so it can be tested directly) sets it via repositories.findActiveExtension(...) for every bundled-extension/dependency reference, alongside the URL it already set.
  • webui: ExtensionReference.available (optional, so older registries that don't send this field yet are treated as available - no behavior change for them). The extension detail page's renderExtensionRef now shows an unavailable reference as plain namespace.extension (not available) text instead of a dead link.

Testing

  • LocalRegistryServiceTest: 2 new tests covering an available reference, an unavailable one, and the null-list no-op case.
  • extension-detail-overview.spec.tsx (new file): 4 tests covering both bundled extensions and dependencies, available and unavailable.

Server: ./gradlew test - 1054/1054 passing. Webui: yarn lint clean, yarn test - 171/171 passing.

…lable

Addresses the remaining piece of #224. Extension
packs have not required their bundled extensions to already exist in
the registry for some time now - bundledExtensions is a plain list of
namespace.extension strings, and publish-time validation only checks
the format, not resolvability, unlike extensionDependencies. What was
still missing: the API handed back a URL for every reference whether
or not it actually resolved, and the extension detail page linked to
all of them uniformly, so following a reference to an unpublished
extension led to a bare 404 with no indication beforehand.

- ExtensionReferenceJson gains an available boolean, set by
  LocalRegistryService.resolveExtensionReferences (renamed from
  setExtensionReferenceUrls) via repositories.findActiveExtension(...)
  for every bundled-extension/dependency reference.
- webui: ExtensionReference.available (optional, for older registries
  that don't send it yet); the extension detail page now shows an
  unavailable reference as plain 'namespace.extension (not available)'
  text instead of a dead link.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…ility

The extension.json cache for an extension was only evicted when the
extension itself changed. If it was also referenced as a bundled
extension/dependency by another extension, that other extension's
cached json (with a stale available=false for the reference) was
never invalidated, e.g. once the referenced extension got published.

ExtensionService.updateExtension - the single method already invoked
whenever an extension's active status changes - now also evicts the
extension.json cache of every extension that references it, reusing
the existing RepositoryService.findBundledExtensionsReference /
findDependenciesReference queries.

Separately, LocalRegistryService.resolveExtensionReferences (which
sets the available flag) had only been wired into
toExtensionVersionJsonV2. The two v1 toExtensionVersionJson overloads,
backing the v1 getExtension/query endpoints and the publish response,
still had their own older loop that set the url but never available.
Both now delegate to resolveExtensionReferences like v2 does.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@netomi

netomi commented Aug 30, 2026

Copy link
Copy Markdown
Contributor Author

Pushed a follow-up commit addressing two related cache/availability gaps found while reviewing this change:

  1. Cache invalidation: extension.json was only evicted for the extension that changed, not for other extensions that reference it as a bundled extension/dependency. So if extension A bundles B, and A's json gets cached before B is published, publishing B afterwards never invalidated A's cache — it kept reporting available: false for B. ExtensionService.updateExtension (the single choke point already invoked whenever an extension's active status changes) now also evicts the cache of every referencing extension, reusing the existing RepositoryService.findBundledExtensionsReference/findDependenciesReference queries.

  2. v1 API gap: resolveExtensionReferences (which sets the available flag) had only been wired into toExtensionVersionJsonV2. The two v1 toExtensionVersionJson overloads — backing the v1 getExtension/query endpoints and the publish response — still used their own older logic that set the URL but never available. Both now delegate to resolveExtensionReferences like v2 does.

Added regression tests for both (ExtensionServiceTest, LocalRegistryServiceTest) and fixed a couple of pre-existing test mocks that needed the newly-called repository methods stubbed. Full ./gradlew test run: 1057/1057 passing.

@netomi

netomi commented Aug 30, 2026

Copy link
Copy Markdown
Contributor Author

Actually I am not sure anymore if this is really worth it.

@netomi
netomi marked this pull request as draft August 31, 2026 06:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow to publish an extension pack without need to publish all extension to registry at first

1 participant